Пример #1
0
    def pass_gamestate(self):
        Round = self.round
        Tokens_Inventories = np.concatenate(
            (expand_inventory(self.inventory,
                              self.players)[self.active_player:, :],
             expand_inventory(
                 self.inventory,
                 self.players)[:self.active_player, :])).flatten()
        Air_Supply = self.air_supply
        Token_Positions = expand_vector(categorize_tokens(self.tokens))
        Player_Positions = np.concatenate(
            (self.positions[self.active_player:, :],
             self.positions[:self.active_player, :])).flatten()
        Intermediate_Scores = np.concatenate(
            (self.player_scores[self.active_player:],
             self.player_scores[:self.active_player])).flatten()

        return np.hstack(
            (Round, Tokens_Inventories, Air_Supply, Token_Positions,
             Player_Positions, Intermediate_Scores))
Пример #2
0
    def next_round(self):
        # reset air supply to 25
        self.air_supply = 25

        # remove blanks from token row
        self.tokens = np.delete(self.tokens, np.where(self.tokens == -1)[0])

        # clean up tokens collected in the previous round
        for i in range(self.players):
            # score any tokens that players got back to the sub with
            if self.positions[i, 0] == -1:
                self.player_scores[i] += list(map(sum, self.inventory))[i]

            # drop any tokens that did not make it back
            else:
                # set up a counter to track how many tokens have been added to the current stack
                stacked = 0

                # loop through players
                for j in range(self.players):
                    # request drops until the player's inventory is empty
                    while len(self.inventory[j]) > 0:
                        # request which token to drop
                        selected_token = death_drop(
                            categorize_tokens(self.inventory[j]))

                        # translate the mask back to an indx
                        selected_token = np.where(selected_token == 1)[0][0]

                        # add the selected tokens to the token row
                        # if this is the first token in a stack
                        if stacked == 0:
                            # add it to the end of the row
                            self.tokens = np.append(
                                self.tokens, self.inventory[j][selected_token])

                        # if the stack is not full, add to it
                        else:
                            self.tokens[-1] += self.inventory[j][
                                selected_token]

                        # remove the tokens from the player's inventory
                        self.inventory[j] = np.delete(self.inventory[j],
                                                      selected_token)

                        # update the stack counter
                        stacked += 1

                        # if the stack is full, reset the counter to 0
                        if stacked == 3:
                            stacked = 0

        # fully clear player inventories
        self.inventory = [np.array([]) for i in range(self.players)]

        # set the active player to the deepest player
        self.active_player = np.argmax(self.positions[:, 0])

        # put each player on the sub (position -1) with downward heading (+1)
        self.positions = np.tile([-1, 1], (self.players, 1))

        # update the round counter
        self.round += 1
Пример #3
0
def simulate_game(players, model_turn_around, model_pick_up, model_drop_token,
                  noise):

    # declare lists to store individual components of the game state
    TurnID = []  # int, indexing identifier
    Active_Player = []  # int, indexing identifier
    Round = []  # int
    Tokens_Inventories = [
    ]  # array with dim [players, 32], row 0 is inventory of active player
    Air_Supply = []  # int
    Token_Positions = []  # vector
    Player_Positions = [
    ]  # array with dim [players, 2], row 0 is active player
    Intermediate_Scores = []  # vector, index 0 is active player

    # additional lists to document the decisions made by the player on a given turn
    Turn_Around = [0]  # bool, happens prior to board update
    Pick_Up = [0]  # bool, happens after board update
    Drop = [[0 for i in range(32)]]  # vector, happens after board update

    # initiate a new game state
    game = GameState(players)

    # start turn counter, document initial game state
    turn = 0
    TurnID.append(turn)
    Active_Player.append(game.active_player)
    Round.append(game.round)
    Tokens_Inventories.append(
        np.concatenate((expand_inventory(game.inventory,
                                         game.players)[game.active_player:, :],
                        expand_inventory(
                            game.inventory,
                            game.players)[:game.active_player, :])).flatten())
    Air_Supply.append(game.air_supply)
    Token_Positions.append(expand_vector(categorize_tokens(game.tokens)))
    Player_Positions.append(
        np.concatenate((game.positions[game.active_player:, :],
                        game.positions[:game.active_player, :])).flatten())
    Intermediate_Scores.append(
        np.concatenate((game.player_scores[game.active_player:],
                        game.player_scores[:game.active_player])).flatten())

    # declare a flag for game end
    continue_game = True

    # take turns until the game is over
    while continue_game:
        # take a turn, collect the player actions taken
        continue_game, turn_taken, turn_around, pick_up, drop = take_turn(
            game, model_turn_around, model_pick_up, model_drop_token, noise)

        # skip to next turn if active player is already back at the sub
        if turn_taken == False:
            continue

        # document the game state
        turn += 1
        TurnID.append(turn)
        Active_Player.append(game.active_player)
        Round.append(game.round)
        Tokens_Inventories.append(
            np.concatenate(
                (expand_inventory(game.inventory,
                                  game.players)[game.active_player:, :],
                 expand_inventory(
                     game.inventory,
                     game.players)[:game.active_player, :])).flatten())
        Air_Supply.append(game.air_supply)
        Token_Positions.append(expand_vector(categorize_tokens(game.tokens)))
        Player_Positions.append(
            np.concatenate((game.positions[game.active_player:, :],
                            game.positions[:game.active_player, :])).flatten())
        Intermediate_Scores.append(
            np.concatenate(
                (game.player_scores[game.active_player:],
                 game.player_scores[:game.active_player])).flatten())

        # document the player decisions
        Turn_Around.append(int(turn_around))
        Pick_Up.append(int(pick_up))
        Drop.append(expand_vector(drop))

    # wrap the board states into a dataframe
    Game_Log = pd.DataFrame({
        "TurnID": TurnID,
        "Active_Player": Active_Player,
        "Round": Round,
        "Tokens_Inventories": Tokens_Inventories,
        "Air_Supply": Air_Supply,
        "Token_Positions": Token_Positions,
        "Player_Positions": Player_Positions,
        "Intermediate_Scores": Intermediate_Scores,
        "Turn_Around": Turn_Around,
        "Pick_Up": Pick_Up,
        "Drop": Drop
    })

    # document the winner
    # ignoring tie breakers, all players lose when tied
    Placement = dict([(i, 0) for i in range(len(game.player_scores))])
    if not np.all(game.player_scores == game.player_scores[0]):
        Placement[np.argmax(game.player_scores)] = 1

    return Game_Log, Placement
Пример #4
0
def take_turn(game, model_turn_around, model_pick_up, model_drop_token, noise):
    # reporter variables
    turn_taken = False
    turn_around = False
    pick_up = False
    drop = np.array([])

    # check that the active player is not already back on the submarine
    if not (game.positions[game.active_player, 0] == -1
            and game.positions[game.active_player, 1] == -1):
        # note that the turn was not taken
        turn_taken = True

        # update the air supply
        game.update_air_supply()

        # determine whether the active player turns around
        if game.positions[game.active_player,
                          1] == 1 and game.positions[game.active_player,
                                                     0] != -1:
            if turn_around_decision(game.pass_gamestate(), model_turn_around,
                                    noise):
                # turn the player back toward the sub if True
                game.positions[game.active_player, 1] = -1
                turn_around = True

        # roll the dice
        roll = die_roll(len(game.inventory[game.active_player]))

        # move the player along the token lineup until they consume their moves or reach the end
        while roll > 0:
            # check to see if the player is on the last available space when moving down
            if game.positions[game.active_player, 1] == 1:
                if game.positions[game.active_player, 0] == max(
                        np.setdiff1d(
                            np.arange(len(game.tokens)),
                            game.positions[np.arange(len(game.positions)) !=
                                           game.active_player][:, 0])):
                    break
            # check to see if the player is at the sub when moving up
            else:
                if game.positions[game.active_player, 0] == -1:
                    break

            # move the player a step in the appropriate direction
            game.positions[game.active_player,
                           0] += game.positions[game.active_player, 1]

            # continue moving without consuming the roll if the token is already occupied
            if game.positions[game.active_player, 0] in game.positions[
                    np.arange(len(game.positions)) != game.active_player][:,
                                                                          0]:
                continue

            # check to see if they have reached the sub
            if game.positions[game.active_player, 0] == -1:
                break

            # consume one movement from the roll
            roll = roll - 1

        # determine whether the active player picks up or drops a token
        # check to see if a token is available
        if game.tokens[game.positions[game.active_player, 0]] > -1:
            if pick_up_decision(game.pass_gamestate(), model_pick_up, noise):
                # pick up the token if True
                game.collect_token()
                pick_up = True
        elif len(game.inventory[game.active_player]) > 0:
            # select tokens to drop
            drop = drop_decision(
                categorize_tokens(game.inventory[game.active_player]),
                game.pass_gamestate(), model_drop_token, noise)

            # drop a token if any indicated
            if sum(drop > 0):
                game.drop_token(drop)

    # update the active player
    if game.active_player < game.players - 1:
        game.active_player += 1
    else:
        game.active_player = 0

    # check to see if oxygen has run out
    if game.air_supply <= 0 or np.all(game.positions[:, 0] == -1):
        # start the next round
        game.next_round(noise)

    # return a boolean indicating whether the game is over alongside descriptions of player's actions
    return (game.round <= 3, turn_taken, turn_around, pick_up, drop)