Re: poker card game revisited (code included)
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)
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)
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)
[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)
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)
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)
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)
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)
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)
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