class NimGame: """A Nim game class based off NimGameStub. """ def get_initial_state(self): ''' Constructs the game board and has player 1 start the game. ''' return { "board": [1, 3, 5, 7], "first_player": True } def get_next_state(self, state, action): ''' Creates a copy of the current board and then makes adjustments based on the chosen action from a player's turn. ''' new_board = state["board"].copy() new_board[action[0]] = new_board[action[0]] - action[1] return { "board": new_board, "first_player": not state["first_player"], } def get_actions(self, state): ''' Construct the list of actions that can be taken by a player. Is there a more efficient way of doign this? ''' actions = [] new_board = state["board"].copy() for i in range(4): # check the four rows of the board if new_board[i] > 0: # if a row is not empty for j in range(1,4): # check if you can remove 1, 2, or 3 ticks in the row if j <= new_board[i]: # if so actions.append((i,j)) # include that as an option return actions def get_reward(self, state): ''' Reports who wins. ''' if state["first_player"]: return 1 # If it is the player's turn and there is nothing on the board, then it was the robot who crossed off the last line. return 0 # Otherwise, the first player made the last move and lost. def is_over(self, state): ''' Reports true if there are no more lines to cross. ''' if all(ticks == 0 for ticks in state["board"]): return True return False def get_objective(self, state): ''' Reports the desired obejctive to help choose the move that yields the optimal reward under the lookahead_strategy for computer players. ''' return max if state["first_player"] else min