Example #1
0
 def suitable_pile_pop(self, bottomCard):
     """
     each Card in the pile
     is face-up, the pile alternates in color, and the pile is
     built top down. Additionally, all Cards in the given pile must
     be face-up.
     """
     if bottomCard is None:
         Error.print_error(Error.CARD_IS_NONE, lineno())
         return False
     if bottomCard.is_face_down():
         Error.print_error(Error.CARD_IS_FACE_DOWN, lineno())
         return False
     idx = self.index(bottomCard)
     popped = self[idx:]
     evenColor = bottomCard.color()
     for i in range(len(popped)):
         c = popped[i]
         if c.is_face_down():
             Error.print_error(Error.CARD_IS_FACE_DOWN, lineno())
         if c.rank != bottomCard.rank - i:
             Error.print_error(Error.INVALID_RANK, lineno())
         if i % 2 == 0 and c.color() != evenColor or i % 2 == 1 and c.color() == evenColor:
             Error.print_error(Error.INVALID_COLOR, lineno())
         if (
             c.is_face_down()
             or c.rank != bottomCard.rank - i
             or i % 2 == 0
             and c.color() != evenColor
             or i % 2 == 1
             and c.color() == evenColor
         ):
             return False
     return True
Example #2
0
 def suitable_card_pop(self):
     """
     @todo: commentme
     """
     if self.is_empty():
         Error.print_error(Error.EMPTY_PILE, lineno())
     return not self.is_empty()
Example #3
0
 def enqueue_card(self, card):
     """
     The same as enqueue(), but overwritten by Pile subclasses. Only
     legal for Stock piles.
     """
     if self.suitable_card_enqueue(card):
         return self.enqueue(card)
     Error.print_error(Error.ILLEGAL_ENQUEUE_CARD, lineno())
Example #4
0
 def pop_card(self):
     """
     Equivalent to deque.pop(), but is overridden by Pile subclasses
     for additional functionality.
     """
     if self.suitable_card_pop():
         return self.pop()
     Error.print_error(Error.ILLEGAL_POP_CARD, lineno())
Example #5
0
 def push_card(self, card):
     """
     The same as push(), but is overridden by Pile subclasses to 
     check if pushing the Card to this Pile is legal.
     """
     if self.suitable_card_push(card):
         return self.push(card)
     Error.print_error(Error.ILLEGAL_PUSH_CARD, lineno())
Example #6
0
 def suitable_pile_pop(self, bottomCard):
     """
     @todo: commentme
     """
     if bottomCard is None:
         Error.print_error(Error.CARD_IS_NONE, lineno())
     if not bottomCard in self:
         Error.print_error(Error.CARD_NOT_IN_PILE, lineno())
     return bottomCard is not None and bottomCard in self
Example #7
0
 def push_pile(self, pile):
     """
     Pushes a list of Cards to the top of this Pile, if it is legal 
     to do so. Overridden by subclasses for which pushing a Pile is 
     legal.
     """
     if self.suitable_pile_push(pile):
         return self.extend(pile)
     Error.print_error(Error.ILLEGAL_PUSH_PILE, lineno())
Example #8
0
 def suitable_card_enqueue(self, card):
     """
     Enqueues the specified card to this Pile if it exists and if
     this Pile is not full. Overridden by subclasses.
     """
     if card is None:
         Error.print_error(Error.CARD_IS_NONE, lineno(), False)
     if len(self) >= self.maxlen:
         Error.print_error(Error.EXCEEDS_MAXIMUM, lineno(), False)
     return card is not None and len(self) < self.maxlen
Example #9
0
 def card_at(self, idx):
     """
     Returns the Card at the specified index in this Pile, if the
     index is valid. Otherwise, prints an error message and returns
     None.
     """
     size = len(self)
     if idx >= -size and idx < size:
         return self[idx]
     Error.print_error(Error.INVALID_INDEX, lineno())
Example #10
0
 def suitable_card_push(self, card):
     """
     A suitable card is a card whose value and suit fit them to be
     played or placed onto a pile.
     
     Overridden by subclasses.
     """
     if card is None:
         Error.print_error(Error.CARD_IS_NONE, lineno())
     if len(self) >= self.maxlen:
         Error.print_error(Error.EXCEEDS_MAXIMUM, lineno())
     return card is not None and len(self) < self.maxlen
Example #11
0
 def suitable_pile_enqueue(self, pile):
     """
     A pile is suitable if it can be legally enqueued to this
     Pile.
     """
     if pile is None:
         return Error.print_error(Error.PILE_IS_NONE, lineno(), False)
     if len(pile) == 1:
         return self.suitable_card_enqueue(self, pile[0])
     if len(self) + len(pile) >= self.maxlen:
         Error.print_error(Error.EXCEEDS_MAXIMUM, lineno())
     return (pile is not None and 
             len(self) + len(pile) < self.maxlen)
Example #12
0
 def suitable_pile_push(self, pile):
     """
     A suitable pile is a pile of cards that will be accepted
     upon push.
     
     Overridden by subclasses.
     """
     if pile is None:
         Error.print_error(Error.PILE_IS_NONE, lineno())
     if len(self) + len(pile) >= self.maxlen:
         Error.print_error(Error.EXCEEDS_MAXIMUM, lineno())
     return (pile is not None and 
             len(self) + len(pile) < self.maxlen)
Example #13
0
 def is_complete(self):
     """
     Returns true if this Pile contains all 13 Cards of
     its suit in ascending order.
     """
     for i in range(len(self)):
         card = self[i]
         if card.rank != i + 1:
             Error.print_error(Error.INVALID_RANK, lineno())
         if card.suit != self.suit:
             Error.print_error(Error.INVALID_SUIT, lineno())
         if card.rank != i + 1 or card.suit != self.suit:
             return False
     return len(self) == self.maxlen
Example #14
0
 def index(self, card):
     """
     Returns the index of the specified Card in the Pile, if the 
     Card is in this Pile. Otherwise, prints an error message and
     returns None.
     """
     if card is None:
         return Error.print_error(Error.CARD_IS_NONE, lineno())
     
     # If the card is valid, search for its index in this Pile.
     for i in range(len(self)):
         if self.card_at(i) == card:
             return i
     Error.print_error(Error.CARD_NOT_IN_PILE, lineno())
Example #15
0
 def suitable_pile_pop(self, bottomCard):
     """
     Piles of cards cannot be popped from a Foundation pile.
     """
     if bottomCard == self.peek():
         return True
     return Error.print_error(Error.ILLEGAL_POP_PILE, lineno(), False)
Example #16
0
 def suitable_card_push(self, card):
     """
     Cards may not be pushed onto the Stock pile, with the exception
     of the initial deal. Only Cards from the Waste pile may be 
     enqueued by the dealer to the bottom of the Stock pile.
     """
     return Error.print_error(Error.ILLEGAL_PUSH_CARD, lineno(), False)
Example #17
0
 def suitable_pile_push(self, pile):
     """
     Piles of cards cannot be pushed to a Foundation pile.
     """
     if len(pile) == 1:
         return self.suitable_card_push(pile[0])
     return Error.print_error(Error.ILLEGAL_PUSH_PILE, False)
Example #18
0
 def suitable_pile_pop(self, card):
     """
     Popping a pile of Cards from the Stock pile is not 
     allowed.
     """
     if card == self.peek():
         return True
     return Error.print_error(Error.ILLEGAL_POP_PILE, lineno(), False)
Example #19
0
 def pop_n(self, n):
     """
     Pops and returns a Pile containing the last n Cards at the top
     of this Pile.
     """
     if n > len(self):
         return Error.print_error(Error.TOO_MANY_POPS, lineno())
     
     # Grab the last n cards, and remove them from this Pile.
     popped = self[len(self)-n:]
     for _ in range(n):
         self.pop()
     return popped
Example #20
0
    def suitable_pile_push(self, pile):
        """
        A suitable pile is one that is built down and alternating in
        color. The bottom card in the pile must also be a suitable
        card.
        """
        # Reject pile if it is None, empty, or if its bottom
        # card isn't suitable.
        if pile is None:
            Error.print_error(Error.PILE_IS_NONE, lineno())
        if pile.is_empty():
            Error.print_error(Error.EMPTY_PILE, lineno())
        if pile is None or pile.is_empty() or not self.suitable_card_push(pile[0]):
            return False

        # Reject pile if any card is face-down, or if it is
        # not built correctly, or if it is not alternating in color.
        bottom = pile[0]
        evenColor = bottom.color()
        for i in range(len(pile)):
            c = pile[i]
            if (
                c.is_face_down()
                or c.rank != bottom.rank - i
                or i % 2 == 0
                and c.color() != evenColor
                or i % 2 == 1
                and c.color() == evenColor
            ):
                if c.is_face_down():
                    Error.print_error(Error.CARD_IS_FACE_DOWN, lineno())
                if c.rank != bottom.rank - i:
                    Error.print_error(Error.INVALID_RANK, lineno())
                if i % 2 == 0 and c.color() != evenColor or i % 2 == 1 and c.color() == evenColor:
                    Error.print_error(Error.INVALID_COLOR, lineno())
                return False
        return True
Example #21
0
 def suitable_pile_push(self, pile):
     """
     Piles of Cards cannot be pushed to the top of a Waste
     pile.
     """
     return Error.print_error(Error.ILLEGAL_PUSH_PILE, lineno(), False)
Example #22
0
 def suitable_pile_push(self, pile):
     """
     Pushing a pile of Cards to the Stock pile is not allowed.
     """
     return Error.print_error(Error.ILLEGAL_PUSH_PILE, lineno(), False)
Example #23
0
    def suitable_card_push(self, card):
        """Pushes the given Card to the top of this Pile.
         
        The card is rejected unless it alternates in color and builds
        on the rest of the Pile in a top-down fashion. If this Pile is
        empty, the new Card must be a King.
        """
        # Reject None cards and face-down cards.
        if len(self) >= self.maxlen:
            Error.print_error(Error.EXCEEDS_MAXIMUM, lineno())
        if card is None:
            Error.print_error(Error.CARD_IS_NONE, lineno())
        if card.is_face_down():
            Error.print_error(Error.CARD_IS_FACE_DOWN, lineno())
        if len(self) >= self.maxlen or card is None or card.is_face_down():
            return False

        # If empty, accept only if card is a King. Otherwise, card must
        # build on this Pile's top card and alternate in color.
        if self.is_empty():
            if card.rank != Rank.KING:
                Error.print_error(Error.EXPECTED_KING, lineno())
            return card.rank == Rank.KING
        top = self.peek()
        if card.color() == top.color():
            Error.print_error(Error.INVALID_COLOR, lineno())
        if card.rank != top.rank - 1:
            Error.print_error(Error.INVALID_RANK, lineno())
        return card.color() != top.color() and card.rank == top.rank - 1
Example #24
0
 def enqueue_card(self, card):
     """Cards cannot be inserted to the bottom of a Tableau pile."""
     return Error.print_error(Error.ILLEGAL_ENQUEUE_CARD, lineno())
Example #25
0
 def suitable_card_enqueue(self, card):
     """
     Cards cannot be inserted to the bottom of a
     Foundation pile.
     """
     return Error.print_error(Error.ILLEGAL_ENQUEUE_CARD, lineno(), False)
Example #26
0
 def suitable_card_push(self, card):
     """
     Rejects cards that are of the inappropriate suit or rank for 
     this Pile. The rank of the prospective card must be one higher 
     than the Card at the top of this Pile, or Ace if this Pile is 
     empty. The suit of the prospective Card must match this Pile's 
     suit.
     """
     if len(self) >= self.maxlen:
         Error.print_error(Error.EXCEEDS_MAXIMUM, lineno())
     if card is None:
         return Error.print_error(Error.CARD_IS_NONE, lineno(), False)
     if card.is_face_down():
         Error.print_error(Error.CARD_IS_FACE_DOWN, lineno())
     if card.suit != self.suit:
         Error.print_error(Error.INVALID_SUIT, lineno())
     if (len(self) >= self.maxlen or 
         card is None or card.is_face_down() or 
         card.suit != self.suit):
         return False
     if self.is_empty():
         if card.rank != Rank.ACE:
             Error.print_error(Error.EXPECTED_ACE, lineno())
         return card.rank == Rank.ACE
     top = self.peek()
     if card.rank != top.rank + 1:
         Error.print_error(Error.INVALID_RANK, lineno())
     return card.rank == top.rank + 1