X-Git-Url: http://winboard.nl/cgi-bin?p=capablanca.git;a=blobdiff_plain;f=lasker-2.2.3%2Fsrc%2Fmovecheck.c;h=61bc64c67b43ebeb2c0f3d6a99ae3179e7658b5c;hp=edeeea74e683b9e97d120cdeb8365c9da0303167;hb=5317b80b41045bd23473faf4748a9539a06e5f52;hpb=3f31178e2168d0dc5ca0db4e245c63c25bb7ed1d diff --git a/lasker-2.2.3/src/movecheck.c b/lasker-2.2.3/src/movecheck.c index edeeea7..61bc64c 100644 --- a/lasker-2.2.3/src/movecheck.c +++ b/lasker-2.2.3/src/movecheck.c @@ -45,13 +45,13 @@ int is_move(const char *mstr) { int len = strlen(mstr); - if ((len > 3) && (mstr[len - 2] == '=')) - len -= 2; - /* remove the 'mates' marker */ if (mstr[len - 1] == '#') len--; + if ((len > 3) && (mstr[len - 2] == '=' || mstr[len - 2] == '/')) + len -= 2; + if (len == 4) { /* Test for e2e4 */ if (isfile(mstr[0]) && isrank(mstr[1]) && isfile(mstr[2]) && isrank(mstr[3])) { @@ -570,16 +570,18 @@ static int legal_king_move(struct game_state_t * gs, int ff, int fr, int tf, int if (gs->onMove == WHITE) { /* King side castling */ - if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->wkmoved >= 0) - && (gs->wkrmoved >= 0) && (gs->board[gs->files-3][0] == NOPIECE) && + if ((fr == 0) && (tr == 0) && ((ff == gs->files/2) && (tf == gs->files-2) || + gs->drops == 2 && (tf == gs->files/2) && (ff == gs->files-1)) // [HGM] reverse Seirawan gating + && (gs->wkmoved >= 0) && (gs->wkrmoved >= 0) && (gs->board[gs->files-3][0] == NOPIECE) && (gs->board[gs->files-2][0] == NOPIECE) && (gs->board[gs->files-1][0] == W_ROOK) && (gs->board[gs->files/2+1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, 0)) && (!is_square_attacked(gs, gs->files/2, 0)) && (!is_square_attacked(gs, gs->files-3, 0))) { return 2; } /* Queen side castling */ - if ((fr == 0) && (tr == 0) && (ff == gs->files/2) && (tf == 2) && (gs->wkmoved >= 0) - && (gs->wqrmoved >= 0) && (gs->board[3][0] == NOPIECE) && + if ((fr == 0) && (tr == 0) && ((ff == gs->files/2) && (tf == 2) || + gs->drops == 2 && (tf == gs->files/2) && (ff == 0)) // [HGM] reverse Seirawan gating + && (gs->wkmoved >= 0) && (gs->wqrmoved >= 0) && (gs->board[3][0] == NOPIECE) && (gs->board[2][0] == NOPIECE) && (gs->board[1][0] == NOPIECE) && (gs->board[0][0] == W_ROOK) && (gs->board[gs->files/2-1][0] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, 0)) && @@ -588,16 +590,18 @@ static int legal_king_move(struct game_state_t * gs, int ff, int fr, int tf, int } } else { /* Black */ /* King side castling */ - if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == gs->files-2) && (gs->bkmoved >= 0) - && (gs->bkrmoved >= 0) && (gs->board[gs->files-3][7] == NOPIECE) && + if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && ((ff == gs->files/2) && (tf == gs->files-2) || + gs->drops == 2 && (tf == gs->files/2) && (ff == gs->files-1)) // [HGM] reverse Seirawan gating + && (gs->bkmoved >= 0) && (gs->bkrmoved >= 0) && (gs->board[gs->files-3][7] == NOPIECE) && (gs->board[gs->files-2][gs->ranks-1] == NOPIECE) && (gs->board[gs->files-1][gs->ranks-1] == B_ROOK) && (gs->board[gs->files/2+1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2+1, gs->ranks-1)) && (!is_square_attacked(gs, gs->files/2, gs->ranks-1)) && (!is_square_attacked(gs, gs->files-3, gs->ranks-1))) { return 2; } /* Queen side castling */ - if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && (ff == gs->files/2) && (tf == 2) && (gs->bkmoved >= 0) - && (gs->bqrmoved >= 0) && (gs->board[3][gs->ranks-1] == NOPIECE) && + if ((fr == gs->ranks-1) && (tr == gs->ranks-1) && ((ff == gs->files/2) && (tf == 2) || + gs->drops == 2 && (tf == gs->files/2) && (ff == 0)) // [HGM] reverse Seirawan gating + && (gs->bkmoved >= 0) && (gs->bqrmoved >= 0) && (gs->board[3][gs->ranks-1] == NOPIECE) && (gs->board[2][gs->ranks-1] == NOPIECE) && (gs->board[1][gs->ranks-1] == NOPIECE) && (gs->board[0][gs->ranks-1] == B_ROOK) && (gs->board[gs->files/2-1][gs->ranks-1] == NOPIECE) && (!is_square_attacked(gs, gs->files/2-1, gs->ranks-1)) && @@ -1291,7 +1295,7 @@ int legal_move(struct game_state_t * gs, int fFile, int fRank, int tFile, int tRank) { - int move_piece; + int move_piece, victim; int legal; if (fFile == ALG_DROP) { @@ -1369,9 +1373,15 @@ int legal_move(struct game_state_t * gs, return 0; if (!iscolor(gs->board[fFile][fRank], gs->onMove)) /* Wrong color */ return 0; - if ((gs->board[tFile][tRank] != NOPIECE) && - iscolor(gs->board[tFile][tRank], gs->onMove)) /* Can't capture own */ - return 0; + if (((victim = gs->board[tFile][tRank]) != NOPIECE) && + iscolor(gs->board[tFile][tRank], gs->onMove)) { + if(piecetype(move_piece) == KING && piecetype(victim) == ROOK) { // [HGM] could be FRC castling + } + if(gs->drops== 2 && piecetype(move_piece) == ROOK && piecetype(victim) == KING) { // [HGM] could be Seirawan reverse gating + return legal_king_move(gs, fFile, fRank, tFile, tRank); + } + return 0; /* Can't capture own */ + } if ((fFile == tFile) && (fRank == tRank)) /* Same square */ return 0; switch (move_piece) { @@ -1500,8 +1510,11 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom } 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"); - if(gs->drops == 2 && promote && gs->holding[gs->onMove == BLACK][promote-1]) - mt->piecePromotionTo = promote, gating = 1; + if(gs->drops == 2 && promote && gs->holding[gs->onMove == BLACK][abs(promote)-1]) { // promote can be flipped (reverse gating kludge) + int c = gs->onMove == WHITE ? 0 : gs->ranks-1; + mt->piecePromotionTo = promote; gating = 1; + if(promote < 0) sprintf(mt->moveString, "R/%c%d-e%d", mt->fromRank + 'a', c, c); // use RxK notation for Rook-square gatings + } } else { stm = colorval(gs->board[mt->fromFile][mt->fromRank]); if(gs->promoType == 3) { // Shogi-style promotions: not just Pawns, but many pieces can promote @@ -1556,7 +1569,9 @@ static int move_calculate(struct game_state_t * gs, struct move_t * mt, int prom // now we must test virginity of the moved piece. Yegh! for (i = g->numHalfMoves-1; i >= 0; i--) { if (g->moveList[i].fromFile == mt->fromFile && g->moveList[i].fromRank == mt->fromRank || - g->moveList[i].toFile == mt->fromFile && g->moveList[i].toRank == mt->fromRank) return MOVE_ILLEGAL; + g->moveList[i].toFile == mt->fromFile && g->moveList[i].toRank == mt->fromRank || + g->moveList[i].fromFile == ALG_CASTLE && (gs->onMove == WHITE ? 0 : gs->ranks-1) == mt->fromRank && + (g->moveList[i].fromRank == mt->fromFile || gs->files>>1 == mt->fromFile )) return MOVE_ILLEGAL; } mt->piecePromotionTo = promote; // gating OK gating = 1; // remember we did it for check test @@ -1811,7 +1826,7 @@ int has_legal_move(struct game_state_t * gs) int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int promote) { int type = is_move(mstr); - int result; + int result, flipflag = 1; mt->piecePromotionTo = NOPIECE; mt->color = gs->onMove; @@ -1886,6 +1901,11 @@ int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int pro return MOVE_ILLEGAL; if(result == 2) { // [HGM] castle: orthodox castling was given as King move; convert it to new format + int ff=mt->fromFile, tf=mt->toFile; + if(piecetype(gs->board[tf][mt->toRank]) == KING) { // [HGM] RxK notation + mt->fromFile = tf; mt->toFile = ff > tf ? gs->files-2 : 2; // correct to coventional + flipflag = -1; // kludge: flip gated piece + } if(mt->fromFile - mt->toFile > 1) { // Q-side mt->fromRank = 0; mt->toRank = mt->toFile+1; @@ -1904,7 +1924,7 @@ int parse_move(char *mstr, struct game_state_t * gs, struct move_t * mt, int pro if(gs->drops == 2 && promote == DRAGONHORSE) promote = HAWK; } - return move_calculate(gs, mt, promote); + return move_calculate(gs, mt, promote*flipflag); } /* Returns MOVE_OK, MOVE_NOMATERIAL, MOVE_CHECKMATE, or MOVE_STALEMATE */ @@ -1942,8 +1962,11 @@ int execute_move(struct game_state_t * gs, struct move_t * mt, int check_game_st gs->board[mt->toRank][backRank] = rook; // then put back gs->board[mt->toFile][backRank] = king; if(gs->drops == 2 && mt->piecePromotionTo != NOPIECE) { // [HGM] Seirawan-style gating - gs->board[fKing][backRank] = mt->piecePromotionTo | gs->onMove; // for now always on King square - gs->holding[gs->onMove==WHITE ? 0 : 1][mt->piecePromotionTo-1]--; // remove gated piece from holdings + if(mt->piecePromotionTo > 0) + gs->board[fKing][backRank] = mt->piecePromotionTo | gs->onMove; // gate on King square + else + gs->board[mt->fromRank][backRank] = -mt->piecePromotionTo | gs->onMove; // gate on Rook square + gs->holding[gs->onMove==WHITE ? 0 : 1][abs(mt->piecePromotionTo)-1]--; // remove gated piece from holdings } } else { movedPiece = gs->board[mt->fromFile][mt->fromRank]; @@ -2142,10 +2165,17 @@ int backup_move(int g, int mode) // 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 + if(gs->board[m->fromRank][rank] != NOPIECE) + gs->holding[gs->onMove==WHITE ? 1 : 0][piecetype(gs->board[m->fromRank][rank])-1]++; // put back in holdings (onMove not flipped yet!) + if(gs->board[kingFromFile][rank] != NOPIECE) + gs->holding[gs->onMove==WHITE ? 1 : 0][piecetype(gs->board[kingFromFile][rank])-1]++; // put back in holdings (onMove not flipped yet!) gs->board[m->fromRank][rank] = ROOK | m->color; // Rook fromSqr gs->board[kingFromFile][rank] = KING | m->color; // King fromSquare goto cleanupMove; } + if(gs->board[m->fromFile][m->fromRank] != NOPIECE) { // [HGM] from-square occupied; move must have been Seirawan-style gating + gs->holding[gs->onMove==WHITE ? 1 : 0][piecetype(gs->board[m->fromFile][m->fromRank])-1]++; // put back in holdings (onMove not flipped yet!) + } gs->board[m->fromFile][m->fromRank] = gs->board[m->toFile][m->toRank]; if (m->piecePromotionTo != NOPIECE) { gs->board[m->fromFile][m->fromRank] = PAWN | @@ -2275,9 +2305,6 @@ int backup_move(int g, int mode) goto cleanupMove; } gs->board[m->toFile][m->toRank] = m->pieceCaptured; - if(gs->board[m->fromFile][m->fromRank] != NOPIECE) { // [HGM] from-square occupied, must have been Seirawan-style gating - gs->holding[gs->onMove==WHITE ? 1 : 0][piecetype(gs->board[m->fromFile][m->fromRank])-1]++; // put back in holdings (onMove not flipped yet!) - } cleanupMove: if (game_globals.garray[g].status != GAME_EXAMINE) { game_update_time(g);