+++ /dev/null
-lasker/data/boards/wild
install -d -m0755 ${CHESSDDIR}/data/messages
install -d -m0755 ${CHESSDDIR}/data/stats
install -d -m0755 ${CHESSDDIR}/data/boards/wild
+ install -d -m0755 ${CHESSDDIR}/data/boards/capablanca
+ install -d -m0755 ${CHESSDDIR}/data/boards/knightmate
+ install -d -m0755 ${CHESSDDIR}/data/boards/gothic
+ install -d -m0755 ${CHESSDDIR}/data/boards/super
+ install -d -m0755 ${CHESSDDIR}/data/boards/crazyhouse
+ install -d -m0755 ${CHESSDDIR}/data/boards/fischerandom
+ install -d -m0755 ${CHESSDDIR}/data/boards/fr
+ install -d -m0755 ${CHESSDDIR}/data/boards/zh
+ install -d -m0755 ${CHESSDDIR}/data/boards/shatranj
+ install -d -m0755 ${CHESSDDIR}/data/boards/xiangqi
+ install -d -m0755 ${CHESSDDIR}/data/boards/shogi
+ install -d -m0755 ${CHESSDDIR}/data/boards/caparandom
+ install -d -m0755 ${CHESSDDIR}/data/boards/courier
+ install -d -m0755 ${CHESSDDIR}/data/boards/fairy
+ install -d -m0755 ${CHESSDDIR}/data/boards/great
install -d -m0755 ${CHESSDDIR}/games/history
install -d -m0755 ${CHESSDDIR}/games/journal
install -d -m0755 ${CHESSDDIR}/games/adjourned
cp -u ${srcdir}/../data/help/[a-z]* ${CHESSDDIR}/data/help
cp -u ${srcdir}/../data/usage/[a-z]* ${CHESSDDIR}/data/usage
cp -u ${srcdir}/../data/messages/[a-z]* ${CHESSDDIR}/data/messages
+ cp -u ${srcdir}/../data/boards/capablanca/* ${CHESSDDIR}/data/boards/capablanca
+ cp -u ${srcdir}/../data/boards/gothic/* ${CHESSDDIR}/data/boards/gothic
+ cp -u ${srcdir}/../data/boards/knightmate/* ${CHESSDDIR}/data/boards/knightmate
+ cp -u ${srcdir}/../data/boards/fischerandom/* ${CHESSDDIR}/data/boards/fischerandom
+ cp -u ${srcdir}/../data/boards/shatranj/* ${CHESSDDIR}/data/boards/shatranj
+ cp -u ${srcdir}/../data/boards/crazyhouse/* ${CHESSDDIR}/data/boards/crazyhouse
+ cp -u ${srcdir}/../data/boards/super/* ${CHESSDDIR}/data/boards/super
+ cp -u ${srcdir}/../data/boards/wild/* ${CHESSDDIR}/data/boards/wild
+ cp -u ${srcdir}/../data/boards/xiangqi/* ${CHESSDDIR}/data/boards/xiangqi
+ cp -u ${srcdir}/../data/boards/shogi/* ${CHESSDDIR}/data/boards/shogi
+ cp -u ${srcdir}/../data/boards/courier/* ${CHESSDDIR}/data/boards/courier
+ cp -u ${srcdir}/../data/boards/fairy/* ${CHESSDDIR}/data/boards/fairy
+ cp -u ${srcdir}/../data/boards/great/* ${CHESSDDIR}/data/boards/great
+ cp -u ${srcdir}/../data/boards/caparandom/* ${CHESSDDIR}/data/boards/caparandom
perl -e 'mkdir("${CHESSDDIR}/players/$$_",0755) for ("a".."z")'
perl -e 'mkdir("${CHESSDDIR}/games/history/$$_",0755) for ("0".."99")'
perl -e 'mkdir("${CHESSDDIR}/games/journal/$$_",0755) for ("a".."z")'
for (j = len - 1; j >= 0; j--) {
switch (alg_list[i][j]) {
case 'f':
- if ((tmp[j] < 'a') || (tmp[j] > 'h'))
+ if ((tmp[j] < 'a') || (tmp[j] > 'l')) // [HGM] upto l-file
goto nomatch;
if (ltf == ALG_UNKNOWN)
ltf = tmp[j] - 'a';
lff = tmp[j] - 'a';
break;
case 'r':
- if ((tmp[j] < '1') || (tmp[j] > '8'))
+ if ((tmp[j] < '0') || (tmp[j] > '9')) // [HGM] also match 0- and 9-rank
goto nomatch;
- if (ltr == ALG_UNKNOWN)
- ltr = tmp[j] - '1';
- else
- lfr = tmp[j] - '1';
+ if (ltr == ALG_UNKNOWN)\r
+ ltr = tmp[j] - '0'; // [HGM] allow 0-rank for Xiangqi, correct later\r
+ else\r
+ lfr = tmp[j] - '0';
break;
case 'p':
if (isupper(tmp[j]))
c = tmp[j];
if (c == 'k')
lpiece = KING;
+ else if (c == 'e') // [HGM] note that som piece indicators are ambiguous,
+ lpiece = ELEPHANT; // and their true meaning depends on the variant,
+ else if (c == 'v') // which we do not know at this point.
+ lpiece = CENTAUR;
+ else if (c == 's')
+ lpiece = SILVER;
+ else if (c == 'g')
+ lpiece = GOLD;
+ else if (c == 'l')
+ lpiece = LANCE;
+ else if (c == 'f')
+ lpiece = FERZ;
+ else if (c == 'h')
+ lpiece = HORSE;
+ else if (c == 'w')
+ lpiece = WAZIR;
+ else if (c == 'o')
+ lpiece = SQUIRREL;
else if (c == 'q')
lpiece = QUEEN;
+ else if (c == 'c')
+ lpiece = MARSHALL;
+ else if (c == 'a')
+ lpiece = CARDINAL;
+ else if (c == 'm')
+ lpiece = MAN;
else if (c == 'r')
lpiece = ROOK;
else if (c == 'b')
static void add_promotion(struct game_state_t *gs, const char *mstr, struct move_t * mt)
{
char *s;
- int piece;
+ int piece, i;
s = strchr(mstr, '=');
if (s == NULL) {
return;
if (piecetype(gs->board[mt->fromFile][mt->fromRank]) != PAWN) {
return;
}
- if (mt->toRank != 7 && mt->toRank != 0) {
+ if (mt->toRank != gs->ranks-1 && mt->toRank != 0) {
return;
}
switch (tolower(s[1])) {
+ case 'f':
+ piece = FERZ2;
+ break;
case 'q':
piece = QUEEN;
break;
+ case 'c':\r
+ if(!gs->capablancaPieces) return; // [HGM] should make variant-dependent piece mask\r
+ piece = MARSHALL;\r
+ break;\r
+ case 'a':\r
+ if(!gs->capablancaPieces) return;\r
+ piece = CARDINAL;\r
+ break;\r
+ case 'm':\r
+ if(!gs->royalKnight) return; // [HGM] only in knightmate\r
+ piece = MAN;\r
+ break;\r
case 'r':
piece = ROOK;
break;
piece = BISHOP;
break;
case 'n':
+ if(gs->royalKnight) return; // [HGM] not in knightmate\r
piece = KNIGHT;
break;
+ // Superchess promotons: filtered out later by promoType
+ case 'g':
+ piece = MASTODON;
+ break;
+ case 'o':
+ piece = SQUIRREL;
+ break;
+ case 'w':
+ piece = WOODY;
+ break;
+ case 'v':
+ piece = CENTAUR;
+ break;
+ case 'e':\r
+ piece = EMPRESS;
+ break;
+ case 's':
+ piece = PRINCESS;
+ break;
default:
return;
}
+ i = colorval(gs->board[mt->fromFile][mt->fromRank]) == WHITE ? 0 : 1;
+ if(piece >= WOODY && (gs->promoType != 2 || gs->holding[i][piece-1] == 0)) return;
+
mt->piecePromotionTo = piece | colorval(gs->board[mt->fromFile][mt->fromRank]);
}
d_printf( "CHESSD: Shouldn't try to algebraicly parse non-algabraic move string.\n");
return MOVE_ILLEGAL;
}
+ \r
+ // [HGM] check if move does not stray off board\r
+ if(gs->ranks < 10) { \r
+ if(tr == 0 || fr == 0) return MOVE_ILLEGAL; // used nonexistent 0-rank\r
+ if(tr != ALG_UNKNOWN) tr--; if(fr != ALG_UNKNOWN) fr--; // shift to lowest rank = 1\r
+ }\r
+ if(tr >= gs->ranks || fr >= gs->ranks || tf >= gs->files || ff >= gs->files)\r
+ return MOVE_ILLEGAL;\r
+
+ // [HGM] resolve ambiguity in piece, type based on variant
+ switch(piece) {
+ case ELEPHANT:
+ if(strstr(gs->variant, "super")) piece = EMPRESS; else
+ if(strstr(gs->variant, "great")) piece = MODERNELEPHANT; else
+ if(strstr(gs->variant, "courier")) piece = ALFIL2;
+ break;
+ case CARDINAL:
+ if(strstr(gs->variant, "super")) piece = AMAZON; else
+ if(strstr(gs->variant, "xiangqi")) piece = MANDARIN;
+ break;
+ case MARSHALL:
+ if(strstr(gs->variant, "xiangqi")) piece = CANNON;
+ break;
+ case SILVER:
+ if(strstr(gs->variant, "super")) piece = PRINCESS;
+ if(strstr(gs->variant, "great")) piece = MAN2;
+ break;
+ case BISHOP:
+ if(strstr(gs->variant, "shatranj")) piece = ALFIL;
+ break;
+ case QUEEN:
+ if(strstr(gs->variant, "shatranj")) piece = FERZ;
+ break;
+ case WAZIR:
+ if(strstr(gs->variant, "super")) piece = WOODY;
+ break;
+ case KNIGHT:
+ if(strstr(gs->variant, "shogi")) piece = HONORABLEHORSE;
+ break;
+ case MAN:
+ if(strstr(gs->variant, "great")) piece = MINISTER;
+ break;
+ case HORSE:
+ if(strstr(gs->variant, "great")) piece = PRIESTESS;
+ break;
+ case GOLD:
+ if(strstr(gs->variant, "great")) piece = MASTODON;
+ break;
+ }
+\r
/* Resolve ambiguities in to-ness */
if (tf == ALG_UNKNOWN) {
d_printf("Ambiguous %s(%d)\n", __FUNCTION__, __LINE__);
}
/* Need to find pawn on ff that can take to tf and fill in ranks */
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
if ((ff != ALG_UNKNOWN) && (ff != f))
continue;
if (piecetype(gs->board[f][r]) != piece)
ff = ALG_UNKNOWN;
fr = ALG_UNKNOWN;
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
- if ((piecetype(gs->board[f][r]) != PAWN) && (piecetype(gs->board[f][r]) != BISHOP)) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
+ if ((piecetype(gs->board[f][r]) != PAWN) && (piecetype(gs->board[f][r]) != piece)) {
+ // note that the interpretation Bxc4 is matched last, and has set piece to BISHOP
continue;
}
+
if (legal_andcheck_move(gs, f, r, tf, tr)) {
- if ((piecetype(gs->board[f][r]) == PAWN) && (f != 1)) {
+ if ((piecetype(gs->board[f][r]) == PAWN) && (f != tolower(mstr[0]) - 'a')) {
continue;
}
/* if its a lowercase 'b' then prefer the pawn move if there is one */
if ((ff != ALG_UNKNOWN) && (fr != ALG_UNKNOWN) &&
- piecetype(gs->board[f][r]) == PAWN && mstr[0] == 'b') {
+ piecetype(gs->board[f][r]) == PAWN && mstr[0] >= 'a') {
ff = f;
fr = r;
continue;
}
if ((ff != ALG_UNKNOWN) && (fr != ALG_UNKNOWN) &&
- piecetype(gs->board[ff][fr]) == PAWN && mstr[0] == 'b') {
+ piecetype(gs->board[ff][fr]) == PAWN && mstr[0] >= 'a') {
continue;
}
if ((ff == ALG_UNKNOWN) || (fr == ALG_UNKNOWN)) {
/* Need to find a piece that can go to tf, tr */
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
if ((ff != ALG_UNKNOWN) && (ff != f))
continue;
if ((fr != ALG_UNKNOWN) && (fr != r))
piece = piecetype(gs->board[mt->fromFile][mt->fromRank]);
}
- if ((piece == KING) && ((mt->fromFile == 4) && (mt->toFile == 6))) {
- strcpy(mStr, "O-O");
- goto check;
- }
- if ((piece == KING) && ((mt->fromFile == 4) && (mt->toFile == 2))) {
- strcpy(mStr, "O-O-O");
- goto check;
- }
+ if ((mt->fromFile == ALG_CASTLE) && (mt->toFile > mt->toRank)) { // [HGM] castle: K ends right of R\r
+ strcpy(mStr, "O-O");\r
+ goto check;\r
+ }\r
+ if ((mt->fromFile == ALG_CASTLE) && (mt->toFile < mt->toRank)) { // [HGM] castle: K ends left of R\r
+ strcpy(mStr, "O-O-O");\r
+ goto check;\r
+ }\r
strcpy(mStr, "");
switch (piece) {
case PAWN:
if (mt->fromFile == ALG_DROP) {
strcpy(mStr,"P");
- } else if (mt->fromFile != mt->toFile) {
+ } else if (mt->fromFile != mt->toFile
+ || gs->board[mt->toFile][mt->toRank] != NOPIECE) { // [HGM] XQ: forward captures as "axa6"
sprintf(tmp, "%c", mt->fromFile + 'a');
strcpy(mStr, tmp);
}
case ROOK:
strcpy(mStr, "R");
break;
+ case ALFIL2:
+ case AMAZON:
+ case CARDINAL:\r
+ strcpy(mStr, "A");\r
+ break;\r
+ case CANNON:
+ case MARSHALL:\r
+ strcpy(mStr, "C");\r
+ break;\r
+ case MAN:\r
+ strcpy(mStr, "M");\r
+ break;\r
+ case FERZ:
case QUEEN:
strcpy(mStr, "Q");
break;
+ case EMPRESS:
+ case ELEPHANT:
+ strcpy(mStr, "E");
+ break;
+ case ALFIL:
+ strcpy(mStr, "B");
+ break;
+ case FERZ2:
+ strcpy(mStr, "F");
+ break;
+ case WOODY:
+ case WAZIR:
+ strcpy(mStr, "W");
+ break;
+ case SQUIRREL:
+ strcpy(mStr, "O");
+ break;
+ case CENTAUR:
+ strcpy(mStr, "V");
+ break;
+ case HORSE:
+ strcpy(mStr, "H");
+ break;
+ case HONORABLEHORSE:
+ strcpy(mStr, "N");
+ break;
+ case DRAGONKING:
+ strcpy(mStr, "J");
+ break;
+ case DRAGONHORSE:
+ strcpy(mStr, "I");
+ break;
+ case LANCE:
+ strcpy(mStr, "L");
+ break;
+ case PRINCESS:
+ case SILVER:
+ strcpy(mStr, "S");
+ break;
+ case MASTODON:
+ case GOLD:
+ strcpy(mStr, "G");
+ break;
+ case MANDARIN:
+ strcpy(mStr, "A");
+ break;
case KING:
strcpy(mStr, "K");
break;
/* Checks for ambiguity in short notation ( Ncb3, R8e8 or so) */
if (piece != PAWN) {
ambig = r_ambig = f_ambig = 0;
- for (r = 0; r < 8; r++)
- for (f = 0; f < 8; f++) {
+ for (r = 0; r < gs->ranks; r++)\r
+ for (f = 0; f < gs->files; f++) {\r
if ((gs->board[f][r] != NOPIECE) && iscolor(gs->board[f][r], gs->onMove)
&& (piecetype(gs->board[f][r]) == piece) &&
((f != mt->fromFile) || (r != mt->fromRank))) {
}
}
}
- if (ambig > 0) {
- /* Ambiguity in short notation, need to add file,rank or _both_ in
- notation */
- if (f_ambig == 0) {
- sprintf(tmp, "%c", mt->fromFile + 'a');
- strcat(mStr, tmp);
- } else if (r_ambig == 0) {
- sprintf(tmp, "%d", mt->fromRank + 1);
- strcat(mStr, tmp);
- } else {
- sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1);
- strcat(mStr, tmp);
- }
- }
- }
- if ((gs->board[mt->toFile][mt->toRank] != NOPIECE) ||
- ((piece == PAWN) && (mt->fromFile != mt->toFile))) {
- strcat(mStr, "x");
- }
- }
- sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1);
- strcat(mStr, tmp);
-
- if ((piece == PAWN) && (mt->piecePromotionTo != NOPIECE)) {
- strcat(mStr, "="); /* = before promoting piece */
- switch (piecetype(mt->piecePromotionTo)) {
- case KNIGHT:
- strcat(mStr, "N");
- break;
- case BISHOP:
- strcat(mStr, "B");
- break;
- case ROOK:
- strcat(mStr, "R");
- break;
- case QUEEN:
- strcat(mStr, "Q");
- break;
- default:
- break;
- }
- }
+ if (ambig > 0) {\r
+ /* Ambiguity in short notation, need to add file,rank or _both_ in\r
+ notation */\r
+ if (f_ambig == 0) {\r
+ sprintf(tmp, "%c", mt->fromFile + 'a');\r
+ strcat(mStr, tmp);\r
+ } else if (r_ambig == 0) {\r
+ sprintf(tmp, "%d", mt->fromRank + 1 - (gs->ranks > 9));\r
+ strcat(mStr, tmp);\r
+ } else {\r
+ sprintf(tmp, "%c%d", mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks > 9));\r
+ strcat(mStr, tmp);\r
+ }\r
+ }\r
+ }\r
+ if ((gs->board[mt->toFile][mt->toRank] != NOPIECE) ||\r
+ ((piece == PAWN) && (mt->fromFile != mt->toFile))) {\r
+ strcat(mStr, "x");\r
+ }\r
+ }\r
+ sprintf(tmp, "%c%d", mt->toFile + 'a', mt->toRank + 1 - (gs->ranks > 9));\r
+ strcat(mStr, tmp);\r
+\r
+ if ((piece == PAWN) && (mt->piecePromotionTo != NOPIECE)) {\r
+ strcat(mStr, "="); /* = before promoting piece */\r
+ switch (piecetype(mt->piecePromotionTo)) {\r
+ case KNIGHT:\r
+ strcat(mStr, "N");\r
+ break;\r
+ case BISHOP:\r
+ strcat(mStr, "B");\r
+ break;\r
+ case ROOK:\r
+ strcat(mStr, "R");\r
+ break;\r
+ case CARDINAL:\r
+ strcat(mStr, "A");\r
+ break;\r
+ case MARSHALL:\r
+ strcat(mStr, "C");\r
+ break;\r
+ case MAN:\r
+ strcat(mStr, "M");\r
+ break;\r
+ case QUEEN:\r
+ strcat(mStr, "Q");\r
+ break;\r
+ case FERZ2:\r
+ strcat(mStr, "F");\r
+ break;\r
+ case WOODY:\r
+ strcat(mStr, "W");\r
+ break;\r
+ case EMPRESS:\r
+ strcat(mStr, "E");\r
+ break;\r
+ case CENTAUR:\r
+ strcat(mStr, "V");\r
+ break;\r
+ case PRINCESS:\r
+ strcat(mStr, "S");\r
+ break;\r
+ case SQUIRREL:\r
+ strcat(mStr, "O");\r
+ break;\r
+ case MASTODON:\r
+ strcat(mStr, "G");\r
+ break;\r
+ default:\r
+ break;\r
+ }\r
+ }\r
check:;
fakeMove = *gs;
execute_move(&fakeMove, mt, 0);
#include "includes.h"
-const char *wpstring[] = {" ", "P", "N", "B", "R", "Q", "K"};
-static const char *bpstring[] = {" ", "p", "n", "b", "r", "q", "k"};
+const char *wpstring[] = {" ", "P", "N", "B", "R", "A", "C", "M", "Q", "E", "B", "Q", "W", "H", "N", "J", "I", "L",
+ "C", "S", "G", "H", "A", "F", "E", "H", "M", "S", "E", "W", "O", "G", "V", "S", "E", "A", "K"};
+const char *bpstring[] = {" ", "p", "n", "b", "r", "a", "c", "m", "q", "e", "b", "q", "w", "h", "n", "j", "i", "l",
+ "c", "s", "g", "h", "a", "f", "e", "h", "m", "s", "e", "w", "o", "g", "v", "s", "e", "a", "k"};
-static int pieceValues[7] = {0, 1, 3, 3, 5, 9, 0};
+int pieceValues[KING+1] = {0, 1, 3, 3, 5, 8, 9, 3, 9, 1, 1, 2, 2, 2, 1, 6, 5, 2, 3, 3, 3, 1, 5, 2, 1, 7, 7, 3, 3, 3, 7, 7, 7, 8, 9, 12, 0};
static const int mach_type = (1<<7) | (1<<8) | (1<<9) | (1<<10) | (1<<11);
#define IsMachineStyle(n) (((1<<(n)) & mach_type) != 0)
-static char bstring[MAX_BOARD_STRING_LEGTH];
+static char bstring[MAX_BOARD_STRING_LENGTH];
static int board_read_file(char *category, char *gname, struct game_state_t *gs);
-static void wild_update(int style);
+static void wild_update(board_t b, int style);
static int style1(struct game_state_t *b, struct move_t *ml);
static int style2(struct game_state_t *b, struct move_t *ml);
{
int f,r;
+ if(gs->files <= 0) gs->files = 8; // [HGM] for pristine board, set default size
+ if(gs->ranks <= 0) gs->ranks = 8;
for (f = 0; f < 2; f++) {
- for (r = 0; r < 8; r++)
+ for (r = 0; r < BW; r++)
gs->ep_possible[f][r] = 0;
- for (r = PAWN; r <= QUEEN; r++)
+ for (r = PAWN; r <= KING-1; r++)
gs->holding[f][r-PAWN] = 0;
}
- gs->wkmoved = gs->wqrmoved = gs->wkrmoved = 0;
- gs->bkmoved = gs->bqrmoved = gs->bkrmoved = 0;
+ gs->wkmoved = gs->wqrmoved = gs->wkrmoved = -1; // [HGM] castle: no rights
+ gs->bkmoved = gs->bqrmoved = gs->bkrmoved = -1;
gs->onMove = WHITE;
gs->moveNum = 1;
gs->lastIrreversable = -1;
{
int f,r;
- for (f = 0; f < 8; f++)
- for (r = 0; r < 8; r++)
+ for (f = 0; f < BW; f++)
+ for (r = 0; r < BH; r++)
gs->board[f][r] = NOPIECE;
reset_board_vars(gs);
}
{
int f,r;
- for (f = 0; f < 8; f++)
- for (r = 2; r < 6; r++)
- gs->board[f][r] = NOPIECE;
- for (f = 0; f < 8; f++)
- gs->board[f][1] = W_PAWN;
- for (f = 0; f < 8; f++)
- gs->board[f][6] = B_PAWN;
- gs->board[0][0] = W_ROOK;
- gs->board[1][0] = W_KNIGHT;
- gs->board[2][0] = W_BISHOP;
- gs->board[3][0] = W_QUEEN;
- gs->board[4][0] = W_KING;
- gs->board[5][0] = W_BISHOP;
- gs->board[6][0] = W_KNIGHT;
- gs->board[7][0] = W_ROOK;
- gs->board[0][7] = B_ROOK;
- gs->board[1][7] = B_KNIGHT;
- gs->board[2][7] = B_BISHOP;
- gs->board[3][7] = B_QUEEN;
- gs->board[4][7] = B_KING;
- gs->board[5][7] = B_BISHOP;
- gs->board[6][7] = B_KNIGHT;
- gs->board[7][7] = B_ROOK;
+ for (f = 0; f < BW; f++)\r
+ for (r = 0; r < BH; r++)\r
+ gs->board[f][r] = NOPIECE;\r
+ for (f = 0; f < gs->files; f++)\r
+ gs->board[f][gs->ranks-7] = W_PAWN;\r
+ for (f = 0; f < gs->files; f++)\r
+ gs->board[f][6] = B_PAWN;\r
+ gs->board[0][0] = W_ROOK;\r
+ gs->board[1][0] = W_KNIGHT;\r
+ gs->board[2][0] = W_BISHOP; \r
+ gs->board[3][0] = W_QUEEN;\r
+ gs->board[gs->files/2][0] = W_KING;\r
+ gs->board[gs->files-3][0] = W_BISHOP;\r
+ gs->board[gs->files-2][0] = W_KNIGHT;\r
+ gs->board[gs->files-1][0] = W_ROOK;\r
+ gs->board[0][gs->ranks-1] = B_ROOK;\r
+ gs->board[1][gs->ranks-1] = B_KNIGHT;\r
+ gs->board[2][gs->ranks-1] = B_BISHOP;\r
+ gs->board[3][gs->ranks-1] = B_QUEEN;\r
+ gs->board[gs->files/2][gs->ranks-1] = B_KING;\r
+ gs->board[gs->files-3][gs->ranks-1] = B_BISHOP;\r
+ gs->board[gs->files-2][gs->ranks-1] = B_KNIGHT;\r
+ gs->board[gs->files-1][gs->ranks-1] = B_ROOK;\r
+#if 1
+ if(gs->files == 10) {\r
+ gs->board[6][0] = W_CARDINAL;\r
+ gs->board[4][0] = W_MARSHALL;\r
+ gs->board[6][gs->ranks-1] = B_CARDINAL;\r
+ gs->board[4][gs->ranks-1] = B_MARSHALL;\r
+ }\r
+ if(gs->royalKnight) {\r
+ gs->board[1][0] = W_MAN;\r
+ gs->board[gs->files-2][0] = W_MAN;\r
+ gs->board[1][gs->ranks-1] = B_MAN;\r
+ gs->board[gs->files-2][gs->ranks-1] = B_MAN;\r
+ }\r
+#endif
+
reset_board_vars(gs);
+ // [HGM] castle: standard setup has rights for corner Rooks and central King
+ gs->wkmoved = gs->files/2;
+ gs->bkmoved = gs->files/2;
+ gs->wkrmoved = gs->files-1;
+ gs->bkrmoved = gs->files-1;
+ gs->wqrmoved = 0;
+ gs->bqrmoved = 0;
}
int board_init(int g,struct game_state_t *b, char *category, char *board)
{
int retval = 0;
- int wval;
-
- if (!category || !board || !category[0] || !board[0])
- /* accounts for bughouse too */
- board_standard(b);
+ int wval, i, j;
+
+ b->files = b->ranks = 8;\r
+ b->pawnDblStep = (!category || strcmp(category, "shatranj")); \r
+ b->royalKnight = (category && !strcmp(category, "knightmate"));\r
+ b->capablancaPieces = 0;
+ b->holdings = 0;
+ b->drops = 0;
+ b->castlingStyle = 1;
+ b->palace = 0;
+ b->setup = 0;
+ b->bareKingLoses = 0;
+ b->stalemate = 1;
+ b->promoType = 1;
+ b->variant[0] = 0; // [HGM] variant: default is normal, if variant name is missing\r
+ if (!category || !board || !category[0] || !board[0]) \r
+ /* accounts for bughouse too */\r
+ board_standard(b);\r
else {
- if (!strcmp(category, "wild")) {
- if (sscanf(board, "%d", &wval) == 1 && wval >= 1 && wval <= 4)
- wild_update(wval);
+ if(category && category[0]) strcpy(b->variant, category); // [HGM] variant: remember category name\r
+ if (!strcmp(category, "wild") && sscanf(board, "%d", &wval) == 1) {
+ if(wval >= 1 && wval <= 4)\r
+ wild_update(b->board, wval);
+ sprintf(b->variant, "wild/%d", wval);\r
+ }
+
+ if (board && !strcmp(board, "0"))
+ b->setup = 0; // [HGM] variant: any board in the default file "0" is supposed to be implied by the variant\r
+
+ if (!strcmp(category, "knightmate")) {\r
+ board_standard(b);\r
+ } else if (!strcmp(category, "super")) {\r
+ board_standard(b);
+ b->holdings = 1;
+ b->promoType = 2;
+ for(i=CENTAUR; i<=AMAZON; i++) {
+ int placed = 0;
+ do { int p, newp;
+ j = random() % 8;
+ if((p = piecetype(b->board[j][0])) >= CENTAUR) continue; // includes King
+ b->holding[1][p-PAWN] = ++b->holding[0][p-PAWN]; // piece to holding
+ if(board && !strcmp(board, "1")) newp = i - CENTAUR + WOODY; else newp = i;
+ if(board && !strcmp(board, "2")) newp = WOODY + random()%7;
+ b->board[j][0] = newp | WHITE; // place replacements
+ b->board[j][7] = newp | BLACK;
+ placed = 1;
+ } while(!placed);
}
- retval = board_read_file(category, board, b);
+ b->setup = 1;\r
+ } else if (!strcmp(category, "fischerandom")) {\r
+ wild_update(b->board, 22);
+ b->castlingStyle = 2;
+ b->setup = 1; // [HGM] FRC: even the default is a setup position, for which an initial board has to be printed\r
+ } else if (!strcmp(category, "caparandom")) {
+ b->files = 10;\r
+ wild_update(b->board, 46);
+ b->castlingStyle = 2;
+ b->setup = 1; \r
+ } else retval = board_read_file(category, board, b); \r
+ }
+ if(b->setup && game_globals.garray[g].FENstartPos[0]) // [HGM] use pre-existing start position, if one available
+ FEN_to_board(game_globals.garray[g].FENstartPos, b); // (could be wild board, or shuffle variant)
+ if(b->castlingStyle == 1) {
+ b->wkmoved = b->files/2;
+ b->bkmoved = b->files/2;
+ b->wkrmoved = b->files-1;
+ b->bkrmoved = b->files-1;
+ b->wqrmoved = 0;
+ b->bqrmoved = 0;
+ } else if(b->castlingStyle == 2) {
+ for(i=j=0; i < b->files; i++) {
+ int p = b->board[i][0];
+ if(p == W_ROOK || p == W_KING) {
+ switch(j++) {
+ case 0: b->wqrmoved = b->bqrmoved = i; break;
+ case 1: b->wkmoved = b->bkmoved = i; break;
+ case 2: b->wkrmoved = b->bkrmoved = i; break;
+ }
+ }
+ }
}
+\r
MakeFENpos(g, game_globals.garray[g].FENstartPos);
+
return retval;
}
int *p;
*ws = *bs = 0;
- for (f = 0; f < 8; f++) {
- for (r = 0; r < 8; r++) {
+ for (f = 0; f < b->ranks; f++) {
+ for (r = 0; r < b->files; r++) {
if (colorval(b->board[r][f]) == WHITE)
p = ws;
else
*p += pieceValues[piecetype(b->board[r][f])];
}
}
- for (r = PAWN; r <= QUEEN; r++) {
+ for (r = PAWN; r < KING; r++) {
*ws += b->holding[0][r-1] * pieceValues[r];
*bs += b->holding[1][r-1] * pieceValues[r];
}
static char *holding_str(int *holding)
{
- static char tmp[30];
+ static char tmp[80];
int p,i,j;
i = 0;
- for (p = PAWN; p <= QUEEN; p++) {
+ for (p = PAWN; p < KING; p++) {
for (j = 0; j < holding[p-1]; j++) {
tmp[i++] = wpstring[p][0];
}
static char *append_holding_machine(char *buf, int g, int c, int p)
{
struct game_state_t *gs = &game_globals.garray[g].game_state;
- char tmp[50];
+ char tmp[160];
sprintf(tmp, "<b1> game %d white [%s] black [", g+1, holding_str(gs->holding[0]));
strcat(tmp, holding_str(gs->holding[1]));
int c = colorval(pieceCaptured);
struct game_state_t *gs = &game_globals.garray[g].game_state;
int pp, pl;
- char tmp1[80], tmp2[80];
+ char tmp1[160], tmp2[160];
if (c == WHITE) {
c = 0;
int orientation, int relation,
int p)
{
- int bh = (b->gameNum >= 0 && game_globals.garray[b->gameNum].link >= 0);
+ int bh = (b->gameNum >= 0 && game_globals.garray[b->gameNum].link >= 0
+ || b->holdings ); // [HGM] zh: make sure holdings are printed
orient = orientation;
myTurn = relation;
move happened, not current time */
if (game_globals.garray[b->gameNum].status == GAME_EXAMINE) {
unsigned nhm = game_globals.garray[b->gameNum].numHalfMoves;
+
if (nhm > 0) {
wTime = ml[nhm - 1].wTime;
bTime = ml[nhm - 1].bTime;
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);
char *move_and_time(struct move_t *m)
{
static char tmp[20];
+#if 0
+ if(m->depth>0)
+ sprintf(tmp, "%-7s (%s%.2f/%d)", m->algString, /* tenth_str(m->tookTime, 0), */
+ m->score>0 ? "+" : "", m->score, m->depth);
+ else
+#endif
sprintf(tmp, "%-7s (%s)", m->algString, tenth_str(m->tookTime, 0));
return tmp;
}
/* The following take the game state and whole move list */
+void Enlarge(char *a, int ss, int w)
+{
+ int l, i;
+ char *p, *q;
+ if(strlen(a) < ss) return;
+ for(i=8; i<w; i++) {
+ l = strlen(a);
+ p = a + l; q = p + ss;
+ while(q != a+l-ss) *q-- = *p--;
+ }
+}
+
static int genstyle(struct game_state_t *b, struct move_t *ml, const char *wp[], const char *bp[],
const char *wsqr, const char *bsqr,
const char *top, const char *mid, const char *start, const char *end,
const char *label,const 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;
+ int f, r, count, i;\r
+ char tmp[80], mylabel[80], *p, *q, myTop[80], myMid[80];\r
+ int firstR, lastR, firstF, lastF, inc;\r
+ int ws, bs, sqrSize = strlen(wp[0]);\r
+\r
+ board_calc_strength(b, &ws, &bs);\r
+ if (orient == WHITE) {\r
+ firstR = b->ranks-1;\r
+ firstF = b->files-1;\r
+ lastR = lastF = 0;\r
+ inc = -1;\r
+ } else {\r
+ firstR = firstF = 0;\r
+ lastR = b->ranks-1;\r
+ lastF = b->files-1;\r
+ inc = 1;\r
}
- 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]);
+ strcpy(myTop, top);
+ strcpy(myMid, mid);
+ Enlarge(myTop, sqrSize, b->files);\r
+ Enlarge(myMid, sqrSize, b->files);\r
+ strcat(bstring, myTop);\r
+ for (f = firstR, count = b->ranks-1; f != lastR + inc; f += inc, count--) {\r
+ sprintf(tmp, " %d %s", f + (b->ranks < 10), start);\r
+ strcat(bstring, tmp);\r
+ for (r = lastF; r != firstF - inc; r = r - inc) {\r
+ if (square_color(r, f) == WHITE)\r
+ strcat(bstring, wsqr);\r
+ else\r
+ strcat(bstring, bsqr);\r
+ if (piecetype(b->board[r][f]) == NOPIECE) {\r
+ if (square_color(r, f) == WHITE)\r
+ strcat(bstring, bp[0]);\r
+ else\r
+ strcat(bstring, wp[0]);\r
} 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 (game_globals.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[game_globals.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 */
-static int style13(struct game_state_t *b, struct move_t *ml)
-{
- static const 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 const 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 const char *wsqr = "\033[40m";
- static const char *bsqr = "\033[45m";
- static const char *top = "\t+------------------------+\n";
- static const char *mid = "";
- static const char *start = "|";
- static const char *end = "\033[0m|";
- static const char *label = "\t a b c d e f g h\n";
- static const 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 */
-static int style1(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {" |", " P |", " N |", " B |", " R |", " Q |", " K |"};
- static const 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 */
-static int style2(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {"+ ", "P ", "N ", "B ", "R ", "Q ", "K "};
- static const 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 */
-static int style3(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {" ", " P ", " N ", " B ", " R ", " Q ", " K "};
- static const 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 */
-static int style4(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {" ", " P ", " N ", " B ", " R ", " Q ", " K "};
- static const 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 */
-static int style5(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {" ", " o ", " :N:", " <B>", " |R|", " {Q}", " =K="};
- static const 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) */
-static int style6(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {" |", " wp |", " WN |", " WB |", " WR |", " WQ |", " WK |"};
- static const 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 */
-static int style7(struct game_state_t *b, struct move_t *ml)
-{
- static const char *wp[] = {" ", " P", " N", " B", " R", " Q", " K"};
- static const 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 */
-static int style8(struct game_state_t *b, struct 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,
- game_globals.garray[b->gameNum].white_name,
- (orient == WHITE) ? "*" : ":",
- game_globals.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",
- game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,
- (b->onMove == WHITE) ? "W" : "B",
- ws,
- bs,
- (wTime + 5) / 10,
- (bTime + 5) / 10,
- game_globals.garray[b->gameNum].numHalfMoves ?
- ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString :
- "none",
- game_globals.garray[b->gameNum].numHalfMoves ?
- tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :
- "0:00");
- strcat(bstring, tmp);
- return 0;
-}
-
-/* last 2 moves only (previous non-verbose mode) */
-static int style9(struct game_state_t *b, struct move_t *ml)
-{
- int i, count;
- char tmp[80];
- int startmove;
-
- sprintf(tmp, "\nMove %-23s%s\n",
- game_globals.garray[b->gameNum].white_name,
- game_globals.garray[b->gameNum].black_name);
- strcat(bstring, tmp);
- sprintf(tmp, "---- -------------- --------------\n");
- strcat(bstring, tmp);
- startmove = ((game_globals.garray[b->gameNum].numHalfMoves - 3) / 2) * 2;
- if (startmove < 0)
- startmove = 0;
- for (i = startmove, count = 0;
- i < game_globals.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... */
-static int style10(struct game_state_t *b, struct 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])]);
- }
+ int piece = piecetype(b->board[r][f]);
+// if(piece > QUEEN) piece = ELEPHANT + (piece == KING); // All fairies become elephants in ascii styles\r
+ if (colorval(b->board[r][f]) == WHITE)\r
+ strcat(bstring, wp[piece]);\r
+ else\r
+ strcat(bstring, bp[piece]);\r
+ }\r
+ }\r
+ sprintf(tmp, "%s", end);\r
+ strcat(bstring, tmp);\r
+ switch (count) {\r
+ case 7:\r
+ sprintf(tmp, " Move # : %d (%s)", b->moveNum, CString(b->onMove));\r
+ strcat(bstring, tmp);\r
+ break;\r
+ case 6:\r
+/* if ((b->moveNum > 1) || (b->onMove == BLACK)) { */\r
+/* The change from the above line to the one below is a kludge by hersco. */\r
+ if (game_globals.garray[b->gameNum].numHalfMoves > 0) {\r
+/* loon: think this fixes the crashing ascii board on takeback bug */\r
+ sprintf(tmp, " %s Moves : '%s'", CString(CToggle(b->onMove)),\r
+ move_and_time(&ml[game_globals.garray[b->gameNum].numHalfMoves - 1]));\r
+ strcat(bstring, tmp);\r
+ }\r
+ break;\r
+ case 5:\r
+ break;\r
+ case 4:\r
+ sprintf(tmp, " Black Clock : %s", tenth_str(((bTime > 0) ? bTime : 0), 1));\r
+ strcat(bstring, tmp);\r
+ break;\r
+ case 3:\r
+ sprintf(tmp, " White Clock : %s", tenth_str(((wTime > 0) ? wTime : 0), 1));\r
+ strcat(bstring, tmp);\r
+ break;\r
+ case 2:\r
+ sprintf(tmp, " Black Strength : %d", bs);\r
+ strcat(bstring, tmp);\r
+ break;\r
+ case 1:\r
+ sprintf(tmp, " White Strength : %d", ws);\r
+ strcat(bstring, tmp);\r
+ break;\r
+ case 0:\r
+ break;\r
+ }\r
+ strcat(bstring, "\n");\r
+ if (count != 0)\r
+ strcat(bstring, myMid);\r
+ else\r
+ strcat(bstring, myTop);\r
+ }\r
+ q = mylabel; i = 0;
+ if (orient == WHITE) {\r
+ p = label;
+ while(*p) {
+ switch(*p) {
+ case ' ':
+ case '\t':
+ case '\n':
+ *q++ = *p++; break;
+ default:
+ if(++i > b->files) { *q++ = '\n'; *q++ = 0; }
+ *q++ = *p++;
+ }
}
- strcat(bstring, "|\n");
- }
- strcat(bstring, (b->onMove == WHITE) ? "W " : "B ");
- if (game_globals.garray[b->gameNum].numHalfMoves) {
- sprintf(tmp, "%d ",
- ml[game_globals.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),
- (game_globals.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,
- game_globals.garray[b->gameNum].white_name,
- game_globals.garray[b->gameNum].black_name,
- myTurn,
- game_globals.garray[b->gameNum].wInitTime / 600,
- game_globals.garray[b->gameNum].wIncrement / 10,
- ws,
- bs,
- (wTime + 5) / 10,
- (bTime + 5) / 10,
- game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,
- game_globals.garray[b->gameNum].numHalfMoves ?
- ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString :
- "none",
- game_globals.garray[b->gameNum].numHalfMoves ?
- tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :
- "0:00",
- game_globals.garray[b->gameNum].numHalfMoves ?
- ml[game_globals.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") */
-static int style11(struct game_state_t *b, struct 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,
- game_globals.garray[b->gameNum].white_name,
- (orient == WHITE) ? "*" : ":",
- game_globals.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",
- game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,
- (b->onMove == WHITE) ? "W" : "B",
- ws,
- bs,
- (wTime + 5) / 10,
- (bTime + 5) / 10,
- game_globals.garray[b->gameNum].numHalfMoves ?
- ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString :
- "none",
- game_globals.garray[b->gameNum].numHalfMoves ?
- tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :
- "0:00");
- strcat(bstring, tmp);
- return 0;
+ p = blabel;
+ while(*p) {
+ switch(*p) {
+ case ' ':
+ case '\t':
+ case '\n':
+ *q++ = *p++; break;
+ default:
+ *q++ = *p++ + b->files - 12;
+ if(++i >= b->files) { *q++ = '\n'; *q++ = 0; }
+ }
+ }\r
+ }\r
+ *q++ = 0;
+ strcat(bstring, mylabel);\r
+ return 0;\r
}
-/* Similar to style 10. See the "style12" help file for information */
-static int style12(struct game_state_t *b, struct 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 (game_globals.garray[b->gameNum].numHalfMoves) {
- sprintf(tmp, "%d ",
- ml[game_globals.garray[b->gameNum].numHalfMoves - 1].doublePawn);
- } else {
- sprintf(tmp, "-1 ");
+/* Experimental ANSI board for colour representation */\r
+static int style13(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const 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 A ", "\033[37m\033[1m C ", "\033[37m\033[1m M ", "\033[37m\033[1m Q ", "\033[37m\033[1m E ", "\033[37m\033[1m K "};\r
+ static const 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 A ", "\033[21m\033[37m C ", "\033[21m\033[37m M ", "\033[21m\033[37m Q ", "\033[21m\033[37m E ", "\033[21m\033[37m K "};\r
+ static const char *wsqr = "\033[40m";\r
+ static const char *bsqr = "\033[45m";\r
+ static const char *top = "\t+------------------------+\n";\r
+ static const char *mid = "";\r
+ static const char *start = "|";\r
+ static const char *end = "\033[0m|";\r
+ static const char *label = "\t a b c d e f g h i j k l\n";\r
+ static const char *blabel = "\t l k j i h g f e d c b a\n";\r
+return 0;\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* Standard ICS */\r
+static int style1(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {" |", " P |", " N |", " B |", " R |", " A |", " C |", " M |", " Q |", " E |", " B |", " Q |",
+ " W |", " H |", " N |", " J |", " I |", " L |", " C |", " S |", " G |", " H |", " A |", " F |",
+ " E |", " H |", " M |", " S |", " E |", " W |", " O |", " G |", " V |", " S |", " E |", " A |", " K |"};
+ static const char *bp[] = {" |", " *P|", " *N|", " *B|", " *R|", " *A|", " *C|", " *M|", " *Q|", " *E|", " *B|", " *Q|",
+ " *W|", " *H|", " *N|", " *J|", " *I|", " *L|", " *C|", " *S|", " *G|", " *H|", " *A|", " *F|",
+ " *E|", " *H|", " *M|", " *S|", " *E|", " *W|", " *O|", " *G|", " *V|", " *S|", " *E|", " *A|", " *K|"};
+ static char *wsqr = "";\r
+ static char *bsqr = "";\r
+ static char *top = "\t---------------------------------\n";\r
+ static char *mid = "\t|---+---+---+---+---+---+---+---|\n";\r
+ static char *start = "|";\r
+ static char *end = "";\r
+ static char *label = "\t a b c d e f g h i j k l\n";\r
+ static char *blabel = "\t l k j i h g f e d c b a\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* USA-Today Sports Center-style board */\r
+static int style2(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {"- ", "P ", "N ", "B ", "R ", "A ", "C ", "M ", "Q ", "E ", "B ", "Q ",
+ "W ", "H ", "N ", "J ", "I ", "L ", "C ", "S ", "G ", "H ", "A ", "F ",
+ "E ", "H ", "M ", "S ", "E ", "W ", "O ", "G ", "V ", "S ", "E ", "A ", "K "};
+ static const char *bp[] = {"+ ", "p' ", "n' ", "b' ", "r' ", "a' ", "c' ", "m' ", "q' ", "e' ", "b' ", "q' ",
+ "w' ", "h' ", "n' ", "j' ", "i' ", "l' ", "c' ", "s' ", "g' ", "h' ", "a' ", "f' ",
+ "e' ", "h' ", "m' ", "s' ", "e' ", "w' ", "o' ", "g' ", "v' ", "s' ", "e' ", "a' ", "k' "};
+ static char *wsqr = "";\r
+ static char *bsqr = "";\r
+ static char *top = "";\r
+ static char *mid = "";\r
+ static char *start = "";\r
+ static char *end = "";\r
+ static char *label = "\ta b c d e f g h i j k l\n";\r
+ static char *blabel = "\tl k j i h g f e d c b a\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* Experimental vt-100 ANSI board for dark backgrounds */\r
+static int style3(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {" ", " P ", " N ", " B ", " R ", " A ", " C ", " M ", " Q ", " E ", " B ", " Q ",
+ " W ", " H ", " N ", " J ", " I ", " L ", " C ", " S ", " G ", " H ", " A ", " F ",
+ " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K "};
+ static const char *bp[] = {" ", " *P", " *N", " *B", " *R", " *A", " *C", " *M", " *Q", " *E", " *B", " *Q",
+ " *W", " *H", " *N", " *J", " *I", " *L", " *C", " *S", " *G", " *H", " *A", " *F",
+ " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K"};
+ static char *wsqr = "\033[0m";\r
+ static char *bsqr = "\033[7m";\r
+ static char *top = "\t+------------------------+\n";\r
+ static char *mid = "";\r
+ static char *start = "|";\r
+ static char *end = "\033[0m|";\r
+ static char *label = "\t a b c d e f g h i j k l\n";\r
+ static char *blabel = "\t l k j i h g f e d c b a\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* Experimental vt-100 ANSI board for light backgrounds */\r
+static int style4(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {" ", " P ", " N ", " B ", " R ", " A ", " C ", " M ", " Q ", " E ", " B ", " Q ",
+ " W ", " H ", " N ", " J ", " I ", " L ", " C ", " S ", " G ", " H ", " A ", " F ",
+ " E ", " H ", " M ", " S ", " E ", " W ", " O ", " G ", " V ", " S ", " E ", " A ", " K "};
+ static const char *bp[] = {" ", " *P", " *N", " *B", " *R", " *A", " *C", " *M", " *Q", " *E", " *B", " *Q",
+ " *W", " *H", " *N", " *J", " *I", " *L", " *C", " *S", " *G", " *H", " *A", " *F",
+ " *E", " *H", " *M", " *S", " *E", " *W", " *O", " *G", " *V", " *S", " *E", " *A", " *K"};
+ static char *wsqr = "\033[7m";\r
+ static char *bsqr = "\033[0m";\r
+ static char *top = "\t+------------------------+\n";\r
+ static char *mid = "";\r
+ static char *start = "|";\r
+ static char *end = "\033[0m|";\r
+ static char *label = "\t a b c d e f g h i j k l\n";\r
+ static char *blabel = "\t l k j i h g f e d c b a\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* Style suggested by ajpierce@med.unc.edu */\r
+static int style5(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {" ", " o ", " :N:", " <B>", " |R|", " (A)", " [C]", " :M:", " {Q}", " !E!",
+ " <B>", " {Q}", " .W.", " :H:", " :N:", " <J>", " |I|", " |L|",
+ " |C|", " !S!", " :G:", " :H:", " {A}", " {F}", " !E!", " (H)", " [M]", " :S:",
+ " !E!", " |W|", " *O*", " {G}", " :V:", " (S)", " [E]", " &A&", " =K="};
+ static const char *bp[] = {" ", " p ", " :n:", " <b>", " |r|", " (a)", " [c]", " :m:", " {q}", " !e!",
+ " <b>", " {q}", " .w.", " :h:", " :n:", " <j>", " |i|", " |l|",
+ " |c|", " !s!", " :g:", " :h:", " {a}", " {f}", " !e!", " (h)", " [m]", " :s:",
+ " !e!", " |w|", " *o*", " {g}", " :v:", " (s)", " [e]", " &a&", " =k="};
+ static char *wsqr = "";\r
+ static char *bsqr = "";\r
+ static char *top = " . . . . . . . . .\n";\r
+ static char *mid = " . . . . . . . . .\n";\r
+ static char *start = "";\r
+ static char *end = "";\r
+ static char *label = "\t a b c d e f g h i j k l\n";\r
+ static char *blabel = "\t l k j i h g f e d c b a\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* Email Board suggested by Thomas Fought (tlf@rsch.oclc.org) */\r
+static int style6(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {" |", " wp |", " WN |", " WB |", " WR |", " WA |", " WC |", " WM |", " WQ |",
+ " WE |", " WB |", " WQ |", " WW |", " WH |", " WN |", " WJ |", " WI |", " WL |",
+ " WC |", " WS |", " WG |", " WH |", " WA |", " WF |", " WE |", " WH |", " WM |",
+ " WS |", " WE |", " WW |", " WO |", " WG |", " WV |", " WS |", " WE |", " WA |", " WK |"};
+ static const char *bp[] = {" |", " bp |", " BN |", " BB |", " BR |", " BA |", " BC |", " BM |", " BQ |",
+ " BE |", " BB |", " BQ |", " BW |", " BH |", " BN |", " BJ |", " BI |", " BL |",
+ " BC |", " BS |", " BG |", " BH |", " BA |", " BF |", " BE |", " BH |", " BM |",
+ " BS |", " BE |", " BW |", " BO |", " BG |", " BV |", " BS |", " BE |", " BA |", " BK |"};
+ static char *wsqr = "";\r
+ static char *bsqr = "";\r
+ static char *top = "\t-----------------------------------------\n";\r
+ static char *mid = "\t-----------------------------------------\n";\r
+ static char *start = "|";\r
+ static char *end = "";\r
+ static char *label = "\t A B C D E F G H I J K L\n";\r
+ static char *blabel = "\t L K J I H G F E D C B A\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+\r
+/* Miniature board */\r
+static int style7(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ static const char *wp[] = {" ", " P", " N", " B", " R", " A", " C", " M", " Q", " E", " B", " Q", " W", " H", " N", " J", " I", " L",
+ " C", " S", " G", " H", " A", " F", " E", " H", " M", " S", " E", " W", " O", " G", " V", " S", " E", " A", " K"};
+ static const char *bp[] = {" -", " p", " n", " b", " r", " a", " c", " m", " q", " e", " b", " q", " w", " h", " n", " j", " i", " l",
+ " c", " s", " g", " h", " a", " f", " e", " h", " m", " s", " e", " w", " o", " g", " v", " s", " e", " a", " k"};
+ static char *wsqr = "";\r
+ static char *bsqr = "";\r
+ static char *top = "\t:::::::::::::::::::::\n";\r
+ static char *mid = "";\r
+ static char *start = "..";\r
+ static char *end = " ..";\r
+ static char *label = "\t a b c d e f g h i j k l\n";\r
+ static char *blabel = "\t l k j i h g f e d c b a\n";\r
+\r
+ return genstyle(b, ml, wp, bp, wsqr, bsqr, top, mid, start, end, label, blabel);\r
+}\r
+
+/* ICS interface maker board-- raw data dump */\r
+static int style8(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ char tmp[160];\r
+ int f, r;\r
+ int ws, bs;\r
+\r
+ board_calc_strength(b, &ws, &bs);\r
+ sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum + 1,\r
+ game_globals.garray[b->gameNum].white_name,\r
+ (orient == WHITE) ? "*" : ":",\r
+ game_globals.garray[b->gameNum].black_name,\r
+ (orient == WHITE) ? ":" : "*");\r
+ strcat(bstring, tmp);\r
+ for (r = 0; r < b->ranks; r++) {\r
+ for (f = 0; f < b->files; f++) {\r
+ if (b->board[f][r] == NOPIECE) {\r
+ strcat(bstring, " ");\r
+ } else {\r
+ if (colorval(b->board[f][r]) == WHITE)\r
+ strcat(bstring, wpstring[piecetype(b->board[f][r])]);\r
+ else\r
+ strcat(bstring, bpstring[piecetype(b->board[f][r])]);\r
+ }\r
+ }\r
+ }\r
+ sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n",\r
+ game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,\r
+ (b->onMove == WHITE) ? "W" : "B",\r
+ ws,\r
+ bs,\r
+ (wTime + 5) / 10,\r
+ (bTime + 5) / 10,\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString :\r
+ "none",\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :\r
+ "0:00");\r
+ strcat(bstring, tmp);\r
+ return 0;\r
+}\r
+\r
+/* last 2 moves only (previous non-verbose mode) */\r
+static int style9(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ int i, count;\r
+ char tmp[160];\r
+ int startmove;\r
+\r
+ sprintf(tmp, "\nMove %-23s%s\n",\r
+ game_globals.garray[b->gameNum].white_name,\r
+ game_globals.garray[b->gameNum].black_name);\r
+ strcat(bstring, tmp);\r
+ sprintf(tmp, "---- -------------- --------------\n");\r
+ strcat(bstring, tmp);\r
+ startmove = ((game_globals.garray[b->gameNum].numHalfMoves - 3) / 2) * 2;\r
+ if (startmove < 0)\r
+ startmove = 0;\r
+ for (i = startmove, count = 0;\r
+ i < game_globals.garray[b->gameNum].numHalfMoves && count < 4;\r
+ i++, count++) {\r
+ if (!(i & 0x01)) {\r
+ sprintf(tmp, " %2d ", i / 2 + 1);\r
+ strcat(bstring, tmp);\r
+ }\r
+ sprintf(tmp, "%-23s", move_and_time(&ml[i]));\r
+ strcat(bstring, tmp);\r
+ if (i & 0x01)\r
+ strcat(bstring, "\n");\r
+ }\r
+ if (i & 0x01)\r
+ strcat(bstring, "\n");\r
+ return 0;\r
+}\r
+\r
+/* Sleator's 'new and improved' raw dump format... */\r
+static int style10(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ int f, r;\r
+ char tmp[160];\r
+ int ws, bs;\r
+\r
+ board_calc_strength(b, &ws, &bs);\r
+ sprintf(tmp, "<10>\n");\r
+ strcat(bstring, tmp);\r
+ for (r = b->ranks-1; r >= 0; r--) {\r
+ strcat(bstring, "|");\r
+ for (f = 0; f < b->files; f++) {\r
+ if (b->board[f][r] == NOPIECE) {\r
+ strcat(bstring, " ");\r
+ } else {\r
+ if (colorval(b->board[f][r]) == WHITE)\r
+ strcat(bstring, wpstring[piecetype(b->board[f][r])]);\r
+ else\r
+ strcat(bstring, bpstring[piecetype(b->board[f][r])]);\r
+ }\r
+ }\r
+ strcat(bstring, "|\n");\r
+ }\r
+ strcat(bstring, (b->onMove == WHITE) ? "W " : "B ");\r
+ if (game_globals.garray[b->gameNum].numHalfMoves) {\r
+ sprintf(tmp, "%d ",\r
+ ml[game_globals.garray[b->gameNum].numHalfMoves - 1].doublePawn);\r
+ } else {\r
+ sprintf(tmp, "-1 ");\r
+ }\r
+ strcat(bstring, tmp);\r
+ sprintf(tmp, "%d %d %d %d %d\n",\r
+ (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights\r
+ (b->wkmoved >= 0 && b->wqrmoved >= 0),\r
+ (b->bkmoved >= 0 && b->bkrmoved >= 0),\r
+ (b->bkmoved >= 0 && b->bqrmoved >= 0),\r
+ (game_globals.garray[b->gameNum].numHalfMoves - ((b->lastIrreversable == -1) ? 0 :\r
+ b->lastIrreversable)));\r
+ strcat(bstring, tmp);\r
+ sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d\n",\r
+ b->gameNum,\r
+ game_globals.garray[b->gameNum].white_name,\r
+ game_globals.garray[b->gameNum].black_name,\r
+ myTurn,\r
+ game_globals.garray[b->gameNum].wInitTime / 600,\r
+ game_globals.garray[b->gameNum].wIncrement / 10,\r
+ ws,\r
+ bs,\r
+ (wTime + 5) / 10,\r
+ (bTime + 5) / 10,\r
+ game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString :\r
+ "none",\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :\r
+ "0:00",\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString :\r
+ "none",\r
+ (orient == WHITE) ? 0 : 1);\r
+ strcat(bstring, tmp);\r
+ sprintf(tmp, ">10<\n");\r
+ strcat(bstring, tmp);\r
+ return 0;\r
+}\r
+\r
+/* Same as 8, but with verbose moves ("P/e3-e4", instead of "e4") */\r
+static int style11(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ char tmp[160];\r
+ int f, r;\r
+ int ws, bs;\r
+\r
+ board_calc_strength(b, &ws, &bs);\r
+ sprintf(tmp, "#@#%03d%-16s%s%-16s%s", b->gameNum,\r
+ game_globals.garray[b->gameNum].white_name,\r
+ (orient == WHITE) ? "*" : ":",\r
+ game_globals.garray[b->gameNum].black_name,\r
+ (orient == WHITE) ? ":" : "*");\r
+ strcat(bstring, tmp);\r
+ for (r = 0; r < b->ranks; r++) {\r
+ for (f = 0; f < b->files; f++) {\r
+ if (b->board[f][r] == NOPIECE) {\r
+ strcat(bstring, " ");\r
+ } else {\r
+ if (colorval(b->board[f][r]) == WHITE)\r
+ strcat(bstring, wpstring[piecetype(b->board[f][r])]);\r
+ else\r
+ strcat(bstring, bpstring[piecetype(b->board[f][r])]);\r
+ }\r
+ }\r
+ }\r
+ sprintf(tmp, "%03d%s%02d%02d%05d%05d%-7s(%s)@#@\n",\r
+ game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,\r
+ (b->onMove == WHITE) ? "W" : "B",\r
+ ws,\r
+ bs,\r
+ (wTime + 5) / 10,\r
+ (bTime + 5) / 10,\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString :\r
+ "none",\r
+ game_globals.garray[b->gameNum].numHalfMoves ?\r
+ tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :\r
+ "0:00");\r
+ strcat(bstring, tmp);\r
+ return 0;\r
+}\r
+
+
+int kludgeFlag = 0; \r
+/* Similar to style 10. See the "style12" help file for information */\r
+static int style12(struct game_state_t *b, struct move_t *ml)\r
+{\r
+ int f, r;\r
+ char tmp[160]; // [HGM] 80 caused problems with long login names\r
+ int ws, bs;
+ int nhm = kludgeFlag ? 0 : game_globals.garray[b->gameNum].numHalfMoves;
+ // [HGM] setup: the number of half moves appeared in this routine an enormous number of times,
+ // and had to be dug out of the game_globals, so that this routine could only be used to print
+ // a board from a game, and not just any board given by an isolated game_state_t. This was very
+ // inconvenient for printing initial boards in move lists of shuffle variants, so I added the
+ // global kludgeFlag to signal that we want to print an initial position, and force nhm = 0.\r
+\r
+ board_calc_strength(b, &ws, &bs);\r
+\r
+ sprintf(bstring, "<12> ");\r
+ for (r = b->ranks-1; r >= 0; r--) {\r
+ for (f = 0; f < b->files; f++) {
+ if (b->board[f][r] == NOPIECE) {\r
+ strcat(bstring, "-");\r
+ } else {\r
+ if (colorval(b->board[f][r]) == WHITE)\r
+ strcat(bstring, wpstring[piecetype(b->board[f][r])]);\r
+ else\r
+ strcat(bstring, bpstring[piecetype(b->board[f][r])]);\r
+ }\r
+ }\r
+ strcat(bstring, " ");\r
}
+\r
+ strcat(bstring, (b->onMove == WHITE) ? "W " : "B ");\r
+ if (nhm) {\r
+ sprintf(tmp, "%d ",\r
+ ml[nhm - 1].doublePawn);\r
+ } else {\r
+ sprintf(tmp, "-1 ");\r
+ }\r
+ strcat(bstring, tmp);\r
+ sprintf(tmp, "%d %d %d %d %d ",\r
+ (b->wkmoved >= 0 && b->wkrmoved >= 0), // [HGM] castle: inverted the logic, both must have rights\r
+ (b->wkmoved >= 0 && b->wqrmoved >= 0),\r
+ (b->bkmoved >= 0 && b->bkrmoved >= 0),\r
+ (b->bkmoved >= 0 && b->bqrmoved >= 0),\r
+ (nhm - ((b->lastIrreversable == -1) ? 0 : b->lastIrreversable)));\r
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),
- (game_globals.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 %d\n",
- b->gameNum + 1,
- game_globals.garray[b->gameNum].white_name,
- game_globals.garray[b->gameNum].black_name,
- myTurn,
- game_globals.garray[b->gameNum].wInitTime / 600,
- game_globals.garray[b->gameNum].wIncrement / 10,
- ws,
- bs,
- (wTime / 10),
- (bTime / 10),
- game_globals.garray[b->gameNum].numHalfMoves / 2 + 1,
- game_globals.garray[b->gameNum].numHalfMoves ?
- ml[game_globals.garray[b->gameNum].numHalfMoves - 1].moveString :
- "none",
- game_globals.garray[b->gameNum].numHalfMoves ?
- tenth_str(ml[game_globals.garray[b->gameNum].numHalfMoves - 1].tookTime, 0) :
- "0:00",
- game_globals.garray[b->gameNum].numHalfMoves ?
- ml[game_globals.garray[b->gameNum].numHalfMoves - 1].algString :
- "none", (orient == WHITE) ? 0 : 1,
- b->moveNum > 1 ? 1 : 0); /* ticking */
-
- strcat(bstring, tmp);
- return 0;
-}
+ sprintf(tmp, "%d %s %s %d %d %d %d %d %d %d %d %s (%s) %s %d %d\n",\r
+ b->gameNum + 1,\r
+ game_globals.garray[b->gameNum].white_name,\r
+ game_globals.garray[b->gameNum].black_name,\r
+ myTurn,\r
+ game_globals.garray[b->gameNum].wInitTime / 600,\r
+ game_globals.garray[b->gameNum].wIncrement / 10,\r
+ ws,\r
+ bs,\r
+ (wTime / 10),\r
+ (bTime / 10),\r
+ nhm / 2 + 1,\r
+ nhm ?\r
+ ml[nhm - 1].moveString :\r
+ "none",\r
+ nhm ?\r
+ tenth_str(ml[nhm - 1].tookTime, 0) :\r
+ "0:00",\r
+ nhm ?\r
+ ml[nhm - 1].algString :\r
+ "none", (orient == WHITE) ? 0 : 1,\r
+ b->moveNum > 1 ? 1 : 0); /* ticking */\r
+
+ strcat(bstring, tmp);\r
+ return 0;\r
+}\r
static int board_read_file(char *category, char *gname, struct game_state_t *gs)
{
return 1;
board_clear(gs);
+ gs->setup = 1;
while (!feof(fp)) {
c = fgetc(fp);
if (onNewLine) {
onColor = BLACK;
if (gs->onMove < 0)
gs->onMove = BLACK;
+ } else if (c == 'S') { int f=8, r=8;
+ // [HGM] rules: read rule modifiers
+ fscanf(fp, "%dx%d", &f, &r); gs->files=f; gs->ranks = r;
+ while (!feof(fp) && c != '\n') {
+ c = fgetc(fp);
+ switch(c) {
+ case 'r':
+ gs->royalKnight = 1;
+ break;
+ case 'c':
+ gs->capablancaPieces = 1;
+ break;
+ case 'd':
+ gs->drops = 1;
+ break;
+ case 'h':
+ gs->holdings = -1; // color-flip holdings
+ break;
+ case 'p':
+ gs->palace = 3;
+ break;
+ case 'P':
+ gs->promoType = 2; // only promote to captured pieces
+ gs->holdings = 1; // use holdings to hold own captured pieces
+ break;
+ case 'F':
+ gs->castlingStyle = 2; // FRC castling
+ break;
+ case 'w':
+ gs->castlingStyle = 1; // wild castling, from both center files
+ break;
+ case 'n':
+ gs->castlingStyle = 0; // no castling
+ break;
+ case 'f':
+ gs->castlingStyle = 3; // free castling
+ break;
+ case 'D':
+ gs->pawnDblStep = 0; // suppress pawn double step
+ break;
+ case 'b':
+ gs->bareKingLoses = 1; // apply baring rule
+ break;
+ case 's':
+ gs->stalemate = 0; // stalemate loses
+ break;
+ }
+ }
+ continue;
} else if (c == '#') {
while (!feof(fp) && c != '\n')
c = fgetc(fp); /* Comment line */
case 'B':
onPiece = BISHOP;
break;
+ case 'A':\r
+ onPiece = CARDINAL;\r
+ break;\r
+ case 'C':\r
+ onPiece = MARSHALL;\r
+ break;\r
+ case 'M':\r
+ onPiece = MAN;\r
+ break;\r
case 'Q':
onPiece = QUEEN;
break;
- case 'K':
- onPiece = KING;
+ case 'T':
+ onPiece = ELEPHANT;
break;
- case 'a':
- case 'b':
- case 'c':
- case 'd':
- case 'e':
- case 'f':
- case 'g':
- case 'h':
- onFile = c - 'a';
- onRank = -1;
+ case 'E':
+ onPiece = ALFIL;
+ break;
+ case 't':
+ onPiece = ALFIL2;
+ break;
+ case 'q':
+ onPiece = FERZ;
+ break;
+ case 'F':
+ onPiece = FERZ2;
+ break;
+ case 'W':
+ onPiece = WAZIR;
+ break;
+ case 'w':
+ onPiece = WOODY;
+ break;
+ case 'p':
+ onPiece = PRIESTESS;
+ break;
+ case 'r':
+ onPiece = MINISTER;
+ break;
+ case 'z':
+ onPiece = MAN2;
+ break;
+ case 'u':
+ onPiece = NIGHTRIDER;
+ break;
+ case 'o':
+ onPiece = MODERNELEPHANT;
+ break;
+ case 's':
+ onPiece = MASTODON;
+ break;
+ case 'Z':
+ onPiece = AMAZON;
+ break;
+ case 'V':
+ onPiece = CENTAUR;
+ break;
+ case 'H':
+ onPiece = HORSE;
+ break;
+ case 'n':
+ onPiece = HONORABLEHORSE;
+ break;
+ case 'J':
+ onPiece = DRAGONKING;
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;
+ case 'I':
+ onPiece = DRAGONHORSE;
break;
- case '#':
+ case 'L':
+ onPiece = LANCE;
+ break;
+ case 'O':
+ onPiece = CANNON;
+ break;
+ case 'S':
+ onPiece = SILVER;
+ break;
+ case 'G':
+ onPiece = GOLD;
+ break;
+ case 'm':
+ onPiece = MANDARIN;
+ break;
+ case 'K':
+ onPiece = KING;
+ break;
+ case 'a':\r
+ case 'b':\r
+ case 'c':\r
+ case 'd':\r
+ case 'e':\r
+ case 'f':\r
+ case 'g':\r
+ case 'h':\r
+ case 'i':\r
+ case 'j':\r
+ case 'k':\r
+ case 'l':\r
+ onFile = c - 'a';\r
+ if(onFile >= gs->files) { onFile = -1; break; }\r
+ onRank = -1;\r
+ break;\r
+ case '@':
+ if (onColor >= 0 && onPiece >= 0) // allow placement in holdings\r
+ gs->holding[onColor == BLACK][onPiece-1]++;
+ break;\r
+ case '1':\r
+ case '2':\r
+ case '3':\r
+ case '4':\r
+ case '5':\r
+ case '6':\r
+ case '7':\r
+ case '8':\r
+ case '9':\r
+ case '0':\r
+ onRank = c - '1' + (gs->ranks > 9);\r
+ if(onRank < 0 || onRank >= gs->ranks) { onRank = -1; break; }\r
+ if (onFile >= 0 && onColor >= 0 && onPiece >= 0)\r
+ gs->board[onFile][onRank] = onPiece | onColor;\r
+ break;\r case '#':
while (!feof(fp) && c != '\n')
c = fgetc(fp); /* Comment line */
case '\n':
#define ANY_SQUARE -1
#define SquareColor(f, r) ((f ^ r) & 1)
-static void place_piece(board_t b, int piece, int squareColor)
-{
+static void place_piece(board_t b, int piece, int squareColor, int width)
+{ //[HGM] board: make width a variable
int r, f;
int placed = 0;
while (!placed) {
if (squareColor == ANY_SQUARE) {
- f = random() % 8;
+ f = random() % width;
} else {
- f = (random() % 4) * 2;
+ f = (random() % ((width+1)/2)) * 2; // to not overflow odd-width boards
if (SquareColor(f, r) != squareColor)
f++;
}
}
}
-static void wild_update(int style)
+static void wild_update(board_t b, int style)
{
- int f, r, i;
- board_t b;
+ int f, r, i, j;
- for (f = 0; f < 8; f++)
+ for (f = 0; f < BW; f++) // [HGM] board: make sure also works with wider boards
for (r = 0; r < 8; r++)
b[f][r] = NOPIECE;
for (f = 0; f < 8; f++) {
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);
+ place_piece(b, W_BISHOP, WHITE_SQUARE, 8);
+ place_piece(b, W_BISHOP, BLACK_SQUARE, 8);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+ place_piece(b, B_BISHOP, WHITE_SQUARE, 8);
+ place_piece(b, B_BISHOP, BLACK_SQUARE, 8);
+ place_piece(b, B_KNIGHT, ANY_SQUARE, 8);
+ place_piece(b, B_KNIGHT, ANY_SQUARE, 8);
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);
+ place_piece(b, W_KING, ANY_SQUARE, 8);
+ place_piece(b, W_QUEEN, ANY_SQUARE, 8);
+ place_piece(b, W_ROOK, ANY_SQUARE, 8);
+ place_piece(b, W_ROOK, ANY_SQUARE, 8);
+ place_piece(b, W_BISHOP, ANY_SQUARE, 8);
+ place_piece(b, W_BISHOP, ANY_SQUARE, 8);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
/* 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);
+ place_piece(b, W_KING, ANY_SQUARE, 8);
for (i = 0; i < 8; i++) {
if (b[i][0] != W_KING) {
b[i][0] = (random() % 4) + 2;
break;
case 4:
/* Generate White king on random square plus random set of pieces */
- place_piece(b, W_KING, ANY_SQUARE);
+ place_piece(b, W_KING, ANY_SQUARE, 8);
for (i = 0; i < 8; i++) {
if (b[i][0] != W_KING) {
b[i][0] = (random() % 4) + 2;
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));
+ place_piece(b, B_BISHOP, !SquareColor(i, 0), 8);
}
}
for (i = 0; i < 8; i++) {
if (b[i][0] != W_BISHOP) {
- place_piece(b, b[i][0] | BLACK, ANY_SQUARE);
+ place_piece(b, b[i][0] | BLACK, ANY_SQUARE, 8);
}
}
break;
+ case 22:
+ /* Chess960 placement: King between R */
+ place_piece(b, W_BISHOP, WHITE_SQUARE, 8);
+ place_piece(b, W_BISHOP, BLACK_SQUARE, 8);
+ place_piece(b, W_QUEEN, ANY_SQUARE, 8);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 8);
+ for (i = j = 0; i < 8; i++) {
+ if(b[i][0] == NOPIECE) b[i][0] = (j++ == 1 ? W_KING : W_ROOK);
+ }
+ /* Black mirrors White */
+ for (i = 0; i < 8; i++) {
+ b[i][7] = b[i][0] | BLACK;
+ }
+ break;
+ case 46:
+ /* Chess960 placement: King between R */
+ place_piece(b, W_BISHOP, WHITE_SQUARE, 10);
+ place_piece(b, W_BISHOP, BLACK_SQUARE, 10);
+ place_piece(b, W_QUEEN, ANY_SQUARE, 10);
+ place_piece(b, W_MARSHALL, ANY_SQUARE, 10);
+ place_piece(b, W_CARDINAL, ANY_SQUARE, 10);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 10);
+ place_piece(b, W_KNIGHT, ANY_SQUARE, 10);
+ for (i = j = 0; i < 10; i++) {
+ if(b[i][0] == NOPIECE) j++ == 1 ? W_KING : W_ROOK;
+ }
+ /* Black mirrors White */
+ for (i = 0; i < 10; i++) {
+ b[i][7] = b[i][0] | BLACK;
+ }
+ break;
default:
return;
break;
void wild_init(void)
{
- wild_update(1);
- wild_update(2);
- wild_update(3);
- wild_update(4);
+ board_t b;
+ wild_update(b, 1);
+ wild_update(b, 2);
+ wild_update(b, 3);
+ wild_update(b, 4);
}
/* These will go into an array */
-#define NOPIECE 0x00
-#define PAWN 0x01
-#define KNIGHT 0x02
-#define BISHOP 0x03
-#define ROOK 0x04
-#define QUEEN 0x05
-#define KING 0x06
-
-#define MAX_BOARD_STRING_LEGTH 1280 /* Abitrarily 80 * 16 */
+#define NOPIECE 0
+#define PAWN 1
+#define KNIGHT 2
+#define BISHOP 3
+#define ROOK 4
+#define CARDINAL 5
+#define MARSHALL 6
+#define MAN 7
+#define QUEEN 8
+#define ELEPHANT 9
+#define ALFIL 10
+#define FERZ 11
+#define WAZIR 12
+#define HORSE 13
+#define HONORABLEHORSE 14
+#define DRAGONKING 15
+#define DRAGONHORSE 16
+#define LANCE 17
+#define CANNON 18
+#define SILVER 19
+#define GOLD 20
+#define NIGHTRIDER 21
+#define MANDARIN 22
+#define FERZ2 23
+#define ALFIL2 24
+#define PRIESTESS 25
+#define MINISTER 26
+#define MAN2 27
+#define MODERNELEPHANT 28
+#define WOODY 29
+#define SQUIRREL 30
+#define MASTODON 31
+#define CENTAUR 32
+#define PRINCESS 33
+#define EMPRESS 34
+#define AMAZON 35
+#define KING 36
+
+#define MAX_BOARD_STRING_LENGTH 1280 /* Abitrarily 80 * 16 */
#define MAX_STYLES 13
#define W_PAWN (PAWN | WHITE)
#define W_KNIGHT (KNIGHT | WHITE)
#define W_BISHOP (BISHOP | WHITE)
#define W_ROOK (ROOK | WHITE)
+#define W_CARDINAL (CARDINAL | WHITE)
+#define W_MARSHALL (MARSHALL | WHITE)
+#define W_MAN (MAN | WHITE)
#define W_QUEEN (QUEEN | WHITE)
+#define W_ELEPHANT (ELEPHANT | WHITE)
+#define W_ALFIL (ALFIL | WHITE)
+#define W_FERZ (FERZ | WHITE)
+#define W_WAZIR (WAZIR | WHITE)
+#define W_ALFIL2 (ALFIL2 | WHITE)
+#define W_FERZ2 (FERZ2 | WHITE)
+#define W_AMAZON (AMAZON | WHITE)
+#define W_CENTAUR (CENTAUR | WHITE)
+#define W_HORSE (HORSE | WHITE)
+#define W_HONORABLEHORSE (HONORABLEHORSE | WHITE)
+#define W_DRAGONKING (DRAGONKING | WHITE)
+#define W_DRAGONHORSE (DRAGONHORSE | WHITE)
+#define W_LANCE (LANCE | WHITE)
+#define W_CANNON (CANNON | WHITE)
+#define W_SILVER (SILVER | WHITE)
+#define W_GOLD (GOLD | WHITE)
#define W_KING (KING | WHITE)
+#define W_MANDARIN (MANDARIN | WHITE)
+#define W_EMPRESS (EMPRESS | WHITE)
+#define W_PRINCESS (PRINCESS | WHITE)
+#define W_WOODY (WOODY | WHITE)
+#define W_MINISTER (MINISTER | WHITE)
+#define W_PRIESTESS (PRIESTESS | WHITE)
+#define W_MASTODON (MASTODON | WHITE)
+#define W_MAN2 (MAN2 | WHITE)
+#define W_NIGHTRIDER (NIGHTRIDER | WHITE)
#define B_PAWN (PAWN | BLACK)
#define B_KNIGHT (KNIGHT | BLACK)
#define B_BISHOP (BISHOP | BLACK)
#define B_ROOK (ROOK | BLACK)
+#define B_CARDINAL (CARDINAL | BLACK)
+#define B_MARSHALL (MARSHALL | BLACK)
+#define B_MAN (MAN | BLACK)
#define B_QUEEN (QUEEN | BLACK)
+#define B_ELEPHANT (ELEPHANT | BLACK)
+#define B_ALFIL (ALFIL | BLACK)
+#define B_FERZ (FERZ | BLACK)
+#define B_WAZIR (WAZIR | BLACK)
+#define B_ALFIL2 (ALFIL2 | BLACK)
+#define B_FERZ2 (FERZ2 | BLACK)
+#define B_AMAZON (AMAZON | BLACK)
+#define B_CENTAUR (CENTAUR | BLACK)
+#define B_HORSE (HORSE | BLACK)
+#define B_HONORABLEHORSE (HONORABLEHORSE | BLACK)
+#define B_DRAGONKING (DRAGONKING | BLACK)
+#define B_DRAGONHORSE (DRAGONHORSE | BLACK)
+#define B_LANCE (LANCE | BLACK)
+#define B_CANNON (CANNON | BLACK)
+#define B_SILVER (SILVER | BLACK)
+#define B_GOLD (GOLD | BLACK)
#define B_KING (KING | BLACK)
+#define B_MANDARIN (MANDARIN | BLACK)
+#define B_EMPRESS (EMPRESS | BLACK)
+#define B_PRINCESS (PRINCESS | BLACK)
+#define B_WOODY (WOODY | BLACK)
+#define B_MINISTER (MINISTER | BLACK)
+#define B_PRIESTESS (PRIESTESS | BLACK)
+#define B_MASTODON (MASTODON | BLACK)
+#define B_MAN2 (MAN2 | BLACK)
+#define B_NIGHTRIDER (NIGHTRIDER | BLACK)
#define isblack(p) ((p) & BLACK)
#define iswhite(p) (!isblack(p))
#define colorval(p) ((p) & 0x80)
#define square_color(r,f) ((((r)+(f)) & 0x01) ? BLACK : WHITE)
-extern int pieceValues[7];
+extern int pieceValues[KING+1];
+#define BW 12
+#define BH 10
/* Treated as [file][rank] */
-typedef int board_t[8][8];
+typedef int board_t[BW][BH];
GENSTRUCT struct game_state_t {
- int board[8][8];
+ int board[BW][BH];
/* for bughouse */
- int holding[2][5];
+ int holding[2][KING];
/* For castling */
- unsigned char wkmoved, wqrmoved, wkrmoved;
- unsigned char bkmoved, bqrmoved, bkrmoved;
+ char wkmoved, wqrmoved, wkrmoved;
+ char bkmoved, bqrmoved, bkrmoved;
/* for ep */
- int ep_possible[2][8];
+ int ep_possible[2][BW];
/* For draws */
int lastIrreversable;
int onMove;
int moveNum;
/* Game num not saved, must be restored when read */
int gameNum;
+ char royalKnight;
+ char capablancaPieces;
+ char pawnDblStep;
+ char ranks;
+ char files;
+ char holdings;
+ char drops;
+ char castlingStyle;
+ char palace;
+ char setup;
+ char bareKingLoses;
+ char stalemate;
+ char promoType;
+ char variant[20];
};
#define ALG_DROP -2
+#define ALG_CASTLE -3
/* bughouse: if a drop move, then fromFile is ALG_DROP and fromRank is piece */
/* these are used when examining a game */
int wTime;
int bTime;
+
+ /* [HGM] these are used for computer games */
+ float score;
+ int depth;
};
#define MoveToHalfMove( gs ) ((((gs)->moveNum - 1) * 2) + (((gs)->onMove == WHITE) ? 0 : 1))
extern const char *wpstring[];
extern const char *bpstring[];
+extern int kludgeFlag; // [HGM] setup: forces move nr to zero in board printing
+
/* the FEN for the default initial position */
#define INITIAL_FEN "rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w"
#include "includes.h"
#include "command_list.h"
-static const char *usage_dir[NUM_LANGS] = {USAGE_DIR, USAGE_SPANISH,
+const char *usage_dir[NUM_LANGS] = {USAGE_DIR, USAGE_SPANISH,
USAGE_FRENCH, USAGE_DANISH};
static int lastCommandFound = -1;
#define DEFAULT_TIME 2
#define DEFAULT_INCREMENT 12
#define DEFAULT_MAX_SOUGHT 1000
-#define DEFAULT_IDLE_TIMEOUT 3600
+#define DEFAULT_IDLE_TIMEOUT 36000
#define DEFAULT_LOGIN_TIMEOUT 300
#define DEFAULT_GUEST_PREFIX_ONLY 0
void FEN_to_board(char* FENpos, struct game_state_t* gs)
{
- int f,r;
- char next;
-
-
- for (r=7; r >=0; r--) {
- f=0;
- while (f<8) {
- next = *(FENpos++);
- if (isalpha(next))
- gs->board[f++][r] = CharToPiece(next);
- else if (next != '/') {
- int t = (next - '0');
- do
- gs->board[f++][r] = NOPIECE;
- while (--t);
- }
- }
- }
- if (*(FENpos + 1) == 'w') /* the char after the space */
- gs->onMove = WHITE;
- else
- gs->onMove = BLACK;
+ int f,r;\r
+ char next;\r
+printf("FEN, var='%s'\n", gs->variant);\r
+ for (r=gs->ranks-1; r >=0; r--) {\r
+ f=0;\r
+ while (f<gs->files) {\r
+ next = *(FENpos++);\r
+ if (isalpha(next))\r
+ gs->board[f++][r] = CharToPiece(next, gs->variant);\r
+ else if (next != '/') {\r
+ int t = (next - '0');\r
+ if(*FENpos >= '0' && *FENpos <= '9') // [HGM] can be double-digit\r
+ t = 10*t + *(FENpos++) - '0';\r
+ do\r
+ gs->board[f++][r] = NOPIECE;\r
+ while (--t && f < gs->files);\r
+ }\r
+ }\r
+ }\r
+ if (*(FENpos + 1) == 'w') /* the char after the space */\r
+ gs->onMove = WHITE;\r
+ else\r
+ gs->onMove = BLACK;\r
}
/* converts a board to a FEN pos */
static void board_to_FEN(char* FENpos, struct game_state_t* gs)
{
- int f,r,count;
- char piece;
-
- for (r=7; r>=0; r--) {
- count = 0;
- for (f=0; f<8; f++) {
- if ((piece = PieceToChar(gs->board[f][r])) != ' ') {
- if (count) {
- *(FENpos++) = count + '0';
- count = 0;
- }
- *(FENpos++) = piece;
- } else {
- if (f == 7)
- *(FENpos++) = count + '0' + 1;
- else
- count++;
- }
- }
- *(FENpos++) = '/';
- }
-
- *(--FENpos) = ' ';
-
- if (gs->onMove == WHITE)
- *(++FENpos) = 'w';
- else
- *(++FENpos) = 'b';
- *(++FENpos) = '\0';
+ int f,r,count;\r
+ char piece; \r
+\r
+ for (r=gs->ranks-1; r>=0; r--) {\r
+ count = 0;\r
+ for (f=0; f<gs->files; f++) {\r
+ if ((piece = PieceToChar(gs->board[f][r])) != ' ') {\r
+ if (count) { \r
+ if(count > 9) { count -= 10; *(FENpos++) = '1'; }\r
+ *(FENpos++) = count + '0';\r
+ count = 0;\r
+ }\r
+ *(FENpos++) = piece;\r
+ } else {\r
+ if (f == gs->files-1) {\r
+ if(count > 8) { count -= 10; *(FENpos++) = '1'; }\r
+ *(FENpos++) = count + '0' + 1;\r
+ } else\r
+ count++;\r
+ }\r
+ }\r
+ *(FENpos++) = '/';\r
+ }\r
+\r
+ *(--FENpos) = ' ';\r
+\r
+ if (gs->onMove == WHITE)\r
+ *(++FENpos) = 'w';\r
+ else\r
+ *(++FENpos) = 'b';\r
+ *(++FENpos) = '\0';\r
}
char *boardToFEN(int g)
const char *TypeStrings[NUM_GAMETYPES] = {"untimed", "blitz", "standard",
"nonstandard", "wild", "lightning",
- "bughouse"};
+ "bughouse", "gothic", "knightmate",
+ "capablanca"};
/* this method is awful! how about allocation as we need it and freeing
afterwards! */
return tstr;
}
-const char *bstr[] = {"untimed", "blitz", "standard", "non-standard", "wild", "lightning", "Bughouse"};
+const char *bstr[] = {"untimed", "blitz", "standard", "non-standard", "wild", "lightning", "Bughouse", "Gothic", "Knightmate", "Capablanca"};
const char *rstr[] = {"unrated", "rated"};
if(cat && cat[0]) {
if (!strcmp(cat, "bughouse"))
return TYPE_BUGHOUSE;
+ if (!strcmp(cat, "gothic"))
+ return TYPE_GOTHIC;
+ if (!strcmp(cat, "knightmate"))
+ return TYPE_KNIGHTMATE;
+ if (!strcmp(cat, "capablanca"))
+ return TYPE_CAPABLANCA;
if (board && board[0]) {
if (!strcmp(cat, "wild"))
return TYPE_WILD;
if ((game_globals.garray[g].status != GAME_SETUP) &&
(check_kings(&game_globals.garray[g].game_state))) {
- d_printf( "Game has invalid amount of kings. Aborting...\n");
+ d_printf( "Game has invalid number of kings. Aborting...\n");
+{ int f, r;
+d_printf("files = %d, ranks = %d\n", game_globals.garray[g].game_state.files, game_globals.garray[g].game_state.ranks);
+for(r=0; r<game_globals.garray[g].game_state.ranks; r++) {
+ for(f=0; f<game_globals.garray[g].game_state.files; f++)
+ d_printf("b[%d][%d]=%d\n",f,r,game_globals.garray[g].game_state.board[f][r]);
+}
+}
game_finish(g);
for (p = 0; p < player_globals.p_num; p++) {
sprintf(endstr, "%s checkmated",
game_globals.garray[g].winner == WHITE ? blackguy : whiteguy);
break;
+ case END_BARE:
+ sprintf(endstr, "%s bared",
+ game_globals.garray[g].winner == WHITE ? blackguy : whiteguy);
+ break;
case END_RESIGN:
sprintf(endstr, "%s resigned",
game_globals.garray[g].winner == WHITE ? blackguy : whiteguy);
case END_RESIGN:
case END_FLAG:
case END_ADJWIN:
+ case END_BARE:
return ((game_globals.garray[g].winner == WHITE) ? symbols[0] : symbols[1]);
break;
case END_AGREEDDRAW:
"\n[Event \"%s %s %s game\"]\n"
"[Site \"%s, %s\"]\n",
config_get_tmp("SERVER_NAME"),
- rstr[game_globals.garray[g].rated], bstr[game_globals.garray[g].type],
+ rstr[game_globals.garray[g].rated], /*bstr[game_globals.garray[g].type],*/
+ game_globals.garray[g].variant, // [HGM] allow more variation in game_types
config_get_tmp("SERVER_NAME"),
config_get_tmp("SERVER_LOCATION"));
strftime(tmp, sizeof(tmp),
"[BlackElo \"%d\"]\n",
game_globals.garray[g].white_name, game_globals.garray[g].black_name, wr, br);
strcat(gameString, tmp);
+ if(game_globals.garray[g].game_state.variant[0]) { // [HGM] variant: print variant tag
+ sprintf(tmp,
+ "[Variant \"%s\"]\n",
+ game_globals.garray[g].game_state.variant);
+ strcat(gameString, tmp);
+ }
+ if(game_globals.garray[g].game_state.setup) { // [HGM] setup: print the FEN
+ sprintf(tmp,
+ "[Setup \"1\"]\n"
+ "[FEN \"%s\"]\n",
+ game_globals.garray[g].FENstartPos);
+ strcat(gameString, tmp);
+ }
sprintf(tmp,
"[TimeControl \"%d+%d\"]\n"
"[Mode \"ICS\"]\n"
col = 0;
}
strcat(gameString, tmp);
+ if(moves[i].depth > 0) { // [HGM] computer game, add {score/depth} comment
+ if ((col += sprintf(tmp, "{%s%.2f/%d} ", moves[i].score > 0 ? "+" : "",
+ moves[i].score, moves[i].depth)) > 70) {
+ strcat(gameString, "\n");
+ col = 0;
+ }
+ strcat(gameString, tmp);
+ }
}
strcat(gameString, "\n");
} else {
strcat(gameString, "\nUnrated ");
}
- strcat (gameString, TypeStrings[game_globals.garray[g].type]);
+// strcat (gameString, TypeStrings[game_globals.garray[g].type]);
+ strcat (gameString, game_globals.garray[g].variant);
strcat(gameString, " match, initial time: ");
if ((game_globals.garray[g].bInitTime != game_globals.garray[g].wInitTime) || (game_globals.garray[g].wIncrement != game_globals.garray[g].bIncrement)) { /* different starting times */
sprintf(tmp, "%d minutes, increment: %d seconds AND %d minutes, increment: %d seconds.\n\n", game_globals.garray[g].wInitTime / 600, game_globals.garray[g].wIncrement / 10, game_globals.garray[g].bInitTime / 600, game_globals.garray[g].bIncrement / 10);
sprintf(tmp, "%d minutes, increment: %d seconds.\n\n", game_globals.garray[g].wInitTime / 600, game_globals.garray[g].wIncrement / 10);
}
strcat(gameString, tmp);
+ if(game_globals.garray[g].game_state.setup) { // [HGM] setup: print the initial position board
+ char *q; struct game_state_t initial_gs; struct move_t ml[600]; int r, f;
+
+ initial_gs.gameNum = g;
+ initial_gs.wkrmoved = 0; // [HGM] for some reason calling reset_board_vars() does not work here
+ initial_gs.wqrmoved = 0; // so I just duplicated the code and pasted it here...
+ initial_gs.wkmoved = 0;
+ initial_gs.bkrmoved = 0;
+ initial_gs.bqrmoved = 0;
+ initial_gs.bkmoved = 0;
+ initial_gs.onMove = WHITE;
+ initial_gs.lastIrreversable = -1;
+ initial_gs.files = game_globals.garray[g].game_state.files;
+ initial_gs.ranks = game_globals.garray[g].game_state.ranks;
+ initial_gs.holdings = game_globals.garray[g].game_state.holdings;
+ strcpy(initial_gs.variant, game_globals.garray[g].game_state.variant);
+ for (f = 0; f < 2; f++) {
+ for (r = 0; r < initial_gs.files; r++)
+ initial_gs.ep_possible[f][r] = 0;
+ for (r = PAWN; r <= QUEEN; r++)
+ initial_gs.holding[f][r-PAWN] = 0;
+ }
+ FEN_to_board(game_globals.garray[g].FENstartPos ,&initial_gs);
+
+ kludgeFlag = 1; // [HGM] setup: this is not thread safe. Must it be???
+ q = board_to_string(
+ game_globals.garray[g].white_name,
+ game_globals.garray[g].black_name,
+ game_globals.garray[g].wTime,
+ game_globals.garray[g].bTime,
+ &initial_gs,
+ ml,
+ 11,
+ WHITE, 0, 0);
+ kludgeFlag = 0;
+
+ strcat(gameString, q);
+ strcat(gameString, "\n");
+ }
sprintf(tmp, "Move %-19s%-19s\n", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
strcat(gameString, tmp);
strcat(gameString, "---- ---------------- ----------------\n");
game_ended(g, (game_globals.garray[g].white == p) ? WHITE : BLACK, END_LOSTCONNECTION);
}
-int CharToPiece(char c)
+int CharToPiece(char c, char *variant)
{
+
+ if(variant) {
+ if(!strcmp(variant, "shogi")) {
+ switch(c) {
+ case 'N':
+ return W_HONORABLEHORSE;
+ case 'n':
+ return B_HONORABLEHORSE;
+ case 'L':
+ return W_LANCE;
+ case 'l':
+ return B_LANCE;
+ case 'S':
+ return W_SILVER;
+ case 's':
+ return B_SILVER;
+ case 'G':
+ return W_GOLD;
+ case 'g':
+ return B_GOLD;
+ }
+ } else if(!strcmp(variant, "xiangqi")) {
+ switch(c) {
+ case 'A':
+ return W_MANDARIN;
+ case 'a':
+ return B_MANDARIN;
+ case 'H':
+ return W_HORSE;
+ case 'h':
+ return B_HORSE;
+ case 'C':
+ return W_CANNON;
+ case 'c':
+ return B_CANNON;
+ }
+ } else if(!strcmp(variant, "super")) {
+ switch(c) {
+ case 'E':
+ return W_EMPRESS;
+ case 'e':
+ return B_EMPRESS;
+ case 'S':
+ return W_PRINCESS;
+ case 's':
+ return B_PRINCESS;
+ case 'Z':
+ return W_AMAZON;
+ case 'z':
+ return B_AMAZON;
+ case 'V':
+ return W_CENTAUR;
+ case 'v':
+ return B_CENTAUR;
+ }
+ }
+ }
switch (c) {
case 'P':
return W_PAWN;
return W_ROOK;
case 'r':
return B_ROOK;
+ case 'A':
+ return W_CARDINAL;
+ case 'a':
+ return B_CARDINAL;
+ case 'C':
+ return W_MARSHALL;
+ case 'c':
+ return B_MARSHALL;
+ case 'M':
+ return W_MAN;
+ case 'm':
+ return B_MAN;
case 'Q':
return W_QUEEN;
case 'q':
return B_QUEEN;
+ case 'E':
+ return W_ELEPHANT;
+ case 'e':
+ return B_ELEPHANT;
case 'K':
return W_KING;
case 'k':
case B_PAWN:
return 'p';
case W_KNIGHT:
+ case W_HONORABLEHORSE:
return 'N';
case B_KNIGHT:
+ case B_HONORABLEHORSE:
return 'n';
case W_BISHOP:
return 'B';
return 'R';
case B_ROOK:
return 'r';
+ case W_CARDINAL:
+ case W_MANDARIN:
+ case W_ALFIL2:
+ return 'A';
+ case B_CARDINAL:
+ case B_MANDARIN:
+ case B_ALFIL2:
+ return 'a';
+ case W_CANNON:
+ case W_MARSHALL:
+ return 'C';
+ case B_CANNON:
+ case B_MARSHALL:
+ return 'c';
+ case W_MAN:
+ case W_MINISTER:
+ return 'M';
+ case B_MAN:
+ case B_MINISTER:
+ return 'm';
case W_QUEEN:
return 'Q';
case B_QUEEN:
return 'q';
+ case W_ELEPHANT:
+ case W_EMPRESS:
+ return 'E';
+ case B_ELEPHANT:
+ case B_EMPRESS:
+ return 'e';
+ case W_ALFIL:
+ return 'B';
+ case B_ALFIL:
+ return 'b';
+ case W_FERZ:
+ return 'Q';
+ case B_FERZ:
+ return 'q';
+ case W_FERZ2:
+ return 'F';
+ case B_FERZ2:
+ return 'f';
+ case W_WAZIR:
+ case W_WOODY:
+ return 'W';
+ case B_WAZIR:
+ case B_WOODY:
+ return 'w';
+ case W_HORSE:
+ case W_PRIESTESS:
+ case W_NIGHTRIDER:
+ return 'H';
+ case B_HORSE:
+ case B_PRIESTESS:
+ case B_NIGHTRIDER:
+ return 'h';
+ case W_SILVER:
+ case W_PRINCESS:
+ case W_MAN2:
+ return 'S';
+ case B_SILVER:
+ case B_PRINCESS:
+ case B_MAN2:
+ return 's';
+ case W_GOLD:
+ case W_MASTODON:
+ return 'G';
+ case B_GOLD:
+ case B_MASTODON:
+ return 'g';
+ case W_AMAZON:
+ return 'Z';
+ case B_AMAZON:
+ return 'z';
+ case W_CENTAUR:
+ return 'V';
+ case B_CENTAUR:
+ return 'v';
case W_KING:
return 'K';
case B_KING:
return 'k';
+ case W_LANCE:
+ return 'L';
+ case B_LANCE:
+ return 'l';
default:
return ' ';
}
if (game_globals.garray[g].type == TYPE_BLITZ) {
game_globals.garray[g].white_rating = player_globals.parray[wp].b_stats.rating;
game_globals.garray[g].black_rating = player_globals.parray[bp].b_stats.rating;
- } else if (game_globals.garray[g].type == TYPE_WILD) {
+ } else if (game_globals.garray[g].type == TYPE_WILD ||
+ game_globals.garray[g].type == TYPE_KNIGHTMATE ||
+ game_globals.garray[g].type == TYPE_CAPABLANCA ||
+ game_globals.garray[g].type == TYPE_GOTHIC) {
game_globals.garray[g].white_rating = player_globals.parray[wp].w_stats.rating;
game_globals.garray[g].black_rating = player_globals.parray[bp].w_stats.rating;
} else if (game_globals.garray[g].type == TYPE_LIGHT) {
if (!fp) {
return -1;
}
- for (piece=PAWN; piece <= QUEEN; piece++) {
+ for (piece=PAWN; piece < KING; piece++) {
game_globals.garray[g].game_state.holding[0][piece-PAWN]
= game_globals.garray[g].game_state.holding[1][piece-PAWN] = 0;
}
wr = player_globals.parray[wp].b_stats.rating;
br = player_globals.parray[bp].b_stats.rating;
type[1] = 'b';
- } else if (game_globals.garray[g].type == TYPE_WILD) {
+ } else if (game_globals.garray[g].type == TYPE_WILD ||
+ game_globals.garray[g].type == TYPE_KNIGHTMATE ||
+ game_globals.garray[g].type == TYPE_GOTHIC) {
wr = player_globals.parray[wp].w_stats.rating;
br = player_globals.parray[bp].w_stats.rating;
type[1] = 'w';
int f, r;
- for (f = 0; f < 8; f++) {
- for (r = 0; r < 8; r++) {
+ for (f = 0; f < gs->files; f++) {
+ for (r = 0; r < gs->ranks; r++) {
if (gs->board[f][r] == B_KING) blackking++;
if (gs->board[f][r] == W_KING) whiteking++;
}
/* Do not change the order of these - DAV */
GENSTRUCT enum gametype {TYPE_UNTIMED, TYPE_BLITZ, TYPE_STAND, TYPE_NONSTANDARD,
- TYPE_WILD, TYPE_LIGHT, TYPE_BUGHOUSE};
+ TYPE_WILD, TYPE_LIGHT, TYPE_BUGHOUSE, TYPE_GOTHIC, TYPE_KNIGHTMATE, TYPE_CAPABLANCA};
-#define NUM_GAMETYPES 7
+#define NUM_GAMETYPES 10
/* OK, DAV, I'll try it another way. -- hersco */
enum ratetype {RATE_STAND, RATE_BLITZ, RATE_WILD, RATE_LIGHT, RATE_BUGHOUSE};
END_ADJDRAW,
END_ADJWIN,
END_ADJABORT,
- END_COURTESYADJOURN
+ END_COURTESYADJOURN,
+ END_BARE // [HGM] bare king
};
struct journal {
char black_name[MAX_LOGIN_NAME]; _NULLTERM
int white_rating;
int black_rating;
+ char variant[80]; // [HGM] arbitrary variant name for sending to interface, derived from load-directory name
};
extern const char *TypeStrings[NUM_GAMETYPES];
for (i = 0; i < 8; i++)
for (j = 0; j < 8; j++) {
pieceChar = getc(fp);
- gs->board[i][j] = CharToPiece(pieceChar);
+ gs->board[i][j] = CharToPiece(pieceChar, NULL);
}
}
if (fscanf(fp, "%d %d %d %d %d %d",
strcpy(EndSymbol, "Mat");
rate_change = 1;
break;
+ case END_BARE:
+ sprintf(tmp, "%s bared} %s", NameOfLoser, winSymbol);
+ strcpy(EndSymbol, "Bar");
+ rate_change = 1;
+ break;
case END_RESIGN:
sprintf(tmp, "%s resigns} %s", NameOfLoser, winSymbol);
strcpy(EndSymbol, "Res");
pprintf (p,"\n%s",avail_black);
avail_printed = 1;
}
- if (gl != -1) /* bughouse ? */ {
+ if (gl == -1) /* bughouse ? */ {
if (((player_globals.parray[game_globals.garray[gl].white].b_stats.rating <= pp->availmax) && (player_globals.parray[game_globals.garray[gl].white].b_stats.rating >= pp->availmin)) || (!pp->availmax)) {
pprintf (p,"\n%s",avail_bugwhite);
avail_printed = 1;
}
if ((len = strlen(command)) > 1) {
if (command[len - 2] == '=') {
+printf("promo '%s'\n", command);
switch (tolower(command[strlen(command) - 1])) {
case 'n':
pp->promote = KNIGHT;
case 'r':
pp->promote = ROOK;
break;
+ case 'a':
+ pp->promote = CARDINAL;
+ break;
+ case 'c':
+ pp->promote = MARSHALL;
+ break;
+ case 'm':
+ pp->promote = MAN;
+ break;
case 'q':
pp->promote = QUEEN;
break;
+ // courier promotion
+ case 'f':
+ pp->promote = FERZ2;
+ break;
+ // Superchess promotions
+ case 'e':
+ pp->promote = EMPRESS;
+ break;
+ case 's':
+ pp->promote = PRINCESS;
+ break;
+ case 'v':
+ pp->promote = CENTAUR;
+ break;
+ case 'w':
+ pp->promote = WOODY;
+ break;
+ case 'o':
+ pp->promote = SQUIRREL;
+ break;
+ case 'g':
+ pp->promote = MASTODON;
+ break;
default:
pprintf(p, "Don't understand that move.\n");
return;
}
}
}
+
switch (parse_move(command, &gg->game_state, &move, pp->promote)) {
case MOVE_ILLEGAL:
pprintf(p, "Illegal move.\n");
gg->moveList = (struct move_t *) realloc(gg->moveList, sizeof(struct move_t) * gg->moveListSize);
}
result = execute_move(&gg->game_state, &move, 1);
- if (result == MOVE_OK && gg->link >= 0 && move.pieceCaptured != NOPIECE) {
+ if (result == MOVE_OK && (gg->link >= 0 || gg->game_state.holdings) && move.pieceCaptured != NOPIECE) {
/* transfer captured piece to partner */
/* check if piece reverts to a pawn */
+ int victim = move.pieceCaptured, partner = gg->link;
+ // [HGM] zh: if not Bughouse, the game_state.holdings field decides what happens
+ if(gg->link < 0) {
+ partner = g; // pieces stay with current board
+ if(gg->game_state.holdings == -1) victim ^= WHITE|BLACK; // flip color
+ }
if (was_promoted(&game_globals.garray[g], move.toFile, move.toRank))
- update_holding(gg->link, colorval(move.pieceCaptured) | PAWN);
+ update_holding(partner, colorval(victim) | PAWN); // [HGM] todo: for Shogi we would have to demote differently!
else
- update_holding(gg->link, move.pieceCaptured);
+ update_holding(partner, victim);
}
now = tenth_secs();
move.atTime = now;
game_ended(g, CToggle(gg->game_state.onMove), END_NOMATERIAL);
}
}
+ if (result == MOVE_BARE) {
+ if (gg->status == GAME_EXAMINE) {
+ int p1;
+
+ for (p1 = 0; p1 < player_globals.p_num; p1++) {
+ if (player_globals.parray[p1].status != PLAYER_PROMPT)
+ continue;
+ if (player_is_observe(p1, g) || player_globals.parray[p1].game == g) {
+ pprintf(p1, "%s bared.\n",
+ (gg->game_state.onMove == BLACK) ? "White" : "Black");
+ }
+ }
+ } else {
+ game_ended(g, gg->game_state.onMove, END_BARE);
+ }
+ }
}
int com_resign(int p, param_list param)
int piece;
int minor_pieces = 0;
- for (i = 0; i < 8; i++)
- for (j = 0; j < 8; j++) {
+ for (i = 0; i < gs->files; i++)
+ for (j = 0; j < gs->ranks; j++) {
piece = gs->board[i][j];
switch (piecetype(piece)) {
case BISHOP:
#include "includes.h"
-static const char *help_dir[NUM_LANGS] = {HELP_DIR, HELP_SPANISH,
+const char *help_dir[NUM_LANGS] = {HELP_DIR, HELP_SPANISH,
HELP_FRENCH, HELP_DANISH};
#include "includes.h"
const char *colorstr[] = {"", "[black] ", "[white] "};
-static const char *adjustr[] = {"", " (adjourned)"};
+const char *adjustr[] = {"", " (adjourned)"};
static void prepare_match(int g,int wt,int bt,int winc,int binc,int wp, int bp,int rated)
{
player_globals.parray[bp].name,
game_globals.garray[g].black_rating,
rstr[game_globals.garray[g].rated],
- bstr[game_globals.garray[g].type],
+ //bstr[game_globals.garray[g].type],
+ game_globals.garray[g].variant,
game_globals.garray[g].wInitTime,
game_globals.garray[g].wIncrement);
pprintf(wp, "%s", outStr);
player_globals.parray[bp].name,
mess,
rstr[game_globals.garray[g].rated],
- bstr[game_globals.garray[g].type]);
+ //bstr[game_globals.garray[g].type]);
+ game_globals.garray[g].variant);
pprintf(wp, "%s", outStr);
pprintf(bp, "%s", outStr);
decline_withdraw_offers(white_player, -1, PEND_SIMUL,
DO_WITHDRAW | DO_DECLINE);
}
+ game_globals.garray[g].FENstartPos[0] = 0; // [HGM] new shuffle
if (board_init(g,&game_globals.garray[g].game_state, category, board)) {
pprintf(white_player, "PROBLEM LOADING BOARD. Game Aborted.\n");
pprintf(black_player, "PROBLEM LOADING BOARD. Game Aborted.\n");
else
game_globals.garray[g].type = game_isblitz(wt, winc, bt, binc, category, board);
+ if(category && category[0]) { // [HGM] set variant string from directory for games loaded from file
+ if(!strcmp(category, "wild") && board)
+ sprintf(game_globals.garray[g].variant, "%s/%s", category, board);
+ else
+ strcpy(game_globals.garray[g].variant, category);
+ }
+ else
+ strcpy(game_globals.garray[g].variant, bstr[game_globals.garray[g].type]);
+
prepare_match(g,wt,bt,winc,binc,white_player,black_player,rated);
output_match_messages(white_player,black_player,g, "Creating");
} else {
strcpy(category,parsebuf);
if (!strncmp("bughouse",category, strlen(category))
- && strlen(category) >= 3) {
+ && strlen(category) >= 3 || !strcmp("bh", category)) {
strcpy(category, "bughouse");
bughouse = 1;
}
+ // [HGM] allow some shortcuts for variant names
+ if(!strcmp("bh", category)) {
+ strcpy(category, "bughouse");
+ } else
+ if(!strcmp("zh", category)) {
+ strcpy(category, "crazyhouse");
+ } else
+ if(!strcmp("fr", category)) {
+ strcpy(category, "fischerandom");
+ } else
+ if(!strcmp("sj", category)) {
+ strcpy(category, "shatranj");
+ } else
+ if(!strcmp("gc", category)) {
+ strcpy(category, "gothic");
+ } else
+ if(!strcmp("ca", category)) {
+ strcpy(category, "capablanca");
+ } else
+ if(!strcmp("cr", category)) {
+ strcpy(category, "caparandom");
+ } else
+ if(!strcmp("su", category)) {
+ strcpy(category, "super");
+ } else
+ if(!strcmp("sg", category)) {
+ strcpy(category, "shogi");
+ } else
+ if(!strcmp("km", category)) {
+ strcpy(category, "knightmate");
+ } else
+ if(!strcmp("gr", category)) {
+ strcpy(category, "great");
+ } else
+ if(!strcmp("xq", category)) {
+ strcpy(category, "xiangqi");
+ }
}
} else
confused = 1;
pprintf(p, "Can't interpret %s in match command.\n", parsebuf);
return 0;
}
+ if(category && (!board || !board[0]))
+ strcpy(board, "0"); // [HGM] variants: always provide default board
return 1;
}
#include "includes.h"
+// [HGM] some explanation of the parser code:
+// The routine parse_move() calls is_move() to recognize some simple cases,
+// like OO-castle and long algebraic with or without dash. What does not fall
+// in this class is handed to alg_is_move(), whch is really a continuation
+// of is_move(), to recognize SAN.
+// Depending on the type of move syntax, parse_move can extract from- and to-square
+// immediately, or transate the OO-castling to internal from-to representation.
+// Only for SAN syntax the routine alg_pars_move() is called to extract the
+// given elements, (through get_move_info(), which is the same as alg_is_move(),
+// xcept that it does not discard the value of the elements), and disambiguate
+// the move (i.e. determines the from-square) by looking for a piece of the given
+// type on the board for which the move is pseudo-legal (using legal_move() ).
+// Th
+
/* Simply tests if the input string is a move or not. */
/* If it matches patterns below */
/* Add to this list as you improve the move parser */
}
-int NextPieceLoop(board_t b, int *f, int *r, int color)
+int NextPieceLoop(board_t b, int *f, int *r, int color, int w, int h)
{
for (;;) {
(*r) = (*r) + 1;
- if (*r > 7) {
+ if (*r >= h) {
*r = 0;
*f = *f + 1;
- if (*f > 7)
+ if (*f >= w)
break;
}
if ((b[*f][*r] != NOPIECE) && iscolor(b[*f][*r], color))
/* See legal_move() */
static int legal_pawn_move( struct game_state_t *gs, int ff, int fr, int tf, int tr )
{
- if (ff == tf) {
- if (gs->board[tf][tr] != NOPIECE) return 0;
- if (gs->onMove == WHITE) {
- if (tr - fr == 1) return 1;
- if ((fr == 1) && (tr - fr == 2) && gs->board[ff][2]==NOPIECE) return 1;
- } else {
- if (fr - tr == 1) return 1;
- if ((fr == 6) && (fr - tr == 2) && gs->board[ff][5]==NOPIECE) return 1;
- }
- return 0;
- }
+ if (ff == tf) {\r
+ if (gs->board[tf][tr] != NOPIECE && !gs->palace) return 0; // [HGM] XQ pawns can capture straight ahead\r
+ if (gs->onMove == WHITE) {\r
+ if (tr - fr == 1) return 1;\r
+ if ((fr <= gs->pawnDblStep) && (tr - fr == 2) && gs->board[ff][fr+1]==NOPIECE) return 1;
+ } else {\r
+ if (fr - tr == 1) return 1;\r
+ if ((fr >= gs->ranks - 1 - gs->pawnDblStep) && (fr - tr == 2) && gs->board[ff][fr-1]==NOPIECE) return 1;\r
+ }\r
+ return 0;\r
+ }\r
if (ff != tf) { /* Capture ? */
if ((ff - tf != 1) && (tf - ff != 1)) return 0;
- if ((fr - tr != 1) && (tr - fr != 1)) return 0;
if (gs->onMove == WHITE) {
- if (fr > tr) return 0;
+ if(gs->palace) return (fr >= gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns\r
+ if (tr != fr+1) return 0;
if ((gs->board[tf][tr] != NOPIECE) && iscolor(gs->board[tf][tr],BLACK))
return 1;
if (gs->ep_possible[0][ff] == 1) {
if ((tf==ff-1) && (gs->board[ff-1][fr] == B_PAWN)) return 1;
}
} else {
- if (tr > fr) return 0;
+ if(gs->palace) return (fr < gs->ranks/2 && fr == tr); // [HGM] XQ promoted pawns\r
+ if (tr != fr-1) return 0;
if ((gs->board[tf][tr] != NOPIECE) && iscolor(gs->board[tf][tr],WHITE))
return 1;
if (gs->ep_possible[1][ff] == 1) {
return 0;
}
+static int legal_horse_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
+{
+ int dx, dy;
+
+ dx = ff - tf;
+ dy = fr - tr;
+ if (abs(dx) == 2) {
+ if (abs(dy) == 1 && gs->board[(ff+tf)/2][fr] == NOPIECE)
+ return 1;
+ }
+ if (abs(dy) == 2) {
+ if (abs(dx) == 1 && gs->board[ff][(fr+tr)/2] == NOPIECE)
+ return 1;
+ }
+ return 0;
+}
+
+static int legal_honorablehorse_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
+{
+ int dx, dy;
+
+ dx = ff - tf;
+ dy = fr - tr;
+ if (dy == gs->onMove == WHITE ? 2 : -2) {
+ if (abs(dx) == 1)
+ return 1;
+ }
+ return 0;
+}
+
static int legal_bishop_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
{
int dx, dy, x, y;
}
}
+static int legal_cannon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
+{
+ int i, cnt=0;
+ int start, stop;
+
+ if (ff == tf) {
+ if (fr < tr) {
+ start = fr + 1;
+ stop = tr - 1;
+ } else {
+ start = tr + 1;
+ stop = fr - 1;
+ }
+ for (i = start; i <= stop; i++) {
+ if (gs->board[ff][i] != NOPIECE) cnt++;
+ }
+ return (cnt == 0 && gs->board[tf][tr] == NOPIECE) ||
+ (cnt == 1 && gs->board[tf][tr] != NOPIECE);
+ } else if (fr == tr) {
+ if (ff < tf) {
+ start = ff + 1;
+ stop = tf - 1;
+ } else {
+ start = tf + 1;
+ stop = ff - 1;
+ }
+ for (i = start; i <= stop; i++) {
+ if (gs->board[i][fr] != NOPIECE) cnt++;
+ }
+ return (cnt == 0 && gs->board[tf][tr] == NOPIECE) ||
+ (cnt == 1 && gs->board[tf][tr] != NOPIECE);
+ } else {
+ return 0;
+ }
+}
+
+static int legal_lance_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
+{
+ int i;
+ int start, stop;
+
+ if (ff == tf) {
+ if (abs(fr - tr) == 1)
+ return 1;
+ if (fr < tr) {
+ if(gs->onMove != WHITE) return 0;
+ start = fr + 1;
+ stop = tr - 1;
+ } else {
+ if(gs->onMove == WHITE) return 0;
+ start = tr + 1;
+ stop = fr - 1;
+ }
+ for (i = start; i <= stop; i++) {
+ if (gs->board[ff][i] != NOPIECE)
+ return 0;
+ }
+ return 1;
+ }
+}
+
static int legal_queen_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
{
return legal_rook_move(gs, ff, fr, tf, tr) || legal_bishop_move(gs, ff, fr, tf, tr);
}
+static int legal_cardinal_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_knight_move(gs, ff, fr, tf, tr) || legal_bishop_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_marshall_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_rook_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
/* Ckeck, if square (kf,kr) is attacked by enemy piece.
* Used in castling from/through check testing.
*/
static int is_square_attacked (struct game_state_t *gs, int kf, int kr)
{
struct game_state_t fakeMove;
+ int oldk = gs->onMove == WHITE ? gs->wkmoved : gs->bkmoved;
fakeMove = *gs;
- fakeMove.board[4][kr] = NOPIECE;
+ fakeMove.board[oldk][kr] = NOPIECE; // [HGM] castle: this routine is called only when King has not moved\r
fakeMove.board[kf][kr] = KING | fakeMove.onMove;
fakeMove.onMove = CToggle (fakeMove.onMove);
if (in_check(&fakeMove)) return 1;
gs->onMove = CToggle(gs->onMove);
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
if (legal_move(gs, f, r, kf, kr)) {
gs->onMove = CToggle(gs->onMove);
return 1;
}
*/
+static int legal_man_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ if (abs(ff - tf) > 1)\r
+ return 0;\r
+ if (abs(fr - tr) > 1)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+static int legal_wazir_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ if(gs->palace && (tr > gs->palace && tr < gs->ranks - gs->palace ||
+ tf < (gs->files - gs->palace)/2 || tf >= (gs->files + gs->palace)/2))
+ return 0;\r
+ if (abs(ff - tf) == 1 && fr == tr)\r
+ return 1;\r
+ if (abs(fr - tr) == 1 && ff == tf)\r
+ return 1;\r
+ return 0;\r
+}\r
+\r
+static int legal_dababba_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ if (abs(ff - tf) == 2 && fr == tr)\r
+ return 1;\r
+ if (abs(fr - tr) == 2 && ff == tf)\r
+ return 1;\r
+ return 0;\r
+}\r
+\r
+static int legal_ferz_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ if (abs(ff - tf) != 1)\r
+ return 0;\r
+ if (abs(fr - tr) != 1)\r
+ return 0;\r
+ return 1;\r
+}\r
+
+static int legal_mandarin_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ if(gs->palace && (tr > gs->palace && tr < gs->ranks - gs->palace ||
+ tf < (gs->files - gs->palace)/2 || tf >= (gs->files + gs->palace)/2))
+ return 0;\r
+ if (abs(ff - tf) != 1)\r
+ return 0;\r
+ if (abs(fr - tr) != 1)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+static int legal_alfil_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{
+ if (abs(ff - tf) != 2)\r
+ return 0;\r
+ if (abs(fr - tr) != 2)\r
+ return 0;\r
+ return 1;\r
+}\r
+\r
+static int legal_elephant_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ if (abs(ff - tf) != 2)\r
+ return 0;\r
+ if (abs(fr - tr) != 2)\r
+ return 0;
+ if(gs->board[(ff+tf)/2][(fr+tr)/2] != NOPIECE) return 0; // blocked
+ if((tr >= gs->ranks/2) != (fr >= gs->ranks/2)) return 0; // do not cross river\r
+ return 1;\r
+}\r
+\r
+static int legal_gold_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_wazir_move(gs, ff, fr, tf, tr) || (abs(ff-tf) == 1 && tr == fr + (gs->onMove==WHITE ? 1 : -1));\r
+}\r
+\r
+static int legal_silver_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_ferz_move(gs, ff, fr, tf, tr) || (tf == ff && tr == fr + (gs->onMove==WHITE ? 1 : -1) );\r
+}\r
+\r
+static int legal_woody_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_wazir_move(gs, ff, fr, tf, tr) || legal_dababba_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_squirrel_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_alfil_move(gs, ff, fr, tf, tr) || legal_dababba_move(gs, ff, fr, tf, tr)
+ || legal_knight_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_mastodon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_man_move(gs, ff, fr, tf, tr) || legal_alfil_move(gs, ff, fr, tf, tr)
+ || legal_dababba_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_centaur_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_man_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_amazon_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_queen_move(gs, ff, fr, tf, tr) || legal_knight_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_dragonking_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_rook_move(gs, ff, fr, tf, tr) || legal_ferz_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_dragonhorse_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_bishop_move(gs, ff, fr, tf, tr) || legal_wazir_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_modernelephant_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_ferz_move(gs, ff, fr, tf, tr) || legal_alfil_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_priestess_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_knight_move(gs, ff, fr, tf, tr) || legal_ferz_move(gs, ff, fr, tf, tr)
+ || legal_alfil_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
+static int legal_minister_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)\r
+{\r
+ return legal_knight_move(gs, ff, fr, tf, tr) || legal_wazir_move(gs, ff, fr, tf, tr)
+ || legal_dababba_move(gs, ff, fr, tf, tr);\r
+}\r
+\r
static int legal_king_move(struct game_state_t * gs, int ff, int fr, int tf, int tr)
{
- if (gs->onMove == WHITE) {
- /* King side castling */
- if ((fr == 0) && (tr == 0) && (ff == 4) && (tf == 6) && !gs->wkmoved
- && (!gs->wkrmoved) && (gs->board[5][0] == NOPIECE) &&
- (gs->board[6][0] == NOPIECE) && (gs->board[7][0] == W_ROOK) &&
- (!is_square_attacked(gs, 4, 0)) && (!is_square_attacked(gs, 5, 0))) {
- return 1;
- }
- /* Queen side castling */
- if ((fr == 0) && (tr == 0) && (ff == 4) && (tf == 2) && !gs->wkmoved
- && (!gs->wqrmoved) && (gs->board[3][0] == NOPIECE) &&
- (gs->board[2][0] == NOPIECE) && (gs->board[1][0] == NOPIECE) &&
- (gs->board[0][0] == W_ROOK) &&
- (!is_square_attacked(gs, 4, 0)) && (!is_square_attacked(gs, 3, 0))) {
- return 1;
- }
- } else { /* Black */
- /* King side castling */
- if ((fr == 7) && (tr == 7) && (ff == 4) && (tf == 6) && !gs->bkmoved
- && (!gs->bkrmoved) && (gs->board[5][7] == NOPIECE) &&
- (gs->board[6][7] == NOPIECE) && (gs->board[7][7] == B_ROOK) &&
- (!is_square_attacked(gs, 4, 7)) && (!is_square_attacked(gs, 5, 7))) {
- return 1;
- }
- /* Queen side castling */
- if ((fr == 7) && (tr == 7) && (ff == 4) && (tf == 2) && (!gs->bkmoved)
- && (!gs->bqrmoved) && (gs->board[3][7] == NOPIECE) &&
- (gs->board[2][7] == NOPIECE) && (gs->board[1][7] == NOPIECE) &&
- (gs->board[0][7] == B_ROOK) &&
- (!is_square_attacked(gs, 4, 7)) && (!is_square_attacked(gs, 3, 7))) {
+ int result;
+
+ // [HGM] castle: test first if valid as regular King move; result = 1 or 0
+ if(gs->royalKnight)\r
+ result = legal_knight_move(gs, ff, fr, tf, tr);\r
+ else if(gs->palace) {
+ result = legal_wazir_move(gs, ff, fr, tf, tr);
+ if(!result && ff == tf && piecetype(gs->board[tf][tr]) == KING) { // XQ regicide
+ int i, d = (tr>fr ? 1 : -1);
+ for(i=fr+d; i!=tr; i+=d)
+ if(gs->board[ff][i] != NOPIECE) return 0; // line of sight blocked
return 1;
}
+ } else\r
+ result = legal_man_move(gs, ff, fr, tf, tr);
+
+ if(result) return 1;\r
+ // [HGM] castle: orthodox legal castlings given as King move return 2
+
+ if (gs->onMove == WHITE) {\r
+ /* King side castling */\r
+ if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->wkmoved >= 0)\r
+ && (gs->wkrmoved >= 0) && (gs->board[gs->files-3][0] == NOPIECE) &&\r
+ (gs->board[gs->files-2][0] == NOPIECE) && (gs->board[gs->files-1][0] == W_ROOK) &&\r
+ (gs->board[gs->files/2+1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, 0)) &&\r
+ (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, gs->files-3, 0))) {\r
+ return 2;\r
+ }\r
+ /* Queen side castling */\r
+ if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == 2) && (gs->wkmoved >= 0)\r
+ && (gs->wqrmoved >= 0) && (gs->board[3][0] == NOPIECE) &&\r
+ (gs->board[2][0] == NOPIECE) && (gs->board[1][0] == NOPIECE) &&\r
+ (gs->board[0][0] == W_ROOK) &&\r
+ (gs->board[gs->files/2-1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, 0)) &&\r
+ (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, 3, 0))) {\r
+ return 2;\r
+ }\r
+ } else { /* Black */\r
+ /* King side castling */\r
+ if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->bkmoved >= 0)\r
+ && (gs->bkrmoved >= 0) && (gs->board[gs->files-3][7] == NOPIECE) &&\r
+ (gs->board[gs->files-2][gs->ranks-1] == NOPIECE) && (gs->board[gs->files-1][gs->ranks-1] == B_ROOK) &&\r
+ (gs->board[gs->files/2+1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, gs->ranks-1)) &&\r
+ (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, gs->files-3, gs->ranks-1))) {\r
+ return 2;\r
+ }\r
+ /* Queen side castling */\r
+ if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == 2) && (gs->bkmoved >= 0)\r
+ && (gs->bqrmoved >= 0) && (gs->board[3][gs->ranks-1] == NOPIECE) &&\r
+ (gs->board[2][gs->ranks-1] == NOPIECE) && (gs->board[1][gs->ranks-1] == NOPIECE) &&\r
+ (gs->board[0][gs->ranks-1] == B_ROOK) &&\r
+ (gs->board[gs->files/2-1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, gs->ranks-1)) &&\r
+ (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, 3, gs->ranks-1))) {\r
+ return 2;\r
+ }\r
}
- if (abs(ff - tf) > 1)
- return 0;
- if (abs(fr - tr) > 1)
- return 0;
- return 1;
+\r
+ return 0; // neither regular King move nor castling
}
static void add_pos(int tof, int tor, int *posf, int *posr, int *numpos)
int onf, int onr,
int *posf, int *posr, int *numpos)
{
- if (gs->onMove == WHITE) {
- if (gs->board[onf][onr + 1] == NOPIECE) {
- add_pos(onf, onr + 1, posf, posr, numpos);
- if ((onr == 1) && (gs->board[onf][onr + 2] == NOPIECE))
- add_pos(onf, onr + 2, posf, posr, numpos);
- }
- if ((onf > 0) && (gs->board[onf - 1][onr + 1] != NOPIECE) &&
- (iscolor(gs->board[onf - 1][onr + 1], BLACK)))
- add_pos(onf - 1, onr + 1, posf, posr, numpos);
- if ((onf < 7) && (gs->board[onf + 1][onr + 1] != NOPIECE) &&
- (iscolor(gs->board[onf + 1][onr + 1], BLACK)))
+ if (gs->onMove == WHITE) {\r
+ if (gs->board[onf][onr + 1] == NOPIECE || gs->palace) {\r
+ add_pos(onf, onr + 1, posf, posr, numpos);\r
+ if ((onr <= gs->pawnDblStep) && (gs->board[onf][onr + 2] == NOPIECE))\r
+ add_pos(onf, onr + 2, posf, posr, numpos);\r
+ }\r
+ if (onf > 0) {
+ if (gs->board[onf - 1][onr + 1] != NOPIECE &&\r
+ iscolor(gs->board[onf - 1][onr + 1], BLACK))\r
+ add_pos(onf - 1, onr + 1, posf, posr, numpos);
+ if(gs->palace && onr >= gs->ranks/2 && (gs->board[onf-1][onr] || iscolor(gs->board[onf-1][onr], BLACK)))
+ add_pos(onf - 1, onr, posf, posr, numpos); // XQ promoted pawn
+ }\r
+ if (onf < gs->files-1) {
+ if (gs->board[onf + 1][onr + 1] != NOPIECE &&\r
+ iscolor(gs->board[onf + 1][onr + 1], BLACK))\r
+ add_pos(onf + 1, onr + 1, posf, posr, numpos);
+ if(gs->palace && onr >= gs->ranks/2 && (gs->board[onf+1][onr] || iscolor(gs->board[onf+1][onr], BLACK)))
+ add_pos(onf + 1, onr, posf, posr, numpos); // XQ promoted pawn
+ }\r
+ if (gs->ep_possible[0][onf] == -1)\r
+ add_pos(onf - 1, onr + 1, posf, posr, numpos);\r
+ if (gs->ep_possible[0][onf] == 1)\r
add_pos(onf + 1, onr + 1, posf, posr, numpos);
- if (gs->ep_possible[0][onf] == -1)
- add_pos(onf - 1, onr + 1, posf, posr, numpos);
- if (gs->ep_possible[0][onf] == 1)
- add_pos(onf + 1, onr + 1, posf, posr, numpos);
- } else {
- if (gs->board[onf][onr - 1] == NOPIECE) {
- add_pos(onf, onr - 1, posf, posr, numpos);
- if ((onr == 6) && (gs->board[onf][onr - 2] == NOPIECE))
- add_pos(onf, onr - 2, posf, posr, numpos);
- }
- if ((onf > 0) && (gs->board[onf - 1][onr - 1] != NOPIECE) &&
- (iscolor(gs->board[onf - 1][onr - 1], WHITE)))
- add_pos(onf - 1, onr - 1, posf, posr, numpos);
-/* loon: changed what looks like a typo, here's the original line:
- add_pos(onf - 1, onr + 1, posf, posr, numpos);
-*/
- if ((onf < 7) && (gs->board[onf + 1][onr - 1] != NOPIECE) &&
- (iscolor(gs->board[onf + 1][onr - 1], WHITE)))
- add_pos(onf + 1, onr - 1, posf, posr, numpos);
- if (gs->ep_possible[1][onf] == -1)
- add_pos(onf - 1, onr - 1, posf, posr, numpos);
- if (gs->ep_possible[1][onf] == 1)
- add_pos(onf + 1, onr - 1, posf, posr, numpos);
- }
+ } else {\r
+ if (gs->board[onf][onr - 1] == NOPIECE || gs->palace) {\r
+ add_pos(onf, onr - 1, posf, posr, numpos);\r
+ if ((onr >= gs->ranks - gs->pawnDblStep - 1) && (gs->board[onf][onr - 2] == NOPIECE))\r
+ add_pos(onf, onr - 2, posf, posr, numpos);\r
+ }\r
+ if (onf > 0) {
+ if (gs->board[onf - 1][onr - 1] != NOPIECE &&\r
+ iscolor(gs->board[onf - 1][onr - 1], WHITE))\r
+ add_pos(onf - 1, onr - 1, posf, posr, numpos);
+ if(gs->palace && onr < gs->ranks/2 && !iscolor(gs->board[onf-1][onr], BLACK))
+ add_pos(onf - 1, onr, posf, posr, numpos); // XQ promoted pawn
+ }\r
+ if (onf < gs->files-1) {
+ if (gs->board[onf + 1][onr - 1] != NOPIECE &&\r
+ iscolor(gs->board[onf + 1][onr - 1], WHITE))\r
+ add_pos(onf + 1, onr - 1, posf, posr, numpos);
+ if(gs->palace && onr < gs->ranks/2 && !iscolor(gs->board[onf+1][onr], BLACK))
+ add_pos(onf + 1, onr, posf, posr, numpos); // XQ promoted pawn
+ }\r
+ if (gs->ep_possible[1][onf] == -1)\r
+ add_pos(onf - 1, onr - 1, posf, posr, numpos);\r
+ if (gs->ep_possible[1][onf] == 1)\r
+ add_pos(onf + 1, onr - 1, posf, posr, numpos);\r
+ }\r
}
static void possible_knight_moves(struct game_state_t * gs,
int onf, int onr,
int *posf, int *posr, int *numpos)
{
- static int knightJumps[8][2] = {{-1, 2}, {1, 2}, {2, -1}, {2, 1},
- {-1, -2}, {1, -2}, {-2, 1}, {-2, -1}};
- int f, r;
- int j;
+ static int knightJumps[8][2] = {{-1, 2}, {1, 2}, {2, -1}, {2, 1},\r
+ {-1, -2}, {1, -2}, {-2, 1}, {-2, -1}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 8; j++) {\r
+ f = knightJumps[j][0] + onf;\r
+ r = knightJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;\r
+ if ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}
- for (j = 0; j < 8; j++) {
- f = knightJumps[j][0] + onf;
- r = knightJumps[j][1] + onr;
- if ((f < 0) || (f > 7))
- continue;
- if ((r < 0) || (r > 7))
- continue;
- if ((gs->board[f][r] == NOPIECE) ||
- (iscolor(gs->board[f][r], CToggle(gs->onMove))))
- add_pos(f, r, posf, posr, numpos);
- }
+static void possible_horse_moves(struct game_state_t * gs,
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ static int knightJumps[8][4] = {{-1, 2, 0, 1}, {1, 2, 0, 1}, {2, -1, 1, 0}, {2, 1, 1, 0},\r
+ {-1, -2, 0, -1}, {1, -2, 0, -1}, {-2, 1, -1, 0}, {-2, -1, -1, 0}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 8; j++) {\r
+ f = knightJumps[j][0] + onf;\r
+ r = knightJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;\r
+ if ((gs->board[knightJumps[j][2] + onf][knightJumps[j][3] + onr] == NOPIECE) &&
+ ((gs->board[f][r] == NOPIECE) || (iscolor(gs->board[f][r], CToggle(gs->onMove)))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
}
static void possible_bishop_moves(struct game_state_t * gs,
int onf, int onr,
int *posf, int *posr, int *numpos)
{
- int f, r;
-
- /* Up Left */
- f = onf;
- r = onr;
- for (;;) {
- f--;
- r++;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
- /* Up Right */
- f = onf;
- r = onr;
- for (;;) {
- f++;
- r++;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
- /* Down Left */
- f = onf;
- r = onr;
- for (;;) {
- f--;
- r--;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
- /* Down Right */
- f = onf;
- r = onr;
- for (;;) {
- f++;
- r--;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
+ int f, r;\r
+\r
+ /* Up Left */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ f--;\r
+ r++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Up Right */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ f++;\r
+ r++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Down Left */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ f--;\r
+ r--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Down Right */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ f++;\r
+ r--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
}
static void possible_rook_moves(struct game_state_t * gs,
int onf, int onr,
int *posf, int *posr, int *numpos)
{
- int f, r;
+ int f, r;\r
+\r
+ /* Left */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ f--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Right */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ f++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Up */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ r++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Down */\r
+ f = onf;\r
+ r = onr;\r
+ for (;;) {\r
+ r--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+}
- /* Left */
- f = onf;
- r = onr;
- for (;;) {
- f--;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
- /* Right */
- f = onf;
- r = onr;
- for (;;) {
- f++;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
- /* Up */
- f = onf;
- r = onr;
- for (;;) {
- r++;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
- /* Down */
- f = onf;
- r = onr;
- for (;;) {
- r--;
- if ((f < 0) || (f > 7))
- break;
- if ((r < 0) || (r > 7))
- break;
- if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))
- break;
- add_pos(f, r, posf, posr, numpos);
- if (gs->board[f][r] != NOPIECE)
- break;
- }
+static void possible_cannon_moves(struct game_state_t * gs,
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ int f, r, i;\r
+\r
+ /* Left */\r
+ f = onf;\r
+ r = onr;\r
+ for (i=0;;) {\r
+ f--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue;
+ if(i == 0)
+ add_pos(f, r, posf, posr, numpos); // no hop: non-capt
+ else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove))
+ add_pos(f, r, posf, posr, numpos); // hop: capt\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Right */\r
+ f = onf;\r
+ r = onr;\r
+ for (i=0;;) {\r
+ f++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue;
+ if(i == 0)
+ add_pos(f, r, posf, posr, numpos); // no hop: non-capt
+ else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove))
+ add_pos(f, r, posf, posr, numpos); // hop: capt\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Up */\r
+ f = onf;\r
+ r = onr;\r
+ for (i=0;;) {\r
+ r++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue;
+ if(i == 0)
+ add_pos(f, r, posf, posr, numpos); // no hop: non-capt
+ else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove))
+ add_pos(f, r, posf, posr, numpos); // hop: capt\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Down */\r
+ f = onf;\r
+ r = onr;\r
+ for (i=0;;) {\r
+ r--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && i++ == 0) continue;
+ if(i == 0)
+ add_pos(f, r, posf, posr, numpos); // no hop: non-capt
+ else if(i == 2 && !iscolor(gs->board[f][r], gs->onMove))
+ add_pos(f, r, posf, posr, numpos); // hop: capt\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
}
+static void possible_lance_moves(struct game_state_t * gs,
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ int f, r;\r
+\r
+ /* Up */\r
+ f = onf;\r
+ r = onr;\r
+ for (;gs->onMove == WHITE;) {\r
+ r++;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+ /* Down */\r
+ f = onf;\r
+ r = onr;\r
+ for (;gs->onMove == BLACK;) {\r
+ r--;\r
+ if ((f < 0) || (f >= gs->files))\r
+ break;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ break;\r
+ if ((gs->board[f][r] != NOPIECE) && (iscolor(gs->board[f][r], gs->onMove)))\r
+ break;\r
+ add_pos(f, r, posf, posr, numpos);\r
+ if (gs->board[f][r] != NOPIECE)\r
+ break;\r
+ }\r
+}
+
+static void possible_cardinal_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);\r
+ possible_bishop_moves(gs, onf, onr, posf, posr, numpos);\r
+}\r
+\r
+static void possible_marshall_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ possible_rook_moves(gs, onf, onr, posf, posr, numpos);\r
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);\r
+}\r
+\r
static void possible_queen_moves(struct game_state_t * gs,
int onf, int onr,
int *posf, int *posr, int *numpos)
possible_bishop_moves(gs, onf, onr, posf, posr, numpos);
}
+static void possible_alfil_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 4; j++) {\r
+ f = 2*kingJumps[j][0] + onf;\r
+ r = 2*kingJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;\r
+ if ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}\r
+\r
+static void possible_ferz_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 4; j++) {\r
+ f = kingJumps[j][0] + onf;\r
+ r = kingJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;
+ if ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}\r
+\r
+static void possible_mandarin_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 4; j++) {\r
+ f = kingJumps[j][0] + onf;\r
+ r = kingJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;
+ if(gs->palace && (r >= gs->palace && r < gs->ranks - gs->palace ||
+ f < (gs->files - gs->palace)/2 || f >= (gs->files + gs->palace)/2))
+ continue;\r
+ if ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}\r
+\r
+static void possible_wazir_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ static int kingJumps[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 4; j++) {\r
+ f = kingJumps[j][0] + onf;\r
+ r = kingJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;\r
+ if(gs->palace && (r >= gs->palace && r < gs->ranks - gs->palace ||
+ f < (gs->files - gs->palace)/2 || f >= (gs->files + gs->palace)/2))
+ continue;\r
+ if ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}\r
+\r
+static void possible_dababba_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ static int kingJumps[4][2] = {{0, -1}, {0, 1}, {-1, 0}, {1, 0}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 4; j++) {\r
+ f = 2*kingJumps[j][0] + onf;\r
+ r = 2*kingJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;\r
+ if ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}\r
+\r
+static void possible_man_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_wazir_moves(gs, onf, onr, posf, posr, numpos);
+ possible_ferz_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_dragonking_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_rook_moves(gs, onf, onr, posf, posr, numpos);
+ possible_ferz_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_dragonhorse_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_wazir_moves(gs, onf, onr, posf, posr, numpos);
+ possible_bishop_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_centaur_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_man_moves(gs, onf, onr, posf, posr, numpos);
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_woody_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_wazir_moves(gs, onf, onr, posf, posr, numpos);
+ possible_dababba_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_squirrel_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_alfil_moves(gs, onf, onr, posf, posr, numpos);
+ possible_dababba_moves(gs, onf, onr, posf, posr, numpos);
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_mastodon_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_man_moves(gs, onf, onr, posf, posr, numpos);
+ possible_alfil_moves(gs, onf, onr, posf, posr, numpos);
+ possible_dababba_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_amazon_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_queen_moves(gs, onf, onr, posf, posr, numpos);
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_modernelephant_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_ferz_moves(gs, onf, onr, posf, posr, numpos);
+ possible_alfil_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_priestess_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_ferz_moves(gs, onf, onr, posf, posr, numpos);
+ possible_alfil_moves(gs, onf, onr, posf, posr, numpos);
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_minister_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_wazir_moves(gs, onf, onr, posf, posr, numpos);
+ possible_dababba_moves(gs, onf, onr, posf, posr, numpos);
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);
+}
+
+static void possible_gold_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_wazir_moves(gs, onf, onr, posf, posr, numpos);
+ if(gs->onMove == WHITE) {
+ if(onr < gs->ranks-1)
+ if(onf > 0 && !iscolor(gs->board[onf-1][onr+1], WHITE))
+ add_pos(onf-1, onr+1, posf, posr, numpos);\r
+ if(onf < gs->files-1 && !iscolor(gs->board[onf+1][onr+1], WHITE))
+ add_pos(onf+1, onr+1, posf, posr, numpos);\r
+ } else {
+ if(onr > 0)
+ if(onf > 0 && !iscolor(gs->board[onf-1][onr-1], BLACK))
+ add_pos(onf-1, onr-1, posf, posr, numpos);\r
+ if(onf < gs->files-1 && !iscolor(gs->board[onf+1][onr-1], BLACK))
+ add_pos(onf+1, onr-1, posf, posr, numpos);\r
+ }
+}
+
+static void possible_silver_moves(struct game_state_t * gs,\r
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{
+ possible_ferz_moves(gs, onf, onr, posf, posr, numpos);
+ if(gs->onMove == WHITE) {
+ if(onr < gs->ranks-1 && !iscolor(gs->board[onf][onr+1], WHITE))
+ add_pos(onf, onr+1, posf, posr, numpos);\r
+ } else {
+ if(onr > 0 && !iscolor(gs->board[onf][onr-1], BLACK))
+ add_pos(onf, onr-1, posf, posr, numpos);\r
+ }
+}
+
+static void possible_honorablehorse_moves(struct game_state_t * gs,\r
+ int onf, int onr,\r
+ int *posf, int *posr, int *numpos)\r
+{\r
+ int f, r = onr + (gs->onMove == WHITE ? 2 : -2);\r
+
+ if(r < 0 || r >= gs->ranks) return;\r
+ if(onf > 0) {
+ if ((gs->board[onf-1][r] == NOPIECE) ||\r
+ (iscolor(gs->board[onf-1][r], CToggle(gs->onMove))))\r
+ add_pos(onf - 1, r, posf, posr, numpos);\r
+ }\r
+ if(onf < gs->files - 1) {
+ if ((gs->board[onf+1][r] == NOPIECE) ||\r
+ (iscolor(gs->board[onf+1][r], CToggle(gs->onMove))))\r
+ add_pos(onf + 1, r, posf, posr, numpos);\r
+ }\r
+}\r
+\r
static void possible_king_moves(struct game_state_t * gs,
int onf, int onr,
int *posf, int *posr, int *numpos)
{
- static int kingJumps[8][2] = {{-1, -1}, {0, -1}, {1, -1}, {-1, 1},
- {0, 1}, {1, 1}, {-1, 0}, {1, 0}};
- int f, r;
- int j;
-
- for (j = 0; j < 8; j++) {
- f = kingJumps[j][0] + onf;
- r = kingJumps[j][1] + onr;
- if ((f < 0) || (f > 7))
- continue;
- if ((r < 0) || (r > 7))
- continue;
- if ((gs->board[f][r] == NOPIECE) ||
- (iscolor(gs->board[f][r], CToggle(gs->onMove))))
- add_pos(f, r, posf, posr, numpos);
- }
+ if(gs->royalKnight)\r
+ possible_knight_moves(gs, onf, onr, posf, posr, numpos);\r
+ else if(gs->palace)
+ possible_wazir_moves(gs, onf, onr, posf, posr, numpos);
+ else\r
+ possible_man_moves(gs, onf, onr, posf, posr, numpos);\r
}
+static void possible_elephant_moves(struct game_state_t * gs,
+ int onf, int onr,
+ int *posf, int *posr, int *numpos)
+{\r
+ static int kingJumps[4][2] = {{-1, -1}, {1, -1}, {-1, 1}, {1, 1}};\r
+ int f, r;\r
+ int j;\r
+\r
+ for (j = 0; j < 4; j++) {\r
+ f = 2*kingJumps[j][0] + onf;\r
+ r = 2*kingJumps[j][1] + onr;\r
+ if ((f < 0) || (f >= gs->files))\r
+ continue;\r
+ if ((r < 0) || (r >= gs->ranks))\r
+ continue;\r
+ if ((gs->board[(f+onf)/2][(r+onr)/2] == NOPIECE) && ((gs->board[f][r] == NOPIECE) ||\r
+ (iscolor(gs->board[f][r], CToggle(gs->onMove)))))\r
+ add_pos(f, r, posf, posr, numpos);\r
+ }\r
+}\r
+
/* Doesn't check for check */
int legal_move(struct game_state_t * gs,
int fFile, int fRank,
if (fFile == ALG_DROP) {
move_piece = fRank;
+ if(!gs->drops) return 0; // [HGM] variants: no drops in this variant
if (move_piece == KING)
return 0;
if (gs->holding[gs->onMove==WHITE ? 0 : 1][move_piece-1] == 0)
return 0;
if (gs->board[tFile][tRank] != NOPIECE)
return 0;
- if (move_piece == PAWN && (tRank == 0 || tRank == 7))
+ if (move_piece == PAWN && (tRank == 0 || tRank == gs->ranks-1))
return 0;
return 1;
+ } else if(fFile == ALG_CASTLE) {
+ // [HGM] castle: this code can handle any type of free castling
+ // it does not check if Rook and King from squares correspond to the rights, as the
+ // user never enters such squares, but they are copied from the rights on entering o-o-o
+ int backRank, kRook, qRook, fKing, leftEmpty, rightEmpty, leftCheck, rightCheck, f;
+ if(!gs->castlingStyle) return 0; // no castling in this variant
+ if(gs->onMove == WHITE) {
+ if(gs->wkmoved < 0) return 0; // King moved
+ fKing = gs->wkmoved;
+ backRank = 0;
+ kRook = gs->wkrmoved;
+ qRook = gs->wqrmoved;
+ } else {
+ if(gs->bkmoved < 0) return 0; // King moved
+ fKing = gs->bkmoved;
+ backRank = gs->ranks-1;
+ kRook = gs->bkrmoved;
+ qRook = gs->bqrmoved;
+ }
+ if((tRank > tFile ? qRook : kRook) < 0) return 0; // Rook moved
+ // here we verified rights do exist, so from squares (fRank and fKing) must be valid
+ if(gs->board[fRank][backRank] != (ROOK | gs->onMove) ) return 0; // only with own Rook
+ if(gs->board[fKing][backRank] != (KING | gs->onMove) ) return 0; // only with own King
+
+ // by now we know that K and R are in correct position, and still have rights
+ if(tRank > tFile) { // R ends right of K: q-side
+ leftEmpty = fRank < tFile ? fRank+1 : tFile+1;
+ rightEmpty = tRank < fKing ? fKing-1 : tRank-1;
+ } else { // k-side
+ leftEmpty = tRank < fKing ? tRank+1 : fKing+1;
+ rightEmpty = fRank < tFile ? fRank-1 : tFile-1;
+ }
+ for(f=leftEmpty; f<=rightEmpty; f++) // check if other pieces block castling
+ if(f != fRank && f != fKing && gs->board[f][backRank] != NOPIECE) return 0;
+
+ leftCheck = fKing < tFile ? fKing : tFile+1;
+ rightCheck = fKing < tFile ? tFile-1 : fKing;
+ for(f=leftCheck; f<=rightCheck; f++) // check if King passes attacked square or was in check
+ if(is_square_attacked(gs, f, backRank)) return 0;
+
+ return 1; // passed all tests
} else {
move_piece = piecetype(gs->board[fFile][fRank]);
}
case ROOK:
legal = legal_rook_move(gs, fFile, fRank, tFile, tRank);
break;
+ case CARDINAL:\r
+ case PRINCESS:\r
+ legal = legal_cardinal_move(gs, fFile, fRank, tFile, tRank);\r
+ break;\r
+ case MARSHALL:\r
+ case EMPRESS:\r
+ legal = legal_marshall_move(gs, fFile, fRank, tFile, tRank);\r
+ break;\r
+ case MAN:\r
+ case MAN2:\r
+ legal = legal_man_move(gs, fFile, fRank, tFile, tRank);\r
+ break;\r
case QUEEN:
legal = legal_queen_move(gs, fFile, fRank, tFile, tRank);
break;
+ case ELEPHANT:
+ legal = legal_elephant_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case AMAZON:
+ legal = legal_amazon_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case WOODY:
+ legal = legal_woody_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case SQUIRREL:
+ legal = legal_squirrel_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case MASTODON:
+ legal = legal_mastodon_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case CENTAUR:
+ legal = legal_centaur_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case HORSE:
+ legal = legal_horse_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case FERZ:
+ case FERZ2:
+ legal = legal_ferz_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case MANDARIN:
+ legal = legal_mandarin_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case WAZIR:
+ legal = legal_wazir_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case ALFIL:
+ case ALFIL2:
+ legal = legal_alfil_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case MODERNELEPHANT:
+ legal = legal_modernelephant_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case PRIESTESS:
+ legal = legal_priestess_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case MINISTER:
+ legal = legal_minister_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case SILVER:
+ legal = legal_silver_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case GOLD:
+ legal = legal_gold_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case LANCE:
+ legal = legal_lance_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case CANNON:
+ legal = legal_cannon_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case DRAGONHORSE:
+ legal = legal_dragonhorse_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case DRAGONKING:
+ legal = legal_dragonking_move(gs, fFile, fRank, tFile, tRank);
+ break;
+ case HONORABLEHORSE:
+ legal = legal_honorablehorse_move(gs, fFile, fRank, tFile, tRank);
+ break;
case KING:
legal = legal_king_move(gs, fFile, fRank, tFile, tRank);
break;
* the move is legal. Returns MOVE_ILLEGAL if move leaves you in check */
static int move_calculate(struct game_state_t * gs, struct move_t * mt, int promote)
{
- struct game_state_t fakeMove;
-
- mt->pieceCaptured = gs->board[mt->toFile][mt->toRank];
- mt->enPassant = 0; /* Don't know yet, let execute move take care
- of it */
- if (mt->fromFile == ALG_DROP) {
- mt->piecePromotionTo = NOPIECE;
- sprintf(mt->moveString, "%s/%c%c-%c%d",
- wpstring[mt->fromRank],
- DROP_CHAR, DROP_CHAR,
- mt->toFile + 'a', mt->toRank + 1);
+ struct game_state_t fakeMove;\r
+\r
+ mt->pieceCaptured = gs->board[mt->toFile][mt->toRank];\r
+ mt->enPassant = 0; /* Don't know yet, let execute move take care\r
+ of it */\r
+ if (mt->fromFile == ALG_DROP) {\r
+ mt->piecePromotionTo = NOPIECE;\r
+ sprintf(mt->moveString, "%s/%c%c-%c%d",\r
+ wpstring[mt->fromRank],\r
+ DROP_CHAR, DROP_CHAR,\r
+ mt->toFile + 'a', mt->toRank + 1 - (gs->ranks>9));\r
+ } else if(mt->fromFile == ALG_CASTLE) {
+ // [HGM] castle: generalized castling, fr and tr give from and to file of Rook.
+ sprintf(mt->moveString, mt->toRank > mt->toFile ? "o-o-o" : "o-o");
} else {
- if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) &&
- ((mt->toRank == 0) || (mt->toRank == 7))) {
- mt->piecePromotionTo = promote |
- (colorval(gs->board[mt->fromFile][mt->fromRank]));
- } else {
- mt->piecePromotionTo = NOPIECE;
+ if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) &&
+ !gs->palace && // [HGM] XQ: no promotions in xiangqi\r
+ ((mt->toRank == 0) || (mt->toRank == gs->ranks-1))) {
+ if(!gs->pawnDblStep && promote == PRINCESS) promote = MAN2;
+ if(!gs->pawnDblStep && promote != FERZ2 && promote != MAN2) promote = FERZ; // [HGM] kludge to recognize shatranj
+ mt->piecePromotionTo = promote |\r
+ (colorval(gs->board[mt->fromFile][mt->fromRank]));\r
+ } else {\r
+ mt->piecePromotionTo = NOPIECE;\r
+ }\r
+ if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) &&\r
+ ((mt->fromRank - mt->toRank == 2) || (mt->toRank - mt->fromRank == 2))) {\r
+ mt->doublePawn = mt->fromFile;\r
+ } else {\r
+ mt->doublePawn = -1;\r
}
- if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == PAWN) &&
- ((mt->fromRank - mt->toRank == 2) || (mt->toRank - mt->fromRank == 2))) {
- mt->doublePawn = mt->fromFile;
- } else {
- mt->doublePawn = -1;
- }
- if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) &&
- (mt->fromFile == 4) && (mt->toFile == 2)) {
- sprintf(mt->moveString, "o-o-o");
- } else if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) &&
- (mt->fromFile == 4) && (mt->toFile == 6)) {
+#if 0
+ if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) &&\r
+ (mt->fromFile == gs->files/2) && (mt->toFile == 2) &&
+ mt->fromRank == mt->toRank) {\r
+ sprintf(mt->moveString, "o-o-o");\r
+ } else if ((piecetype(gs->board[mt->fromFile][mt->fromRank]) == KING) &&\r
+ (mt->fromFile == gs->files/2) && (mt->toFile == gs->files-2) &&
+ mt->fromRank == mt->toRank) {\r
sprintf(mt->moveString, "o-o");
} else {
- sprintf(mt->moveString, "%s/%c%d-%c%d",
- wpstring[piecetype(gs->board[mt->fromFile][mt->fromRank])],
- mt->fromFile + 'a', mt->fromRank + 1,
- mt->toFile + 'a', mt->toRank + 1);
- }
- }
- /* Replace this with an algabraic de-parser */
-
- sprintf(mt->algString, alg_unparse(gs, mt));
- fakeMove = *gs;
- /* Calculates enPassant also */
- execute_move(&fakeMove, mt, 0);
-
- /* Does making this move leave ME in check? */
- if (in_check(&fakeMove))
- return MOVE_ILLEGAL;
- /* IanO: bughouse variants: drop cannot be check/checkmate */
-
- return MOVE_OK;
+#else
+ {
+#endif\r
+ sprintf(mt->moveString, "%s/%c%d-%c%d",\r
+ wpstring[piecetype(gs->board[mt->fromFile][mt->fromRank])],\r
+ mt->fromFile + 'a', mt->fromRank + 1 - (gs->ranks>9),\r
+ mt->toFile + 'a', mt->toRank + 1 - (gs->ranks>9));\r
+ }\r
+ }\r
+ /* Replace this with an algabraic de-parser */\r
+\r
+ sprintf(mt->algString, alg_unparse(gs, mt));\r
+ fakeMove = *gs;\r
+ /* Calculates enPassant also */\r
+ execute_move(&fakeMove, mt, 0);\r
+\r
+ /* Does making this move leave ME in check? */\r
+ if (in_check(&fakeMove))\r
+ return MOVE_ILLEGAL;\r
+ /* IanO: bughouse variants: drop cannot be check/checkmate */\r
+\r
+ return MOVE_OK;\r
}
int legal_andcheck_move(struct game_state_t * gs,
*/
int in_check(struct game_state_t * gs)
{
- int f, r;
- int kf = -1, kr = -1;
-
- /* Find the king */
- if (gs->onMove == WHITE) {
- for (f = 0; f < 8 && kf < 0; f++)
- for (r = 0; r < 8 && kf < 0; r++)
- if (gs->board[f][r] == B_KING) {
- kf = f;
- kr = r;
- }
- } else {
- for (f = 0; f < 8 && kf < 0; f++)
- for (r = 0; r < 8 && kf < 0; r++)
- if (gs->board[f][r] == W_KING) {
- kf = f;
- kr = r;
- }
- }
- if (kf < 0) {
- d_printf( "CHESSD: Error game with no king!\n");
- return 0;
- }
- for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
- if (legal_move(gs, f, r, kf, kr)) { /* In Check? */
- return 1;
- }
- }
- return 0;
+ int f, r;\r
+ int kf = -1, kr = -1;\r
+\r
+ /* Find the king */\r
+ if (gs->onMove == WHITE) {\r
+ for (f = 0; f < gs->files && kf < 0; f++)\r
+ for (r = 0; r < gs->ranks && kf < 0; r++)\r
+ if (gs->board[f][r] == B_KING) {\r
+ kf = f;\r
+ kr = r;\r
+ }\r
+ } else {\r
+ for (f = 0; f < gs->files && kf < 0; f++)\r
+ for (r = 0; r < gs->ranks && kf < 0; r++)\r
+ if (gs->board[f][r] == W_KING) {\r
+ kf = f;\r
+ kr = r;\r
+ }\r
+ }\r
+ if (kf < 0) {\r
+ d_printf( "CHESSD: Error game with no king!\n");\r
+ return 0;\r
+ }\r
+ for (InitPieceLoop(gs->board, &f, &r, gs->onMove);\r
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {\r
+ if (legal_move(gs, f, r, kf, kr)) { /* In Check? */\r
+ return 1;\r
+ }\r
+ }\r
+ return 0;\r
}
int has_legal_move(struct game_state_t * gs)
int numpossible = 0;
for (InitPieceLoop(gs->board, &f, &r, gs->onMove);
- NextPieceLoop(gs->board, &f, &r, gs->onMove);) {
+ NextPieceLoop(gs->board, &f, &r, gs->onMove, gs->files, gs->ranks);) {
switch (piecetype(gs->board[f][r])) {
case PAWN:
possible_pawn_moves(gs, f, r, possiblef, possibler, &numpossible);
case ROOK:
possible_rook_moves(gs, f, r, possiblef, possibler, &numpossible);
break;
+ case CARDINAL:\r
+ case PRINCESS:\r
+ possible_cardinal_moves(gs, f, r, possiblef, possibler, &numpossible);\r
+ break;\r
+ case MARSHALL:\r
+ case EMPRESS:\r
+ possible_marshall_moves(gs, f, r, possiblef, possibler, &numpossible);\r
+ break;\r
+ case MAN:\r
+ case MAN2:\r
+ possible_man_moves(gs, f, r, possiblef, possibler, &numpossible);\r
+ break;\r
case QUEEN:
possible_queen_moves(gs, f, r, possiblef, possibler, &numpossible);
break;
+ case ELEPHANT:
+ possible_elephant_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case AMAZON:
+ possible_amazon_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case WOODY:
+ possible_woody_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case SQUIRREL:
+ possible_squirrel_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case MASTODON:
+ possible_mastodon_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case CENTAUR:
+ possible_centaur_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case HORSE:
+ possible_horse_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case FERZ:
+ case FERZ2:
+ possible_ferz_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case MANDARIN:
+ possible_mandarin_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case WAZIR:
+ possible_wazir_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case ALFIL:
+ case ALFIL2:
+ possible_alfil_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case MODERNELEPHANT:
+ possible_modernelephant_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case PRIESTESS:
+ possible_priestess_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case MINISTER:
+ possible_minister_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case SILVER:
+ possible_silver_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case GOLD:
+ possible_gold_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case CANNON:
+ possible_cannon_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case LANCE:
+ possible_lance_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case DRAGONHORSE:
+ possible_dragonhorse_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case DRAGONKING:
+ possible_dragonking_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
+ case HONORABLEHORSE:
+ possible_honorablehorse_moves(gs, f, r, possiblef, possibler, &numpossible);
+ break;
case KING:
kf = f;
kr = r;
}
}
- /* IanO: if we got here, then kf and kr must be set */
- if (gs->gameNum >=0 && game_globals.garray[gs->gameNum].link >= 0) {
- /* bughouse: potential drops as check interpositions */
- gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]++;
- for (f=kf-1; f<=kf+1; f++) for (r=kr-1; r<=kr+1; r++) {
- if (f>=0 && f<8 && r>=0 && r<8 && gs->board[f][r] == NOPIECE) {
- /* try a drop next to the king */
- if (legal_andcheck_move(gs, ALG_DROP, QUEEN, f, r)) {
+ /* IanO: if we got here, then kf and kr must be set */\r
+ if (gs->gameNum >=0 && game_globals.garray[gs->gameNum].link >= 0
+ || gs->holdings) { // [HGM] zh: also in 2-player games with drops\r
+ /* bughouse: potential drops as check interpositions */\r
+ gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]++;\r
+ for (f=kf-1; f<=kf+1; f++) for (r=kr-1; r<=kr+1; r++) {\r
+ if (f>=0 && f<gs->files && r>=0 && r<gs->ranks && gs->board[f][r] == NOPIECE) {\r
+ /* try a drop next to the king */\r
+ if (legal_andcheck_move(gs, ALG_DROP, QUEEN, f, r)) {\r
gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]--;
- return 1;
- }
- }
- }
- gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]--;
- }
+ // OK, so we have an interposing drop. But do we have something to drop?
+ if(game_globals.garray[gs->gameNum].link < 0) {
+ // we have no partner, so we must have something to drop now
+ for(i=QUEEN; i>=PAWN; i--)
+ if(gs->holding[gs->onMove==WHITE ? 0 : 1][i-1]) break;
+ if(i > PAWN) return 1; // we have a non-Pawn to drop
+ // We have a Pawn, but check if it legal to drop it
+ if(i == PAWN && r != 0 && r != gs->ranks-1) return 1; // [HGM] todo: for Shogi there are extra conditions on Pawn drops!
+ }\r
+ return 1;\r
+ }\r
+ }\r
+ }\r
+ gs->holding[gs->onMove==WHITE ? 0 : 1][QUEEN - 1]--;\r
+ }\r
return 0;
}
/* This will end up being a very complicated function */
int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int promote)
{
- int type = is_move(mstr);
- int result;
-
- mt->piecePromotionTo = NOPIECE;
- mt->color = gs->onMove;
- switch (type) {
- case MS_NOTMOVE:
- return MOVE_ILLEGAL;
- break;
- case MS_COMP:
- mt->fromFile = mstr[0] - 'a';
- mt->fromRank = mstr[1] - '1';
- mt->toFile = mstr[2] - 'a';
- mt->toRank = mstr[3] - '1';
- break;
- case MS_COMPDASH:
- mt->fromFile = mstr[0] - 'a';
- mt->fromRank = mstr[1] - '1';
- mt->toFile = mstr[3] - 'a';
- mt->toRank = mstr[4] - '1';
- break;
- case MS_KCASTLE:
- mt->fromFile = 4;
- mt->toFile = 6;
- if (gs->onMove == WHITE) {
- mt->fromRank = 0;
- mt->toRank = 0;
- } else {
- mt->fromRank = 7;
- mt->toRank = 7;
- }
+ int type = is_move(mstr);\r
+ int result;\r
+\r
+ mt->piecePromotionTo = NOPIECE;\r
+ mt->color = gs->onMove;\r
+ switch (type) {\r
+ case MS_NOTMOVE:\r
+ return MOVE_ILLEGAL;\r
+ break;\r
+ case MS_COMP:\r
+ mt->fromFile = mstr[0] - 'a';\r
+ mt->fromRank = mstr[1] - '1' + (gs->ranks>9);\r
+ mt->toFile = mstr[2] - 'a';\r
+ mt->toRank = mstr[3] - '1' + (gs->ranks>9);\r
+ break;\r
+ case MS_COMPDASH:\r
+ mt->fromFile = mstr[0] - 'a';\r
+ mt->fromRank = mstr[1] - '1' + (gs->ranks>9);\r
+ mt->toFile = mstr[3] - 'a';\r
+ mt->toRank = mstr[4] - '1' + (gs->ranks>9);\r
+ break;\r
+ case MS_KCASTLE:\r
+#if 0
+ mt->fromFile = gs->files/2;\r
+ mt->toFile = gs->files-2;\r
+ if (gs->onMove == WHITE) {\r
+ mt->fromRank = 0;\r
+ mt->toRank = 0;\r
+ } else {\r
+ mt->fromRank = gs->ranks-1;\r
+ mt->toRank = gs->ranks-1;\r
+ }\r
break;
+#endif
+ // [HGM] castle: for now always assume Fischer-type castling (of which normal castling is a special case).
+ mt->fromFile = ALG_CASTLE;\r
+ mt->toFile = gs->files-2;\r
+ mt->fromRank = gs->onMove == WHITE ? gs->wkrmoved : gs->bkrmoved;\r
+ mt->toRank = mt->toFile-1; // R next to K\r
+ break; \r
case MS_QCASTLE:
- mt->fromFile = 4;
- mt->toFile = 2;
- if (gs->onMove == WHITE) {
- mt->fromRank = 0;
- mt->toRank = 0;
- } else {
- mt->fromRank = 7;
- mt->toRank = 7;
- }
- break;
- case MS_ALG:
- /* Fills in the mt structure */
- if ((result = alg_parse_move(mstr, gs, mt)) != MOVE_OK)
- return result;
- break;
- default:
- return MOVE_ILLEGAL;
+#if 0\r
+ mt->fromFile = gs->files/2;\r
+ mt->toFile = 2;\r
+ if (gs->onMove == WHITE) {\r
+ mt->fromRank = 0;\r
+ mt->toRank = 0;\r
+ } else {\r
+ mt->fromRank = gs->ranks-1;\r
+ mt->toRank = gs->ranks-1;\r
+ }\r
break;
+#endif\r
+ mt->fromFile = ALG_CASTLE;\r
+ mt->toFile = 2;\r
+ mt->fromRank = gs->onMove == WHITE ? gs->wqrmoved : gs->bqrmoved;\r
+ mt->toRank = mt->toFile+1;
+ break;\r
+ case MS_ALG:\r
+ /* Fills in the mt structure */\r
+ if ((result = alg_parse_move(mstr, gs, mt)) != MOVE_OK)\r
+ return result;\r
+ break;\r
+ default:\r
+ return MOVE_ILLEGAL;\r
+ break;\r
}
- if (!legal_move(gs, mt->fromFile, mt->fromRank, mt->toFile, mt->toRank)) {
- return MOVE_ILLEGAL;
- }
-
- if (mt->piecePromotionTo != NOPIECE) {
- promote = piecetype(mt->piecePromotionTo);
- }
-
- return move_calculate(gs, mt, promote);
+ if((mt->fromRank >= gs->ranks || mt->fromRank < 0 || mt->fromFile >= gs->files) &&
+ mt->fromFile != ALG_DROP && mt->fromFile != ALG_CASTLE\r
+ || mt->toRank < 0 || mt->toRank >= gs->ranks || mt->toFile >= gs->files)\r
+ return MOVE_ILLEGAL; // [HGM] make sure move stays on board
+\r
+ if (!(result = legal_move(gs, mt->fromFile, mt->fromRank, mt->toFile, mt->toRank)))
+ return MOVE_ILLEGAL;\r
+
+ if(result == 2) { // [HGM] castle: orthodox castling was given as King move; convert it to new format
+ if(mt->fromFile - mt->toFile > 1) { // Q-side
+ mt->fromRank = 0;
+ mt->toRank = mt->toFile+1;
+ } else if(mt->toFile - mt->fromFile > 1) { // K-side
+ mt->fromRank = gs->files-1;
+ mt->toRank = mt->toFile-1;
+ }
+ mt->fromFile = ALG_CASTLE;
+ }\r
+\r
+ if (mt->piecePromotionTo != NOPIECE) {\r
+ promote = piecetype(mt->piecePromotionTo);\r
+ }\r
+\r
+ return move_calculate(gs, mt, promote);\r
}
/* Returns MOVE_OK, MOVE_NOMATERIAL, MOVE_CHECKMATE, or MOVE_STALEMATE */
{
int movedPiece;
int tookPiece;
- int i, j, foobar;
+ int i, j, foobar, wCnt, bCnt, king, rook;
if (mt->fromFile == ALG_DROP) {
movedPiece = mt->fromRank;
gs->board[mt->toFile][mt->toRank] = movedPiece | gs->onMove;
if (gs->gameNum >= 0)
gs->lastIrreversable = game_globals.garray[gs->gameNum].numHalfMoves;
+ } else if(mt->fromFile == ALG_CASTLE) {
+ int backRank, fKing;
+ // [HGM] castle: perform castling
+ if(gs->onMove == WHITE) {
+ backRank = 0;
+ fKing = gs->wkmoved;
+ gs->wkmoved = -gs->wkmoved-2;
+ } else {
+ backRank = gs->ranks-1;
+ fKing = gs->bkmoved;
+ gs->bkmoved = -gs->bkmoved-2;
+ }
+ // move Rook & King, in a way that is resistant to ending where they started (for FRC!)
+ rook = gs->board[mt->fromRank][backRank]; // first remember\r
+ king = gs->board[fKing][backRank];\r
+ gs->board[mt->fromRank][backRank] = NOPIECE; // then erase\r gs->board[fKing][backRank] = NOPIECE;\r gs->board[mt->toRank][backRank] = rook; // then put back
+ gs->board[mt->toFile][backRank] = king;
} else {
movedPiece = gs->board[mt->fromFile][mt->fromRank];
tookPiece = gs->board[mt->toFile][mt->toRank];
gs->board[mt->toFile][mt->toRank] = gs->board[mt->fromFile][mt->fromRank];
} else {
gs->board[mt->toFile][mt->toRank] = mt->piecePromotionTo | gs->onMove;
+ if(gs->promoType == 2) gs->holding[gs->onMove][mt->piecePromotionTo-1]--;
}
gs->board[mt->fromFile][mt->fromRank] = NOPIECE;
/* Check if irreversable */
- if ((piecetype(movedPiece) == PAWN) || (tookPiece != NOPIECE)) {
+ if ((piecetype(movedPiece) == PAWN) && (mt->fromRank != mt->toRank) // [HGM] XQ: sideway Pawn move reversible!
+ || (tookPiece != NOPIECE)) {
if (gs->gameNum >= 0)
gs->lastIrreversable = game_globals.garray[gs->gameNum].numHalfMoves;
}
/* Check if this move is en-passant */
if ((piecetype(movedPiece) == PAWN) && (mt->fromFile != mt->toFile) &&
- (tookPiece == NOPIECE)) {
+ (tookPiece == NOPIECE) && !gs->palace) { // [HGM] XQ: no e.p. in sideway xiangqi moves
if (gs->onMove == WHITE) {
mt->pieceCaptured = B_PAWN;
} else {
}
gs->board[mt->toFile][mt->fromRank] = NOPIECE;
}
- /* Check en-passant flags for next moves */
- for (i = 0; i < 8; i++) {
- gs->ep_possible[0][i] = 0;
- gs->ep_possible[1][i] = 0;
- }
+ /* Check en-passant flags for next moves */\r
+ for (i = 0; i < gs->files; i++) {\r
+ gs->ep_possible[0][i] = 0;\r
+ gs->ep_possible[1][i] = 0;\r
+ }\r
/* Added by Sparky 3/16/95
From soso@Viktoria.drp.fmph.uniba.sk Thu Mar 16 13:08:51 1995
if ((mt->toFile+1 < 7 ) .... should be : (mt->toFile < 7 ) }
*/
- if ((piecetype(movedPiece) == PAWN) &&
- ((mt->fromRank == mt->toRank + 2) || (mt->fromRank + 2 == mt->toRank))) {
- /* Should turn on enpassent flag if possible */
- if (gs->onMove == WHITE) {
- if ((mt->toFile < 7) && gs->board[mt->toFile + 1][3] == B_PAWN) {
- gs->ep_possible[1][mt->toFile + 1] = -1;
- }
- if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][3] == B_PAWN) {
- gs->ep_possible[1][mt->toFile - 1] = 1;
- }
- } else {
- if ((mt->toFile < 7) && gs->board[mt->toFile + 1][4] == W_PAWN) {
- gs->ep_possible[0][mt->toFile + 1] = -1;
- }
- if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][4] == W_PAWN) {
- gs->ep_possible[0][mt->toFile - 1] = 1;
- }
- }
- }
- if ((piecetype(movedPiece) == ROOK) && (mt->fromFile == 0)) {
- if ((mt->fromRank == 0) && (gs->onMove == WHITE))
- gs->wqrmoved = 1;
- if ((mt->fromRank == 7) && (gs->onMove == BLACK))
- gs->bqrmoved = 1;
- }
- if ((piecetype(movedPiece) == ROOK) && (mt->fromFile == 7)) {
- if ((mt->fromRank == 0) && (gs->onMove == WHITE))
- gs->wkrmoved = 1;
- if ((mt->fromRank == 7) && (gs->onMove == BLACK))
- gs->bkrmoved = 1;
- }
- if (piecetype(movedPiece) == KING) {
- if (gs->onMove == WHITE)
- gs->wkmoved = 1;
- else
- gs->bkmoved = 1;
- }
- if ((piecetype(movedPiece) == KING) &&
- ((mt->fromFile == 4) && ((mt->toFile == 6)))) { /* Check for KS castling */
- gs->board[5][mt->toRank] = gs->board[7][mt->toRank];
- gs->board[7][mt->toRank] = NOPIECE;
+ if ((piecetype(movedPiece) == PAWN) &&\r
+ ((mt->fromRank == mt->toRank + 2) || (mt->fromRank + 2 == mt->toRank))) {\r
+ /* Should turn on enpassent flag if possible */\r
+ if (gs->onMove == WHITE) {\r
+ if ((mt->toFile < gs->files-1) && gs->board[mt->toFile + 1][mt->toRank] == B_PAWN) {\r
+ gs->ep_possible[1][mt->toFile + 1] = -1;\r
+ }\r
+ if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][mt->toRank] == B_PAWN) {\r
+ gs->ep_possible[1][mt->toFile - 1] = 1;\r
+ }\r
+ } else {\r
+ if ((mt->toFile < gs->files-1) && gs->board[mt->toFile + 1][mt->toRank] == W_PAWN) {\r
+ gs->ep_possible[0][mt->toFile + 1] = -1;\r
+ }\r
+ if ((mt->toFile - 1 >= 0) && gs->board[mt->toFile - 1][mt->toRank] == W_PAWN) {\r
+ gs->ep_possible[0][mt->toFile - 1] = 1;\r
+ }\r
+ }\r
+ }\r
+ if ((piecetype(movedPiece) == ROOK) && (mt->fromRank == 0) && (gs->onMove == WHITE)) {\r
+ if (mt->fromFile == gs->wqrmoved) // [HGM] castle: flip w.r.t. -1 to remember original\r
+ gs->wqrmoved = -gs->wqrmoved-2;\r
+ if (mt->fromFile == gs->wkrmoved)\r
+ gs->wkrmoved = -gs->wkrmoved-2;\r
+ }\r
+ if ((piecetype(movedPiece) == ROOK) && (mt->fromRank == gs->ranks-1) && (gs->onMove == BLACK)) {\r
+ if (mt->fromFile == gs->bqrmoved)\r
+ gs->bqrmoved = -gs->bqrmoved-2;\r
+ if (mt->fromFile == gs->bkrmoved)\r
+ gs->bkrmoved = -gs->bkrmoved-2;\r
+ }\r
+ if (piecetype(movedPiece) == KING) {\r
+ if ((gs->onMove == WHITE) && (mt->fromFile == gs->wkmoved))\r
+ gs->wkmoved = -gs->wkmoved-2;\r
+ if ((gs->onMove == BLACK) && (mt->fromFile == gs->bkmoved))\r
+ gs->bkmoved = -gs->bkmoved-2;\r
}
- if ((piecetype(movedPiece) == KING) &&
- ((mt->fromFile == 4) && ((mt->toFile == 2)))) { /* Check for QS castling */
- gs->board[3][mt->toRank] = gs->board[0][mt->toRank];
- gs->board[0][mt->toRank] = NOPIECE;
+#if 0\r
+ if ((piecetype(movedPiece) == KING) &&\r
+ ((mt->fromFile == gs->files/2) && (mt->toFile == gs->files-2)) &&
+ mt->fromRank == mt->toRank) { /* Check for KS castling */\r
+ gs->board[gs->files-3][mt->toRank] = gs->board[gs->files-1][mt->toRank];\r
+ gs->board[gs->files-1][mt->toRank] = NOPIECE;\r
+ }\r
+ if ((piecetype(movedPiece) == KING) &&\r
+ ((mt->fromFile == gs->files/2) && (mt->toFile == 2)) &&
+ mt->fromRank == mt->toRank) { /* Check for QS castling */\r
+ gs->board[3][mt->toRank] = gs->board[0][mt->toRank];\r
+ gs->board[0][mt->toRank] = NOPIECE;\r
}
- }
- if (gs->onMove == BLACK)
- gs->moveNum++;
-
- if (check_game_status) {
- /* Does this move result in check? */
- if (in_check(gs)) {
- /* Check for checkmate */
- gs->onMove = CToggle(gs->onMove);
- if (!has_legal_move(gs))
- return MOVE_CHECKMATE;
- } else {
- /* Check for stalemate */
- gs->onMove = CToggle(gs->onMove);
- if (!has_legal_move(gs))
- return MOVE_STALEMATE;
-/* loon: check for insufficient mating material, first try */
- foobar = 0;
- for (i=0; i<8; i++) {
- for (j=0; j<8; j++) {
- switch(piecetype(gs->board[i][j])) {
- case KNIGHT:
- case BISHOP:
- foobar++;
- break;
- case KING:
- case NOPIECE:
- break;
- default:
- foobar = 2;
- break;
+#endif\r
+ }\r
+ if (gs->onMove == BLACK)\r
+ gs->moveNum++;\r
+\r
+ if (check_game_status) {\r
+ /* Does this move result in check? */\r
+ if (in_check(gs)) {\r
+ /* Check for checkmate */\r
+ gs->onMove = CToggle(gs->onMove);\r
+ if (!has_legal_move(gs))\r
+ return MOVE_CHECKMATE;\r
+ } else {\r
+ /* Check for stalemate */\r
+ gs->onMove = CToggle(gs->onMove);\r
+ if (!has_legal_move(gs))\r
+ return gs->stalemate ? MOVE_STALEMATE : MOVE_CHECKMATE; // [HGM] in XQ and shatranj stalemate loses\r
+ }\r
+/* loon: check for insufficient mating material, first try */\r
+ foobar = wCnt = bCnt = 0;\r
+ for (i=0; i<gs->files; i++) {\r
+ for (j=0; j<gs->ranks; j++) {
+ int p = gs->board[i][j];\r
+ switch(piecetype(p)) {\r
+ case KNIGHT:\r
+ case BISHOP:\r
+ foobar++;\r
+ break;\r
+ case KING:\r
+ case NOPIECE:\r
+ break;\r
+ default:\r
+ foobar = 2;\r
+ break;\r
}
- }
+ if(p != NOPIECE && iscolor(p, WHITE)) wCnt++;
+ if(iscolor(p, BLACK)) bCnt++;\r
+ }\r
}
- if (foobar < 2)
- return MOVE_NOMATERIAL;
- }
- } else {
- gs->onMove = CToggle(gs->onMove);
- }
- return MOVE_OK;
+ if(gs->bareKingLoses) { // [HGM] with bare-King-loses rule only KK is insuff. material
+ if(gs->onMove == BLACK && wCnt == 1 && bCnt > 1) return MOVE_BARE;
+ if(gs->onMove == WHITE && bCnt == 1 && wCnt > 1) return MOVE_BARE;
+ if(bCnt == 1 && wCnt == 1) return MOVE_NOMATERIAL;
+ } else if (foobar < 2)\r
+ return MOVE_NOMATERIAL;\r
+ } else {\r
+ gs->onMove = CToggle(gs->onMove);\r
+ }\r
+ return MOVE_OK;\r
}
int backup_move(int g, int mode)
if (m->toFile < 0) {
return MOVE_ILLEGAL;
}
+ if(m->fromFile == ALG_CASTLE) {
+ // [HGM] castling in new format. Derive K and R moves
+ int rank, kingFromFile;
+ if(m->color == WHITE) {
+ rank = 0;
+ kingFromFile = -gs->wkmoved-2;
+ if(kingFromFile<0) kingFromFile = -kingFromFile-2; // safety catch; should never happen?
+ gs->wkmoved = kingFromFile;
+ if(m->toRank > m->toFile) gs->wqrmoved = m->fromRank;
+ else gs->wkrmoved = m->fromRank;
+ } else {
+ rank = gs->ranks-1;
+ kingFromFile = -gs->bkmoved-2;
+ if(kingFromFile<0) kingFromFile = -kingFromFile-2; // safety catch; should never happen?
+ gs->bkmoved = kingFromFile;
+ if(m->toRank > m->toFile) gs->bqrmoved = m->fromRank;
+ else gs->bkrmoved = m->fromRank;
+ }
+ // remove first, as one might come back to a square the other left
+ gs->board[m->toFile ][rank] = NOPIECE; // King toSqr
+ gs->board[m->toRank ][rank] = NOPIECE; // Rook toSqr
+ gs->board[m->fromRank][rank] = ROOK | m->color; // Rook fromSqr
+ gs->board[kingFromFile][rank] = KING | m->color; // King fromSquare
+ goto cleanupMove;
+ }
gs->board[m->fromFile][m->fromRank] = gs->board[m->toFile][m->toRank];
if (m->piecePromotionTo != NOPIECE) {
gs->board[m->fromFile][m->fromRank] = PAWN |
*******************/
if (piecetype(gs->board[m->fromFile][m->fromRank]) == ROOK) {
if (m->color == WHITE) {
- if ((m->fromFile == 0) && (m->fromRank == 0)) {
- for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {
- m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];
- if ((m1->fromFile == 0) && (m1->fromRank == 0))
- break;
- }
- if (i == game_globals.garray[g].numHalfMoves - 1)
- gs->wqrmoved = 0;
- }
- if ((m->fromFile == 7) && (m->fromRank == 0)) {
+ if ((m->fromFile == -gs->wqrmoved-2) && (m->fromRank == 0)) {
for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {
m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];
- if ((m1->fromFile == 7) && (m1->fromRank == 0))
- break;
- }
- if (i == game_globals.garray[g].numHalfMoves - 1)
- gs->wkrmoved = 0;
- }
- } else {
- if ((m->fromFile == 0) && (m->fromRank == 7)) {
- for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {
- m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];
- if ((m1->fromFile == 0) && (m1->fromRank == 0))
+ if ((m1->fromFile == -gs->wqrmoved-2) && (m1->fromRank == 0))
break;
}
if (i == game_globals.garray[g].numHalfMoves - 1)
- gs->bqrmoved = 0;
+ gs->wqrmoved = m->fromFile;
}
- if ((m->fromFile == 7) && (m->fromRank == 7)) {
- for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {
- m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];
- if ((m1->fromFile == 7) && (m1->fromRank == 0))
- break;
- }
- if (i == game_globals.garray[g].numHalfMoves - 1)
- gs->bkrmoved = 0;
- }
- }
- }
+ if ((m->fromFile == -gs->wkrmoved-2) && (m->fromRank == 0)) {\r
+ for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {\r
+ m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];\r
+ if ((m1->fromFile == -gs->wkrmoved-2) && (m1->fromRank == 0))\r
+ break;\r
+ }\r
+ if (i == game_globals.garray[g].numHalfMoves - 1)\r
+ gs->wkrmoved = m->fromFile;\r
+ }\r
+ } else {\r
+ if ((m->fromFile == -gs->bqrmoved-2) && (m->fromRank == gs->ranks-1)) {\r
+ for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {\r
+ m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];\r
+ if ((m1->fromFile == -gs->bkrmoved-2) && (m1->fromRank == gs->ranks-1))\r
+ break;\r
+ }\r
+ if (i == game_globals.garray[g].numHalfMoves - 1)\r
+ gs->bqrmoved = m->fromFile;\r
+ }\r
+ if ((m->fromFile == -gs->bkrmoved-2) && (m->fromRank == gs->ranks-1)) {\r
+ for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {\r
+ m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];\r
+ if ((m1->fromFile == -gs->wkrmoved-2) && (m1->fromRank == gs->ranks-1))\r
+ break;\r
+ }\r
+ if (i == game_globals.garray[g].numHalfMoves - 1)\r
+ gs->bkrmoved = m->fromFile;\r
+ }\r
+ }\r
+ }\r
if (piecetype(gs->board[m->fromFile][m->fromRank]) == KING) {
gs->board[m->toFile][m->toRank] = m->pieceCaptured;
-
+#if 0
+ /* [HGM] castlings are already intercepted due to new format; this code wrecks knightmate! */
if (m->toFile - m->fromFile == 2) {
gs->board[7][m->fromRank] = ROOK |
colorval(gs->board[m->fromFile][m->fromRank]);
}
goto cleanupMove;
}
+#endif
/******************
When takeback a _first_ move of king (not the castling),
the ?kmoved variable must be cleared . To check, if the move is first,
we should scan moveList.
*******************/
- if (m->color == WHITE) {
-
- if ((m->fromFile == 4) && (m->fromRank == 0)) {
- for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {
- m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];
- if ((m1->fromFile == 4) && (m1->fromRank == 0))
- break;
- }
- if (i == game_globals.garray[g].numHalfMoves - 1)
- gs->wkmoved = 0;
- }
- } else {
- if ((m->fromFile == 4) && (m->fromRank == 7)) {
- for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {
- m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];
- if ((m1->fromFile == 4) && (m1->fromRank == 7))
- break;
- }
- if (i == game_globals.garray[g].numHalfMoves - 1)
- gs->bkmoved = 0;
- }
- }
- }
+ if (m->color == WHITE) {\r
+\r
+ if ((m->fromFile == -gs->wkmoved-2) && (m->fromRank == 0)) {\r
+ for (i = 2; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {\r
+ m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];\r
+ if ((m1->fromFile == gs->wkmoved-2) && (m1->fromRank == 0))\r
+ break;\r
+ }\r
+ if (i == game_globals.garray[g].numHalfMoves - 1)\r
+ gs->wkmoved = m->fromFile;\r
+ }\r
+ } else {\r
+ if ((m->fromFile == -gs->bkmoved-2) && (m->fromRank == gs->ranks-1)) {\r
+ for (i = 3; i < game_globals.garray[g].numHalfMoves - 1; i += 2) {\r
+ m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[i] : &game_globals.garray[g].examMoveList[i];\r
+ if ((m1->fromFile == -gs->bkmoved-2) && (m1->fromRank == gs->ranks-1))\r
+ break;\r
+ }\r
+ if (i == game_globals.garray[g].numHalfMoves - 1)\r
+ gs->bkmoved = m->fromFile;\r
+ }\r
+ }\r
+ }\r
if (m->enPassant) { /* Do enPassant */
gs->board[m->toFile][m->fromRank] = PAWN |
(colorval(gs->board[m->fromFile][m->fromRank]) == WHITE ? BLACK : WHITE);
array. (patch from Soso, added by Sparky 3/17/95)
********/
- if (game_globals.garray[g].numHalfMoves > 0) {
- m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves - 1] :
- &game_globals.garray[g].examMoveList[game_globals.garray[g].numHalfMoves - 1];
- if (piecetype(gs->board[m1->toFile][m1->toRank]) == PAWN) {
- if ((m1->toRank - m1->fromRank) == 2) {
- if ((m1->toFile < 7) && gs->board[m1->toFile + 1][3] == B_PAWN) {
- gs->ep_possible[1][m1->toFile + 1] = -1;
- }
- if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][3] == B_PAWN) {
- gs->ep_possible[1][m1->toFile - 1] = 1;
- }
- }
- if ((m1->toRank - m1->fromRank) == -2) {
- if ((m1->toFile < 7) && gs->board[m1->toFile + 1][4] == W_PAWN) {
- gs->ep_possible[0][m1->toFile + 1] = -1;
- }
- if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][4] == W_PAWN) {
- gs->ep_possible[0][m1->toFile - 1] = 1;
- }
- }
- }
- }
+ if (game_globals.garray[g].numHalfMoves > 0) {\r
+ m1 = (mode==REL_GAME) ? &game_globals.garray[g].moveList[game_globals.garray[g].numHalfMoves - 1] : \r
+ &game_globals.garray[g].examMoveList[game_globals.garray[g].numHalfMoves - 1];\r
+ if (piecetype(gs->board[m1->toFile][m1->toRank]) == PAWN) {\r
+ if ((m1->toRank - m1->fromRank) == 2) {\r
+ if ((m1->toFile < gs->files-1) && gs->board[m1->toFile + 1][m1->toRank] == B_PAWN) {\r
+ gs->ep_possible[1][m1->toFile + 1] = -1;\r
+ }\r
+ if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][m1->toRank] == B_PAWN) {\r
+ gs->ep_possible[1][m1->toFile - 1] = 1;\r
+ }\r
+ }\r
+ if ((m1->toRank - m1->fromRank) == -2) {\r
+ if ((m1->toFile < gs->files-1) && gs->board[m1->toFile + 1][m1->toRank] == W_PAWN) {\r
+ gs->ep_possible[0][m1->toFile + 1] = -1;\r
+ }\r
+ if ((m1->toFile - 1 >= 0) && gs->board[m1->toFile - 1][m1->toRank] == W_PAWN) {\r
+ gs->ep_possible[0][m1->toFile - 1] = 1;\r
+ }\r
+ }\r
+ }\r
+ }\r
/************** and here's the end **************/
return MOVE_OK;
}
-/*
- Copyright (c) 1993 Richard V. Nash.
- Copyright (c) 2000 Dan Papasian
- Copyright (C) Andrew Tridgell 2002
-
- 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.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
-*/
-
-#ifndef _MOVECHECK_H
-#define _MOVECHECK_H
-
-#define MOVE_OK 0
-#define MOVE_ILLEGAL 1
-#define MOVE_STALEMATE 2
-#define MOVE_CHECKMATE 3
-#define MOVE_AMBIGUOUS 4
-#define MOVE_NOMATERIAL 5
-
-#define MS_NOTMOVE 0
-#define MS_COMP 1
-#define MS_COMPDASH 2
-#define MS_ALG 3
-#define MS_KCASTLE 4
-#define MS_QCASTLE 5
-
-#define isrank(c) (((c) <= '8') && ((c) >= '1'))
-#define isfile(c) (((c) >= 'a') && ((c) <= 'h'))
-
-#endif /* _MOVECHECK_H */
+/*\r
+ Copyright (c) 1993 Richard V. Nash.\r
+ Copyright (c) 2000 Dan Papasian\r
+ Copyright (C) Andrew Tridgell 2002\r
+ \r
+ This program is free software; you can redistribute it and/or modify\r
+ it under the terms of the GNU General Public License as published by\r
+ the Free Software Foundation; either version 2 of the License, or\r
+ (at your option) any later version.\r
+ \r
+ This program is distributed in the hope that it will be useful,\r
+ but WITHOUT ANY WARRANTY; without even the implied warranty of\r
+ MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the\r
+ GNU General Public License for more details.\r
+ \r
+ You should have received a copy of the GNU General Public License\r
+ along with this program; if not, write to the Free Software\r
+ Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.\r
+*/\r
+\r
+#ifndef _MOVECHECK_H\r
+#define _MOVECHECK_H\r
+\r
+#define MOVE_OK 0\r
+#define MOVE_ILLEGAL 1\r
+#define MOVE_STALEMATE 2\r
+#define MOVE_CHECKMATE 3\r
+#define MOVE_AMBIGUOUS 4\r
+#define MOVE_NOMATERIAL 5\r
+#define MOVE_BARE 6\r
+\r
+#define MS_NOTMOVE 0\r
+#define MS_COMP 1\r
+#define MS_COMPDASH 2\r
+#define MS_ALG 3\r
+#define MS_KCASTLE 4\r
+#define MS_QCASTLE 5\r
+\r
+#define isrank(c) (((c) <= '9') && ((c) >= '0'))\r
+#define isfile(c) (((c) >= 'a') && ((c) <= 'l'))\r
+\r
+#endif /* _MOVECHECK_H */\r
g = pp->game;
} else if (pp->num_observe) {
for (g = 0; g < pp->num_observe; g++) {
- pprintf(p, "%s\n", movesToString(pp->observe_list[g], 0));
+ pprintf_noformat(p, "%s\n", movesToString(pp->observe_list[g], 0));
}
return COM_OK;
} else {
pprintf(p, "Sorry, that is a private game.\n");
return COM_OK;
}
- pprintf(p, "%s\n", movesToString(g, 0)); /* pgn may break interfaces? */
+ pprintf_noformat(p, "%s\n", movesToString(g, 0)); /* pgn may break interfaces? */
return COM_OK;
}
int p1;
char subj[81];
- if (!CheckPFlag(p, PFLAG_REG)) {
- pprintf (p,"Unregistered players cannot use mailmoves.\n");
+ if (param[1].type == TYPE_NULL) {
+ if (!CheckPFlag(p, PFLAG_REG)) {
+ pprintf (p,"Unregistered players must specify their e-mail address.\n");
+ return COM_OK;
+ }
+ } else if(!safestring(param[1].val.string)) {
+ pprintf (p,"Bad e-mail address.\n");
return COM_OK;
}
return COM_OK;
}
sprintf(subj, "FICS game report %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
- if (mail_string_to_user(p, subj,
+ if (param[1].type == TYPE_NULL ? mail_string_to_user(p, subj,
+ movesToString(g, CheckPFlag(p, PFLAG_PGN))) :
+ mail_string_to_address(param[1].val.string, subj,
movesToString(g, CheckPFlag(p, PFLAG_PGN)))) {
pprintf(p, "Moves NOT mailed, perhaps your address is incorrect.\n");
} else {
pprintf(p, "Loading from catagory: %s, board: %s.\n", category, board);
}
+ game_globals.garray[g].FENstartPos[0] = 0; // [HGM] new shuffle game
if (setup) {
board_clear(&game_globals.garray[g].game_state);
game_globals.garray[g].status = GAME_SETUP;
gg = &game_globals.garray[g];
category[0] = '\0';
board[0] = '\0';
+ game_globals.garray[g].FENstartPos[0] = 0; // [HGM] make new shuffle for now
if (board_init(g,&gg->game_state, category, board)) {
pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
d_printf( "CHESSD: PROBLEM LOADING BOARD %s %s. Examine Aborted.\n",
game_remove(g);
return -1;
}
+
+ // [HGM] OK, we retreived the game info, which includes variant name as "category/board"
+ // So now we set up the board again, this time for the proper variant (and proper shuffle)
+ sscanf(gg->variant, "%s/%s", category, board);
+ if(category[0] && !board[0]) strcpy(board, "0");
+ if (board_init(g,&gg->game_state, category, board)) {
+ pprintf(p, "PROBLEM LOADING BOARD. Examine Aborted.\n");
+ d_printf( "CHESSD: PROBLEM LOADING BOARD %s %s. Examine Aborted.\n",
+ category, board);
+ game_remove(g);
+ return -1;
+ }
} else if (ReadGameAttrs(fp, g) < 0) {
pprintf(p, "Gamefile is corrupt; please notify an admin.\n");
game_remove(g);
pp->side = WHITE; /* oh well... */
pp->game = g;
-
send_boards(g);
if (CheckPFlag(p, PFLAG_OPEN)) /* was open */
announce_notavail(p);
char fileName2[MAX_FILENAME_SIZE];
FILE* fpGame;
- if (mail && !CheckPFlag(p, PFLAG_REG)) {
- pprintf (p,"Unregistered players cannot use mailstored.\n");
- return;
+ if (param[2].type == TYPE_NULL) {
+ if (!CheckPFlag(p, PFLAG_REG)) {
+ pprintf (p,"Unregistered players must specify their e-mail address.\n");
+ return COM_OK;
+ }
+ } else if(!safestring(param[2].val.string)) {
+ pprintf (p,"Bad e-mail address.\n");
+ return COM_OK;
}
if (!FindPlayer(p, param[0].val.word, &wp, &wconnected))
} else {
sprintf(subj, "FICS adjourned game %s vs %s", game_globals.garray[g].white_name, game_globals.garray[g].black_name);
}
- if (mail_string_to_user(p, subj,
+ if (param[2].type == TYPE_NULL ? mail_string_to_user(p, subj,
+ movesToString(g, CheckPFlag(p, PFLAG_PGN))) :
+ mail_string_to_address(param[2].val.string, subj,
movesToString(g, CheckPFlag(p, PFLAG_PGN))))
pprintf(p, "Moves NOT mailed, perhaps your address is incorrect.\n");
else
pprintf(p, "Moves mailed.\n");
} else {
- pprintf(p, "%s\n", movesToString(g, 0));
+ pprintf_noformat(p, "%s\n", movesToString(g, 0));
} /* Do smoves */
}
}
int white_k = 0;
int black_k = 0;
- for (f = 0; (f < 8); f++) {
- for (r = 0; (r < 8); r++) {
+ for (f = 0; (f < b->files); f++) {
+ for (r = 0; (r < b->ranks); r++) {
if (b->board[f][r] == W_KING) {
white_k += 1;
if (white_k == 2) {
}
}
if (((b->board[f][r] == W_PAWN) || (b->board[f][r] == B_PAWN)) &&
- ((r == 0) || (r == 7))) {
+ ((r == 0) || (r == b->ranks-1))) {
pprintf (p,"Pawns cannot be placed on the first or eighth rank.\n");
return 0;
}
pprintf(p,"The position is not valid - staying in setup mode.\n");
return COM_OK;
} else { /* try to load a category of board */
- if (param[1].type != TYPE_NULL) {
- if (!board_init (pp->game,&(game_globals.garray[pp->game].game_state),param[0].val.word,param[1].val.word)) {
+ char *board = param[1].val.word;
+ if (param[1].type == TYPE_NULL) board = "0";
+ game_globals.garray[pp->game].FENstartPos[0] = 0; // [HGM] new shuffle
+ if (!board_init (pp->game,&(game_globals.garray[pp->game].game_state),param[0].val.word,board)) {
game_globals.garray[pp->game].game_state.gameNum = gamenum;
+ if(!strcmp(board,"0"))
+ sprintf(game_globals.garray[pp->game].variant, "%s",param[0].val.word);
+ else
+ sprintf(game_globals.garray[pp->game].variant, "%s/%s",param[0].val.word,board);
send_board_to(pp->game, p);
- pprintf (p,"Board set up as %s %s.\n",param[0].val.word,param[1].val.word);
+ pprintf (p,"Board set up as %s %s.\n",param[0].val.word,board);
} else {
- pprintf (p,"Board %s %s is unavailable.\n",param[0].val.word,param[1].val.word);
+ pprintf (p,"Board %s %s is unavailable.\n",param[0].val.word,board);
game_globals.garray[pp->game].game_state.gameNum = gamenum;
}
return COM_OK;
- }
+
}
}
pprintf (p, "You have supplied an incorrect parameter to setup.\n");
/*check wp@e3 */
} else if (dropstr[0] == 'w') {
- piece = CharToPiece(dropstr[1]) & 0x07;
+ piece = CharToPiece(dropstr[1], game_globals.garray[g].game_state.variant) & 0x7F;
color = WHITE;
getsquare(dropstr+3,&f,&r);
} else if (len == 5) { /* check length to avoid b@e2 and bb@e2 being confused */
if (dropstr[0] == 'b') {
- piece = CharToPiece(dropstr[1]) | BLACK;
+ piece = CharToPiece(dropstr[1], game_globals.garray[g].game_state.variant) | BLACK;
getsquare(dropstr+3,&f,&r);
}
if (!((dropstr[1] == '@') || (dropstr[1] == '*')))
return 0;
else {
- piece = CharToPiece(dropstr[0]);
+ piece = CharToPiece(dropstr[0], game_globals.garray[g].game_state.variant);
getsquare(dropstr+2,&f,&r);
}
}
g = pp->game;
else
g = pp->observe_list[0];
+ if(pp->game == g) { // [HGM] capture engine kibitz of player
+ float score; int depth;
+ if(sscanf(param[0].val.string, "!!! %f/%d", &score, &depth) == 2) {
+ struct game *gg = &game_globals.garray[g];
+ if(gg->numHalfMoves && gg->status == GAME_ACTIVE) {
+ int n = gg->numHalfMoves-1;
+ if(n && (gg->game_state.onMove == WHITE && gg->black != p ||
+ gg->game_state.onMove == BLACK && gg->white != p )) n--;
+ gg->moveList[n].score = score;
+ gg->moveList[n].depth = depth;
+ }
+ }
+ }
for (p1 = 0; p1 < player_globals.p_num; p1++) {
if ((p1 == p) || (player_globals.parray[p1].status != PLAYER_PROMPT))
continue;
#include "includes.h"
-static int safestring(char *str);
+int safestring(char *str);
char *eatword(char *str)
{
return (isprint(c) && !strchr(">!&*?/<|`$;", c));
}
-static int safestring(char *str)
+int safestring(char *str)
{
int i;
#endif
}
-static var_list variables[] = {
+var_list variables[] = {
{"ads", set_ads},
{"availinfo", set_availinfo},
{"availmax", set_availmax},