From 757a7c0bc8dcafaa1f796b31c0a43c412771ad90 Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Tue, 12 May 2015 20:15:46 -0400 Subject: [PATCH 1/3] Created game_of_sticks.py and test_game_of_sticks.py --- game_of_sticks.py | 182 +++++++++++++++++++++++++++++++++++++++++ test_game_of_sticks.py | 107 ++++++++++++++++++++++++ 2 files changed, 289 insertions(+) create mode 100644 game_of_sticks.py create mode 100644 test_game_of_sticks.py diff --git a/game_of_sticks.py b/game_of_sticks.py new file mode 100644 index 0000000..3dbb5b0 --- /dev/null +++ b/game_of_sticks.py @@ -0,0 +1,182 @@ +import os +import random + + +class SticksGame: + # X Print out rules + # X create and start turns + # X remove turn sticks from pile + # X display remaining sticks + # X Stop when player starts turn with one stick in pile + def __init__(self, player1, player2): + self.pile = 20 + self.player1 = player1 + self.player2 = player2 + self.current_player = player1 + + def display_rules(self): + print("Welcome to the Game of Sticks!\n\ +In the Game of Sticks there is a heap of sticks on a board.\n\ +On their turn, each player picks up 1 to 3 sticks.\n\ +The one who has to pick the final stick will be the loser.\n") + + def display_pile(self): + return "Pile contains {} sticks.".format(self.pile) + + def switch_players(self): + if self.current_player == self.player1: + self.current_player = self.player2 + else: + self.current_player = self.player1 + + def remove(self): + print("Currently {}'s turn".format(self.current_player.name)) + self.current_player.pick_up(self.pile) + self.pile -= self.current_player.sticks + self.current_player.sticks = 0 + + def winner(self): + if self.pile > 0: + return None + else: + return self.current_player + + def menu(self): + self.display_rules() + + go = input("Ready? (y/n) ").lower() + + if go[0] == "y": + self.start() + elif go[0] == "n": + return + else: + self.menu() + + def start(self): + self.pile = 20 + while not self.winner(): + os.system('clear') + print(self.display_pile()) + self.remove() + self.switch_players() + + self.current_player.win_state = True + print("Game Over!") + self.player1.win_check() + self.player2.win_check() + self.play_again() + + def play_again(self): + go_again = input("Would you like to play again (y/n)? ").lower() + + if go_again[0] == "y": + self.start() + elif go_again[0] == "n": + return + else: + self.play_again() + +############################################################################### + + +class Player: + # X decide how many sticks to pick up + def __init__(self, name="Player"): + self.name = name + self.sticks = 0 + self.win_state = False + + def pick_up(self, remaining): + try: + num = int(input("How many sticks would you like to pick up? ")) + + if num in [1, 2, 3]: + self.sticks = num + else: + print("Invalid choice!") + return self.pick_up(remaining) + except ValueError: + print("Invalid choice!") + return self.pick_up(remaining) + + def win_check(self): + if self.win_state: + print("The winner is {}!".format(self.name)) + + def __repr__(self): + return self.name + +############################################################################### + + +class AIPlayer(Player): + def __init__(self, name="AI"): + super().__init__(name) + self.chosen = {} + self.possibilities = {} + self.tally = 0 + + def choices(self, remaining): + return self.possibilities.setdefault(remaining, [1, 2, 3]) + + def pick_up(self, remaining): + choice = random.choice(self.choices(remaining)) + self.chosen[remaining] = choice + self.sticks = choice + + def win_check(self): + if self.win_state: + print("The winner is {}!".format(self.name)) + self.integrate_win() + self.tally += 1 + else: + self.chosen = {} + + def integrate_win(self): + # for each choice made, add that choice into the + # possible choices + for key in self.chosen: + self.possibilities[key].append(self.chosen[key]) + + self.chosen = {} + + +############################################################################### + +def menu(): + print("Welcome to the Game of Sticks!\n\ +In the Game of Sticks there is a heap of sticks on a board.\n\ +On their turn, each player picks up 1 to 3 sticks.\n\ +The one who has to pick the final stick will be the loser.\n") + + set_up = input("Would you like to play against another [h]uman, \ +a [c]omputer, or a [t]rained computer? ").lower() + + if set_up[0] == "h": + player_name1 = input("First Player's Name: ") + player_name2 = input("Second Player's Name: ") + player1 = Player(player_name1) + player2 = Player(player_name2) + game = SticksGame(player1, player2) + game.start() + elif set_up[0] == "c": + player_name = input("Your Name: ") + player1 = Player(player_name) + player2 = AIPlayer() + game = SticksGame(player1, player2) + game.start() + elif set_up[0] == "c": + player_name = input("Your Name: ") + player1 = Player(player_name) + player2 = AIPlayer() + game = SticksGame(player1, player2) + game.start() + else: + os.system('clear') + print("Invalid choice, please try again") + return menu() + + +if __name__ == '__main__': + menu() diff --git a/test_game_of_sticks.py b/test_game_of_sticks.py new file mode 100644 index 0000000..fa9dcf9 --- /dev/null +++ b/test_game_of_sticks.py @@ -0,0 +1,107 @@ +from game_of_sticks import SticksGame, Player, AIPlayer + + +def test_SticksGame_has_pile(): + game = SticksGame("p1", "p2") + assert game.pile == 20 + + +class TestGame(SticksGame): + def play_again(self): + return None + + +def test_SticksGame_ends(): + game = TestGame("p1", "p2") + assert not game.winner() == "p1" + assert not game.winner() == "p2" + game.pile = 0 + assert game.winner() == "p1" + assert not game.winner() == "p2" + + +def test_SticksGame_displays_pile(): + game = SticksGame("p1", "p2") + assert game.display_pile() == "Pile contains 20 sticks." + game.pile = 3 + assert game.display_pile() == "Pile contains 3 sticks." + + +def test_SticksGame_switches_players(): + game = SticksGame("p1", "p2") + game.switch_players() + assert game.current_player == "p2" + game.switch_players() + assert game.current_player == "p1" + + +class TestPlayer(Player): + def __init__(self): + super().__init__() + self.check = 2 + + def pick_up(self, remaining): + if self.check in [1, 2, 3]: + self.sticks = self.check + + +def test_player_decides_how_many_sticks_to_take(): + player = TestPlayer() + assert player.sticks == 0 + player.pick_up(1) + assert player.sticks == 2 + player.check = 1 + player.pick_up(1) + assert player.sticks == 1 + player.check = 3 + player.pick_up(1) + assert player.sticks == 3 + player.check = 4 + player.pick_up(1) + assert not player.sticks == 4 + + +def test_SticksGame_removes_sticks_from_pile(): + player = TestPlayer() + game = SticksGame(player, player) + assert game.pile == 20 + game.remove() + assert game.pile == 18 + player.check = 4 + game.remove() + assert game.pile == 18 + + +def test_SticksGame_goes_until_winner(): + p1 = TestPlayer() + p2 = TestPlayer() + game = TestGame(p1, p2) + game.start() + print(game.pile) + print(game.current_player) + assert game.winner() is not None + + +def test_AI_test_game(): + ai = AIPlayer() + ai.pick_up(17) + ai.pick_up(12) + ai.pick_up(3) + ai.integrate_win() + assert len(ai.choices(17)) == 4 + ai.pick_up(17) + ai.pick_up(10) + ai.integrate_win() + assert len(ai.choices(17)) == 5 + assert len(ai.choices(10)) == 4 + ai.pick_up(17) + ai.pick_up(10) + ai.win_check() + assert len(ai.choices(17)) == 5 + assert len(ai.choices(10)) == 4 + + +def test_AI_choices(): + """An initial player should have 1, 2, 3 as choices for all numbers.""" + ai = AIPlayer() + assert ai.choices(13) == [1, 2, 3] From 1e41a626e5c355c7fc8432da6d25762bc1a9d12e Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Tue, 12 May 2015 20:51:34 -0400 Subject: [PATCH 2/3] Added AI training to game_of_sticks.py and corresponding tests to test_game_of_sticks --- game_of_sticks.py | 89 ++++++++++++++++++++++++++++++------------ test_game_of_sticks.py | 8 +++- 2 files changed, 71 insertions(+), 26 deletions(-) diff --git a/game_of_sticks.py b/game_of_sticks.py index 3dbb5b0..3a499dc 100644 --- a/game_of_sticks.py +++ b/game_of_sticks.py @@ -14,44 +14,37 @@ def __init__(self, player1, player2): self.player2 = player2 self.current_player = player1 - def display_rules(self): - print("Welcome to the Game of Sticks!\n\ -In the Game of Sticks there is a heap of sticks on a board.\n\ -On their turn, each player picks up 1 to 3 sticks.\n\ -The one who has to pick the final stick will be the loser.\n") +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def display_pile(self): return "Pile contains {} sticks.".format(self.pile) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def switch_players(self): if self.current_player == self.player1: self.current_player = self.player2 else: self.current_player = self.player1 - def remove(self): - print("Currently {}'s turn".format(self.current_player.name)) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + + def remove(self, silent=False): + if not silent: + print("Currently {}'s turn\n".format(self.current_player.name)) self.current_player.pick_up(self.pile) self.pile -= self.current_player.sticks self.current_player.sticks = 0 +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def winner(self): if self.pile > 0: return None else: return self.current_player - def menu(self): - self.display_rules() - - go = input("Ready? (y/n) ").lower() - - if go[0] == "y": - self.start() - elif go[0] == "n": - return - else: - self.menu() +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def start(self): self.pile = 20 @@ -67,6 +60,8 @@ def start(self): self.player2.win_check() self.play_again() +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def play_again(self): go_again = input("Would you like to play again (y/n)? ").lower() @@ -87,6 +82,8 @@ def __init__(self, name="Player"): self.sticks = 0 self.win_state = False +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def pick_up(self, remaining): try: num = int(input("How many sticks would you like to pick up? ")) @@ -100,9 +97,14 @@ def pick_up(self, remaining): print("Invalid choice!") return self.pick_up(remaining) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def win_check(self): if self.win_state: - print("The winner is {}!".format(self.name)) + print("The winner is {}!\n".format(self.name)) + self.win_state = False + +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def __repr__(self): return self.name @@ -117,25 +119,35 @@ def __init__(self, name="AI"): self.possibilities = {} self.tally = 0 +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def choices(self, remaining): return self.possibilities.setdefault(remaining, [1, 2, 3]) +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def pick_up(self, remaining): choice = random.choice(self.choices(remaining)) self.chosen[remaining] = choice self.sticks = choice - def win_check(self): +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + + def win_check(self, silent=False): if self.win_state: - print("The winner is {}!".format(self.name)) + if not silent: + print("The winner is {}!\n".format(self.name)) self.integrate_win() self.tally += 1 + self.win_state = False else: self.chosen = {} +# ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # + def integrate_win(self): - # for each choice made, add that choice into the - # possible choices + """for each choice made, add that choice into the + possible choices""" for key in self.chosen: self.possibilities[key].append(self.chosen[key]) @@ -144,7 +156,31 @@ def integrate_win(self): ############################################################################### + +class AISticksGame(SticksGame): + def start(self): + count = 100000 + while count > 0: + self.pile = 20 + while not self.winner(): + self.remove(silent=True) + self.switch_players() + + self.current_player.win_state = True + self.player1.win_check(silent=True) + self.player2.win_check(silent=True) + count -= 1 + if self.player1.tally >= self.player2.tally: + return self.player1 + else: + return self.player2 + + +############################################################################### + + def menu(): + os.system('clear') print("Welcome to the Game of Sticks!\n\ In the Game of Sticks there is a heap of sticks on a board.\n\ On their turn, each player picks up 1 to 3 sticks.\n\ @@ -166,10 +202,13 @@ def menu(): player2 = AIPlayer() game = SticksGame(player1, player2) game.start() - elif set_up[0] == "c": + elif set_up[0] == "t": + ai1 = AIPlayer() + ai2 = AIPlayer() + AI_game = AISticksGame(ai1, ai2) player_name = input("Your Name: ") player1 = Player(player_name) - player2 = AIPlayer() + player2 = AI_game.start() game = SticksGame(player1, player2) game.start() else: diff --git a/test_game_of_sticks.py b/test_game_of_sticks.py index fa9dcf9..ccdc04d 100644 --- a/test_game_of_sticks.py +++ b/test_game_of_sticks.py @@ -1,4 +1,4 @@ -from game_of_sticks import SticksGame, Player, AIPlayer +from game_of_sticks import SticksGame, Player, AIPlayer, AISticksGame def test_SticksGame_has_pile(): @@ -105,3 +105,9 @@ def test_AI_choices(): """An initial player should have 1, 2, 3 as choices for all numbers.""" ai = AIPlayer() assert ai.choices(13) == [1, 2, 3] + +def test_AISticksGame(): + HAL = AIPlayer() + GLaDOS = AIPlayer() + game = AISticksGame(HAL, GLaDOS) + assert game.start() == HAL or game.start() == GLaDOS From 5083818e645ef3b1059c0788bb7da4c0d20a7642 Mon Sep 17 00:00:00 2001 From: Benjamin Phillips Date: Tue, 12 May 2015 21:02:23 -0400 Subject: [PATCH 3/3] Altered game output slightly in game_of_sticks.py --- game_of_sticks.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/game_of_sticks.py b/game_of_sticks.py index 3a499dc..7a3b38e 100644 --- a/game_of_sticks.py +++ b/game_of_sticks.py @@ -17,7 +17,8 @@ def __init__(self, player1, player2): # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # def display_pile(self): - return "Pile contains {} sticks.".format(self.pile) + return "Pile contains {} sticks.".format(self.pile) \ + + (" / " * self.pile) # ~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~ # @@ -55,6 +56,7 @@ def start(self): self.switch_players() self.current_player.win_state = True + os.system('clear') print("Game Over!") self.player1.win_check() self.player2.win_check()