Ejemplo n.º 1
0
 def load_smuggler(self, s: str):
     actions = phase_subtokens(s)
     for idx, action in enumerate(actions):
         if not action:
             assert idx == len(actions) - 1
             break
         subtokens = action_subtokens(action)
         if action.upper().startswith('CARD'):
             card = self.determine_card(action, self.gs)
             yield load_all_phase_card_action(card, subtokens[1:])
             continue
         # Just 'Y' could match if we don't require the length of name_subtokens to be 2, which would be an issue
         name_subtokens = tokens(subtokens[0])
         if tokens_match(name_subtokens,
                         ['YELLOW', 'TILE']) and len(name_subtokens) == 2:
             assert len(
                 subtokens) == 2, 'Location required with yellow tile'
             yield YellowTileAction(
                 self.location_transformer.apply(Location(int(
                     subtokens[1]))))
             continue
         gain, cost, roll = subtokens
         yield EncounterSmuggler(load_good(gain),
                                 Pay() if cost == '-2' else load_good(cost),
                                 load_roll(roll))
Ejemplo n.º 2
0
 def load_choose_reward(self, s: str) -> typing.Iterator[PlayerAction]:
     actions = phase_subtokens(s)
     for idx, action in enumerate(actions):
         if not action:
             assert idx == len(actions) - 1
             break
         subtokens = action_subtokens(action)
         if action.upper().startswith('CARD'):
             card = self.determine_card(action, self.gs)
             yield load_all_phase_card_action(card, subtokens[1:])
             continue
         # Just 'Y' could match if we don't require the length of name_subtokens to be 2, which would be an issue
         name_subtokens = tokens(subtokens[0])
         if tokens_match(name_subtokens,
                         ['YELLOW', 'TILE']) and len(name_subtokens) == 2:
             assert len(
                 subtokens) == 2, 'Location required with yellow tile'
             yield YellowTileAction(
                 self.location_transformer.apply(Location(int(
                     subtokens[1]))))
             continue
         for subtoken in subtokens:
             if subtoken in {'3', '6', '9', '12'}:
                 for _ in range(int(subtoken) // 3):
                     yield ChooseReward(ChooseReward.LIRA)
                 continue
             card = load_exact_card(subtoken)
             yield ChooseReward(card)
Ejemplo n.º 3
0
def load_possible_red_tile_action(s: str) -> typing.Union[Roll, RedTileAction]:
    subtokens = action_subtokens(s)
    if len(subtokens) == 1:
        return load_roll(subtokens[0])

    first = subtokens[0]
    assert tokens_match(tokens(first), ['RED', 'TILE']), '{} is not RedTile'.format(first)
    assert len(subtokens) == 4, 'RedTile requires 3 inputs, got'.format(len(subtokens) - 1)
    initial_roll = load_roll(subtokens[1])
    final_roll = load_roll(subtokens[3])
    method = {'F': RedTileAction.TO_FOUR, 'R': RedTileAction.REROLL, '4': RedTileAction.TO_FOUR}[subtokens[2]]
    return RedTileAction(initial_roll, final_roll, method)
Ejemplo n.º 4
0
def load_warehouse_action(s: str) -> typing.Union[GenericTileAction, GreenTileAction]:
    if not s:
        return GenericTileAction()
    gt, good = action_subtokens(s)
    assert tokens_match(tokens(gt), ['GREEN', 'TILE']), '{} is not GreenTile'.format(gt)
    return GreenTileAction(load_good(good))
Ejemplo n.º 5
0
    def load_phase_3(
            self,
            s: str,
            tile: typing.Optional[Tile] = None
    ) -> typing.Iterator[PlayerAction]:
        actions = phase_subtokens(s)
        player_state = self.gs.player_states[self.gs.turn_state.current_player]
        tile = self.gs.location_map[
            player_state.location] if tile is None else tile
        tile_state = typing.cast(MarketTileState, self.gs.tile_states[tile])
        for idx, action in enumerate(actions):
            if action == '!':
                yield SkipTileAction()
                return
            if action == '':
                assert tile in self.GENERIC_ACTION_TILES, f'{tile} is not generic'
                yield GenericTileAction()
                continue
            subtokens = action_subtokens(action)
            if action.upper().startswith('CARD'):
                card = self.determine_card(action, self.gs, tile)
                if card in {Card.DOUBLE_PO, Card.DOUBLE_DEALER}:
                    assert len(subtokens) == 1
                    yield DoubleCardAction(
                        card, (GenericTileAction(), GenericTileAction()))
                    continue
                if card is Card.DOUBLE_SULTAN:
                    _, first_cost, second_cost = subtokens
                    yield DoubleCardAction(
                        card,
                        (SultansPalaceAction(load_good_counter(first_cost)),
                         SultansPalaceAction(load_good_counter(second_cost))))
                    continue
                if card is Card.SELL_ANY:
                    assert len(
                        subtokens
                    ) == 3, 'Incorrect number of arguments for sell any goods card'
                    assert tile is Tile.SMALL_MARKET, 'Can only use sell any goods card at small marker'
                    if not 'ALL'.startswith(subtokens[1].upper()):
                        yield SellAnyCardAction(
                            load_market_action(' '.join(subtokens[1:]),
                                               player_state, tile_state))
                        continue
                    assert 0 < sum(player_state.cart_contents.values()) <= 5, \
                        f'All is ambiguous with {sum(player_state.cart_contents.values())} goods'
                    yield SellAnyCardAction(
                        MarketAction(player_state.cart_contents.copy(),
                                     load_good_counter(subtokens[2])))
                    continue
                yield load_all_phase_card_action(card, subtokens[1:])
                continue
            # Just 'Y' could match if we don't require the length of name_subtokens to be 2, which would be an issue
            name_subtokens = tokens(subtokens[0])
            if tokens_match(name_subtokens,
                            ['YELLOW', 'TILE']) and len(name_subtokens) == 2:
                assert len(
                    subtokens) == 2, 'Location required with yellow tile'
                yield YellowTileAction(
                    self.location_transformer.apply(Location(int(
                        subtokens[1]))))
                continue

            if tile is Tile.POLICE_STATION:
                location = Location(int(subtokens[0]))
                dest_tile = self.gs.location_map[
                    self.location_transformer.apply(location)]
                args = ' '.join(subtokens[1:])
                dest_actions = list(self.load_phase_3(args, tile=dest_tile))
                assert len(dest_actions) == 1
                # This is manually type checked in the constructor
                dest_action = typing.cast(
                    typing.Union[PlaceTileAction, GreenTileAction,
                                 DoubleCardAction, SellAnyCardAction],
                    dest_actions[0])
                yield PoliceStationAction(location, dest_action)
                continue

            if tile is Tile.FOUNTAIN:
                if len(subtokens) == 1 and subtokens[0].upper() == 'ALL':
                    yield GenericTileAction()
                    continue
                locations = map(
                    self.location_transformer.apply,
                    typing.cast(typing.Iterator[Location], map(int,
                                                               subtokens)))
                yield FountainAction(locations)
                continue

            if tile in {Tile.SMALL_MARKET, Tile.LARGE_MARKET}:
                yield load_market_action(action, player_state, tile_state)
                continue

            lookup_table = {
                Tile.GREAT_MOSQUE:
                load_mosque_action,
                # Post office is always generic or card
                Tile.FABRIC_WAREHOUSE:
                load_warehouse_action,
                Tile.SMALL_MOSQUE:
                load_mosque_action,
                Tile.FRUIT_WAREHOUSE:
                load_warehouse_action,
                # Police station is special, above
                # Fountain is special, above
                Tile.SPICE_WAREHOUSE:
                load_warehouse_action,
                Tile.BLACK_MARKET:
                load_black_market_action,
                Tile.CARAVANSARY:
                load_caravansary_action,
                # Small market is special, above
                Tile.TEA_HOUSE:
                load_tea_house_action,
                Tile.SULTANS_PALACE:
                load_sultans_palace_action,
                # Large market is special, above
                # Wainwright is always generic
                # Gemstone dealer is always generic
            }
            yield lookup_table[tile](action)
Ejemplo n.º 6
0
    def load_phases_12(self, s: str) -> typing.Iterator[PlayerAction]:
        dont_pay = False
        if s.endswith('!$'):
            dont_pay = True
            s = s[:-2].strip()
        actions = phase_subtokens(s)
        player_state = self.gs.player_states[self.gs.turn_state.current_player]
        for idx, action in enumerate(actions):
            skip_assistant = False
            if action.endswith('!'):
                skip_assistant = True
                action = action[:-1]
            action = action.rstrip()

            if action.isdigit():
                yield Move(self.location_transformer.apply(
                    Location(int(action))),
                           skip_assistant=skip_assistant)
                if skip_assistant:
                    assert idx == len(
                        actions) - 1, 'Assistant skip was not last action'
                    yield YieldTurn()
                    return
                continue

            subtokens = action_subtokens(action)
            assert subtokens, 'Empty action not allowed in phase 1'
            if action.upper().startswith('CARD'):
                card = self.determine_card(action, self.gs)

                if card is Card.NO_MOVE:
                    assert len(subtokens) == 1
                    yield NoMoveCardAction(skip_assistant)
                    if skip_assistant:
                        assert idx == len(
                            actions) - 1, 'Assistant skip was not last action'
                        yield YieldTurn()
                        return
                    continue

                if card is Card.EXTRA_MOVE:
                    assert len(subtokens
                               ) == 2, 'Location required with extra move card'
                    yield ExtraMoveCardAction(
                        Move(self.location_transformer.apply(
                            Location(int(subtokens[1]))),
                             skip_assistant=skip_assistant))
                    if skip_assistant:
                        assert idx == len(
                            actions) - 1, 'Assistant skip was not last action'
                        yield YieldTurn()
                        return
                    continue

                if card is Card.RETURN_ASSISTANT:
                    assert len(
                        subtokens
                    ) == 2, 'Location required with return assistant card'
                    yield ReturnAssistantCardAction(
                        self.location_transformer.apply(
                            Location(int(subtokens[1]))))
                    continue

                yield load_all_phase_card_action(card, subtokens[1:])
                continue

            assert tokens_match(tokens(subtokens[0]),
                                ['YELLOW', 'TILE']), f'Unknown action {action}'
            assert len(subtokens) == 2, 'Location required with yellow tile'
            yield YellowTileAction(
                self.location_transformer.apply(Location(int(subtokens[1]))))
            continue

        # After applying all the explicit actions
        tile_state = self.gs.tile_states[self.gs.location_map[
            player_state.location]]
        if len(tile_state.players) > 1 and self.gs.location_map[
                player_state.location] is not Tile.FOUNTAIN:
            if dont_pay:
                yield YieldTurn()
            else:
                yield Pay()
        else:
            assert not dont_pay, 'Payment not required'