draw.c   [plain text]


/*
    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;

};