/* Sjeng - a chess variants playing program Copyright (C) 2000-2001 Gian-Carlo Pascutto Originally based on Faile, Copyright (c) 2000 Adrien M. Regimbald 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., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA File: draw.c Purpose: Detect draws */ #include "config.h" #include "sjeng.h" #include "extvars.h" #include "protos.h" bool is_draw (void) { /* GCP: this is straigth from Faile but converted to Sjeng internals */ /* is_draw () is used to see if a position is a draw. Some notes: * - the 2 repetition trick is attempted first: if we have already seen a * position in the search history (not game history), we haven't found * anything better to do than repeat, and searching the position again would * be a waste of time * - if there is no match on the 2 repetition check, we look for an actual * 3 fold repetition * - we can't check for the 50 move rule here, since the 50 move rule must be * checked at the end of a search node due to mates on the 50th move, yet * we want to check for a draw by repetition before we waste any time * searching the position or generating moves * - is_draw () can be used in both search () and search_root () as the * for loop for the 2 repetition trick will exit immediately at the root */ int i, repeats = 0, end, start; /* Check on the 2 repetition trick. Some notes: * - a position can't possibly have occurred once before if fifty isn't * at least 4 * - the end point is picked to look at the least number of positions, ie * if going to the last capture is shorter than looking at the whole search * history, we will do only that much */ if (fifty >= 4) { if ((move_number) < (move_number + ply - 1 - fifty)) { end = move_number + ply - 1 - fifty; } else { end = move_number; } for (i = (move_number + ply - 3); i >= 0 && i >= end; i -= 2) { if (hash == hash_history[i]) { return TRUE; } } } /* Check for actual 3 repetition match. Some notes: * - a position can't possibly have occurred twice before if fifty isn't * at least 6 * - there is no need for us to consider positions encountered during search, * as if there was a match on any of them, it would have been found above * - we need to adjust the starting point here based on who's turn it is: * if it's the same as at the root, we need to subtract one extra */ if (fifty >= 6) { start = move_number - 1 - (ply % 2); end = move_number + ply - 1 - fifty; for (i = start; i >= 0 && i >= end; i -= 2) { if (hash == hash_history[i]) { repeats++; } if (repeats >= 2) { return TRUE; } } } return FALSE; };