Sophie

Sophie

distrib > Mandriva > 2010.2 > x86_64 > by-pkgid > 219d4374ba8edcb72a3dd34b31551351 > files > 50

lib64poker-eval-devel-136.0-1mdv2010.1.x86_64.rpm

/*
 *  Copyright 2006 Michael Maurer <mjmaurer@yahoo.com>, 
 *                 Brian Goetz <brian@quiotix.com>, 
 *                 Loic Dachary <loic@dachary.org>, 
 *                 Tim Showalter <tjs@psaux.com>
 *
 * This program gives you software freedom; you can copy, convey,
 * propagate, redistribute and/or modify this program under the terms of
 * the GNU General Public License (GPL) as published by the Free Software
 * Foundation (FSF), either version 3 of the License, or (at your option)
 * any later version of the GPL published by the FSF.
 *
 * This program is distributed in the hope that it will be useful, but
 * WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the GNU
 * General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License along
 * with this program in a file in the toplevel directory called "GPLv3".
 * If not, see <http://www.gnu.org/licenses/>.
 */
/* $Id: pokenum.c 5146 2008-12-04 03:11:22Z bkuhn $
   Example showing how to calculate pot equity using the enumeration functions.
   See also hcmp2.c and hcmpn.c for slightly lower level examples.

Note: games that use the joker are not yet implemented, though listed below.

Typical usage: 
$ pokenum [-mc niter] [-t] [-O]
          [-h|-h8|-o|-o8|-7s|-7s8|-7snsq|-r|-5d|-5d8|-5dnsq|-l|-l27]
          <pocket1> - <pocket2> - ... [ -- <board> ] [ / <dead> ]
      -t     terse output (one line, list of EV values)
      -O     compute and output detailed relative rank ordering histogram
      -mc    sample monte-carlo style instead of full enumeration
      -h     holdem hi (default)
      -h8    holdem hi/lo 8-or-better
      -o     omaha hi
      -o8    omaha hi/lo 8-or-better
      -7s    7-card stud hi
      -7s8   7-card stud hi/lo 8-or-better
      -7snsq 7-card stud hi/lo no stinking qualifier
      -r     7-card stud ace-to-5 low (razz)
      -5d    5-card draw hi (with joker)
      -5d8   5-card draw hi/lo 8-or-better (with joker)
      -5dnsq 5-card draw hi/lo no stinking qualifier (with joker)
      -l     5-card draw ace-to-5 lowball (with joker)
      -l27   5-card draw deuce-to-seven lowball

Streaming usage:
$ pokenum -i
followed by lines on stdin, one enumeration request per line, for example:
  -t -h Ac 7c - 5s 4s - Ks Kd
  -t -h Ac 7c - 5s 4s - Ks Kd -- 7h 2c 3h
  -t -h Ac 7c - 5s 4s - Ks Kd -- 7h 2c 3h 4d
  -t -mc 10000 -l27 5h 4h 3h / 5s Qd - 9s 8h 6d / Ks Kh

Use '-' between each player (optional in flop games).
Use '--' before the board (if any).
Use '/' before dead cards (can appear within a hand for discards).
Use 'Xx' for the joker.

Examples:

$ pokenum -h Ac 7c - 5s 4s - Ks Kd
$ pokenum -h Ac 7c 5s 4s Ks Kd
$ pokenum -h Ac 7c 5s 4s Ks Kd -- 7h 2c 3h

$ pokenum -o As Kh Qs Jh - 8h 8d 7h 6d
$ pokenum -o As Kh Qs Jh 8h 8d 7h 6d
$ pokenum -o As Kh Qs Jh 8h 8d 7h 6d -- 8s Ts Jc

$ pokenum -7s As Ah Ts Th 8h 8d - Kc Qc Jc Td 3c 2d
$ pokenum -7s As Ah Ts Th 8h 8d - Kc Qc Jc Td 3c 2d / 5c 6c 2s Jh

$ pokenum -l 7h 5s 3d Xx / Kd - 9s 8h 6d 4c / 8c
$ pokenum -l27 5h 4h 3h 2h / 5s - 9s 8h 6d 4c / Kd
$ pokenum -mc 10000 -l27 5h 4h 3h / 5s Qd - 9s 8h 6d / Ks Kh

   Michael Maurer, Apr 2002
*/

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <errno.h>

#include "poker_defs.h"
#include "enumdefs.h"

static int
parseArgs(int argc, char **argv,
          enum_game_t *game, enum_sample_t *enumType, int *niter,
          StdDeck_CardMask pockets[], StdDeck_CardMask *board,
          StdDeck_CardMask *dead, int *npockets, int *nboard,
          int *orderflag, int *terse) {
  /* we have a type problem: we define the masks here as
     StdDeck_CardMask, which makes it impossible to hold jokers.
     we need to redesign some of the deck typing to make this work... */
  enum_gameparams_t *gameParams = enumGameParams(game_holdem);
  enum { ST_OPTIONS, ST_POCKET, ST_BOARD, ST_DEAD } state;
  int ncards;
  int card;
  int i;

  state = ST_OPTIONS;
  *npockets = *nboard = ncards = 0;
  *terse = 0;
  *orderflag = 0;
  *game = game_holdem;
  *enumType = ENUM_EXHAUSTIVE;
  StdDeck_CardMask_RESET(*dead);
  StdDeck_CardMask_RESET(*board);
  for (i=0; i<ENUM_MAXPLAYERS; i++)
    StdDeck_CardMask_RESET(pockets[i]);
  while (++argv, --argc) {
    if (state == ST_OPTIONS) {
      if (argv[0][0] != '-') {
        state = ST_POCKET;
        argv--; argc++;
      } else {
        if (strcmp(*argv, "-mc") == 0) {
          *enumType = ENUM_SAMPLE;
          if (argc < 1)
            return 1;
          *niter = strtol(argv[1], NULL, 0);
          if (*niter <= 0 || errno != 0)
            return 1;
          argv++; argc--;                       /* put card back in list */
        } else if (strcmp(*argv, "-t") == 0) {
          *terse = 1;
        } else if (strcmp(*argv, "-O") == 0) {
          *orderflag = 1;
        } else if (strcmp(*argv, "-h") == 0) {
          *game = game_holdem;
        } else if (strcmp(*argv, "-h8") == 0) {
          *game = game_holdem8;
        } else if (strcmp(*argv, "-o") == 0) {
          *game = game_omaha;
        } else if (strcmp(*argv, "-o8") == 0) {
          *game = game_omaha8;
        } else if (strcmp(*argv, "-7s") == 0) {
          *game = game_7stud;
        } else if (strcmp(*argv, "-7s8") == 0) {
          *game = game_7stud8;
        } else if (strcmp(*argv, "-7snsq") == 0) {
          *game = game_7studnsq;
        } else if (strcmp(*argv, "-r") == 0) {
          *game = game_razz;
        } else if (strcmp(*argv, "-5d") == 0) {
          *game = game_5draw;
        } else if (strcmp(*argv, "-5d8") == 0) {
          *game = game_5draw8;
        } else if (strcmp(*argv, "-5dnsq") == 0) {
          *game = game_5drawnsq;
        } else if (strcmp(*argv, "-l") == 0) {
          *game = game_lowball;
        } else if (strcmp(*argv, "-l27") == 0) {
          *game = game_lowball27;
        } else {                                /* unknown option switch */
          return 1;
        }
        if ((gameParams = enumGameParams(*game)) == NULL)
          return 1;
      }
      
    } else if (state == ST_POCKET) {
      if (strcmp(*argv, "-") == 0) {            /* player delimiter */
        if (ncards > 0) {                       /* is a player pending? */
          if (ncards < gameParams->minpocket)   /* too few pocket cards */
            return 1;
          (*npockets)++;
          ncards = 0;
        }
        state = ST_POCKET;
      } else if (strcmp(*argv, "--") == 0) {    /* board prefix */
        state = ST_BOARD;
      } else if (strcmp(*argv, "/") == 0) {     /* dead card prefix */
        state = ST_DEAD;
      } else {
        if (*npockets >= ENUM_MAXPLAYERS)           /* too many players */
          return 1;
        if (DstringToCard(StdDeck, *argv, &card) == 0) /* parse error */
          return 1;
        if (StdDeck_CardMask_CARD_IS_SET(*dead, card)) /* card already seen */
          return 1;
        StdDeck_CardMask_SET(pockets[*npockets], card);
        StdDeck_CardMask_SET(*dead, card);
        ncards++;
        if (ncards == gameParams->maxpocket) {  /* implicit player delimiter */
          (*npockets)++;
          ncards = 0;
        }
      }
      
    } else if (state == ST_BOARD) {
      if (strcmp(*argv, "/") == 0) {            /* dead card prefix */
        state = ST_DEAD;
      } else {
        if (DstringToCard(StdDeck, *argv, &card) == 0) /* parse error */
          return 1;
        if (StdDeck_CardMask_CARD_IS_SET(*dead, card)) /* card already seen */
          return 1;
        if (*nboard >= gameParams->maxboard) /* too many board cards */
          return 1;
        StdDeck_CardMask_SET(*board, card);
        StdDeck_CardMask_SET(*dead, card);
        (*nboard)++;
      }
      
    } else if (state == ST_DEAD) {
      if (strcmp(*argv, "-") == 0) {            /* player delimiter */
        if (ncards > 0) {                       /* is a player pending? */
          if (ncards < gameParams->minpocket)   /* too few pocket cards */
            return 1;
          (*npockets)++;
          ncards = 0;
        }
        state = ST_POCKET;
      } else {
        if (DstringToCard(StdDeck, *argv, &card) == 0) /* parse error */
          return 1;
        if (StdDeck_CardMask_CARD_IS_SET(*dead, card)) /* card already seen */
          return 1;
        StdDeck_CardMask_SET(*dead, card);
      }
    }
  }
  if (ncards > 0) {                             /* is a player pending? */
    if (ncards < gameParams->minpocket)         /* too few pocket cards */
      return 1;
    (*npockets)++;
    ncards = 0;
  }
  if (*npockets == 0)                           /* no players seen */
    return 1;
  return 0;
}

#define MAX_ARGS 100
#define BUF_LEN 1000

int 
main(int argc, char **argv) {
  enum_game_t game;
  enum_sample_t enumType;
  int niter = 0, npockets, nboard, err, terse, orderflag;
  StdDeck_CardMask pockets[ENUM_MAXPLAYERS];
  StdDeck_CardMask board;
  StdDeck_CardMask dead;
  enum_result_t result;
  int fromStdin;

  fromStdin = (argc == 2 && !strcmp(argv[1], "-i"));
  if (fromStdin)
    argv = (char **) malloc(MAX_ARGS * sizeof(char *));
  do {
    err = 0;
    enumResultClear(&result);
    if (fromStdin) {	/* read one line from stdin, split into argv/argc */
      char buf[BUF_LEN], *p;
      if (fgets(buf, sizeof(buf), stdin) == NULL)
        break;
      argc = 0;
      argv[argc++] = "pokenum";
      p = strtok(buf, " \t\r\n");
      while (p != NULL) {
        argv[argc++] = p;
        p = strtok(NULL, " \t\r\n");
      }
    }
    if (parseArgs(argc, argv, &game, &enumType, &niter,
                  pockets, &board, &dead, &npockets, &nboard,
                  &orderflag, &terse)) {
      if (fromStdin) {
        printf("ERROR\n");
      } else {
        printf("single usage: %s [-t] [-O] [-mc niter]\n", argv[0]);
        printf("\t[-h|-h8|-o|-o8|-7s|-7s8|-7snsq|-r|-5d|-5d8|-5dnsq|-l|-l27]\n");
        printf("\t<pocket1> - <pocket2> - ... [ -- <board> ] [ / <dead> ] ]\n");
        printf("streaming usage: %s -i < argsfile\n", argv[0]);
      }
      err = 1;
    } else {
      if (enumType == ENUM_EXHAUSTIVE) {
        err = enumExhaustive(game, pockets, board, dead, npockets, nboard,
                             orderflag, &result);
      } else if (enumType == ENUM_SAMPLE) {
        err = enumSample(game, pockets, board, dead, npockets, nboard, niter,
                         orderflag, &result);
      } else {
        err = 1;
      }
      if (err) {
        if (fromStdin)
          printf("ERROR\n");
        else
          printf("enumeration function failed err=%d\n", err);
      } else {
        if (terse)
          enumResultPrintTerse(&result, pockets, board);
        else
          enumResultPrint(&result, pockets, board);
      }
    }
    enumResultFree(&result);
    fflush(stdout);
  } while (fromStdin);
  return err;
}