games-request@tekred.TEK.COM (03/02/88)
Submitted by: Jan Wolter <janc@crim.eecs.umich.edu> Comp.sources.games: Volume 3, Issue 88 Archive-name: cchess/Part03 #! /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 3 (of 5)." # Contents: cchess.h init.c main.c # Wrapped by billr@tekred on Tue Jan 12 12:09:54 1988 PATH=/bin:/usr/bin:/usr/ucb ; export PATH if test -f cchess.h -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"cchess.h\" else echo shar: Extracting \"cchess.h\" \(2560 characters\) sed "s/^X//" >cchess.h <<'END_OF_cchess.h' X/* C O R R E S P O N D E N C E C H E S S Version 1.00 X * X * Play chess with another player, with notification of moves by mail. X * X * (C) Apr 1986 - Jan Dithmar Wolter. X * X * This source code may be freely distributed and modified, but not X * sold or used for profit without the permission of the author. X */ X X#include <stdio.h> X#include <setjmp.h> X#include <signal.h> X#include <pwd.h> X#include <ctype.h> X#include <sys/types.h> X#include <sys/dir.h> X X#include "def.h" X X/* External declarations of all globals */ Xextern boolean newgame,moveok,kibitz,solo,hidden,eachgame; Xextern boolean commodore,incheck,inmate,repeated,stripped,interupt,bigboard; Xextern boolean istame,must_take; Xextern int myillmoves, illmoves, tamemoves, mvssize; Xextern short cx,cy; Xextern short msgarea; Xextern short wfr,wfc,wtr,wtc,bfr,bfc,btr,btc; Xextern schar promote; Xextern schar ib[R_SIZE][C_SIZE],b[R_SIZE][C_SIZE],bc[R_SIZE][C_SIZE]; Xextern schar order,mycolor,toplay,taken; Xextern boolean wcck, wccq, bcck, bccq; Xextern int movecnt,playcnt; Xextern int hisuid,myuid; Xextern int consmade,consmoves; Xextern char status; Xextern char *version, *copyright,file_version[]; Xextern char *resltname[], *captname[HI_CAPTURE+1],*typename[],*langname[]; Xextern char **piecename,*chessname[HI_NAMES+1][PIECES+1],pc[2*PIECES+2]; Xextern char hisid[20],myid[20]; Xextern char cbuffer[CB_LEN+1],*mbuffer,*sbuffer; Xextern char mb1[MB_LEN+1],mb2[MB_LEN+1]; Xextern char blankstr[BLANK_LEN+1]; Xextern char option[OPTIONS],maxopt[OPTIONS]; Xextern char defopt[HI_GAME+1][OPTIONS]; Xextern int errcode; Xextern char bs_char; Xextern char fname[50]; Xextern long lastday; Xextern FILE *rfp; Xextern FILE *wfp; Xextern jmp_buf jmpenv; Xextern boolean issmart,erases,cleardown,scrolled; Xextern int LINES, COLS; X X#ifndef LSIGNAL Xextern jmp_buf susp_env; Xextern boolean susp1_flg, susp2_flg; X#endif LSIGNAL X X#ifdef DEBUG Xextern boolean debugon; X#endif X X/* Declarations of routines */ Xextern struct passwd *getpwnam(), *getpwuid(), *getpwent(); Xextern char enter(), enterd(), xenter(), xenterd(), *getenv(), *fgetl(); Xextern boolean check(), legal(), cart(), diag(), canmove(), place(),forces(); Xextern boolean isrepeat(), compare(),checkbd(), enterdyn(), enteryn(); Xextern boolean editbd(); Xextern char *index(), *strcpy(), *strcat(), *malloc(), *gpwuid(); Xextern char *pcol(), *pcapcol(), *pman(), *pcolman(), *yorn(), *cday(); Xextern char *sprintf(), *strncpy(); Xextern schar compkib(); Xextern long day(), atol(); Xextern int mprintf(); Xextern FILE *upopen(); Xextern int fseek(); X Xextern struct direct *readdir(); END_OF_cchess.h if test 2560 -ne `wc -c <cchess.h`; then echo shar: \"cchess.h\" unpacked with wrong size! fi # end of overwriting check fi if test -f init.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"init.c\" else echo shar: Extracting \"init.c\" \(22583 characters\) sed "s/^X//" >init.c <<'END_OF_init.c' X/* CCHESS CHALLENGE ROUTINES version 1.00 X * X * (C) Copyright - Jan D. Wolter - Apr 1986 X * X * Mostly routines to make and accept game challenges. X */ X X#include "cchess.h" X X#ifndef NOTERMCAP Xextern char *DL; X#endif NOTERMCAP X X/* CHALLENGE() X * X * Make a challenge. User is prompted for options. Challenge line is X * written in the game file. The flag counter is set if this is a X * counter challenge to a previous challenge. X */ X Xdochallenge(counter) Xboolean counter; X{ Xregister int i; Xchar ch,var; X X /* Choose colors */ X X wprint("\nWhat color would you like "); X if (counter) X { X wprintf("[%s]? ",pcol(mycolor)); X ch = enterd("WB",(mycolor==WHITE)?'W':'B'); X } X else X { X wprint("(B/W)? "); X ch = enter("WB"); X } X if (ch == 'W') X { X wprint("hite"); X mycolor = WHITE; X } X else X { X wprint("lack"); X mycolor = BLACK; X } X if (order == (schar) -1) X Firstwhite = (ch == 'B'); X else X Firstwhite = (ch == 'W'); X X wprint("\nDo you wish to play a variant game "); X if (counter) X { X ch = (Game_type != TY_CHESS); X wprintf("[%s]? ",yorn(ch)); X ch = enterdyn(ch); X } X else X { X wprint("(Y/N)? "); X ch = enteryn(); X } X X if (ch) X { X wprint("\nVariants games are:\n"); X wprint(" (A) Chess - Standard modern game\n"); X wprint(" (B) Kriegspiel - Other player's moves hidden\n"); X wprint(" (C) Shatranj - 6th century Persian game\n"); X wprint(" (D) Courier - 13th century 12x8 board game\n"); X wprint(" (E) Halfboard - Standard game on 4x8 board\n"); X wprint(" (F) Karma Chess - Capturing men promoted to victim's rank\n"); X wprint(" (G) Rifle Chess - Capture without moving\n"); X wprint(" (H) Kamikazi Chess - Capturing men lost\n"); X wprint(" (I) Double Chess - Make two moves per turn\n"); X wprint(" (J) Steamroller - White pawns and king move twice\n"); X wprint(" (K) Progressive - One more move every turn\n"); X wprint(" (L) Maharajah - White has only maharajah piece\n"); X wprint(" (M) Losing Chess - First one to lose all his men wins.\n"); X wprint(" (N) Conversion Chess - Combination of Karma and Rifle Chess\n"); X /* If you add to the menu above, add letter to string below */ X if (counter && Game_type == TY_MIXED) X wprint(" (Z) Mixed Game - Same custom game you were challenged to\n"); X wprintf("\nWhich would you like to play [%s]? ", X typename[counter ? Game_type : TY_CHESS]); X ch = xenterd("ZABCDEFGHIJKLMN" + (!counter || Game_type != TY_MIXED), X counter?((Game_type == TY_MIXED)? 'Z': Game_type+'A'-1):'A'); X X var = (ch == 'Z') ? TY_MIXED : ch - 'A' + 1; X wprintf("%c - %s",ch,typename[var]); X X if (var != TY_MIXED) X { X /* Set up default options */ X for (i=1;i<OPTIONS;i++) X option[i] = defopt[var][i]; X X /* Make the initial board */ X setup(b); X } X X wprint("\nWould you like to customize the game? "); X if (enterdyn(counter?(Game_type==TY_MIXED):FALSE)) X { X customize(); X goto skip; X } X } X else X { X /* Copy in the default options */ X for (i=1;i<OPTIONS;i++) X option[i] = defopt[1][i]; X setup(b); X } X X /* Ask about the basic stuff */ X X wprint("Would you like the game to be private (Y/N)? "); X Private = enterdyn(Kriegspiel); X X if (!Musttake && !Kriegspiel && !Musttake && X Capture == CA_NORMAL && Kcapture == CA_NORMAL) X { X wprint("Would you like the computer to kibitz (Y/N)? "); X Help_me = enterdyn(Help_me); X } X else X Help_me = FALSE; X X /* write challenge line to game file */ X Xskip:if (newgame) X { X if ((wfp=fopen(fname,"w"))==NULL) X { X wprintf("Cchess error: Unable to create gamefile %s\n",fname); X done(1); X } X chmod(fname,0700); X fprintf(wfp,"%5ld:V %s\n",day(),version); X } X X /* Save the challenge */ X fprintf(wfp,"%5ld:C ",day()); X saveopts(wfp); X placeboard(b); X fflush(wfp); X X /* send a challenge message */ X sprintf(cbuffer,"You have been challenged to a game of chess by %s.\nRun \042%s %s\042 to respond.\n",myid,RUN_CMD,myid); X mesg("Cchess Challenge",cbuffer); X X} X X/* CUSTOMIZE X * X * Fiddle with low-level game options. This does run in visual mode. X * The use of the goofy loop here is to make suspends work correctly. X */ X Xcustomize() X{ Xschar ob[R_SIZE][C_SIZE]; Xregister int question; Xregister int i; Xboolean progress; Xint v,r,c,tmparea; X X hidden = FALSE; X question = 0; X#ifndef LSIGNAL X susp1_flg = TRUE; X setjmp(susp_env); X#endif LSIGNAL X scrolled = TRUE; X X for ( ; question >= 0 ; question++) X { X if (scrolled) X { X disp(b,WHITE); X if (question != 9) X { X tmparea = (cy + 1 >= LINES) ? LINES - 1 : cy + 1; X cprint("[default answers shown in brackets]"); X } X wputchar('\n'); X msgarea = (cy >= LINES) ? LINES - 1 : cy; X } X switch(question) X { X case 0: /* Get the board size */ X wprintf("Board Size [%dx%d]:",Rows+1,Cols+1); X wprintf("\nRows (1-%d)? ", HI_ROWS+1); X v = readdint(HI_ROWS+1,Rows+1)-1; X wputchar('\n'); X if (v != Rows) scrolled = TRUE; X Rows = v; X break; X case 1: X wprintf("Columns (1-%d)? ", HI_COLS+1); X v = readdint(HI_COLS+1,Cols+1)-1; X wputchar('\n'); X if (v != Cols) scrolled = TRUE; X Cols = v; X if (Cols == 0 && Rows == 0) X { X wprint("You got to be kidding!\n"); X scrolled = FALSE; X question -=2; X } X break; X X case 2: X wprintf("Is the board checkered [%s]? ",yorn(!Plain)); X v = !enterdyn(!Plain); X if (v != Plain) scrolled = TRUE; X Plain = v; X break; X X case 3: /* Piece names */ X initmore(); X mprintf("What names should the pieces be given"); X Language = enterone(langname,HI_NAMES,Language); X piecename = chessname[Language]; X break; X X case 4: /* White King piece */ X wprintf("Should white have a mateable piece [%s]? ", X yorn(Whiteking != SQ)); X if (!enterdyn(Whiteking != SQ)) X { X Whiteking = SQ; X question++; X } X break; X case 5: X wprintf("Which is the white mateable piece [%s]? ", X (Whiteking != SQ)? pman(Whiteking) : ""); X while ((v = xenterd(pc,pc[PIECES-Whiteking])) == ' ') X bell(); X Whiteking = PIECES - (index(pc,v)-pc); X wprintf("%s\n",pman(Whiteking)); X break; X X case 6: /* Black King piece */ X wprintf("Should black have a mateable piece [%s]? ", X yorn(Blackking != SQ)); X if (!enterdyn(Blackking != SQ)) X { X Blackking = SQ; X question++; X } X break; X case 7: X wprintf("Which is the black mateable piece [%s]? ", X (Blackking != SQ)? pman(Blackking) : ""); X while ((v = xenterd(pc,pc[PIECES-Blackking])) == ' ') X bell(); X Blackking = PIECES - (index(pc,v)-pc); X wprintf("%s\n",pman(Blackking)); X break; X X X case 8: /* Edit the board - If board is illegal keep asking till ok */ X wprintf("Would you like to edit the initial placement [No]? "); X if (enterdyn(FALSE)) X { X /* Set things up for the editor */ X copy(b,bc); X copy(b,ob); X#ifndef NOTERMCAP X /* Clear scrolling area */ X if (cleardown) X { X cursor(1,tmparea); X msgarea = tmparea; X clbot(); X } X else X#endif NOTERMCAP X scrolled = TRUE; X X break; X } X else X { X#ifndef NOTERMCAP X if (!DL && cy == LINES) wputchar('\n'); X#endif NOTERMCAP X /* If he says not to edit, make sure board is OK */ X if (!checkbd(b,WHITE) || !checkbd(b,BLACK)) X question--; X else X question++; X } X break; X X case 9: /* Take an editor command */ X if (editbd(b,ob)) X question--; X else X { X#ifndef NOTERMCAP X if (cleardown) X { X cursor(1,msgarea); X clbot(); X cprint("[default answers shown in brackets]"); X wputchar('\n'); X msgarea = (cy >= LINES) ? LINES - 1 : cy; X } X else X#endif NOTERMCAP X scrolled = TRUE; X } X break; X X case 10: /* Enter Capture Rules */ X initmore(); X mprint("What is the rule for pieces capturing"); X Capture = enterone(captname,HI_CAPTURE,Capture); X break; X case 11: X if (Whiteking != SQ || Blackking != SQ) X { X initmore(); X mprint("What is the rule for "); X pkings(mprintf); X mprint(" capturing"); X Kcapture = enterone(captname,HI_KCAPTURE,Kcapture); X } X break; X X case 12: /* Is this Kriegspiel? */ X wprintf("Are enemy pieces visible to player [%s]? ", X yorn(!Kriegspiel)); X Kriegspiel = !enterdyn(!Kriegspiel); X break; X X case 13: /* May both players castle? */ X if (cancastle(b,WHITE) || cancastle(b,BLACK)) X { X wprintf("Is castling allowed [%s]? ", yorn(!Oldcastle)); X Oldcastle = !enterdyn(!Oldcastle); X } X /* if not possible to castle, just leave option with default */ X break; X X case 14: /* Old fashioned pawns? */ X /* Ask if there are any pawns, ask about pawn moves */ X if ((find(b,WP,&r,&c),r != -1) || (find(b,BP,&r,&c),r != -1)) X { X wprintf("Can Pawn move double on their first moves [%s]? ", X yorn(!Oldpawn)); X Oldpawn = (!enterdyn(!Oldpawn)); X } X else X question++; X break; X case 15: X if (Whiteking != WP && Blackking != WP) X { X wprintf("Pawn promotion to %s, %s, %s or %s [%s]? ", X piecename[WQ], piecename[WR], piecename[WB], X piecename[WN], yorn(Promotion==PR_QRBN)); X if (enterdyn(Promotion==PR_QRBN)) X { X Promotion = PR_QRBN; X question++; X } X } X else X { X Promotion = PR_NONE; X question++; X } X break; X case 16: X if (Whiteking != WM && Blackking != WM) X { X wprintf("Pawn promotion to %s only [%s]? ", X piecename[WM], yorn(Promotion!=PR_NONE)); X if (enterdyn(Promotion!=PR_NONE)) X Promotion = PR_MINISTER; X else X Promotion = PR_NONE; X } X else X Promotion = PR_NONE; X break; X X case 17: /* Select Multiple moves */ X if (Capture == CA_CONVERSION || Kcapture == CA_CONVERSION) X { X Whitemoves = Blackmoves = Winitmoves = Binitmoves = 1; X question += 4; X } X else X { X wprintf("Is this a Progressive chess game [%s]? ", X yorn(!Whitemoves)); X progress = enterdyn(!Whitemoves); X } X break; X case 18: X wprintf("How many moves on White's first turn [%d]? ",Winitmoves); X Winitmoves = readdint(HI_WIMOVES,Winitmoves); X wputchar('\n'); X if (progress) X { X Binitmoves = Whitemoves = Blackmoves = MO_PROGRESS; X question += 3; X } X break; X case 19: X wprintf("How many moves on White's later turns [%d]? ", X Whitemoves); X Whitemoves = readdint(HI_WMOVES,Whitemoves); X wputchar('\n'); X break; X case 20: X wprintf("How many moves on Black's first turn [%d]? ", X Binitmoves); X Binitmoves = readdint(HI_BIMOVES,Binitmoves); X wputchar('\n'); X break; X case 21: X wprintf("How many moves on Black's later turns [%d]? ", X Blackmoves); X Blackmoves = readdint(HI_BMOVES,Blackmoves); X wputchar('\n'); X break; X case 22: X if (Winitmoves > 1 || Binitmoves > 1) X { X wprintf("Must players stay on their own sides on the first turns [%s]? ",yorn(Tabiyat)); X Tabiyat = enterdyn(Tabiyat); X } X else X Tabiyat = FALSE; X break; X case 23: X if ((Winitmoves > 1 || Binitmoves > 1 || X Whitemoves > 1 || Blackmoves > 1 || X Whitemoves == MO_PROGRESS) && X (Whiteking != SQ || Blackking != SQ)) X { X wprintf("May "); X pkings(wprintf); X wprintf(" move through check [%s]? ", X yorn(Thrucheck)); X Thrucheck = enterdyn(Thrucheck); X } X break; X X case 24: /* Enter results */ X initmore(); X mprint("What is the effect of being stalemated"); X Staleresult = enterone(resltname,HI_STALE,Staleresult); X break; X case 25: X initmore(); X mprint("What is the effect of losing all forces"); X if (Blackking != SQ || Whiteking != SQ) X mprint(" except your mateable piece"); X Stripresult = enterone(resltname,HI_STRIP,Stripresult); X break; X X case 26: /* Must take? */ X if (Capture != CA_NONE || Kcapture != CA_NONE) X { X wprintf("Must pieces be captured whenever possible [%s]? ", X yorn(Musttake)); X Musttake = enterdyn(Musttake); X } X else X Musttake = FALSE; X break; X X case 27: /* Privacy */ X if (Kriegspiel) X wprint("To prevent peeking, Kriegspiel games should be private:\n"); X X wprintf("Would you like the game to be private [%s]? ", X yorn(Kriegspiel)); X Private = enterdyn(Kriegspiel); X break; X X case 28: /* Computer Kibitzing */ X if (!Musttake && !Kriegspiel && X Capture == CA_NORMAL && Kcapture == CA_NORMAL) X { X wprintf("Would you like the computer to kibitz [Yes]? "); X Help_me = enterdyn(TRUE); X } X else X Help_me = FALSE; X break; X X case 29: /* Give him a chance to make another pass */ X X /* Figure out if anything really got changed */ X for (i=4;i<OPTIONS;i++) X if (i != OP_NAMES && i != OP_BOARD && X option[i] != defopt[Game_type][i]) X { X Game_type = TY_MIXED; X break; X } X X /* Print out the options */ X initmore(); X mprint("Options selected:\n"); X printopts(mprintf); X X mprint("Are these correct? "); X if (enteryn()) X question = -100; /* Exit loop */ X else X question = -1; /* Restart loop */ X break; X X default: X wprint("Lost in customization\n"); X question = -100; X break; X } X } X#ifndef LSIGNAL X susp1_flg = FALSE; X#endif LSIGNAL X} X Xint enterone(name,hi,def) Xint hi; Xchar *name[]; Xint def; X{ Xregister int i; Xregister char ch; X mprintf(" [%s]:\n",name[def]); X for (i = 0; i <= hi; i++) X mprintf(" (%c) %s\n",i+'A',name[i]); X mprintf("enter (A-%c)? ",hi+'A'); X for (;;) X { X if ((ch = getchar()) == '\n' || ch == '\r') X i = def; X else X i = (ch <= 'Z') ? ch - 'A' : ch - 'a'; X X if (i > hi || i < 0) X bell(); X else X break; X } X X mprintf("%c - %s\n",i+'A',name[i]); X return(i); X} X X/* PKINGS() X * X * Print names of mateable pieces. Don't call this if there are none. X * prtf is the function to print with. mprintf or wprintf or printf. X */ X Xpkings(prtf) Xint (*prtf)(); X{ X if (Whiteking != SQ) X { X (*prtf)("%ss",pman(Whiteking)); X if (Whiteking != Blackking && Blackking != SQ) X (*prtf)(" and %ss",pcolman(-Blackking)); X } X else X (*prtf)("%ss", pcolman(-Blackking)); X} X X/* ACCEPT() X * X * Accept Challange mode. Print options. Accept, Reject or X * Counter-challenge. Write appropriate selection in game file. X * Not in visual mode. X */ X Xdoaccept() X{ Xboolean first = TRUE; Xboolean washidden; X X /* Some initialization stuff */ X washidden = hidden; X hidden = FALSE; X#ifndef LSIGNAL X susp1_flg = TRUE; X setjmp(susp_env); X#endif LSIGNAL X scrolled = TRUE; X X for (;;) X { X if (scrolled) X { X disp(b,kibitz?WHITE:mycolor); X wputchar('\n'); X msgarea = (cy >= LINES) ? LINES - 1 : cy; X } X X if (first) X { X initmore(); X if (kibitz) X { X if (moveok) X mprintf("%s has been challenged by %s",myid,hisid); X else X mprintf("%s has been challenged by %s",hisid,myid); X } X else X { X if (moveok) X mprintf("You have been challenged by %s",hisid); X else X mprintf("You have challenged %s",hisid); X } X X mprint(" to a game of correspondence chess\nwith the following options:\n\n"); X printopts(mprintf); X if (!moveok) X { X#ifndef LSIGNAL X susp1_flg = FALSE; X#endif LSIGNAL X hidden = washidden; X return; X } X mprint("Help, "); X first = FALSE; X } X X mprint("Accept, Reject or Counter-Challenge? "); X switch (xenter("LACRVOH?EQ\014")) X { X case 'H': /* Offer help */ X case '?': X wprint("Help\n"); X initmore(); X mprint(" A - Accept this cchess challenge\n"); X mprint(" R - Reject this cchess challenge\n"); X mprint(" C - Counter-challenge with different options\n"); X mprint(" O - Print the options again\n"); X mprint(" L - Print date of challenge\n"); X mprint("^L - Redraw display\n"); X mprint(" Q - Quit the program without doing anything\n"); X break; X X case '\014': X wprint("Redraw\n"); X scrolled = TRUE; X break; X case 'L': X wprintf("Last challenge made on %s\n",cday(lastday)); X break; X X case 'O': /* Redisplay the options */ X wprint("Options\n"); X initmore(); X printopts(mprintf); X break; X X case 'Q': /* Quit */ X wprint("Quit\n"); X return; X case 'E': /* Exit */ X wprint("Exit\n"); X return; X X case 'A': /* challenge accepted */ X wprint("Accept\n"); X#ifndef LSIGNAL X susp1_flg = FALSE; X#endif LSIGNAL X status = 3; X fprintf(wfp,"%5ld:A \n",day()); X /* mail message */ X sprintf(cbuffer, X "Your challenge has been accepted. Run \042%s %s\042.\n", X RUN_CMD,myid); X mesg("Cchess Challenge Accepted",cbuffer); X hidden = washidden; X return; X X case 'R': /* challenge rejected */ X wprint("Reject\n"); X#ifndef LSIGNAL X susp1_flg = FALSE; X#endif LSIGNAL X unlink(fname); X mesg("Cchess Challenge Rejected", X "Your challenge has been rejected.\n"); X return; X X case 'C': /* counter challenge */ X wprint("Challenge\n"); X#ifndef LSIGNAL X susp1_flg = FALSE; X#endif LSIGNAL X clr(); X dochallenge(TRUE); X return; X X case 'V': /* version command */ X versprint(); X break; X } X } X} X X X/* EDITBD() X * X * Edit a board set up. Board ob is passed in with the original arrangment. X * Board nb is the current set up. Upon return, it contains the edited set up. X * The global board, bc should be a copy of nb. This reads just one command. X * It returns FALSE if the last command was a quit. X */ X Xboolean editbd(nb,ob) Xschar nb[R_SIZE][C_SIZE]; Xschar ob[R_SIZE][C_SIZE]; X{ Xshort ox, oy; Xint row,col,i; Xchar buf[40],*name; Xchar ch,cmd; Xschar piece; Xchar *tp; X X /* Prompt for a command */ X X wprint("Place, Delete or Quit? "); X cmd = xenter("PDUEQVH?\014"); X X switch (cmd) X { X case 'H': X case '?': X wprint("Help\n"); X X wprint("Would you like a list of commands? "); X if (enteryn()) X { X initmore(); X mprint("Place - Put a piece on a square\n"); X mprint("Delete - Remove a piece from board\n"); X mprint("Undo - Undo all changes to board\n"); X mprint("Quit - Exit board edit mode\n"); X mprint("^L - Redraw the screen\n"); X } X X wprint("Would you like a list of pieces? "); X if (enteryn()) X { X initmore(); X for (i=1;i<PIECES;i+=2) X mprintf(" %c = %-9.9s %c = %-9.9s\n", X pc[PIECES-i],piecename[i], X pc[PIECES-i-1],piecename[i+1]); X#if (PIECES % 2) == 1 X mprintf(" %c = %-9.9s\n", X pc[0],piecename[PIECES]); X#endif X } X break; X X case 'P': X wprint("Place\n"); X X /* Get the piece */ X wprint("What Type of Piece (upper case for black)? "); X for (;;) X { X ch = getchar(); X if (ch == '\n' || ch == '\r') break; X if (ch == 'p') ch = 'i'; X else if (ch == 'P') ch = 'I'; X if ((tp = index(pc,ch)) != 0) break; X bell(); X } X if (ch == '\n' || ch == '\r') X { X wputchar('\n'); X break; X } X piece = (tp-pc)-PIECES; X wprint(name = pcolman(piece)); X X /* Get the position */ X wprintf("\nWhere should the %s be placed? ",name); X X case 'D': X if (cmd == 'D') X { X piece = SQ; X wprint("Delete\nFrom what position? "); X } X if (!pread(buf)) break; X col = buf[0] - 'A'; X row = buf[1] - '1'; X wputchar('\n'); X X if (cmd == 'D' && nb[row][col] == SQ) X { X wprintf("No piece at %2.2s\n",buf); X break; X } X X /* Make the change to the board copy */ X bc[row][col] = piece; X X /* Display the new position */ X#ifndef NOTERMCAP X if (!scrolled && issmart) X { X ox = cx; oy = cy; X update(nb,bc); X cursor(ox,oy); X } X else X { X#endif NOTERMCAP X disp(bc, kibitz ? WHITE : mycolor); X wputchar('\n'); X#ifndef NOTERMCAP X } X#endif NOTERMCAP X /* Make the change to the real board */ X nb[row][col] = piece; X break; X X case 'U': X wprint("Undo\n"); X if (compare(nb,ob)) X { X wprint("No changes have been made\n"); X break; X } X wprint("Do you want to undo all changes? "); X if (!enteryn()) break; X#ifndef NOTERMCAP X if (!scrolled && issmart) X { X ox = cx; oy = cy; X update(nb,ob); X cursor(ox,oy); X } X else X#endif NOTERMCAP X scrolled = TRUE; X X copy(ob,nb); X copy(ob,bc); X break; X X case 'Q': /* Quit */ X wprint("Quit\n"); X case 'E': /* Exit */ X if (cmd == 'E') wprint("Exit\n"); X#ifndef NOTERMCAP X if (!DL && cy == LINES) wputchar('\n'); X#endif NOTERMCAP X /* Make sure we got a sane board */ X if (!(checkbd(nb,WHITE) && checkbd(nb,BLACK))) break; X X /* Confirm that he is really done */ X wprint("Are you sure you're done editing? "); X if (!enteryn()) break; X return(FALSE); X X case '\014': /* Control-L redraws the screen */ X wprint("Redraw\n"); X scrolled = TRUE; X break; X X case 'V': /* Version */ X versprint(); X break; X } X return(TRUE); X} X X X/* CHECKBD() X * X * Check if an edited board is a reasonable one. This is currently X * a bit too strict. It should really only check if the second player X * is in check, or the first player is stalemated. X */ X Xboolean checkbd(nb,color) Xschar nb[R_SIZE][C_SIZE]; Xschar color; X{ Xint row,col; Xregister int r,c; Xschar myking = Kingpiece(color); X X if (myking != SQ) X { X /* Find a King */ X switch (piececount(nb,myking,&row,&col)) X { X case 0: X wprintf("No %s on board\n",pcolman(myking)); X return(FALSE); X case 2: X wprintf("Too many %ss on the board\n",pcolman(myking)); X return(FALSE); X } X X if (check(nb,-color,row,col)) X { X wprintf("%s is in check\n",pcolman(myking)); X return(FALSE); X } X } X else X { X /* Make sure you have at least some sort of piece */ X for (r=0;r<=Rows;r++) X for (c=0;c<=Cols;c++) X if (nb[r][c]*color > 0) X goto ok; X wprintf("No %s pieces on board\n",pcol(color)); X return(FALSE); X } X Xok: if(!canmove(nb,color,FALSE)) X { X wprintf("%s cannot move\n",pcol(color)); X return(FALSE); X } X X return(TRUE); X} X X/* PIECECOUNT X * X * Return 0 if there are no pieces of the type, 1 if there is exactly one, X * or 2 if there are more than one. The location of the first one found X * is returned in the last two. X */ X Xint piececount(nb,piece,row,col) Xschar nb[R_SIZE][C_SIZE]; Xschar piece; Xint *row,*col; X{ Xregister int r,c,tcol; X X /* Find one Piece */ X find(nb,piece,row,col); X if (*row == -1) X return(0); X X /* Any more of them? */ X tcol = *col; X for (r = *row;r <= Rows;r++) X { X for (c=tcol+1; c<=Cols; c++) X if (nb[r][c] == piece) X return(2); X tcol = -1; X } X return(1); X} X X/* CANCASTLE X * X * If there is a sensible way to castle on the current board? X */ X Xcancastle(nb,color) Xschar nb[R_SIZE][C_SIZE]; Xschar color; X{ Xint row,col; X X /* There is exactly one king of this color */ X if (piececount(nb,color*WK,&row,&col) != 1) X return(FALSE); X X /* There is a rook of the same color at one of the margins */ X return (nb[row][0] == color*WR || nb[row][Cols] == color*WR); X} X Xversprint() X{ X wprintf("Version %s %s\n",version,copyright); X} END_OF_init.c if test 22583 -ne `wc -c <init.c`; then echo shar: \"init.c\" unpacked with wrong size! fi # end of overwriting check fi if test -f main.c -a "${1}" != "-c" ; then echo shar: Will not over-write existing file \"main.c\" else echo shar: Extracting \"main.c\" \(25282 characters\) sed "s/^X//" >main.c <<'END_OF_main.c' X/* C O R R E S P O N D E N C E C H E S S version 1.00 X * X * Play chess with another player, with notification of moves by mail. X * X * (C) Copyright - Dec 1987 - Jan Dithmar Wolter. X * X * This source code may be freely used, but not for purposes of profit X * without the permission of the author. This copyright notice should X * not be removed. X * X * I would be very interested in hearing about suggestions, bug reports, X * and porting problems with cchess. I can be mailed on usenet at X * janc@crim.eecs.umich.edu. Better yet, dial into M-Net at X * (313)994-6333, give yourself an account and join the "ugames" X * conference. This is a free public bbs and cchess's development site. X * X * Any programmer who wishes to make improvements should be warned that X * this is a sadly unmodular program. There are tons of global variables X * and subroutines have curious side-effects. The arrays containing the X * board (b and bc) and the input buffers (mbuffer and sbuffer) are X * particularly strange this way, being used for just about everything. X * Sorry. That's what happens when what was originally supposed to be a X * "quicky" project grows for five years. X * X * version 0.10: X * First pre-release version. X * version 0.11: X * Added Unix 4.2bsd support. X * Rationalized version dependent signal handlers as much as X * possible with three different signal handling libraries. X * Added Computer Kibitzing option to help make up for poor X * graphics. X * version 0.12: X * Save illegal moves in kriegspeil games. X * Added Big Board option on Ron Theriault's suggestion. X * Solidified Forfiet/Draw code. (Finally). X * Touched up transcripts. X * Added help command. X * version 0.13: X * Added support for 22 column terminals (Commodores). X * Pawn promotion noted on transcripts. X * Redraw and Version work at "Not your move prompt" X * Solidified Challenge/Accept code. (Finally). X * version 0.14: X * Cosmetic changes to Exit command. X * Fix system() calls to protect them from dirty tricks. X * Let Kriegspielers replay the game after it is over. X * Improve castling code so it will work for halfboard games. X * Kriegspiel only counts some kinds of illegal moves. X * Time stamp added to each line of game file. X * Version and Redraw commands work at accept draw prompt. X * Replay renamed Playback, and dodraw() integrated with domove(). X * White pieces displayed with highlighting on the big board. X * Divided sys.c file into sys.c and scrn.c. X * Fixed a bug that caused moves to get lost during playbacks. X * version 0.15: X * Fixed a pawn promotion bug that appeared in 0.14. X * Added Shatranj and Courier game variations. X * Added Karma, Rifle & Kamikazi Chess capture variations. X * Version 6 style ioctl() calls now understood by sys.c X * version 0.16 X * Repeated position detection code kludged in. X * Fifty move rule enforcement installed. X * Game cancellation command added. X * Minor bug fixes to Karma chess, Kriegspiel and Scoreboard. X * version 0.17 X * Big changes in the way options are represented internally X * and in game files and in score file. X * Addition of Maharajah piece. X * Multiple moves for variant games. X * Steamroller, Double Chess and Progressive variants added. X * Initial board set-up specified in transcript file. X * O command to display current game options added. X * mprint() for "--More--" on Help and Options. X * Board editor for custom chess boards. X * Further generalization of castling code. X * No spaces allowed in transcript file names. X * Bug fixes to mate detection. X * Redraw works at "Are you sure" and "Move:" prompts. X * Use user defined backspace character from stty calls. X * Mailer is run in background. X * Clarification of format of comments under board. X * version 0.18 X * May name a user with -g option. X * Speedup of -g option with lookaside buffer for passwd lookups. X * Auto-redraw after suspend (sort of) made to work. X * Addition of French and German piece names. X * Various small bug fixes for system V. X * Added -a option to move in all possible games. X * Fixed printing of cancellation requests in transcripts. X * Illegal moves optionally printed in kriegspiel transcripts. X * Enter kibitz mode only if you are neither of the players. X * Changes to allow no king, or some other mateable piece. X * Fixes to the computer kibitzer (rooks don't cover themselves). X * Bug Fixes to playback of multimove games. X * Broke cmd.c file into cmd.c and init.c. X * Added Last command to display date of last move. X * Redesign of challenge and accept subsystems. X * Maharajah and Losing chess variant games added. X * Many fixes to mate detection. X * Tab'iyat option for sped up openings. X * version 0.19 X * Turned off nl to crnl mapping and fixed stuff to work that way. X * Rewrote directory reading to use clone of 4.2bsd readdir(). X * Fix things so display isn't confused by R lines in gamefile. X * Close files when -a option is used. X * Fix queen moves in mate detection. X * Simplification of compile time definitions. X * Rewrite to simplify cctrans() routine. X * Innumerable minor fixes and clean up work all over. X * Conversion Chess added with thanks to Kenneth Larimer. X * Version numbers added to game files. X * Crude support of 4.3bsd windowing interupt. X * version 1.00 X * Cleaned up for posting to USENET. X */ X X#include "cchess.h" X X/* String identifying current version */ Xchar *version = "0.19"; Xchar *copyright = "(c) 1987 Jan Wolter"; X X/* Characters and Names for pieces (some foreign name sets are incomplete) */ X Xchar pc[] = "HJDEMIRNBQK kqbnrimedjh"; Xchar *chessname[HI_NAMES+1][PIECES+1] = { X { "Empty Square", "King", "Queen", "Bishop", X "Knight", "Rook", "Pawn", "Minister", X "Elephant", "Duke", "Jester", "Maharajah"}, X X { "Empty Square", "Shah", "Queen", "Bishop", X "Faras", "Rukh", "Baidaq", "Firz", X "Fil", "Duke", "Jester", "Maharajah"}, X X { "Empty Square", "Roi", "Dame", "Fou", X "Cavaler", "Tour", "Pion", "Ministre", X "Elephant", "Duc", "Jester", "Maharajah"}, X X { "Empty Square", "Konig", "Dame", "Laufer", X "Springer", "Turm", "Bauer", "Minister", X "Elefant", "Herzog", "Jester", "Maharajah"} }; Xchar **piecename; X Xshort wfr,wfc,wtr,wtc; /* last white move - used for en paussant legality */ Xshort bfr,bfc,btr,btc; /* last black move - used for en paussant legality */ Xschar promote = 0; /* Character to promote pawn to - 0 if no promotion */ X X/* Have the Kings or the Rooks been moved? */ Xboolean wcck = TRUE; /* White can castle king-side */ Xboolean wccq = TRUE; /* White can castle queen-side */ Xboolean bcck = TRUE; /* Black can castle king-side */ Xboolean bccq = TRUE; /* Black can castle queen-side */ X X/* Initial board layout */ X /* Last four columns */ Xschar ib[R_SIZE][C_SIZE] = { /* for Courier only. */ X WR, WN, WB, WQ, WK, WB, WN, WR, WB, WE, WN, WR, X WP, WP, WP, WP, WP, WP, WP, WP, WP, WP, WP, WP, X SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, X SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, X SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, X SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, SQ, X BP, BP, BP, BP, BP, BP, BP, BP, BP, BP, BP, BP, X BR, BN, BB, BQ, BK, BB, BN, BR, BB, BE, BN, BR, X }; X Xschar bc[R_SIZE][C_SIZE]; /* Copy of the board, so moves can be taken back */ Xschar b[R_SIZE][C_SIZE]; /* Main board */ Xint errcode; /* Move error code */ X Xint hisuid; /* Opponent user id number */ Xint myuid; /* Player user id number */ Xchar hisid[20]; /* Opponent login name */ Xchar myid[20]; /* Player login name */ X#ifdef COMPAT018 Xchar file_version[6] = "0.18"; /* Version of cchess that produced game file */ X /* If no version line, assume 0.18 */ X#else Xchar file_version[6] = ""; /* Version of cchess that produced game file */ X#endif COMPAT018 X Xint movecnt; /* Number of moves made so far in game */ Xint playcnt; /* Number of moves including proposals */ Xint mvssize; /* Number of moves on the move stack */ Xint tamemoves; /* Number of tame moves made */ Xint consmoves; /* Number of consecutive moves allowed */ Xint consmade; /* Number of consecutive moves made */ X Xchar fname[50]; /* Name of the gameboardfile */ XFILE *rfp; /* File pointer for reading from boardfile */ XFILE *wfp; /* File pointer for writing to boardfile */ X X/* Game status code: X * 0 -> No challenge made. X * 1 -> Challenge has been sent. X * 2 -> (not used) X * 3 -> Ready to move. X * 4 -> A draw has been proposed. X * 5 -> A draw has been accepted. X * 6 -> Player has forfeited. X * 7 -> cancellation has been proposed. X * 8 -> cancellation has been accepted. X */ X Xchar status; X X/* General Purpose Global Flags */ X Xboolean newgame; /* Are we starting a new game file? */ Xboolean moveok = TRUE; /* Allow player to move? */ Xboolean solo; /* Is he playing himself? */ Xboolean kibitz = FALSE; /* Is this a kibitzing session? */ Xboolean bigboard = FALSE; /* Display board in large format? */ Xboolean hidden = FALSE; /* Should enemy moves be shown? */ Xboolean incheck = FALSE; /* Is player in check (or mate)? */ Xboolean inmate = FALSE; /* Is plater (check or stale) mated */ Xboolean repeated = FALSE; /* Is this a thrice repeated position? */ Xboolean stripped = FALSE; /* Have we just stripped the other player? */ Xboolean istame; /* Was the last move a tame one? */ Xboolean interupt; /* OK to interupt out of program? */ Xboolean eachgame = FALSE; /* Play each playable game? */ Xboolean must_take = FALSE; /* Allow only moves which capture? */ X Xschar toplay=WHITE; /* color to play next */ Xschar order; /* -1 if other player named first, else 1 */ Xschar mycolor; /* What color am I? */ Xschar taken; /* Piece taken in last move. SQ for none. */ Xlong lastday; /* Day number on which last move was made. */ Xboolean erases=TRUE; /* Can terminal erase properly? */ Xboolean issmart=FALSE; /* Can address cursor and erase? */ Xboolean cleardown=FALSE; /* Can clear screen below cursor and smart? */ Xboolean commodore=FALSE; /* Do we have a 22 column terminal? */ Xboolean scrolled=FALSE; /* Has the screen scrolled? */ Xint illmoves; /* Count of illegal Kriegspiel moves */ Xint myillmoves; /* Count of my illegal Kriegspiel moves */ Xshort cx,cy; /* Current Cursor position (used by TERMCAP) */ Xshort msgarea = 0; /* Line below screen where prompts begin */ Xint LINES = 0; /* Number of lines per screen */ Xint COLS = 40; /* Number of columns per screen */ Xchar bs_char = '\b'; /* User definable backspace character */ X#ifdef DEBUG Xboolean debugon = FALSE; /* Debugging flag */ X#endif DEBUG X X/* Names of standard variant games */ Xchar *typename[HI_GAME+1] = { X "Mixed", "Chess", "Kriegspiel", "Shatranj", "Courier", X "Halfboard Chess", "Karma Chess", "Rifle Chess", "Kamikazi Chess", X "Double Chess", "Steamroller", "Progressive Chess", "Maharajah", X "Losing Chess", "Conversion Chess"}; X Xchar *langname[HI_NAMES+1] = { "English","Persian","French","German"}; X X/* Names of game results */ Xchar *resltname[4] = {"Draw","Win","Lose","Continue"}; X X/* Names of Capture rules */ Xchar *captname[HI_CAPTURE+1] = X {"Standard","No","Rifle","Conversion","Karma","Kamikazi"}; X X/* Current game options */ Xchar option[OPTIONS]; X X/* Maximum legal values for the options */ Xchar maxopt[OPTIONS] = X { HI_COLOR, HI_PRIVATE, HI_KIBITZ, HI_GAME, X HI_ROWS, HI_COLS, HI_BOARD, HI_NAMES, X HI_VISIB, HI_CASTLE, HI_DPAWN, HI_STRIP, X HI_STALE, HI_CAPTURE, HI_KCAPTURE, HI_PROMOTE, X HI_WIMOVES, HI_BIMOVES, HI_WMOVES, HI_BMOVES, X HI_THRUCHECK, HI_WHITEKING, HI_BLACKKING, HI_MUSTTAKE, X HI_TABIYAT }; X X/* Variant game default options */ Xchar defopt[HI_GAME+1][OPTIONS] = X { X /* Customized game */ X { FALSE, FALSE, TRUE, TY_MIXED, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Standard Chess */ X { FALSE, FALSE, TRUE, TY_CHESS, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Kriegspiel */ X { FALSE, FALSE, TRUE, TY_KRIEGSPIEL, X 7, 7, FALSE, 0, X TRUE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Shatranj */ X { FALSE, FALSE, TRUE, TY_SHATRANJ, X 7, 7, TRUE, 1, X FALSE, TRUE, TRUE, RE_LOSE, X RE_WIN, CA_NORMAL, CA_NORMAL, PR_MINISTER, X 10, 10, 1, 1, X FALSE, WK, WK, FALSE, X TRUE }, X X /* Courier */ X { FALSE, FALSE, TRUE, TY_COURIER, X 7, 11, TRUE, 0, X FALSE, TRUE, TRUE, RE_LOSE, X RE_WIN, CA_NORMAL, CA_NORMAL, PR_MINISTER, X 12, 12, 1, 1, X FALSE, WK, WK, FALSE, X TRUE }, X X /* Halfboard */ X { FALSE, FALSE, TRUE, TY_HALFBOARD, X 7, 3, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Karma Chess */ X { FALSE, FALSE, TRUE, TY_KARMA, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_KARMA, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Rifle Chess */ X { FALSE, FALSE, TRUE, TY_RIFLE, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_RIFLE, CA_RIFLE, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Kamikazi Chess */ X { FALSE, FALSE, TRUE, TY_KAMIKAZI, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_KAMIKAZI, CA_NONE, PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE }, X X /* Double Move Chess */ X { FALSE, FALSE, TRUE, TY_DOUBLE, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 2, 2, 2, 2, X TRUE, WK, WK, FALSE, X FALSE }, X X /* Steamroller */ X { FALSE, FALSE, TRUE, TY_STEAMROLLER, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 2, 1, 2, 1, X TRUE, WK, WK, FALSE, X FALSE }, X X /* Progressive Chess */ X { FALSE, FALSE, TRUE, TY_PROGRESSIVE, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_LOSE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, MO_PROGRESS, MO_PROGRESS, MO_PROGRESS, X FALSE, SQ, SQ, FALSE, X FALSE }, X X /* Maharajah */ X { FALSE, FALSE, TRUE, TY_MAHARAJAH, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, WH, WK, FALSE, X FALSE }, X X /* Losing Chess */ X { FALSE, FALSE, FALSE, TY_LOSING, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_WIN, X RE_WIN, CA_NORMAL, CA_NORMAL, PR_QRBN, X 1, 1, 1, 1, X FALSE, SQ, SQ, FALSE, X FALSE }, X X /* Conversion Chess */ X { FALSE, FALSE, TRUE, TY_CONVERSION, X 7, 7, FALSE, 0, X FALSE, FALSE, FALSE, RE_NONE, X RE_DRAW, CA_CONVERSION,CA_CONVERSION,PR_QRBN, X 1, 1, 1, 1, X FALSE, WK, WK, FALSE, X FALSE } }; X Xchar cbuffer[CB_LEN+1]; /* Comment Buffer */ Xchar mb1[MB_LEN+1]; /* Move Buffer One. */ Xchar mb2[MB_LEN+1]; /* Move Buffer Two. */ Xchar *mbuffer=mb1; /* Pointer to current move buffer */ Xchar *sbuffer=mb2; /* Pointer to spare move buffer */ Xjmp_buf jmpenv; /* Long jump buffer */ X X/* Some really weird things used to sort of recover from suspends: */ X/* susp1_flg is set if susp_env contains a place to jump to after */ X/* we've been suspended. susp2_flg is turned on if we got suspended */ X/* while there was no susp_env defined */ X#ifndef LSIGNAL Xjmp_buf susp_env; Xboolean susp1_flg = FALSE, susp2_flg = FALSE; X#endif LSIGNAL X X/* String of spaces used when arbitary strings of spaces are needed */ Xchar blankstr[BLANK_LEN+1] /* Must be exactly BLANK_LEN spaces */ X = " "; X X Xchar transcript = FALSE; /* Should we just print the transcript? */ X Xint realuid; Xboolean activeonly = FALSE; X Xmain(argc,argv) Xint argc; Xchar *argv[]; X{ Xstruct passwd *pwd; /* Password file entry */ Xregister int players,i,j; X X /* check legality of arguments */ X players = 0; X for (i=1;i<argc;i++) X if (argv[i][0] == '-') X for (j = 1; argv[i][j]; j++) X switch (argv[i][j]) X { X case 'a': X eachgame = TRUE; X break; X X case 's': X scoreboard(); X exit(0); X X case 'b': X bigboard = TRUE; X break; X X case 'g': X if (++i < argc) X { X if ((pwd = getpwnam(argv[i])) == 0) X { X printf("No user %s on this system\n",argv[i]); X exit(1); X } X printf("%s's games in progress\n-----------------------------\n", X argv[i]); X list(pwd->pw_uid); X } X else X { X printf("Games in progress\n-----------------\n"); X list(-1); X } X exit(0); X X case 't': X transcript = TRUE; X break; X#ifdef DEBUG X case 'd': X debugon = TRUE; X break; X#endif DEBUG X default: X printf("Illegal %s option: -%c\n",argv[0],argv[i][j]); X usage(argv[0]); X } X else X if (++players == 1) X strcpy(hisid,argv[i]); X else if (players == 2) X strcpy(myid,argv[i]); X else X { X printf("Too many options for %s\n",argv[0]); X usage(argv[0]); X } X X /* Look up the two players */ X X realuid = getuid(); X X if (players >= 1) X { X /* does opponent exist? */ X if ((pwd = getpwnam(hisid)) == 0) X { X printf("No user %s on this system\n",hisid); X exit(1); X } X hisuid = pwd->pw_uid; X } X if (players == 2) X { X /* does second name exist? */ X if ((pwd = getpwnam(myid)) == 0) X { X printf("No user %s on this system\n",myid); X exit(1); X } X myuid = pwd->pw_uid; X X /* If one of the named players is me, ignore it */ X#ifdef DEBUG X if (!eachgame && !debugon) X#else X if (!eachgame) X#endif DEBUG X { X if (myuid == realuid) X players = 1; X else if (hisuid == realuid) X { X players = 1; X /* Swap names */ X strcpy(myid,hisid); X strcpy(hisid,pwd->pw_name); X hisuid = myuid; X myuid = realuid; X } X } X } X else if (players == 1) X { X /* Get my name */ X if ((pwd = getpwuid(realuid)) == 0) X { X printf("Panic: Can't get your password entry\n"); X exit(1); X } X strcpy(myid,pwd->pw_name); X myuid = realuid; X } X X /* If -a flag and less than two names, do all matching games */ X if (eachgame) X { X if (players < 2) X { X activeonly = (players == 0); X scangames(); /* Doesn't return */ X } X else X eachgame = FALSE; X } X X /* If no -a flag, must have at least one player name */ X if (players == 0) X { X printf("Must specify name of opponent.\n"); X usage(argv[0]); X } X X /* Are we kibitzing? */ X if (players == 2) kibitz = TRUE; X X#ifdef DEBUG X if (debugon) X { X if (players == 2) X kibitz = FALSE; X else X { X printf("Debug option requires two names.\n"); X exit(1); X } X } X#endif DEBUG X X /* Get termcap, set cbreak, noecho, trap interupts */ X initterm(); X X run(); X exit(-1); X} X X X/* myid, myuid, hisid and hisuid must be set before calling this */ X/* this never returns. It always calls done() instead. */ X Xrun() X{ X /* Initialize various globals */ X wcck = wccq = bcck = bccq = TRUE; X interupt = TRUE; X errcode = E_OK; X status = 0; X taken = SQ; X X /* As he playing himself? */ X solo = (hisuid == myuid); X X /* See if the Move File Exists */ X order = -1; X sprintf(fname,"%s/%d.%d",CCDIR,hisuid,myuid); X X if ((rfp=fopen(fname,"r"))==NULL) X { X order = 1; X sprintf(fname,"%s/%d.%d",CCDIR,myuid,hisuid); X X if ((rfp=fopen(fname,"r"))==NULL) X { X clr(); X wprintf("No game in progress between %s and %s\n", X myid,hisid); X if (eachgame || kibitz || transcript) done(0); X wprintf("Would you like to challenge %s (Y/N)? ", X hisid); X if (enterdyn(TRUE)) X { X newgame = TRUE; X status = 0; X dochallenge(FALSE); X } X done(0); X } X } X X /* Open the Game file to write */ X X if ((wfp=fopen(fname,"a"))==NULL) X { X wprintf("Cchess error: Unable to write to gamefile %s\n", X fname); X done(1); X } X X /* Just print a transcript, if that option was selected */ X if (transcript) X { X if (eachgame) X { X if (activeonly) X wprintf("Transcript of game against %s? ",hisid); X else X wprintf("Transcript of game between %s and %s? ", X myid,hisid); X if (!enterdyn(FALSE)) done(0); X } X trans(TRUE); X done(0); X } X X newgame = FALSE; X X /* read in the game to date */ X ldboard(); X X if (solo) mycolor = toplay; X if (mycolor != toplay) X moveok = FALSE; X else X moveok = !kibitz; X if (eachgame) X { X if (activeonly) X { X if (mycolor == toplay) X { X wprintf("Move against %s? ",hisid); X if (!enterdyn(FALSE)) done(0); X } X else X done(0); X } X else X { X wprintf("Game between %s and %s? ",myid,hisid); X if (!enterdyn(FALSE)) done(0); X } X } X X switch (status) X { X case 0: /* no challenge made */ X wprintf("Cchess Error: No Challenge after load.\n"); X done(1); X X case 1: /* challenge made */ X doaccept(); X /* if white accepted, let him move */ X if (status != 3 || (mycolor != WHITE && !solo)) break; X toplay = WHITE; X if (Winitmoves == MO_PROGRESS) X consmoves = 1; X else X consmoves = Winitmoves; X X case 3: /* make move */ X if (stripped) X domate(Stripresult,EV_FORCES); X else if (inmate) X { X if (incheck) X domate(RE_LOSE,EV_CHECKMATE); X else X domate(Staleresult,EV_STALEMATE); X } X else if (repeated) X domate(RE_DRAW,EV_REPEATED); X else X domove(RE_NONE); /* Make a move */ X break; X X case 4: /* draw proposal made */ X if (tamemoves >= MAXTAME) X domate(RE_DRAW,EV_FIFTYMOVES); /* Draw is final */ X else X domove(RE_DRAW); /* Answer a draw proposal */ X break; X X case 5: /* other player accepted draw */ X domate(RE_DRAW,EV_AGREEMENT); X break; X X case 6: /* other player forfeited */ X X domate(RE_WIN,EV_FORFIET); X break; X X case 7: /* cancellation proposal made */ X domove(RE_CANCEL); /* Answer a cancellation proposal */ X break; X X case 8: /* other player accepted cancellation */ X domate(RE_CANCEL,EV_AGREEMENT); X break; X X default: X wprintf("Cchess Error: Weird status %d\n",status); X done(1); X } X X done(0); X} X X X X/* SCANGAMES() X * X * If activeonly is set, list all games the user can move in. If activeonly X * is not set, list all games that hisuid is in. For each one, prompt if X * he wants to move in it. Run the program if he does. Visual mode X * not used here. X */ X Xscangames() X{ Xregister struct direct *gfd; Xregister char *pwname; Xregister int n; Xint uid1,uid2; XDIR *fp; X X if ((fp = opendir(CCDIR))== 0) X { X printf("Panic: unable to read %s directory\n",CCDIR); X exit(1); X } X n = 0; X igpwuid(); X X /* Get name and uid to search for */ X if (activeonly) X { X if ((pwname = gpwuid(myuid = realuid)) == 0) X { X printf("Panic: Can't get your password entry\n"); X exit(1); X } X strcpy(myid,pwname); X } X else X { X strcpy(myid,hisid); X myuid = hisuid; X kibitz = TRUE; X } X X while ((gfd = readdir(fp)) != NULL) X if (gfd->d_name[0] != '.' && sscanf(gfd->d_name,"%d.%d",&uid1,&uid2)==2) X { X /* Does this game involve me? */ X if (uid1 == myuid) X hisuid = uid2; X else if (uid2 == myuid) X hisuid = uid1; X else X continue; X X /* Look up the other person's id */ X if ((pwname=gpwuid(hisuid)) == 0) X continue; X strcpy(hisid,pwname); X X if (n == 0) X { X initterm(); X clr(); X } X X /* Play the game */ X if (!setjmp(jmpenv)) X run(); X n++; X } X endpwent(); /* close the password file */ X if (n == 0) X printf("No games\n"); X X /* Turn off eachgame flag so done() will really exit us */ X eachgame = FALSE; X closedir(fp); X done(0); X} X X X X/* USAGE X * X * Print a rather long winded usage message. This doesn't return. X */ X Xusage(name) Xchar *name; X{ X printf("To play: %s [-a] [-b] opponent\n",name); X printf("To peek: %s [-b] player player\n",name); X printf("For transcript: %s [-a] -t player [player]\n",name); X printf("For scoreboard: %s -s\n",name); X printf("For game list: %s -g [player]\n",name); X exit(1); X} END_OF_main.c if test 25282 -ne `wc -c <main.c`; then echo shar: \"main.c\" unpacked with wrong size! fi # end of overwriting check fi echo shar: End of archive 3 \(of 5\). cp /dev/null ark3isdone MISSING="" for I in 1 2 3 4 5 ; do if test ! -f ark${I}isdone ; then MISSING="${MISSING} ${I}" fi done if test "${MISSING}" = "" ; then echo You have unpacked all 5 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