Sponsored By

What I Did During My Summer Vacation: Developing a Game in 13 Weeks

In the short span of time from June 13 to September 22, 2001, Reel Deal Poker Challenge went from a concept to a gold master. Roger Pedersen shares his tale of developing a poker game in just 13 weeks.

December 1, 2001

13 Min Read

Author: by Roger Pedersen

The Start

In the short span of time from June 13 to September 22, 2001, Reel Deal Poker Challenge went from a concept to a gold master. Some preliminary artwork, concept art and minimal documentation were available at the start. The game was desinged for Phantom EFX, a small publisher and developer whose strength is in their superb graphics and audio (they have an in-house sound studio).

The Concept
Phantom EFX's first title was Reel Deal Slots and Video Poker, and they desired to continue in the gambling genre with a poker game. Reel Deal Poker Challenge presents a variety of poker games inside an elegant Poker Palace. There are three floors of play where the opponents play better on each level and the stakes get higher. Each floor has a poker room for regular play against four animated, talking players or eight basic players (a standard poker view) and a tournament room where four players play one variation for 20 hands and the player with the most money is the winner. A cashier area to register players, get more cash when your wallet is looking empty and see your statistics. There is a slot room with a few slot machines to promote the previous title, and an elevator allowing players access to the other floors when they have earned enough " reputation points" by playing in tournaments. One of the popular concepts used in the first title was a prize room where players win valuable prizes when they do well. In Poker Challenge, when a player wins certain tournaments, they win a valuable prize. The prizes are unknown to the player and collecting all of them is a secondary goal in the game.

The goal of the game is to earn enough "reputation points" and money to challenge to World's Best Poker player in a winner take all $2.5 Million game.

The Plan
A good poker engine takes time to develop. From 1993 to 1995, I had been director of development at Villa Crespo Software, then the premier gambling entertainment software company with titles like Stanford Wong's Video Poker, Amarillo Slim's Dealer's Choice, The Gold Sheet Football Analyzer and Dr. Thorp's Blackjack. For Poker Challenge, we licensed a poker engine from one of the developers I had worked with at VCS. The next issue was using DirectX 8.0, which had recently been released. For artwork, the easiest format to work with was BMP. I tried using the PNG format, but the time needed to write and properly implement the routines was not available. Sound was to initially be outputted via the "play" function, with Direct Sound to be implemented later.

The Eye Openers
The DirectX sample code for Direct Draw and Direct Input uses MFC and Dialog Boxes which, when they compiled cleanly, didn't relate to what I needed. MFC and window/dialog boxes were not used in this project. One issue that came up was that in Direct Draw full screen, exclusive mode, debugging became impossible except by using Message Boxes. To debug properly, the following code was used frequently by commenting and uncommenting the code below.

Note: include Ddutil.h and Ddutil.cpp (provided in DirectX8.0)

void InitializeGraphics(HWND hWnd)
{
RECT qrect={0,0,800,600};

if(!hWnd)
{
MessageBox(0,"Your hWndNULL",TEXT("Poker2000"),MB_ICONERROR| MB_OK); exit(0);
}
//************** USE THIS IN FINAL NON-WINDOW VERSION if(FAILED(DXscreen->CreateFullScreenDisplay(hWnd,800,600,32)))
{
if(FAILED(DXscreen->CreateFullScreenDisplay(hWnd,800,600,24)))
{
if(FAILED(DXscreen->CreateFullScreenDisplay(hWnd,800,600,16)))
{
MessageBox(hWnd,"Unable to find a compatible display mode. The program will now exit.",
TEXT("Poker2000"), MB_ICONERROR | MB_OK);
exit(0);
}
}
}
//************** USE THIS TO DEBUG (WINDOW VERSION)
// if (FAILED(DXscreen->CreateWindowedDisplay(hWnd, 800, 600)))
// exit(0);
}-

The poker engine was written in MS Visual BASIC and played several poker variations (Draw Poker No Openers and Jacks or Better to Open, Five Card Stud, Seven Card Stud, Chicago Hi (Seven Card Stud with the High Spade in the Hole/ down cards the second winner), and Hold 'Em. The first issue was to convert the BASIC code to C++ code.

The poker AI was primarily in one VB module, but the variables were defined and used in numerous modules. After rewriting the original code several items had to be fixed. The engine did not account for equal poker hands, as when four players each have a Royal Flush. The engine designer's reaction was it would never happen. Well, what about a straight flush or a flush with the same ranked cards? This issue was fixed by allowing a suit order (Spades, Hearts, Diamonds then Clubs) and allowing multiple players to be the winner. The original AI also didn't look at other tie breaking issues. The new version resolved tiebreak by having two components of the "handresult" which comprised of Result Type and a Long Tie Factor. The Result Type is a number comprised of a best hand number (pair is 20, two pair is 40, to a straight flush as 160 and a royal flush as 180) plus the rank of the key card (2 through Ace or 14). The Long Tie Factor is a long (4 bytes) where each card's rank in Importance order is stored. A hand of three kings, two aces, a 3 and a 5 is stored as {13, 13, 13, 14, 14, 5, 3}. If two players have the same Result Type such as a pair of kings each (value 33) then the Long Tie Factor number is used to break the apparent tie. Reel Deal Poker Challenge poker added two variations, Chicago Low (the opposite of Chicago Hi where the lowest spade in the down cards shares as winner) and Omaha (a very popular poker variation). In games like Texas Hold 'Em and Omaha, the best possible hand must be determined. Texas Hold 'Em is a poker game where each player is dealt two cards down and five cards are dealt as community cards (used by all players). Omaha is similar to Hold 'Em except each player is dealt four cards down and five cards are dealt as community cards. In Omaha, the final hand is the best hand comprised of two of the four down cards and three of the five community cards. In Texas, the player uses their two down cards and three of the five community cards to make their best hand. The AI was programmed to analyze and determine a player's best hand.

Know the Rules
As a programmer, we often give tasks to the computer rather than let events happen naturally. In Draw Poker: Jacks or Better to Open variation, the code was originally written to allow only a player having a hand of a pair of Jacks or Better to open betting and continue the hand. If no player had a pair of Jacks or better, the hand was redealt. The program decided the course of play not the players. This method was incorrect. The final version gives each player the choice to "check" (pass), "fold" or "bet." If all players "check," the hand is redealt. If a player "bets" and they do not have the required hand, the "check" option is substituted. In Five Card Stud, Seven Card Stud and Chicago, the first bet is a forced bet for the player with the lowest up card. In Hold 'Em and Omaha, the player to the dealer's left must make a forced bet called the "blind bet. " The ace is always the high card except the Ace of Spades in Chicago Lo where, according to several websites on poker, the ace can be the lowest hole (down) card. This information changed the Chicago Lo AI where the Two of Spades was the lowest card.

Sound and Animation

Direct Sound replaced the "Play" function so that multiple audio files could be outputted simultaneously. In Poker Challenge, each room had background (ambient) music playing and the poker rooms had three to four large background music files. While the ambient music was playing, one or two sound effects could be triggered. In the four player poker room, any of the three animated characters will chat with the players, therefore a chat audio file had to be in memory. The following code (using DSutil.cpp, DSutil.h and DSound.h) was used to initialize Direct Sound, the needed sound buffers (four background sound buffers, two sound effect buffers and one character chat buffer) and a sample of how the sounds were played.

 

///------ DirectSound Object and Buffers ------//
CSoundManager* g_pSoundManager = NULL;
CSound* g_pBackSound[4] = {NULL,NULL,NULL,NULL};
CSound* g_pSFX1Sound = NULL;
CSound* g_pSFX2Sound = NULL;
CSound* g_pChatSound = NULL;

void InitDSound(HWND hWnd)
{
HRESULT hr;
// Create a static IDirectSound in the CSound class.
// Set coop level to DSSCL_PRIORITY or DSSCL_NORMAL, and set primary buffer
// format to stereo, 22kHz and 16-bit output.
g_pSoundManager = new CSoundManager();

If( FAILED( hr = g_pSoundManager->Initialize( hWnd, DSSCL_NORMAL, 4, 22050, 16 ) ) ){
MessageBox( hWnd, "Error initializing DirectSound. Program will now exit.",
"DirectSound Init", MB_OK | MB_ICONERROR );
exit(1);
}
}

// CREATE THE SOUND EFFECTS #1 AUDIO BUFFER
// flag==1 to test if playing, else overwrite new SFX1 Sound
int NewSFX1Sound(TCHAR *strFileName,int flag) {
HRESULT hr;

if(g_pSFX1Sound){
// testing if sound is playing
if((flag==1) && g_pSFX1Sound->IsSoundPlaying())return(1); g_pSFX1Sound->Stop();
}
if(strlen(strFileName)>0){
SAFE_DELETE(g_pSFX1Sound);
// Sound if existed has stopped and has been deleted
hr = g_pSoundManager->Create( &g_pSFX1Sound, strFileName, 0, GUID_NULL, 1 );
}
return(0);
}
// PLAY THE SOUND EFFECTS #1 AUDIO BUFFER
void PlaySFX1()
{
HRESULT hr;
DWORD dwFlags = 0L; // set to DSBPLAY_LOOPING if looping needed g_pSFX1Sound ->Stop(); g_pSFX1Sound ->Reset(); Hr = g_pSFX1Sound->Play( 0, dwFlags );
}

 

In the four player poker room, the the opponents are highly animated characters designed to chat at 15 frames per second. Each character has seven different poses and each pose has five different eye frames and seven different mouth frames. The first time a player enters the four player poker room, all of the required graphics (poses, mouth and eye frames) are loaded into memory as surfaces. Using fast blitting from surface to screen and a 67 millisecond timer (1/15 of a second), the animations mimicked the chat audio files. Every chat line for each character was broken into a 1/15 of a second "pose, mouth, eye" setting which became the structure used to describe character animation. A zero for the eye or mouth position meant to use the pose's eye or mouth. The audio lines were then mapped to various response categories like "raise", "fold," and "call."

 

// ANIMATION: POSE, MOUTH, EYE FRAMES
char Pchar_buff[10][1000][3]={
//YVETTE: "Wow,good hand"
{{1, 3, 0},{1, 7, 0},{1, 7, 5},{1, 1, 5},{1, 1, 5},{1, 1, 5},{1, 1, 5},
{1, 1, 5},{1, 1, 5},{1, 6, 5},{1, 7, 5},{1, 7, 5},{1, 7, 0},
{1, 3, 0},{1, 3, 0},{1, 3, 0},{2,10, 0},{2, 6, 5},{2, 6, 5},{2,10, 5},
{2, 3, 5},{2,10, 5},{2, 1, 5},{2, 1, 5},{2, 1, 5},{2, 1, 5},

// CORRESPONDING AUDIO FILES
char CharAudio[10][30][30]={
{ // Yvette
{"\\Yvette\\GOODHAND.WAV"}, {"\\Yvette\\likethat2.WAV"},

void LoadTalkerPic(int pl, int st) // pl is player, st is start line
{
int stoffset=0,i,xpose,xmouth,xeyes;
BOOL flag; DWORD startTime=0;
DWORD Msec7=67; // 67 ms (67/1000) is close to 1/15 of a second
RECT prc;

CurPose= 9; // force a change
CurMouth= 0;
CurEyes= 0;

// Locate the line to have character say
for(i=0;i st;i++)
Stoffset+= Pchar_offset[pl][i];

// Have character perform 1/15 second animation: pose, mouth and eyes
for(i=0;i>Pchar_offset[pl][st];i++){
// Get from the above chat structure the pose
xpose= (int)Pchar_buff[pl][stoffset+i][0];
Xmouth=0;
xeyes= 0;
// Get from the above chat structure the mouth frame if((int)Pchar_buff[pl][stoffset+i][1]>0)
xmouth= (int)Pchar_buff[pl][stoffset+i][1]+5;
// Get from the above chat structure the eye frame if((int)Pchar_buff[pl][stoffset+i][2]>0)
xeyes= (int)Pchar_buff[pl][stoffset+i][2];
// Make the character talk for 1/15 of a second MakeCharTalk(0,pl,xpose,xeyes,xmouth);
// Start the audio after the first frame is displayed
if(i==0){
if(strlen(CharAudio[pl][st])>0){
strcpy(WAVfname,".\\WAV"); strcat(WAVfname,CharAudio[pl][st]);
NewChatSound(WAVfname,0);
PlayChat();
}
} // i==0
} // i loop
}

 

Addictive Gaming Techniques
Poker Challenge has several interesting gaming concepts that draw the player deeper into the game play. Players start off with $2,500 and no reputation points on the first level of the Poker Palace. They can enter the tournament or non-tournament poker room, view the prize room (initially it's empty), see the elevator (initially blocked by a bouncer), play slots and view their statistics. Curiosity and fun game play will propel the player to play in the non-tournament poker room to raise enough money to enter the tournaments. Through winning at tournaments, player earns reputation points, valuable prizes and money. As they increase their reputation points, the other floors open up where the opponents play tougher and high stake games are available. Eventually, through game play and word of mouth, players will learn about a secret poker game for $2.5 million and the World Championship which is only achievable through winning enough reputation points from the third floor of the Poker Palace. As the players win tournaments, the prize room will fill up. Until then, players will wonder what valuable prizes go in the prize room slots. There are also a few hidden "Easter eggs" for players to discover. The statistics tables are also updated as the player enters each poker room. In the non-tournament rooms the player can decide which poker variation to play. While in a tournament room, only one variation of poker is played for the 20 hands. The humorous and well-animated 4-player mode is very addictive and immerses the player into the poker atmosphere. The slot room is an extra feature that promotes Phantom EFX's first title. Hopefully this winter's holiday season, many players will enjoy what I did this summer.

______________________________________________________

 

Read more about:

Features
Daily news, dev blogs, and stories from Game Developer straight to your inbox

You May Also Like