|
DataMuseum.dkPresents historical artifacts from the history of: DKUUG/EUUG Conference tapes |
This is an automatic "excavation" of a thematic subset of
See our Wiki for more about DKUUG/EUUG Conference tapes Excavated with: AutoArchaeologist - Free & Open Source Software. |
top - metrics - downloadIndex: T i
Length: 22583 (0x5837) Types: TextFile Names: »init.c«
└─⟦b20c6495f⟧ Bits:30007238 EUUGD18: Wien-båndet, efterår 1987 └─⟦this⟧ »EUUGD18/General/Cchess/init.c«
/* CCHESS CHALLENGE ROUTINES version 1.00 * * (C) Copyright - Jan D. Wolter - Apr 1986 * * Mostly routines to make and accept game challenges. */ #include "cchess.h" #ifndef NOTERMCAP extern char *DL; #endif NOTERMCAP /* CHALLENGE() * * Make a challenge. User is prompted for options. Challenge line is * written in the game file. The flag counter is set if this is a * counter challenge to a previous challenge. */ dochallenge(counter) boolean counter; { register int i; char ch,var; /* Choose colors */ wprint("\nWhat color would you like "); if (counter) { wprintf("[%s]? ",pcol(mycolor)); ch = enterd("WB",(mycolor==WHITE)?'W':'B'); } else { wprint("(B/W)? "); ch = enter("WB"); } if (ch == 'W') { wprint("hite"); mycolor = WHITE; } else { wprint("lack"); mycolor = BLACK; } if (order == (schar) -1) Firstwhite = (ch == 'B'); else Firstwhite = (ch == 'W'); wprint("\nDo you wish to play a variant game "); if (counter) { ch = (Game_type != TY_CHESS); wprintf("[%s]? ",yorn(ch)); ch = enterdyn(ch); } else { wprint("(Y/N)? "); ch = enteryn(); } if (ch) { wprint("\nVariants games are:\n"); wprint(" (A) Chess - Standard modern game\n"); wprint(" (B) Kriegspiel - Other player's moves hidden\n"); wprint(" (C) Shatranj - 6th century Persian game\n"); wprint(" (D) Courier - 13th century 12x8 board game\n"); wprint(" (E) Halfboard - Standard game on 4x8 board\n"); wprint(" (F) Karma Chess - Capturing men promoted to victim's rank\n"); wprint(" (G) Rifle Chess - Capture without moving\n"); wprint(" (H) Kamikazi Chess - Capturing men lost\n"); wprint(" (I) Double Chess - Make two moves per turn\n"); wprint(" (J) Steamroller - White pawns and king move twice\n"); wprint(" (K) Progressive - One more move every turn\n"); wprint(" (L) Maharajah - White has only maharajah piece\n"); wprint(" (M) Losing Chess - First one to lose all his men wins.\n"); wprint(" (N) Conversion Chess - Combination of Karma and Rifle Chess\n"); /* If you add to the menu above, add letter to string below */ if (counter && Game_type == TY_MIXED) wprint(" (Z) Mixed Game - Same custom game you were challenged to\n"); wprintf("\nWhich would you like to play [%s]? ", typename[counter ? Game_type : TY_CHESS]); ch = xenterd("ZABCDEFGHIJKLMN" + (!counter || Game_type != TY_MIXED), counter?((Game_type == TY_MIXED)? 'Z': Game_type+'A'-1):'A'); var = (ch == 'Z') ? TY_MIXED : ch - 'A' + 1; wprintf("%c - %s",ch,typename[var]); if (var != TY_MIXED) { /* Set up default options */ for (i=1;i<OPTIONS;i++) option[i] = defopt[var][i]; /* Make the initial board */ setup(b); } wprint("\nWould you like to customize the game? "); if (enterdyn(counter?(Game_type==TY_MIXED):FALSE)) { customize(); goto skip; } } else { /* Copy in the default options */ for (i=1;i<OPTIONS;i++) option[i] = defopt[1][i]; setup(b); } /* Ask about the basic stuff */ wprint("Would you like the game to be private (Y/N)? "); Private = enterdyn(Kriegspiel); if (!Musttake && !Kriegspiel && !Musttake && Capture == CA_NORMAL && Kcapture == CA_NORMAL) { wprint("Would you like the computer to kibitz (Y/N)? "); Help_me = enterdyn(Help_me); } else Help_me = FALSE; /* write challenge line to game file */ skip:if (newgame) { if ((wfp=fopen(fname,"w"))==NULL) { wprintf("Cchess error: Unable to create gamefile %s\n",fname); done(1); } chmod(fname,0700); fprintf(wfp,"%5ld:V %s\n",day(),version); } /* Save the challenge */ fprintf(wfp,"%5ld:C ",day()); saveopts(wfp); placeboard(b); fflush(wfp); /* send a challenge message */ 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); mesg("Cchess Challenge",cbuffer); } /* CUSTOMIZE * * Fiddle with low-level game options. This does run in visual mode. * The use of the goofy loop here is to make suspends work correctly. */ customize() { schar ob[R_SIZE][C_SIZE]; register int question; register int i; boolean progress; int v,r,c,tmparea; hidden = FALSE; question = 0; #ifndef LSIGNAL susp1_flg = TRUE; setjmp(susp_env); #endif LSIGNAL scrolled = TRUE; for ( ; question >= 0 ; question++) { if (scrolled) { disp(b,WHITE); if (question != 9) { tmparea = (cy + 1 >= LINES) ? LINES - 1 : cy + 1; cprint("[default answers shown in brackets]"); } wputchar('\n'); msgarea = (cy >= LINES) ? LINES - 1 : cy; } switch(question) { case 0: /* Get the board size */ wprintf("Board Size [%dx%d]:",Rows+1,Cols+1); wprintf("\nRows (1-%d)? ", HI_ROWS+1); v = readdint(HI_ROWS+1,Rows+1)-1; wputchar('\n'); if (v != Rows) scrolled = TRUE; Rows = v; break; case 1: wprintf("Columns (1-%d)? ", HI_COLS+1); v = readdint(HI_COLS+1,Cols+1)-1; wputchar('\n'); if (v != Cols) scrolled = TRUE; Cols = v; if (Cols == 0 && Rows == 0) { wprint("You got to be kidding!\n"); scrolled = FALSE; question -=2; } break; case 2: wprintf("Is the board checkered [%s]? ",yorn(!Plain)); v = !enterdyn(!Plain); if (v != Plain) scrolled = TRUE; Plain = v; break; case 3: /* Piece names */ initmore(); mprintf("What names should the pieces be given"); Language = enterone(langname,HI_NAMES,Language); piecename = chessname[Language]; break; case 4: /* White King piece */ wprintf("Should white have a mateable piece [%s]? ", yorn(Whiteking != SQ)); if (!enterdyn(Whiteking != SQ)) { Whiteking = SQ; question++; } break; case 5: wprintf("Which is the white mateable piece [%s]? ", (Whiteking != SQ)? pman(Whiteking) : ""); while ((v = xenterd(pc,pc[PIECES-Whiteking])) == ' ') bell(); Whiteking = PIECES - (index(pc,v)-pc); wprintf("%s\n",pman(Whiteking)); break; case 6: /* Black King piece */ wprintf("Should black have a mateable piece [%s]? ", yorn(Blackking != SQ)); if (!enterdyn(Blackking != SQ)) { Blackking = SQ; question++; } break; case 7: wprintf("Which is the black mateable piece [%s]? ", (Blackking != SQ)? pman(Blackking) : ""); while ((v = xenterd(pc,pc[PIECES-Blackking])) == ' ') bell(); Blackking = PIECES - (index(pc,v)-pc); wprintf("%s\n",pman(Blackking)); break; case 8: /* Edit the board - If board is illegal keep asking till ok */ wprintf("Would you like to edit the initial placement [No]? "); if (enterdyn(FALSE)) { /* Set things up for the editor */ copy(b,bc); copy(b,ob); #ifndef NOTERMCAP /* Clear scrolling area */ if (cleardown) { cursor(1,tmparea); msgarea = tmparea; clbot(); } else #endif NOTERMCAP scrolled = TRUE; break; } else { #ifndef NOTERMCAP if (!DL && cy == LINES) wputchar('\n'); #endif NOTERMCAP /* If he says not to edit, make sure board is OK */ if (!checkbd(b,WHITE) || !checkbd(b,BLACK)) question--; else question++; } break; case 9: /* Take an editor command */ if (editbd(b,ob)) question--; else { #ifndef NOTERMCAP if (cleardown) { cursor(1,msgarea); clbot(); cprint("[default answers shown in brackets]"); wputchar('\n'); msgarea = (cy >= LINES) ? LINES - 1 : cy; } else #endif NOTERMCAP scrolled = TRUE; } break; case 10: /* Enter Capture Rules */ initmore(); mprint("What is the rule for pieces capturing"); Capture = enterone(captname,HI_CAPTURE,Capture); break; case 11: if (Whiteking != SQ || Blackking != SQ) { initmore(); mprint("What is the rule for "); pkings(mprintf); mprint(" capturing"); Kcapture = enterone(captname,HI_KCAPTURE,Kcapture); } break; case 12: /* Is this Kriegspiel? */ wprintf("Are enemy pieces visible to player [%s]? ", yorn(!Kriegspiel)); Kriegspiel = !enterdyn(!Kriegspiel); break; case 13: /* May both players castle? */ if (cancastle(b,WHITE) || cancastle(b,BLACK)) { wprintf("Is castling allowed [%s]? ", yorn(!Oldcastle)); Oldcastle = !enterdyn(!Oldcastle); } /* if not possible to castle, just leave option with default */ break; case 14: /* Old fashioned pawns? */ /* Ask if there are any pawns, ask about pawn moves */ if ((find(b,WP,&r,&c),r != -1) || (find(b,BP,&r,&c),r != -1)) { wprintf("Can Pawn move double on their first moves [%s]? ", yorn(!Oldpawn)); Oldpawn = (!enterdyn(!Oldpawn)); } else question++; break; case 15: if (Whiteking != WP && Blackking != WP) { wprintf("Pawn promotion to %s, %s, %s or %s [%s]? ", piecename[WQ], piecename[WR], piecename[WB], piecename[WN], yorn(Promotion==PR_QRBN)); if (enterdyn(Promotion==PR_QRBN)) { Promotion = PR_QRBN; question++; } } else { Promotion = PR_NONE; question++; } break; case 16: if (Whiteking != WM && Blackking != WM) { wprintf("Pawn promotion to %s only [%s]? ", piecename[WM], yorn(Promotion!=PR_NONE)); if (enterdyn(Promotion!=PR_NONE)) Promotion = PR_MINISTER; else Promotion = PR_NONE; } else Promotion = PR_NONE; break; case 17: /* Select Multiple moves */ if (Capture == CA_CONVERSION || Kcapture == CA_CONVERSION) { Whitemoves = Blackmoves = Winitmoves = Binitmoves = 1; question += 4; } else { wprintf("Is this a Progressive chess game [%s]? ", yorn(!Whitemoves)); progress = enterdyn(!Whitemoves); } break; case 18: wprintf("How many moves on White's first turn [%d]? ",Winitmoves); Winitmoves = readdint(HI_WIMOVES,Winitmoves); wputchar('\n'); if (progress) { Binitmoves = Whitemoves = Blackmoves = MO_PROGRESS; question += 3; } break; case 19: wprintf("How many moves on White's later turns [%d]? ", Whitemoves); Whitemoves = readdint(HI_WMOVES,Whitemoves); wputchar('\n'); break; case 20: wprintf("How many moves on Black's first turn [%d]? ", Binitmoves); Binitmoves = readdint(HI_BIMOVES,Binitmoves); wputchar('\n'); break; case 21: wprintf("How many moves on Black's later turns [%d]? ", Blackmoves); Blackmoves = readdint(HI_BMOVES,Blackmoves); wputchar('\n'); break; case 22: if (Winitmoves > 1 || Binitmoves > 1) { wprintf("Must players stay on their own sides on the first turns [%s]? ",yorn(Tabiyat)); Tabiyat = enterdyn(Tabiyat); } else Tabiyat = FALSE; break; case 23: if ((Winitmoves > 1 || Binitmoves > 1 || Whitemoves > 1 || Blackmoves > 1 || Whitemoves == MO_PROGRESS) && (Whiteking != SQ || Blackking != SQ)) { wprintf("May "); pkings(wprintf); wprintf(" move through check [%s]? ", yorn(Thrucheck)); Thrucheck = enterdyn(Thrucheck); } break; case 24: /* Enter results */ initmore(); mprint("What is the effect of being stalemated"); Staleresult = enterone(resltname,HI_STALE,Staleresult); break; case 25: initmore(); mprint("What is the effect of losing all forces"); if (Blackking != SQ || Whiteking != SQ) mprint(" except your mateable piece"); Stripresult = enterone(resltname,HI_STRIP,Stripresult); break; case 26: /* Must take? */ if (Capture != CA_NONE || Kcapture != CA_NONE) { wprintf("Must pieces be captured whenever possible [%s]? ", yorn(Musttake)); Musttake = enterdyn(Musttake); } else Musttake = FALSE; break; case 27: /* Privacy */ if (Kriegspiel) wprint("To prevent peeking, Kriegspiel games should be private:\n"); wprintf("Would you like the game to be private [%s]? ", yorn(Kriegspiel)); Private = enterdyn(Kriegspiel); break; case 28: /* Computer Kibitzing */ if (!Musttake && !Kriegspiel && Capture == CA_NORMAL && Kcapture == CA_NORMAL) { wprintf("Would you like the computer to kibitz [Yes]? "); Help_me = enterdyn(TRUE); } else Help_me = FALSE; break; case 29: /* Give him a chance to make another pass */ /* Figure out if anything really got changed */ for (i=4;i<OPTIONS;i++) if (i != OP_NAMES && i != OP_BOARD && option[i] != defopt[Game_type][i]) { Game_type = TY_MIXED; break; } /* Print out the options */ initmore(); mprint("Options selected:\n"); printopts(mprintf); mprint("Are these correct? "); if (enteryn()) question = -100; /* Exit loop */ else question = -1; /* Restart loop */ break; default: wprint("Lost in customization\n"); question = -100; break; } } #ifndef LSIGNAL susp1_flg = FALSE; #endif LSIGNAL } int enterone(name,hi,def) int hi; char *name[]; int def; { register int i; register char ch; mprintf(" [%s]:\n",name[def]); for (i = 0; i <= hi; i++) mprintf(" (%c) %s\n",i+'A',name[i]); mprintf("enter (A-%c)? ",hi+'A'); for (;;) { if ((ch = getchar()) == '\n' || ch == '\r') i = def; else i = (ch <= 'Z') ? ch - 'A' : ch - 'a'; if (i > hi || i < 0) bell(); else break; } mprintf("%c - %s\n",i+'A',name[i]); return(i); } /* PKINGS() * * Print names of mateable pieces. Don't call this if there are none. * prtf is the function to print with. mprintf or wprintf or printf. */ pkings(prtf) int (*prtf)(); { if (Whiteking != SQ) { (*prtf)("%ss",pman(Whiteking)); if (Whiteking != Blackking && Blackking != SQ) (*prtf)(" and %ss",pcolman(-Blackking)); } else (*prtf)("%ss", pcolman(-Blackking)); } /* ACCEPT() * * Accept Challange mode. Print options. Accept, Reject or * Counter-challenge. Write appropriate selection in game file. * Not in visual mode. */ doaccept() { boolean first = TRUE; boolean washidden; /* Some initialization stuff */ washidden = hidden; hidden = FALSE; #ifndef LSIGNAL susp1_flg = TRUE; setjmp(susp_env); #endif LSIGNAL scrolled = TRUE; for (;;) { if (scrolled) { disp(b,kibitz?WHITE:mycolor); wputchar('\n'); msgarea = (cy >= LINES) ? LINES - 1 : cy; } if (first) { initmore(); if (kibitz) { if (moveok) mprintf("%s has been challenged by %s",myid,hisid); else mprintf("%s has been challenged by %s",hisid,myid); } else { if (moveok) mprintf("You have been challenged by %s",hisid); else mprintf("You have challenged %s",hisid); } mprint(" to a game of correspondence chess\nwith the following options:\n\n"); printopts(mprintf); if (!moveok) { #ifndef LSIGNAL susp1_flg = FALSE; #endif LSIGNAL hidden = washidden; return; } mprint("Help, "); first = FALSE; } mprint("Accept, Reject or Counter-Challenge? "); switch (xenter("LACRVOH?EQ\014")) { case 'H': /* Offer help */ case '?': wprint("Help\n"); initmore(); mprint(" A - Accept this cchess challenge\n"); mprint(" R - Reject this cchess challenge\n"); mprint(" C - Counter-challenge with different options\n"); mprint(" O - Print the options again\n"); mprint(" L - Print date of challenge\n"); mprint("^L - Redraw display\n"); mprint(" Q - Quit the program without doing anything\n"); break; case '\014': wprint("Redraw\n"); scrolled = TRUE; break; case 'L': wprintf("Last challenge made on %s\n",cday(lastday)); break; case 'O': /* Redisplay the options */ wprint("Options\n"); initmore(); printopts(mprintf); break; case 'Q': /* Quit */ wprint("Quit\n"); return; case 'E': /* Exit */ wprint("Exit\n"); return; case 'A': /* challenge accepted */ wprint("Accept\n"); #ifndef LSIGNAL susp1_flg = FALSE; #endif LSIGNAL status = 3; fprintf(wfp,"%5ld:A \n",day()); /* mail message */ sprintf(cbuffer, "Your challenge has been accepted. Run \042%s %s\042.\n", RUN_CMD,myid); mesg("Cchess Challenge Accepted",cbuffer); hidden = washidden; return; case 'R': /* challenge rejected */ wprint("Reject\n"); #ifndef LSIGNAL susp1_flg = FALSE; #endif LSIGNAL unlink(fname); mesg("Cchess Challenge Rejected", "Your challenge has been rejected.\n"); return; case 'C': /* counter challenge */ wprint("Challenge\n"); #ifndef LSIGNAL susp1_flg = FALSE; #endif LSIGNAL clr(); dochallenge(TRUE); return; case 'V': /* version command */ versprint(); break; } } } /* EDITBD() * * Edit a board set up. Board ob is passed in with the original arrangment. * Board nb is the current set up. Upon return, it contains the edited set up. * The global board, bc should be a copy of nb. This reads just one command. * It returns FALSE if the last command was a quit. */ boolean editbd(nb,ob) schar nb[R_SIZE][C_SIZE]; schar ob[R_SIZE][C_SIZE]; { short ox, oy; int row,col,i; char buf[40],*name; char ch,cmd; schar piece; char *tp; /* Prompt for a command */ wprint("Place, Delete or Quit? "); cmd = xenter("PDUEQVH?\014"); switch (cmd) { case 'H': case '?': wprint("Help\n"); wprint("Would you like a list of commands? "); if (enteryn()) { initmore(); mprint("Place - Put a piece on a square\n"); mprint("Delete - Remove a piece from board\n"); mprint("Undo - Undo all changes to board\n"); mprint("Quit - Exit board edit mode\n"); mprint("^L - Redraw the screen\n"); } wprint("Would you like a list of pieces? "); if (enteryn()) { initmore(); for (i=1;i<PIECES;i+=2) mprintf(" %c = %-9.9s %c = %-9.9s\n", pc[PIECES-i],piecename[i], pc[PIECES-i-1],piecename[i+1]); #if (PIECES % 2) == 1 mprintf(" %c = %-9.9s\n", pc[0],piecename[PIECES]); #endif } break; case 'P': wprint("Place\n"); /* Get the piece */ wprint("What Type of Piece (upper case for black)? "); for (;;) { ch = getchar(); if (ch == '\n' || ch == '\r') break; if (ch == 'p') ch = 'i'; else if (ch == 'P') ch = 'I'; if ((tp = index(pc,ch)) != 0) break; bell(); } if (ch == '\n' || ch == '\r') { wputchar('\n'); break; } piece = (tp-pc)-PIECES; wprint(name = pcolman(piece)); /* Get the position */ wprintf("\nWhere should the %s be placed? ",name); case 'D': if (cmd == 'D') { piece = SQ; wprint("Delete\nFrom what position? "); } if (!pread(buf)) break; col = buf[0] - 'A'; row = buf[1] - '1'; wputchar('\n'); if (cmd == 'D' && nb[row][col] == SQ) { wprintf("No piece at %2.2s\n",buf); break; } /* Make the change to the board copy */ bc[row][col] = piece; /* Display the new position */ #ifndef NOTERMCAP if (!scrolled && issmart) { ox = cx; oy = cy; update(nb,bc); cursor(ox,oy); } else { #endif NOTERMCAP disp(bc, kibitz ? WHITE : mycolor); wputchar('\n'); #ifndef NOTERMCAP } #endif NOTERMCAP /* Make the change to the real board */ nb[row][col] = piece; break; case 'U': wprint("Undo\n"); if (compare(nb,ob)) { wprint("No changes have been made\n"); break; } wprint("Do you want to undo all changes? "); if (!enteryn()) break; #ifndef NOTERMCAP if (!scrolled && issmart) { ox = cx; oy = cy; update(nb,ob); cursor(ox,oy); } else #endif NOTERMCAP scrolled = TRUE; copy(ob,nb); copy(ob,bc); break; case 'Q': /* Quit */ wprint("Quit\n"); case 'E': /* Exit */ if (cmd == 'E') wprint("Exit\n"); #ifndef NOTERMCAP if (!DL && cy == LINES) wputchar('\n'); #endif NOTERMCAP /* Make sure we got a sane board */ if (!(checkbd(nb,WHITE) && checkbd(nb,BLACK))) break; /* Confirm that he is really done */ wprint("Are you sure you're done editing? "); if (!enteryn()) break; return(FALSE); case '\014': /* Control-L redraws the screen */ wprint("Redraw\n"); scrolled = TRUE; break; case 'V': /* Version */ versprint(); break; } return(TRUE); } /* CHECKBD() * * Check if an edited board is a reasonable one. This is currently * a bit too strict. It should really only check if the second player * is in check, or the first player is stalemated. */ boolean checkbd(nb,color) schar nb[R_SIZE][C_SIZE]; schar color; { int row,col; register int r,c; schar myking = Kingpiece(color); if (myking != SQ) { /* Find a King */ switch (piececount(nb,myking,&row,&col)) { case 0: wprintf("No %s on board\n",pcolman(myking)); return(FALSE); case 2: wprintf("Too many %ss on the board\n",pcolman(myking)); return(FALSE); } if (check(nb,-color,row,col)) { wprintf("%s is in check\n",pcolman(myking)); return(FALSE); } } else { /* Make sure you have at least some sort of piece */ for (r=0;r<=Rows;r++) for (c=0;c<=Cols;c++) if (nb[r][c]*color > 0) goto ok; wprintf("No %s pieces on board\n",pcol(color)); return(FALSE); } ok: if(!canmove(nb,color,FALSE)) { wprintf("%s cannot move\n",pcol(color)); return(FALSE); } return(TRUE); } /* PIECECOUNT * * Return 0 if there are no pieces of the type, 1 if there is exactly one, * or 2 if there are more than one. The location of the first one found * is returned in the last two. */ int piececount(nb,piece,row,col) schar nb[R_SIZE][C_SIZE]; schar piece; int *row,*col; { register int r,c,tcol; /* Find one Piece */ find(nb,piece,row,col); if (*row == -1) return(0); /* Any more of them? */ tcol = *col; for (r = *row;r <= Rows;r++) { for (c=tcol+1; c<=Cols; c++) if (nb[r][c] == piece) return(2); tcol = -1; } return(1); } /* CANCASTLE * * If there is a sensible way to castle on the current board? */ cancastle(nb,color) schar nb[R_SIZE][C_SIZE]; schar color; { int row,col; /* There is exactly one king of this color */ if (piececount(nb,color*WK,&row,&col) != 1) return(FALSE); /* There is a rook of the same color at one of the margins */ return (nb[row][0] == color*WR || nb[row][Cols] == color*WR); } versprint() { wprintf("Version %s %s\n",version,copyright); }