First implementation and testing client
parent
3346ca8a3d
commit
1db6116b74
@ -0,0 +1,136 @@
|
|||||||
|
from enum import Enum, auto
|
||||||
|
from random import shuffle
|
||||||
|
|
||||||
|
class Suit(Enum):
|
||||||
|
CLUBS = auto()
|
||||||
|
HEARTS = auto()
|
||||||
|
DIAMONDS = auto()
|
||||||
|
SPADES = auto()
|
||||||
|
|
||||||
|
class Game:
|
||||||
|
def __init__(self):
|
||||||
|
self.foundations = {suit: 1 for suit in Suit}
|
||||||
|
self.deck = self.get_random_pile()
|
||||||
|
self.carpet = set(self.deck[-20:])
|
||||||
|
self.free_cells = 0
|
||||||
|
self.moves = 0
|
||||||
|
self.deck = self.deck[:-20]
|
||||||
|
self.offers = [self.deck.pop()]
|
||||||
|
|
||||||
|
def get_random_pile(self):
|
||||||
|
cards = {(suit, value) for suit in Suit for value in range(2, 13+1)}
|
||||||
|
deck = list(cards)
|
||||||
|
shuffle(deck)
|
||||||
|
return deck
|
||||||
|
|
||||||
|
def can_drop(self, card):
|
||||||
|
suit, value = card
|
||||||
|
return self.foundations[suit] == value - 1
|
||||||
|
# FIXME: use this function.
|
||||||
|
def can_move(self):
|
||||||
|
if len(self.deck) > 0: return True
|
||||||
|
if len(self.offers) > 0 and self.can_drop(self.offers[-1]): return True
|
||||||
|
if any(self.can_drop(card) for card in self.carpet): return True
|
||||||
|
if self.free_cells > 0: return True
|
||||||
|
return False
|
||||||
|
|
||||||
|
def count_move(self):
|
||||||
|
self.moves += 1
|
||||||
|
|
||||||
|
# Possible moves
|
||||||
|
def drop_from_carpet(self, card):
|
||||||
|
if card not in self.carpet:
|
||||||
|
raise ValueError()
|
||||||
|
suit, value = card
|
||||||
|
if self.foundations[suit] != value - 1:
|
||||||
|
raise ValueError()
|
||||||
|
self.count_move()
|
||||||
|
self.carpet.remove(card)
|
||||||
|
self.free_cells += 1
|
||||||
|
self.foundations[suit] = value;
|
||||||
|
def autodrop(self):
|
||||||
|
# This is independent for each suit.
|
||||||
|
for suit in Suit:
|
||||||
|
while (suit, self.foundations[suit]+1) in self.carpet:
|
||||||
|
self.drop_from_carpet((suit, self.foundations[suit]+1))
|
||||||
|
def drop_card_from_offer(self): # to the foundations
|
||||||
|
if len(self.offers) == 0:
|
||||||
|
raise ValueError()
|
||||||
|
offered_card = self.offers[-1]
|
||||||
|
suit, value = offered_card
|
||||||
|
if self.foundations[suit] != value - 1:
|
||||||
|
raise ValueError()
|
||||||
|
self.count_move()
|
||||||
|
self.offers.pop()
|
||||||
|
self.foundations[suit] = value
|
||||||
|
if len(self.offers) == 0 and len(self.deck) > 0:
|
||||||
|
self.count_move()
|
||||||
|
self.offers.append(self.deck.pop())
|
||||||
|
def flip_deck(self):
|
||||||
|
if len(self.deck) == 0:
|
||||||
|
raise ValueError()
|
||||||
|
self.count_move()
|
||||||
|
self.offers.append(self.deck.pop())
|
||||||
|
def get_card_from_deck(self):
|
||||||
|
if len(self.offers) == 0:
|
||||||
|
raise ValueError()
|
||||||
|
if self.free_cells < 1:
|
||||||
|
raise ValueError()
|
||||||
|
self.count_move()
|
||||||
|
self.carpet.add(self.offers.pop())
|
||||||
|
self.free_cells -= 1
|
||||||
|
if len(self.offers) == 0 and len(self.deck) > 0:
|
||||||
|
self.count_move()
|
||||||
|
self.offers.append(self.deck.pop())
|
||||||
|
def game_result(self): # None for not finished, True for win, False for fail
|
||||||
|
if all(self.foundations[suit] == 13 for suit in Suit):
|
||||||
|
return True
|
||||||
|
if self.can_move(): return None
|
||||||
|
return False
|
||||||
|
def print(self):
|
||||||
|
from pprint import pprint
|
||||||
|
# Print game state
|
||||||
|
print(f'Moves: {self.moves}\nFree cells: {self.free_cells}\nCards in deck: {len(self.deck)}\nAvailable card: {self.offers[-1] if len(self.offers) > 0 else "None"}')
|
||||||
|
print('Foundations:')
|
||||||
|
pprint(self.foundations)
|
||||||
|
print('Carpet:')
|
||||||
|
pprint(self.carpet)
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
## A simple testing game:
|
||||||
|
from textwrap import dedent
|
||||||
|
|
||||||
|
game = Game()
|
||||||
|
game.print()
|
||||||
|
while game.game_result() is None:
|
||||||
|
q = input('pafdg? ')
|
||||||
|
try:
|
||||||
|
if q.startswith('p'):
|
||||||
|
game.print()
|
||||||
|
if q.startswith('a'):
|
||||||
|
game.autodrop()
|
||||||
|
if q.startswith('f'):
|
||||||
|
game.flip_deck()
|
||||||
|
if q.startswith('d'):
|
||||||
|
game.drop_card_from_offer()
|
||||||
|
if q.startswith('g'):
|
||||||
|
game.get_card_from_deck()
|
||||||
|
if q.startswith('?'):
|
||||||
|
print(dedent("""\
|
||||||
|
p: print state
|
||||||
|
a: autodrop carpet
|
||||||
|
f: flip deck
|
||||||
|
d: drop from offers
|
||||||
|
g: get from offers
|
||||||
|
?: this help.
|
||||||
|
"""))
|
||||||
|
except ValueError as e:
|
||||||
|
print(e)
|
||||||
|
print('Try again!')
|
||||||
|
print(f'Game ended in {game.moves}.')
|
||||||
|
if game.game_result():
|
||||||
|
print('You won!')
|
||||||
|
else:
|
||||||
|
print('You lost:')
|
||||||
|
game.print()
|
||||||
|
|
Loading…
Reference in New Issue