/* 
 * fish.h
 * Copyright 1999 Brian Goetz
 * 
 * An example program for the poker hand evaluation library.
 * It is so named because it performs the same action as a program written 
 * by Roy Hashimoto a long time ago.  
 * 
 * Given a (possibly empty) set of input cards, a (possibly empty)
 * set of dead cards, and the number of cards in a hand, this program
 * computes the distribution of each type of possible hand type after
 * exhaustively enumerating the set of possible hands which include the input
 * cards and exclude the dead cards.  
 *
 * 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/>.
 */

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

#include "poker_defs.h"
#include "inlines/eval_type.h"

/* added the following line */
#include "inlines/eval.h"

#define d_flag 1 /* dead flag   - 2 cards  (my pocket cards)  */ 
                /* example: -d As Ks */

#define n_flag 2 /* number flag - number of cards in play 
                 * examples:     2 - pre-flop
                 *               5 - after-flop
                 *               6 - turn 
                 *               7 - river 
                 */

#define o_flag 3 /* opponent flag - number of opponents
                 * example:  -o 2, -o 3, ... , -o 8 
                 *
                 * this number referes to opponents and doesn't
                 * include you the player.
                 */

#define b_flag 4 /* board flag - following cards are on the board
                  * example: -b Th Jh 3s
                  * example: -b Th Jh 3s 8c
                  * example: -b Th Jh 3s 8c Ac
                  *
                  * If the -b flag is not seen it indicates that no
                  * cards are on the board
                  */

int gNCards, gNPegged, gNDead;
CardMask gDeadCards, gPeggedCards;

float opponents = 0;

static void
parseArgs(int argc, char **argv) {
  int i, c;
  int flag;  

  /* no flags set */
  flag = 0;

  for (i = 1; i < argc; ++i) {
    if (argv[i][0] == '-') {
      if (strcmp(argv[i], "-n") == 0) {
	if (++i == argc) goto error;
        flag = n_flag;
	gNCards = atoi(argv[i]);
      } 
      else if (strcmp(argv[i], "-o") == 0) {
	if (++i == argc) goto error;
        opponents = atoi(argv[i]);
      }
      else if (strcmp(argv[i], "-d") == 0) {
        flag = d_flag;
	if (++i == argc) goto error;
        if (Deck_stringToCard(argv[i], &c) == 0)
          goto error;
        if (!CardMask_CARD_IS_SET(gDeadCards, c)) {
          CardMask_SET(gDeadCards, c);
          ++gNDead;
        }
      } 
      else 
        goto error;
    } else {
      if (Deck_stringToCard(argv[i], &c) == 0)
        goto error;
      if (!CardMask_CARD_IS_SET(gPeggedCards, c)) {
        CardMask_SET(gPeggedCards, c);
        ++gNPegged;
      }
    }
  }

  return;

 error:
  fprintf(stderr, "Usage: fish [ -o opponents ] [ -d dead-card ] [-n n_cards] [ cards ]\n");
  exit(0);
}


uint32 totals[HandType_LAST+1];

static void dump_totals(void) {
  int i;
  int sum = 0;
  float EV = 0.0;        // working variable for percentage of HandTypes
  float wayOne = 0.0;
  float wayTwo = 0.0;

  // total of all HandTypes */
  // example: 20 straights and 3 flushes result in sum becoming 23
  for (i = HandType_FIRST; i <= HandType_LAST; i++)
    sum = sum + totals[i];
  
  for (i = HandType_FIRST; i <= HandType_LAST; i++)
    if ( totals[i] != -2 ) {  // what does this mean?
      
      EV = ( (float) totals[i] / (float) sum);  // HandType percentages

//      wayOne = 1.0 - pow((1.0 - ((float) totals[i]) / (float) sum), opponents);

//    wayTwo = EV -  pow((                                    EV ), opponents);
//      wayTwo = ((float) totals[i]  / (float) sum) - ((float) totals[i]  / (float) sum) ;
//      wayTwo = EV - ((float) totals[i]  / (float) sum) ;

      wayOne =       1.0 - pow((                      1.0 - EV ), opponents);
      wayTwo = EV - pow(((float) totals[i]  / (float) sum), opponents) ;


          // printf("P(%s | %d) : %#.3g\n",
          // printf("P(%s | %d) : %#.3g\n",

      if ( opponents == 0 ) {    // Probability I will have a HandType
          printf("P(%s | %d) : %4.1f\n", \
                                handTypeNamesPadded[i], \
                                (int) 0, \
                                100.0 * EV ); 
      }
      else { // Probability Opponent will not have HandType 
          printf("P(%s | %d) : %4.1f\n", \
                                handTypeNamesPadded[i], \
                                (int) opponents, \
                                100.0 * wayOne ); 
      }
    }
  
}

int 
main(int argc, char **argv) {
  CardMask hand, deadCards, cards;
  int handtype, nHands=0;

  gNCards = 7;
  CardMask_RESET(gDeadCards);
  CardMask_RESET(gPeggedCards);
  parseArgs(argc, argv);
  CardMask_OR(deadCards, gDeadCards, gPeggedCards);

  /* We use the fast and small EVAL_TYPE evaluator, since we only care 
     about the hand type, not the particular cards.  If we cared about the
     individual cards, we'd use EVAL_N.  
   */
  ENUMERATE_N_CARDS_D(cards, (gNCards-gNPegged), deadCards,
                      {
                        CardMask_OR(hand, cards, gPeggedCards);
                        handtype = Hand_EVAL_TYPE(hand, gNCards);
                        ++nHands;
                        ++totals[handtype];
                      });

  printf("handtype is: %d\n", handtype);
  printf("%d boards", nHands);
  if (gNPegged > 0) 
    printf(" containing %s ", Deck_maskString(gPeggedCards));
  if (gNDead) 
    printf(" with %s removed ", Deck_maskString(gDeadCards));
  printf("\n");

  dump_totals();
  return 0;
}
