Beispiel #1
0
 def kill_escaped(self):
     '''
     Kill all sprites related to a plane that left the aerospace.
     '''
     for plane in self.__planes.values():
         s = self.surface.get_rect()
         x, y = plane['sprites'][0].position
         if x < 0 or x > s.width or y < 0 or y > s.height:
             # This is the worst scenario
             msg = 'Tower? ... Tower? ... Aaaaahhhh!'
             event = S.PLANE_LEAVES_RANDOM
             colour = S.KO_COLOUR
             crossed = self.__get_crossed_gates(plane['plane'])
             # This might be better
             for gate in crossed:
                 msg = 'Tower? It doesn\'t seem we are where we should...'
                 event = S.PLANE_LEAVES_WRONG_GATE  #little better!
                 if gate.name == plane['plane'].destination and \
                    plane['plane'].altitude % 1000 == 0:
                     msg = 'Thank you tower, and good bye!'
                     colour = S.OK_COLOUR
                     event = S.PLANE_LEAVES_CORRECT_GATE  #yay! :)
             plane['plane'].pilot.say(msg, colour)
             self.gamelogic.remove_plane(plane['plane'], event)
             log.info('%s left aerospace under event %s' %
                      (plane['plane'].icao, event))
             log.debug('Data at exit was: %s' %
                       plane['plane'].get_current_configuration())
Beispiel #2
0
 def _abort_clear(self, msg):
     '''
     Abort clear, generating all events of the case and resetting relevant
     variables.
     '''
     log.info('%s aborts: %s' % (self.plane.icao, msg))
     self.pilot.say('Aborting clear command: %s' % msg, S.ALERT_COLOUR)
     self.pilot.status['procedure'] = None
     self.pilot.set_target_conf_to_current()
     self.pilot.adjust_to_valid_FL()
Beispiel #3
0
 def remove_plane(self, plane, event):
     '''
     Remove a plane from the game.
     '''
     log.info('%s removed, event is %s' % (plane.icao, event))
     self.score_event(event, plane=plane)
     self.aerospace.remove_plane(plane)
     self.strips.remove_strip(plane)
     if event in (S.PLANE_CRASHES, S.PLANE_LEAVES_RANDOM):
         self.fatalities += 1
Beispiel #4
0
 def update(self, pings):
     '''
     Update the plane status according to the elapsed time.
     Pings = number of radar pings from last update.
     '''
     burning_speed = 1 if self.pilot.status['haste'] == 'normal' else 2
     initial = self.position.copy()
     for i in range(pings):
         # Pilot's updates
         self.pilot.update()
     # Compute waiting time score if not airborne
     # FIXME: distinguish between just landed and waiting to takeoff
     if self.flags.on_ground:
         mult = pings * S.PING_IN_SECONDS
         self.aerospace.gamelogic.score_event(S.PLANE_WAITS_ONE_SECOND,
                                              multiplier=mult)
     # Decrease fuel amount if airborne
     elif self.fuel > 0:
         dist = U.ground_distance(initial, self.position)
         burnt = burning_speed * dist * self.fuel_efficiency
         self.fuel -= burnt
         self.aerospace.gamelogic.score_event(S.PLANE_BURNS_FUEL_UNIT,
                                              multiplier=burnt)
     # Check if a fuel emergency has to be triggered.
     # FIXME: this is goo reason to use objects intstead of IATA/NAME
     try:
         dest_point = self.aerospace.airports[self.destination].location
     except KeyError:
         tmp = self.aerospace.gates[self.destination].location
         dest_point = Vector3(tmp[0], tmp[1], self.altitude)
     dist = U.ground_distance(dest_point, self.position)
     self.fuel_delta = self.fuel - (2 * dist * self.fuel_efficiency)
     self.dist_to_target = dist
     if not self.flags.fuel_emergency and self.fuel_delta < 0:
         log.info('%s is declaring fuel emergency' % self.icao)
         msg = 'Pan-Pan, Pan-Pan, Pan-Pan... We are low on fuel, ' \
               'requesting priority landing!'
         self.pilot.say(msg, S.KO_COLOUR)
         self.aerospace.gamelogic.score_event(S.EMERGENCY_FUEL)
         self.flags.fuel_emergency = True
     # Fuel has ran out
     if self.fuel < 0:
         msg = 'Mayday! Mayday! Mayday! All engines have flamed out, we ' \
               'are going down!'
         self.pilot.say(msg, S.KO_COLOUR)
         log.info('%s has ran out of fuel' % self.icao)
         self.fuel = 0
         self.max_speed = self.min_speed * 2
         max_down = self.climb_rate_limits[0]
         self.climb_rate_limits = [max_down, max_down / 2.0]
     # Update sprite
     self.rect = U.sc(self.position.xy)
     self.trail.appendleft(U.sc(self.position.xy))
Beispiel #5
0
    def process_commands(self, commands):
        '''
        Process commands.

        This is a "subroutine" of ``execute`` which is also called by some of
        the procedures. This is such that is possible to process commands
        without triggering score events and setting flags (as it happens with
        ``execute()``).

        This method will silently pass if the command name has not been
        recognised. This is to allow the method to process set of commands that
        also contains *procedures* (such LAND, TAKEOFF, etc...).
        '''
        pi = self.pilot
        pl = self.plane
        tc = self.pilot.target_conf
        for cname, (args, flags) in commands.items():
            log.info('%s executes: %s' %
                     (pl.icao, ' '.join((cname, repr(args), repr(flags)))))
            # PROCESS COMMANDS
            # Since flags are "universal" across commands (they all do the same
            # thing if they are called the same), it is possible to process
            # them separately.
            if cname == 'HEADING':
                assert len(args) == 1
                tc.heading = args[0]
                pi.status['veer_dir'] = \
                                pi.navigator.get_shortest_veering_direction()
            elif cname == 'ALTITUDE':
                tc.altitude = args[0]
            elif cname == 'SPEED':
                tc.speed = args[0]
            elif cname == 'ABORT':
                self.abort()
            elif cname == 'SQUAWK':
                if pl.flags.on_ground:
                    pi.say('Currently at airport %s, our destination is %s' %
                              (pl.origin, pl.destination), S.OK_COLOUR)
                else:
                    pi.say('Currently heading %s, our destination is %s' %
                          (U.rint(pl.heading), pl.destination), S.OK_COLOUR)
            else:
                log.debug('process_commands() ignored: %s' % cname)
            # PROCESS FLAGS
            # Flags with the same name have the same meaning and therefore
            # can be processed independently from the command they are
            # associated with. Since they can modify the value set by their
            # command, they must follow the command processing
            if 'EXPEDITE' in flags:
                pi.status['haste'] = 'expedite'
            if 'LONG' in flags:
                pi.status['veer_dir'] *= -1  #invert direction
Beispiel #6
0
def main():
    try:
        version = __version__  #set when package is buit @UndefinedVariable
    except NameError:
        version = '<unknown>'
    try:
        log.info('### NEW MATCH - Game version: %s ################' % version)
        MainWindow().main_loop()
    except:
        trace = traceback.format_exc()
        log.critical(trace)
        print trace
        sys.exit(1)
Beispiel #7
0
 def update(self):
     '''
     Operations that must be performed when the radar pings.
     '''
     assert self.phase in (self.ACCELERATING, self.CLIMBING, self.HEADING)
     pl = self.plane
     pi = self.pilot
     if self.phase == self.ACCELERATING:
         if pl.speed > pl.landing_speed:
             pi.target_conf.altitude = self.target_altitude
             pl.flags.on_ground = False
             self.phase = self.CLIMBING
             log.info('%s is lifting off' % pl.icao)
         else:
             if pi.navigator.check_overshot(self.end_of_runway):
                 log.info('%s crashed due to too short runway' % pl.icao)
                 pl.terminate(S.PLANE_CRASHES)
     if self.phase == self.CLIMBING:
         if pi.navigator.check_overshot(self.end_of_runway):
             pi.target_conf.heading = self.target_heading
             self.phase = self.HEADING
             log.info('%s is setting post-lift-off course' % pl.icao)
     if self.timer <= 0 and self.phase == self.HEADING:
         pl.aerospace.runways_manager.release_runway(pl)
         pl.flags.locked = False
         pi.status['procedure'] = None
         log.info('%s has terminated takeoff, runway free' % pl.icao)
     self.timer -= S.PING_IN_SECONDS
Beispiel #8
0
 def _abort_landing(self, msg):
     '''
     Abort landing, generating all events of the case and resetting relevant
     variables.
     '''
     # TODO: Introducing abort codes would simplify testing!
     log.info('%s aborts: %s' % (self.plane.icao, msg))
     self.pilot.say('Aborting landing: %s' % msg, S.ALERT_COLOUR)
     # Marked runway as free
     if self.lander and self.lander.taxiing_data:
         self.pilot.aerospace.runways_manger.release_runway(self.plane)
     self.pilot.status['procedure'] = None
     self.pilot.set_target_conf_to_current()
     self.pilot.adjust_to_valid_FL()
Beispiel #9
0
 def _initiate(self, commands):
     '''
     Automatically called by ancestor class upon ``__init__``
     '''
     self.pilot.executer.process_commands(commands)
     st = self.pilot.status
     param = commands['CIRCLE'][0][0]
     if param in ('L', 'LEFT', 'CCW'):
         st['veer_dir'] = S.LEFT
     elif param in ('R', 'RIGHT', 'CW'):
         st['veer_dir'] = S.RIGHT
     else:
         msg = 'Unknown parameter for circle command.'
         raise BaseException(msg)
     if self._check_expedite(commands):
         st['haste'] = 'expedite'
     log.info('%s is circling %s' % (self.plane.icao, st['veer_dir']))
Beispiel #10
0
 def _initiate(self, commands):
     '''
     Automatically called by ancestor class upon ``__init__``
     '''
     # Preliminary check: is the beacon in range?
     point = commands['CLEAR'][0][0]
     veer_type = 'expedite' if 'EXPEDITE' in commands['CLEAR'][1] else None
     if not self.pilot.navigator.check_reachable(point, veer_type) \
        and 'SPEED' not in commands \
        or ('SPEED' in commands \
            and commands['SPEED'][0][0] > self.plane.speed):
         msg = 'The target waypoint is too close for us to fly over it!'
         return self._abort_clear(msg)
     if self._check_expedite(commands):
         self.pilot.status['haste'] = 'expedite'
     # Head towards the point
     commands['HEADING'] = commands['CLEAR']
     self.pilot.executer.process_commands(commands)
     self.target = point
     log.info('%s is clearing towards %s' % (self.plane.icao, point))
Beispiel #11
0
 def update(self):
     '''
     Perform actions (typically making a new aeroplane to appear) based
     on the kind of challenge.
     '''
     now = time()
     if now - self.last_entry > self.frequency:
         self.last_entry = now
         if self.plane_counter == 0:
             for i in range(self.PLANE_NUMBER_START):
                 self.__add_plane()
         else:
             self.__add_plane()
     if self.frequency != self.FREQ_LIMIT and \
        now - self.last_freq_increase > self.MOD_PERIOD:
         self.last_freq_increase = now
         self.frequency += self.FREQ_STEP
     # If there have been 3 (or more) destroyed planes, terminate the match
     if self.gamelogic.fatalities >= self.MAX_LOST:
         msg = ('THREE_STRIKES_OUT: Match si over after %s planes ' \
               'entered the aerospace' % self.plane_counter, S.KO_COLOUR)
         log.info(msg)
         self.gamelogic.game_commander.display([msg])
Beispiel #12
0
 def _initiate(self, commands):
     '''
     Automatically called by ancestor class upon ``__init__``
     '''
     pl = self.plane
     aspace = pl.aerospace
     r_name = commands['TAKEOFF'][0][0]
     port = aspace.airports[pl.origin]
     runway = port.runways[r_name]
     twin = port.runways[runway['twin']]
     start_point = runway['location'] + port.location
     vector = Vector3(*(-twin['ils']).normalized().xy)
     self.end_of_runway = twin['location'] + port.location
     # SAVE PROCEDURE' PERSISTENT DATA
     h = commands['HEADING'][0][0] if 'HEADING' in commands \
                             else U.v3_to_heading(vector)
     a = commands['ALTITUDE'][0][0] if 'ALTITUDE' in commands \
                             else pl.max_altitude
     self.target_heading = h
     self.target_altitude = a
     self.timer = S.RUNWAY_BUSY_TIME
     # LET'S ROLL!!
     pl.position = start_point.copy()
     aspace.runways_manager.use_runway(port, twin, pl)
     pl.flags.locked = True
     # Give 1 m/s speed and update target to set the heading/sprite icon
     pl.velocity = vector.copy()
     self.pilot.set_target_conf_to_current()
     # Set max acceleration
     self.pilot.target_conf.speed = \
         commands['SPEED'][0][0] if 'SPEED' in commands else pl.max_speed
     self.phase = self.ACCELERATING
     # LOG
     log.info('%s is taking off from %s %s' %
                                 (pl.icao, pl.origin, runway['name']))
     if self._check_expedite(commands):
         self.pilot.status['haste'] = 'expedite'
Beispiel #13
0
 def _initiate(self, commands):
     '''
     Automatically called by ancestor class upon ``__init__``
     '''
     pl = self.plane
     pi = self.pilot
     port_name, rnwy_name = commands['LAND'][0]
     self.lander = Lander(self.pilot, port_name, rnwy_name)
     l = self.lander
     # EARLY RETURN - Maximum incidence angle into the ILS is 60°
     ils_heading = U.v3_to_heading(l.ils)
     boundaries = [(ils_heading - S.ILS_TOLERANCE)%360,
                   (ils_heading + S.ILS_TOLERANCE)%360]
     if not U.heading_in_between(boundaries, pl.heading):
         msg = 'ILS heading must be within %s degrees ' \
               'from current heading' % S.ILS_TOLERANCE
         return self._abort_landing(msg)
     # EARLY RETURN - No possible intersection (the RADAR_RANGE*3
     # ensures that the segments to test for intersection are long enough.
     if not l.set_intersection_point():
         msg = 'The ILS does not intersect the plane current heading'
         return self._abort_landing(msg)
     # EARLY RETURN - Although the intersection is ahead of the plane,
     # it's too late to merge into the ILS vector
     type_ = pi.status['haste']
     if l.set_merge_point(pi.navigator.get_veering_radius(type_)) < 0:
         msg = 'We are too close to the ILS to merge into it'
         return self._abort_landing(msg)
     # LANDING IS NOT EXCLUDED A PRIORI...
     log.info('%s started landing procedure, destination: %s %s' %
                             (self.plane.icao, port_name, rnwy_name))
     # SETTING PERSISTENT DATA
     if self._check_expedite(commands):
         pi.status['haste'] = 'expedite'
     self.phase = self.INTERCEPTING
     self.lander = l