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