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
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
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
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))
def tokenize(self): return Message(self.season, self.year)
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
def __str__(self): return str(Message(self))
def tokenize(self): result = Message(self.key) if self.dislodged: result.extend(MRT(self.retreats)) return result
def tokenize(self): return Message([self.unit_type, self.maybe_coast])
def send(self, message): if not self.closed: self.send_out(Message(message))
def tokenize(self): return self.order or Message(self.key)
def strict(self): return Message(self.key)
def tokenize(self): from language import Message return Message(self.get_params())