Пример #1
0
def setup_pre_phase(G, player_setup_path='config/faction_setup.yml'):

    player_setup = load(player_setup_path)

    # place fixed units

    for name, config in player_setup.items():
        if 'units' not in config.setup:
            continue

        for unit in config.setup.units:
            add_unit(G, unit)

    # prep temp info

    G.temp = tdict()

    for name, faction in player_setup.items():
        out = tdict()
        out.player = name
        if 'cadres' in faction.setup:
            out.info = faction.setup.cadres
            out.msg = 'Choose this many cadres to place into each of these territories'
        else:
            out.msg = 'Wait while other players place their cadres'
Пример #2
0
def load_map(G, tiles='config/tiles.yml', borders='config/borders.yml'):

    tiles = load(tiles)
    borders = load(borders)

    for b in borders:
        n1, n2 = b.tile1, b.tile2
        t = b.type

        if 'borders' not in tiles[n1]:
            tiles[n1].borders = tdict()
        tiles[n1].borders[n2] = t

        if 'borders' not in tiles[n2]:
            tiles[n2].borders = tdict()
        tiles[n2].borders[n1] = t

    G.tiles = tiles

    for name, tile in G.tiles.items():
        tile.name = name
        tile.units = tset()
        if tile.type != 'Sea' and tile.type != 'Ocean':
            for neighbor in tile.borders.keys():
                if G.tiles[neighbor].type == 'Sea' or G.tiles[
                        neighbor].type == 'Ocean':
                    tile.type = 'Coast'
                    break

        # add tile to game objects
        tile.obj_type = 'tile'
        G.objects.table[name] = tile
Пример #3
0
def load_game_info(G, seed=None, path='config/game_info.yml'):
    info = load(path)

    game = tdict()

    game.seed = seed
    G.random = random.Random(seed)
    # G.random = TestRandom(seed)

    game.year = info.first_year - 1  # zero based
    game.last_year = info.last_year
    num_rounds = game.last_year - game.year

    game.turn_order_options = info.turn_order_options

    game.sequence = ['Setup'] + num_rounds * info.year_order + ['Scoring']
    game.index = 0  # start below 0, so after increment in next_phase() it starts at 0
    #game.action_phases = tset(x for x in info.phases if info.phases[x]) # no need for action phases anymore (all action phases have a pre phase)

    game.peace_dividends = tlist(
        sum([[v] * n for v, n in info.peace_dividends.items()], []))
    G.random.shuffle(game.peace_dividends)

    game.victory = info.victory

    G.game = game

    G.objects = tdict()
    G.objects.table = tdict()
Пример #4
0
def load_map(G, tiles='config/tiles.yml', borders='config/borders.yml'):

    tiles = load(tiles)
    borders = load(borders)

    for b in borders:
        n1, n2 = b.tile1, b.tile2
        t = b.type

        if 'borders' not in tiles[n1]:
            tiles[n1].borders = tdict()
        tiles[n1].borders[n2] = t

        if 'borders' not in tiles[n2]:
            tiles[n2].borders = tdict()
        tiles[n2].borders[n1] = t

    G.tiles = tdict({name: idict(tile) for name, tile in tiles.items()})

    for name, tile in G.tiles.items():
        tile.__dict__['_id'] = name
        # tile.name = name
        tile.units = tset()
        if tile.type not in {'Sea', 'Ocean', 'Strait'}:
            for neighbor in tile.borders.keys():
                if G.tiles[neighbor].type == 'Sea' or G.tiles[
                        neighbor].type == 'Ocean':
                    tile.type = 'Coast'
                    break

        # add tile to game objects
        tile.obj_type = 'tile'
        tile.visible = tset({'Axis', 'West', 'USSR'})
        G.objects.table[name] = tile
Пример #5
0
def production_pre_phase(G):

    if 'temp' in G:
        del G.temp

    G.temp = tdict()

    G.temp.active_idx = 0
    G.temp.prod = tdict()

    # TODO: update blockades

    for player, faction in G.players.items():
        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)
Пример #6
0
def new_movement(G, player):
    G.temp.battles = tdict()  # track new battles due to engaging
    G.temp.has_moved = tdict()  # units can only move once per movement phase
    G.temp.threats = tset()
    G.temp.battle_groups = tdict()

    active = G.temp.order[G.temp.active_idx]
    G.logger.write('{} has {} command points for movement'.format(
        active, G.temp.commands[active].value))
Пример #7
0
def load_game_info(G, path='config/game_info.yml'):
    info = load(path)

    game = tdict()

    game.sequence = ['Setup'] + 10 * info.year_order
    game.index = -1  # start below 0, so after increment in next_phase() it starts at 0
    #game.action_phases = tset(x for x in info.phases if info.phases[x]) # no need for action phases anymore (all action phases have a pre phase)

    G.game = game

    G.objects = tdict()
    G.objects.table = tdict()
Пример #8
0
def eval_movement(G, source, unit,
                  dest):  # usually done when a unit leaves a tile
    player = G.nations.designations[unit.nationality]
    new_battle, engaging, disengaging = False, False, False

    # update source
    enemies = get_enemies(G, player)
    source_powers = powers_present(G, source)
    if 'disputed' in source and len(enemies.intersection(
            source_powers)):  # there were enemies in source
        disengaging = True

        if not conflict_present(G, source):
            make_undisputed(G, source)
            G.logger.write('{} is no longer disputed'.format(source._id))
        elif player not in source_powers and player in source.aggressors:  # player no longer present
            source.aggressors.remove(player)
            G.objects.updated[source._id] = source

            G.logger.write('{} has left {}'.format(player, source._id))

        if 'owner' in source and source.owner not in source_powers:  # owner no longer present
            new_owner = source.aggressors[0]
            switch_ownership(G, source, new_owner)

    dest_powers = powers_present(G, dest)

    if len(enemies.intersection(
            dest_powers)):  # enemy in destination -> engaging
        engaging = True
        if 'disputed' not in dest:
            new_battle = True
            make_disputed(G, dest, player)
        elif player not in dest.aggressors:
            dest.aggressors.append(player)

    elif 'owner' in dest and dest.owner != player:  # unoccupied enemy territory
        switch_ownership(G, dest, player)

    # TODO: interventions

    #track battle groups
    if isANS(G, unit) and engaging:
        #TODO: only if dest is a Sea tile!?
        sourceName = source._id
        destName = dest._id
        if not destName in G.temp.battle_groups:
            G.temp.battle_groups[destName] = tdict()
        G.temp.battle_groups[destName][unit._id] = sourceName

    # TODO: Sea Invasions -> unit can't fight in current battle
    #

    # TODO: Check for realizations of threats (violations)

    # Axis entering Canada -> USA becomes West satellite
    if player == 'Axis' and dest._id == 'Ottawa' and 'USA' not in G.player.West.members:
        USA_becomes_satellite(G, 'West')

    return new_battle, engaging, disengaging
Пример #9
0
def convert_from_saveable(data):
	if data is None:
		return None
	if isinstance(data, (str, int, float)):
		try:
			return int(data)
		except:
			pass
		return data
	if isinstance(data, dict):
		
		if len(data) == 1:
			key, val = next(iter(data.items()))
			if 'set' == key:
				return tset(convert_from_saveable(el) for el in val)
			if 'xset' == key:
				return xset(convert_from_saveable(el) for el in val)
			if 'tuple' == key:
				return tuple(convert_from_saveable(el) for el in val)
			if '_object_' == key[:8]:
				typ = eval(key[8:])
				obj = typ()
				obj.load_state(val)
				return obj
		
		if '_id' in data:
			return idict({convert_from_saveable(k): convert_from_saveable(v) for k, v in data.items()})
		
		return tdict({convert_from_saveable(k): convert_from_saveable(v) for k, v in data.items()})
	if isinstance(data, list):
		return tlist(convert_from_saveable(el) for el in data)
	try:
		return data.save_state()
	except AttributeError:
		raise Exception('Cannot save data of type: {}'.format(type(data)))
Пример #10
0
def prepare_combat_structs(G, player):
	G.temp.combat = adict()
	c = G.temp.combat
	c.stages = []

	#calc optional battles for player
	battles_to_select = tset()
	for tilename in G.temp.potential_battles:
		if tilename in G.temp.battles:
			continue
		is_relevant = player in powers_present(G, G.tiles[tilename])
		if is_relevant:
			battles_to_select.add(tilename)
	c.battles_to_select = battles_to_select

	#calc battles that have to be fought and therefore are revealed
	battles_to_reveal = tdict()
	for tilename in G.temp.battles:
		if G.temp.battles[tilename] == player:
			battles_to_reveal[tilename] = player
		else:
			#print('RIESEN ERROR: new battle with another player!!!!',G.temp.battles[b])
			pass
	c.battles_to_reveal = battles_to_reveal

	#add all bettles_to_reveal to c.battles
	c.battles = adict()
	c.battles_remaining = []
	add_battles_to_reveal(G, player)
	assert len(c.battles_to_reveal.keys()) == 0, 'prepare_combat_structs: AFTER REVEALING STILL BATTLES_TO_REVEAL!'
Пример #11
0
def government_pre_phase(G): # prep influence
	
	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)
Пример #12
0
def play_intel(G, player, card, target, *args):

    G.temp.hack = tdict()
    G.temp.hack.target = target
    G.temp.hack.card = card
    G.temp.hack.source = player
    G.temp.hack.args = args

    return encode_intel_response(G, card, player, target)
Пример #13
0
def load_card_decks(G,
                    action_path='config/cards/action_cards.yml',
                    investment_path='config/cards/investment_cards.yml',
                    info_path='config/cards/card_info.yml'):

    cinfo = load(info_path)
    caction = load(action_path)
    cinvest = load(investment_path)

    action_cards = tdict()
    action_cards.deck = tlist()

    for ID, card in caction.items():
        card = idict(card)
        card.obj_type = 'action_card'
        card.visible = tset()
        card.__dict__['_id'] = 'action_{}'.format(ID)
        action_cards.deck.append(card._id)
        G.objects.table[card._id] = card

    investment_cards = tdict()
    investment_cards.deck = tlist()

    for ID, card in cinvest.items():
        card = idict(card)
        card.obj_type = 'investment_card'
        card.visible = tset()
        card.__dict__['_id'] = 'invest_{}'.format(ID)
        investment_cards.deck.append(card._id)
        G.objects.table[card._id] = card

    G.cards = tdict()

    G.cards.action = action_cards
    G.cards.action.discard_pile = tlist()

    G.cards.investment = investment_cards
    G.cards.investment.discard_pile = tlist()

    G.cards.info = cinfo

    shuffle(G.random, G.cards.investment)
    shuffle(G.random, G.cards.action)
Пример #14
0
def step(player, action):

    phase = PHASES[G.game.sequence[G.game.index]]

    G.objects.created = tdict()
    G.objects.updated = tdict()
    G.objects.removed = tdict()

    G.begin()

    global PHASE_DONE

    try:

        if PHASE_DONE:
            PHASE_DONE = False
            all_actions = next_phase()
        else:
            # validate action
            assert player in WAITING_ACTIONS, 'It is not {}\'s turn'.format(
                player)
            options = util.decode_actions(WAITING_ACTIONS[player])
            assert action in options, 'Invalid action: {}'.format(action)

            try:
                all_actions = phase(G, player, action)
            except PhaseComplete:
                if DEBUG:
                    PHASE_DONE = True
                    all_actions = adict()
                else:
                    all_actions = next_phase()

    except Exception as e:
        G.abort()

        return process_actions('error', sys.exc_info(), player)

    else:
        G.commit()

        return process_actions('actions', all_actions, player)
Пример #15
0
def step(player, action):
	G.objects.created = tdict()
	G.objects.updated = tdict()
	G.objects.removed = tdict()
	
	G.begin()
	
	global PHASE_DONE
	
	try:
		
		#print('step',player,action,'PHASE_DONE=',PHASE_DONE)
		if PHASE_DONE:
			PHASE_DONE = False
			all_actions = evaluate_action()
		else:
			# validate action
			assert player in WAITING_ACTIONS, 'It is not {}\'s turn'.format(player)
			options = util.decode_actions(WAITING_ACTIONS[player])
			assert action in options, 'Invalid action: {}'.format(action)
			
			all_actions = evaluate_action(player, action)
			
	except GameEnds:
		print('GAME ENDS')
		pass

	
	except Exception as e:
		#print(e)
		G.abort()
		
		if DEBUG:
			raise e
		
		return process_actions('error', sys.exc_info(), player)
		
	else:
		G.commit()
		
		return process_actions('actions', all_actions, player)
Пример #16
0
def start_new_game(player='Axis', debug=False):
    global G, DEBUG

    DEBUG = debug

    G = setup.init_gamestate()

    G.logger = Logger(*G.players.keys(), stdout=True)

    G.objects.created = G.objects.table.copy()
    G.objects.updated = tdict()
    G.objects.removed = tdict()

    for name in G.players:
        WAITING_OBJS[name] = adict()
        WAITING_OBJS[name].created = adict()
        WAITING_OBJS[name].updated = adict()
        WAITING_OBJS[name].removed = adict()

    # start setup phase - no need for a transaction, since there is no user input yet, so the outcome is constant
    return process_actions('actions', next_phase(), player)
Пример #17
0
def pre_command_phase(G):

    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})

    G.temp.battles = tdict()

    return encode_command_card_phase(G)
Пример #18
0
def init_gamestate():

    G = tdict()

    load_game_info(G)

    load_map(G)

    load_players_and_minors(G)
    load_card_decks(G)

    load_unit_rules(G)

    return G
Пример #19
0
def setup_pre_phase(G, player_setup_path='config/faction_setup.yml'):

    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)
Пример #20
0
def start_new_game(player='Axis', debug=False, seed=None):
	global G, DEBUG
	
	DEBUG = debug

	G = setup.init_gamestate(seed=seed)
	
	G.logger = Logger(*G.players.keys(), stdout=True)
	
	if G.game.seed is not None:
		G.logger.write('Set seed {}'.format(G.game.seed))
	
	G.objects.created = G.objects.table.copy()
	G.objects.updated = tdict()
	G.objects.removed = tdict()
	
	for name in G.players:
		WAITING_OBJS[name] = adict()
		WAITING_OBJS[name].created = adict()
		WAITING_OBJS[name].updated = adict()
		WAITING_OBJS[name].removed = adict()
	
	# start setup phase - no need for a transaction, since there is no user input yet, so the outcome is constant
	return process_actions('actions', evaluate_action(), player)
Пример #21
0
def setup_phase(G, action):  # player, tilename, unit_type
    # place user chosen units

    # out: send message to all players to choose what tiles to place how many cadres on

    try:
        msg = io.get()

        assert msg.player in incomplete, 'Player {} is already done'.format(
            msg.player)

        reqs = player_setup[msg.player].setup.cadres

        placed = False

        for member, tiles in reqs.items():
            if msg.tile in tiles:
                placed = True
                assert tiles[
                    msg.
                    tile] > 0, 'No more cadres can be placed onto {}'.format(
                        msg.tile)

                unit = tdict()
                unit.type = msg.type
                unit.tile = msg.tile
                unit.nationality = member
                unit.cv = 1

                add_unit(G, unit)

                tiles[msg.tile] -= 1
                if tiles[msg.tile] == 0:
                    del tiles[msg.tile]

        assert placed, 'Tile {} not available for placement'.format(msg.tile)

    except (ActionError, AssertionError) as e:
        io.put({'error': 'Invalid Action', 'msg': str(e)})

    # draw action cards
    for name, config in player_setup.items():
        if 'action_cards' in config.setup:
            G.players[name].hand.extend(
                draw_cards(G.action_cards, config.setup.action_cards))
        if 'investment_cards' in config.setup:
            G.players[name].hand.extend(
                draw_cards(G.investment_cards, config.setup.investment_cards))
Пример #22
0
def init_gamestate(seed=None):

    if seed is None:
        seed = random.getrandbits(64)

    G = tdict()

    load_game_info(G, seed=seed)

    load_map(G)

    load_players_and_minors(G)
    load_card_decks(G)

    load_unit_rules(G)

    return G
Пример #23
0
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
Пример #24
0
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)
Пример #25
0
def load_players_and_minors(G):
    player_setup = load('config/faction_setup.yml')

    capitals = load('config/capitals.yml')

    G.nations = tdict()
    territories = tdict()
    designations = tdict()
    minor_designation = 'Minor'

    for tile in G.tiles.values():
        if 'alligence' in tile:
            designations[tile.alligence] = minor_designation
            if tile.alligence not in territories:
                territories[tile.alligence] = tset()
            territories[tile.alligence].add(tile._id)
    designations['USA'] = 'Major'
    G.nations.designations = designations
    G.nations.territories = territories
    G.nations.capitals = capitals

    for nation, tilename in capitals.items():
        G.tiles[tilename].capital = True

    G.nations.groups = tdict()

    # load factions/players
    players = tdict()

    groups = tset(player_setup.keys())
    rivals = tdict()
    for g in groups:
        gps = groups.copy()
        gps.remove(g)
        rivals[g] = tset(gps)

    for name, config in player_setup.items():

        faction = tdict()

        faction.stats = tdict()
        faction.stats.handlimit = config.Handlimit
        faction.stats.factory_all_costs = config.FactoryCost
        faction.stats.factory_idx = 0
        faction.stats.factory_cost = faction.stats.factory_all_costs[
            faction.stats.factory_idx]
        faction.stats.emergency_command = config.EmergencyCommand

        faction.stats.rivals = rivals[name]

        faction.stats.DoW = tdict({r: False for r in rivals[name]})

        faction.stats.at_war_with = tdict({r: False for r in rivals[name]})
        faction.stats.at_war = False

        faction.stats.aggressed = False
        faction.stats.peace_dividends = tlist()

        faction.stats.enable_USA = 'enable_USA' in config
        faction.stats.enable_Winter = 'enable_Winter' in config

        faction.cities = tdict()
        faction.cities.MainCapital = config.MainCapital
        faction.cities.SubCapitals = config.SubCapitals

        faction.members = tdict()
        for nation, info in config.members.items():
            faction.members[nation] = tset([nation])
            if info.type == 'Great_Power':
                faction.stats.great_power = nation
            if 'Colonies' in info:
                faction.members[nation].update(info.Colonies)

        full_cast = tset()
        for members in faction.members.values():
            full_cast.update(members)
        for member in full_cast:
            G.nations.designations[member] = name

        faction.homeland = tdict(
            {member: tset()
             for member in faction.members.keys()})
        faction.territory = tset()

        for tile_name, tile in G.tiles.items():
            if 'alligence' not in tile:
                continue
            if tile.alligence in faction.members:  # homeland
                faction.homeland[tile.alligence].add(tile_name)
            if tile.alligence in full_cast:
                faction.territory.add(tile_name)
                tile.owner = name

        faction.tracks = tdict()
        pop, res = compute_tracks(faction.territory, G.tiles)
        faction.tracks.POP = pop
        faction.tracks.RES = res
        faction.tracks.IND = config.initial_ind

        faction.units = tdict()
        faction.hand = tset()  # for cards
        faction.technologies = tset()
        faction.secret_vault = tset()
        faction.influence = tset()

        faction.diplomacy = tdict()
        faction.diplomacy.associates = tset()
        faction.diplomacy.protectorates = tset()
        faction.diplomacy.satellites = tset()
        faction.diplomacy.violations = tset()

        players[name] = faction
    G.players = players

    # load minors/diplomacy
    minors = tdict()
    majors = tdict()
    status = tdict()
    for name, team in G.nations.designations.items():
        if team not in G.nations.groups:
            G.nations.groups[team] = tset()
        G.nations.groups[team].add(name)

        if team in {minor_designation, 'Major'}:
            status[name] = tdict()

            status[name].is_armed = False
            status[name].units = tdict()

        if team == minor_designation:  # only minors
            minor = tdict()

            minor.faction = None
            minor.value = 0

            minors[name] = minor

        if team == 'Major':  # only includes neutral majors
            major = tdict()

            major.faction = None
            major.value = 0

            majors[name] = major

    G.diplomacy = tdict()
    G.diplomacy.minors = minors
    G.diplomacy.majors = majors
    G.diplomacy.neutrals = minors.copy()
    G.diplomacy.neutrals.update(majors)
    G.diplomacy.influence = tdict()
    G.nations.status = status
Пример #26
0
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)
Пример #27
0
def load_players_and_minors(G):
    player_setup = load('config/faction_setup.yml')

    nations = tdict()
    minor_designation = 'Minor'

    for tile in G.tiles.values():
        if 'alligence' in tile:
            nations[tile.alligence] = minor_designation
    G.nations = nations  # map nationality to faction/minor

    # load factions/players
    players = tdict()

    groups = tset(player_setup.keys())
    rivals = tdict()
    for g in groups:
        gps = groups.copy()
        gps.remove(g)
        rivals[g] = list(gps)

    for name, config in player_setup.items():

        faction = tdict()

        faction.stats = tdict()
        faction.stats.handlimit = config.Handlimit
        faction.stats.factory_all_costs = config.FactoryCost
        faction.stats.factory_idx = 0
        faction.stats.factory_cost = faction.stats.factory_all_costs[
            faction.stats.factory_idx]
        faction.stats.emergency_command = config.EmergencyCommand
        faction.stats.DoW = tdict()
        faction.stats.DoW[rivals[name][0]] = False
        faction.stats.DoW[rivals[name][1]] = False
        faction.stats.enable_USA = 'enable_USA' in config
        faction.stats.enable_Winter = 'enable_Winter' in config

        faction.cities = tdict()
        faction.cities.MainCapital = config.MainCapital
        faction.cities.SubCapitals = config.SubCapitals

        faction.members = tdict()
        for nation, info in config.members.items():
            nations[nation] = name
            faction.members[nation] = tset([nation])
            if 'Colonies' in info:
                faction.members[nation].update(info.Colonies)

        faction.homeland = tset()
        faction.territory = tset()

        full_cast = tset()
        for members in faction.members.values():
            full_cast.update(members)

        for tile_name, tile in G.tiles.items():
            if 'alligence' not in tile:
                continue
            if tile.alligence in faction.members:  # homeland
                faction.homeland.add(tile_name)
            if tile.alligence in full_cast:
                faction.territory.add(tile_name)

        faction.tracks = tdict()
        pop, res = compute_tracks(faction.territory, G.tiles)
        faction.tracks.pop = pop
        faction.tracks.res = res
        faction.tracks.ind = config.initial_ind

        faction.units = tdict()
        faction.hand = tset()  # for cards
        faction.influence = tdict()

        players[name] = faction
    G.players = players

    # load minors/diplomacy
    minors = tdict()
    for name, team in nations.items():
        if team == minor_designation:
            minor = tdict()

            minor.units = tset()
            minor.is_armed = False
            minor.influence_faction = None
            minor.influence_value = 0

            minors[name] = minor
    G.minors = minors
Пример #28
0
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
Пример #29
0
def switch_ownership(G, tile, owner):

    G.objects.updated[tile._id] = tile

    if 'disputed' in tile:

        if owner in tile.aggressors:
            tile.aggressors.remove(owner)

        if len(tile.aggressors) == 0:
            make_undisputed(G, tile)

    pop = tile['pop']
    res = tile['res']
    msg = ''

    if 'owner' in tile and tile.owner in G.players:
        G.players[tile.owner].territory.remove(tile._id)

        G.players[tile.owner].tracks.POP -= pop
        G.players[tile.owner].tracks.RES -= res

    if pop > 0 or res > 0:
        msg = ' (gaining POP={} RES={})'.format(pop, res)

    G.logger.write('{} has taken control of {}{}'.format(owner, tile._id, msg))

    if 'blockaded' in tile:
        del tile.blockaded

    if 'unsupplied' in tile:
        del tile.unsupplied

    G.players[owner].territory.add(tile._id)
    G.players[owner].tracks.POP += pop
    G.players[owner].tracks.RES += res

    if 'capital' in tile:
        owner_info = G.players[owner]
        nation = tile.alligence

        # take control of all unoccupied tiles in nation
        for tilename in G.nations.territories[nation]:
            other = G.tiles[tilename]
            if other._id != tile._id and len(other.units) == 0:
                switch_ownership(G, other, owner)

        if nation in G.nations.status:  # minor switches side

            if tile.owner in G.players:
                G.players[tile.owner].satellites.remove(nation)
            owner_info.diplomacy.satellites.add(nation)

            G.nations.groups[G.nations.designations[nation]].remove(nation)
            G.nations.designations[nation] = owner
            G.nations.groups[owner].add(nation)
        else:  # something bigger -> major/great power
            flag = False
            for rival in G.players:
                faction = G.players[rival]
                if nation in faction.members:
                    flag = True
                    if nation == faction.stats.great_power:
                        # MainCapital

                        if rival == owner:
                            del faction.stats.fallen
                            G.logger.write('{} has been liberated!'.format(
                                tile._id))

                        else:
                            G.logger.write(
                                '{} has fallen! ({} production is zero)'.
                                format(tile._id, tile.owner))
                            faction.stats.fallen = owner

                            # TODO: maybe add conquered great power to satellites???
                            # rule 2.21 defeat of Major Power's Capital: permanently remove
                            # all national units from play
                            for tilename in G.nations.territories[nation]:
                                other = G.tiles[tilename]
                                u_remove = []
                                for uid in other.units:
                                    if uid in G.players[rival].units:
                                        u_remove.append(uid)
                                for uid in u_remove:
                                    remove_from_play(G, uid)

                    else:
                        # SubCapital from MajorPower

                        # TODO: liberating Great Powers or satellites adds them back properly (not just satellite)

                        assert rival != owner, 'regaining great powers is not supported currently'

                        G.logger.write('{} has fallen.'.format(nation))

                        # wipe out all major power units (nation)
                        for uid, unit in faction.units.items():
                            if unit.nationality == nation:
                                remove_unit(G, unit)

                        # turn all colonies into armed minors
                        for colony in faction.members[nation]:
                            if colony != nation:
                                G.nations.status[colony] = tdict()
                                G.nations.status[colony].units = tdict()

                                convert_to_armed_minor(G, colony)

                        # add major power as satellite
                        del faction.homeland[nation]
                        G.nations.groups[rival].remove(nation)
                        G.nations.designations[nation] = owner
                        G.nations.groups[owner].add(nation)
                else:
                    for member in faction.members:
                        states = faction.members[member]
                        if nation in states:  # colony
                            flag = True
                            # colony becomes a satellite

                            states.remove(nation)
                            G.logger.write('{} captures {}'.format(
                                owner, nation))

                            owner_info.diplomacy.satellites.add(nation)
                            G.nations.groups[
                                G.nations.designations[nation]].remove(nation)
                            G.nations.designations[nation] = owner
                            G.nations.groups[owner].add(nation)

                            break
            assert flag, 'No nation was captured: {}'.format(nation, tile._id)

    tile.owner = owner
    if check_victory_by_military(G, owner):
        set_game_won(G, owner, 'military')
        raise GameEnds
Пример #30
0
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