GNO-Extras/v7/games/fish.c#b00008
Bobbi Webber-Manners 000d69c9ed Initial checkin
2020-01-28 23:22:35 -05:00

528 lines
9.6 KiB
Plaintext

#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
/* Through, `my' refers to the program, `your' to the player */
# define CTYPE 13
# define CTSIZ (CTYPE+1)
# define DECK 52
# define NOMORE 0
# define DOUBTIT (-1);
typedef char HAND[CTSIZ];
/* data structures */
short debug;
HAND myhand;
HAND yourhand;
char deck[DECK];
short nextcd;
int proflag;
int shuffle(void);
int choose(char a[], int n);
int error(char *s);
int rand(void);
int draw(void);
int empty(HAND h);
int mark(HAND hand, int cd);
int deal(HAND hand, int n);
int stats(void);
int phand(HAND h);
int instruct(void);
int game(void);
int start(HAND h);
int hedrew(int d);
int heguessed(int d);
int myguess(void);
int move(HAND hs, HAND ht, int g, int v);
int guess(void);
int madebook(int x);
int score(void);
/* utility and output programs */
void test(void) {
HAND h;
int i;
i=mark(h,i);
}
int shuffle(void) {
/* shuffle the deck, and reset nextcd */
/* uses the random number generator `rand' in the C library */
/* assumes that `srand' has already been called */
register i;
for( i=0; i<DECK; ++i ) deck[i] = (i%13)+1; /* seed the deck */
for( i=DECK; i>0; --i ){ /* select the next card at random */
deck[i-1] = choose( deck, i );
}
nextcd = 0;
}
int choose(char a[], int n ) {
/* pick and return one at random from the n choices in a */
/* The last one is moved to replace the one chosen */
register j, t;
if( n <= 0 ) error( "null choice" );
j = rand() % n;
t = a[j];
a[j] = a[n-1];
return(t);
}
int draw(void) {
if( nextcd >= DECK ) return( NOMORE );
return( deck[nextcd++] );
}
int error(char *s) {
fprintf( stderr, "error: " );
fprintf( stderr, s );
exit( 1 );
}
int empty(HAND h) {
register i;
for( i=1; i<=CTYPE; ++i ){
if( h[i] != 0 && h[i] != 4 ) return( 0 );
}
return( i );
}
int mark(HAND hand, int cd) {
if( cd != NOMORE ){
++hand[cd];
if( hand[cd] > 4 ){
error( "mark overflow" );
}
}
return( cd );
}
int deal(HAND hand, int n) {
while( n-- ){
if( mark( hand, draw() ) == NOMORE ) error( "deck exhausted" );
}
}
char *cname[] = {
"NOMORE!!!",
"A",
"2",
"3",
"4",
"5",
"6",
"7",
"8",
"9",
"10",
"J",
"Q",
"K"
};
int stats(void) {
register i, ct, b;
if( proflag ) printf( "Pro level\n" );
b = ct = 0;
for( i=1; i<=CTYPE; ++i ){
if( myhand[i] == 4 ) ++b;
else ct += myhand[i];
}
if( b ){
printf( "My books: " );
for( i=1; i<=CTYPE; ++i ){
if( myhand[i] == 4 ) printf( "%s ", cname[i] );
}
printf( "\n" );
}
printf( "%d cards in my hand, %d in the pool\n", ct, DECK-nextcd );
printf( "You ask me for: " );
}
int phand(HAND h) {
register i, j;
j = 0;
for( i = 1; i<= CTYPE; ++i ){
if( h[i] == 4 ) {
++j;
continue;
}
if( h[i] ){
register k;
k = h[i];
while( k-- ) printf( "%s ", cname[i] );
}
}
if( j ){
printf( "+ Books of " );
for( i=1; i<=CTYPE; ++i ){
if( h[i] == 4 ) printf( "%s ", cname[i] );
}
}
printf( "\n" );
}
int main(int argc, char *argv[]) {
/* initialize shuffling, ask for instructions, play game, die */
register c;
if( argc > 1 && argv[1][0] == '-' ){
while( argv[1][0] == '-' ) { ++argv[1]; ++debug; }
argv++;
argc--;
}
srand( getpid() );
printf( "instructions?\n" );
if( (c=getchar()) != '\n' ){
if( c != 'n' ) instruct();
while( getchar() != '\n' );
}
game();
}
/* print instructions */
char *inst[] = {
"`Go Fish' is a childrens' card game.",
"The Object is to accumulate `books' of 4 cards",
"with the same face value.",
"The players alternate turns; each turn begins with one",
"player selecting a card from his hand, and asking the",
"other player for all cards of that face value.",
"If the other player has one or more cards of that face value",
"in his hand, he gives them to the first player, and the",
"first player makes another request.",
"Eventually, the first player asks for a card which",
"is not in the second player's hand: he replies `GO FISH!'",
"The first player then draws a card from the `pool' of",
"undealt cards. If this is the card he had last requested, he",
"draws again.",
"When a book is made, either through drawing or requesting,",
"the cards are laid down and no further action takes",
"place with that face value.",
"To play the computer, simply make guesses by typing",
"a, 2, 3, 4, 5, 6, 7, 8, 9, 10, j, q, or k when asked.",
"Hitting return gives you information about the size of",
"my hand and the pool, and tells you about my books.",
"Saying `p' as a first guess puts you into `pro' level;",
"The default is pretty dumb!",
"Good Luck!",
""
};
int instruct(void) {
register char **cpp;
printf( "\n" );
for( cpp = inst; **cpp != '\0'; ++cpp ){
printf( "%s\n", *cpp );
}
}
int game(void) {
shuffle();
deal( myhand, 7 );
deal( yourhand, 7 );
start( myhand );
for(;;){
register g;
/* you make repeated guesses */
for(;;) {
printf( "your hand is: " );
phand( yourhand );
printf( "you ask me for: " );
if( !move( yourhand, myhand, g=guess(), 0 ) ) break;
printf( "Guess again\n" );
}
/* I make repeated guesses */
for(;;) {
if( (g=myguess()) != NOMORE ){
printf( "I ask you for: %s\n", cname[g] );
}
if( !move( myhand, yourhand, g, 1 ) ) break;
printf( "I get another guess\n" );
}
}
}
/* reflect the effect of a move on the hands */
int move(HAND hs, HAND ht, int g, int v) {
/* hand hs has made a guess, g, directed towards ht */
/* v on indicates that the guess was made by the machine */
register int d;
char *sp, *tp;
sp = tp = "I";
if( v ) tp = "You";
else sp = "You";
if( g == NOMORE ){
d = draw();
if( d == NOMORE ) score();
else {
printf( "Empty Hand\n" );
if( !v ) printf( "You draw %s\n", cname[d] );
mark( hs, d );
}
return( 0 );
}
if( !v ) heguessed( g );
if( hs[g] == 0 ){
if( v ) error( "Rotten Guess" );
printf( "You don't have any %s's\n", cname[g] );
return(1);
}
if( ht[g] ){ /* successful guess */
printf( "%s have %d %s%s\n", tp, ht[g], cname[g], ht[g]>1?"'s":"" );
hs[g] += ht[g];
ht[g] = 0;
if( hs[g] == 4 ) madebook(g);
return(1);
}
/* GO FISH! */
printf( "%s say \"GO FISH!\"\n", tp );
newdraw:
d = draw();
if( d == NOMORE ) {
printf( "No more cards\n" );
return(0);
}
mark( hs, d );
if( !v ) printf( "You draw %s\n", cname[d] );
if( hs[d] == 4 ) madebook(d);
if( d == g ){
printf( "%s drew the guess, so draw again\n", sp );
if( !v ) hedrew( d );
goto newdraw;
}
return( 0 );
}
int madebook(int x) {
printf( "Made a book of %s's\n", cname[x] );
}
int score(void) {
register my, your, i;
my = your = 0;
printf( "The game is over.\nMy books: " );
for( i=1; i<=CTYPE;++i ){
if( myhand[i] == 4 ){
++my;
printf( "%s ", cname[i] );
}
}
printf( "\nYour books: " );
for( i=1; i<=CTYPE;++i ){
if( yourhand[i] == 4 ){
++your;
printf( "%s ", cname[i] );
}
}
printf( "\n\nI have %d, you have %d\n", my, your );
printf( "\n%s win!!!\n", my>your?"I":"You" );
exit(0);
}
# define G(x) { if(go) goto err; else go = x; }
int guess(void) {
/* get the guess from the tty and return it... */
register g, go;
go = 0;
for(;;) {
switch( g = getchar() ){
case 'p':
case 'P':
++proflag;
continue;
case '2':
case '3':
case '4':
case '5':
case '6':
case '7':
case '8':
case '9':
G(g-'0');
continue;
case 'a':
case 'A':
G(1);
continue;
case '1':
G(10);
continue;
case '0':
if( go != 10 ) goto err;
continue;
case 'J':
case 'j':
G(11);
continue;
case 'Q':
case 'q':
G(12);
continue;
case 'K':
case 'k':
G(13);
continue;
case '\n':
if( empty( yourhand ) ) return( NOMORE );
if( go == 0 ){
stats();
continue;
}
return( go );
case ' ':
case '\t':
continue;
default:
err:
while( g != '\n' ) g = getchar();
printf( "what?\n" );
continue;
}
}
}
/* the program's strategy appears from here to the end */
char try[100];
char ntry;
char haveguessed[CTSIZ];
char hehas[CTSIZ];
int start(HAND h) {
;
}
int hedrew(int d){
++hehas[d];
}
int heguessed(int d){
++hehas[d];
}
int myguess(void) {
register i, lg, t;
if( empty( myhand ) ) return( NOMORE );
/* make a list of those things which i have */
/* leave off any which are books */
/* if something is found that he has, guess it! */
ntry = 0;
for( i=1; i<=CTYPE; ++i ){
if( myhand[i] == 0 || myhand[i] == 4 ) continue;
try[ntry++] = i;
}
if( !proflag ) goto random;
/* get ones he has, if any */
for( i=0; i<ntry; ++i ){
if( hehas[try[i]] ) {
i = try[i];
goto gotguess;
}
}
/* is there one that has never been guessed; if so, guess it */
lg = 101;
for( i=0; i<ntry; ++i ){
if( haveguessed[try[i]] < lg ) lg = haveguessed[try[i]];
}
/* remove all those not guessed longest ago */
t = 0;
for( i=0; i<ntry; ++i ){
if( haveguessed[try[i]] == lg ) try[t++] = try[i];
}
ntry = t;
if( t <= 0 ) error( "bad guessing loop" );
random:
i = choose( try, ntry ); /* make a random choice */
gotguess: /* do bookkeeping */
hehas[i] = 0; /* he won't anymore! */
for( t=1; t<=CTYPE; ++t ){
if( haveguessed[t] ) --haveguessed[t];
}
haveguessed[i] = 100; /* will have guessed it */
return(i);
}