🚀 go-pugleaf

RetroBBS NetNews Server

Inspired by RockSolid Light RIP Retro Guy

Thread View: net.sources.games
1 messages
1 total messages Started by games-request Tue, 01 Mar 1988 23:26
v03i088: cchess - corrispondence chess, Part03/05
#1
Author: games-request
Date: Tue, 01 Mar 1988 23:26
2014 lines
56828 bytes
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
Thread Navigation

This is a paginated view of messages in the thread with full content displayed inline.

Messages are displayed in chronological order, with the original post highlighted in green.

Use pagination controls to navigate through all messages in large threads.

Back to All Threads