Пример #1
0
    def __init__(self, limit=1000):
        """
        Here is the algorithm for class construction:
        1. Initializes round limit.
        2. Creates the Deck and Pile.
        3. Creates both Players and places them in a list.
        4. Creates the lists holding round and negotiation counts.
        """

        # 1. Initialize round limit

        self.__limit = limit

        # 2. Creates the Deck and Pile

        self.__deck = Deck()
        self.__pile = Pile()

        # 3. Creates both Players and places them in a list

        self.__players = [None, Player(), Player()]

        # 4. Creates the lists holding round and negotiation counts

        self.__round_wins = [0, 0, 0]
Пример #2
0
 def __init__(self, deck_size, deck_w_jokers, num_players, start_hand_size,
              direction):
     super(SpoonsEnv, self).__init__(deck_size, deck_w_jokers, num_players,
                                     start_hand_size, direction)
     self.trash = Pile()
     self.pass_pile = Pile()
     self.end_player = num_players - 1
Пример #3
0
 def setup_game(self):
     self.pile = Pile()
     self.board = Board()
     self.create_players()
     self.deal()
     self.set_starting_tile()
     self.play()
Пример #4
0
def initGame(mastersound):
    '''
        Initialize a new model of the game:

        Starts the intro song

        returns a tuple 
            a deck
            a list of minidecks
            a pile
            a new playscreen
    '''


    deck = Deck()
    pile = Pile()
    minidecks = []

    mastersound.stop()
    mastersound.intro()

    #Initialize a list of slots
    
    for i in range(NUMBEROFMINID):
        minidecks.append(Minideck(deck.draw_cards(CARDSINMINIDECK)))



    pile.put(deck.draw_card())

    return deck, minidecks, pile, PlayScreen()
  def testPile(self):
     '''
       Tests the pile class
     '''
     pile = Pile()

     pile.put('H5')
     pile.put('H6')

     self.assertEqual(pile.topCard(), 'H6')
Пример #6
0
 def __init__(self, deck_size, deck_w_jokers, num_players, start_hand_size,
              direction):
     super(BartokEnv, self).__init__(deck_size, deck_w_jokers, num_players,
                                     start_hand_size, direction)
     self.center = Pile()
     self.draw2 = False
     self.draw2_effect = 0
Пример #7
0
 def __init__(self):
     """
     Constructor:
     Creates the empty hand
     """
     self.__pile = Pile()
     self.__hand = Hand()
Пример #8
0
 def __init__(self, game):
     super(Bartok, self).__init__(game)
     self.env['center'] = Pile()
     # Determines if the current player mustDraw2
     self.env['mustDraw2'] = False
     # Keeps track of the number of players who cumulatively Draw 2
     self.env['draw2Effect'] = 0
Пример #9
0
def test():
    board = Board.from_config_file('board.cfg')
    pile = Pile.from_config_file('pile.cfg')
    players = [
        Player('Bot_1', RandomAgent()),
        Player('Bot_2', RandomAgent())
    ]
    game_count = 10000
    starter_winner_count = 0
    total_move_count = 0

    for i in range(game_count):
        new_board = copy.deepcopy(board)
        new_pile = copy.deepcopy(pile)
        new_players = copy.deepcopy(players)
        state = State(new_board, new_players, new_pile, False, False)
        game = Game(state)
        game.execute_setup()
        game.play_game()
        print(f'At game #{i:04}')
        total_move_count += game.move_count
        if game.starter == game.winner:
            starter_winner_count += 1

    print(f'Percentage of games won by starter: {starter_winner_count/game_count*100}%')
    print(f'Average number of total moves in a game: {total_move_count/game_count}')
Пример #10
0
    def __init__(self,
                 players: List[Player],
                 turn=0,
                 trade_pile=None,
                 draw_pile=None,
                 verbose=True,
                 seed=None):
        self.turn = turn
        self.players: List[Player] = players
        if draw_pile is None:
            draw_pile = DEFAULT_TRADE_PILE.copy()
            random.shuffle(draw_pile)
        self.trade_pile: Pile[Card] = Pile('trade_pile', trade_pile or [])
        self.draw_pile: Pile[Card] = Pile('draw_pile', draw_pile)
        #self.scrap_pile : Pile[Card] = Pile('scrap', [])

        if seed:
            random.seed(seed)
        self.verbose = verbose
Пример #11
0
def main():
    board = Board.from_config_file('board.cfg')
    pile = Pile.from_config_file('pile.cfg')
    players = [
        Player('Bot_1', RandomAgent()),
        Player('Bot_2', RandomAgent())
    ]
    state = State(board, players, pile, True, True)
    game = Game(state)
    game.execute_setup()
    game.play_game()
Пример #12
0
 def new_deck(self):
     """
     Creates and initializes a standard deck of 52 standard playing
     Cards.
     """
     deck = []
     for suit in Suit.SUITS:
         for rank in range(1,14):
             deck.append(Card(suit, rank))
     self.deck = Pile(deck)
     self.shuffle_cards()
     return self.deck
Пример #13
0
class Destiny:
    def __init__(self, decks=1, seed=None):
        self.pile1, self.pile2 = Pile(decks).shuffle(seed).split()

    def run(self):
        rounds = 0
        while not self.iswon():
            self.round([], [])
            rounds += 1
        return rounds

    def round(self, cards1, cards2):
        if len(self.pile1) == 0:
            self.pile1.pushall(cards1 + cards2)
            return

        if len(self.pile2) == 0:
            self.pile2.pushall(cards2 + cards1)
            return

        card1, card2 = self.pile1.pop(), self.pile2.pop()

        cards1.append(card1)
        cards2.append(card2)

        if card1 > card2:
            self.pile1.pushall(cards1 + cards2)
            return

        if card2 > card1:
            self.pile2.pushall(cards2 + cards1)
            return

        self.round(cards1, cards2)

    def iswon(self):
        return len(self.pile1) == 0 or len(self.pile2) == 0

    def __str__(self):
        return "%s\n\n%s" % (self.pile1, self.pile2)
Пример #14
0
    def __init__(self, limit=1000):
        """
        Initialize round limit
        Initialize the Deck and Pile
        Create both Players and place in list
        Create the lists holding the round and negotiation counts
        """
        # 1. Initialize round limit

        self.__limit = limit

        # 2. Initialize the Deck and Pile

        self.__deck = Deck()
        self.__pile = Pile()

        # 3. Create both Players and place in list

        self.__players = [None, Player(), Player()]

        # 4. Create the lists holding the round and negotiation counts

        self.__round_wins = [0, 0, 0]
Пример #15
0
 def __init__(self, name, game, id):
     self.name = name
     self.id = id
     self.actions = 0
     self.buys = 0
     self.money = 0
     self.score = 0
     self.potion = 0
     self.game = game
     self.hand = Pile()
     self.board = Pile()
     self.deck = Pile()
     self.durations = Pile()
     self.drawpile = Pile()
     self.discardpile = Pile()
Пример #16
0
    def reset(self):
        self.draw_pile : Pile[Card] = Pile('draw_pile')
        self.discard_pile : Pile[Card] = Pile('discard_pile', DEFAULT_PLAYER_DRAW)
        self.health = 50
        self.bases : Pile[BaseCard] = Pile('bases', [])
        self.outposts : Pile[OutpostCard] = Pile('outposts', [])
        self.need_draw = True

        # turn data
        self.hand : Pile[Card] = Pile('hand', [])
        self.in_play : Pile[Card] = Pile('in_play', [])
        self.trade = 0
        self.discard = 0
        self.on_top = 0
        self.damage = 0
        self.remaining_actions : List[Tuple[Card, Action]] = []
Пример #17
0
    def choose_from_piles(self, action: str, *piles: Pile, min_n=0, max_n=1, ship_only=False, remove_from_pile=True) -> Tuple[Pile, List[Card]]:
        if ship_only:
            filtered_piles = [Pile(p.name, filter(lambda c: not isinstance(c, (BaseCard, OutpostCard)), p)) for p in piles]
        else:
            filtered_piles = piles

        filtered_piles = [p for p in filtered_piles if p and len(p) > max(1, min_n)]

        if not filtered_piles:
            if min_n > 0:
                raise UndoMove()
            return None, None

        pile, cards = self.do_choose_from_piles(action, filtered_piles, min_n, max_n)
        actual_pile = None
        if pile and remove_from_pile:
            actual_pile = [p for p in piles if p.name == pile.name]
            assert len(actual_pile) == 1
            actual_pile = actual_pile[0]
            for c in cards:
                actual_pile.remove(c)

        return actual_pile, cards
Пример #18
0
    def __init__(self, name, health=50, draw_pile=None, discard_pile=None, bases=None, hand=None, outposts=None, need_draw=True):
        if draw_pile is None and discard_pile is None:
            discard_pile = DEFAULT_PLAYER_DRAW

        self.draw_pile : Pile[Card] = Pile('draw_pile', draw_pile or [])
        self.discard_pile : Pile[Card] = Pile('discard_pile', discard_pile or [])
        self.health = health
        self.name = name
        self.bases : Pile[BaseCard] = Pile('bases', bases or [])
        self.outposts : Pile[OutpostCard] = Pile('outposts', outposts or [])
        self.need_draw = need_draw

        # turn data
        self.hand : Pile[Card] = Pile('hand', hand or [])
        self.in_play : Pile[Card] = Pile('in_play', [])
        self.trade = 0
        self.discard = 0
        self.on_top = 0
        self.damage = 0
        self.remaining_actions : List[Tuple[Card, Action]] = []
Пример #19
0
	def _parse_page(self, page):
		pile = Pile()
		pile.parse_layout(page)
		piles = pile.split_piles()
		return piles
Пример #20
0
class Dealer:
    
    """
    
    A Dealer shuffles and deals a deck of Cards. He also moves Cards 
    on the Board from Pile to Pile, and draws Cards from the Stock pile
    to be used in play.
    
    """
    
    def __init__(self, draw=3, username='******'):
        """
        Creates a new Dealer by initializing a Board and shuffling and
        dealing a new deck of Cards.
        """
        self.board = Board()
        self.deck = self.new_deck()
        self.player = Player(username)
        self.num_draw = TYPE_OF_DRAW[self.player.data['draw']]
        self.history = []

    def print_board(self):
        """
        Prints a representation of the Solitaire game in its current
        state.
        """
        self.board.print_board()

    def shuffle_cards(self):
        """Randomly shuffles the deck of Cards."""
        random.shuffle(self.deck)

    def new_deck(self):
        """
        Creates and initializes a standard deck of 52 standard playing
        Cards.
        """
        deck = []
        for suit in Suit.SUITS:
            for rank in range(1,14):
                deck.append(Card(suit, rank))
        self.deck = Pile(deck)
        self.shuffle_cards()
        return self.deck

    def empty_board(self):
        """
        Collects all the cards on the Board and inserts them 
        into the Dealer's deck.
        """
        waste = self.board.waste
        stock = self.board.stock
        while not waste.is_empty():
            card = waste.pop()
            card.flip_down()
            self.deck.append(card)
        while not stock.is_empty():
            card = stock.pop()
            card.flip_down()
            self.deck.append(card)
        for foundation in self.board.foundations.values():
            while not foundation.is_empty():
                card = foundation.pop()
                card.flip_down()
                self.deck.append(card)
        for tableau in self.board.tableaux:
            while not tableau.is_empty():
                card = tableau.pop()
                card.flip_down()
                self.deck.append(card)
        self.shuffle_cards()
    
    def addHistory(self):
        """
        Adds a copy of the current board state to the
        history.
        """
        stock, waste, foundations, tableaux = self.board.copy_board()
        lastBoard = Board()
        lastBoard.set_piles(stock, waste, foundations, tableaux)
        historyEntry = {'board': lastBoard, 'score': self.player.current_score}
        self.history.append(historyEntry)
    
    def undo(self):
        """
        Sets the current state of the board to the last
        entry in the history. Increments the player's number
        of moves and reverts the player's score.
        """
        if len(self.history) == 0:
            return False
        new_state = self.history.pop()
        self.board = new_state['board']
        self.player.current_score = new_state['score']
        self.player.current_moves += 1
        return True

    def change_player(self, username):
        """
        Changes this dealer's player.
        """
        self.player.db.unlock_db()
        self.player = Player(username)
        self.num_draw = self.player.options['draw']
    
    def player_won(self):
        """
        Checks if the player has won the game, and if they
        have, returns True. Otherwise, returns False.
        """
        for suit in Suit.SUITS:
            fpile = self.board.foundations[suit]
            if not fpile.is_complete():
                return False
        return True

    def new_game(self, win=False):
        """
        Empties the Cards on the Board and re-deals the Cards for a new game.
        """
        self.empty_board()
        self.deal()
        self.player.start_game()
        self.history = []
        self.num_draw = TYPE_OF_DRAW[self.player.data['draw']]
    
    def deal(self):
        """
        Deals Cards into the Board's Tableau piles from left to right, 
        and flips the top Card in each pile. The leftmost Tableau pile
        has one Card, and the number of Cards in the remaining Tableau
        piles increases from left to right. The remaining 28 Cards are 
        dealt to the Board's Stock pile.
        """
        piles = self.board.tableaux
        stock = self.board.stock
        size = len(piles)
        height = 7
        
        # Push Cards to the Tableau piles
        for i in range(height):
            for k in range(i, size):
                pile = piles[k]
                c = self.deck.pop()
                if k == i:
                    c.flip_up()
                pile.push(c)
        
        # Push the remaining Cards to the Stock pile.
        for card in self.deck:
            stock.push(card)
    
    def handle_move(self, card, srcPile, destPile):
        """
        Handles a move. PROBABLY NOT KEEPING
        """
        if srcPile is None or destPile is None:
            return
        if srcPile == self.board.stock:
            if destPile == self.board.stock:
                return self.draw()
        if srcPile == self.board.waste:
            if destPile == self.board.waste:
                return destPile.push(card)
            return destPile.push_card(card)
        if srcPile in self.board.foundations.values():
            if destPile == srcPile or destPile in self.board.tableaux:
                return destPile.push_card(card)
        if srcPile in self.board.tableaux:
            if destPile in self.board.foundations.values():
                return destPile.push_card(card)
            if destPile in self.board.tableaux:
                pile = Pile([card])
                return destPile.push_pile(pile)

    def update_score(self, srcPile, destPile, flip=False):
        """
        Calculates the score for the move. Standard scoring for 
        Solitaire is as follows:
        
        Waste to Tableau: +5
        Waste to Foundation: +10
        Tableau to Foundation: +10
        Turn over Tableau card: +5
        Foundation to Tableau: -15
        Recycle waste when playing by ones: -100
        """
        if (srcPile == self.board.waste and 
            destPile in self.board.tableaux):
            return 5
        if ((srcPile == self.board.waste or srcPile in self.board.tableaux) and
            destPile in self.board.foundations.values()):
            return 10
        if (srcPile in self.board.foundations.values() and 
            destPile in self.board.tableaux):
            return -15
        if (srcPile == self.board.waste and 
            destPile == self.board.waste and self.draw == 1):
            return -100
        return 0

    def recycle_waste(self):
        """
        Empties the Waste pile, adding the Cards to
        the bottom of the Stock pile. Called each
        time Cards are drawn from Stock.
        """
        waste = self.board.waste
        stock = self.board.stock
        self.addHistory()
        while not waste.is_empty():
            self.pop_enqueue_card(waste, stock, True)
        stock.reverse()
        waste.squared = 0

    def draw(self):
        """
        Draws a certain number of cards from the stock
        pile, depending on the type of draw.
        """
        waste = self.board.waste
        stock = self.board.stock
        self.addHistory()
        self.player.current_moves += 1
        if stock.is_empty():
            return self.recycle_waste()
        for _ in range(self.num_draw):
            self.pop_push_card(stock, waste, True)
        waste.squared = max(len(waste) - 3, waste.squared, 0)
        if len(waste) < 3:
            waste.squared = 0

    def pop_enqueue_card(self, srcPile, destPile, flip=False):
        """
        Pops the topmost Card from srcPile and enqueues
        it to the bottom of destPile. If flip is True,
        flips the Card.
        """
        if (srcPile is None or destPile is None or 
            srcPile.is_empty()):
            return
        card = srcPile.peek()
        if card is None:
            return
        if srcPile.suitable_card_pop():
            srcPile.pop_card()
            if destPile.suitable_card_enqueue(card):
                if flip:
                    card.flip()
                destPile.enqueue_card(card)
            else:
                srcPile.push(card)
    
    def pop_push(self, card, source, dest):
        """
        Pops a card/pile off the source pile and pushes it
        onto the destination pile.
        """
        if card == source.peek():
            return self.pop_push_card(source, dest)
        return self.pop_push_pile(card, source, dest)

    def pop_push_card(self, srcPile, destPile, flip=False):
        """
        Pops the topmost Card from srcPile and pushes
        it to the top of destPile. If flip is True,
        flips the Card.
        """
        if (srcPile is None or destPile is None or 
            srcPile.is_empty()):
            return False
        card = srcPile.peek()
        if card is None:
            return False
        if srcPile.suitable_card_pop():
            srcPile.pop_card()
            if destPile.suitable_card_push(card):
                if flip:
                    card.flip()
                destPile.push_card(card)
                if srcPile in self.board.tableaux:
                    if (srcPile.peek() is not None and 
                        srcPile.peek().is_face_down()):
                        self.player.update_current_score(5)
                    srcPile.flip_top()
                scoreIncr = self.update_score(srcPile, destPile)
                self.player.update_current_score(scoreIncr)
                if srcPile != self.board.stock:
                    self.player.current_moves += 1
                return True
            else:
                srcPile.push(card)
                return False
        return False
    
    def pop_push_pile(self, topCard, srcPile, destPile, flip=False):
        """
        Pops a Pile of Cards from srcPile and pushes
        it to the top of destPile. If flip is True,
        flips the Card.
        """
        if srcPile is None or destPile is None or topCard is None:
            return False
        if srcPile.is_empty():
            return False
        if not srcPile.suitable_pile_pop(topCard):
            return False
        if ((srcPile in self.board.tableaux or 
             srcPile == self.board.waste or 
             srcPile == self.board.stock) and 
            srcPile == destPile):
            return False
        removed = srcPile.pop_pile(topCard)
        if removed is None:
            return False
        if not destPile.suitable_pile_push(removed):
            srcPile.extend(removed)
            return False
        if flip:
            removed = [card.flip() for card in removed]
        if srcPile in self.board.tableaux:
            if (srcPile.peek() is not None and 
                srcPile.peek().is_face_down()):
                self.player.update_current_score(5)
            srcPile.flip_top()
        destPile.push_pile(removed)
        scoreIncr = self.update_score(srcPile, destPile)
        self.player.update_current_score(scoreIncr)
        if srcPile != self.board.stock:
            self.player.current_moves += 1
        return True
    
    def pop_pile(self, bottomCard, srcPile):
        """
        Pops a pile from srcPile beginning with bottomCard.
        """
        if (srcPile is None or 
            bottomCard is None or 
            srcPile.is_empty() or not 
            srcPile.suitable_pile_pop(bottomCard)):
            return
        self.addHistory()
        return srcPile.pop_pile(bottomCard)
    
    def undo_pop_pile(self, pile, srcPile):
        """
        Re-pushes the pile popped from srcPile to srcPile
        if pile couldn't be pushed to destPile during a move.
        """
        if pile is None or srcPile is None:
            return
        srcPile.extend(pile)

    def push_pile(self, pile, srcPile, destPile):
        """
        Pushes pile to destPile if it is legal. Otherwise,
        undoes the pop and pushes pile back to srcPile.
        """
        if pile is None:
            return self.undo_pop_pile(pile, srcPile)
        if pile is not None and srcPile is not None and destPile is None:
            return self.undo_pop_pile(pile, srcPile)
        if (srcPile.name == self.board.stock.name and 
            destPile.name == self.board.stock.name):
            return
        if ((srcPile in self.board.tableaux or 
             srcPile == self.board.waste) and 
            srcPile.name == destPile.name):
            return self.undo_pop_pile(pile, srcPile)
        if not destPile.suitable_pile_push(pile):
            return self.undo_pop_pile(pile, srcPile)
        if srcPile in self.board.tableaux:
            if (srcPile.peek() is not None and 
                srcPile.peek().is_face_down()):
                self.player.update_current_score(5)
            srcPile.flip_top()
        destPile.push_pile(pile)
        scoreIncr = self.update_score(srcPile, destPile)
        self.player.update_current_score(scoreIncr)
        if srcPile != self.board.stock:
            self.player.current_moves += 1

    def to_foundation(self, card, srcPile):
        """
        Sends a card to its appropriate source pile
        if it's suitable.
        """
        suit = card.suit
        fpile = self.board.foundations[suit]
        return self.pop_push_pile(card, srcPile, fpile)
    
    def next_move(self):
        """
        Calculates possible moves for the current board
        configuration.
        """
        vacant_tableau = False
        king_waiting = False
        
        # Check if there are runs starting with a King
        # in any of the Tableau piles, so that they may be
        # moved to empty Tableau piles.
        for tab in self.board.tableaux:
            if tab.is_empty():
                vacant_tableau = True
            else:
                for card in tab:
                    if card.is_face_down():
                        continue
                    if card.rank == Rank.KING:
                        if card == tab.peek():
                            continue
                        king_waiting = True
                        break
        
        # Check if there is a King at the top of the
        # Waste pile so that it may be moved to an empty
        # Tableau pile.
        if not self.board.waste.is_empty():
            card = self.board.waste.peek()
            if card.rank == Rank.KING:
                king_waiting = True

        # The next step is to try to move one column to another 
        # column. Non-empty columns (columns which contain face-down
        # cards) are moved first, because we want to free up
        # whatever cards may be hidden.
        for tab in self.board.tableaux:
            if tab.contains_face_down():
                bottom = tab.first_face_up_card()
                idx = tab.index(bottom)
                for tab2 in self.board.tableaux:
                    if tab2 == tab:
                        continue
                    if tab2.is_empty():
                        if bottom.rank == Rank.KING:
                            # Tell the player to move the King in tab
                            # to the empty tab2
                            print "Move %s from %s to %s" % (str(bottom), tab.name, tab2.name)
                            return
                    else:
                        if tab2.suitable_pile_push(tab[idx:]):
                            print "Move %s from %s to %s" % (str(bottom), tab.name, tab2.name)
                            return

        # If a Tableau containing face-down cards cannot be moved, try
        # to move a Tableau pile without face-down cards, but only if
        # a King is waiting.
        for tab in self.board.tableaux:
            if tab.is_empty() or tab.contains_face_down():
                continue
            bottom = tab[0]
            if bottom.rank == Rank.KING:
                continue
            for tab2 in self.board.tableaux:
                if tab2 == tab or tab2.is_empty():
                    continue
                elif tab2.suitable_pile_push(tab):
                    if not vacant_tableau and king_waiting:
                        print "Move %s to %s" % (tab.name, tab2.name)
                        return

        # If we can't move piles from Tableau to Tableau,
        # we try moving a card from Waste to a Tableau.
        if not self.board.waste.is_empty():
            top = self.board.waste.peek()
            
            # If the top of the Waste pile is a King, move
            # it to an empty Tableau pile. Otherwise, if it
            # can go on a nonempty Tableau pile, push it there.
            for tab in self.board.tableaux:
                if tab.is_empty():
                    if top.rank == Rank.KING:
                        print "%i: " % lineno(), "Move %s from %s to %s" % (str(top), self.board.waste.name, tab.name)
                        return
                    else:
                        if tab.suitable_card_push(top):
                            print "Move %s from %s to %s" % (str(top), self.board.waste.name, tab.name)
                            return
            
            # If the top of Waste cannot go on any Tableau piles,
            # try moving it to its Foundation pile.
            fpile = self.board.foundations[top.suit]
            if fpile.suitable_card_push(top):
                print "Move %s from %s to %s" % (str(top), self.board.waste.name, fpile.name)
                return
            
            # Otherwise, try to move the card of the same rank and color
            # on a Tableau pile to its Foundation pile so the top of Waste
            # can take its place on the Tableau.
            for tab in self.board.tableaux:
                if tab.is_empty():
                    continue
                card = tab.peek()
                fpile2 = self.board.foundations[card.suit]
                if (card.color == top.color and 
                    card.rank == top.rank and 
                    fpile2.suitable_card_push(card)):
                    print "Move %s from %s to %s" % (str(card), tab.name, fpile2.name)
                    return

        # If a Tableau pile contains many cards, try to reduce
        # its size by moving the top cards to their Foundation
        # piles.
        # If a Tableau pile contains only one card, try to move
        # it to its Foundation pile to free it up for waiting
        # Kings. If it can't go to a Foundation pile, then try
        # putting the card of same rank and color on its foundation.
        for tab in self.board.tableaux:
            if tab.is_empty():
                continue
            if len(tab) > 1:
                if king_waiting:
                    card = tab.peek()
                    fpile = self.board.foundations[card.suit]
                    if fpile.suitable_card_push(card):
                        print "Move %s from %s to %s" % (str(card), tab.name, fpile.name)
                        return
            elif len(tab) == 1:
                card = tab.peek()
                fpile = self.board.foundations[card.suit]
                if fpile.suitable_card_push(card):
                    print "Move %s from %s to %s" % (str(card), tab.name, fpile.name)
                    return
                else:
                    for tab2 in self.board.tableaux:
                        if tab == tab2 or tab2.is_empty():
                            continue
                        card2 = tab2.peek()
                        if card.color() == card2.color() and card.rank == card2.rank:
                            fpile2 = self.board.foundations[card2.suit]
                            if fpile2.suitable_card_push(card2):
                                print "Move %s from %s to %s" % (str(card2), tab2.name, fpile2.name)
                                return

        # Try moving cards in the Tableaux to
        # their Foundation piles.
        for tab in self.board.tableaux:
            if tab.is_empty():
                continue
            card = tab.peek()
            fpile = self.board.foundations[card.suit]
            if fpile.suitable_card_push(card):
                print "Move %s from %s to %s" % (str(card), tab.name, fpile.name)
                return

        # Draw from the stock if we couldn't move any cards.
        if not self.board.stock.is_empty():
            print "Draw cards from the Stock pile."
            return

        # No moves, give up!
        print "There are no moves left, try pressing undo or starting a new game!"
    
    def can_autocomplete(self):
        """
        Returns true if the Cards in the Piles are ordered
        such that the game can be auto-completed.
        """
        if not self.board.stock.is_empty():
            return False
        prev_rank = 14
        for card in self.board.waste:
            if card.rank > prev_rank:
                return False
            prev_rank = card.rank
        
        for tab in self.board.tableaux:
            if tab.contains_face_down():
                return False
        return True
    
    def all_empty(self):
        """
        Returns true if the Waste and Tableaux 
        piles are both empty.
        """
        piles = []
        piles.append(self.board.waste)
        piles.extend(self.board.tableaux)
        for pile in piles:
            if not pile.is_empty():
                return False
        return True
    
    def autocomplete(self):
        """
        Autocompletes the board as much as possible.
        """
        piles = []
        piles.append(self.board.waste)
        piles.extend(self.board.tableaux)
        
        all_empty = self.all_empty()
        while not all_empty:
            for pile in piles:
                if pile.is_empty():
                    continue
                card = pile.peek()
                self.to_foundation(card, pile)
            all_empty = self.all_empty()
            
            
Пример #21
0
 def __init__(self, game):
     super(Spoons, self).__init__(game)
     self.initHandCount = 4
     self.env['trash'] = Pile()
Пример #22
0
 def __init__(self, deck_size, deck_w_jokers, deck_wo_queens, num_players, start_hand_size, direction):
     super(OldmaidEnv, self).__init__(deck_size, deck_w_jokers, deck_wo_queens, num_players, start_hand_size, direction)
     self.trash = Pile()
     self.pass_pile = Pile()
Пример #23
0
 def __init__(self, deck_size, deck_w_jokers, num_players, start_hand_size, direction):
     super(SevensEnv, self).__init__(deck_size, deck_w_jokers, num_players, start_hand_size, direction)
     self.spades_layout = Pile()
     self.diamonds_layout = Pile()
     self.clubs_layout = Pile()
     self.hearts_layout = Pile()
Пример #24
0
class Game:
    "The Board State"

    def start(self):
        "begin a new game of Dominoes"
        print("Welcome to Dominoes!", end="\n\n")
        self.setup_game()

    def setup_game(self):
        self.pile = Pile()
        self.board = Board()
        self.create_players()
        self.deal()
        self.set_starting_tile()
        self.play()

    def create_players(self):
        "creates 2 new players: Athur and Dutch"
        self.players = [Player('Arthur Morgan'), Player('Dutch')]

    def deal(self):
        "deal 7 domninoes to each player, one at a time"
        for i in range(7):
            domino_1 = self.pile.take_domino()
            self.players[0].add_domino(domino_1)
            domino_2 = self.pile.take_domino()
            self.players[1].add_domino(domino_2)
        print('\n')

    def set_starting_tile(self):
        "sets the starting tile on the board"
        domino = self.pile.take_domino()
        self.board.add_domino(domino)

    def play(self):
        "start the game, manages turns and win state"
        self.game_end = False
        p = 0
        while (not self.game_end):
            turn_outcome = self.turn(self.players[p])
            if turn_outcome == 'next':
                p = 1 if p == 0 else 0
            if turn_outcome == 'blocked':
                print('Blocked! players cannot continue')
                dot_count_1 = self.dot_count((self.players[0]).hand)
                dot_count_2 = self.dot_count((self.players[1]).hand)
                print((self.players[0]).name + "'s hand count is " +
                      str(dot_count_1))
                print((self.players[1]).name + "'s hand count is " +
                      str(dot_count_2))

                if (dot_count_1 < dot_count_2):
                    print((self.players[0]).name + ' Wins!')
                else:
                    print((self.players[1]).name + ' Wins!')
                self.game_end = True
            if turn_outcome == 'domino':
                print('Domino!')
                print((self.players[p]).name + ' Wins!')
                self.game_end = True

    def dot_count(self, hand):
        "counts the value of a players hand to tally up a score"
        count = 0
        for domino in hand.dominoes.values():
            count += domino.value_1
            count += domino.value_2
        return count

    def turn(self, player):
        "a single turn. validates what the turn outcome is "
        if len(player.hand.dominoes) == 0:
            return 'domino'
        if len(self.pile.dominoes) > 0:
            new_domino = self.pile.take_domino()
            player.add_domino(new_domino)
        if self.has_valid_moves(player.hand):
            domino, position = self.make_move(player)
            self.place_domino(player, domino, position)
        else:
            print(len(self.pile.dominoes), len(player.hand.dominoes))
            if len(self.pile.dominoes) == 0:
                if (not self.has_valid_moves((self.players[0]).hand)
                        and not self.has_valid_moves((self.players[1]).hand)):
                    return 'blocked'
            else:
                print("No valid moves, draw again.")
                self.turn(player)
        return 'next'

    def make_move(self, player):
        "a player move selection pool"
        valid_moves = self.get_valid_moves(player.hand)
        move_display = list(
            map(
                lambda move: 'PLACE ' +
                (move["domino"]).show() + ' ' + move["placement"],
                valid_moves))
        move, index = pick(move_display, self.get_selection_heading(player))
        player_move = valid_moves[index]
        return (player_move['domino'], player_move['placement'])

    def place_domino(self, player, domino, position):
        "placement of a player's domino onto the board"
        player.remove_domino(domino.id)
        self.board.add_domino(domino, position)
        print(str(player.name) + " places down domino " + str(domino))

    def get_selection_heading(self, player):
        "provide information of the game state while a player makes a move"
        player_details = str(player.name) + "'s Turn"
        board = "\nBoard:\n" + str(self.board)
        hand = "\n\nHand\n" + str(player.hand)
        title = "\n\nSelect a valid move:\n"
        return player_details + board + hand + title

    def has_valid_moves(self, hand):
        "validates if a player can maka a valid move"
        return len(self.get_valid_moves(hand)) > 0

    def get_valid_moves(self, hand):
        "returns a players valid moves"
        first = self.board.dominoes[0]
        last = self.board.dominoes[-1]
        moves = []
        for domino in hand.dominoes.values():
            if (domino.value_1 == first.value_1
                    or domino.value_2 == first.value_1):
                moves.append({"domino": domino, "placement": "LEFT"})
            if (domino.value_1 == last.value_2
                    or domino.value_2 == last.value_2):
                moves.append({"domino": domino, "placement": "RIGHT"})
        return moves
Пример #25
0
 def construct_piles_subseqs(self):
     """
     This method handles most of this program's tasks. It creates 
     the Piles of Cards on the table from the Cards dealt from the 
     Deck. It also places the Card in its correct position in the 
     list of SubSequences, linking it to the top Card from the 
     previous Pile.
     
     The Algorithm:
     
     A. Outer Loop for each Card in the Deck
        1. Retrieve the Card from the Deck: card_from_deck
        2. Set a flag to indicate if we place the 
           card_from_deck in an existing Pile
        3. Inner Loop through each Pile starting from the 
           leftmost Pile - Python list index 0 - to find the
           correct one on which to place the card_from_deck
           a. Obtain a reference to the top Card on the current 
              Pile(Stack): See Pile methods
           b. If there exists a Pile whose top Card is higher 
              than the card_from_deck, then
              1.   Add the card_from_deck onto the Pile: See Pile methods
              ii.  Set the flag to say we have found a Pile on 
                   which to place the card_from_deck
              iii. Obtain a reference to the top Card on the 
                   previous Pile - the one to the left of where 
                   you just placed the card_from_deck: (one less 
                   index value in Python list): 
                   This needs to be a if / else block:
                   if the pile has an index of 0, then prev_card = None
                   else prev_card = top Card on the previous Pile
              iv. Add the card_from_deck to the list of 
                  SubSequences using the add_card_to_subseq method
              v.   Break out of loop
        4. Check the flag:
           If we haven't found a place for the card_from_deck 
           in an existing Pile, then
           a. Create a new Pile (in Python list of Piles)
           b. Obtain a reference to the top Card on the 
              previous Pile - the one to the left of where 
              you just placed the card_from_deck: (one less 
              index value in Python list): 
              This needs to be a if / else block:
              if the pile has an index of 0, then prev_card = None
              else prev_card = top Card on the previous Pile
           c. Add the card_from_deck to the list of SubSequences 
              using the add_card_to_subseq method
           d. Push the card_from_deck onto the Pile
           e. Add the new pile to the pile list
     """
     for i in range(self.CARDS_IN_DECK):
         card_from_deck = self.__deck.dequeue()
         flag = 0
         while flag < 5:
             for t in range(len(self.__piles)):
                 top = self.__piles[t].get_top_card()
                 if top.compare(card_from_deck) == 1:
                     self.__piles[t].add_card(card_from_deck)
                     if len(self.__piles[t - 1]) == 0:
                         prev_card = None
                     else:
                         prev_card = self.__piles[t - 1].get_top_card()
                         self.add_card_to_subseq(card_from_deck, prev_card)
                     flag += 5
                     break
             if flag == 0:
                 self.__piles.append(Pile())
                 if len(self.__piles) <= 1:
                     prev_card = None
                 else:
                     prev_card = self.__piles[len(self.__piles) -
                                              2].get_top_card()
                 self.add_card_to_subseq(card_from_deck, prev_card)
                 self.__piles[len(self.__piles) - 1].push(card_from_deck)
             flag += 5
Пример #26
0
 def __init__(self, name, id_, max_size=MAX_SIZE):
     self.name = name
     self.id = id_
     self.hand = Pile()
     self.knowledge = []
     self.points = 0
Пример #27
0
 def _parse_page(self, page):
     print 'parsing page ' + str(page.pageid)
     pile = Pile()
     pile.parse_layout(page)
     piles = pile.split_piles()
     return piles
Пример #28
0
    def __init__(self):
        # create and shuffle deck
        self.gameDeck = Deck()
        self.gameDeck.createDeck()
        self.gameDeck.shuffleDeck()

        # initialize piles
        self.handPile = Pile("h", self.gameDeck.cards[:])
        self.wastePile = Pile("w", []) 
        self.foundationsPiles = [
            Pile("f", []),
            Pile("f", []),
            Pile("f", []),
            Pile("f", []) 
        ]
        self.tableauPiles = [
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", [])
        ]
Пример #29
0
	def _parse_page(self, page):
		print 'parsing page '+str(page.pageid)
		pile = Pile()
		pile.parse_layout(page)
		piles = pile.split_piles()
		return piles
Пример #30
0
    def load_piles(self, display_size):
        display_width, display_height = display_size
        pile_spacing = 50

        start_x = 50
        start_y = self.card_size[1] + 100

        foundation_x_step = self.card_size[0] + pile_spacing
        foundation_start_x = display_width - (foundation_x_step * 4)

        tableau1 = Pile([self.cards[0]], start_x, start_y, self.card_size)
        tableau2 = Pile(self.cards[1:3],
                        start_x + self.card_size[0] + pile_spacing, start_y,
                        self.card_size)
        tableau3 = Pile(self.cards[3:6],
                        start_x + self.card_size[0] * 2 + pile_spacing * 2,
                        start_y, self.card_size)
        tableau4 = Pile(self.cards[6:10],
                        start_x + self.card_size[0] * 3 + pile_spacing * 3,
                        start_y, self.card_size)
        tableau5 = Pile(self.cards[10:15],
                        start_x + self.card_size[0] * 4 + pile_spacing * 4,
                        start_y, self.card_size)
        tableau6 = Pile(self.cards[15:21],
                        start_x + self.card_size[0] * 5 + pile_spacing * 5,
                        start_y, self.card_size)
        tableau7 = Pile(self.cards[21:28],
                        start_x + self.card_size[0] * 6 + pile_spacing * 6,
                        start_y, self.card_size)

        stock = Pile(self.cards[28:],
                     start_x,
                     pile_spacing,
                     self.card_size,
                     pile_type="stock")
        waste = Pile([],
                     start_x + self.card_size[0] + pile_spacing,
                     pile_spacing,
                     self.card_size,
                     pile_type="waste")

        foundation1 = Pile([],
                           foundation_start_x,
                           pile_spacing,
                           self.card_size,
                           pile_type="foundation")
        foundation2 = Pile([],
                           foundation_start_x + foundation_x_step,
                           pile_spacing,
                           self.card_size,
                           pile_type="foundation")
        foundation3 = Pile([],
                           foundation_start_x + foundation_x_step * 2,
                           pile_spacing,
                           self.card_size,
                           pile_type="foundation")
        foundation4 = Pile([],
                           foundation_start_x + foundation_x_step * 3,
                           pile_spacing,
                           self.card_size,
                           pile_type="foundation")

        self.piles = [
            tableau1, tableau2, tableau3, tableau4, tableau5, tableau6,
            tableau7, stock, waste, foundation1, foundation2, foundation3,
            foundation4
        ]
Пример #31
0
 def _parse_page(self, page):
     pile = Pile()
     pile.parse_layout(page)
     piles = pile.split_piles()
     return piles
Пример #32
0
 def __init__(self, decks=1, seed=None):
     self.pile1, self.pile2 = Pile(decks).shuffle(seed).split()
Пример #33
0
    def construct_piles_subseqs(self):
        """
        This method handles most of this program's tasks. It creates 
        the Piles of Cards on the table from the Cards dealt from the 
        Deck. It also places the Card in its correct position in the 
        list of SubSequences, linking it to the top Card from the 
        previous Pile.
        
        The Algorithm:
        
        A. Outer Loop for each each Card in the Deck
           1. Retrieve the Card from the Deck: card_from_deck
           2. Set a flag to indicate if we place the 
              card_from_deck in an existing Pile
           3. Inner Loop through each Pile starting from the 
              leftmost Pile - Python list index 0 - to find the
              correct one on which to place the card_from_deck
              a. Obtain a reference to the top Card on the current 
                 Pile(Stack) using peek
              b. If there exists a Pile whose top Card is higher 
                 than the card_from_deck, then
                 i.   Set the flag to say we have found a Pile on 
                      which to place the card_from_deck
                 ii.  Obtain a reference to the top Card on the 
                      previous Pile - the one to the left of where 
                      you just placed the card_from_deck: (one less 
                      index value in Python list) using peek
                 iii. Add the card_from_deck to the list of 
                      SubSequences using the add_card_to_subseq 
                      method
                 iv.  Push the card_from_deck onto the Pile
           4. Check the flag:
              If we haven't found a place for the card_from_deck 
              in an existing Pile, then
              a. Create a new Pile (in Python list of Piles (Stacks)
              b. Obtain a reference to the top Card on the previous 
                 Pile - the one to the left of where you just placed 
                 the card_from_deck: (one less index value in Python 
                 list) using peek - unless this first Card from the 
                 Deck, when the number of Piles are zero, using len 
                 function.
              c. Add the card_from_deck to the list of SubSequences 
                 using the add_card_to_subseq method
              d. Push the card_from_deck onto the Pile
        """
        for card in range(self.CARDS_IN_DECK):
            card_from_deck = self.__deck.deal()
            flag = False
            prev_card = None
            if len(self.__piles) > 0:

                for i in range(len(self.__piles)):
                    top_card = self.__piles[i].get_top_card()
                    if top_card.compare(card_from_deck) > 0:
                        flag = True
                        if i > 0:
                            prev_card = self.__piles[i - 1].get_top_card()
                        self.add_card_to_subseq(card_from_deck, prev_card)
                        self.__piles[i].add_card(card_from_deck)
                        break
            if flag is not True:
                pile = Pile()
                if len(self.__piles) > 0:
                    prev_card = self.__piles[len(self.__piles) -
                                             1].get_top_card()
                self.add_card_to_subseq(card_from_deck, prev_card)
                pile.add_card(card_from_deck)
                self.__piles.append(pile)
Пример #34
0
class Game:

    def __init__(self):
        # create and shuffle deck
        self.gameDeck = Deck()
        self.gameDeck.createDeck()
        self.gameDeck.shuffleDeck()

        # initialize piles
        self.handPile = Pile("h", self.gameDeck.cards[:])
        self.wastePile = Pile("w", []) 
        self.foundationsPiles = [
            Pile("f", []),
            Pile("f", []),
            Pile("f", []),
            Pile("f", []) 
        ]
        self.tableauPiles = [
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", []),
            Pile("t", [])
        ]

    def displayCards(self):
        print("=" * 150)

        print("[h]  || " + str(self.handPile))
        print("-" * 150)

        print("[w]  || " + str(self.wastePile))
        print("-" * 150)

        for i, foundationsPile in enumerate(self.foundationsPiles):
            print("[f" + str(i + 1) + "] || ", end="")
            print(foundationsPile)
        print("-" * 150)

        for i, tableauPile in enumerate(self.tableauPiles):
            print("[t" + str(i + 1) + "] || ", end="")
            print(tableauPile)
        print("-" * 150)

    def gameLoop(self):
        
        # insert cards from hand pile into tableau piles
        for n, tableauPile in enumerate(self.tableauPiles):
            tableauPile.insertCardFrom(self.handPile, n + 1)

        keyMap = {
            "h": self.handPile,
            "w": self.wastePile,
            "f1": self.foundationsPiles[0],
            "f2": self.foundationsPiles[1],
            "f3": self.foundationsPiles[2],
            "f4": self.foundationsPiles[3],
            "t1": self.tableauPiles[0],
            "t2": self.tableauPiles[1],
            "t3": self.tableauPiles[2],
            "t4": self.tableauPiles[3],
            "t5": self.tableauPiles[4],
            "t6": self.tableauPiles[5],
            "t7": self.tableauPiles[6]
        }

        while (True):
            # flip top card in waste pile
            if (not self.wastePile.isEmpty()):
                self.wastePile.cards[-1].flip()

            # flip top card in tableau piles
            for tableauPile in self.tableauPiles:
                if (not tableauPile.isEmpty()):
                    tableauPile.cards[-1].flip()

            self.displayCards()

            """
            # quiting
            while True:
                action = input("[continue (c) or quit (q)] || ")
                if (action == "c" or action == "q"):
                    break
            """

            action = "c"

            if (action == "c"):
                # prompt user for input 
                while True:
                    try: 
                        fromPile = keyMap[input("[move from]  || ")]
                        break
                    except:
                        continue

                while True:
                    try: 
                        toPile = keyMap[input("[move to]    || ")]
                        break
                    except:
                        continue

                if (fromPile.label == "t" and toPile.label == "t"):
                    while True: 
                        try: 
                            numOfCards = int(input("[# of cards] || "))
                            break
                        except:
                            continue
                else: 
                    numOfCards = 1

                # commit move 
                if (toPile.isValidMove(fromPile, numOfCards)):
                    toPile.insertCardFrom(fromPile, numOfCards)
                    print("--- move executed ---")
                else:
                    print("--- move failed ---")

                # if game is won
                if (len(self.foundationsPiles[0].cards) == 13 and len(self.foundationsPiles[1].cards) == 13 and len(self.foundationsPiles[2].cards) == 13 and len(self.foundationsPiles[3].cards) == 13):
                    self.displayCards()
                    print("--- congratulations, you won! ---")
                    break

            elif (action == "q"):
                print("--- exited ---")  
                break
Пример #35
0
    def _init_piles(self) -> [Pile]:
        '''
        Initializes a new list of piles randomly. Used 
        when starting a new game
        '''
        cards = self._generate_random_deck()
        piles = []

        piles.append(Pile('tableau', [cards[0]], number=0))
        piles.append(Pile('tableau', cards[1:3], number=1))
        piles.append(Pile('tableau', cards[3:6], number=2))
        piles.append(Pile('tableau', cards[6:10], number=3))
        piles.append(Pile('tableau', cards[10:15], number=4))
        piles.append(Pile('tableau', cards[15:21], number=5))
        piles.append(Pile('tableau', cards[21:28], number=6))

        piles.append(Pile('stock', cards[28:]))
        piles.append(Pile('waste'))

        piles.append(Pile('foundation', number=0))
        piles.append(Pile('foundation', number=1))
        piles.append(Pile('foundation', number=2))
        piles.append(Pile('foundation', number=3))

        return piles
Пример #36
0
class Player(object):

    """This class represents a player that plays the game."""

    def __init__(self, name, game, id):
        self.name = name
        self.id = id
        self.actions = 0
        self.buys = 0
        self.money = 0
        self.score = 0
        self.potion = 0
        self.game = game
        self.hand = Pile()
        self.board = Pile()
        self.deck = Pile()
        self.durations = Pile()
        self.drawpile = Pile()
        self.discardpile = Pile()
        self.island = Pile()
        self.nativeVillage = Pile()
        self.pirateShip = 0

    def move_card_to_pile(self, card, target_pile):
        """Moves a card from the draw pile, the discard pile, or the hand to another target pile"""

        for p in (self.drawpile, self.discardpile, self.hand):
            if card in p:
                p.remove(card)
        target_pile.add(card)

    def create_info(self):
        """Creates an PlayerInfo-Object containing public informations about this player"""

        return PlayerInfo(
            self.name,
            len(self.hand),
            len(self.drawpile),
            len(self.discardpile),
            self.actions,
            self.buys,
            self.money,
            self == self.game.active_player,
            self.score,
            self.potion,
            self.id,
            )

    def can_do_action(self):
        """Indicates if the player can play an action card"""

        return self.actions > 0 and len([c for c in self.hand if c.cardtype &
                ACTION]) > 0

    def play_card(self, card_id):
        """Play the given card"""

        card = [card for card in self.hand if card.id == card_id]
        if not card:
            raise CardNotInHandException("Can't play %s" % card_id)
        card = card[0]
        self.hand.remove(card)
        self.board.add(card)

    def discard_card(self, card):
        """Discards the given card from the hand"""

        if not card in self.hand:
            raise CardNotInHandException("Can't discard %s" % card)
        self.hand.remove(card)
        self.discardpile.add(card)

    def put_on_drawpile(self, card):
        if card:
            self.deck.add(card)
            self.drawpile.add(card)

    def trash_card(self, card):
        """Remove a card from the deck and put it onto the games trashpile"""

        try:
            self.game.trash.add(self.deck.remove(card))
        except ValueError:
            pass
        try:
            self.game.trash.add(self.board.remove(card))
        except ValueError:
            pass
        try:
            self.game.trash.add(self.hand.remove(card))
        except ValueError:
            pass
        try:
            self.game.trash.add(self.discardpile.remove(card))
        except ValueError:
            pass
        try:
            self.game.trash.add(self.durations.remove(card))
        except ValueError:
            pass

    def take_card(self, card, to_hand=False, to_deck=False):
        """Take a card and put in into the discard pile or hand or deck"""

        self.deck.add(card)

        if to_hand:
            self.hand.add(card)
        elif to_deck:
            self.drawpile.add(card)
        else:
            self.discardpile.add(card)

    def draw_card(self, just_reveal=False):
        """Draw a card. If the drawpile is empty, shuffle the discardpile into
    the drawpile and try again. If the drawpile is still empty, do nothing"""

        card = None
        try:
            card = self.drawpile.take()
        except PileIsEmptyException:
            self.discardpile.shuffle_into(self.drawpile)
            try:
                card = self.drawpile.take()
            except PileIsEmptyException:
                pass

        if card and not just_reveal:
            self.hand.add(card)
        return card
Пример #37
0
class Broker():
    """
    This class plays the Buy, Sell, or Negotiate card game.
    It has a Deck, a Pile and two Players as instance variables.
    It also contains an instance variable for counting the number
    of rounds and negotiations and which Player won them.
    It contains an optional parameter that you can set to stop
    the play after a certain number of rounds, called limit.

    """
    def __init__(self, limit=1000):
        """
        Here is the algorithm for class construction:
        1. Initializes round limit.
        2. Creates the Deck and Pile.
        3. Creates both Players and places them in a list.
        4. Creates the lists holding round and negotiation counts.
        """

        # 1. Initialize round limit

        self.__limit = limit

        # 2. Creates the Deck and Pile

        self.__deck = Deck()
        self.__pile = Pile()

        # 3. Creates both Players and places them in a list

        self.__players = [None, Player(), Player()]

        # 4. Creates the lists holding round and negotiation counts

        self.__round_wins = [0, 0, 0]

    def setup(self):
        """
        Here is the algorithm for game setup:
        1. Initializes the Deck.
        2. Shuffles the Deck 5 times and displays it.
        3. Deals the Cards.
        4. Displays the dealt Hands.
        """

        print("=============SETUP===============")

        # 1. Initializes the Deck

        print("The new deck:")
        self.__deck.initialize()

        # 2. Shuffles the Deck 5 times and displays it

        for d in range(5):
            self.__deck.shuffle()
        print("The shuffled deck:")
        print(self.__deck)

        # 3. Deals the cards

        for c in range(26):
            for p in range(1, 3):
                card = self.__deck.deal()
                player = self.__players[p]
                player.add_card(card)

        # 4. Displays the dealt hands

        print("Original hands:")
        for p in range(1, 3):
            player = self.__players[p]
            print("Player{}:".format(p))
            player.display_hand()

    def play(self):
        """
        Here is the algorithm for playing a game:
          Loop for each round of play
          Game ends when someone wins or after round limit
          1. Each player plays a Card to the pile
             Display the first two top Cards on the Pile
          2. Call determine_pile_winner to determine the winner
             Winner is returned as player number (1 or 2)
             or 0, if cards are equal
          3. If Cards are equal,
             winner is determined through negotiation
             If Cards are not equal, winner gets pile
             A. Cards are equal:
                If both players have at least one Card,
                Call negotiate to determine winner
             B. One player does not have enough Cards,
                use Coin flip to see if he survives
          4. Cards are not equal: winning Player adds Pile to Hand
          5. Check for game over: meaning a Player has no Cards
          6. Increment the number of rounds
        """

        print("=============== PLAY ===============")

        rounds = 1
        game_over = False

        # Loop for each round of play
        # Game ends when someone wins or after round limit

        while not game_over and rounds <= self.__limit:

            print("\nRound{}: ".format(rounds))

            # 1. Each player plays a Card to the pile
            #    Display the first two top Cards on the Pile

            for p in range(1, 3):
                player = self.__players[p]
                player.play_card(self.__pile)

            p1_card, p2_card = self.__pile.top_two_cards()

            print("Player1: Card: " + str(p1_card))
            print("Player2: Card: " + str(p2_card))

            # 2. Call determine_pile_winner to determine the winner
            #    Winner is returned as player number (1 or 2)
            #    or 0, if cards are equal

            winner = self.determine_pile_winner()
            print("Winner: Player" + str(winner))

            # 3. If Cards are equal,
            #    winner is determined through negotiation
            #    If Cards are not equal, winner gets pile

            if winner == 0:
                print("\nLet the NEGOTIATIONs Begin!!!")

                # A. Cards are equal:
                #    If both players have at least one Card,
                #    Call negotiate to determine winner

                p1_num_cards = self.__players[1].get_num_cards()
                p2_num_cards = self.__players[2].get_num_cards()

                if (p1_num_cards >= 1) and (p2_num_cards >= 1):
                    winner = self.negotiate()

                    print("Winner: Player" + str(winner))
                    if winner == 0:
                        game_over = self.use_coin_flip_for_neg()
                    else:
                        self.__players[winner].add_pile(self.__pile)

                # B. One player does not have enough Cards,
                #    use Coin flip to see if he survives
                else:
                    game_over = self.use_coin_flip_for_neg()

            # 4. Cards are not equal: winning Player adds Pile to Hand

            else:
                self.__players[winner].add_pile(self.__pile)

            self.__round_wins[0] += 1
            self.__round_wins[winner] += 1

            # 5. Check for game over: meaning a Player has no Cards

            if (self.__players[1].get_num_cards() == 0
                    or self.__players[2].get_num_cards() == 0):
                game_over = True

            # 6. Increment the number of rounds

            rounds += 1

    def determine_pile_winner(self):
        """
        Here is the algorithm for determining a pile winner:
          1. Retrieve the top two Cards from the Pile
          2. Compare the Cards:
             A. Cards are equal:
                Return winner = 0
             B. Flip Coin to see whether the low Card
                or the high Card wins the play
                1. If the flip is heads, make high card holder the winner
                2. If the flip is tails, make low card holder the winner
        """

        # 1. Retrieve the top two Cards from the Pile

        p1_card, p2_card = self.__pile.top_two_cards()

        # 2. Compare the Cards:

        compare_result = p1_card.compare(p2_card)

        if compare_result == 0:

            # A. Cards are equal:
            #    Return winner = 0

            return 0

        else:

            # B. Flip Coin to see whether the low Card
            #    or the high Card wins the play

            face = Coin().flip()
            print("Face: {}".format(face))

            # 1. If the flip is heads, make high card holder the winner

            if face == "Heads":

                if compare_result > 0:
                    return 1
                else:
                    return 2

                # 2. If the flip is tails, make low card holder the winner

            else:
                if compare_result > 0:
                    return 2
                else:
                    return 1

    def negotiate(self):
        """
        Here is the algorithm for negotiation:
          1. Loop while there is no clear winner (winner == 0)
             A. Loop for each player to play Cards for the Pile,
                up to four Cards, as long as both Players have Cards
                1. If both Players have Cards:
                   Display the first two top Cards on the Pile
                2. Break if a player is out of Cards
             B. Call determine_pile_winner to find who won
                the negotiation
             C. If no clear winner and one player is out of Cards
                then break
          2. Return winner
        """

        # 1. Loop while there is no clear winner (winner == 0)
        #    Clear winner: determine_pile_winner returns 1 or 2

        winner = 0
        while winner == 0:

            # A. Loop for each player to play Cards for the Pile,
            #    up to four Cards

            low_on_cards = False
            for c in range(4):

                # 1. If both Players have Cards,
                #    Display the first two top Cards on the Pile

                if (self.__players[1].get_num_cards() >= 1
                        and self.__players[2].get_num_cards() >= 1):

                    for p in range(1, 3):
                        player = self.__players[p]
                        player.play_card(self.__pile)

                    p1_card, p2_card = self.__pile.top_two_cards()

                    print("Player1: Card: " + str(p1_card))
                    print("Player2: Card: " + str(p2_card))

                # 2. Break if a player is out of Cards

                else:
                    low_on_cards = True
                    break

            # B. Call determine_pile_winner to find who won
            #    the negotiation

            winner = self.determine_pile_winner()

            # C. If no clear winner and one player is out of Cards
            #    then break

            if winner == 0 and low_on_cards:
                break

        # 2. Return winner
        return winner

    def use_coin_flip_for_neg(self):
        """
        When one of the Players has only one Card and the game
        is in negotiation:
        Use a Coin flip to determine who gets the Pile of Cards

        Here is the algorithm for flipping Coin during negotiation:
          1. If the Coin is heads, the Player with the most Cards
             adds the Pile of Cards to his Hand and wins the game
          2. Else the Coin is tails, the Player with the least
             amount of Cards adds the Pile of Cards to his Hand
             and the game is continued
        """

        game_over = False

        print("Using coin flip to settle negotiation")
        face = Coin().flip()
        print("Face: " + str(face))

        p1_num_cards = self.__players[1].get_num_cards()
        p2_num_cards = self.__players[2].get_num_cards()

        # 1. If the Coin is heads, the Player with the most Cards
        #    adds the Pile of Cards to his Hand and wins the game

        if face == "Heads":
            game_over = True

            if p1_num_cards < p2_num_cards:
                winner = 2
            else:
                winner = 1
            self.__players[winner].add_pile(self.__pile)

        # 2. Else the Coin is tails, the Player with the least
        #    amount of Cards adds the Pile of Cards to his Hand
        #    and the game is continued

        else:
            p1_num_cards = self.__players[1].get_num_cards()
            p2_num_cards = self.__players[2].get_num_cards()

            if p1_num_cards > p2_num_cards:
                winner = 2
            else:
                winner = 1

            self.__players[winner].add_pile(self.__pile)

        return game_over

    def display_results(self):
        """
        Displays the game results, when game is over

        Here is the algorithm for displaying results at game end
          1. The game ends when the round limit is reached,
             or a player is out of Cards.
              A. Round limit was reached.
                 The winner is the one with the most Cards.
              B. A player is out of Cards.
                 The winner is the one with all the Cards.
          2. Display Hands, if both players still have Cards.
        """

        print()
        print("========== Game Over - show results ============")

        print()
        print("Number of Rounds:", self.__round_wins[0])
        print("Number of Rounds won by Player 1:", self.__round_wins[1])
        print("Number of Rounds won by Player 2:", self.__round_wins[2])

        # 1. The game ends when the round limit is reached,
        #    or a player is out of Cards

        p1_num_cards = self.__players[1].get_num_cards()
        p2_num_cards = self.__players[2].get_num_cards()

        winner = 0
        if self.__round_wins[0] >= self.__limit:

            # A. Round limit was reached,
            #    The winner is the one with the most Cards

            print("Round limit of {} rounds reached".format(self.__limit))

            if p1_num_cards == p2_num_cards:

                print("Game is tied")

            else:
                if p1_num_cards > p2_num_cards:
                    winner = 1
                else:
                    winner = 2

                print("Player{} has won the game".format(winner))
        else:

            # B. A player is out of Cards
            #    The winner is the one with all the Cards

            if p1_num_cards > p2_num_cards:
                winner = 1
            else:
                winner = 2

            print("Player{} has won the game".format(winner))

        # 2. Display Hands, if both players still have Cards

        if winner == 0 or self.__players[winner].get_num_cards() < 52:
            for p in range(1, 3):
                print("Player{} Cards:".format(p))
                self.__players[p].display_hand()
                print()
Пример #38
0
class Player():
    """__init__
	Default Constructor - Creates a player with the provided name. Also creates the hand
		and knowledge variables
	@param name : String - the name of the player
	@param id : String - a unique player ID in case of overlapping names. In format 
		"name-UNIXtimestamp"
	"""
    def __init__(self, name, id_, max_size=MAX_SIZE):
        self.name = name
        self.id = id_
        self.hand = Pile()
        self.knowledge = []
        self.points = 0

    # ------------------------------------------------------------------------------
    # Public Methods
    """ push(card)
	Push a new card into the player's hand
	@param card : Card - the card to add to the player's hand
	@return : boolean - true if push successful, false if max_size
	"""

    def push(self, card):
        if self.getHandSize() < self.max_size:
            self.hand.push(card)
            return True
        else:
            ERROR.write(
                "Invalid Push: Inserting into player hand would violate max_size."
            )
            return False

    """ push_sort(card)
	Push a new card into the player's hand and sort the hand
	Postcondition: The player's hand is in sorted order
	@param card : Card - the card to add to the player's hand
	@return : boolean - true if successful, false if max_size
	"""

    def push_sort(self, card):
        result = self.push(card)
        self.hand.sort()
        return result

    """ remove(card)
	Remove the specified card from the player's hand
	Postcondition: card no longer exists in the player's hand
	@param card : Card - the card to remove
	"""

    def remove(self, card):
        self.hand.remove(card)

    """ sort()
	Sort the player's hand pile
	"""

    def sort(self):
        self.hand.sort()

    def getID(self):
        return self.id

    def getName(self):
        return self.name

    def getPoints(self):
        return self.points

    def getHandSize(self):
        return len(self.hand)

    def getKnowledge(self):
        return self.knowledge

    def hand_tostr(self):
        return str(self.hand)

    # ------------------------------------------------------------------------------
    # Python Methods

    def __len__(self):
        return len(self.hand)

    def __str__(self):
        return self.name

    def __repr__(self):
        return self.id

    """ __contains__(other)
	Checks if other (a card Object...) is contained within the pile
	Precondition: type(other) == Card
	@param other : Card - the card to check the presence of.
	"""

    def __contains__(self, other):
        if type(other) != type(Card(2, 0)):  # confirm other is a Card
            return False
        elif other in self.hand:  #Check if the card is contained
            return True
        else:
            return False

    def __iter__(self):
        return self.hand.__iter__()

    def __next__(self):
        return self.hand.__next__()

    def __eq__(self, other):
        return self.getID() == other.getID()