strcpy(EndSymbol, "Bar");
rate_change = 1;
break;
+ case END_PERPETUAL:
+ sprintf(tmp, "%s perpetually checking} %s", NameOfLoser, winSymbol);
+ strcpy(EndSymbol, "Per");
+ rate_change = 1;
+ break;
case END_RESIGN:
sprintf(tmp, "%s resigns} %s", NameOfLoser, winSymbol);
strcpy(EndSymbol, "Res");
return 0;
}
+static int perp_check(struct game g, int first, int third)
+{
+ struct game_state_t gs = g.game_state; // current position, both first and last of loop
+ int half_move, no_perp = 0;
+printf("perp %d %d\n",first,third);
+ for(half_move=first+1; half_move<third; half_move++) {
+ gs.onMove = CToggle(gs.onMove);
+ if(!in_check(&gs)) no_perp |= (half_move&1) + 1; // 1 = white not in check, 2 = black not in check
+ gs.onMove = CToggle(gs.onMove);
+printf("move%d, p=%d\n",half_move,no_perp);
+ if(no_perp == 3) break;
+ execute_move(&gs, &g.moveList[half_move], 0);
+ }
+ if(no_perp == (third&1) + 1) return END_NOTENDED; // stm was checking, other not: defer judgement
+ if(no_perp == 2 - (third&1)) return END_PERPETUAL; // stm was not checking, other was: stm wins
+ if(no_perp == 0) return END_REPETITION; // mutual perpertual check, draw
+ // here we should check for chasing
+ return END_REPETITION;
+}
+
static char *GetFENpos (int g, int half_move)
{
if (half_move < 0)
{
struct player *pp = &player_globals.parray[p];
struct pending* pend;
- int move_num;
+ int move_num, s1, s2, result = END_REPETITION;
int flag1 = 1, flag2 = 1;
- char *pos1 = GetFENpos (g, game_globals.garray[g].numHalfMoves - 1);
- char *pos2 = GetFENpos (g, game_globals.garray[g].numHalfMoves);
+ int numPly = game_globals.garray[g].numHalfMoves;
+ char *pos1 = GetFENpos (g, numPly - 1); // current position
+ char *pos2 = "";
char *pos;
- if (game_globals.garray[g].numHalfMoves < 8) /* can't have three repeats any quicker. */
+ if (numPly < 8) /* can't have three repeats any quicker. */
return 0;
- for (move_num = game_globals.garray[g].game_state.lastIrreversable - 1; // [HGM] FEN stored in moveList[numHalfMoves-1] !
- move_num < game_globals.garray[g].numHalfMoves - 1; move_num++) {
+ if((game_globals.garray[g].white == p) != (numPly&1)) { // claimer has the move
+ pos2 = pos1;
+ pos1 = GetFENpos (g, numPly - 2); // also check position before opponent's move (which could have pre-empted him)
+ } // pos1 is now always a position where the opponent has the move
+
+ for (move_num = numPly - 2; // [HGM] FEN stored in moveList[numHalfMoves-1] !
+ move_num >= game_globals.garray[g].game_state.lastIrreversable - 1; move_num--) {
pos = GetFENpos (g, move_num);
if (strlen(pos1) == strlen(pos) && !strcmp(pos1, pos))
- flag1++;
+ flag1++ == 2 && (s1 = move_num);
if (strlen(pos2) == strlen(pos) && !strcmp(pos2, pos))
- flag2++;
-printf("%2d. %d-%d %s %s %s\n", move_num, flag1, flag2, pos1,pos2,pos);
+ flag2++ == 2 && (s2 = move_num); // remember start of last two loops
+printf("%2d. %d-%d '%s' '%s' '%s'\n", move_num, flag1, flag2, pos1,pos2,pos);
}
if (flag1 >= 3 || flag2 >= 3) {
if ((pend = find_pend(pp->opponent, p, PEND_DRAW)) != NULL) {
delete_pending(pend);
decline_withdraw_offers(p, -1, -1,DO_DECLINE);
}
- game_ended(g, (game_globals.garray[g].white == p) ? BLACK : WHITE, END_REPETITION);
+ if(game_globals.garray[g].game_state.palace) { // [HGM] in Xiangqi we have to test for perpetuals to determine the outcome
+ if(flag2 >= 3) result = perp_check(game_globals.garray[g], s2, numPly);
+ else result = perp_check(game_globals.garray[g], s1, numPly - (pos2[0] != 0));
+ if(result == END_NOTENDED) {
+ pprintf(p, "Perpetuals can be claimed only during the turn of the winner\n");
+ return 1;
+ }
+ game_ended(g, (numPly&1) ? BLACK : WHITE, result); // stm wins
+ return 1;
+ }
+ game_ended(g, (game_globals.garray[g].white == p) ? BLACK : WHITE, result);
return 1;
}
else return 0;