Created
February 22, 2012 10:13
-
-
Save christianp/1883965 to your computer and use it in GitHub Desktop.
A python3 version of the game Mad Abel
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
from itertools import product,combinations,count | |
from random import shuffle,randrange | |
from time import sleep | |
def nicelist(l): | |
if len(l)<=1: | |
return ''.join(l) | |
else: | |
return ', '.join(l[:-1])+' and '+l[-1] | |
class BaseCard: | |
suits = ['hearts','spades','diamonds','clubs'] | |
sorts = ['Ace','2','3','4','5','6','7','8','9','10','Jack','Queen','King'] | |
def __init__(self,a=0,b=0): | |
self.a = a | |
self.b = b | |
def __eq__(c1,c2): | |
return c1.a==c2.a and c1.b==c2.b | |
def __hash__(self): | |
return self.a*4+self.b | |
def __repr__(self): | |
return '%s of %s' % (self.sorts[self.a],self.suits[self.b]) | |
def makeZCard(n): | |
class Card(BaseCard): | |
sorts = [BaseCard.sorts[n-1]]+BaseCard.sorts[:n-1] | |
def __add__(c1,c2): | |
return Card( (c1.a+c2.a) % n, (c1.b+c2.b) % 4) | |
def makeDeck(): | |
return [Card(a,b) for a,b in product(range(n),range(4))] | |
return Card | |
class D6Card(BaseCard): | |
mult = [[0,1,2,3,4,5],[1,0,5,4,3,2],[2,4,3,0,5,1],[3,5,0,2,1,4],[4,2,1,5,0,3],[5,3,4,1,2,0]] | |
sorts = [BaseCard.sorts[5]]+BaseCard.sorts[:5] | |
def __add__(c1,c2): | |
a = D6Card.mult[c2.a][c1.a] | |
b = (c1.b+c2.b) % 4 | |
return D6Card(a,b) | |
def makeDeck(): | |
return [D6Card(a,b) for a,b in product(range(6),range(4))] | |
class Player: | |
def __init__(self,name): | |
self.hand = [] | |
self.name = name | |
def go(self,target,idCard): | |
return [] | |
def __repr__(self): | |
return self.name | |
class HumanPlayer(Player): | |
def go(self,target,idCard): | |
print('Your hand:') | |
for i,c in enumerate(self.hand): | |
print('%i. %s' % (i+1,c)) | |
inp = input('\nWhich cards do you play? ') | |
if inp=='take': | |
return [] | |
return [self.hand[int(i)-1] for i in inp.split(' ') if len(i)] | |
class AutoPlayer(Player): | |
def go(self,target,idCard): | |
for i in range(4,-1,-1): | |
for cards in combinations(self.hand,i): | |
if sum(cards,idCard)==target: | |
return cards | |
return [] | |
class Game: | |
def __init__(self,Card,reporting=True): | |
self.reporting = reporting | |
self.Card = Card | |
self.idCard = Card() | |
self.deck = Card.makeDeck() | |
shuffle(self.deck) | |
self.pile = [] | |
self.play(self.deal(2)) #deal two cards onto the pile | |
self.players = [] | |
def addPlayers(self,*players): | |
for player in players: | |
self.players.append(player) | |
player.hand = self.deal(7) | |
def deal(self,n): | |
if len(self.deck)<n: | |
top = self.pile[-2:] | |
bottom = self.pile[:-2] | |
bottom.reverse() | |
self.deck = bottom + self.deck | |
b=self.deck[-n:] | |
del self.deck[-n:] | |
return b | |
def play(self,cards): | |
self.pile += cards | |
self.target = sum(self.pile[-2:],self.idCard) | |
def report(self,msg,delay=0.2): | |
if self.reporting: | |
print(msg) | |
sleep(delay) | |
def describeTarget(self): | |
self.report('The %s and the %s are on the top of the pile.' % (self.pile[-1],self.pile[-2])) | |
def run(self): | |
start = randrange(len(self.players)) | |
for i in count(): | |
player = self.players[(i+start) % len(self.players)] | |
self.report("Turn %i. %s's go." % (i+1,player)) | |
self.describeTarget() | |
cards = player.go(self.target,self.idCard) | |
while len(cards)>0 and sum(cards,self.idCard)!=self.target: | |
self.report("\nThose cards don't sum to the target. Try again.") | |
self.describeTarget() | |
cards = player.go(self.target,self.idCard) | |
if len(cards)==0: | |
self.report('^^ %s draws two cards from the deck' % player) | |
player.hand += self.deal(2) | |
else: | |
self.report('>> %s plays %s' % (player, nicelist(['the '+str(c) for c in cards]))) | |
self.play(cards) | |
player.hand = [c for c in player.hand if not c in cards] | |
if len(player.hand)==0: | |
self.report('!! %s has no cards left!\n\n%s wins!' % (player,player)) | |
return player | |
self.report('\n',1) | |
def demo(): | |
#size=int(input("How many cards per suit? ")) | |
game = Game(Card=D6Card) | |
game.addPlayers( | |
AutoPlayer('Bot'), | |
HumanPlayer(input('What is your name? ')) | |
) | |
game.run() | |
if __name__ == '__main__': | |
demo() |
Now plays on the dihedral group of order 6.
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
The rules:
From a deck of cards, take those numbered ace to N of all four suits, and throw the rest away.
Deal 4 cards to each player, and two cards face-up in a pile on the table. Put the rest of the deck face-down on the table.
This is a game based on adding cards together.
The sum of a set of cards is:
The suits have the following values:
So in the game where face values go up to 5, the sum of the 3 of diamonds and the 4 of clubs is the 2 of spades.
The target is the sum of the top two cards on the pile. Players take turns to make up the sum using any combination of the cards in their hands. If a player can't make the target, they draw two cards from the deck and the next player takes their turn.
The winner is the first person to get rid of all their cards.