예제 #1
0
    def ordered_coast(self, unit, coast_spec, datc):
        ''' Finds a coast from its maybe_coast representation.
            If the specified coast doesn't exist, returns a fake one.
            Uses the unit's unit_type, and (depending on options)
            its location to disambiguate bicoastal destinations.
        '''#'''
        # Collect specifications
        unit_type = unit.coast.unit_type
        coastline = province = None
        for token in Message(coast_spec):
            if token.is_province():
                province = self.spaces.get(token) or Province(token, [], None)
            elif token.is_coastline():
                coastline = token
        if not province:
            raise ValueError('Missing province in coast spec: %s' %
                             Message(coast_spec))

        # Try to match all specs, but without ambiguity
        coast = self.coasts.get((unit_type, province.key, coastline))
        if coast:
            if datc.datc_4b3 == 'a' and not unit.can_move_to(coast):
                # Wrong coast specified; change it to the right one.
                possible = [
                    c for c in province.coasts
                    if c.key in unit.coast.borders_out
                    and c.unit_type == unit_type
                ]
                if len(possible) == 1: coast = possible[0]
        else:
            possible = []
            for item in province.coasts:
                if unit_type and item.unit_type != unit_type: continue
                if coastline and item.coastline != coastline: continue
                possible.append(item)
            if unit_type and datc.datc_4b6 == 'b' and not possible:
                possible = [
                    place for place in province.coasts
                    if place.unit_type == unit_type
                ]
            self.log_debug(20, 'Possible coasts for %s: %r of %r', unit_type,
                           possible, province.coasts)
            if len(possible) == 1: coast = possible[0]
            elif possible:
                # Multiple coasts; see whether our location disambiguates.
                # Note that my 4.B.2 "default" coast is the possible one.
                nearby = [
                    c for c in possible if c.key in unit.coast.borders_out
                ]
                if len(nearby) == 1 and datc.datc_4b2 != 'c': coast = nearby[0]
                elif nearby and datc.datc_4b1 == 'b': coast = nearby[0]
            if not coast:
                coast = Coast(None, province, coastline, [])
        self.log_debug(20, 'ordered_coast(%s, %s) -> %s (%s, %s, %s, %s)',
                       unit, coast_spec, coast, datc.datc_4b1, datc.datc_4b2,
                       datc.datc_4b3, datc.datc_4b6)
        return coast
예제 #2
0
 def create(klass, order, nation, board, datc):
     # Note that we don't care about order[3], so it could be MTO or CTO.
     unit = board.ordered_unit(nation, order[0], datc)
     supported = board.ordered_unit(nation, order[2], datc)
     if len(order) > 4:
         dest = board.ordered_coast(supported, order[4], datc)
         legal_dest = True
         if supported.can_move_to(dest):
             if datc.datc_4b4 in 'abc' and not dest.exists():
                 # Coastline specifications are required due to ambiguity
                 legal_dest = False
             elif dest.coastline:
                 if dest.coastline not in Message(order[4]):
                     # Coastline specifications might be required anyway
                     legal_dest = datc.datc_4b4 != 'a'
                 elif datc.datc_4b4 == 'e':
                     # Coastline specifications are ignored
                     dest = Coast(dest.unit_type, dest.province, None, [])
             routes = []
         else:
             routes = supported.coast.convoy_routes(dest.province, board)
         result = SupportMoveOrder(unit, supported, dest, legal_dest)
         result.routes = routes
     else:
         result = SupportHoldOrder(unit, supported)
     result.order = order
     return result
예제 #3
0
 def create(klass, order, nation, board, datc):
     for token in Message(order):
         if token.is_power():
             power = board.powers.get(token) or Power(token, [])
             break
     else:
         power = board.powers[nation.key]
     result = klass(power)
     result.order = order
     return result
예제 #4
0
 def handle_THX(self, message):
     ''' Complains about rejected orders, and tries to fix some of them.'''
     folded = message.fold()
     result = folded[2][0]
     if result != MBV:
         self.log_debug(7, 'Invalid order for %s: %s', self.power, message)
         replacement = None
         if result != NRS:
             move_unit = folded[1][0]
             move_type = folded[1][1]
             if move_type in (MTO, SUP, CVY, CTO):
                 replacement = [move_unit, HLD]
             elif move_type == RTO and result != NMR:
                 replacement = [move_unit, DSB]
             elif move_type == BLD and result != NMB:
                 replacement = [self.power, WVE]
         if replacement:
             self.log_debug(8, 'Ordering %s instead', Message(replacement))
             self.send(SUB(replacement))
예제 #5
0
 def tokenize(self):
     return Message(self.season, self.year)
예제 #6
0
    def ordered_unit(self, nation, unit_spec, datc=None):
        ''' Finds a unit from its token representation.
            If the specified unit doesn't exist, returns a fake one.
            Accepts any combination of country, unit type, province,
            and coast tokens (even illegal ones); last takes precedence.
            
            >>> Russia = standard_map.powers[RUS]
            >>> print standard_map.ordered_unit(Russia, [RUS, FLT, SEV])
            RUS FLT SEV
            
            # Finds an existing unit, if possible
            >>> print standard_map.ordered_unit(Russia, [RUS, STP])
            RUS FLT ( STP SCS )
            >>> unit = standard_map.ordered_unit(Russia, [MOS])
            >>> print unit
            RUS AMY MOS
            >>> unit.exists()
            True
            >>> print standard_map.ordered_unit(Russia, [BUD])
            AUS AMY BUD
            
            # Country and unit type can be guessed, but only if unambiguous 
            >>> unit = standard_map.ordered_unit(Russia, [AMY, UKR])
            >>> print unit
            RUS AMY UKR
            >>> unit.exists()
            False
            >>> print standard_map.ordered_unit(Russia, [BLA])
            RUS FLT BLA
            >>> unit = standard_map.ordered_unit(Russia, [ARM])
            >>> print unit.coast.unit_type
            None
            >>> unit.exists()
            False
            
            # Will not correct unambiguously wrong orders unless asked
            >>> unit = standard_map.ordered_unit(Russia, [RUS, (STP, NCS)])
            >>> print unit
            RUS FLT ( STP NCS )
            >>> unit.exists()
            False
            >>> class datc(object):
            ...     datc_4b5 = 'b'
            >>> unit = standard_map.ordered_unit(Russia, [RUS, (STP, NCS)], datc)
            >>> print unit
            RUS FLT ( STP SCS )
            >>> unit.exists()
            True
        '''#'''
        # Collect specifications
        country = unit_type = coastline = province = None
        for token in Message(unit_spec):
            if token.is_power():
                country = self.powers.get(token) or Power(token, [])
            elif token.is_province():
                province = self.spaces.get(token) or Province(token, [], None)
            elif token.is_coastline():
                coastline = token
            elif token.is_unit_type():
                unit_type = token
        if not province:
            raise ValueError('Missing province in unit spec: %s' %
                             Message(unit_spec))

        # Try to match all specs, but without ambiguity
        unit = None
        for item in province.units:
            if unit_type and item.coast.unit_type != unit_type: continue
            if country and item.nation != country: continue
            if (coastline and item.coast.coastline != coastline
                    and not (datc and datc.datc_4b5 == 'b')):
                continue

            if unit:
                if item.dislodged == unit.dislodged:
                    if item.nation == unit.nation:
                        unit = country = nation = None
                        break
                    elif item.nation == nation:
                        unit = item
                    elif unit.nation != nation:
                        unit = country = nation = None
                        break
                elif item.dislodged:
                    unit = item
            else:
                unit = item
        if not unit:
            coast = self.coasts.get((unit_type, province.key, coastline))
            if not coast:
                for item in province.coasts:
                    if unit_type and item.unit_type != unit_type: continue
                    if item.coastline != coastline: continue
                    if coast:
                        coast = Coast(None, province, coastline, [])
                        break
                    coast = item
                if not coast: coast = Coast(unit_type, province, coastline, [])
            unit = Unit(country or nation, coast)
        self.log_debug(20, 'ordered_unit(%s, %s) -> %s', nation, unit_spec,
                       unit)
        return unit
예제 #7
0
 def __str__(self):
     return str(Message(self))
예제 #8
0
 def tokenize(self):
     result = Message(self.key)
     if self.dislodged: result.extend(MRT(self.retreats))
     return result
예제 #9
0
 def tokenize(self):
     return Message([self.unit_type, self.maybe_coast])
예제 #10
0
 def send(self, message):
     if not self.closed: self.send_out(Message(message))
예제 #11
0
 def tokenize(self):
     return self.order or Message(self.key)
예제 #12
0
 def strict(self):
     return Message(self.key)
예제 #13
0
 def tokenize(self):
     from language import Message
     return Message(self.get_params())
예제 #14
0
 def tokenize(self):
     result = Message(self.key)
     if self.dislodged: result.extend(MRT(self.retreats))
     return result