|
|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T m
Length: 25282 (0x62c2)
Types: TextFile
Names: »main.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987
└─⟦this⟧ »EUUGD18/General/Cchess/main.c«
/* C O R R E S P O N D E N C E C H E S S version 1.00
*
* Play chess with another player, with notification of moves by mail.
*
* (C) Copyright - Dec 1987 - Jan Dithmar Wolter.
*
* This source code may be freely used, but not for purposes of profit
* without the permission of the author. This copyright notice should
* not be removed.
*
* I would be very interested in hearing about suggestions, bug reports,
* and porting problems with cchess. I can be mailed on usenet at
* janc@crim.eecs.umich.edu. Better yet, dial into M-Net at
* (313)994-6333, give yourself an account and join the "ugames"
* conference. This is a free public bbs and cchess's development site.
*
* Any programmer who wishes to make improvements should be warned that
* this is a sadly unmodular program. There are tons of global variables
* and subroutines have curious side-effects. The arrays containing the
* board (b and bc) and the input buffers (mbuffer and sbuffer) are
* particularly strange this way, being used for just about everything.
* Sorry. That's what happens when what was originally supposed to be a
* "quicky" project grows for five years.
*
* version 0.10:
* First pre-release version.
* version 0.11:
* Added Unix 4.2bsd support.
* Rationalized version dependent signal handlers as much as
* possible with three different signal handling libraries.
* Added Computer Kibitzing option to help make up for poor
* graphics.
* version 0.12:
* Save illegal moves in kriegspeil games.
* Added Big Board option on Ron Theriault's suggestion.
* Solidified Forfiet/Draw code. (Finally).
* Touched up transcripts.
* Added help command.
* version 0.13:
* Added support for 22 column terminals (Commodores).
* Pawn promotion noted on transcripts.
* Redraw and Version work at "Not your move prompt"
* Solidified Challenge/Accept code. (Finally).
* version 0.14:
* Cosmetic changes to Exit command.
* Fix system() calls to protect them from dirty tricks.
* Let Kriegspielers replay the game after it is over.
* Improve castling code so it will work for halfboard games.
* Kriegspiel only counts some kinds of illegal moves.
* Time stamp added to each line of game file.
* Version and Redraw commands work at accept draw prompt.
* Replay renamed Playback, and dodraw() integrated with domove().
* White pieces displayed with highlighting on the big board.
* Divided sys.c file into sys.c and scrn.c.
* Fixed a bug that caused moves to get lost during playbacks.
* version 0.15:
* Fixed a pawn promotion bug that appeared in 0.14.
* Added Shatranj and Courier game variations.
* Added Karma, Rifle & Kamikazi Chess capture variations.
* Version 6 style ioctl() calls now understood by sys.c
* version 0.16
* Repeated position detection code kludged in.
* Fifty move rule enforcement installed.
* Game cancellation command added.
* Minor bug fixes to Karma chess, Kriegspiel and Scoreboard.
* version 0.17
* Big changes in the way options are represented internally
* and in game files and in score file.
* Addition of Maharajah piece.
* Multiple moves for variant games.
* Steamroller, Double Chess and Progressive variants added.
* Initial board set-up specified in transcript file.
* O command to display current game options added.
* mprint() for "--More--" on Help and Options.
* Board editor for custom chess boards.
* Further generalization of castling code.
* No spaces allowed in transcript file names.
* Bug fixes to mate detection.
* Redraw works at "Are you sure" and "Move:" prompts.
* Use user defined backspace character from stty calls.
* Mailer is run in background.
* Clarification of format of comments under board.
* version 0.18
* May name a user with -g option.
* Speedup of -g option with lookaside buffer for passwd lookups.
* Auto-redraw after suspend (sort of) made to work.
* Addition of French and German piece names.
* Various small bug fixes for system V.
* Added -a option to move in all possible games.
* Fixed printing of cancellation requests in transcripts.
* Illegal moves optionally printed in kriegspiel transcripts.
* Enter kibitz mode only if you are neither of the players.
* Changes to allow no king, or some other mateable piece.
* Fixes to the computer kibitzer (rooks don't cover themselves).
* Bug Fixes to playback of multimove games.
* Broke cmd.c file into cmd.c and init.c.
* Added Last command to display date of last move.
* Redesign of challenge and accept subsystems.
* Maharajah and Losing chess variant games added.
* Many fixes to mate detection.
* Tab'iyat option for sped up openings.
* version 0.19
* Turned off nl to crnl mapping and fixed stuff to work that way.
* Rewrote directory reading to use clone of 4.2bsd readdir().
* Fix things so display isn't confused by R lines in gamefile.
* Close files when -a option is used.
* Fix queen moves in mate detection.
* Simplification of compile time definitions.
* Rewrite to simplify cctrans() routine.
* Innumerable minor fixes and clean up work all over.
* Conversion Chess added with thanks to Kenneth Larimer.
* Version numbers added to game files.
* Crude support of 4.3bsd windowing interupt.
* version 1.00
* Cleaned up for posting to USENET.
*/
#include "cchess.h"
/* String identifying current version */
char *version = "0.19";
char *copyright = "(c) 1987 Jan Wolter";
/* Characters and Names for pieces (some foreign name sets are incomplete) */
char pc[] = "HJDEMIRNBQK kqbnrimedjh";
char *chessname[HI_NAMES+1][PIECES+1] = {
{ "Empty Square", "King", "Queen", "Bishop",
"Knight", "Rook", "Pawn", "Minister",
"Elephant", "Duke", "Jester", "Maharajah"},
{ "Empty Square", "Shah", "Queen", "Bishop",
"Faras", "Rukh", "Baidaq", "Firz",
"Fil", "Duke", "Jester", "Maharajah"},
{ "Empty Square", "Roi", "Dame", "Fou",
"Cavaler", "Tour", "Pion", "Ministre",
"Elephant", "Duc", "Jester", "Maharajah"},
{ "Empty Square", "Konig", "Dame", "Laufer",
"Springer", "Turm", "Bauer", "Minister",
"Elefant", "Herzog", "Jester", "Maharajah"} };
char **piecename;
short wfr,wfc,wtr,wtc; /* last white move - used for en paussant legality */
short bfr,bfc,btr,btc; /* last black move - used for en paussant legality */
schar promote = 0; /* Character to promote pawn to - 0 if no promotion */
/* Have the Kings or the Rooks been moved? */
boolean wcck = TRUE; /* White can castle king-side */
boolean wccq = TRUE; /* White can castle queen-side */
boolean bcck = TRUE; /* Black can castle king-side */
boolean bccq = TRUE; /* Black can castle queen-side */
/* Initial board layout */
/* Last four columns */
schar ib[R_SIZE][C_SIZE] = { /* for Courier only. */
WR, WN, WB, WQ, WK, WB, WN, WR, WB, WE, WN, WR,
WP, WP, WP, WP, WP, WP, WP, WP, WP, WP, WP, WP,
SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ,
SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ,
SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ,
SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ,
BP, BP, BP, BP, BP, BP, BP, BP, BP, BP, BP, BP,
BR, BN, BB, BQ, BK, BB, BN, BR, BB, BE, BN, BR,
};
schar bc[R_SIZE][C_SIZE]; /* Copy of the board, so moves can be taken back */
schar b[R_SIZE][C_SIZE]; /* Main board */
int errcode; /* Move error code */
int hisuid; /* Opponent user id number */
int myuid; /* Player user id number */
char hisid[20]; /* Opponent login name */
char myid[20]; /* Player login name */
#ifdef COMPAT018
char file_version[6] = "0.18"; /* Version of cchess that produced game file */
/* If no version line, assume 0.18 */
#else
char file_version[6] = ""; /* Version of cchess that produced game file */
#endif COMPAT018
int movecnt; /* Number of moves made so far in game */
int playcnt; /* Number of moves including proposals */
int mvssize; /* Number of moves on the move stack */
int tamemoves; /* Number of tame moves made */
int consmoves; /* Number of consecutive moves allowed */
int consmade; /* Number of consecutive moves made */
char fname[50]; /* Name of the gameboardfile */
FILE *rfp; /* File pointer for reading from boardfile */
FILE *wfp; /* File pointer for writing to boardfile */
/* Game status code:
* 0 -> No challenge made.
* 1 -> Challenge has been sent.
* 2 -> (not used)
* 3 -> Ready to move.
* 4 -> A draw has been proposed.
* 5 -> A draw has been accepted.
* 6 -> Player has forfeited.
* 7 -> cancellation has been proposed.
* 8 -> cancellation has been accepted.
*/
char status;
/* General Purpose Global Flags */
boolean newgame; /* Are we starting a new game file? */
boolean moveok = TRUE; /* Allow player to move? */
boolean solo; /* Is he playing himself? */
boolean kibitz = FALSE; /* Is this a kibitzing session? */
boolean bigboard = FALSE; /* Display board in large format? */
boolean hidden = FALSE; /* Should enemy moves be shown? */
boolean incheck = FALSE; /* Is player in check (or mate)? */
boolean inmate = FALSE; /* Is plater (check or stale) mated */
boolean repeated = FALSE; /* Is this a thrice repeated position? */
boolean stripped = FALSE; /* Have we just stripped the other player? */
boolean istame; /* Was the last move a tame one? */
boolean interupt; /* OK to interupt out of program? */
boolean eachgame = FALSE; /* Play each playable game? */
boolean must_take = FALSE; /* Allow only moves which capture? */
schar toplay=WHITE; /* color to play next */
schar order; /* -1 if other player named first, else 1 */
schar mycolor; /* What color am I? */
schar taken; /* Piece taken in last move. SQ for none. */
long lastday; /* Day number on which last move was made. */
boolean erases=TRUE; /* Can terminal erase properly? */
boolean issmart=FALSE; /* Can address cursor and erase? */
boolean cleardown=FALSE; /* Can clear screen below cursor and smart? */
boolean commodore=FALSE; /* Do we have a 22 column terminal? */
boolean scrolled=FALSE; /* Has the screen scrolled? */
int illmoves; /* Count of illegal Kriegspiel moves */
int myillmoves; /* Count of my illegal Kriegspiel moves */
short cx,cy; /* Current Cursor position (used by TERMCAP) */
short msgarea = 0; /* Line below screen where prompts begin */
int LINES = 0; /* Number of lines per screen */
int COLS = 40; /* Number of columns per screen */
char bs_char = '\b'; /* User definable backspace character */
#ifdef DEBUG
boolean debugon = FALSE; /* Debugging flag */
#endif DEBUG
/* Names of standard variant games */
char *typename[HI_GAME+1] = {
"Mixed", "Chess", "Kriegspiel", "Shatranj", "Courier",
"Halfboard Chess", "Karma Chess", "Rifle Chess", "Kamikazi Chess",
"Double Chess", "Steamroller", "Progressive Chess", "Maharajah",
"Losing Chess", "Conversion Chess"};
char *langname[HI_NAMES+1] = { "English","Persian","French","German"};
/* Names of game results */
char *resltname[4] = {"Draw","Win","Lose","Continue"};
/* Names of Capture rules */
char *captname[HI_CAPTURE+1] =
{"Standard","No","Rifle","Conversion","Karma","Kamikazi"};
/* Current game options */
char option[OPTIONS];
/* Maximum legal values for the options */
char maxopt[OPTIONS] =
{ HI_COLOR, HI_PRIVATE, HI_KIBITZ, HI_GAME,
HI_ROWS, HI_COLS, HI_BOARD, HI_NAMES,
HI_VISIB, HI_CASTLE, HI_DPAWN, HI_STRIP,
HI_STALE, HI_CAPTURE, HI_KCAPTURE, HI_PROMOTE,
HI_WIMOVES, HI_BIMOVES, HI_WMOVES, HI_BMOVES,
HI_THRUCHECK, HI_WHITEKING, HI_BLACKKING, HI_MUSTTAKE,
HI_TABIYAT };
/* Variant game default options */
char defopt[HI_GAME+1][OPTIONS] =
{
/* Customized game */
{ FALSE, FALSE, TRUE, TY_MIXED,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Standard Chess */
{ FALSE, FALSE, TRUE, TY_CHESS,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Kriegspiel */
{ FALSE, FALSE, TRUE, TY_KRIEGSPIEL,
7, 7, FALSE, 0,
TRUE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Shatranj */
{ FALSE, FALSE, TRUE, TY_SHATRANJ,
7, 7, TRUE, 1,
FALSE, TRUE, TRUE, RE_LOSE,
RE_WIN, CA_NORMAL, CA_NORMAL, PR_MINISTER,
10, 10, 1, 1,
FALSE, WK, WK, FALSE,
TRUE },
/* Courier */
{ FALSE, FALSE, TRUE, TY_COURIER,
7, 11, TRUE, 0,
FALSE, TRUE, TRUE, RE_LOSE,
RE_WIN, CA_NORMAL, CA_NORMAL, PR_MINISTER,
12, 12, 1, 1,
FALSE, WK, WK, FALSE,
TRUE },
/* Halfboard */
{ FALSE, FALSE, TRUE, TY_HALFBOARD,
7, 3, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Karma Chess */
{ FALSE, FALSE, TRUE, TY_KARMA,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_KARMA, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Rifle Chess */
{ FALSE, FALSE, TRUE, TY_RIFLE,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_RIFLE, CA_RIFLE, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Kamikazi Chess */
{ FALSE, FALSE, TRUE, TY_KAMIKAZI,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_KAMIKAZI, CA_NONE, PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE },
/* Double Move Chess */
{ FALSE, FALSE, TRUE, TY_DOUBLE,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
2, 2, 2, 2,
TRUE, WK, WK, FALSE,
FALSE },
/* Steamroller */
{ FALSE, FALSE, TRUE, TY_STEAMROLLER,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
2, 1, 2, 1,
TRUE, WK, WK, FALSE,
FALSE },
/* Progressive Chess */
{ FALSE, FALSE, TRUE, TY_PROGRESSIVE,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_LOSE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, MO_PROGRESS, MO_PROGRESS, MO_PROGRESS,
FALSE, SQ, SQ, FALSE,
FALSE },
/* Maharajah */
{ FALSE, FALSE, TRUE, TY_MAHARAJAH,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, WH, WK, FALSE,
FALSE },
/* Losing Chess */
{ FALSE, FALSE, FALSE, TY_LOSING,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_WIN,
RE_WIN, CA_NORMAL, CA_NORMAL, PR_QRBN,
1, 1, 1, 1,
FALSE, SQ, SQ, FALSE,
FALSE },
/* Conversion Chess */
{ FALSE, FALSE, TRUE, TY_CONVERSION,
7, 7, FALSE, 0,
FALSE, FALSE, FALSE, RE_NONE,
RE_DRAW, CA_CONVERSION,CA_CONVERSION,PR_QRBN,
1, 1, 1, 1,
FALSE, WK, WK, FALSE,
FALSE } };
char cbuffer[CB_LEN+1]; /* Comment Buffer */
char mb1[MB_LEN+1]; /* Move Buffer One. */
char mb2[MB_LEN+1]; /* Move Buffer Two. */
char *mbuffer=mb1; /* Pointer to current move buffer */
char *sbuffer=mb2; /* Pointer to spare move buffer */
jmp_buf jmpenv; /* Long jump buffer */
/* Some really weird things used to sort of recover from suspends: */
/* susp1_flg is set if susp_env contains a place to jump to after */
/* we've been suspended. susp2_flg is turned on if we got suspended */
/* while there was no susp_env defined */
#ifndef LSIGNAL
jmp_buf susp_env;
boolean susp1_flg = FALSE, susp2_flg = FALSE;
#endif LSIGNAL
/* String of spaces used when arbitary strings of spaces are needed */
char blankstr[BLANK_LEN+1] /* Must be exactly BLANK_LEN spaces */
= " ";
char transcript = FALSE; /* Should we just print the transcript? */
int realuid;
boolean activeonly = FALSE;
main(argc,argv)
int argc;
char *argv[];
{
struct passwd *pwd; /* Password file entry */
register int players,i,j;
/* check legality of arguments */
players = 0;
for (i=1;i<argc;i++)
if (argv[i][0] == '-')
for (j = 1; argv[i][j]; j++)
switch (argv[i][j])
{
case 'a':
eachgame = TRUE;
break;
case 's':
scoreboard();
exit(0);
case 'b':
bigboard = TRUE;
break;
case 'g':
if (++i < argc)
{
if ((pwd = getpwnam(argv[i])) == 0)
{
printf("No user %s on this system\n",argv[i]);
exit(1);
}
printf("%s's games in progress\n-----------------------------\n",
argv[i]);
list(pwd->pw_uid);
}
else
{
printf("Games in progress\n-----------------\n");
list(-1);
}
exit(0);
case 't':
transcript = TRUE;
break;
#ifdef DEBUG
case 'd':
debugon = TRUE;
break;
#endif DEBUG
default:
printf("Illegal %s option: -%c\n",argv[0],argv[i][j]);
usage(argv[0]);
}
else
if (++players == 1)
strcpy(hisid,argv[i]);
else if (players == 2)
strcpy(myid,argv[i]);
else
{
printf("Too many options for %s\n",argv[0]);
usage(argv[0]);
}
/* Look up the two players */
realuid = getuid();
if (players >= 1)
{
/* does opponent exist? */
if ((pwd = getpwnam(hisid)) == 0)
{
printf("No user %s on this system\n",hisid);
exit(1);
}
hisuid = pwd->pw_uid;
}
if (players == 2)
{
/* does second name exist? */
if ((pwd = getpwnam(myid)) == 0)
{
printf("No user %s on this system\n",myid);
exit(1);
}
myuid = pwd->pw_uid;
/* If one of the named players is me, ignore it */
#ifdef DEBUG
if (!eachgame && !debugon)
#else
if (!eachgame)
#endif DEBUG
{
if (myuid == realuid)
players = 1;
else if (hisuid == realuid)
{
players = 1;
/* Swap names */
strcpy(myid,hisid);
strcpy(hisid,pwd->pw_name);
hisuid = myuid;
myuid = realuid;
}
}
}
else if (players == 1)
{
/* Get my name */
if ((pwd = getpwuid(realuid)) == 0)
{
printf("Panic: Can't get your password entry\n");
exit(1);
}
strcpy(myid,pwd->pw_name);
myuid = realuid;
}
/* If -a flag and less than two names, do all matching games */
if (eachgame)
{
if (players < 2)
{
activeonly = (players == 0);
scangames(); /* Doesn't return */
}
else
eachgame = FALSE;
}
/* If no -a flag, must have at least one player name */
if (players == 0)
{
printf("Must specify name of opponent.\n");
usage(argv[0]);
}
/* Are we kibitzing? */
if (players == 2) kibitz = TRUE;
#ifdef DEBUG
if (debugon)
{
if (players == 2)
kibitz = FALSE;
else
{
printf("Debug option requires two names.\n");
exit(1);
}
}
#endif DEBUG
/* Get termcap, set cbreak, noecho, trap interupts */
initterm();
run();
exit(-1);
}
/* myid, myuid, hisid and hisuid must be set before calling this */
/* this never returns. It always calls done() instead. */
run()
{
/* Initialize various globals */
wcck = wccq = bcck = bccq = TRUE;
interupt = TRUE;
errcode = E_OK;
status = 0;
taken = SQ;
/* As he playing himself? */
solo = (hisuid == myuid);
/* See if the Move File Exists */
order = -1;
sprintf(fname,"%s/%d.%d",CCDIR,hisuid,myuid);
if ((rfp=fopen(fname,"r"))==NULL)
{
order = 1;
sprintf(fname,"%s/%d.%d",CCDIR,myuid,hisuid);
if ((rfp=fopen(fname,"r"))==NULL)
{
clr();
wprintf("No game in progress between %s and %s\n",
myid,hisid);
if (eachgame || kibitz || transcript) done(0);
wprintf("Would you like to challenge %s (Y/N)? ",
hisid);
if (enterdyn(TRUE))
{
newgame = TRUE;
status = 0;
dochallenge(FALSE);
}
done(0);
}
}
/* Open the Game file to write */
if ((wfp=fopen(fname,"a"))==NULL)
{
wprintf("Cchess error: Unable to write to gamefile %s\n",
fname);
done(1);
}
/* Just print a transcript, if that option was selected */
if (transcript)
{
if (eachgame)
{
if (activeonly)
wprintf("Transcript of game against %s? ",hisid);
else
wprintf("Transcript of game between %s and %s? ",
myid,hisid);
if (!enterdyn(FALSE)) done(0);
}
trans(TRUE);
done(0);
}
newgame = FALSE;
/* read in the game to date */
ldboard();
if (solo) mycolor = toplay;
if (mycolor != toplay)
moveok = FALSE;
else
moveok = !kibitz;
if (eachgame)
{
if (activeonly)
{
if (mycolor == toplay)
{
wprintf("Move against %s? ",hisid);
if (!enterdyn(FALSE)) done(0);
}
else
done(0);
}
else
{
wprintf("Game between %s and %s? ",myid,hisid);
if (!enterdyn(FALSE)) done(0);
}
}
switch (status)
{
case 0: /* no challenge made */
wprintf("Cchess Error: No Challenge after load.\n");
done(1);
case 1: /* challenge made */
doaccept();
/* if white accepted, let him move */
if (status != 3 || (mycolor != WHITE && !solo)) break;
toplay = WHITE;
if (Winitmoves == MO_PROGRESS)
consmoves = 1;
else
consmoves = Winitmoves;
case 3: /* make move */
if (stripped)
domate(Stripresult,EV_FORCES);
else if (inmate)
{
if (incheck)
domate(RE_LOSE,EV_CHECKMATE);
else
domate(Staleresult,EV_STALEMATE);
}
else if (repeated)
domate(RE_DRAW,EV_REPEATED);
else
domove(RE_NONE); /* Make a move */
break;
case 4: /* draw proposal made */
if (tamemoves >= MAXTAME)
domate(RE_DRAW,EV_FIFTYMOVES); /* Draw is final */
else
domove(RE_DRAW); /* Answer a draw proposal */
break;
case 5: /* other player accepted draw */
domate(RE_DRAW,EV_AGREEMENT);
break;
case 6: /* other player forfeited */
domate(RE_WIN,EV_FORFIET);
break;
case 7: /* cancellation proposal made */
domove(RE_CANCEL); /* Answer a cancellation proposal */
break;
case 8: /* other player accepted cancellation */
domate(RE_CANCEL,EV_AGREEMENT);
break;
default:
wprintf("Cchess Error: Weird status %d\n",status);
done(1);
}
done(0);
}
/* SCANGAMES()
*
* If activeonly is set, list all games the user can move in. If activeonly
* is not set, list all games that hisuid is in. For each one, prompt if
* he wants to move in it. Run the program if he does. Visual mode
* not used here.
*/
scangames()
{
register struct direct *gfd;
register char *pwname;
register int n;
int uid1,uid2;
DIR *fp;
if ((fp = opendir(CCDIR))== 0)
{
printf("Panic: unable to read %s directory\n",CCDIR);
exit(1);
}
n = 0;
igpwuid();
/* Get name and uid to search for */
if (activeonly)
{
if ((pwname = gpwuid(myuid = realuid)) == 0)
{
printf("Panic: Can't get your password entry\n");
exit(1);
}
strcpy(myid,pwname);
}
else
{
strcpy(myid,hisid);
myuid = hisuid;
kibitz = TRUE;
}
while ((gfd = readdir(fp)) != NULL)
if (gfd->d_name[0] != '.' && sscanf(gfd->d_name,"%d.%d",&uid1,&uid2)==2)
{
/* Does this game involve me? */
if (uid1 == myuid)
hisuid = uid2;
else if (uid2 == myuid)
hisuid = uid1;
else
continue;
/* Look up the other person's id */
if ((pwname=gpwuid(hisuid)) == 0)
continue;
strcpy(hisid,pwname);
if (n == 0)
{
initterm();
clr();
}
/* Play the game */
if (!setjmp(jmpenv))
run();
n++;
}
endpwent(); /* close the password file */
if (n == 0)
printf("No games\n");
/* Turn off eachgame flag so done() will really exit us */
eachgame = FALSE;
closedir(fp);
done(0);
}
/* USAGE
*
* Print a rather long winded usage message. This doesn't return.
*/
usage(name)
char *name;
{
printf("To play: %s [-a] [-b] opponent\n",name);
printf("To peek: %s [-b] player player\n",name);
printf("For transcript: %s [-a] -t player [player]\n",name);
printf("For scoreboard: %s -s\n",name);
printf("For game list: %s -g [player]\n",name);
exit(1);
}