/*
**  Program to compute basic strategy table, taking into account
**  the removal of cards from the deck.
*/
/*********************************************************************/
#include <stdio.h>
/*********************************************************************/
/*
**  The following array tells how many of each card there are in the deck
**
**                       2   3   4   5   6   7   8   9   10   A      */
int deck[12] = { 0 , 0 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 4 , 16 , 4 };
/*********************************************************************/
static int hit=0;
/*********************************************************************/
double dealer_function (
/*
**  Calculate player's expectation based on dealer's play
*/
    int          player,     /*  I  Total of player's hand */
    int          dealer,     /*  I  Total of dealer's hand */
    int          soft )      /*  I  =1 if dealer's hand is soft */
{
    double expect,sum,out;
    int nbsum,ii;

    if (dealer > 21 && soft) {
        dealer -= 10;
        soft = 0;
    }

    if (dealer > 17 || (dealer==17 && !soft)) {

        if (dealer > 21 || player > dealer) {
            out = 1.0;
        } else if (player < dealer) {
            out = -1.0;
        } else {
            out = 0.0;
        }

    } else {

        sum = 0.0;
        nbsum = 0;
        for (ii=2; ii<12; ii++) {
            if (deck[ii]) {
                deck[ii]--;
                if (ii==11) soft=1;
                expect =  dealer_function (player, dealer+ii, soft);
                deck[ii]++;
                sum += expect * deck[ii];
                nbsum += deck[ii];
            }
        }
        out = sum / nbsum;
    }

    return (out);
}
/*********************************************************************/
double player_function (
/*
**  Calculate player's expectation
*/
    int          player,     /*  I  Total of player's hand */
    int          soft,       /*  I  =1 if player's hand is soft */
    int          upcard )    /*  I  Dealer's upcard */

{
    double ehit,estand,expect,sum,out;
    int ii,jj,nbsum;

    /* Check for player busted */

    if (player > 21) {
        if (soft) {
            player -= 10;
            soft = 0;
        } else {
            return (-1.0);
        }
    }

    /* Calculate expectation if player stands */

    estand = dealer_function (player, upcard, (upcard==11) );

    /* Calculate expectation if player hits */

    if (player == 21) {

        ehit = -1.0;

    } else {

        sum = 0.0;
        nbsum = 0;
        for (ii=2; ii<12; ii++) {
            if (deck[ii]) {
                deck[ii]--;
                if (ii==11) soft=1;
                expect = player_function (player+ii, soft, upcard);
                deck[ii]++;
                sum += expect * deck[ii];
                nbsum += deck[ii];
            }
        }
        ehit = sum / nbsum;
    }

    if (ehit > estand) {
        hit = 1;
        out = ehit;
    } else {
        hit = 0;
        out = estand;
    }

    return (out);
}
/*********************************************************************/
int main () {

    char tmp[10];
    int player,upcard;
    double expect;
    int soft=0;
    int p1,p2,ii;

    printf ("        2  3  4  5  6  7  8  9 10  A\n\n");

    for (player=20; player>11; player--) {

        for (p1=player-10; p1<=player-p1; p1++) {

            p2 = player - p1;

            sprintf (tmp, "%d,%d", p1, p2);
            printf ("%5s: ", tmp);
            fflush (stdout);

            deck[p1]--;
            deck[p2]--;

            for (upcard=2; upcard<12; upcard++) {

                deck[upcard]--;

                expect = player_function (player, soft, upcard);

                deck[upcard]++;

                if (hit) printf (" H ");
                else printf (" S ");
                fflush (stdout);
            }

            deck[p1]++;
            deck[p2]++;

            printf ("\n");
        }

        printf ("\n");
    }
    return (0);
}
/*********************************************************************/