Add nim stub to main repo

This commit is contained in:
Chris Proctor 2022-05-11 16:46:00 -04:00
parent cc50795d43
commit af79c47691
4 changed files with 116 additions and 0 deletions

34
nim/game_stub.py Normal file
View File

@ -0,0 +1,34 @@
class NimGameStub:
"""A stub is a minimal version of a class which stands in for the
real class, which hasn't yet been written. The stub has all the correct
methods, and their inputs and outputs are the right kind of thing,
but it doesn't really do anything.
"""
def get_initial_state(self):
return {
"board": [1, 3, 5, 7],
"first_player": True
}
def get_next_state(self, state, action):
next_state = {
"board": state["board"].copy(),
"first_player": not state["first_player"],
}
return next_state
def get_actions(self, state):
return [
(0, 0),
(1, 0), (1, 1),
(2, 0), (2, 1), (2, 2), (3, 0), (3, 1), (3, 2), (3, 3),
]
def get_reward(self, state):
return 0
def is_over(self, state):
return False
def get_objective(self, state):
return max if state["first_player"] else min

35
nim/player.py Normal file
View File

@ -0,0 +1,35 @@
from nim.game_stub import NimGameStub
from strategy.lookahead_strategy import LookaheadStrategy
class HumanNimPlayer:
def __init__(self, name):
self.name = name
self.game = NimGameStub()
def choose_action(self, state):
actions = self.game.get_actions(state)
for i, action in enumerate(actions):
row, lines_to_remove = action
print(f"{i}. Remove {lines_to_remove} from row {row}.")
choice = self.get_int(len(actions))
return actions[choice]
def get_int(self, maximum):
while True:
response = input("> ")
if response.isdigit():
value = int(response)
if value < maximum:
return value
print("Invalid input.")
class ComputerNimPlayer:
def __init__(self, name):
self.name = name
self.strategy = LookaheadStrategy(NimGameStub(), max_depth=3, deterministic=False)
def choose_action(self, state):
action = self.strategy.choose_action(state)
row, lines_to_remove = action
print(f"{self.name} removes {lines_to_remove} from row {row}")
return action

32
nim/view.py Normal file
View File

@ -0,0 +1,32 @@
from nim.game_stub import NimGameStub
class NimView:
def __init__(self, player0, player1):
self.players = [player0, player1]
self.game = NimGameStub()
def greet(self):
print(f"{self.players[0].name} and {self.players[1].name}, welcome to Nim.")
def show_board(self, state):
for lines_in_row in state["board"]:
print("| " * lines_in_row)
def get_action(self, state):
self.show_board(state)
player = self.get_current_player(state)
return player.choose_action(state)
def get_current_player(self, state):
if state["first_player"]:
return self.players[0]
else:
return self.players[1]
def conclude(self, state):
self.show_board(state)
if self.game.get_reward(state) > 0:
winner = self.players[0]
else:
winner = self.players[1]
print(f"Congratulations, {winner.name}!")

15
play_nim.py Normal file
View File

@ -0,0 +1,15 @@
from nim.game_stub import NimGameStub
from nim.view import NimView
from nim.player import HumanNimPlayer, ComputerNimPlayer
player0 = HumanNimPlayer(input("What's your name? "))
player1 = ComputerNimPlayer("Robot")
view = NimView(player0, player1)
game = NimGameStub()
view.greet()
state = game.get_initial_state()
while not game.is_over(state):
action = view.get_action(state)
state = game.get_next_state(state, action)
view.conclude(state)