def setUp(self): #create a list of all the cards that we don't know/unseen self.unseen_actors = ['scarlett','plum','peacock','green','mustard','white'] self.unseen_weapons = ['candlestick','dagger','pipe','revolver','rope','wrench'] self.unseen_rooms = ['kitchen','ballroom','conservatory','dining','billiard','library','lounge','hall','study'] #basic game deck self.deck = GameDeck()
def __init__(self, players): ''' creates a new game based on the player colours inputted in the player array ''' self.turn_list = [] self.total_incorrect_cards = 18 self.controlled_player_index = -1 self.location = None self.actor = None self.weapon = None self.reference_deck = GameDeck() self.players = self.create_players(players) #tracker of the cards that are not in the solution self.incorrect_cards = [] self.testing_harness_enabled = True
def __init__(self, colour, number_of_cards): ''' creator ''' self.reference_deck = GameDeck() if int(number_of_cards) < 1: raise ValueError("The number of cards held by the player is less than one") if not isinstance(colour, str): raise TypeError("The colour for the player is not a string") if not self.reference_deck.is_actor(colour): raise ValueError("The colour of the player is incorrect") self.number_of_cards = int(number_of_cards) self.colour = colour self.cards_held = [] self.viewed = [] self.cards_not_held = [] self.potentially_viewed = GameTree() self.potentially_held = GameTree()
class GamePlayer: ''' Logical representation of a player within the game Will track the objects that is holds and has viewed ''' def __init__(self, colour, number_of_cards): ''' creator ''' self.reference_deck = GameDeck() if int(number_of_cards) < 1: raise ValueError("The number of cards held by the player is less than one") if not isinstance(colour, str): raise TypeError("The colour for the player is not a string") if not self.reference_deck.is_actor(colour): raise ValueError("The colour of the player is incorrect") self.number_of_cards = int(number_of_cards) self.colour = colour self.cards_held = [] self.viewed = [] self.cards_not_held = [] self.potentially_viewed = GameTree() self.potentially_held = GameTree() def turn(self): ''' plays a turn for the player main turner function ''' #if the total number of cards that are know to not be held is equal to the number of cards that cannot be held; we can deduce the cards that are held by this player if len(cards_not_held) == (21 - self.number_of_cards - len(held)): return 1 else: return 0 def exclude_cards(self, cards): ''' excludes a list of cards from the possible cards that could be held ''' for i in range(len(cards)): if cards[i] not in self.cards_not_held: self.cards_not_held.append(cards[i]) def set_card_held(self, card): ''' sets a card to be held by the player raises a ValueError if the card is already present ''' if len(self.cards_held) < self.number_of_cards: if card not in self.cards_held: self.cards_held.append(card) self.set_card_seen(card) return raise ValueError def set_card_seen(self,card): ''' sets a card to be seen ''' self.exclude_cards([card]) def get_cards_held(self): ''' returns a list of all cards held ''' return self.cards_held def get_number_of_cards_held(self): ''' returns the number of cards held ''' return self.number_of_cards def get_number_of_cards_known(self): ''' returns the number of cards known for this player ''' return len(self.cards_held) def get_colour(self): ''' returns the colour of the function ''' return self.colour def set_cards_potentially_seen(self, cards): ''' sets the input cards as potentially_viewed ''' pass def set_cards_potentially_held(self, cards): ''' sets the inputs cards as potentially_viewed ''' pass
class TestSimpleDeduction(unittest.TestCase): def setUp(self): #create a list of all the cards that we don't know/unseen self.unseen_actors = ['scarlett','plum','peacock','green','mustard','white'] self.unseen_weapons = ['candlestick','dagger','pipe','revolver','rope','wrench'] self.unseen_rooms = ['kitchen','ballroom','conservatory','dining','billiard','library','lounge','hall','study'] #basic game deck self.deck = GameDeck() def update_unseen_cards(self, incorrect_cards): ''' updates the cards that are still yet to be seen ''' for card in incorrect_cards: if self.deck.is_actor(card) and (card in self.unseen_actors): self.unseen_actors.remove(card) elif self.deck.is_weapon(card) and (card in self.unseen_weapons): self.unseen_weapons.remove(card) elif self.deck.is_room(card) and (card in self.unseen_rooms): self.unseen_rooms.remove(card) def decide_responder_index(self, game): ''' returns a random index of a player who still has unseen cards ''' potential_cards = [] for i in range(len(game.players)): if not game.get_number_of_cards_known(i) == game.get_number_of_cards_held(i): potential_cards.append(i) return int(random.sample(potential_cards, 1)[0]) def test_basic_path_correct_3(self): # create the game with the know player cards players = [("white", 6), ("plum", 6), ("scarlett", 6)] test_game = Game(players) test_game.set_controlled_player(0) test_game.set_player_cards_held(0, ["rope","wrench","kitchen","white","green","revolver"]) self.update_unseen_cards(test_game.incorrect_cards) #keep playing guess until the game is not complete while not test_game.is_complete(): possible_cards = [] #get three unknown cards from the unknown cards if self.unseen_actors: actor = str(random.sample(self.unseen_actors, 1)[0]) possible_cards.append(actor) else: actor = "green" if self.unseen_rooms: room = str(random.sample(self.unseen_rooms, 1)[0]) possible_cards.append(room) else: room = "kitchen" if self.unseen_weapons: weapon = str(random.sample(self.unseen_weapons, 1)[0]) possible_cards.append(weapon) else: weapon = "rope" responder_index = self.decide_responder_index(test_game) card_seen = random.sample(possible_cards, 1) print("current turn: " + actor + ", " + room + ", " + weapon + ' responder index: ' + str(responder_index) + " cards seen: " + str(card_seen)) #create a guess from above cards test_game.turn(0, actor, weapon, room, responder_index, card_seen) print(test_game.incorrect_cards) self.update_unseen_cards(test_game.incorrect_cards) #complete the game self.assertTrue(test_game.is_complete(), "game complete") def test_basic_path_correct_4(self): # create the game with the know player cards players = [("white", 4), ("plum", 4), ("scarlett", 5), ("green", 5)] test_game = Game(players) test_game.set_controlled_player(0) test_game.set_player_cards_held(0, ["rope","wrench","kitchen","white"]) self.update_unseen_cards(test_game.incorrect_cards) #keep playing guess until the game is not complete while not test_game.is_complete(): possible_cards = [] #get three unknown cards from the unknown cards if self.unseen_actors: actor = str(random.sample(self.unseen_actors, 1)[0]) possible_cards.append(actor) else: actor = "green" if self.unseen_rooms: room = str(random.sample(self.unseen_rooms, 1)[0]) possible_cards.append(room) else: room = "kitchen" if self.unseen_weapons: weapon = str(random.sample(self.unseen_weapons, 1)[0]) possible_cards.append(weapon) else: weapon = "rope" responder_index = self.decide_responder_index(test_game) card_seen = random.sample(possible_cards, 1) print("current turn: " + actor + ", " + room + ", " + weapon + ' responder index: ' + str(responder_index) + " cards seen: " + str(card_seen)) #create a guess from above cards test_game.turn(0, actor, weapon, room, responder_index, card_seen) print(test_game.incorrect_cards) self.update_unseen_cards(test_game.incorrect_cards) #complete the game self.assertTrue(test_game.is_complete(), "game complete") def test_basic_path_correct_5(self): # create the game with the know player cards players = [("white", 4), ("plum", 4), ("scarlett", 4), ("green", 3), ("mustard", 3)] test_game = Game(players) test_game.set_controlled_player(0) test_game.set_player_cards_held(0, ["billiard","library","dagger","mustard"]) self.update_unseen_cards(test_game.incorrect_cards) #keep playing guess until the game is not complete while not test_game.is_complete(): possible_cards = [] #get three unknown cards from the unknown cards if self.unseen_actors: actor = str(random.sample(self.unseen_actors, 1)[0]) possible_cards.append(actor) else: actor = "billards" if self.unseen_rooms: room = str(random.sample(self.unseen_rooms, 1)[0]) possible_cards.append(room) else: room = "library" if self.unseen_weapons: weapon = str(random.sample(self.unseen_weapons, 1)[0]) possible_cards.append(weapon) else: weapon = "dagger" responder_index = self.decide_responder_index(test_game) card_seen = random.sample(possible_cards, 1) print("current turn: " + actor + ", " + room + ", " + weapon + ' responder index: ' + str(responder_index) + " cards seen: " + str(card_seen)) #create a guess from above cards test_game.turn(0, actor, weapon, room, responder_index, card_seen) print(test_game.incorrect_cards) self.update_unseen_cards(test_game.incorrect_cards) #complete the game self.assertTrue(test_game.is_complete(), "game complete") def test_basic_path_correct_6(self): # create the game with the know player cards players = [("white", 3), ("plum", 3), ("scarlett", 3), ("green", 3), ("mustard", 3), ("peacock", 3)] test_game = Game(players) test_game.set_controlled_player(0) test_game.set_player_cards_held(0, ["billiard","library","dagger"]) self.update_unseen_cards(test_game.incorrect_cards) #keep playing guess until the game is not complete while not test_game.is_complete(): possible_cards = [] #get three unknown cards from the unknown cards if self.unseen_actors: actor = str(random.sample(self.unseen_actors, 1)[0]) possible_cards.append(actor) else: actor = "billards" if self.unseen_rooms: room = str(random.sample(self.unseen_rooms, 1)[0]) possible_cards.append(room) else: room = "library" if self.unseen_weapons: weapon = str(random.sample(self.unseen_weapons, 1)[0]) possible_cards.append(weapon) else: weapon = "dagger" responder_index = self.decide_responder_index(test_game) card_seen = random.sample(possible_cards, 1) print("current turn: " + actor + ", " + room + ", " + weapon + ' responder index: ' + str(responder_index) + " cards seen: " + str(card_seen)) #create a guess from above cards test_game.turn(0, actor, weapon, room, responder_index, card_seen) print(test_game.incorrect_cards) self.update_unseen_cards(test_game.incorrect_cards) #complete the game self.assertTrue(test_game.is_complete(), "game complete")
class Game: def __init__(self, players): ''' creates a new game based on the player colours inputted in the player array ''' self.turn_list = [] self.total_incorrect_cards = 18 self.controlled_player_index = -1 self.location = None self.actor = None self.weapon = None self.reference_deck = GameDeck() self.players = self.create_players(players) #tracker of the cards that are not in the solution self.incorrect_cards = [] self.testing_harness_enabled = True def create_players(self, players): ''' initialise the players based on the passed players array ''' if not players: raise ValueError("The player list was empty") seen_colours = [] player_array = [] for i in range(len(players)): colour, number_of_cards = players[i] if colour in seen_colours: raise ValueError("There are duplicate colours inputted") if not self.reference_deck.is_actor(colour): raise ValueError("The colour specfied for player " + str(i+1) + " does not exist") player = GamePlayer(colour, number_of_cards) player_array.append(player) seen_colours.append(colour) return player_array ## Getters and Setters def get_number_of_cards_held(self, player_index): ''' gets the number of cards held by the player at the int, player_index ''' player = self.players[player_index] return player.get_number_of_cards_held() def get_number_of_cards_known(self, player_index): ''' gets the number of cards that are known for the player at the int, player_index ''' player = self.players[player_index] return player.get_number_of_cards_known() def set_player_cards_held(self, player_index, cards): ''' sets the player object at player_array[player_index] to be holding the cards array [zero indexed] adds the cards array to the incorrect_cards array ''' player = self.players[player_index] # adding more cards than is possible if (player.get_number_of_cards_known() + len(cards)) > player.get_number_of_cards_held(): raise ValueError("The number of cards you are trying to add is larger than the max number of cards player " + str(player_index+1) + " can hold") for i in range(len(cards)): #card does not exist if not self.reference_deck.in_deck(cards[i]): raise ValueError("Card: " + str(i+1) + " is not in the game deck") player.set_card_held(cards[i]) self.set_cards_incorrect(cards) def set_cards_incorrect(self, cards): ''' appends the cards array to the incorrect_cards array, not including duplicates ''' for i in range(len(cards)): if not self.reference_deck.in_deck(cards[i]): raise ValueError("Card: " + str(i) + " is not in the game deck") if cards[i] not in self.incorrect_cards: self.incorrect_cards.append(cards[i]) def set_controlled_player(self, player_index): ''' sets the index of the player controlled character (zero indexed) ''' if 0 <= player_index <= len(self.players)-1: self.controlled_player_index = player_index else: raise IndexError("The specified error is out of range") def set_weapon(self, weapon): ''' sets the solution weapon to be the input weapon string ''' if self.testing_harness_enabled: self.weapon = weapon def set_actor(self, actor): ''' sets the solution actor to be the input actor string ''' if self.testing_harness_enabled: self.actor = actor def set_location(self, location): ''' sets the solution location to be the input location string ''' if self.testing_harness_enabled: self.location = location ## game functionality def is_complete(self): ''' checks if a solution to the current games state returns true if there is a solution, false otherwise ''' if len(self.incorrect_cards) == self.total_incorrect_cards: return True else: return False def validate_turn_input(self, guesser_index, actor, weapon, room, responder_index, cards_seen): ''' Returns true if the input of the game turn inputed is valid and returns an error otherwise ''' if guesser_index == responder_index: raise ValueError("The guesser is the same as the responder") if not -1 < guesser_index <= len(self.players)-1: raise IndexError("Guesser index is out of bounds") if not -1 < responder_index <= len(self.players)-1: raise IndexError("Responder index is out of bounds") if not self.reference_deck.is_actor(actor): raise ValueError("Incorrect actor card specified") if not self.reference_deck.is_room(room): raise ValueError("Incorrect room card specified") if not self.reference_deck.is_weapon(weapon): raise ValueError("Incorrect weapon card specified") return True def turn(self, guesser_index, actor, weapon, room, responder_index, cards_seen): ''' Plays a turn for the game based on the input data cards_seen should be empty if the player hasn't seen any cards ''' try: self.validate_turn_input(guesser_index, actor, weapon, room, responder_index, cards_seen) except: e = sys.exc_info()[0] v = sys.exc_info()[1] print(e) print(v) return False current_turn = GameTurn(guesser_index, actor, weapon, room, responder_index, cards_seen) self.turn_list.append(current_turn) guesser_player = self.players[guesser_index] response_player = self.players[responder_index] guesser_player.set_cards_potentially_seen([actor, weapon, room]) response_player.set_cards_potentially_held([actor, weapon, room]) #player controlled if guesser_index == self.controlled_player_index: if cards_seen == None: raise Exception('There was no card seen for the current player') #add the card to the seen list self.set_player_cards_held(responder_index, cards_seen) return else: #someone elses turn if responder_index == self.controlled_player_index: #player controlled response return else: #another play response return def game_complete(self): ''' command to end the game ''' print("Game Ended. Goodbye.") sys.exit return