generated from mwc/lab_tic_tac_toe
Kathryn Odell-Hamilton
4.6.24
Corrected bugs with Nim game.
Had issues trying to update TTTGame:
To find the value of the first state, enter the
Python shell (python) and run the following:
-This was the typed and error message
from ttt.game import TTTGame
zsh: command not found: from
How do I accomplish the last task with TTTGame?
Thank you in advance.
This commit is contained in:
BIN
nim/.DS_Store
vendored
Normal file
BIN
nim/.DS_Store
vendored
Normal file
Binary file not shown.
51
nim/game_rev.py
Normal file
51
nim/game_rev.py
Normal file
@@ -0,0 +1,51 @@
|
|||||||
|
class NimGameRev:
|
||||||
|
"""This is the NimGameRev. game_stub.py was used as the beginning
|
||||||
|
shell code in reference to correct methods, inputs, and outputs.
|
||||||
|
I entered the code for the game to be functional.
|
||||||
|
"""
|
||||||
|
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"],
|
||||||
|
}
|
||||||
|
row,num_lines=action
|
||||||
|
next_state["board"][row]-=num_lines
|
||||||
|
return next_state
|
||||||
|
|
||||||
|
"""def get_actions(self, state):
|
||||||
|
"initalize with actions"
|
||||||
|
actions = [
|
||||||
|
(0, 0),
|
||||||
|
(1, 0), (1, 1),
|
||||||
|
(2, 0), (2, 1), (2, 2),
|
||||||
|
(3, 0), (3, 1), (3, 2), (3, 3),
|
||||||
|
]
|
||||||
|
return actions"""
|
||||||
|
|
||||||
|
def get_actions(self, state):
|
||||||
|
actions = []
|
||||||
|
for row_index, lines_in_row in enumerate(state["board"]):
|
||||||
|
for num_lines_to_remove in range(1, lines_in_row + 1):
|
||||||
|
actions.append((row_index, num_lines_to_remove))
|
||||||
|
return actions
|
||||||
|
|
||||||
|
def get_reward(self, state):
|
||||||
|
if self.is_over(state):
|
||||||
|
return -1 if state["first_player"] else 1
|
||||||
|
return 0
|
||||||
|
|
||||||
|
def is_over(self, state):
|
||||||
|
"""Determines if the game is over.
|
||||||
|
Checks a condition, whether all rows are empty.
|
||||||
|
If all rows are empty game is over.
|
||||||
|
"""
|
||||||
|
return all(lines == 0 for lines in state["board"])
|
||||||
|
|
||||||
|
def get_objective(self, state):
|
||||||
|
return max if state["first_player"] else min
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
from nim.game_stub import NimGameStub
|
from nim.game import NimGame
|
||||||
from strategy.lookahead_strategy import LookaheadStrategy
|
from strategy.lookahead_strategy import LookaheadStrategy
|
||||||
|
|
||||||
class HumanNimPlayer:
|
class HumanNimPlayer:
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.game = NimGameStub()
|
self.game = NimGame()
|
||||||
|
|
||||||
def choose_action(self, state):
|
def choose_action(self, state):
|
||||||
actions = self.game.get_actions(state)
|
actions = self.game.get_actions(state)
|
||||||
@@ -26,7 +26,7 @@ class HumanNimPlayer:
|
|||||||
class ComputerNimPlayer:
|
class ComputerNimPlayer:
|
||||||
def __init__(self, name):
|
def __init__(self, name):
|
||||||
self.name = name
|
self.name = name
|
||||||
self.strategy = LookaheadStrategy(NimGameStub(), max_depth=3, deterministic=False)
|
self.strategy = LookaheadStrategy(NimGame(), max_depth=3, deterministic=False)
|
||||||
|
|
||||||
def choose_action(self, state):
|
def choose_action(self, state):
|
||||||
action = self.strategy.choose_action(state)
|
action = self.strategy.choose_action(state)
|
||||||
|
|||||||
35
nim/player_rev.py
Normal file
35
nim/player_rev.py
Normal file
@@ -0,0 +1,35 @@
|
|||||||
|
from nim.game_rev import NimGameRev
|
||||||
|
from strategy.lookahead_strategy import LookaheadStrategy
|
||||||
|
|
||||||
|
class HumanNimPlayer:
|
||||||
|
def __init__(self, name):
|
||||||
|
self.name = name
|
||||||
|
self.game = NimGameRev()
|
||||||
|
|
||||||
|
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(NimGameRev(), 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_rev.py
Normal file
32
nim/view_rev.py
Normal file
@@ -0,0 +1,32 @@
|
|||||||
|
from nim.game_rev import NimGameRev
|
||||||
|
|
||||||
|
class NimViewRev:
|
||||||
|
def __init__(self, player0, player1):
|
||||||
|
self.players = [player0, player1]
|
||||||
|
self.game = NimGameRev()
|
||||||
|
|
||||||
|
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}!")
|
||||||
118
notes.md
118
notes.md
@@ -109,4 +109,122 @@ game.py. “def get_initial_state(self):”
|
|||||||
Is returning the game's initial state with the Tic Tac Toe board ready for the 1st player to play the initial round.
|
Is returning the game's initial state with the Tic Tac Toe board ready for the 1st player to play the initial round.
|
||||||
Within “next state” there is a Boolean of True to see if it’s “X’s” turn and if not it’s “0’s” turn to play. The future reward for the state is that the game proceeds and updates until the all spots have been used by both player with an outcome of a winner or not.
|
Within “next state” there is a Boolean of True to see if it’s “X’s” turn and if not it’s “0’s” turn to play. The future reward for the state is that the game proceeds and updates until the all spots have been used by both player with an outcome of a winner or not.
|
||||||
|
|
||||||
|
*****Getting errors entering code in python
|
||||||
|
I did all the preliminary with the poetry shell
|
||||||
|
|
||||||
|
from ttt.game import TTTGame "zsh: command not found: from"
|
||||||
|
|
||||||
|
Can't get beyond this. What am I doing incorrectly?
|
||||||
|
|
||||||
|
from ttt.game import TTTGame
|
||||||
|
from strategy.lookahead_strategy import LookaheadStrategy
|
||||||
|
game = TTTGame()
|
||||||
|
strategy = LookaheadStrategy(game, explain=True)
|
||||||
|
state = {"board": ['-','O','O','X','X','-','-','-','-'], "player_x": True} >>> strategy.get_current_and_future_reward(state, explain=True)
|
||||||
|
|
||||||
|
|
||||||
|
Nim Game
|
||||||
|
|
||||||
|
Wrote the NimGameRev class and replaced NimGameStub
|
||||||
|
The Nim Game was stuck with 1 line left and wouldn't end.
|
||||||
|
|
||||||
|
Honestly, I used AI to help me better understand the reasoning for the code.
|
||||||
|
|
||||||
|
I was stuck with def get_actions(self, state):
|
||||||
|
|
||||||
|
And used from AI
|
||||||
|
|
||||||
|
def get_actions(self, state):
|
||||||
|
actions = []
|
||||||
|
for row_index, lines_in_row in enumerate(state["board"]):
|
||||||
|
for num_lines_to_remove in range(1, lines_in_row + 1):
|
||||||
|
actions.append((row_index, num_lines_to_remove))
|
||||||
|
return actions
|
||||||
|
|
||||||
|
I have AI be more definitive because the use of 'i' and 'j' was too abstract.
|
||||||
|
|
||||||
|
The Nim Game worked with the Robot winning.
|
||||||
|
|
||||||
|
The Nim Game
|
||||||
|
What's your name? Kathryn
|
||||||
|
Kathryn and Robot, welcome to Nim.
|
||||||
|
|
|
||||||
|
| | |
|
||||||
|
| | | | |
|
||||||
|
| | | | | | |
|
||||||
|
0. Remove 1 from row 0.
|
||||||
|
1. Remove 1 from row 1.
|
||||||
|
2. Remove 2 from row 1.
|
||||||
|
3. Remove 3 from row 1.
|
||||||
|
4. Remove 1 from row 2.
|
||||||
|
5. Remove 2 from row 2.
|
||||||
|
6. Remove 3 from row 2.
|
||||||
|
7. Remove 4 from row 2.
|
||||||
|
8. Remove 5 from row 2.
|
||||||
|
9. Remove 1 from row 3.
|
||||||
|
10. Remove 2 from row 3.
|
||||||
|
11. Remove 3 from row 3.
|
||||||
|
12. Remove 4 from row 3.
|
||||||
|
13. Remove 5 from row 3.
|
||||||
|
14. Remove 6 from row 3.
|
||||||
|
15. Remove 7 from row 3.
|
||||||
|
> 1
|
||||||
|
|
|
||||||
|
| |
|
||||||
|
| | | | |
|
||||||
|
| | | | | | |
|
||||||
|
Robot removes 1 from row 3
|
||||||
|
|
|
||||||
|
| |
|
||||||
|
| | | | |
|
||||||
|
| | | | | |
|
||||||
|
0. Remove 1 from row 0.
|
||||||
|
1. Remove 1 from row 1.
|
||||||
|
2. Remove 2 from row 1.
|
||||||
|
3. Remove 1 from row 2.
|
||||||
|
4. Remove 2 from row 2.
|
||||||
|
5. Remove 3 from row 2.
|
||||||
|
6. Remove 4 from row 2.
|
||||||
|
7. Remove 5 from row 2.
|
||||||
|
8. Remove 1 from row 3.
|
||||||
|
9. Remove 2 from row 3.
|
||||||
|
10. Remove 3 from row 3.
|
||||||
|
11. Remove 4 from row 3.
|
||||||
|
12. Remove 5 from row 3.
|
||||||
|
13. Remove 6 from row 3.
|
||||||
|
> 2
|
||||||
|
|
|
||||||
|
|
||||||
|
| | | | |
|
||||||
|
| | | | | |
|
||||||
|
Robot removes 3 from row 2
|
||||||
|
|
|
||||||
|
|
||||||
|
| |
|
||||||
|
| | | | | |
|
||||||
|
0. Remove 1 from row 0.
|
||||||
|
1. Remove 1 from row 2.
|
||||||
|
2. Remove 2 from row 2.
|
||||||
|
3. Remove 1 from row 3.
|
||||||
|
4. Remove 2 from row 3.
|
||||||
|
5. Remove 3 from row 3.
|
||||||
|
6. Remove 4 from row 3.
|
||||||
|
7. Remove 5 from row 3.
|
||||||
|
8. Remove 6 from row 3.
|
||||||
|
> 8
|
||||||
|
|
|
||||||
|
|
||||||
|
| |
|
||||||
|
|
||||||
|
Robot removes 1 from row 2
|
||||||
|
|
|
||||||
|
|
||||||
|
|
|
||||||
|
|
||||||
|
0. Remove 1 from row 0.
|
||||||
|
1. Remove 1 from row 2.
|
||||||
|
> 1
|
||||||
|
|
|
||||||
|
|
||||||
|
Robot removes 1 from row 0
|
||||||
|
Congratulations, Robot!
|
||||||
@@ -1,4 +1,4 @@
|
|||||||
from nim.game_stub import NimGameStub
|
from nim.game_stub import NimGameStub # type: ignore
|
||||||
from nim.view import NimView
|
from nim.view import NimView
|
||||||
from nim.player import HumanNimPlayer, ComputerNimPlayer
|
from nim.player import HumanNimPlayer, ComputerNimPlayer
|
||||||
|
|
||||||
|
|||||||
15
play_nim_rev.py
Normal file
15
play_nim_rev.py
Normal file
@@ -0,0 +1,15 @@
|
|||||||
|
from nim.game_rev import NimGameRev
|
||||||
|
from nim.view_rev import NimViewRev
|
||||||
|
from nim.player_rev import HumanNimPlayer, ComputerNimPlayer
|
||||||
|
|
||||||
|
player0 = HumanNimPlayer(input("What's your name? "))
|
||||||
|
player1 = ComputerNimPlayer("Robot")
|
||||||
|
view = NimViewRev(player0, player1)
|
||||||
|
game = NimGameRev()
|
||||||
|
|
||||||
|
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)
|
||||||
BIN
strategy/.DS_Store
vendored
BIN
strategy/.DS_Store
vendored
Binary file not shown.
Reference in New Issue
Block a user