0

Although I'm not making a poker game, the objective of the game is the player with the highest poker hand wins. There are four players in my game. I was able to implement a gameboard and a function that would allow the player (once they make a move) to pick up the existing card on the gameboard and have the card face up in their hand. The game is over when there are no more cards or when a player clearly has the highest poker hand early in the and that there's no chance for a bigger hand (This is evident as all the cards are face up).

ORIGINAL:

I found this python poker hand evaluator by Alvin Liang that I want to implement in my game: https://github.com/aliang/pokerhand-eval

BETTER SOLUTION for my needs (I CURRENTLY WANT TO IMPLEMENT THIS): (from Peter Norvig's csc212 udacity course)

import itertools

## Deck adds two cards:
## '?B': black joker; can be used as any black card (S or C)
## '?R': red joker; can be used as any red card (H or D)

allranks = '23456789TJQKA'
redcards = [r+s for r in allranks for s in 'DH']
blackcards = [r+s for r in allranks for s in 'SC']

def best_wild_hand(hand):
"Try all values for jokers in all 5-card selections."
hands = set(best_hand(h)
            for h in itertools.product(*map(replacements, hand)))
return max(hands, key=hand_rank)

def replacements(card):
"""Return a list of the possible replacements for a card.
There will be more than 1 only for wild cards."""
if card == '?B': return blackcards
elif card == '?R': return redcards
else: return [card]

def best_hand(hand):
"From a 7-card hand, return the best 5 card hand."
return max(itertools.combinations(hand, 5), key=hand_rank)

def test_best_wild_hand():
assert (sorted(best_wild_hand("6C 7C 8C 9C TC 5C ?B".split()))
        == ['7C', '8C', '9C', 'JC', 'TC'])
assert (sorted(best_wild_hand("TD TC 5H 5C 7C ?R ?B".split()))
        == ['7C', 'TC', 'TD', 'TH', 'TS'])
assert (sorted(best_wild_hand("JD TC TH 7C 7D 7S 7H".split()))
        == ['7C', '7D', '7H', '7S', 'JD'])
return 'test_best_wild_hand passes'



def hand_rank(hand):
"Return a value indicating the ranking of a hand."
ranks = card_ranks(hand)
if straight(ranks) and flush(hand):
    return (8, max(ranks))
elif kind(4, ranks):
    return (7, kind(4, ranks), kind(1, ranks))
elif kind(3, ranks) and kind(2, ranks):
    return (6, kind(3, ranks), kind(2, ranks))
elif flush(hand):
    return (5, ranks)
elif straight(ranks):
    return (4, max(ranks))
elif kind(3, ranks):
    return (3, kind(3, ranks), ranks)
elif two_pair(ranks):
    return (2, two_pair(ranks), ranks)
elif kind(2, ranks):
    return (1, kind(2, ranks), ranks)
else:
    return (0, ranks)

def card_ranks(hand):
"Return a list of the ranks, sorted with higher first."
ranks = ['--23456789TJQKA'.index(r) for r, s in hand]
ranks.sort(reverse = True)
return [5, 4, 3, 2, 1] if (ranks == [14, 5, 4, 3, 2]) else ranks

def flush(hand):
"Return True if all the cards have the same suit."
suits = [s for r,s in hand]
return len(set(suits)) == 1

def straight(ranks):
"""Return True if the ordered
ranks form a 5-card straight."""
return (max(ranks)-min(ranks) == 4) and len(set(ranks)) == 5

def kind(n, ranks):
"""Return the first rank that this hand has
exactly n-of-a-kind of. Return None if there
is no n-of-a-kind in the hand."""
for r in ranks:
    if ranks.count(r) == n: return r
return None

def two_pair(ranks):
"""If there are two pair here, return the two
ranks of the two pairs, else None."""
pair = kind(2, ranks)
lowpair = kind(2, list(reversed(ranks)))
if pair and lowpair != pair:
    return (pair, lowpair)
else:
    return None

print test_best_wild_hand()

Here's the GamerManager code I have:

import json
import gameboard
from django.shortcuts import HttpResponse, render, redirect, Http404
from django.views.decorators.csrf import csrf_exempt
from django.contrib.auth.decorators import login_required

cardDict = {
    0: "ace of clubs",
    1: "two of clubs",
    2: "three of clubs",
    3: "four of clubs",
    4: "five of clubs",
    5: "six of clubs",
    6: "seven of clubs",
    7: "eight of clubs",
    8: "nine of clubs",
    9: "ten of clubs",
    10: "jack of clubs",
    11: "queen of clubs",
    12: "king of clubs",
    13: "ace of diamonds",
    14: "two of diamonds",
    15: "three of diamonds",
    16: "four of diamonds",
    17: "five of diamonds",
    18: "six of diamonds",
    19: "seven of diamonds",
    20: "eight of diamonds",
    21: "nine of diamonds",
    22: "ten of diamonds",
    23: "jack of diamonds",
    24: "queen of diamonds",
    25: "king of diamonds",
    26: "ace of hearts",
    27: "two of hearts",
    28: "three of hearts",
    29: "four of hearts",
    30: "five of hearts",
    31: "six of hearts",
    32: "seven of hearts",
    33: "eight of hearts",
    34: "nine of hearts",
    35: "ten of hearts",
    36: "jack of hearts",
    37: "queen of hearts",
    38: "king of hearts",
    39: "ace of spades",
    40: "two of spades",
    41: "three of spades",
    42: "four of spades",
    43: "five of spades",
    44: "six of spades",
    45: "seven of spades",
    46: "eight of spades",
    47: "nine of spades",
    48: "ten of spades",
    49: "jack of spades",
    50: "queen of spades",
    51: "king of spades",
    52: "black joker",
    53: "red joker",
    54: "back"
}


@login_required
def createGameRoom(request):
    userName = request.user.username
    board = gameboard.GameBoard()
    points = [0, 0, 0, 0]
    room = request.POST['gameRoom']
    roomDir = 'Game/GameRooms/game'+room+'.json'
    gameFile = open(roomDir)
    gameState = json.load(gameFile)
    gameFile.close()
    if gameState['p1Name'] == userName:
        gameState['board'] = board.board
        gameState['playerNum'] = 4
        gameState['turn'] = 1
        gameState['rounds'] = 0
        gameState['timeLimit'] = 30
        gameState['points'] = points
        gameState['player1'] = [0, 0]
        gameState['player2'] = [0, 5]
        gameState['player3'] = [5, 5]
        gameState['player4'] = [5, 0]
        gameState['player1Hand'] = []
        gameState['player2Hand'] = []
        gameState['player3Hand'] = []
        gameState['player4Hand'] = []
        with open(roomDir, 'w+') as jFile:
            json.dump(gameState, jFile)
            jFile.close()
    return HttpResponse(json.dumps(gameState), content_type="application/json")

@login_required
def resetRoom(request):
    if request.user.is_staff:
        board = gameboard.GameBoard()
        points = [0, 0, 0, 0]
        room = request.GET['room']
        roomDir = 'Game/GameRooms/game'+room+'.json'
        with open(roomDir, 'w+') as jFile:
            gameState = {'board': board.board,
                         'playerNum': 4,
                         'playerCount': 0,
                         'turn': 1,
                         'rounds': 0,
                         'timeLimit': 30,
                         'p1Name': '',
                         'p2Name': '',
                         'p3Name': '',
                         'p4Name': '',
                         'points': points,
                         'player1': [0, 0],
                         'player2': [0, 5],
                         'player3': [5, 5],
                         'player4': [5, 0],
                         'player1Hand': [],
                         'player2Hand': [],
                         'player3Hand': [],
                         'player4Hand': []}
            json.dump(gameState, jFile)
            jFile.close()
        return redirect(showRooms)
    else:
        return HttpResponse('Error')

@login_required
def joinGameRoom(request):
    room = request.GET["room"]
    roomDir = 'Game/GameRooms/game' + room + ".json"
    gameFile = open(roomDir)
    gameState = json.load(gameFile)
    gameFile.close()
    playerNum = 0
    print "joined room:" + str(request.user.username)
    if gameState['playerCount'] >= 4:
        return HttpResponse("Room is full")
    if gameState['p1Name'] == '':
        gameState['p1Name'] = request.user.username
        playerNum = 1
    elif gameState['p2Name'] == '':
        gameState['p2Name'] = request.user.username
        playerNum = 2
    elif gameState['p3Name'] == '':
        gameState['p3Name'] = request.user.username
        playerNum = 3
    elif gameState['p4Name'] == '':
        gameState['p4Name'] = request.user.username
        playerNum = 4
    gameState['playerCount'] += 1
    with open(roomDir, 'w+') as jFile:
        json.dump(gameState, jFile)
        jFile.close()
    context = {'roomNum': room, 'playerNum': playerNum}
    return render(request, "Games/board.html", context)


@login_required
def startRound(request):
    room = request.POST['gameRoom']
    gameDir = 'Game/GameRooms/game'+room+'.json'
    gameFile = open(gameDir)
    gameState = json.load(gameFile)
    board = gameboard.GameBoard()
    board.start()
    gameState['board'] = board.board
    gameState['rounds'] += 1
    gameState['player1'] = [0, 0]
    gameState['player1Hand'] = []
    gameState['player2'] = [0, 5]
    gameState['player2Hand'] = []
    gameState['player3'] = [5, 5]
    gameState['player3Hand'] = []
    gameState['player4'] = [5, 0]
    gameState['player4Hand'] = []
    gameFile.close()
    with open(gameDir, 'w+') as jFile:
        json.dump(gameState, jFile)
        jFile.close()
    return HttpResponse(json.dumps(gameState), content_type="application/json")


@login_required
@csrf_exempt
def makeMove(request):
    room = request.POST['roomNum']
    gameDir = 'Game/GameRooms/game'+room+'.json'
    row = int(request.POST['row'])
    column = int(request.POST['column'])
    playerNum = request.POST['playerNum']
    gameFile = open(gameDir)
    gameState = json.load(gameFile)
    print gameState
    gameFile.close()
    if int(playerNum) == gameState['turn']:
        print 'making move: ' + playerNum + " in room " + room
        player = 'player'+playerNum
        gameState[player] = [row, column]
        card = gameState['board'][row][column]
        if card != 54:
            gameState[player + 'Hand'].append(card)
            gameState['board'][row][column] = 54
        gameState['turn'] += 1
        if gameState['turn'] > 4:
            gameState['turn'] = 1
        with open(gameDir, 'w+') as jfile:
            json.dump(gameState, jfile)
    return HttpResponse(json.dumps(gameState), content_type="application/json")


def checkOccupied(gameState, row, column):
    isOccupied = False
    gameFile = open('Game/GameRooms/game.json')
    gameState = json.load(gameFile)
    if gameState['player1'] == [row, column]:
        isOccupied = True
    if gameState['player2'] == [row, column]:
        isOccupied = True
    if gameState['player3'] == [row, column]:
        isOccupied = True
    if gameState['player4'] == [row, column]:
        isOccupied = True
    gameFile.close()
    return isOccupied

@login_required
def getValidMoves(request):
    gameFile = open('Game/GameRooms/game.json')
    gameState = json.load(gameFile)
    player = ''
    if gameState['turn'] == 1:
        player = 'player1'
    elif gameState['turn'] == 2:
        player = 'player2'
    elif gameState['turn'] == 3:
        player = 'player3'
    elif gameState['turn'] == 4:
        player = 'player4'
    row = gameState[player][0]
    column = gameState[player][1]
    tempRow = row
    tempCol = column
    validMoves = []
    while (tempCol + 1) < 6:
        tempCol += 1
        occupied = checkOccupied(gameState, tempRow, tempCol)
        if not occupied:
            validMoves.append([tempRow, tempCol])
        else:
            break
    tempCol = column
    while (tempCol - 1) >= 0:
            tempCol -= 1
            occupied = checkOccupied(gameState, tempRow, tempCol)
            if not occupied:
                validMoves.append((tempRow, tempCol))
            else:
                break
    tempCol = column
    while (tempRow + 1) < 6:
            tempRow += 1
            occupied = checkOccupied(gameState, tempRow, tempCol)
            if not occupied:
                validMoves.append((tempRow, tempCol))
            else:
                break
    tempRow = row
    while (tempRow - 1) >= 0:
            tempRow -= 1
            occupied = checkOccupied(gameState, tempRow, tempCol)
            if not occupied:
                validMoves.append((tempRow, tempCol))
            else:
                break
    return HttpResponse(json.dumps(validMoves), content_type="application/json")

@login_required
def getBoard(request):
    if request.method == 'POST':
        room = request.POST['gameRoom']
        gameDir = 'Game/GameRooms/game'+room+'.json'
        gameFile = open(gameDir)
        gameState = json.load(gameFile)
        return HttpResponse(json.dumps(gameState), content_type="application/json")


@login_required
def showRooms(request):
    context = {'room_list':range(1,9)}
    return render(request, "Games/rooms.html", context)

and here's my player class

class player:
    def __init__(self, playerNum):
        self.name = ""
        self.playerNum = playerNum
        self.row = 0
        self.column = 0
        self.hand = []

    def toHand(self, card):
        self.hand.append(card)

    def setPiece(self, row, column):
        self.row = row
        self.column = column

    def clearHand(self):
        self.hand = []

Basically, I'm not entirely sure how to connect this evaluator with what I currently have. How do I connect my player's changing hands and gameboard to an existing poker hand evaluator?

Any ideas would help (pseudocode or python).

Kaylie
  • 13
  • 5

1 Answers1

0

The main thing you'll have to do is convert your card representation to his. You use a single number 0..51, he uses an object with suit and rank, both in different orders. To convert your int value (n) to his Card class, try this:

s = 4 - (n // 13);

r = n % 13;
if r == 0:
    r = 14
else:
    r += 1

c = Card(r, s)

After that, his hands are just lists of Card objects.

FWIW, I have a much, much faster public domain poker hand evaluator in C with a Python binding. Since it's not pure Python you'll have to drag the shared library around with you as well as the Python module, but if that works for you I'll point you to it.

Lee Daniel Crocker
  • 12,927
  • 3
  • 29
  • 55
  • Hmm I see. So, to put everything together, I would just import his library and adjust to using an object with a suit and rank. Then I'll have a list of card objects and I have sort through them. Which one is your implementation? I would be interested in having a look. How would I implement yours? Thank you so much! @LeeDanielCrocker – Kaylie May 17 '13 at 11:55
  • I'd love to have a beta tester for my library, which is useful for all kinds of card games and simulations. Unfortunately, I just started a major refactoring of my code, so I can't point you to a clean codebase right now until I finish and put it on GitHub. But if you want to try it, email me some details (like What OS you're using. Python version, etc.) and maybe I can hack together something you can use. – Lee Daniel Crocker May 17 '13 at 22:33