Re: poker card game revisited (code included)

2005-06-16 Thread flupke
John Hazen wrote:
 [Erik Max Francis]
 
Searching for straights and flushes is much better done by masks.
 
 
 Interesting.  I've been thinking about playing with this stuff too, but
 hadn't considered masks.  So each card has a representation:
 
 n bits for rank, then m bits for suit.
 
 10 0001 = 2 clubs
 01 1000 = K spades
 ...
 
 [flupke]
 
As for straights, if i understand correctly, you make all possible 
straights of the cards in the hand and then see if one matches?
 
 
 Yeah, I originally thought that's what you meant, too.  But if you take
 the scheme above, and sort the cards before you merge them into the
 hand-bits aggregate, then you can just have *one* mask for straights,
 and shift it down by a bit each time you check. So the best straight
 mask (A high) would be (ignoring suit bits):
 
 10 01 001000 000100 10
 
 Then this could be shifted right for a K-high straight:
 
 01 001000 000100 10 01
 
 I guess that means that an Ace has to have the following representation,
 since it can be both at the high and low end of a straight:
 
 11 0100 = A hearts
 
 But this may mess with bit-counting shortcuts for other calculations...
 
 This is interesting to think about.  Thanks for the pointer.  I'm also
 going to look at pokersource, though I may put that off until I at least
 partially re-invent the wheel for learning purposes.
 
 -John

I haven't had to much time to play around with it either and i agree 
it's fascinating. However my code now detects high hands properly (need 
to do low hands too and check the wildcards some more. I really need to 
build a test suit) and i find it quite readable code.

Why would you want to start messing with bits in python? It feels like a 
pure c++ approach. Check the way the straight is checked in the code 
posted here. It's very readable and i doubt you can make it as readable 
using bitmasks.

I do think that bitmasks are going to be faster but i could program the 
hand checking stuff fairly quick something that would require a lot more 
work when doing the same with bitmasks. Anyway, i'm still interested in 
that approach and i will try it whenever i've got the time.

Haven't seen a lot of python code that uses bitmasks though. Maybe the 
pokersource C/C++ code can be wrapped in python? :)

Regards,
Benedict
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: poker card game revisited (code included)

2005-06-08 Thread Erik Max Francis
flupke wrote:

 Which projects are you talking about? I only found a library in c to 
 evaluat ranks but i didn't find the code to be very understandable.

pokersource is the main was I was thinking about, yes.

 With histogram do you mean something like this:
 Card hand: 2 clubs, 3 diamonds, 10 of diamonds, 4 of hearts,  3 of hearts
 
 Histogram 1: list [2,3,4,10]
 2 - 14
 Histogram 2: list [1,2,1,0,0,0,0,0,1,0,0,0,0]
 or
 list [1,2,1,1]
 so index 0 is count of rank at index 0 of Histogram 1
 index 1 is count of rank at index 1 of Histogram 1

Histograms usually involve putting things in bins and counting the 
number by bin.  Here the bins are just the ranks of the cards, and so 
you're counting the frequency of the ranks.  Once that's done, you want 
to arrange the frequencies into a mapping of its own, which points to 
the list of ranks that have that frequency.  That way you can easily 
pick things off:  If there is a hit in the four bin, you have quads.  If 
there's a hit in the three bin and either another in the three or one in 
the two bin, you have a boat.  If there's a hit in the three bin but 
_not_ another in three or two, then it's trips.  And so on.

 As for straights, if i understand correctly, you make all possible 
 straights of the cards in the hand and then see if one matches?

Not quite.  You break down the cards by what matters -- ranks and suits 
-- and then make sets based on these.  Then, standing by, you have the 
sets of valid straights (by rank), and then to test for straights, you 
iterate through the straight sets and make intersections with the rank 
set for the hand in question.  If the intersection is the same as the 
straight set, then it's a straight.  (Do this by reverse order of the 
relative values of the straights, and stop when you find the first one, 
to get the highest straight.)  The most efficient way to do this is with 
a bitmask, so that's how it's usually done.

-- 
Erik Max Francis  [EMAIL PROTECTED]  http://www.alcyone.com/max/
San Jose, CA, USA  37 20 N 121 53 W  AIM erikmaxfrancis
   Love is the wisdom of the fool and the folly of the wise.
   -- Samuel Johnson
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: poker card game revisited (code included)

2005-06-08 Thread flupke
Erik Max Francis wrote:
 flupke wrote:
 
 Which projects are you talking about? I only found a library in c to 
 evaluat ranks but i didn't find the code to be very understandable.
 
 
 pokersource is the main was I was thinking about, yes.
 
 With histogram do you mean something like this:
 Card hand: 2 clubs, 3 diamonds, 10 of diamonds, 4 of hearts,  3 of hearts

 Histogram 1: list [2,3,4,10]
 2 - 14   
 Histogram 2: list [1,2,1,0,0,0,0,0,1,0,0,0,0]
 or
 list [1,2,1,1]
 so index 0 is count of rank at index 0 of Histogram 1
 index 1 is count of rank at index 1 of Histogram 1
 
 
 Histograms usually involve putting things in bins and counting the 
 number by bin.  Here the bins are just the ranks of the cards, and so 
 you're counting the frequency of the ranks.  Once that's done, you want 
 to arrange the frequencies into a mapping of its own, which points to 
 the list of ranks that have that frequency.  That way you can easily 
 pick things off:  If there is a hit in the four bin, you have quads.  If 
 there's a hit in the three bin and either another in the three or one in 
 the two bin, you have a boat.  If there's a hit in the three bin but 
 _not_ another in three or two, then it's trips.  And so on.
 
 As for straights, if i understand correctly, you make all possible 
 straights of the cards in the hand and then see if one matches?
 
 
 Not quite.  You break down the cards by what matters -- ranks and suits 
 -- and then make sets based on these.  Then, standing by, you have the 
 sets of valid straights (by rank), and then to test for straights, you 
 iterate through the straight sets and make intersections with the rank 
 set for the hand in question.  If the intersection is the same as the 
 straight set, then it's a straight.  (Do this by reverse order of the 
 relative values of the straights, and stop when you find the first one, 
 to get the highest straight.)  The most efficient way to do this is with 
 a bitmask, so that's how it's usually done.
 

Thanks for the info. I succeeded in doing a straight flush check 
yesterday but not using the method described. My code works now but 
using bitmasks might actually be faster to use for hand detection and 
comparison. I'm not sure that it will be easier to read and understand 
the code though.
I'll play a bit with bitmasks and see what gives.

Thanks,
Benedict
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: poker card game revisited (code included)

2005-06-08 Thread John Hazen
[Erik Max Francis]
   Searching for straights and flushes is much better done by masks.

Interesting.  I've been thinking about playing with this stuff too, but
hadn't considered masks.  So each card has a representation:

n bits for rank, then m bits for suit.

10 0001 = 2 clubs
01 1000 = K spades
...

[flupke]
  As for straights, if i understand correctly, you make all possible 
  straights of the cards in the hand and then see if one matches?

Yeah, I originally thought that's what you meant, too.  But if you take
the scheme above, and sort the cards before you merge them into the
hand-bits aggregate, then you can just have *one* mask for straights,
and shift it down by a bit each time you check. So the best straight
mask (A high) would be (ignoring suit bits):

10 01 001000 000100 10

Then this could be shifted right for a K-high straight:

01 001000 000100 10 01

I guess that means that an Ace has to have the following representation,
since it can be both at the high and low end of a straight:

11 0100 = A hearts

But this may mess with bit-counting shortcuts for other calculations...

This is interesting to think about.  Thanks for the pointer.  I'm also
going to look at pokersource, though I may put that off until I at least
partially re-invent the wheel for learning purposes.

-John
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: poker card game revisited (code included)

2005-06-08 Thread Erik Max Francis
John Hazen wrote:

 Interesting.  I've been thinking about playing with this stuff too, but
 hadn't considered masks.  So each card has a representation:
 
 n bits for rank, then m bits for suit.
 
 10 0001 = 2 clubs
 01 1000 = K spades
 ...

You can also deal with them as a mask of card indexes.  So the deuce of 
clubs is bit 0, the three of clubs is bit 1, all the way up to the ace 
of spades, which is bit 51.  (That obviously won't fit in an int; you'll 
need a long.)

-- 
Erik Max Francis  [EMAIL PROTECTED]  http://www.alcyone.com/max/
San Jose, CA, USA  37 20 N 121 53 W  AIM erikmaxfrancis
   You are the lovers rock / The rock that I cling to
   -- Sade
-- 
http://mail.python.org/mailman/listinfo/python-list


poker card game revisited (code included)

2005-06-07 Thread flupke
Hi,

i've included the code so interested people can take a look.
I've tried to expand on the thread of 26/05/2005 on Checking for a full
house. Code is suboptimal as I coded it rather quickly.
I've added the normal classes one would expect from a cardgame: card,
deck, hand etc.

1. I can detect most things except a straightflush. The problem with the
code now is that it only returns 1 straight which is enough for mere
straight detection but won't suffice for hand comparison and
especially detecting straight flushes. For use in straight flush
detection, the function would need to return all possible straights and
then these would need to be checked to see if they are flushes.
For instance a list [4,4,5,5,6,7,8] yields 4 different straights.
A hand like [4,4,5,5,6,7,8,9] gets even worse.
I can't see how i can do this using sets, i'll need to come up with
another method since the suit is important.

2. Hand comparison.
For this to succeed the getrank function would need to return the exact
5 cards that represent the highest hand. This could be less than 5 cards
if one uses wildcards. Then you not only have the correct rank but also
the highest hand so you can compare in case there are ties.

3. x wild.
For games like deuces wild, what would be the best way to manage
those? I tought about removing them from a hand before shipping it of to
the getrank function?

Any ideas?

Regards,
Benedict Verheyen

= CODE =

Attempt for a poker cardgame representation
Benedict Verheyen
Code additions from web (http://www.ibiblio.org/obp/thinkCSpy/) and
newsgroup comp.lang.python esp. Raymond Hettinger

import random

class Card(object):
  
  Represents a single card
  2,3,4, ... 10, 11 for Jack, 12 for Queen,
  13 for King, 14 for Ace
  
  suitList = [Clubs, Diamonds, Hearts, Spades]
  rankList = [ narf, narf, 2, 3, 4, 5, 6, 7, 8,
9, 10,
  Jack, Queen, King, Ace]

  def __init__(self, suit=0, rank=0):
  
  Initialise a card
  @type suit: int
  @param suit: suit of the card (see suitList)
  @type rank: int
  @param rank: rank of the card (see rankList)
  
  self.suit = suit
  self.rank = rank

  def __str__(self):
  
  Pretty print a card
  
  return self.rankList[self.rank] +  of  + 
self.suitList[self.suit]

  def __cmp__(self, other):
  
  Compare 2 cards
  @type other: card
  @param other: the card to compare with
  
  # check the suits
  if self.suit  other.suit: return 1
  if self.suit  other.suit: return -1
  # suits are the same... check ranks
  if self.rank  other.rank: return 1
  if self.rank  other.rank: return -1
  # ranks are the same... it's a tie
  return 0

class Deck(object):
  
  Represents a deck of cards. We can have different decks of cards
  
  DECK_NORMAL = 1 # 52 cards

  def __init__(self,decktype=DECK_NORMAL):
  
  Makes a deck of cards
  @type decktype: type of deck
  @param decktype: what type of deck is it? (DECK_NORMAL,...)
  
  self.cards = []
  for suit in range(4):
for rank in range(2, 15):
  self.cards.append(Card(suit, rank))

  def printdeck(self):
  
  Pretty print the deck
  
  for card in self.cards:
print card

  def __str__(self):
  
  Pretty print the deck
  
  s = 
  for i in range(len(self.cards)):
  s = s +  *i + str(self.cards[i]) + \n
  return s

  def sort(self,rank=True,suit=False):
  
  Sort the deck
  
  def sortonrank(x,y):
  if x.rank  y.rank: return 1
  if x.rank  y.rank: return -1
  return 0
  def sortonsuit(x,y):
  if x.suit  y.suit: return 1
  if x.suit  y.suit: return -1
  return 0
  def sortonboth(x,y):
  return cmp(x,y)

  if ( rank == True and suit == False):
  self.cards.sort(sortonrank)
  elif ( suit == True and rank == False ):
  self.cards.sort(sortonsuit)
  else:
  self.cards.sort(sortonboth) # roept sort van card op

  def shuffle(self,nshuffle=1):
  
  Shuffle the deck of cards. This happens by swapping cards
  @type nshuffle: int
  @param nshuffle: how many times do we shuffle
  
  import random
  nCards = len(self.cards)
  # swap cards on place i and j
  for shuffle in range(nshuffle):
  print  shuffle %s  % shuffle
  for i in range(nCards):
  j = random.randrange(i, nCards)
  [self.cards[i], self.cards[j]] = 

poker card game revisited (code included)

2005-06-07 Thread flupke
Hi,

i've included the code so people can take a look.
I've tried to expand on the thread of 26/05/2005 on Checking for a full
house. Code is suboptimal as I coded it rather quickly.
I've added the normal classes one would expect from a cardgame: card,
deck, hand etc.

1. I can detect most things except a straightflush. The problem with the
code now is that it only returns 1 straight which is enough for mere
straight detection but won't suffice for hand comparison and
especially detecting straight flushes. For use in straight flush
detection, the function would need to return all possible straights and
then these would need to be checked to see if they are flushes.
For instance a list [4,4,5,5,6,7,8] yields 4 different straights.
A hand like [4,4,5,5,6,7,8,9] gets even worse.
I can't see how i can do this using sets, i'll need to come up with
another method since the suit is important.

2. Hand comparison.
For this to succeed the getrank function would need to return the exact
5 cards that represent the highest hand. This could be less than 5 cards
if one uses wildcards. Then you not only have the correct rank but also
the highest hand so you can compare in case there are ties.

3. x wild.
For games like deuces wild, what would be the best way to manage
those? I tought about removing them from a hand before shipping it of to
the getrank function?

Any ideas?

Regards,
Benedict Verheyen

= CODE =

Attempt for a poker cardgame representation
Benedict Verheyen
Code additions from web (http://www.ibiblio.org/obp/thinkCSpy/) and
newsgroup comp.lang.python esp. Raymond Hettinger

import random

class Card(object):
  
  Represents a single card
  2,3,4, ... 10, 11 for Jack, 12 for Queen,
  13 for King, 14 for Ace
  
  suitList = [Clubs, Diamonds, Hearts, Spades]
  rankList = [ narf, narf, 2, 3, 4, 5, 6, 7, 8,
9, 10,
  Jack, Queen, King, Ace]

  def __init__(self, suit=0, rank=0):
  
  Initialise a card
  @type suit: int
  @param suit: suit of the card (see suitList)
  @type rank: int
  @param rank: rank of the card (see rankList)
  
  self.suit = suit
  self.rank = rank

  def __str__(self):
  
  Pretty print a card
  
  return self.rankList[self.rank] +  of  + 
self.suitList[self.suit]

  def __cmp__(self, other):
  
  Compare 2 cards
  @type other: card
  @param other: the card to compare with
  
  # check the suits
  if self.suit  other.suit: return 1
  if self.suit  other.suit: return -1
  # suits are the same... check ranks
  if self.rank  other.rank: return 1
  if self.rank  other.rank: return -1
  # ranks are the same... it's a tie
  return 0

class Deck(object):
  
  Represents a deck of cards. We can have different decks of cards
  
  DECK_NORMAL = 1 # 52 cards

  def __init__(self,decktype=DECK_NORMAL):
  
  Makes a deck of cards
  @type decktype: type of deck
  @param decktype: what type of deck is it? (DECK_NORMAL,...)
  
  self.cards = []
  for suit in range(4):
for rank in range(2, 15):
  self.cards.append(Card(suit, rank))

  def printdeck(self):
  
  Pretty print the deck
  
  for card in self.cards:
print card

  def __str__(self):
  
  Pretty print the deck
  
  s = 
  for i in range(len(self.cards)):
  s = s +  *i + str(self.cards[i]) + \n
  return s

  def sort(self,rank=True,suit=False):
  
  Sort the deck
  
  def sortonrank(x,y):
  if x.rank  y.rank: return 1
  if x.rank  y.rank: return -1
  return 0
  def sortonsuit(x,y):
  if x.suit  y.suit: return 1
  if x.suit  y.suit: return -1
  return 0
  def sortonboth(x,y):
  return cmp(x,y)

  if ( rank == True and suit == False):
  self.cards.sort(sortonrank)
  elif ( suit == True and rank == False ):
  self.cards.sort(sortonsuit)
  else:
  self.cards.sort(sortonboth) # roept sort van card op

  def shuffle(self,nshuffle=1):
  
  Shuffle the deck of cards. This happens by swapping cards
  @type nshuffle: int
  @param nshuffle: how many times do we shuffle
  
  import random
  nCards = len(self.cards)
  # swap cards on place i and j
  for shuffle in range(nshuffle):
  print  shuffle %s  % shuffle
  for i in range(nCards):
  j = random.randrange(i, nCards)
  [self.cards[i], self.cards[j]] = [self.cards[j],

Re: poker card game revisited (code included)

2005-06-07 Thread Erik Max Francis
flupke wrote:

 i've included the code so people can take a look.
 I've tried to expand on the thread of 26/05/2005 on Checking for a full
 house. Code is suboptimal as I coded it rather quickly.
 I've added the normal classes one would expect from a cardgame: card,
 deck, hand etc.
 
 1. I can detect most things except a straightflush. The problem with the
 code now is that it only returns 1 straight which is enough for mere
 straight detection but won't suffice for hand comparison and
 especially detecting straight flushes. For use in straight flush
 detection, the function would need to return all possible straights and
 then these would need to be checked to see if they are flushes.
 For instance a list [4,4,5,5,6,7,8] yields 4 different straights.
 A hand like [4,4,5,5,6,7,8,9] gets even worse.
 I can't see how i can do this using sets, i'll need to come up with
 another method since the suit is important.
 
 2. Hand comparison.
 For this to succeed the getrank function would need to return the exact
 5 cards that represent the highest hand. This could be less than 5 cards
 if one uses wildcards. Then you not only have the correct rank but also
 the highest hand so you can compare in case there are ties.

It looks like you're not approaching this in a systematic manner. 
Algorithms for determining poker hands are already pretty well-known; 
there are several open source projects that do it efficiently which you 
could learn from.

When you're evaluating poker hands, you're looking for three basic types 
of card groups:  matches, straights, and flushes.  The most efficient 
way to look for matches is with a histogram based on the card rank.  Bin 
the cards up by rank, and then build a second histogram of the counts 
of those ranks indexing into a list of the ranks which had those cards 
(sorted by rank, so you can pull off the highest ones).  Now determining 
all the rank-based hands is easy:  quads have a hit with four matches, a 
boat has a hit with two three matches (there's no two trips so this is 
a boat at best) or both three and two matches, two pair has two hits 
with two matches, etc.

Searching for straights and flushes is much better done by masks. 
Arrange all the possible cards in a huge masks based on both cards and 
ranks (easy to do in Python with the long type) and then build up rank 
masks that build up all possible straight combinations (sorted by the 
highest rank so you can search them in order), and then build up card 
mask ranks for each suit.  For straights, just iterate through the 
straight rank masks and see if you find one that's fully occupied; if 
you do, that's a straight.  For flushes, just iterate through the card 
suit masks and see if you find one that has more five or more unique 
cards in it.  You need to iterate through all four and find the one with 
the highest value (for games with lots of cards, you could have two 
flushes; you want to count the highest one).  Finally, to look for 
straight flushes, first apply the suit masks and then turn it into ranks 
and apply the straight masks.

Then will all this information you can easily arrange the code to select 
the best existing hand.  Note that these all use well-established 
techniques and reveal nothing secret.

 3. x wild.
 For games like deuces wild, what would be the best way to manage
 those? I tought about removing them from a hand before shipping it of to
 the getrank function?

I'll leave it up to you to try to figure out how to make a wild card 
algorithm.

-- 
Erik Max Francis  [EMAIL PROTECTED]  http://www.alcyone.com/max/
San Jose, CA, USA  37 20 N 121 53 W  AIM erikmaxfrancis
   Love is the selfishness of two persons.
   -- Antoine de la Salle
-- 
http://mail.python.org/mailman/listinfo/python-list


Re: poker card game revisited (code included)

2005-06-07 Thread flupke
Erik Max Francis wrote:
 flupke wrote:
 
snip

First of all, my apologies for the double posts. I can only see this 
reply and can't see my original messages. I posted the message from home 
and work and they didn't show up. We use the same isp at home and at 
work so it's probably a problem on their end.

 It looks like you're not approaching this in a systematic manner. 
 Algorithms for determining poker hands are already pretty well-known; 
 there are several open source projects that do it efficiently which you 
 could learn from.

Which projects are you talking about? I only found a library in c to 
evaluat ranks but i didn't find the code to be very understandable.

 When you're evaluating poker hands, you're looking for three basic types 
 of card groups:  matches, straights, and flushes.  The most efficient 
 way to look for matches is with a histogram based on the card rank.  Bin 
 the cards up by rank, and then build a second histogram of the counts 
 of those ranks indexing into a list of the ranks which had those cards 
 (sorted by rank, so you can pull off the highest ones).  Now determining 
 all the rank-based hands is easy:  quads have a hit with four matches, a 
 boat has a hit with two three matches (there's no two trips so this is 
 a boat at best) or both three and two matches, two pair has two hits 
 with two matches, etc.

With histogram do you mean something like this:
Card hand: 2 clubs, 3 diamonds, 10 of diamonds, 4 of hearts,  3 of hearts

Histogram 1: list [2,3,4,10]
2 - 14  
Histogram 2: list [1,2,1,0,0,0,0,0,1,0,0,0,0]
or
list [1,2,1,1]
so index 0 is count of rank at index 0 of Histogram 1
index 1 is count of rank at index 1 of Histogram 1

 Searching for straights and flushes is much better done by masks.
 Arrange all the possible cards in a huge masks based on both cards and 
 ranks (easy to do in Python with the long type) and then build up rank 
 masks that build up all possible straight combinations (sorted by the 
 highest rank so you can search them in order), and then build up card 
 mask ranks for each suit.  For straights, just iterate through the 
 straight rank masks and see if you find one that's fully occupied; if 
 you do, that's a straight.  For flushes, just iterate through the card 
 suit masks and see if you find one that has more five or more unique 
 cards in it.  You need to iterate through all four and find the one with 
 the highest value (for games with lots of cards, you could have two 
 flushes; you want to count the highest one).  Finally, to look for 
 straight flushes, first apply the suit masks and then turn it into ranks 
 and apply the straight masks.

As for straights, if i understand correctly, you make all possible 
straights of the cards in the hand and then see if one matches?

 Then will all this information you can easily arrange the code to select 
 the best existing hand.  Note that these all use well-established 
 techniques and reveal nothing secret.

Well, it's all new to me :)

Regards,
Benedict
-- 
http://mail.python.org/mailman/listinfo/python-list


poker card game revisited (code included)

2005-06-06 Thread flupke
Hi,

i've included the code so interested people can take a look.
I've tried to expand on the thread of 26/05/2005 on Checking for a full 
house. Code is suboptimal as I coded it rather quickly.
I've added the normal classes one would expect from a cardgame: card, 
deck, hand etc.

1. I can detect most things except a straightflush. The problem with the 
code now is that it only returns 1 straight which is enough for mere 
straight detection but won't suffice for hand comparison and 
especially detecting straight flushes. For use in straight flush 
detection, the function would need to return all possible straights and 
then these would need to be checked to see if they are flushes.
For instance a list [4,4,5,5,6,7,8] yields 4 different straights.
A hand like [4,4,5,5,6,7,8,9] gets even worse.
I can't see how i can do this using sets, i'll need to come up with 
another method since the suit is important.

2. Hand comparison.
For this to succeed the getrank function would need to return the exact 
5 cards that represent the highest hand. This could be less than 5 cards 
if one uses wildcards. Then you not only have the correct rank but also 
the highest hand so you can compare in case there are ties.

3. x wild.
For games like deuces wild, what would be the best way to manage 
those? I tought about removing them from a hand before shipping it of to 
the getrank function?

Any ideas?

Regards,
Benedict Verheyen

= CODE =

Attempt for a poker cardgame representation
Benedict Verheyen
Code additions from web (http://www.ibiblio.org/obp/thinkCSpy/) and
newsgroup comp.lang.python esp. Raymond Hettinger

import random

class Card(object):
 
 Represents a single card
 2,3,4, ... 10, 11 for Jack, 12 for Queen,
 13 for King, 14 for Ace
 
 suitList = [Clubs, Diamonds, Hearts, Spades]
 rankList = [ narf, narf, 2, 3, 4, 5, 6, 7, 8, 
9, 10,
 Jack, Queen, King, Ace]

 def __init__(self, suit=0, rank=0):
 
 Initialise a card
 @type suit: int
 @param suit: suit of the card (see suitList)
 @type rank: int
 @param rank: rank of the card (see rankList)
 
 self.suit = suit
 self.rank = rank

 def __str__(self):
 
 Pretty print a card
 
 return self.rankList[self.rank] +  of  + self.suitList[self.suit]

 def __cmp__(self, other):
 
 Compare 2 cards
 @type other: card
 @param other: the card to compare with
 
 # check the suits
 if self.suit  other.suit: return 1
 if self.suit  other.suit: return -1
 # suits are the same... check ranks
 if self.rank  other.rank: return 1
 if self.rank  other.rank: return -1
 # ranks are the same... it's a tie
 return 0

class Deck(object):
 
 Represents a deck of cards. We can have different decks of cards
 
 DECK_NORMAL = 1 # 52 cards

 def __init__(self,decktype=DECK_NORMAL):
 
 Makes a deck of cards
 @type decktype: type of deck
 @param decktype: what type of deck is it? (DECK_NORMAL,...)
 
 self.cards = []
 for suit in range(4):
   for rank in range(2, 15):
 self.cards.append(Card(suit, rank))

 def printdeck(self):
 
 Pretty print the deck
 
 for card in self.cards:
   print card

 def __str__(self):
 
 Pretty print the deck
 
 s = 
 for i in range(len(self.cards)):
 s = s +  *i + str(self.cards[i]) + \n
 return s

 def sort(self,rank=True,suit=False):
 
 Sort the deck
 
 def sortonrank(x,y):
 if x.rank  y.rank: return 1
 if x.rank  y.rank: return -1
 return 0
 def sortonsuit(x,y):
 if x.suit  y.suit: return 1
 if x.suit  y.suit: return -1
 return 0
 def sortonboth(x,y):
 return cmp(x,y)

 if ( rank == True and suit == False):
 self.cards.sort(sortonrank)
 elif ( suit == True and rank == False ):
 self.cards.sort(sortonsuit)
 else:
 self.cards.sort(sortonboth) # roept sort van card op

 def shuffle(self,nshuffle=1):
 
 Shuffle the deck of cards. This happens by swapping cards
 @type nshuffle: int
 @param nshuffle: how many times do we shuffle
 
 import random
 nCards = len(self.cards)
 # swap cards on place i and j
 for shuffle in range(nshuffle):
 print  shuffle %s  % shuffle
 for i in range(nCards):
 j = random.randrange(i, nCards)
 [self.cards[i], self.cards[j]] = [self.cards[j], 
self.cards[i]]

 def removecard(self, card):
 
 Removes a card