def setup_phase(G, player, action): # player, nationality, tilename, unit_type # place user chosen units nationality, tilename, unit_type = action unit = adict() unit.nationality = nationality unit.tile = tilename unit.type = unit_type #print(unit) add_unit(G, unit) G.temp.setup[player].cadres[nationality][tilename] -= 1 if G.temp.setup[player].cadres[nationality][tilename] == 0: del G.temp.setup[player].cadres[nationality][tilename] if len(G.temp.setup[player].cadres[nationality]) == 0: del G.temp.setup[player].cadres[nationality] if len(G.temp.setup[player].cadres) == 0: # all cadres are placed del G.temp.setup[player].cadres if 'action_cards' in G.temp.setup[player]: draw_cards(G, 'action', player, N=G.temp.setup[player].action_cards) del G.temp.setup[player].action_cards if 'investment_cards' in G.temp.setup[player]: draw_cards(G, 'action', player, N=G.temp.setup[player].action_cards) del G.temp.setup[player].investment_cards return encode_setup_actions(G)
def encode_post_gov_actions(G): code = adict() for player, is_active in G.temp.move_to_post.items(): faction = G.players[player] handsize = len(faction.hand) if not is_active and handsize <= faction.stats.handlimit: continue options = xset() if handsize > faction.stats.handlimit: for cid in faction.hand: options.add((cid, )) # options.update(faction.hand.copy()) # # options = xset((options,)) if is_active: options.add(('accept', )) # reveal techs from secret vault options.update(check_revealable(G, player)) # removable nations options.add((removable_nations(G, player), )) code[player] = options for player in G.players: if player not in code and player in G.temp.move_to_post: del G.temp.move_to_post[player] return code
def convert_to_armed_minor(G, nation): if nation in G.diplomacy.neutrals: del G.diplomacy.neutrals[nation] G.nations.status[nation].is_armed = 1 desig = G.nations.designations[nation] # arming the minor for tilename in G.nations.territories[nation]: tile = G.tiles[tilename] tile.owner = desig if tile.muster > 0: unit = adict() unit.nationality = nation unit.type = 'Fortress' unit.tile = tilename unit.cv = tile.muster unit = add_unit(G, unit) G.nations.status[nation].units[unit._id] = unit G.logger.write('A Fortress of {} appears in {} with cv={}'.format(nation, unit.tile, unit.cv))
def encode_setup_actions(G): code = adict() for faction, nationality, tilenames in seq_iterate(G.temp.setup, [None, 'cadres', None], end=True): # if player is not None and faction != player: # continue options = placeable_units(G, faction, nationality, tilenames) if len(options) == 0: continue if faction not in code: code[faction] = xset() code[faction].add((nationality, options)) if len(code) == 0: raise PhaseComplete return code
def count_victory_points(G): points = adict({p: 0 for p in G.players}) for name, faction in G.players.items(): # current production level prod_level = compute_production_level(faction) points[name] += prod_level # control of enemy capitals enemy_cities = 0 for rival, rival_faction in G.players.items(): if rival != name: if rival_faction.cities.MainCapital in faction.territory: enemy_cities += 1 for subcapital in rival_faction.cities.SubCapitals: if subcapital in faction.territory: enemy_cities += 1 points[name] += 2 * enemy_cities # count atomic research atomics = 0 for tech in faction.technologies: if 'Atomic' in tech: atomics += 1 points[name] += 1 * atomics # peace dividends points[name] += sum(faction.stats.peace_dividends) # subtract DoW DoWs = sum(faction.stats.DoW.values()) points[name] -= DoWs return points
def get_game_info(player): info = adict() info.game = adict() info.game.year = G.game.year info.game.phase = G.game.sequence[G.game.index] if 'turn_order' in G.game: info.game.turn_order = G.game.turn_order if 'winner' in G.game: info.game.winner = G.game.won.player info.game.winning_reason = G.game.won.reason info.players = adict() vps = count_victory_points(G) for p, faction in G.players.items(): play = adict() play.tracks = adict() for track, val in faction.tracks.items(): play.tracks[track] = val play.at_war_with = faction.stats.at_war_with play.DoW = faction.stats.DoW if p == player: play.victory_points = vps[p] reserves = adict() for member in faction.members.keys(): reserves[member] = G.units.reserves[member] play.reserves = reserves info.players[p] = play return info
def run(): for id in ids: path = os.path.join(self._path, wztype, '%d.xml' % id) if os.path.isfile(path): yield id, adict(cb(read_soup(path).find(wztype)))
def satellite_phase(G, player=None, action=None): if 'new_sats' in G.temp: new_sats = G.temp.new_sats if 'USA' in new_sats: name = new_sats['USA'] del new_sats['USA'] USA_becomes_satellite(G, name) sat_units = tdict() for nation, fname in new_sats.items(): becomes_satellite(G, fname, nation) if G.nations.status[nation].is_armed: # replace currently existing troops G.logger.write('{} may replace Armed Minor units in {}'.format(fname, nation)) removed = [] for uid, unit in G.nations.status[nation].units: if fname not in sat_units: sat_units[fname] = tdict() sat_units[fname][unit.tile] = unit.cv removed.append(unit) for unit in removed: remove_unit(G, unit) else: ts = [] for tilename in G.nations.territories[nation]: tile = G.tiles[tilename] if 'muster' in tile and tile.muster > 0: if fname not in sat_units: sat_units[fname] = tdict() sat_units[fname][tilename] = tile.muster ts.append(tilename) G.logger.write('{} may place units into {}'.format(fname, ', '.join(ts))) G.temp.sat_units = sat_units del G.temp.new_sats if action is not None: assert player in G.temp.sat_units, '{} has no garrison troops to place'.format(player) unit = adict() unit.tile, unit.type = action unit.nationality = G.players[player].stats.great_power unit.cv = G.temp.sat_units[player][unit.tile] add_unit(G, unit) del G.temp.sat_units[player][unit.tile] if len(G.temp.sat_units[player]) == 0: del G.temp.sat_units[player] if len(G.temp.sat_units): return encode_garrison_options(G) del G.temp.sat_units raise PhaseComplete
def resolve_intel(G, player, response): card = G.temp.hack.card assert player == G.temp.hack.target, 'Target should be responding' # G.logger.write('{} plays {} targeting {}'.format(G.temp.hack.source, G.temp.hack.card.intelligence, G.temp.hack.target)) if response != ('accept', ): # target plays Double Agent ID, *args = response # switch target and source, update args G.temp.hack.target = G.temp.hack.source G.temp.hack.source = player if len(args) > 1: args = (args[-1], ) G.temp.hack.args = args # discard double agent card discard_cards(G, ID) G.logger.write( 'However, {} uses their double agent to reverse the effects'. format(player)) target = G.temp.hack.target player = G.temp.hack.source args = G.temp.hack.args code = None if card.intelligence == 'Coup': nation, = args inf = G.diplomacy.influence[nation] assert inf.faction == target, 'Influence is owned by {} not the target ({})'.format( inf.faction, target) G.players[target].influence.remove(inf._id) del G.diplomacy.influence[nation] del G.objects.table[inf._id] G.objects.removed[inf._id] = inf G.logger.write('{} {} influence is removed from {}'.format( inf.value, target, nation)) elif card.intelligence == 'Agent': tilename, = args tile = G.tiles[tilename] G.temp.intel[player] = tdict() for uid in tile.units: unit = G.objects.table[uid] if unit.nationality in G.players[target].members: unit.visible.add(player) G.objects.updated[uid] = unit G.temp.intel[player][uid] = unit G.logger.write('{} may view all {}\'s units in {} for one turn'.format( player, target, tilename)) elif card.intelligence == 'Spy_Ring': cid = G.random.choice(list(G.players[target].hand)) G.players[target].hand.remove(cid) G.players[player].hand.add(cid) pick = G.objects.table[cid] pick.visible.clear() pick.visible.add(player) pick.owner = player G.objects.updated[cid] = pick G.logger.write('{} steals one card from {}\'s hand'.format( player, target)) elif card.intelligence == 'Sabotage': G.players[target].tracks.IND -= 1 G.logger.write('{} IND is decreased to {}'.format( target, G.players[target].tracks.IND)) elif card.intelligence == 'Code_Break': G.temp.intel[player] = tdict() for cid in G.players[target].hand: card = G.objects.table[cid] card.visible.add(player) G.temp.intel[player][cid] = card G.objects.updated[cid] = card G.logger.write('{} may view {}\'s hand for one turn'.format( player, target)) elif card.intelligence == 'Mole': G.logger.write( '{} may view {}\'s secret vault, and possibly achieve a tech therein' ) vault = G.players[target].secret_vault G.logger.write('{}\'s secret vault contains: {}'.format( target, ', '.join(vault)), player=player) options = xset() for cid in G.players[player].hand: card = G.objects.table[cid] if card.obj_type == 'investment_card' and 'top' in card: if card.top in vault and is_achievable_tech( G, player, card.top): options.add((card.top, cid)) if card.bottom in vault and is_achievable_tech( G, player, card.bottom): options.add((card.bottom, cid)) if len(options): # any tech can be achieved openly or in secret options = xset((xset(['open', 'secret']), options)) options.add(('accept', )) G.temp.mole = target code = adict() code[player] = options else: raise Exception('Unknown intelligence card type: {}'.format( card.intelligence)) del G.temp.hack return code # is None unless mole was played
def check_techs(G, player, cards): global_techs = xset() for name, faction in G.players.items(): if name != player: global_techs.update(faction.technologies) # print(len(cards)) science = adict({ cid: card for cid, card in cards.items() if 'science' in card and card.year <= G.game.year }) simple = adict({cid: card for cid, card in cards.items() if 'top' in card}) # print(len(science), len(simple)) # print(simple) available = adict() for cid, card in simple.items(): if card.top not in available: available[card.top] = xset() available[card.top].add(cid) if card.bottom not in available: available[card.bottom] = xset() available[card.bottom].add(cid) espionage = None if 'Industrial_Espionage' in available: espionage = available['Industrial_Espionage'] del available['Industrial_Espionage'] # remove already discovered techs for tech in G.players[player].technologies: if tech in available: del available[tech] # remove unachievable techs (higher atomic techs) # print(available.keys()) available = adict({ t: c for t, c in available.items() if is_achievable_tech(G, player, t) }) # print(available) options = xset() for tech, sIDs in available.items(): topts = xset() if len(sIDs) > 1: topts.update(choose_2_from(sIDs)) for sciID in science: if tech in cards[sciID].science: topts.add((sIDs, sciID)) if espionage is not None and tech in global_techs: for eID in espionage: combs = sIDs.copy() combs.discard(eID) if len(combs) > 0: topts.add((sIDs, eID)) if len(topts): options.add((tech, topts)) if len(options): # any tech can be achieved openly or in secret options = xset([(xset(['open', 'secret']), options)]) return options
def factory_upgrade_combos(cards, cost): options = adict({c._id: c.value for c in cards}) IDs, vals = zip( *sorted(options.items(), key=operator.itemgetter(1), reverse=True)) return map(tuple, opposite_knapsack(IDs, options, cost))
# if 'log' in out and len(out.log): # print('<{} log>'.format(player)) # print(out.log, end='') # print('</{}>'.format(player)) from flask_app import * print(ping()) if False: out = format_msg_to_python(init_game(debug=True, player='Axis')) G = get_G() fixed = adict() # Setup + New Year try: for player in G.game.turn_order: fixed[player] = [('investment_card', )] * 6 # + [('action_card',)] players = G.game.turn_order except KeyError: players = ['Axis', 'USSR', 'West'] print(players) complete_phase(players) path = save('setup_complete.json') print('Saved Setup phase at {}'.format(path))
def load_gen_card_decks( G, card_config_path='config/card_stats.yml', ): cc = load(card_config_path) config = cc.action_cards G.action_cards = adict() card_list = [] dim = 2 num = sum(config.diplomacy.values()) // dim for _ in range(10): try: picks = split_choices(G, list(config.diplomacy.items()), num, dim) except ValueError: pass else: break wildcards = [] for name, info in config.wildcards.items(): for _ in range(info.count): card = idict(info.items()) del card.count card.name = name wildcards.append(card) G.random.shuffle(wildcards) for season, info in config.seasons.items(): commands = sum([[k] * v for k, v in info.commands.items()], []) G.random.shuffle(commands) if len(info.priorities) > info.count: priorities = G.random.choice(info.priorities, info.count, replace=False).tolist() else: priorities = info.priorities assert len(priorities) == info.count for _ in range(info.num_wildcards): command, priority = commands.pop(), priorities.pop() wildcard = wildcards.pop() card = idict() card.wildcard = wildcard card.command_value = command card.command_priority = priority card.season = season card_list.append(card) for command, priority in zip(commands, priorities): dpl1, dpl2 = picks.pop() card = idict() card.command_value = command card.command_priority = priority card.season = season card.top_diplomacy = dpl1 card.bottom_diplomacy = dpl2 card_list.append(card) G.action_cards.deck = card_list config = cc.investment_cards G.investment_cards = adict() card_list = [] dim = 2 num = 0 techs = [] for name, info in config.technologies.items(): tech = adict(info.items()) count = info.count del tech.count num += count tech.name = name techs.append((tech, count)) for name, info in config.intelligence.items(): tech = adict(info.items()) count = info.count del tech.count num += count tech.name = name techs.append((tech, count)) num = num // dim for _ in range(10): try: picks = split_choices(G, techs, num, dim) except ValueError: pass else: break factories = sum([[k] * v for k, v in config.factory_levels.items()], []) G.random.shuffle(factories) for pick in picks: tech1, tech2 = pick card = idict() card.top_technology = tech1 card.bottom_technology = tech2 card.factory_value = factories.pop() card_list.append(card) G.investment_cards.deck = card_list G.action_cards.discard_pile = [] G.investment_cards.discard_pile = [] G.random.shuffle(G.investment_cards.deck) G.random.shuffle(G.action_cards.deck)
def ANS_rebase_options(G, unit): pts = G.units.rules[unit.type].move options = xset() if pts == 0: return options player = G.nations.designations[unit.nationality] tile = G.tiles[unit.tile] destinations = xset() crossings = adict() borders = G.temp.borders[player] # past border crossings ugroup = G.units.rules[unit.type].type hidden_movement = ugroup == 'S' or ugroup == 'A' disengaging = () #if 'disputed' in tile else None fuel = pts #brauche nur non-strategic movement! is_disengaging = True defensive = True #das ist fuer non-strategic movement #actually, ugroup cannot be 'G' since this is rebasing! #if using it for retreat also, keep this! xing = crossings if ugroup == 'G' else None #borders tracked?!? current = xset() #sea movement if ugroup in 'NS' or (ugroup == 'G' and tile.type in movement_restrictions['sea']): # sea movement fill_movement(G, player, tile, current, crossings=xing, borders=borders, move_type='sea', fuel=fuel, disengaging=disengaging, friendly_only=defensive, hidden_movement=hidden_movement) destinations.update(current) current = xset() # land movement if ugroup == 'G': fill_movement(G, player, tile, destinations, crossings=xing, borders=borders, move_type='land', fuel=fuel, disengaging=disengaging, friendly_only=defensive, hidden_movement=hidden_movement) destinations.update(current) current = xset() if ugroup == 'A': fill_movement(G, player, tile, destinations, crossings=xing, borders=borders, move_type='air', fuel=fuel, disengaging=disengaging, friendly_only=defensive, hidden_movement=hidden_movement) destinations.update(current) #air cannot rebase to sea areas! #eliminate those from dest destinations.discard(unit.tile) #air rebase only to land area if ugroup == 'A': destinations = [d for d in destinations if is_land_area(G, d)] for dest in destinations: if dest in crossings: options.add((dest, crossings[dest])) else: options.add((dest, )) return options
def setup_phase(G, player, action): # player, nationality, tilename, unit_type # place user chosen units if action is None: # pre phase player_setup = load(player_setup_path) # prep temp info - phase specific data temp = tdict() temp.setup = tdict() for name, faction in player_setup.items(): if 'units' in faction.setup: for unit in faction.setup.units: add_unit(G, unit) del faction.setup.units temp.setup[name] = faction.setup G.temp = temp # return action adict(faction: (action_keys, action_options)) return encode_setup_actions(G) nationality, tilename, unit_type = action unit = adict() unit.nationality = nationality unit.tile = tilename unit.type = unit_type add_unit(G, unit) G.temp.setup[player].cadres[nationality][tilename] -= 1 if G.temp.setup[player].cadres[nationality][tilename] == 0: del G.temp.setup[player].cadres[nationality][tilename] if len(G.temp.setup[player].cadres[nationality]) == 0: del G.temp.setup[player].cadres[nationality] if len(G.temp.setup[player].cadres) == 0: # all cadres are placed del G.temp.setup[player].cadres if 'action_cards' in G.temp.setup[player]: draw_cards(G, 'action', player, N=G.temp.setup[player].action_cards) del G.temp.setup[player].action_cards if 'investment_cards' in G.temp.setup[player]: draw_cards(G, 'action', player, N=G.temp.setup[player].action_cards) del G.temp.setup[player].investment_cards return encode_setup_actions(G)
def encode_production_actions(G): code = adict() active_player = G.game.turn_order[G.temp.active_idx] faction = G.players[active_player] options = xset() # pass options.add(('pass', )) # cards options.add(('action_card', )) options.add(('investment_card', )) ex_territory = faction.territory.copy() # new cadres for nationality, tiles in faction.homeland.items(): groups = placeable_units(G, active_player, nationality, tiles) if len(groups): options.add((nationality, groups)) ex_territory -= tiles # new fortresses fort_opts = adict() for tilename in ex_territory: tile = G.tiles[tilename] if not contains_fortress(G, tile): nationality = faction.stats.great_power for nat, lands in faction.members.items(): if tile.alligence in lands: nationality = nat break if G.units.reserves[nationality].Fortress > 0: if nationality not in fort_opts: fort_opts[nationality] = xset() fort_opts[nationality].add(tilename) if len(fort_opts): for nationality, tiles in fort_opts.items(): options.add((nationality, tiles, 'Fortress')) # improve units improvable = xset() for uid, unit in faction.units.items(): # can't upgrade a cv of 4 if unit.cv == 4: continue tile = G.tiles[unit.tile] # unit must be supplied and not engaged if 'disputed' in tile or 'unsupplied' in tile: continue # tile must be land or coast if tile.type in {'Sea', 'Ocean'}: continue improvable.add(unit._id) improvable -= G.temp.prod[active_player].upgraded_units if len(improvable): options.add((improvable, )) code[active_player] = options return code
def production_phase(G, player, action): if len(action) == 1: # card or upgrade unit if action == ('action_card', ): G.temp.prod[player].action_cards_drawn += 1 effect = 'drawing an action card' elif action == ('investment_card', ): G.temp.prod[player].invest_cards_drawn += 1 effect = 'drawing an investment card' elif action == ('pass', ): effect = 'passing' else: ID, = action G.temp.prod[player].upgraded_units.add(ID) unit = G.objects.table[ID] unit.cv += 1 G.objects.updated[ID] = unit effect = 'upgrading a unit in {}'.format(G.objects.table[ID].tile) else: # create new unit nationality, tilename, unit_type = action unit = adict() unit.nationality = nationality unit.tile = tilename unit.type = unit_type unit = add_unit(G, unit) G.temp.prod[player].upgraded_units.add(unit._id) effect = 'building a new cadre in {}'.format(unit.tile) G.temp.prod[player].production_remaining -= 1 G.logger.write( '{} spends 1 production on {} ({} production remaining)'.format( player, effect, G.temp.prod[player].production_remaining)) if G.temp.prod[player].production_remaining == 0: # draw cards draw_cards(G, 'action', player, N=G.temp.prod[player].action_cards_drawn) draw_cards(G, 'investment', player, N=G.temp.prod[player].invest_cards_drawn) G.logger.write('{} is done with production'.format(player)) # clean up temp del G.temp.prod[player] # move to next player G.temp.active_idx += 1 if G.temp.active_idx == len(G.players): raise PhaseComplete # phase is done active_player = G.game.turn_order[G.temp.active_idx] G.logger.write('{} may spend {} production points'.format( active_player, G.temp.prod[active_player].production_remaining)) return encode_production_actions(G)
def travel_options(G, unit): pts = G.units.rules[unit.type].move options = xset() if pts == 0: return options player = G.nations.designations[unit.nationality] tile = G.tiles[unit.tile] destinations = xset() crossings = adict() cmd = G.temp.commands[player] borders = G.temp.borders[player] # past border crossings cls = G.units.rules[unit.type].type hidden_movement = cls == 'S' or cls == 'A' disengaging = () if 'disputed' in tile else None for defensive in range( 2): # gen all steps once with strategic movement and once without if defensive and ('emergency' in cmd or disengaging is not None): continue fuel = pts * (1 + defensive) if 'emergency' in cmd or disengaging is not None: defensive = True xing = crossings if cls == 'G' and ( not defensive or disengaging is not None) else None # if defensive: # 1+1 current = xset() if cls in 'NS' or (cls == 'G' and tile.type in movement_restrictions['sea']): # sea movement fill_movement(G, player, tile, current, crossings=xing, borders=borders, move_type='sea', fuel=fuel, disengaging=disengaging, friendly_only=defensive, hidden_movement=hidden_movement) if len(crossings): print('CROSSINGS', crossings) else: print('*********no crossings!') if len(borders): print('BORDERS', borders) else: print('*********no borders!') # print(destinations) destinations.update(current) current = xset() if cls == 'G': # land movement fill_movement(G, player, tile, destinations, crossings=xing, borders=borders, move_type='land', fuel=fuel, disengaging=disengaging, friendly_only=defensive, hidden_movement=hidden_movement) destinations.update(current) current = xset() if cls == 'A': if tile.type in {'Sea', 'Ocean'}: fuel = pts # no strategic movement defensive = 1 # no engaging fill_movement(G, player, tile, destinations, crossings=xing, borders=borders, move_type='air', fuel=fuel, disengaging=disengaging, friendly_only=defensive, hidden_movement=hidden_movement) if tile.type in {'Sea', 'Ocean'}: break destinations.update(current) destinations.discard(unit.tile) for dest in destinations: if dest in crossings: options.add((dest, crossings[dest])) else: options.add((dest, )) return options
def government_post_phase(G, player=None, action=None): if len(G.temp.move_to_post) and action is not None: action, = action if action == 'accept': G.temp.move_to_post[player] = False elif action in G.players[player].hand: discard_cards(G, action) elif action in G.players[player].secret_vault: reveal_tech(G, player, action) else: decrement_influence(G, action) action = None code = encode_post_gov_actions(G) if len(code): return code # diplomacy resolution (check for control, discard diplomacy_cards), handsize, update tracks # resolve diplomacy if 'diplomacy' in G.temp: discard_cards(G, *G.temp.diplomacy_cards) del G.temp.diplomacy_cards for nation, (fname, val) in G.temp.diplomacy.items(): for _ in range(val): increment_influence(G, fname, nation) del G.temp.diplomacy # check for control new_sats = tdict() for nation, dipl in G.diplomacy.neutrals.items(): if nation not in G.diplomacy.influence: if dipl.faction is None: continue else: faction = G.players[dipl.faction] faction.diplomacy[diplvl[dipl.value]].remove(nation) pop, res = compute_tracks(G.nations.territories[nation], G.tiles) faction.tracks.POP -= pop faction.tracks.RES -= res G.logger.write('{} lost influence over {} (losing POP={} RES={})'.format(dipl.faction, nation, pop, res)) dipl.value = 0 dipl.faction = None else: inf = G.diplomacy.influence[nation] val = min(inf.value, 3) gainer = None loser = None if nation == 'USA': # handle USA separately if dipl.faction is None: if G.players[inf.faction].stats.enable_USA: gainer = inf.faction elif dipl.faction == inf.faction: if G.players[dipl.faction].stats.enable_USA and dipl.value != val: G.players[dipl.faction].diplomacy[diplvl[dipl.value]].remove(nation) else: if G.players[dipl.faction].stats.enable_USA: loser = dipl.faction G.players[dipl.faction].diplomacy[diplvl[dipl.value]].remove(nation) if G.players[inf.faction].stats.enable_USA: gainer = inf.faction else: val = min(inf.value, 3) # cap influence at 3 if dipl.faction is None: gainer = inf.faction elif dipl.faction != inf.faction: loser = dipl.faction gainer = inf.faction G.players[dipl.faction].diplomacy[diplvl[dipl.value]].remove(nation) elif dipl.value == val: # no change required continue else: # value has changed G.players[inf.faction].diplomacy[diplvl[dipl.value]].remove(dipl.faction) faction = G.players[inf.faction] faction.diplomacy[diplvl[inf.value]].add(dipl.faction) dipl.faction = inf.faction dipl.value = inf.value if inf.value == 3: new_sats[nation] = inf.faction # update tracks tmsg = '' if gainer is not None or loser is not None: pop, res = compute_tracks(G.nations.territories[nation], G.tiles) if gainer is not None: G.players[gainer].tracks.POP += pop G.players[gainer].tracks.RES += res tmsg += ' ({} gains POP={}, RES={})'.format(gainer, pop, res) if loser is not None: G.players[loser].tracks.POP -= pop G.players[loser].tracks.RES -= res tmsg += ' (lost by {})'.format(loser) dname = dipname[inf.value] G.logger.write('{} becomes {} of {}{}'.format(nation, dname, inf.faction, tmsg)) if 'USA' in new_sats: name = new_sats['USA'] del new_sats['USA'] USA_becomes_satellite(G, name) sat_units = tdict() for nation, fname in new_sats.items(): becomes_satellite(G, nation) for tilename in G.nations.territories[nation]: tile = G.tiles[tilename] if 'muster' in tile: if fname not in sat_units: sat_units[fname] = tdict() sat_units[fname][tilename] = tile.muster G.temp.sat_units = sat_units # place garrison in new satellites if action is not None: unit = adict() unit.tile, unit.type = action unit.nationality = G.players[player].stats.great_power unit.cv = G.temp.sat_units[player][unit.tile] add_unit(G, unit) del G.temp.sat_units[player][unit.tile] if len(G.temp.sat_units[player]) == 0: del G.temp.sat_units[player] if len(G.temp.sat_units): return encode_sat_units(G) raise PhaseComplete
from collections import namedtuple import traceback from new_year import new_year_phase from production import production_phase, production_pre_phase from government import governmnet_phase, government_pre_phase from command import command_phase, pre_command_phase import json PRE_PHASES = adict({ # all action phases 'Setup': setup_pre_phase, 'Production': production_pre_phase, 'Government': government_pre_phase, 'Spring': pre_command_phase, 'Summer': pre_command_phase, 'Fall': pre_command_phase, 'Winter': pre_command_phase, # 'Land_Combat': None, # 'Naval_Combat': None, }) PHASES = adict({ 'Setup': setup_phase, 'New_Year': new_year_phase, 'Production': production_phase, 'Government': governmnet_phase, 'Spring': command_phase, 'Summer': command_phase, 'Blockade': None, 'Fall': command_phase, 'Winter': command_phase,
import json PHASES = adict({ 'Setup': setup_phase, 'New_Year': new_year_phase, 'Production': production_phase, 'Government': governmnet_phase, 'Spring': planning_phase, 'Summer': planning_phase, 'Blockade': blockade_phase, 'Fall': planning_phase, 'Winter': planning_phase, 'Satellite': satellite_phase, 'Movement': movement_phase, 'Combat': combat_phase, 'Land Battle': land_battle_phase, 'Sea Battle': sea_battle_phase, 'Supply': supply_phase, 'Retreat': retreat_phase, 'Land_Battle': land_battle_phase, 'Naval_Battle': sea_battle_phase, 'Scoring': scoring_phase, }) # ALL game information is in the gamestate "G"
def violation_of_neutrality(G, declarer, nation): # including world reaction and placing armed minor units assert nation in G.diplomacy.neutrals, '{} is no longer neutral'.format(nation) G.players[declarer].stats.aggressed = True G.logger.write('{} has violated the neutrality of {}'.format(declarer, nation)) # world reaction reaction = G.tiles[G.nations.capitals[nation]].muster rivals = G.players[declarer].stats.rivals G.logger.write('{} draw {} cards for world reaction'.format(' and '.join(rivals, reaction))) for rival in rivals: draw_cards(G, 'action', rival, reaction) # remove influence if nation == 'USA': assert declarer not in {'West', 'USSR'}, 'West/USSR cannot violate the neutrality of the USA' if 'USA' in G.diplomacy.influence: inf = G.diplomacy.influence['USA'] del G.diplomacy.influence['USA'] del G.objects.table[inf._id] G.objects.removed[inf._id] = inf G.logger.write('{} loses {} influence in the USA'.format(inf.faction, inf.value)) # USA becomes a West satellite USA_becomes_satellite(G, 'West') if not G.players[declarer].stats.at_war_with['West']: declaration_of_war(G, declarer, 'West') return if nation in G.diplomacy.influence: inf = G.diplomacy.influence[nation] if inf.faction != declarer and inf.value == 2 and not G.players[declarer].stats.at_war_with[inf.faction]: G.logger.write('Since {} was a protectorate of {}, {} hereby declares war on {}'.format(nation, inf.faction, declarer, inf.faction)) declaration_of_war(G, declarer, inf.faction) # nation should now become a satellite of inf.faction - including placing units raise NotImplementedError lvl = diplvl[inf.value] G.players[inf.faction].diplomacy[lvl].remove(nation) decrement_influence(G, nation, inf.value) G.logger.write('{} loses {} influence in {}'.format(inf.faction, inf.value, nation)) # arming the minor for tilename in G.nations.territories[nation]: tile = G.tiles[tilename] if tile.muster > 0: unit = adict() unit.nationality = nation unit.type = 'Fortress' unit.tile = tilename unit.cv = tile.muster add_unit(G, unit) G.logger.write('A Fortress of {} appears in {} with cv={}'.format(nation, unit.tile, unit.cv))
def add_battles_to_reveal(G, player): #turn all units to be visible on each tile in G.temp.battles_to_reveal #moves revealed battles from battles_to_reveal to battles_to_fight #print('battles are revealed...') c = G.temp.combat for tile in c.battles_to_reveal: # atk = c.battles_to_reveal[tile] #print('...', tile, type(tile)) units = G.tiles[tile].units c.battles[tile] = adict() c.battles_remaining.append(tile) b = c.battles[tile] b.tilename = tile b.tile = G.tiles[tile] b.isSeaBattle = b.tile.type in ['Sea', 'Ocean'] #find owners of units on that tile #TODO: replace by powers_present!!! owners = [k for k in powers_present(G, b.tile)] if len(owners) != 2: #TODO implement 3 way battles #if this is the defender, needs to choose who to attack #for now assume that there must be exactly 2 parties in a combat c.ERROR = 'NOT SUPPORTED: COMBAT WITH POWERS != 2 ' + b.tilename pass b.owner = b.tile.owner if 'owner' in tile else None uidsList = [k for k in units] if not b.owner: uid = uidsList[0] b.owner = find_unit_owner(G, G.objects.table[uid]) b.intruder = owners[1] if b.owner == owners[0] else owners[0] assert G.temp.attacker == player, 'ATTACKER != PLAYER!!!!!!' b.attacker = G.temp.attacker #GANZ SICHER RICHTIG b.defender = owners[1] if b.attacker == owners[0] else owners[0] b.units = [] for id in units: unit = G.objects.table[id] unit.visible = xset(G.players.keys()) G.objects.updated[id] = unit attacker = b.attacker defender = b.defender uowner = find_unit_owner(G, unit) uopponent = defender if uowner == attacker else attacker utype = unit.type ugroup = G.units.rules[utype].type upriority = G.units.rules[utype].priority udamage = G.units.rules[utype] uid = id u_battle_group = None if b.isSeaBattle and b.tilename in G.temp.battle_groups and uid in G.temp.battle_groups[b.tilename]: u_battle_group = G.temp.battle_groups[b.tilename][uid] uff = False prec_bomb = False air_def_radar = False sonar = False u = adict() u.unit = unit u.owner = uowner u.group = ugroup u.priority = upriority u.rules = udamage u.id = uid u.battle_group = u_battle_group #modifying cards uff = hasFirstFire(G, uowner, utype) if uowner in G.players: tech = G.players[player].technologies #determine IND damage of AirForce: if utype == 'AirForce' and 'Jets' in tech: prec_bomb = True # air defense radar: #Air Forces in Friendly Territory (1.14) Fire doubledice (two dice/CV) at Enemy Air if uowner == b.owner and utype == 'AirForce' and 'Air_Defense_Radar' in tech: air_def_radar = True #sonar if utype == 'Fleet' and 'Sonar' in tech: sonar = True u.ff = uff u.sonar = sonar u.air_def_radar = air_def_radar u.prec_bomb = prec_bomb u.type = unit.type #if owner of this unit is defender he goes first by default #u.turn 0: this unit goes before same type of opponent, otherwise 1 u.turn = 0 opp_has_ff = hasFirstFire(G, uopponent, utype) uHasFF = False if uowner == 'Minor': if not opp_has_ff: uHasFF = True elif uopponent == 'Minor': if u.ff: uHasFF = True elif uowner == attacker and G.players[uowner].stats.DoW[uopponent] and not opp_has_ff: uHasFF = True elif uowner == attacker and u.ff and not opp_has_ff: uHasFF = True elif uowner == defender and (u.ff or (not opp_has_ff and not G.players[uopponent].stats.DoW[uowner])): uHasFF = True u.turn = 0 if uHasFF else 1 b.units.append(u) unitsSorted = sorted(b.units, key=lambda u: u.battle_group if u.battle_group else 'zzz') if b.isSeaBattle else b.units b.fire_order = sorted(unitsSorted, key=lambda u: u.priority * 10 + u.turn) c.battles_to_reveal.clear()
def production_phase(G, player, action): if action is None: if 'temp' in G: del G.temp G.temp = tdict() G.temp.active_idx = 0 G.temp.prod = tdict() # TODO: update/evaluate blockades for player, faction in G.players.items(): # TODO: check if production is zero because MainCapital is lost -> faction.stats.fallen flag G.temp.prod[player] = tdict() G.temp.prod[player].production_remaining = compute_production_level(faction) G.temp.prod[player].upgraded_units = tset() G.temp.prod[player].action_cards_drawn = 0 G.temp.prod[player].invest_cards_drawn = 0 # remove all blockades (not unsupplied markers) active_player = G.game.turn_order[G.temp.active_idx] G.logger.write( '{} may spend {} production points'.format(active_player, G.temp.prod[active_player].production_remaining)) return encode_production_actions(G) if len(action) == 1: # card or upgrade unit if action == ('action_card',): G.temp.prod[player].action_cards_drawn += 1 effect = 'drawing an action card' elif action == ('investment_card', ): G.temp.prod[player].invest_cards_drawn += 1 effect = 'drawing an investment card' elif action == ('pass',): effect = 'passing' else: ID, = action G.temp.prod[player].upgraded_units.add(ID) unit = G.objects.table[ID] unit.cv += 1 G.objects.updated[ID] = unit effect = 'upgrading a unit in {}'.format(G.objects.table[ID].tile) else: # create new unit nationality, tilename, unit_type = action unit = adict() unit.nationality = nationality unit.tile = tilename unit.type = unit_type unit = add_unit(G, unit) G.temp.prod[player].upgraded_units.add(unit._id) effect = 'building a new cadre in {}'.format(unit.tile) G.temp.prod[player].production_remaining -= 1 G.logger.write('{} spends 1 production on {} ({} production remaining)'.format(player, effect, G.temp.prod[player].production_remaining)) if G.temp.prod[player].production_remaining == 0: # draw cards draw_cards(G, 'action', player, N=G.temp.prod[player].action_cards_drawn) draw_cards(G, 'investment', player, N=G.temp.prod[player].invest_cards_drawn) G.logger.write('{} is done with production'.format(player)) # clean up temp del G.temp.prod[player] # move to next player G.temp.active_idx += 1 if G.temp.active_idx == len(G.players): raise PhaseComplete # phase is done active_player = G.game.turn_order[G.temp.active_idx] G.logger.write( '{} may spend {} production points'.format(active_player, G.temp.prod[active_player].production_remaining)) return encode_production_actions(G)