home
***
CD-ROM
|
disk
|
FTP
|
other
***
search
/
Dream 57
/
Amiga_Dream_57.iso
/
Amiga
/
Jeux
/
Reflexion
/
Crafty-15.19.lha
/
crafty-15.19
/
src
/
searchr.c
< prev
next >
Wrap
C/C++ Source or Header
|
1998-09-13
|
12KB
|
299 lines
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include "chess.h"
#include "data.h"
#include "epdglue.h"
/* modified 06/05/98 */
/*
********************************************************************************
* *
* SearchRoot() is the recursive routine used to implement the alpha/beta *
* negamax search (similar to minimax but simpler to code.) SearchRoot() is *
* only called when ply=1. it is somewhat different from Search() in that *
* some things (null move search, hash lookup, etc.) are not useful at the *
* root of the tree. SearchRoot() calls Search() to search any positions *
* that are below ply=1. *
* *
********************************************************************************
*/
int SearchRoot(TREE *tree, int alpha, int beta, int wtm, int depth) {
register int first_move=1;
register int initial_alpha, value;
register int extensions, begin_root_nodes;
/*
----------------------------------------------------------
| |
| initialize. set NextMove() status to 0 so it will |
| know what has to be done. |
| |
----------------------------------------------------------
*/
tree->in_check[2]=0;
tree->extended_reason[2]=no_extension;
initial_alpha=alpha;
RepetitionCheck(tree,1,wtm);
tree->in_check[1]=Check(wtm);
tree->next_status[1].phase=ROOT_MOVES;
/*
----------------------------------------------------------
| |
| now iterate through the move list and search the |
| resulting positions. note that Search() culls any |
| move that is not legal by using Check(). the special |
| case is that we must find one legal move to search to |
| confirm that it's not a mate or draw. |
| |
----------------------------------------------------------
*/
while ((tree->current_phase[1]=NextRootMove(tree,wtm))) {
tree->extended_reason[1]=0;
#if !defined(FAST)
if (1 <= trace_level)
SearchTrace(tree,1,depth,wtm,alpha,beta,"SearchRoot",tree->current_phase[1]);
#endif
/*
----------------------------------------------------------
| |
| if we push a pawn to the 7th rank, we need to look |
| deeper to see if it can promote. |
| |
----------------------------------------------------------
*/
extensions=-60;
if (Piece(tree->current_move[1])==pawn &&
((wtm && To(tree->current_move[1]) > H5 && TotalBlackPieces<16 &&
!And(mask_pawn_passed_w[To(tree->current_move[1])],BlackPawns)) ||
(!wtm && To(tree->current_move[1]) < A4 && TotalWhitePieces<16 &&
!And(mask_pawn_passed_b[To(tree->current_move[1])],WhitePawns)) ||
push_extensions[To(tree->current_move[1])]) &&
Swap(tree,From(tree->current_move[1]),To(tree->current_move[1]),wtm) >= 0) {
tree->extended_reason[1]|=passed_pawn_extension;
tree->passed_pawn_extensions_done++;
extensions+=pushpp_depth;
}
/*
----------------------------------------------------------
| |
| now make the move and search the resulting position. |
| |
----------------------------------------------------------
*/
MakeMove(tree,1,tree->current_move[1],wtm);
/*
----------------------------------------------------------
| |
| if the move to be made checks the opponent, then we |
| need to remember that he's in check and also extend |
| the depth by one ply for him to get out. |
| |
----------------------------------------------------------
*/
if (Check(ChangeSide(wtm))) {
tree->in_check[2]=1;
tree->extended_reason[2]=check_extension;
tree->check_extensions_done++;
extensions+=incheck_depth;
}
else {
tree->in_check[2]=0;
tree->extended_reason[2]=no_extension;
}
/*
----------------------------------------------------------
| |
| now call Search to produce a value for this move. |
| |
----------------------------------------------------------
*/
begin_root_nodes=tree->nodes_searched;
extensions=Min(extensions,0);
if (first_move) {
value=-ABSearch(tree,-beta,-alpha,ChangeSide(wtm),
depth+extensions,2,DO_NULL);
if (abort_search) {
UnMakeMove(tree,1,tree->current_move[1],wtm);
return(alpha);
}
first_move=0;
}
else {
value=-ABSearch(tree,-alpha-1,-alpha,ChangeSide(wtm),
depth+extensions,2,DO_NULL);
if (abort_search) {
UnMakeMove(tree,1,tree->current_move[1],wtm);
return(alpha);
}
if ((value > alpha) && (value < beta)) {
value=-ABSearch(tree,-beta,-alpha,ChangeSide(wtm),
depth+extensions,2,DO_NULL);
if (abort_search) {
UnMakeMove(tree,1,tree->current_move[1],wtm);
return(alpha);
}
}
}
tree->root_nodes[root_move]=tree->nodes_searched-begin_root_nodes;
if (value > alpha) {
SearchOutput(tree,value,beta);
if(value >= beta) {
History(tree,1,depth,wtm,tree->current_move[1]);
UnMakeMove(tree,1,tree->current_move[1],wtm);
StoreRefutation(tree,1,depth,wtm,value,0);
return(value);
}
alpha=value;
root_value=alpha;
beta=alpha+30;
root_beta=beta;
}
UnMakeMove(tree,1,tree->current_move[1],wtm);
}
/*
----------------------------------------------------------
| |
| all moves have been searched. if none were legal, |
| return either MATE or DRAW depending on whether the |
| side to move is in check or not. |
| |
----------------------------------------------------------
*/
if (abort_search) return(0);
if (first_move == 1) {
value=(Check(wtm)) ? -(MATE-1) : DrawScore(root_wtm==wtm);
if (value >=alpha && value <beta) {
SavePVS(tree,1,value,0);
#if !defined(FAST)
if (1 <= trace_level) printf("Search() no moves! ply=1\n");
#endif
}
return(value);
}
else {
if (alpha != initial_alpha) {
memcpy(&tree->pv[0].path[1],&tree->pv[1].path[1],(tree->pv[1].path_length)*4);
memcpy(&tree->pv[0].path_hashed,&tree->pv[1].path_hashed,3);
History(tree,1,depth,wtm,tree->pv[1].path[1]);
}
StoreBest(tree,1,depth,wtm,alpha,initial_alpha,0);
return(alpha);
}
}
/* modified 03/11/98 */
/*
********************************************************************************
* *
* SearchOutput() is used to print the principal variation whenever it *
* changes. one additional feature is that SearchOutput() will try to do *
* something about variations truncated by the transposition table. if the *
* variation was cut short by a transposition table hit, then we can make the *
* last move, add it to the end of the variation and extend the depth of the *
* variation to cover it. *
* *
********************************************************************************
*/
void SearchOutput(TREE *tree, int value, int bound)
{
#define PrintOK() (tree->nodes_searched>noise_level || value>(MATE-100))
register int *mv, *mvp;
register int wtm;
int temp_root_nodes;
/*
----------------------------------------------------------
| |
| first, move the best move to the top of the ply-1 move |
| list if it's not already there, so that it will be the |
| first move tried in the next iteration. |
| |
----------------------------------------------------------
*/
wtm=root_wtm;
if (!abort_search) {
whisper_value=(analyze_mode && !root_wtm) ? -value : value;
whisper_depth=iteration_depth;
for (mvp=tree->last[0];mvp<tree->last[1];mvp++) if(tree->current_move[1]== *mvp) break;
if (mvp != tree->last[0]) {
temp_root_nodes=tree->root_nodes[mvp-tree->last[0]];
for (mv=mvp;mv>tree->last[0];mv--) {
*mv=*(mv-1);
tree->root_nodes[mv-tree->last[0]]=tree->root_nodes[mv-1-tree->last[0]];
}
tree->root_nodes[0]=temp_root_nodes;
*tree->last[0]=tree->current_move[1];
easy_move=0;
}
end_time=ReadClock(time_type);
/*
----------------------------------------------------------
| |
| if this is not a fail-high move, then output the PV |
| by walking down the path being backed up. |
| |
----------------------------------------------------------
*/
if(value < bound) {
UnMakeMove(tree,1,tree->pv[1].path[1],root_wtm);
DisplayPV(tree,6, wtm, end_time-start_time, value, &tree->pv[1]);
MakeMove(tree,1,tree->pv[1].path[1],root_wtm);
}
else {
if (PrintOK()) {
Print(2," %2i %s ++ ",iteration_depth,
DisplayTime(end_time-start_time));
UnMakeMove(tree,1,tree->current_move[1],wtm);
if (display_options&64) Print(2,"%d. ",move_number);
if ((display_options&64) && !wtm) Print(2,"... ");
Print(2,"%s!!\n",OutputMove(tree,tree->current_move[1],1,wtm));
whisper_text[0]=0;
if (display_options&64)
sprintf(whisper_text," %d.",move_number);
if ((display_options&64) && !wtm)
sprintf(whisper_text+strlen(whisper_text)," ...");
sprintf(whisper_text+strlen(whisper_text)," %s!!",
OutputMove(tree,tree->current_move[1],1,wtm));
MakeMove(tree,1,tree->current_move[1],wtm);
Whisper(6,iteration_depth,end_time-start_time,whisper_value,
tree->nodes_searched,-1,whisper_text);
}
if (tree->current_move[1] != tree->pv[1].path[1]) {
tree->pv[1].path[1]=tree->current_move[1];
tree->pv[1].path_length=1;
tree->pv[1].path_hashed=0;
tree->pv[1].path_iteration_depth=iteration_depth;
}
}
tree->pv[0]=tree->pv[1];
}
}
/* modified 03/11/98 */
/*
********************************************************************************
* *
* SearchTrace() is used to print the search trace output each time a node is *
* traversed in the tree. *
* *
********************************************************************************
*/
void SearchTrace(TREE *tree, int ply, int depth, int wtm,
int alpha, int beta, char* name, int phase)
{
int i;
#if defined(SMP)
Lock(lock_io);
#endif
for (i=1;i<ply;i++) printf(" ");
printf("%d %s d:%5.2f [%s,",ply,OutputMove(tree,tree->current_move[ply],ply,wtm),
(float) depth/ (float) INCREMENT_PLY,DisplayEvaluation(alpha));
printf("%s] n:%d %s(%d)", DisplayEvaluation(beta),
(tree->nodes_searched),name,phase);
if (max_threads > 1) printf(" (t=%d) ",tree->thread_id);
printf("\n");
#if defined(SMP)
UnLock(lock_io);
#endif
}