Category : A Collection of Games for DOS and Windows
Archive   : S21.ZIP
Filename : S21.C

 
Output of file : S21.C contained in archive : S21.ZIP
/*
** Blackjack Player System Simulator
** Copyright (C) 1990 Henry C. Clark
*/

#include "s21.h" /* structures, equates */
#include "s21.pro" /* all function prototypes */

/* the shoe of cards */

#define DECK_COUNT 6

CARD shoe[DECK_COUNT*52]; /* the shoe of cards */

int dealout; /* 1 to shoecut */
int shoecut; /* 190 to 226 */

/* zero origin value array, aces are treated as 1 */

int count[13] = { 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 10, 10, 10 };

/* zero origin face type array */

char face[13] = { 'A', '2', '3', '4', '5', '6', '7', '8',
'9', 'T', 'J', 'Q', 'K' };

/* zero origin suit type array, used only for display */

/* char color[4] = { 'C', 'D', 'H', 'S' };
*/

/* test shoe of cards to check most play types */

/* int testdeck[DECK_COUNT*52] = {
** 1, 1, 1, 1, 1, 1, 1, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 2, 6, 2, 3, 3, 4, 2, 3, 1, 2, 1, 10,
** 2, 2, 2, 2, 2, 2, 2, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 8, 6, 1, 2,10, 6,10, 1,10,10,
** 3, 3, 3, 3, 3, 3, 3, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 7,10,10,10,10,10,10,10,
** 4, 4, 4, 4, 4, 4, 4, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 6,10,10,10,10,10,10,10,
** 5, 5, 5, 5, 5, 5, 5, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 5,10,10,10,10,10, 10,
** 6, 6, 6, 6, 6, 6, 6, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 4,10,10,10,10, 10,
** 7, 7, 7, 7, 7, 7, 7, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 10,10, 1, 10,
** 8, 8, 8, 8, 8, 8, 8, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 10,10, 10,
** 9, 9, 9, 9, 9, 9, 9, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 10, 10,
** 10,10,10,10,10,10,10, 2,
** 1, 2, 3, 4, 5, 6, 7,10,
** 10,
**
** 1, 1, 1, 2, 2, 2, 3, 2,
** 8, 9,10, 8, 9,10, 8,10,
** 10,10, 10,10,
** 3, 3, 4, 4, 4, 5, 5, 2,
** 9,10, 8, 9,10, 8, 9,10,
** 10,
** 5, 6, 6, 6, 7, 7, 7, 2,
** 10, 8, 9,10, 8, 9,10,10,
** 10,
** 8, 8, 8, 9, 9, 9,10, 2,
** 8, 9,10, 8, 9,10, 8,10,
** 10,8,1,10,10,10, 10,
** 10,10,2,
** 9,10,10,
** 10,
**
** 10,10,10,10,10,10,10
**
** };
*/

/* the players */

#define PLAYER_COUNT 7

PLAYER bettor[PLAYER_COUNT]; /* the players */

PLAYER house; /* the house */

extern CFA play_noagr[20][10]; /* play style 0 = no bust */
extern CFA play_std[20][10]; /* play style 1 = standard */

int seentens; /* number of ten value cards seen */
int handsplayed; /* hands played per shoe */

/* statistics */

long s_hands = 0l;
long s_wins = 0l;
long s_pushes = 0l;
long s_losses = 0l;
long s_deals = 0l;
long s_dealerbust = 0l;
long s_playerbust = 0l;
long s_dealerbj = 0l;
long s_playerbj = 0l;

int hihand;
long s_hihands = 0l;
long s_hiwins = 0l;
long s_hipushes = 0l;
long s_hilosses = 0l;


/*
** the program starts here
*/

int _cdecl main()
{
unsigned i, j;
int x;
long k;
int *seed = (int *)0x0000046C;

/* start random number generator from sys clock */
x = *seed;
srand(x);

/* give each player some money */
for ( i=0; i<7; i++ )
bettor[i].bankroll = 100.0;

/* give each player a playing style ( see bet and draw_player ) */
bettor[0].style = 1;
bettor[1].style = 1;
bettor[2].style = 1;
bettor[3].style = 1;
bettor[4].style = 1;
bettor[5].style = 1;
bettor[6].style = 1;

/* statistics header */
printf ( " P1 P2 P3 P4 P5 P6 P7 %%W %%P %%L %%DB %%PB %%DJ %%PJ %%HW %%HP %%HL\n" );

/* shuffle();
**
** for ( i=0; i ** {
** if ( ! (i % 26) )
** printf( "\n" );
** printf ( "%c ", shoe[i].type );
** }
** printf( "\n %d %d\n", dealout, shoecut );
*/

/* show need to shuffle before next deal */
dealout = DECK_COUNT*52;
shoecut = 0;

/* play a lot of hands */
for ( k=0; k<10000; k++ )
{

/* deal the cards */
deal();

/* for ( i=0; i<7; i++ )
** {
** for ( j=0; j **
** printf ( "%d:%c%c-%d ", i, bettor[i].firstcard, bettor[i].secondcard,
** bettor[i].value[j] );
** }
** printf ( "H:%c%c-%d\n", house.firstcard, house.secondcard,
** house.value[0] );
*/
/* draw cards according to styles */
play();

/* for ( i=0; i<7; i++ )
** {
** for ( j=0; j **
** printf ( "%d:%c%c-%d ", i, bettor[i].firstcard, bettor[i].secondcard,
** bettor[i].value[j] );
** }
** printf ( "H:%c%c-%d\n", house.firstcard, house.secondcard,
** house.value[0] );
*/

/* periodically show statistics */
if ( !(k % 500) )
show_stats();

} /* end for loop */

show_stats();
return(0);
}

/*
** show statistics, display the player bankrolls and the percentage
** of important game statistics
*/

int show_stats()
{
int i;

/* each player's bankroll */
for ( i=0; i<7; i++ )
printf ( "%4.f ", bettor[i].bankroll );

/* set totals */
s_hands = s_wins + s_pushes + s_losses;
s_hihands = s_hiwins + s_hipushes + s_hilosses;

/* display percentages ( 1000 X ) */
printf ( " %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld %3ld\n",
(s_wins*1000)/ (s_hands ? s_hands : 1),
(s_pushes*1000)/ (s_hands ? s_hands : 1),
(s_losses*1000)/ (s_hands ? s_hands : 1),
(s_dealerbust*1000)/ (s_deals ? s_deals : 1),
(s_playerbust*1000)/ (s_hands ? s_hands : 1),
(s_dealerbj*1000)/ (s_deals ? s_deals : 1),
(s_playerbj*1000)/ (s_hands ? s_hands : 1),
(s_hiwins*1000)/ (s_hihands ? s_hihands : 1),
(s_hipushes*1000)/ (s_hihands ? s_hihands : 1),
(s_hilosses*1000)/ (s_hihands ? s_hihands : 1)
);
return(1);
}

/*
** play, initial cards have been dealt, check for automatics wins and losses
** then let each player draw cards, finally, check who won
*/

int play()
{
unsigned i;

/* if dealer is showing an ace, and you have 21, you can get even money */
if ( house.firstcard == 'A' )
{
for ( i=0; i<7; i++ )
{
if ( bettor[i].bet )
if ( ( bettor[i].value[0] == 11 ) && ( bettor[i].ace[0] ) )
even_money( &(bettor[i]) );
}
}

/* if the dealer turns over a 21, you lose */
if ( ( house.value[0] == 11 ) && ( house.ace[0] ) )
{
s_dealerbj++; /* dealer blackjack */
for ( i=0; i<7; i++ )
{
if ( bettor[i].bet )

/* some places you tie */
/* if ( ( bettor[i].value[0] == 11 ) && ( bettor[i].ace[0] ) )
** push_money( &(bettor[i]) );
** else
*/
lose_money( &(bettor[i]) );
}
return(1);
}

/* if you have a 21, you win */
for ( i=0; i<7; i++ )
{
if ( bettor[i].bet )
if ( ( bettor[i].value[0] == 11 ) && ( bettor[i].ace[0] ) )
blackjack( &(bettor[i]) );
}

/* each player takes more cards according to the style of play */
for ( i=0; i<7; i++ )
{
if ( bettor[i].bet )
draw_player ( &(bettor[i]) );
}

/* the house takes more cards */
draw_house();

/* see who wins */
for ( i=0; i<7; i++ )
{
if ( bettor[i].bet )
win_lose ( &(bettor[i]) );
}
return(1);
}

/*
** even money bet is dealer shows ace, you have blackjack
*/

int even_money( PLAYER *x )
{
x->bankroll += ( x->bet * 2 ); /* take bet plus win amount */
x->bet = 0.0; /* show money was handled */
s_wins++; /* count a win */
if ( hihand ) /* check hi hand */
s_hiwins++; /* count a hi hand win */
return(1);
}

/*
** a push is a tie, both hands total the same
*/

int push_money( PLAYER *x )
{
x->bankroll += x->bet; /* take bet amount back */
x->bet = 0.0; /* show money was handled */
s_pushes++; /* count a tie */
if ( hihand ) /* check hi hand */
s_hipushes++; /* count a hi hand tie */
return(1);
}

/*
** the dealer won, note that the bet amount is already subtracted
** from the player's bankroll
*/

int lose_money( PLAYER *x )
{
x->bet = 0.0; /* show money was handled */
s_losses++; /* count a loss */
if ( hihand ) /* check hi hand */
s_hilosses++; /* count a hi hand loss */
return(1);
}

/*
** 21 in two cards
*/

int blackjack( PLAYER *x )
{
x->bankroll += ( x->bet * 2.5 ); /* take bet plus win amount */
x->bet = 0.0; /* show money was handled */
s_wins++; /* count a win */
if ( hihand ) /* check hi hand */
s_hiwins++; /* count a hi hand win */
s_playerbj++; /* player blackjack */
return(1);
}

/*
** compare the player's hand(s) to the dealer's
** a dealer bust value is 0, a player's bust value is -1
*/

int win_lose ( PLAYER *x )
{
int i;

for ( i=0; ihands; i++ )
{
if ( x->value[i] > house.value[0] ) /* player won */
{
x->bankroll += ( x->bet * 2 );
s_wins++;
if ( hihand )
s_hiwins++;
}
else
{
if ( x->value[i] == house.value[0] ) /* a tie */
{
x->bankroll += x->bet;
s_pushes++;
if ( hihand )
s_hipushes++;
}
else /* dealer won */
{
s_losses++;
if ( hihand )
s_hilosses++;
}
}
}
x->bet = 0.0; /* show money was handled */

return(1);
}

/*
** bet before the cards are dealt for each hand
** watch for high concentration of tens in the shoe, if so increase bet

*/

int bet()
{
unsigned i;
double x;

hihand = 0;
if ( handsplayed > 3 ) /* wait for three hands */
{
if ( ( seentens / handsplayed ) < 4 ) /* half the expected number */
hihand = 1;
}

for ( i=0; i<7; i++ )
{
switch ( bettor[i].style )
{
case 0:
{
x = 5.0;
if ( hihand )
{
x *= 2; /* double bet */

/* less than 1/4 the expected number of tens seen */
if ( ( seentens / handsplayed ) < 2 )
x *= 2; /* quadruple bet */
}
bettor[i].bet = x;
bettor[i].bankroll -= x; /* tally bet */
break;
}
case 1:
{
x = 5.0;
if ( hihand )
{
x *= 2;
if ( ( seentens / handsplayed ) < 2 )
x *= 2;
}
bettor[i].bet = x;
bettor[i].bankroll -= x;
break;
}
}
}
return(1);
}

/*
** player draws cards according to specified matrix, dependant upon
** the players current value, and the dealer's up card
*/

int draw_player ( PLAYER *x )
{
int showing;
int done;

showing = 11; /* default dealer shows ace */
switch ( house.firstcard )
{
case 'T' :
case 'J' :
case 'Q' :
case 'K' :
{
showing = 10; /* dealer show ten card */
break;
}
case '9' :
case '8' :
case '7' :
case '6' :
case '5' :
case '4' :
case '3' :
case '2' :
{
showing = (int) ( house.firstcard - '0' ); /* dealer shows other */
break;
}
}

/* player always has at least one hand */
done = 0;
while ( !done )
{
/* check for player bust */
if ( x->value[0] > 21 )
{
x->value[0] = -1;
s_playerbust++;
break;
}
/* according to playing style, choose matrix */
switch ( x->style )
{
case 0 :
{
/* call specific function through table of functions */
/* functions will return 0 if another card is wanted */
done = (*play_noagr [(x->value[0] - 2 )][(showing - 2) ] ) (x,0);
break;
}
case 1 :
{
done = (*play_std [(x->value[0] - 2 )][(showing - 2) ] ) (x,0);
break;
}
}
}

/* by splitting pairs, player may have up to four hands */
if ( x->hands > 1 )
{
done = 0;
while ( !done )
{
if ( x->value[1] > 21 )
{
x->value[1] = -1;
s_playerbust++;
break;
}
switch ( x->style )
{
case 0 :
{
done = (*play_noagr [(x->value[1] - 2 )][(showing - 2) ] ) (x,1);
break;
}
case 1 :
{
done = (*play_std [(x->value[1] - 2 )][(showing - 2) ] ) (x,1);
break;
}
}
}
}

if ( x->hands > 2 )
{
done = 0;
while ( !done )
{
if ( x->value[2] > 21 )
{
x->value[2] = -1;
s_playerbust++;
break;
}
switch ( x->style )
{
case 0 :
{
done = (*play_noagr [(x->value[2] - 2 )][(showing - 2) ] ) (x,2);
break;
}
case 1 :
{
done = (*play_std [(x->value[2] - 2 )][(showing - 2) ] ) (x,2);
break;
}
}
}
}

if ( x->hands > 3 )
{
done = 0;
while ( !done )
{
if ( x->value[3] > 21 )
{
x->value[3] = -1;
s_playerbust++;
break;
}
switch ( x->style )
{
case 0 :
{
done = (*play_noagr [(x->value[3] - 2 )][(showing - 2) ] ) (x,3);
break;
}
case 1 :
{
done = (*play_std [(x->value[3] - 2 )][(showing - 2) ] ) (x,3);
break;
}
}
}
}

return(1);
}

/*
** draw house, the dealer must stand on 17 or greater, and hit on 16
** or less
*/

int draw_house()
{
int done;

done = 0;
while ( !done )
{
/* dealer busted */
if ( house.value[0] > 21 )
{
house.value[0] = 0;
s_dealerbust++;
break;
}

/* dealer stops taking cards */
if ( house.value[0] >= 17 )
break;

/* check ace as value of 11 */
if ( house.ace[0] )
{
switch ( house.value[0] )
{
case 2:
case 3:
case 4:
case 5:
case 6:
{
/* printf("%2d:%2d ", shoe[dealout].value, house.value[0] );
*/
next_card( &house, 0 );
break;
}
/* if dealer can make 17 or better, stop drawing cards */
case 7:
case 8:
case 9:
case 10:
case 11:
{
house.value[0] += 10;
break;
}
default:
{
house.ace[0] = 0; /* make ace a 1 */
/* printf("%2d:%2d ", shoe[dealout].value, house.value[0] );
*/
next_card( &house, 0 );
break;
}
}
}
else
{
/* printf("%2d:%2d ", shoe[dealout].value, house.value[0] );
*/
next_card( &house, 0 );
}
}
/* printf("%d\n", house.value[0] );
*/
return(1);
}

/*
** the initial deal of the cards
*/

int deal()
{
unsigned i, j;

/* check if need to reshuffle show */
if ( dealout > shoecut )
shuffle();

/* make bets before deal */
bet();

/* count deals and hands of shoe played */
s_deals++;
handsplayed++;

/* initialize player structure */
for ( i=0; i {
for ( j=0; j<4; j++ )
{
bettor[i].value[j] = 0;
bettor[i].ace[j] = 0;
bettor[i].cards[j] = 0;
}
bettor[i].hands = 1;
}

/* initialize dealer structure */
house.value[0] = 0;
house.ace[0] = 0;
house.cards[0] = 0;
house.hands = 1;

/* give each player a first card */
for ( i=0; i {
bettor[i].firstcard = shoe[dealout].type;
next_card( &(bettor[i]), 0 );
}

/* give dealer first card */
house.firstcard = shoe[dealout].type;
next_card( &house, 0 );

/* give each player a second card */
for ( i=0; i next_card( &(bettor[i]), 0 );

/* give dealer a second card */
/* printf("%2d:%2d ", shoe[dealout].value, house.value[0] );
*/
next_card( &house, 0 );

return(1);
}

/*
** shuffle, use random number to select shoe position for each
** card, if shoe position already used, scan backwards or forwards
** to next available slot, backwards/forwards on odd/even random number
*/

int shuffle()
{
int x;
unsigned c, s, d;

/* initialize shoe positions */
for ( c=0; c<312; c++ )
{
shoe[c].value = 0;
shoe[c].type = ' ';
/* shoe[c].suit = ' ';
*/
}

/* spread cards randomly in shoe */
for ( c=0; c<13; c++ ) /* each card in suit */
{
for ( s=0; s<4; s++ ) /* each suit in deck */
{
for ( d=0; d {
x = rand();
x = x % 312; /* random number MOD 312 */

/* place card if shoe position is unused */
if ( ! shoe[x].value )
{
set_shoe_card ( x, c, s );
continue;
}

/* try again */
x = rand();
x = x % 312; /* random number MOD 312 */

/* place card if shoe position is unused */
if ( ! shoe[x].value )
{
set_shoe_card ( x, c, s );
continue;
}
/* scan backward if shoe position used and random number is odd */
if ( x & 1 )
{
for ( ; x>=0; x-- )
{
if ( ! shoe[x].value )
{
set_shoe_card ( x, c, s );
break;
}
if ( x == 0 )
x = 312;
}
}
else
{
/* scan foreward if shoe position used and random number is even */
for ( ; x<=311; x++ )
{
if ( ! shoe[x].value )
{
set_shoe_card ( x, c, s );
break;
}
if ( x == 311 )
x = -1;
}
}
}
}
}

/* set random cut in shoe */
x = rand();
x = x % 18;
x -= 18;
shoecut = 208 + x; /* cut to 4 deck from 6 */

/* initialize play stats for new shuffle */
dealout = 1; /* burn first card */
seentens = 0; /* counting tens */
handsplayed = 0; /* hands played in shoe */

return(1);
}

/*
** alternate shuffle to use pre-defined test deck
*/

/* int shuffle_x()
** {
** int x, i;
** unsigned c, s, d;
**
** for ( x=0; x<312; x++ )
** {
** set_shoe_card ( x, testdeck[x] - 1, 0 );
** }
**
** shoecut = 300;
**
** dealout = 0;
** seentens = 0;
** handsplayed = 0;
**
** return(1);
** }
*/

/*
** set shoe position with card value, face type, and suit
*/

int set_shoe_card ( unsigned x, unsigned c, unsigned s )
{
shoe[x].value = count[c];
shoe[x].type = face[c];
/* shoe[x].suit = color[s];
*/
return(1);
}

/*
** deal next card, track ten cards seen, track ace in hand,
** increment hand value, second card is last dealt card,
** count number of cards for hand, increment shoe position
*/

int next_card( struct player *x, int y )
{
if ( shoe[dealout].value == 10 )
seentens++;
if ( shoe[dealout].value == 1 )
x->ace[y] = 1;
x->value[y] += shoe[dealout].value;
if ( x->cards[y] == 1 )
x->secondcard = shoe[dealout].type;
x->cards[y]++;

/* printf("%2d:%2d:%1d ", shoe[dealout].value, x->value[y], x->cards[y] );
*/

dealout++;
return(1);
}

/*
** player may split aces and receive exactly one card for each hand
*/

int split_aces ( struct player *x )
{
x->hands = 2;
x->bankroll -= x->bet; /* requires equal bet amount */
x->value[0] = 11;
x->cards[0] = 1;
x->ace[0] = 1;
x->value[1] = 11;
x->cards[1] = 1;
x->ace[1] = 1;
return(1);
}

/*
** player may split pairs to create up to four hands
** card value of pair card is passed to this routine
*/

int split_pairs( struct player *x, int y, int c )
{
x->bankroll -= x->bet; /* requires equal bet amount */
x->value[y] = c;
x->cards[y] = 1;
x->value[x->hands] = c; /* multiple split pairs, use hand count */
x->cards[x->hands] = 1;
x->hands++;
return(1);
}

/*
** player may double his bet for any two card value and receive
** exactly one more card, see style matrix for best hands to
** make this bet
*/

int double_down ( struct player *x, int y )
{
x->bankroll -= x->bet; /* requires equal bet amount */
x->bet *= 2; /* not another hand, a doubled bet */
next_card( x, y );
return(1);
}




  3 Responses to “Category : A Collection of Games for DOS and Windows
Archive   : S21.ZIP
Filename : S21.C

  1. Very nice! Thank you for this wonderful archive. I wonder why I found it only now. Long live the BBS file archives!

  2. This is so awesome! 😀 I’d be cool if you could download an entire archive of this at once, though.

  3. But one thing that puzzles me is the “mtswslnkmcjklsdlsbdmMICROSOFT” string. There is an article about it here. It is definitely worth a read: http://www.os2museum.com/wp/mtswslnk/