#!/usr/bin/python import re, os, random, string, itertools spade='\xe2\x99\xa0' heart='\xe2\x99\xa5' diamond='\xe2\x99\xa6' club='\xe2\x99\xa3' faces=["A"]+range(2,11)+list("JQKA") suits=[(spade, 1), (club, 1), (heart, 4), (diamond, 4)] handsmapping=["High card", "One pair", "Two pair", "Three of a kind", "Straight", "Flush", "Full house", "Four of a kind", "Straight flush", "Royal flush"] class Game(object): def __init__(self): self.deck=deck=list(itertools.product(xrange(1,14), xrange(4))) random.shuffle(deck) random.shuffle(deck) random.shuffle(deck) random.shuffle(deck) random.shuffle(deck) self.status=0 self.players=[] self.hands={} self.waiting=None class Poker(object): def __init__(self): self.games={} def onRecv(self, IRC, line, data): if data==None: return (origin, ident, host, cmd, target, params, extinfo)=data #print data if len(target) and target[0]=="#" and cmd=="PRIVMSG": channel=IRC.channel(target) user=IRC.user(origin) matches=re.findall("^!poker (\\S+)(?:\\s+(.*))?$",extinfo) if matches: cmd, param=matches[0] if cmd=="newgame": if all([m not in channel.modes.keys() or user not in channel.modes[m] for m in "qao"]): channel.msg("%s: You are not operator."%origin) elif channel in self.games.keys(): channel.msg("%s: There is already a game going on in this channel."%origin) else: self.games[channel]=Game() channel.msg("A new poker game has started. Type \x02!poker sit\x02 to join.") elif cmd=="sit": if channel not in self.games.keys(): channel.msg("%s: There is no game going on in this channel."%origin) elif self.games[channel].status!=0: channel.msg("%s: Cannot join the game at this time."%origin) elif user in self.games[channel].players: channel.msg("%s: You are already in the game."%origin) elif len(self.games[channel].players)>=8: channel.msg("%s: This game is full."%origin) else: self.games[channel].players.append(user) channel.msg("%s: Welcome to the game."%origin) elif cmd=="deal": if all([m not in channel.modes.keys() or user not in channel.modes[m] for m in "qao"]): channel.msg("%s: You are not operator."%origin) elif channel not in self.games.keys(): channel.msg("%s: There is no game going on in this channel."%origin) elif len(self.games[channel].players)==0: channel.msg("%s: Nobody has sat yet."%origin) elif self.games[channel].status>0: channel.msg("%s: The cards have already been dealt."%origin) else: channel.me("deals poker hands to %s"%(string.join([user.nick for user in self.games[channel].players],", "))) P=len(self.games[channel].players) for user in self.games[channel].players: hand=list(self.games[channel].deck[0:5*P:P]) del self.games[channel].deck[0:5*P:P] self.games[channel].hands[user]=hand user.notice("Your poker hand is: %s"%(string.join(["\x03%d,0\x02%s%s\x0f"%(suits[s][1], faces[f], suits[s][0]) for (f,s) in hand],", "))) self.games[channel].status=1 self.games[channel].waiting=self.games[channel].players[0] channel.msg("The cards have been dealt.") channel.msg("%s: Do you wish to draw any cards? Type \x02!poker draw n1,n2,...\x02, where n1,n2,... is a list of cards \x02by index\x02 you wish to draw (0 for first card, 1 for second, etc...). Empty list means you wish to keep all cards."%self.games[channel].waiting.nick) elif cmd=="draw": if channel not in self.games.keys(): channel.msg("%s: There is no game going on in this channel."%origin) elif user not in self.games[channel].players: channel.msg("%s: You are not in this game."%origin) elif self.games[channel].status!=1: channel.msg("%s: We are not exchanging cards yet."%origin) elif self.games[channel].waiting!=user: channel.msg("%s: It is not your turn to draw cards yet."%origin) else: if param and any([card not in "01234" for card in param.split(",")]): channel.msg("%s: I could not understand your request."%origin) else: if param=="": channel.msg("%s is keeping all cards."%origin) discards=[] else: discards=[] #print "Param",param for cardid in param.split(","): card=self.games[channel].hands[user][int(cardid)] #print "Discarding ",card if card not in discards: discards.append(card) for card in discards: self.games[channel].hands[user].remove(card) channel.msg("%s is exchanging %d card%s."%(origin, len(discards), "s" if len(discards)>1 else "")) self.games[channel].hands[user].extend(self.games[channel].deck[:len(discards)]) del self.games[channel].deck[:len(discards)] self.games[channel].deck.extend(discards) user.notice("Your new poker hand is: %s"%(string.join(["\x03%d,0\x02%s%s\x0f"%(suits[s][1], faces[f], suits[s][0]) for (f,s) in self.games[channel].hands[user]],", "))) k=self.games[channel].players.index(user) if k2: channel.msg("The winners are %s, and %s. A %d-way tie. Well played, gentlemen!"%(string.join(winners[:-1], ", "), winners[-1], len(winners))) elif len(winners)==2: channel.msg("The winners are %s and %s. A tie. Well played, gentlemen!"%tuple(winners)) else: channel.msg("The winner is %s. Well played, gentlemen!"%winners[0]) del self.games[channel] #matches=re.findall("^!shuffle(?:\\s+([\\d]+))?$",extinfo) #if matches: #if matches[0]: shuffles=int(matches[0]) #else: shuffles=1 #if shuffles>1000: #channel.msg("Get real, %s!"%origin) #return #for s in xrange(shuffles): random.shuffle(deck) #channel.me("shuffles the deck %d time%s."%(shuffles, "s" if shuffles>1 else "")) def evalhand(hand): facevalues=[face for (face,suit) in hand] facevalues.sort(reverse=True) suits=[suit for (face,suit) in hand] duplicities=[(facevalues.count(k),k) for k in xrange(1,14)] duplicities.sort(reverse=True) counts=[count for (count,k) in duplicities] faces=[k for (count,k) in duplicities] ### Check for flush if suits==[0]*5: flush=True elif suits==[1]*5: flush=True elif suits==[2]*5: flush=True elif suits==[3]*5: flush=True else: flush=False ### Check for straight if (max(counts)==1 and max(facevalues)-min(facevalues)==4) or counts==[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]: straight=True else: straight=False if flush and not straight: return (5,)+tuple(faces) elif straight and not flush: return (4,)+tuple(faces) elif flush and counts==[1, 0, 0, 0, 0, 0, 0, 0, 0, 1, 1, 1, 1]: return (9,)+tuple(faces) elif flush and straight: return (8,)+tuple(faces) if 3 in counts and 2 in counts: return (6,)+tuple(faces) if 4 in counts: return (7,)+tuple(faces) if 3 in counts: return (3,)+tuple(faces) if counts.count(2)==2: return (2,)+tuple(faces) if 2 in counts: return (1,)+tuple(faces) return (0,)+tuple(faces)