BookmarkSubscribeRSS Feed
🔒 This topic is solved and locked. Need further help from the community? Please sign in and ask a new question.
brophymj
Quartz | Level 8

Hi

I'm trying to build a program that generates poker game results based on predetermined assumptions about the players. I'm trying to come up with a simple enough algorithm that ranks the hands of players and allocates chips to the best hand. In Texas Holdem there are 2,598,960 unique poker hands but this can be reduced to 7462 distinct poker hand values.

A couple of initial questions. The program will allocate two distinct poker cards from a deck - i've coded them such that 13H is the Ace of Hearts for example. I was going to have a table with the 52 card values and have the cards generated based on the rand function that picks a value between 1 and 52, however, it just occurred to me that when the program allocated a hand to the next player it can't repeat either of the cards allocated to the previous player. The data set I'm thinking will look someting like this:

Player 1Player 2Player 3Player 4Player 5Player 6Shared Card 1Shared Card 2Shared Card 3
13H02C09S07S12D02D06H03D01D
..................

Once the cards are allocated (so all cards are unique as mentioned above), the algorithm then needs to lookup a table so each player is given a value between 1 and 7462 and the chips are allocated based on the highest hand value.

I need to be able to run this algorithm 1000s of times so I can derive a distribution of profit based on the assumptions entered into the alogorithm so speed is important. I've spent a couple of hours on this so far and I'm having some trouble getting started as I'm not sure of a function that restricts the random function from repeating the same value and I'm also concerned that If I have a table that has every possible poker hand that the program will perform very slowly.

Any help would be much appreciated.

Regards

Matthew

1 ACCEPTED SOLUTION

Accepted Solutions
StatsGeek
SAS Employee

I have great news for you. The SAS University Edition includes SAS/IML and is free!

Free Statistical Software, SAS University Edition | SAS

The SAS University Edition is for personal use, but it is not limited to academia. That is, you don't have to be an enrolled student to access it. Note that this is intended for learning purposes only, so don't use it for paid work. Enjoy!

Best,

Steve

View solution in original post

15 REPLIES 15
ballardw
Super User

Something like this perhaps? This generates a number of data sets specified by the parameter Runs, for given number of Players which better be less than 25. The sets are named sequentially as hand1, hand2 etc. with a player identifier, his two dealt cards as card1 and card2 and 4 common cards named common1 through 4.

%macro holdem(Runs=,players=);
%do i = 1 %to &runs;
data cards;
length rank $ 2 suit $1 card $ 3;;
do rank='A','1','2','3','4','5','6','7','8','9','10','J','Q','K';
  do suit = 'C','D','H','S';
   card= cats(rank,suit);
   rand= ranuni(546);
  output;
end;
end;
drop rank suit;
run;
proc sort data=cards; by rand;run;
%let p = &players;/* number of players*/
data deal;
     set cards;  /*after resort on the random value*/
     retain counter ;
     counter +1;
     player = mod(counter,&p)+1;
     if counter gt (&p*2) then do;
   common= 1;/* the common cards*/
   player = .;
  end;
     if counter gt (&p*2 + 4) then stop;
run;
proc sort data=deal; by player;run;
proc transpose data=deal(where=(player ne .)) prefix=card
     out=players;
by player;
var card;
run;

proc transpose data=deal(where=(player = .)) prefix=common
     out=common;
by player;
var card;
run;

proc sql;
create table hand&i as
select a.player, a.card1, a.card2, b.common1,b.common2,b.common3,b.common4
from players as a , common as b
;
quit;

%end;
%mend;

%holdem(Runs=3,players=4);

Its up to you to combine/rank the card combinations and assign your values. Options would be to include the run counter in the hand set, add ",&i as RunCounter" after the b.common4 in the last step.

If you want all of the datasets combined
data allhand;

     set hand: ;

run;

should do it.

Aman4SAS
Obsidian | Level 7

Hi,

do rank='A','1','2','3','4','5','6','7','8','9','10','J','Q','K';


in this you are creating 56 cards,

i guess it should like : do rank='A','2','3','4','5','6','7','8','9','10','J','Q','K';



brophymj
Quartz | Level 8

Hi Ballardw

Thank you very much for your detailed and helpful reply. I've worked through the code and I now understand the logic. The only puzzling thing is that when I execute the macro, my hand1, 2 and 3 are the same. I went through each step and the first data step doesn't seem to generate a different random set of numbers each time the macro loops. I keep getting .98956 as the first entry in the column rand. Do you know what might be causing this?

Kind Regards

Matthew

brophymj
Quartz | Level 8

Hi Ballardw

Just following up on my message above re the ranuni function - would you have an idea of why this is happening?

Thanks

Matthew

ballardw
Super User

The repeated runs are likely the fixed seed in the random generator. It's a feature that allows duplication of random sequences and I used that for debugging. So leave the parantheses emtpy in the ranuni call.

Sorry about the A 1 confusion.

brophymj
Quartz | Level 8

Hi ballardw

I tried putting it in ranuni() instead of ranuni(546) and I got an error message saying "The Ranuni function Call does not have enopugh arguments"...

StatsGeek
SAS Employee

Hi brophymj,

You can't call ranuni without arguments. Instead, use ranuni(0).

Best,

Steve

ballardw
Super User

use &i in the ranuni. That will generate a different stream for each run.

StatsGeek
SAS Employee

Matthew,

Given that you want to run the simulation for 1000's of hands, you should consider running the simulation in IML. Using macros to run the simulation using data steps may be time consuming. For example, I ran the above code for 10,000 runs with 9 players. The simulation took 9:56. In contrast, running the simulation under the same conditions in IML with the code shown below took under a second.

Best,

Steve

proc iml;

  nruns = 10000; *Specify number of runs;

  nplayers = 9; *Specify number of players;

  rank = {A,1,2,3,4,5,6,7,8,9,10,J,Q,K};

  suit = {C,D,H,S};

  do i = 1 to 4;

    do j = 1 to 14;

      deck = deck // concat(strip(rank),suit);

    end;

  end;

  free rank suit;

  hands = J(nruns,nplayers+5,'                      ');

 

  do i = 1 to nplayers;

    name = name || ({player}+strip(char(i)));

  end;

  name = name || {community1 community2 community3 community4 community5};

  mattrib hands colname=name;

  do run = 1 to nruns;

    order = j(52,1,0);

    call randgen(order,'uniform');

    call sortndx(index,order);

    deck_shuffled = deck[index];

    card=1;

    do player = 1 to nplayers;

      hands[run,player] = concat(deck_shuffled[card,],{", "},deck_shuffled[card+1,]);

      card=card+2; 

    end;

    hands[run,nplayers+1:nplayers+5] = deck_shuffled[card:card+4]`;

  end;

  create hands from hands [colname=name];

  append from hands;

  close hands;

quit;

SteveDenham
Jade | Level 19

Strongly recommend the IML approach.  Back with data step, I suggest:

call streaminit(seed=<insert odd integer value>);

data want;

<some code>;

rand=rand('UNIFORM");

<maybe more code>;

run;

Someplace out there is a bunch of notes regarding the superiority of the RAND function to RANUNI.

Steve Denham

brophymj
Quartz | Level 8

Unfortunately I don't have that feature in the version of sas I use - it's my company's software so I can't get it. I think it's prohibitively expensive.

Do you have code for a card evaluator as well i.e. somthing that reads any 5 card hand and allocates a rank so you can determine which player has the best hamnd. 

StatsGeek
SAS Employee

I have great news for you. The SAS University Edition includes SAS/IML and is free!

Free Statistical Software, SAS University Edition | SAS

The SAS University Edition is for personal use, but it is not limited to academia. That is, you don't have to be an enrolled student to access it. Note that this is intended for learning purposes only, so don't use it for paid work. Enjoy!

Best,

Steve

brophymj
Quartz | Level 8

Thank you Stephen

Can I ask, what is IML and how is it different? I will definitely use it if it's faster as I want to simulate 100s of games based on player assumptions regarding players for quick 6 player games i.e. ones that only last 25 minutes or so.

The program will incorporate everything from increasing blinds to probailities of pushing all-in etc. I will start with a simple game and build it up.

Is the coding much different in IML?

Also, would you have the code or advice for evaluating poker hands?

I play lots of online poker and I'm using this as a way of looking alligning my strategy closer to an optimal approach.

Thanks

sas-innovate-2024.png

Join us for SAS Innovate April 16-19 at the Aria in Las Vegas. Bring the team and save big with our group pricing for a limited time only.

Pre-conference courses and tutorials are filling up fast and are always a sellout. Register today to reserve your seat.

 

Register now!

What is Bayesian Analysis?

Learn the difference between classical and Bayesian statistical approaches and see a few PROC examples to perform Bayesian analysis in this video.

Find more tutorials on the SAS Users YouTube channel.

Click image to register for webinarClick image to register for webinar

Classroom Training Available!

Select SAS Training centers are offering in-person courses. View upcoming courses for:

View all other training opportunities.

Discussion stats
  • 15 replies
  • 4321 views
  • 4 likes
  • 6 in conversation