diff options
Diffstat (limited to 'FICS/board.c')
-rw-r--r-- | FICS/board.c | 1001 |
1 files changed, 1001 insertions, 0 deletions
diff --git a/FICS/board.c b/FICS/board.c new file mode 100644 index 0000000..efffcfb --- /dev/null +++ b/FICS/board.c @@ -0,0 +1,1001 @@ +/* board.c + * + */ + +/* + fics - An internet chess server. + Copyright (C) 1993 Richard V. Nash + + This program is free software; you can redistribute it and/or modify + it under the terms of the GNU General Public License as published by + the Free Software Foundation; either version 2 of the License, or + (at your option) any later version. + + This program is distributed in the hope that it will be useful, + but WITHOUT ANY WARRANTY; without even the implied warranty of + MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + GNU General Public License for more details. +*/ + +/* Revision history: + name email yy/mm/dd Change + Richard Nash 93/10/22 Created +*/ + +#include "stdinclude.h" + +#include "common.h" +#include "board.h" +#include "playerdb.h" +#include "gamedb.h" +#include "utils.h" + +extern int style1(); +extern int style2(); +extern int style3(); +extern int style4(); +extern int style5(); +extern int style6(); +extern int style7(); +extern int style8(); +extern int style9(); +extern int style10(); +extern int style11(); +extern int style12(); +extern int style13(); + +PUBLIC char *wpstring[] = {" ", "P", "N", "B", "R", "Q", "K"}; +PUBLIC char *bpstring[] = {" ", "p", "n", "b", "r", "q", "k"}; + +PUBLIC int pieceValues[7] = {0, 1, 3, 3, 5, 9, 0}; +PUBLIC int (*styleFuncs[MAX_STYLES]) () = { + style1, + style2, + style3, + style4, + style5, + style6, + style7, + style8, + style9, + style10, + style11, + style12, + style13 +}; + +PRIVATE const int mach_type = (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11); +#define IsMachineStyle(n) (((1<<(n)) & mach_type) != 0) + +PRIVATE char bstring[MAX_BOARD_STRING_LEGTH]; + +PUBLIC int board_init(game_state_t *b, char *category, char *board) +{ + int retval; + int wval; + + if (!category || !board || !category[0] || !board[0]) + retval = board_read_file("standard", "standard", b); + else { + if (!strcmp(category, "wild")) { + if (sscanf(board, "%d", &wval) == 1 && wval >= 1 && wval <= 4) + wild_update(wval); + } + retval = board_read_file(category, board, b); + } + b->gameNum = -1; + return retval; +} + +PUBLIC void board_calc_strength(game_state_t *b, int *ws, int *bs) +{ + int r, f; + int *p; + + *ws = *bs = 0; + for (f = 0; f < 8; f++) { + for (r = 0; r < 8; r++) { + if (colorval(b->board[r][f]) == WHITE) + p = ws; + else + p = bs; + *p += pieceValues[piecetype(b->board[r][f])]; + } + } + for (r = PAWN; r <= QUEEN; r++) { + *ws += b->holding[0][r-1] * pieceValues[r]; + *bs += b->holding[1][r-1] * pieceValues[r]; + } +} + +PRIVATE char *holding_str(int *holding) +{ + static char tmp[30]; + int p,i,j; + + i = 0; + for (p = PAWN; p <= QUEEN; p++) + { + for (j = 0; j < holding[p-1]; j++) + { + tmp[i++] = wpstring[p][0]; + } + } + tmp[i] = '\0'; + return tmp; +} + +PRIVATE char *append_holding_machine(char *buf, int g, int c, int p) +{ + game_state_t *gs = &garray[g].game_state; + char tmp[50]; + + sprintf(tmp, "<b1> game %d white [%s] black [", g+1, holding_str(gs->holding[0])); + strcat(tmp, holding_str(gs->holding[1])); + strcat(buf, tmp); + if (p) { + sprintf(tmp, "] <- %c%s\n", "WB"[c], wpstring[p]); + strcat(buf, tmp); + } else + strcat(buf, "]\n"); + return buf; +} + +PRIVATE char *append_holding_display(char *buf, game_state_t *gs, int white) +{ + if (white) + strcat(buf, "White holding: ["); + else + strcat(buf, "Black holding: ["); + strcat(buf, holding_str(gs->holding[white ? 0 : 1])); + strcat(buf, "]\n"); + return buf; +} + +PUBLIC void update_holding(int g, int pieceCaptured) +{ + int p = piecetype(pieceCaptured); + int c = colorval(pieceCaptured); + game_state_t *gs = &garray[g].game_state; + int pp, pl; + char tmp1[80], tmp2[80]; + + if (c == WHITE) { + c = 0; + pp = garray[g].white; + } else { + c = 1; + pp = garray[g].black; + } + gs->holding[c][p-1]++; + tmp1[0] = '\0'; + append_holding_machine(tmp1, g, c, p); + sprintf(tmp2, "Game %d %s received: %s -> [%s]\n", g+1, + parray[pp].name, wpstring[p], holding_str(gs->holding[c])); + for (pl = 0; pl < p_num; pl++) { + if (parray[pl].status == PLAYER_EMPTY) + continue; + if (player_is_observe(pl, g) || (parray[pl].game == g)) { + pprintf_prompt(pl, IsMachineStyle(parray[pl].style) ? tmp1 : tmp2); + } + } +} + +/* Globals used for each board */ +PRIVATE char *wName, *bName; +PRIVATE int wTime, bTime; +PRIVATE int orient; +PRIVATE int forPlayer; +PRIVATE int myTurn; /* 1 = my turn, 0 = observe, -1 = other turn */ + /* 2 = examiner, -2 = observing examiner */ + /* -3 = just send position (spos/refresh) */ + +PUBLIC char *board_to_string(char *wn, char *bn, + int wt, int bt, + game_state_t *b, move_t *ml, int style, + int orientation, int relation, + int p) +{ + int bh = (b->gameNum >= 0 && garray[b->gameNum].link >= 0); + wName = wn; + bName = bn; + wTime = wt; + bTime = bt; + orient = orientation; + myTurn = relation; + + forPlayer = p; + if ((style < 0) || (style >= MAX_STYLES)) + return NULL; + + if (style != 11) { /* game header */ + sprintf(bstring, "Game %d (%s vs. %s)\n\n", + b->gameNum + 1, + garray[b->gameNum].white_name, + garray[b->gameNum].black_name); + } else + bstring[0] = '\0'; + if (bh && !IsMachineStyle(style)) + append_holding_display(bstring, b, orientation==BLACK); + if (styleFuncs[style] (b, ml)) + return NULL; + if (bh) { + if (IsMachineStyle(style)) + append_holding_machine(bstring, b->gameNum, 0, 0); + else + append_holding_display(bstring, b, orientation==WHITE); + } + return bstring; +} + +PUBLIC char *move_and_time(move_t *m) +{ + static char tmp[20]; + sprintf(tmp, "%-7s (%s)", m->algString, tenth_str(m->tookTime, 0)); + return tmp; +} + +/* The following take the game state and whole move list */ + +PRIVATE int genstyle(game_state_t *b, move_t *ml, char *wp[], char *bp[], + char *wsqr, char *bsqr, + char *top, char *mid, char *start, char *end, char *label, + char *blabel) +{ + int f, r, count; + char tmp[80]; + int first, last, inc; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + if (orient == WHITE) { + first = 7; + last = 0; + inc = -1; + } else { + first = 0; + last = 7; + inc = 1; + } + strcat(bstring, top); + for (f = first, count = 7; f != last + inc; f += inc, count--) { + sprintf(tmp, " %d %s", f + 1, start); + strcat(bstring, tmp); + for (r = last; r != first - inc; r = r - inc) { + if (square_color(r, f) == WHITE) + strcat(bstring, wsqr); + else + strcat(bstring, bsqr); + if (piecetype(b->board[r][f]) == NOPIECE) { + if (square_color(r, f) == WHITE) + strcat(bstring, bp[0]); + else + strcat(bstring, wp[0]); + } else { + if (colorval(b->board[r][f]) == WHITE) + strcat(bstring, wp[piecetype(b->board[r][f])]); + else + strcat(bstring, bp[piecetype(b->board[r][f])]); + } + } + sprintf(tmp, "%s", end); + strcat(bstring, tmp); + switch (count) { + case 7: + sprintf(tmp, " Move # : %d (%s)", b->moveNum, CString(b->onMove)); + strcat(bstring, tmp); + break; + case 6: +/* if ((b->moveNum > 1) || (b->onMove == BLACK)) { */ +/* The change from the above line to the one below is a kludge by hersco. */ + if (garray[b->gameNum].numHalfMoves > 0) { +/* loon: think this fixes the crashing ascii board on takeback bug */ + sprintf(tmp, " %s Moves : '%s'", CString(CToggle(b->onMove)), + move_and_time(&ml[garray[b->gameNum].numHalfMoves - 1])); + strcat(bstring, tmp); + } + break; + case 5: + break; + case 4: + sprintf(tmp, " Black Clock : %s", tenth_str(((bTime > 0) ? bTime : 0), 1)); + strcat(bstring, tmp); + break; + case 3: + sprintf(tmp, " White Clock : %s", tenth_str(((wTime > 0) ? wTime : 0), 1)); + strcat(bstring, tmp); + break; + case 2: + sprintf(tmp, " Black Strength : %d", bs); + strcat(bstring, tmp); + break; + case 1: + sprintf(tmp, " White Strength : %d", ws); + strcat(bstring, tmp); + break; + case 0: + break; + } + strcat(bstring, "\n"); + if (count != 0) + strcat(bstring, mid); + else + strcat(bstring, top); + } + if (orient == WHITE) + strcat(bstring, label); + else + strcat(bstring, blabel); + return 0; +} + +/* Experimental ANSI board for colour representation */ +PUBLIC int style13(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" ", "\033[37m\033[1m P ", "\033[37m\033[1m N ", "\033[37m\033[1m B ", "\033[37m\033[1m R ", "\033[37m\033[1m Q ", "\033[37m\033[1m K "}; + static char *bp[] = {" ", "\033[21m\033[37m P ", "\033[21m\033[37m N ", "\033[21m\033[37m B ", "\033[21m\033[37m R ", "\033[21m\033[37m Q ", "\033[21m\033[37m K "}; + static char *wsqr = "\033[40m"; + static char *bsqr = "\033[45m"; + static char *top = "\t+------------------------+\n"; + static char *mid = ""; + static char *start = "|"; + static char *end = "\033[0m|"; + static char *label = "\t a b c d e f g h\n"; + static char *blabel = "\t h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Standard ICS */ +PUBLIC int style1(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" |", " P |", " N |", " B |", " R |", " Q |", " K |"}; + static char *bp[] = {" |", " *P|", " *N|", " *B|", " *R|", " *Q|", " *K|"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = "\t---------------------------------\n"; + static char *mid = "\t|---+---+---+---+---+---+---+---|\n"; + static char *start = "|"; + static char *end = ""; + static char *label = "\t a b c d e f g h\n"; + static char *blabel = "\t h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* USA-Today Sports Center-style board */ +PUBLIC int style2(game_state_t *b, move_t *ml) +{ + static char *wp[] = {"+ ", "P ", "N ", "B ", "R ", "Q ", "K "}; + static char *bp[] = {"- ", "p' ", "n' ", "b' ", "r' ", "q' ", "k' "}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = ""; + static char *mid = ""; + static char *start = ""; + static char *end = ""; + static char *label = "\ta b c d e f g h\n"; + static char *blabel = "\th g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Experimental vt-100 ANSI board for dark backgrounds */ +PUBLIC int style3(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" ", " P ", " N ", " B ", " R ", " Q ", " K "}; + static char *bp[] = {" ", " *P", " *N", " *B", " *R", " *Q", " *K"}; + static char *wsqr = "\033[0m"; + static char *bsqr = "\033[7m"; + static char *top = "\t+------------------------+\n"; + static char *mid = ""; + static char *start = "|"; + static char *end = "\033[0m|"; + static char *label = "\t a b c d e f g h\n"; + static char *blabel = "\t h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Experimental vt-100 ANSI board for light backgrounds */ +PUBLIC int style4(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" ", " P ", " N ", " B ", " R ", " Q ", " K "}; + static char *bp[] = {" ", " *P", " *N", " *B", " *R", " *Q", " *K"}; + static char *wsqr = "\033[7m"; + static char *bsqr = "\033[0m"; + static char *top = "\t+------------------------+\n"; + static char *mid = ""; + static char *start = "|"; + static char *end = "\033[0m|"; + static char *label = "\t a b c d e f g h\n"; + static char *blabel = "\t h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Style suggested by ajpierce@med.unc.edu */ +PUBLIC int style5(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" ", " o ", " :N:", " <B>", " |R|", " {Q}", " =K="}; + static char *bp[] = {" ", " p ", " :n:", " <b>", " |r|", " {q}", " =k="}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = " . . . . . . . . .\n"; + static char *mid = " . . . . . . . . .\n"; + static char *start = ""; + static char *end = ""; + static char *label = "\t a b c d e f g h\n"; + static char *blabel = "\t h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Email Board suggested by Thomas Fought (tlf@rsch.oclc.org) */ +PUBLIC int style6(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" |", " wp |", " WN |", " WB |", " WR |", " WQ |", " WK |"}; + static char *bp[] = {" |", " bp |", " BN |", " BB |", " BR |", " BQ |", " BK |"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = "\t-----------------------------------------\n"; + static char *mid = "\t-----------------------------------------\n"; + static char *start = "|"; + static char *end = ""; + static char *label = "\t A B C D E F G H\n"; + static char *blabel = "\t H G F E D C B A\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* Miniature board */ +PUBLIC int style7(game_state_t *b, move_t *ml) +{ + static char *wp[] = {" ", " P", " N", " B", " R", " Q", " K"}; + static char *bp[] = {" -", " p", " n", " b", " r", " q", " k"}; + static char *wsqr = ""; + static char *bsqr = ""; + static char *top = "\t:::::::::::::::::::::\n"; + static char *mid = ""; + static char *start = ".."; + static char *end = " .."; + static char *label = "\t a b c d e f g h\n"; + static char *blabel = "\t h g f e d c b a\n"; + + return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel); +} + +/* ICS interface maker board-- raw data dump */ +PUBLIC int style8(game_state_t *b, move_t *ml) +{ + char tmp[80]; + int f, r; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum + 1, + garray[b->gameNum].white_name, + (orient == WHITE) ? "*" : ":", + garray[b->gameNum].black_name, + (orient == WHITE) ? ":" : "*"); + strcat(bstring, tmp); + for (r = 0; r < 8; r++) { + for (f = 0; f < 8; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, " "); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + } + sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n", + garray[b->gameNum].numHalfMoves / 2 + 1, + (b->onMove == WHITE) ? "W" : "B", + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + garray[b->gameNum].numHalfMoves ? + ml[garray[b->gameNum].numHalfMoves - 1].algString : + "none", + garray[b->gameNum].numHalfMoves ? + tenth_str(ml[garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00"); + strcat(bstring, tmp); + return 0; +} + +/* last 2 moves only (previous non-verbose mode) */ +PUBLIC int style9(game_state_t *b, move_t *ml) +{ + int i, count; + char tmp[80]; + int startmove; + + sprintf(tmp, "\nMove %-23s%s\n", + garray[b->gameNum].white_name, + garray[b->gameNum].black_name); + strcat(bstring, tmp); + sprintf(tmp, "---- -------------- --------------\n"); + strcat(bstring, tmp); + startmove = ((garray[b->gameNum].numHalfMoves - 3) / 2) * 2; + if (startmove < 0) + startmove = 0; + for (i = startmove, count = 0; + i < garray[b->gameNum].numHalfMoves && count < 4; + i++, count++) { + if (!(i & 0x01)) { + sprintf(tmp, " %2d ", i / 2 + 1); + strcat(bstring, tmp); + } + sprintf(tmp, "%-23s", move_and_time(&ml[i])); + strcat(bstring, tmp); + if (i & 0x01) + strcat(bstring, "\n"); + } + if (i & 0x01) + strcat(bstring, "\n"); + return 0; +} + +/* Sleator's 'new and improved' raw dump format... */ +PUBLIC int style10(game_state_t *b, move_t *ml) +{ + int f, r; + char tmp[80]; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(tmp, "<10>\n"); + strcat(bstring, tmp); + for (r = 7; r >= 0; r--) { + strcat(bstring, "|"); + for (f = 0; f < 8; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, " "); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + strcat(bstring, "|\n"); + } + strcat(bstring, (b->onMove == WHITE) ? "W " : "B "); + if (garray[b->gameNum].numHalfMoves) { + sprintf(tmp, "%d ", + ml[garray[b->gameNum].numHalfMoves - 1].doublePawn); + } else { + sprintf(tmp, "-1 "); + } + strcat(bstring, tmp); + sprintf(tmp, "%d %d %d %d %d\n", + !(b->wkmoved || b->wkrmoved), + !(b->wkmoved || b->wqrmoved), + !(b->bkmoved || b->bkrmoved), + !(b->bkmoved || b->bqrmoved), + (garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 : + b->lastIrreversable))); + strcat(bstring, tmp); + sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d\n", + b->gameNum, + garray[b->gameNum].white_name, + garray[b->gameNum].black_name, + myTurn, + garray[b->gameNum].wInitTime / 600, + garray[b->gameNum].wIncrement / 10, + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + garray[b->gameNum].numHalfMoves / 2 + 1, + garray[b->gameNum].numHalfMoves ? + ml[garray[b->gameNum].numHalfMoves - 1].moveString : + "none", + garray[b->gameNum].numHalfMoves ? + tenth_str(ml[garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00", + garray[b->gameNum].numHalfMoves ? + ml[garray[b->gameNum].numHalfMoves - 1].algString : + "none", + (orient == WHITE) ? 0 : 1); + strcat(bstring, tmp); + sprintf(tmp, ">10<\n"); + strcat(bstring, tmp); + return 0; +} + +/* Same as 8, but with verbose moves ("P/e3-e4", instead of "e4") */ +PUBLIC int style11(game_state_t *b, move_t *ml) +{ + char tmp[80]; + int f, r; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum, + garray[b->gameNum].white_name, + (orient == WHITE) ? "*" : ":", + garray[b->gameNum].black_name, + (orient == WHITE) ? ":" : "*"); + strcat(bstring, tmp); + for (r = 0; r < 8; r++) { + for (f = 0; f < 8; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, " "); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + } + sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n", + garray[b->gameNum].numHalfMoves / 2 + 1, + (b->onMove == WHITE) ? "W" : "B", + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + garray[b->gameNum].numHalfMoves ? + ml[garray[b->gameNum].numHalfMoves - 1].moveString : + "none", + garray[b->gameNum].numHalfMoves ? + tenth_str(ml[garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00"); + strcat(bstring, tmp); + return 0; +} + +/* Similar to style 10. See the "style12" help file for information */ +PUBLIC int style12(game_state_t *b, move_t *ml) +{ + int f, r; + char tmp[80]; + int ws, bs; + + board_calc_strength(b, &ws, &bs); + sprintf(bstring, "<12> "); + for (r = 7; r >= 0; r--) { + for (f = 0; f < 8; f++) { + if (b->board[f][r] == NOPIECE) { + strcat(bstring, "-"); + } else { + if (colorval(b->board[f][r]) == WHITE) + strcat(bstring, wpstring[piecetype(b->board[f][r])]); + else + strcat(bstring, bpstring[piecetype(b->board[f][r])]); + } + } + strcat(bstring, " "); + } + strcat(bstring, (b->onMove == WHITE) ? "W " : "B "); + if (garray[b->gameNum].numHalfMoves) { + sprintf(tmp, "%d ", + ml[garray[b->gameNum].numHalfMoves - 1].doublePawn); + } else { + sprintf(tmp, "-1 "); + } + strcat(bstring, tmp); + sprintf(tmp, "%d %d %d %d %d ", + !(b->wkmoved || b->wkrmoved), + !(b->wkmoved || b->wqrmoved), + !(b->bkmoved || b->bkrmoved), + !(b->bkmoved || b->bqrmoved), + (garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 : b->lastIrreversable))); + strcat(bstring, tmp); + sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d\n", + b->gameNum + 1, + garray[b->gameNum].white_name, + garray[b->gameNum].black_name, + myTurn, + garray[b->gameNum].wInitTime / 600, + garray[b->gameNum].wIncrement / 10, + ws, + bs, + (wTime + 5) / 10, + (bTime + 5) / 10, + garray[b->gameNum].numHalfMoves / 2 + 1, + garray[b->gameNum].numHalfMoves ? + ml[garray[b->gameNum].numHalfMoves - 1].moveString : + "none", + garray[b->gameNum].numHalfMoves ? + tenth_str(ml[garray[b->gameNum].numHalfMoves - 1].tookTime, 0) : + "0:00", + garray[b->gameNum].numHalfMoves ? + ml[garray[b->gameNum].numHalfMoves - 1].algString : + "none", (orient == WHITE) ? 0 : 1); + + strcat(bstring, tmp); + return 0; +} + +PUBLIC int board_read_file(char *category, char *gname, game_state_t *gs) +{ + int f, r; + FILE *fp; + char fname[MAX_FILENAME_SIZE + 1]; + int c; + int onNewLine = 1; + int onColor = -1; + int onPiece = -1; + int onFile = -1; + int onRank = -1; + + sprintf(fname, "%s/%s/%s", board_dir, category, gname); + fp = fopen(fname, "r"); + if (!fp) + return 1; + + for (f = 0; f < 8; f++) + for (r = 0; r < 8; r++) + gs->board[f][r] = NOPIECE; + for (f = 0; f < 2; f++) { + for (r = 0; r < 8; r++) + gs->ep_possible[f][r] = 0; + for (r = PAWN; r <= QUEEN; r++) + gs->holding[f][r-1] = 0; + } + gs->wkmoved = gs->wqrmoved = gs->wkrmoved = 0; + gs->bkmoved = gs->bqrmoved = gs->bkrmoved = 0; + gs->onMove = -1; + gs->moveNum = 1; + gs->lastIrreversable = -1; + while (!feof(fp)) { + c = fgetc(fp); + if (onNewLine) { + if (c == 'W') { + onColor = WHITE; + if (gs->onMove < 0) + gs->onMove = WHITE; + } else if (c == 'B') { + onColor = BLACK; + if (gs->onMove < 0) + gs->onMove = BLACK; + } else if (c == '#') { + while (!feof(fp) && c != '\n') + c = fgetc(fp); /* Comment line */ + continue; + } else { /* Skip any line we don't understand */ + while (!feof(fp) && c != '\n') + c = fgetc(fp); + continue; + } + onNewLine = 0; + } else { + switch (c) { + case 'P': + onPiece = PAWN; + break; + case 'R': + onPiece = ROOK; + break; + case 'N': + onPiece = KNIGHT; + break; + case 'B': + onPiece = BISHOP; + break; + case 'Q': + onPiece = QUEEN; + break; + case 'K': + onPiece = KING; + break; + case 'a': + case 'b': + case 'c': + case 'd': + case 'e': + case 'f': + case 'g': + case 'h': + onFile = c - 'a'; + onRank = -1; + break; + case '1': + case '2': + case '3': + case '4': + case '5': + case '6': + case '7': + case '8': + onRank = c - '1'; + if (onFile >= 0 && onColor >= 0 && onPiece >= 0) + gs->board[onFile][onRank] = onPiece | onColor; + break; + case '#': + while (!feof(fp) && c != '\n') + c = fgetc(fp); /* Comment line */ + case '\n': + onNewLine = 1; + onColor = -1; + onPiece = -1; + onFile = -1; + onRank = -1; + break; + default: + break; + } + } + } + fclose(fp); + return 0; +} + +#define WHITE_SQUARE 1 +#define BLACK_SQUARE 0 +#define ANY_SQUARE -1 +#define SquareColor(f, r) ((f ^ r) & 1) + +PRIVATE void place_piece(board_t b, int piece, int squareColor) +{ + int r, f; + int placed = 0; + + if (iscolor(piece, BLACK)) + r = 7; + else + r = 0; + + while (!placed) { + if (squareColor == ANY_SQUARE) { + f = rand() % 8; + } else { + f = (rand() % 4) * 2; + if (SquareColor(f, r) != squareColor) + f++; + } + if ((b)[f][r] == NOPIECE) { + (b)[f][r] = piece; + placed = 1; + } + } +} + +PUBLIC void wild_update(int style) +{ + int f, r, i; + board_t b; + + for (f = 0; f < 8; f++) + for (r = 0; r < 8; r++) + b[f][r] = NOPIECE; + for (f = 0; f < 8; f++) { + b[f][1] = W_PAWN; + b[f][6] = B_PAWN; + } + switch (style) { + case 1: + if (rand() & 0x01) { + b[4][0] = W_KING; + b[3][0] = W_QUEEN; + } else { + b[3][0] = W_KING; + b[4][0] = W_QUEEN; + } + if (rand() & 0x01) { + b[4][7] = B_KING; + b[3][7] = B_QUEEN; + } else { + b[3][7] = B_KING; + b[4][7] = B_QUEEN; + } + b[0][0] = b[7][0] = W_ROOK; + b[0][7] = b[7][7] = B_ROOK; + /* Must do bishops before knights to be sure opposite colored squares are + available. */ + place_piece(b, W_BISHOP, WHITE_SQUARE); + place_piece(b, W_BISHOP, BLACK_SQUARE); + place_piece(b, W_KNIGHT, ANY_SQUARE); + place_piece(b, W_KNIGHT, ANY_SQUARE); + place_piece(b, B_BISHOP, WHITE_SQUARE); + place_piece(b, B_BISHOP, BLACK_SQUARE); + place_piece(b, B_KNIGHT, ANY_SQUARE); + place_piece(b, B_KNIGHT, ANY_SQUARE); + break; + case 2: + place_piece(b, W_KING, ANY_SQUARE); + place_piece(b, W_QUEEN, ANY_SQUARE); + place_piece(b, W_ROOK, ANY_SQUARE); + place_piece(b, W_ROOK, ANY_SQUARE); + place_piece(b, W_BISHOP, ANY_SQUARE); + place_piece(b, W_BISHOP, ANY_SQUARE); + place_piece(b, W_KNIGHT, ANY_SQUARE); + place_piece(b, W_KNIGHT, ANY_SQUARE); + /* Black mirrors White */ + for (i = 0; i < 8; i++) { + b[i][7] = b[i][0] | BLACK; + } + break; + case 3: + /* Generate White king on random square plus random set of pieces */ + place_piece(b, W_KING, ANY_SQUARE); + for (i = 0; i < 8; i++) { + if (b[i][0] != W_KING) { + b[i][0] = (rand() % 4) + 2; + } + } + /* Black mirrors White */ + for (i = 0; i < 8; i++) { + b[i][7] = b[i][0] | BLACK; + } + break; + case 4: + /* Generate White king on random square plus random set of pieces */ + place_piece(b, W_KING, ANY_SQUARE); + for (i = 0; i < 8; i++) { + if (b[i][0] != W_KING) { + b[i][0] = (rand() % 4) + 2; + } + } + /* Black has same set of pieces, but randomly permuted, except that Black + must have the same number of bishops on white squares as White has on + black squares, and vice versa. So we must place Black's bishops first + to be sure there are enough squares left of the correct color. */ + for (i = 0; i < 8; i++) { + if (b[i][0] == W_BISHOP) { + place_piece(b, B_BISHOP, !SquareColor(i, 0)); + } + } + for (i = 0; i < 8; i++) { + if (b[i][0] != W_BISHOP) { + place_piece(b, b[i][0] | BLACK, ANY_SQUARE); + } + } + break; + default: + return; + break; + } + { + FILE *fp; + char fname[MAX_FILENAME_SIZE + 1]; + int onPiece; + + sprintf(fname, "%s/wild/%d", board_dir, style); + fp = fopen(fname, "w"); + if (!fp) { + fprintf(stderr, "FICS: Can't write file name %s\n", fname); + return; + } + fprintf(fp, "W:"); + onPiece = -1; + for (r = 1; r >= 0; r--) { + for (f = 0; f < 8; f++) { + if (onPiece < 0 || b[f][r] != onPiece) { + onPiece = b[f][r]; + fprintf(fp, " %s", wpstring[piecetype(b[f][r])]); + } + fprintf(fp, " %c%c", f + 'a', r + '1'); + } + } + fprintf(fp, "\nB:"); + onPiece = -1; + for (r = 6; r < 8; r++) { + for (f = 0; f < 8; f++) { + if (onPiece < 0 || b[f][r] != onPiece) { + onPiece = b[f][r]; + fprintf(fp, " %s", wpstring[piecetype(b[f][r])]); + } + fprintf(fp, " %c%c", f + 'a', r + '1'); + } + } + fprintf(fp, "\n"); + fclose(fp); + } +} + +PUBLIC void wild_init() +{ + wild_update(1); + wild_update(2); + wild_update(3); + wild_update(4); +} |