예제 #1
0
 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()
예제 #2
0
 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
예제 #3
0
 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()
예제 #4
0
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
예제 #5
0
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") 
예제 #6
0
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