def achieve_tech(G, player, pub, tech, *cIDs): if pub == 'open': G.players[player].technologies.add(tech) G.logger.write('{} has achieved {}'.format(player, tech)) elif pub == 'secret': G.players[player].secret_vault.add(tech) G.players[player].stats.handlimit -= 1 G.logger.write('{} has placed a technology in their secret vault ({} handlimit is now {})'.format( player, player, G.players[player].stats.handlimit)) G.logger.write('- You can reveal {} from your vault anytime during your turn'.format(tech), player=player) discard_cards(G, *cIDs) pass
def planning_phase(G, player, action): if action is None: if 'temp' in G: del G.temp G.temp = tdict() G.temp.season = G.game.sequence[G.game.index] G.temp.active_idx = 0 G.temp.active_players = G.game.turn_order.copy() if G.temp.season == 'Winter': G.temp.active_players = tlist(p for p in G.game.turn_order if G.players[p].stats.enable_Winter) G.temp.decision = tdict() G.temp.passes = 0 G.temp.borders = tdict({p: tdict() for p in G.players}) return encode_command_card_phase(G) faction = G.players[player] head, *tail = action if head == 'pass': G.temp.passes += 1 G.temp.active_idx += 1 G.temp.active_idx %= len(G.temp.active_players) G.logger.write('{} passes'.format(player)) elif head in faction.hand: G.temp.passes = 0 card = G.objects.table[head] del card.owner G.objects.updated[head] = card G.temp.decision[player] = card faction.hand.remove(head) G.logger.write('{} plays a card'.format(player)) G.temp.active_players.remove(player) if len(G.temp.active_players): G.temp.active_idx %= len(G.temp.active_players) if len(G.temp.active_players) > G.temp.passes: return encode_command_card_phase(G) # evaluate card choices G.temp.commands = tdict() for p, card in G.temp.decision.items( ): # RULE OVERRULED: emergency priority tie breaks are automatic if 'season' in card: cmd = tdict() cmd.priority = card.priority cmd.moved = tset() if card.season == G.temp.season: val = card.value msg = ' {} command: {} {}'.format(card.season, card.priority, val) else: cmd.emergency = True val = G.players[p].stats.emergency_command msg = 'n emergency command: {} {}'.format(card.priority, val) cmd.value = val G.temp.commands[p] = cmd else: msg = ' bluff (investment card)' G.logger.write('{} has played a{}'.format(p, msg)) discard_cards(G, card._id) if len(G.temp.commands): ##someone played cmd card ##players put in order of cards: G.temp.order contains players G.temp.order = tlist( k for k, v in sorted([(k, v.priority + ('e' if 'emergency' in v else '')) for k, v in G.temp.commands.items()], key=lambda x: x[1])) G.logger.write('Play order is: {}'.format(', '.join(G.temp.order))) G.temp.active_idx = 0 add_next_phase(G, 'Movement') else: G.logger.write('No player played a command card during {}'.format( G.temp.season)) raise PhaseComplete
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: # G.temp.move_to_post[player] = False #deactivate removing influence!!! 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 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: 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) #@@@@ G.players[inf.faction].diplomacy[diplvl[ dipl.value]].remove(nation) faction = G.players[inf.faction] faction.diplomacy[diplvl[val]].add(nation) dipl.faction = inf.faction dipl.value = val if val >= 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) if nation == 'USA' and not faction.stats.enable_USA: G.logger.write('{} has {} influence in the USA'.format( inf.faction, inf.value)) else: dname = dipname[val] G.logger.write('{} becomes {} of {}{}'.format( nation, dname, inf.faction, tmsg)) G.temp.new_sats = new_sats if len(new_sats): # plan a satellite phase to place garrison troops add_next_phase(G, 'Satellite') raise PhaseComplete
def governmnet_phase(G, player, action): # play cards if action is None: # prep influence G.logger.write('Beginning Government Phase') if 'temp' in G: del G.temp G.temp = tdict() G.temp.diplomacy = tdict() G.temp.diplomacy_cards = tset() G.temp.intel = tdict() G.temp.past_upgrades = tdict() for player in G.players: G.temp.past_upgrades[player] = 0 G.temp.passes = 0 G.temp.active_idx = 0 return encode_government_actions(G) if 'move_to_post' in G.temp: # after phase has ended and only clean up is necessary return government_post_phase(G, player, action) # TODO: make sure cards that should now be visible stay visible if player in G.temp.intel: # hide any temporarily visible objects from intel cards for ID, obj in G.temp.intel[player].items(): obj.visible.discard(player) G.objects.updated[ID] = obj del G.temp.intel[player] if 'hack' in G.temp: if player == G.temp.hack.source: raise NotImplementedError assert action == ( 'cancel', ), 'Misunderstood action: {}'.format(action) G.players[player].hand.add( G.temp.hack.card._id ) # make sure card is back in sources's ownership del G.temp.hack return encode_government_actions(G) else: actions = resolve_intel(G, player, action) if actions is not None: return actions elif 'mole' in G.temp: if action != ('accept', ): _, tech, _ = action G.logger.write('{} uses their mole to achieve {}'.format( player, tech), player=G.temp.mole) achieve_tech(G, player, *action) del G.temp.mole elif 'factory_upgrade' in G.temp: if action == ('cancel', ): G.logger.write('Cancelled factory upgrade', player=player) del G.temp.factory_upgrade return encode_government_actions(G) ID, = action val = G.objects.table[ID].value if ID in G.temp.factory_upgrade.selects: val = -val G.temp.factory_upgrade.selects.discard(ID) G.logger.write('Unselected {}'.format(ID), end='', player=player) else: G.temp.factory_upgrade.selects.add(ID) G.logger.write('Selected {}'.format(ID), end='', player=player) G.temp.factory_upgrade.value += val G.logger.write(' (value so far: {}/{})'.format( G.temp.factory_upgrade.value, G.players[player].stats.factory_cost), player=player) # print(G.temp.factory_upgrade.value) if G.temp.factory_upgrade.value < G.players[player].stats.factory_cost: return encode_factory_upgrade_actions(G) # factory upgrade complete G.players[player].tracks.IND += 1 G.temp.past_upgrades[player] += 1 G.players[player].hand -= G.temp.factory_upgrade.selects G.logger.write( '{} upgrades their IND to {} with factory card values of: {}'. format( player, G.players[player].tracks.IND, ', '.join( str(G.objects.table[ID].value) for ID in G.temp.factory_upgrade.selects))) discard_cards(G, *G.temp.factory_upgrade.selects) del G.temp.factory_upgrade G.temp.passes = 0 elif action == ('pass', ): G.logger.write('{} passes'.format(player)) G.temp.passes += 1 if G.temp.passes == len(G.players): G.logger.write( 'All players have passed consecutively - moving on to Government resolution' ) G.temp.move_to_post = tdict() # for handsize limit options for name, faction in G.players.items(): handsize = len(faction.hand) diff = handsize - faction.stats.handlimit if diff > 0: G.logger.write('{} must discard {} cards'.format( name, diff)) G.temp.move_to_post[name] = True return government_post_phase(G) else: # execute action head, *tail = action if head == 'factory_upgrade': G.temp.factory_upgrade = tdict() G.temp.factory_upgrade.value = 0 G.temp.factory_upgrade.selects = tset() G.logger.write('Select the cards to use for the factory upgrade', player=player) return encode_factory_upgrade_actions(G) elif head in G.players[ player].secret_vault: # reveal tech from secret vault reveal_tech(G, player, head) return encode_government_actions(G) elif head == 'remove': nation, = tail decrement_influence(G, nation) G.logger.write('{} removes one of their influence from {}'.format( player, nation)) return encode_government_actions(G) elif head in {'open', 'secret'}: G.temp.passes = 0 achieve_tech(G, player, head, *tail) else: G.temp.passes = 0 card = G.objects.table[head] if 'wildcard' in card: nation, = tail increment_influence(G, player, nation) extra = '' if card.wildcard == 'Foreign_Aid': # pay IND G.players[player].tracks.IND -= 1 extra = ' (decreasing IND to {})'.format( G.players[player].tracks.IND) G.logger.write( '{} plays {} adding/removing influence in {}{}'.format( player, card.wildcard, nation, extra)) discard_cards(G, head) elif 'intelligence' in card: discard_cards(G, head) return play_intel(G, player, card, *tail) else: nation, = tail play_diplomacy(G, player, nation) G.temp.diplomacy_cards.add(head) card.visible = xset(G.players.keys()) # visible to everyone G.players[card.owner].hand.discard(card._id) del card.owner G.objects.updated[head] = card # discard_cards(G, head) G.temp.active_idx += 1 G.temp.active_idx %= len(G.players) return encode_government_actions(G)
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 planning_phase(G, player, action): faction = G.players[player] head, *tail = action if head == 'pass': G.temp.passes += 1 G.temp.active_idx += 1 G.temp.active_idx %= len(G.temp.active_players) G.logger.write('{} passes'.format(player)) elif head in faction.hand: G.temp.passes = 0 card = G.objects.table[head] # if 'owner' del card.owner G.objects.updated[head] = card G.temp.decision[player] = card faction.hand.remove(head) G.logger.write('{} plays a card'.format(player)) G.temp.active_players.remove(player) if len(G.temp.active_players): G.temp.active_idx %= len(G.temp.active_players) if len(G.temp.active_players) > G.temp.passes: return encode_command_card_phase(G) # evaluate card choices if len(G.temp.decision) == 0: return #raise PhaseComplete G.temp.commands = tdict() for p, card in G.temp.decision.items( ): # RULE OVERRULED: emergency priority tie breaks are automatic if 'season' in card: cmd = tdict() cmd.priority = card.priority cmd.moved = tset() cmd.declarations = tset() if card.season == G.temp.season: val = card.value msg = ' {} command: {} {}'.format(card.season, card.priority, val) else: cmd.emergency = True val = G.players[p].stats.emergency_command msg = 'n emergency command: {} {}'.format(card.priority, val) cmd.value = val G.temp.commands[p] = cmd else: msg = ' bluff (investment card)' G.logger.write('{} has played a{}'.format(p, msg)) discard_cards(G, card._id) if len(G.temp.commands): G.temp.order = tlist( k for k, v in sorted([(k, v.priority + ('e' if 'emergency' in v else '')) for k, v in G.temp.commands.items()], key=lambda x: x[1])) G.logger.write('Play order is: {}'.format(', '.join(G.temp.order))) G.temp.active_idx = 0 else: G.logger.write('No player played a command card during {}'.format( G.temp.season))
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