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