billr@saab.CNA.TEK.COM (Bill Randle) (09/14/89)
Submitted-by: Scott Turner <srt@lanai.cs.ucla.edu> Posting-number: Volume 8, Issue 23 Archive-name: choice/Part02 #! /bin/sh # This is a shell archive. Remove anything before this line, then unpack # it by saving it into a file and typing "sh file". To overwrite existing # files, type "sh file -c". You can also feed this as standard input via # unshar, or by typing "sh <file", e.g.. If this archive is complete, you # will see the following message at the end: # "End of archive 2 (of 2)." # Contents: defs.h instruct.c my_wgets.c my_wgets.h utils.c # Wrapped by billr@saab on Thu Sep 14 09:46:47 1989 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f 'defs.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'defs.h'\" else echo shar: Extracting \"'defs.h'\" \(1890 characters\) sed "s/^X//" >'defs.h' <<'END_OF_FILE' X/* X * defs.h X * Wed Sep 14 14:57:01 1988 -- Scott R. Turner X * X * This file contains the definitions for Choice. X * X * Choice uses an interesting data structure for a set of X * cards. The data structure consists of a 4 X 13 array of X * integers. Marking the integers can indicate either their X * presence (as in a hand held by a player) or their order X * (as in a deck). Shuffling can be done by marking a deck X * in order and then exchanging two randomly selected cards X * a number of times. X * X */ X X#include <stdio.h> X#include <ctype.h> X#include <curses.h> X X/* Constants */ X X#define SPADES 0 X#define HEARTS 1 X#define DIAMONDS 2 X#define CLUBS 3 X X#define JACK 11 X#define QUEEN 12 X#define KING 13 X#define ACE 14 X X/* Interface Values */ X X#define REFRESHKEY 12 X#define SHOWKEY '!' X#define DEBUGKEY '*' X#define QUITKEY 'X' X#define IOLINE1 11 X#define IOLINE2 12 X#define IOLINE3 13 X X/* Card Values */ X X#define UNKNOWN 0 X#define MINE 1 X#define PLAYED 2 X#define HEPLAYED 3 X#define BURIED 4 X X/* Scorefile */ X X#define SCOREFILE "/u/gs8/srt/.choice" X X X/* Data Definitions */ X Xtypedef struct sdeck { X int top; /* Top card in deck */ X int cards[4][15]; /* For convenience, 0 & 1 are ignored */ X} deckt; X Xtypedef struct splayer { X int tricks; /* How many tricks player has taken */ X int score; X int games; X int computer; /* TRUE if the computer player. */ X int whose, num; /* Whose contract, num needed. */ X int trump; /* Trump suit. */ X int shownout[4]; /* Shown out? (for computer) */ X int len[4]; /* Initial lengths. (for computer) */ X int cards[4][15]; /* Player's holding. */ X} player; X Xextern deckt deck; Xextern player players[2]; Xextern int lead, trump; Xextern int debug; X Xstatic char suitchars[4] = {'S','H','D','C'}; Xstatic char honorchars[4] = {'J','Q','K','A'}; X X END_OF_FILE if test 1890 -ne `wc -c <'defs.h'`; then echo shar: \"'defs.h'\" unpacked with wrong size! fi # end of 'defs.h' fi if test -f 'instruct.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'instruct.c'\" else echo shar: Extracting \"'instruct.c'\" \(6774 characters\) sed "s/^X//" >'instruct.c' <<'END_OF_FILE' X/* X * This program (called "Choice") is copyright 1989 to Scott R. Turner, X * in both source code and executable form. Permission is given to X * copy both the source code and the executable under the following X * conditions: X * X * 1. You may copy and distribute verbatim copies of Choice code as you X * receive it, in any medium, provided that you conspicuously and X * appropriately publish on each file a valid copyright notice such as X * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright X * and license notices on all files. You may charge a distribution fee X * for the physical act of transferring a copy, but that fee may not X * exceed your actual costs in creating and delivering the copy. X * X * 2. You may modify your copy or copies of Choice or any portion of it, X * and copy and distribute such modifications under the terms of X * Paragraph 1 above, provided that you also do the following: X * X * a) cause the modified files to carry prominent notices stating X * who last changed such files and the date of any change; and X * X * b) cause the whole of any work that you distribute or publish, X * that in whole or in part contains or is a derivative of Choice X * or any part thereof, to be licensed at no charge to all third X * parties on terms identical to those contained in this License X * Agreement (except that you may choose to grant more extensive X * warranty protection to third parties, at your option). X * X * 3. You may not copy, sublicense, distribute or transfer Choice X * except as expressly provided under this License Agreement. Any attempt X * otherwise to copy, sublicense, distribute or transfer Choice is void and X * your rights to use Choice under this License agreement shall be X * automatically terminated. However, parties who have received computer X * software programs from you with this License Agreement will not have X * their licenses terminated so long as such parties remain in full compliance. X * X * 4. Under no circumstances may you charge for copies of Choice, for copies X * of any program containing code from Choice in whole or in part, or for X * any software package or collection of programs or code that contains Choice X * in whole or part. X * X */ X X/* X * instruct.c X * Mon Sep 19 11:01:18 1988 -- Scott Turner X * X * instruct contains a routine for printing out how to play the X * game. X * X */ X#include "defs.h" X Xinstruct() X{ X clear(); X move(0,0); X printw(" The Game of Choice\n\n"); X printw(" Choice is a two-handed trick-taking game with trump, similar\n"); X printw("to Bridge, Spades and (in particular) two-handed Spades.\n\n"); X printw(" In the first part of the game, the two players take turns drawing\n"); X printw("one card from the top of the deck. If the player likes the card, he\n"); X printw("can choose to keep it (and the next card is discarded sight unseen).\n"); X printw("If he doesn't want it, he discards it, and takes the next\n"); X printw("card from the deck. In this way, both players build up hands of\n"); X printw("thirteen cards.\n\n"); X printw(" In the second part of the game, the two players take turns bidding.\n"); X printw("Each player bids the number of tricks he thinks he can win, if he is\n"); X printw("allowed to name the trump suit. Whoever bids the most tricks wins,\n"); X printw("names the trump suit, and leads for the first trick.\n\n"); X printw(" Whoever wins the first trick leads for the second trick, and so\n"); X printw("on.\n\n"); X move(24,0); X printw("--- Hit any key to continue ---"); X refresh(); X (void) getch(); X clear(); X move(0,0); X printw(" Scoring\n\n"); X printw(" The bidder scores ten times his bid if he makes, plus one point for\n"); X printw("each overtrick. The bidder scores negative ten times his bid if he\n"); X printw("goes down.\n\n"); X printw(" The winner is the first player to 250 points.\n\n"); X printw(" Choice keeps track of the number of games you have won, and will\n"); X printw("display your current standing at the end of each session. You can also\n"); X printw("display your score with the -s option.\n\n"); X move(24,0); X printw("--- Hit any key to continue ---"); X refresh(); X (void) getch(); X clear(); X move(0,0); X printw(" Using This Program\n\n"); X printw(" This program is relatively simple to use.\n\n"); X printw(" Use the 'y' and 'n' keys to answer yes/no questions such as\n"); X printw("'Would you like the QS?'.\n\n"); X printw(" When you are asked for a bid, simply type the number and hit a\n"); X printw("carriage return. A bid of 0 ends the bidding.\n\n"); X printw(" To play a card from your hand type the rank of the card and possibly\n"); X printw("its suit. The program will try to differentiate as much as possible.\n"); X printw("For instance, if you only have one '8' in your hand, typing an '8' will\n"); X printw("play that card.\n\n"); X printw(" Typing a ^L will redraw the screen and typing an 'X' will immediately\n"); X printw("exit the program.\n\n"); X move(24,0); X printw("--- Hit any key to continue ---"); X refresh(); X (void) getch(); X clear(); X move(0,0); X printw(" Options\n\n"); X printw(" Normally the computer bids using a rule-based strategy. It isn't\n"); X printw("very good, though you may find it challenging at first. If Choice is\n"); X printw("called with the -h option (for 'hard') it will play a more challenging\n"); X printw("strategy. Unfortunately, this strategy cheats a little - it looks at\n"); X printw("your hand to determine a good bid.\n\n"); X printw(" For people interested in modifying the program or developing new\n"); X printw("strategies, there are several options which will help you collect statistics\n"); X printw("and debug new strategies. A look through the code will reveal these\n"); X printw("options.\n\n"); X move(24,0); X printw("--- Hit any key to continue ---"); X refresh(); X (void) getch(); X clear(); X move(0,0); X printw(" Credits\n\n"); X printw(" This program was designed and coded by Scott R. Turner (srt@cs.ucla.edu,\n"); X printw("as of late 1989).\n\n"); X printw(" Special thanks goes to John Reeves and Matthew Merzbacher, who helped\n"); X printw("debug early versions of the program and suggested various improvements.\n\n"); X printw(" Choice was inspired by Leslie Kim, a programmer and otherwise interesting\n"); X printw("person. Her electronic address is kim@aerospace.aero.org, and if you\n"); X printw("enjoy using this program you might want to drop her a short note.\n\n"); X move(24,0); X printw("--- Hit any key to continue ---"); X refresh(); X (void) getch(); X clear(); X}; X X X X X X X X X X END_OF_FILE if test 6774 -ne `wc -c <'instruct.c'`; then echo shar: \"'instruct.c'\" unpacked with wrong size! fi # end of 'instruct.c' fi if test -f 'my_wgets.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'my_wgets.c'\" else echo shar: Extracting \"'my_wgets.c'\" \(4384 characters\) sed "s/^X//" >'my_wgets.c' <<'END_OF_FILE' X/* X * A possible replacement for curses' wgetstr(). Allows X * line editing as in csh. X * Recognizes the erase, kill chars, word deleting. X * X * By Hung Le (mott@ucscb.ucsc.edu ...!ucbvax!ucscc!ucscb!mott) X * History: X * 01/18/89 - Initial version X * 03/20/89 - Add control-w to delete word X * 05/17/89 - add option to return immediately or to bell() X * when buffer is full. X * X * Release to Public Domain X */ X#include <curses.h> X#ifdef UNIX X#include <sys/ioctl.h> X#include <sgtty.h> X#endif UNIX X X#define STD_INPUT 0 /* standard input */ X#define NEWLINE '\n' X#define SPACE ' ' X/* default for erase and kill characters */ X#define ERASE '\010' X#define KILL '\025' X#define WORD '\027' X X/* You bugger !!! you did something wrong */ X#define bell() printf("%c", '\007') X X/* X * my_wgetstr(WINDOW *win, char *str, int size, int ret) X * win: the concerned window X * str: buffer holding input X * size: (size -1) is the maximum chars to get X * ret: flag indicating what to do when (size -1) is reached X * 0: ring bell() X * 1: returns X * two macros are defined in "my_wgetstr.h" as RET=1 and NO_RET=0 X * X * works same as wgetstr() in curses but allows editing. X * Recognizes the erase character and the kill character and X * WORD as the word deleting char. X * Will try to get the erase and kill char from the terminal setting. X * If failed, will use the default ERASE and KILL definitions. X * Word char is set to WORD. X * X * DOES NOT check for illegal scrolling. X * Returns X * . when received a new line character X * . if ( (strlen(str) == (size - 1)) and (ret) ) X * X * str[size - 1] must be set to '\0' to end the string properly X * so my_wgetstr(errwin, str, 8) will get at most 7 characters. X * X * Returned value is the number of chars read. X */ X Xmy_wgetstr(win, str, size, ret) XWINDOW *win; Xchar *str; Xint size; Xint ret; X{ X#ifdef UNIX X struct sgttyb ttyb; X#endif X char erase_char, kill_char; X register int x_pos, y_pos, index, in; X X#ifdef UNIX X if (ioctl(STD_INPUT, TIOCGETP, &ttyb) == -1) X { X#endif UNIX X /* X * failed to get terminal setting. Let's use the default X * ERASE and KILL X */ X erase_char = ERASE; X kill_char = KILL; X#ifdef UNIX X } X else X { X erase_char = ttyb.sg_erase; X kill_char = ttyb.sg_kill; X } X#endif UNIX X X /* X * since we are going to set noecho() and crmode() let's be safe and X * save the current tty X */ X savetty(); X noecho(); X crmode(); X X /* get current position */ X getyx(win, y_pos, x_pos); X /* intializing */ X index = 0; X str[index] = '\0'; X X /* while input char is not NEWLINE */ X while ((in = getch() & 0177) != NEWLINE) X { X /* if buffer is full (size -1) */ X if (index >= size - 1) X if (ret)/* return flag set, return immediately */ X break; X else /* allows editing chars to pass through */ X if ((in != erase_char) && (in != kill_char) && (in != WORD)) X { X /* warns user that buffer is full */ X bell(); X continue; X } X X if (in == erase_char) /* ERASING */ X { X if (index > 0) X { X mvwaddch(win, y_pos, --x_pos, SPACE); X str[--index] = SPACE; X wmove(win, y_pos, x_pos); X } X else X bell(); X } X else X if (in == kill_char) /* KILLING */ X { X if (index > 0) X while (index > 0) X { X mvwaddch(win, y_pos, --x_pos, SPACE); X str[--index] = SPACE; X wmove(win, y_pos, x_pos); X } X else X bell(); X } X else X if (in == WORD) /* WORD DELETING */ X { X if (index > 0) X { X /* throw away all spaces */ X while ((index > 0) && (str[index - 1] == SPACE)) X { X mvwaddch(win, y_pos, --x_pos, SPACE); X str[--index] = SPACE; X wmove(win, y_pos, x_pos); X } X /* move back until see another space */ X while ((index > 0) && (str[index - 1] != SPACE)) X { X mvwaddch(win, y_pos, --x_pos, SPACE); X str[--index] = SPACE; X wmove(win, y_pos, x_pos); X } X } X else X bell(); X } X else X { X mvwaddch(win, y_pos, x_pos++, in); X str[index++] = in; X } X /* show result */ X wrefresh(win); X } X /* ends the string properly */ X str[index] = '\0'; X /* restore the tty */ X resetty(); X /* returns number of chars read */ X return (index); X} X X/* X * Getint X * X * Just a little function for Hotel that gets an integer X * using Le's wgetstr. X * X * X */ X X#include "my_wgets.h" Xint getint() X{ X int x,y,num,ans; X char get[80]; X X num = 0; X do { X my_getstr(get,80,0); X num = sscanf(get,"%d",&ans); X } while (num == 0); X return(ans); X}; END_OF_FILE if test 4384 -ne `wc -c <'my_wgets.c'`; then echo shar: \"'my_wgets.c'\" unpacked with wrong size! fi # end of 'my_wgets.c' fi if test -f 'my_wgets.h' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'my_wgets.h'\" else echo shar: Extracting \"'my_wgets.h'\" \(421 characters\) sed "s/^X//" >'my_wgets.h' <<'END_OF_FILE' X/* X * A possible replacement for curses' wgetstr(). Allows X * limited editing. Recognizes the erase and kill chars. X * X * By Hung Le (mott@ucscb.ucsc.edu ...!ucbvax!ucscc!ucscb!mott) X * History: X * 05/18/89 - Initial version X * X * Release to Public Domain X */ X X/* following the curses's convention */ X#define my_getstr(str,size,ret) my_wgetstr(stdscr,str,size,ret) X#define RET 1 X#define NO_RET 0 Xextern int getint(); X END_OF_FILE if test 421 -ne `wc -c <'my_wgets.h'`; then echo shar: \"'my_wgets.h'\" unpacked with wrong size! fi # end of 'my_wgets.h' fi if test -f 'utils.c' -a "${1}" != "-c" ; then echo shar: Will not clobber existing file \"'utils.c'\" else echo shar: Extracting \"'utils.c'\" \(5660 characters\) sed "s/^X//" >'utils.c' <<'END_OF_FILE' X/* X * This program (called "Choice") is copyright 1989 to Scott R. Turner, X * in both source code and executable form. Permission is given to X * copy both the source code and the executable under the following X * conditions: X * X * 1. You may copy and distribute verbatim copies of Choice code as you X * receive it, in any medium, provided that you conspicuously and X * appropriately publish on each file a valid copyright notice such as X * "Copyright (C) 1989 Scott R. Turner", and keep intact the copyright X * and license notices on all files. You may charge a distribution fee X * for the physical act of transferring a copy, but that fee may not X * exceed your actual costs in creating and delivering the copy. X * X * 2. You may modify your copy or copies of Choice or any portion of it, X * and copy and distribute such modifications under the terms of X * Paragraph 1 above, provided that you also do the following: X * X * a) cause the modified files to carry prominent notices stating X * who last changed such files and the date of any change; and X * X * b) cause the whole of any work that you distribute or publish, X * that in whole or in part contains or is a derivative of Choice X * or any part thereof, to be licensed at no charge to all third X * parties on terms identical to those contained in this License X * Agreement (except that you may choose to grant more extensive X * warranty protection to third parties, at your option). X * X * 3. You may not copy, sublicense, distribute or transfer Choice X * except as expressly provided under this License Agreement. Any attempt X * otherwise to copy, sublicense, distribute or transfer Choice is void and X * your rights to use Choice under this License agreement shall be X * automatically terminated. However, parties who have received computer X * software programs from you with this License Agreement will not have X * their licenses terminated so long as such parties remain in full compliance. X * X * 4. Under no circumstances may you charge for copies of Choice, for copies X * of any program containing code from Choice in whole or in part, or for X * any software package or collection of programs or code that contains Choice X * in whole or part. X * X */ X X/* X * utils.c X * Wed Sep 14 15:13:40 1988 -- Scott R. Turner X * X * This file contains some of the utility functions that set up X * the deck, shuffle the deck, get the next card from the deck, and X * so on. X * X */ X#include "defs.h" X#ifdef UNIX Xextern long random(); X#else X#include <stdlib.h> X#include <time.h> X#endif X/* X * randum is the standard 1-n random integer generator. X * X */ X Xint randum(n) X int n; X{ X#ifdef UNIX X return((random() % n) + 1); X#else X return((rand() % n) + 1); X#endif X}; X X/* X * shuffle X * X * This function intializes the deck and then shuffles it. X * X */ X Xshuffle(deck) X deckt *deck; X{ X int suit,rank,i,tmp; X extern long time(); X X (*deck).top = 1; X for(suit=0;suit<=3;suit++) X for(rank=2;rank<=14;rank++) X (*deck).cards[suit][rank] = (suit*13)+(rank-1); X X /* Now shuffle the deck by exchanging two cards some X * number of times. X */ X X for(i=1;i<=500;i++) X { X suit = randum(4) - 1; X rank = randum(13) + 1; X tmp = (*deck).cards[suit][rank]; X (*deck).cards[suit][rank] = (*deck).cards[0][2]; X (*deck).cards[0][2] = tmp; X }; X}; X X/* X * print_hand X * X * A little debug function to print out a hand. X * X */ X Xprint_hand(p,line) X player *p; X int line; X{ X int suit,rank; X X for(suit=0;suit<=3;suit++) X { X move(line,0); X printw(" "); X move(line++,0); X printw("%c: ",suitchars[suit]); X for(rank=14;rank>=2;rank--) X if ((*p).cards[suit][rank] == MINE) { X if (rank <= 10) { X printw("%d ",rank); X } else { X printw("%c ",honorchars[rank - JACK]); X }; X }; X }; X}; X X/* X * do_header fills the top part of the screen with X * the header. X * X */ X Xdo_header() X{ X /* Title */ X move(0,28); X printw("C*H*O*I*C*E"); X X /* Game info line. */ X X move(2,37); X printw("Trump: Contract: "); X /* 789012345678901234567890 */ X /* 3 4 5 */ X X move(4,50); X printw("You Me"); X move(5,45); X printw("----------+----------"); X move(6,37); X printw("Tricks"); X move(7,37); X printw("Score"); X move(8,37); X printw("Games"); X X}; X X/* X * Update the score section of the board. X * X */ X Xupdate_scores() X{ X move(6,43); X clrtoeol(); X move(6,51); X printw("%d",players[0].tricks); X move(6,61); X printw("%d",players[1].tricks); X move(7,42); X clrtoeol(); X move(7,51); X printw("%d",players[0].score); X move(7,61); X printw("%d",players[1].score); X move(8,42); X clrtoeol(); X move(8,51); X printw("%d",players[0].games); X move(8,61); X printw("%d",players[1].games); X}; X X/* X * get_card X * X * This function returns the Ith card of a deck. X * X */ X Xget_card(i,deck,rank,suit) X int i, *rank, *suit; X deckt *deck; X{ X int j,k; X X for(j=0;j<=3;j++) X for(k=2;k<=14;k++) X if((*deck).cards[j][k] == i) { X *suit = j; X *rank = k; X return(0); X }; X}; X X/* X * init_player X * X * This function initializes the player data structure. X * X */ X Xinit_player(p) X player *p; X{ X int suit,rank; X X (*p).tricks = 0; X (*p).trump = -1; X for(suit=0;suit<=3;suit++) X for(rank=2;rank<=14;rank++) X (*p).cards[suit][rank] = 0; X}; X Xstatic char cardstr[5]; X Xchar *card_string(suit,rank) X int rank,suit; X{ X if (rank < JACK) { X sprintf(cardstr,"%d%c",rank,suitchars[suit]); X } else { X sprintf(cardstr,"%c%c",honorchars[rank - JACK],suitchars[suit]); X }; X return(cardstr); X}; X X X END_OF_FILE if test 5660 -ne `wc -c <'utils.c'`; then echo shar: \"'utils.c'\" unpacked with wrong size! fi # end of 'utils.c' fi echo shar: End of archive 2 \(of 2\). cp /dev/null ark2isdone MISSING="" for I in 1 2 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked both archives. rm -f ark[1-9]isdone else echo You still need to unpack the following archives: echo " " ${MISSING} fi ## End of shell archive. exit 0