Author: Jarkko Pesonen
Date: 15:13:20 09/04/05
Go up one level in this thread
// option.cpp
// includes
#include <cstdlib>
#include "option.h"
#include "protocol.h"
#include "util.h"
// types
struct option_t {
const char * var;
bool declare;
const char * init;
const char * type;
const char * extra;
const char * val;
};
// variables
option_t Option[] = {
{ "Hash", true, "16", "spin", "min 4 max 1024", NULL },
{ "Ponder", true, "false", "check", "", NULL },
{ "OwnBook", true, "true", "check", "", NULL },
{ "BookFile", true, "book_small.bin", "string", "", NULL },
{ "NullMove Pruning", true, "Fail High", "combo", "var Always var Fail
High var Never", NULL },
{ "NullMove Reduction", true, "3", "spin", "min 1 max 3", NULL
},
{ "Verification Search", true, "Endgame", "combo", "var Always var
Endgame var Never", NULL },
{ "Verification Reduction", true, "5", "spin", "min 1 max 6", NULL
},
{ "History Pruning", true, "true", "check", "", NULL },
{ "History Threshold", true, "60", "spin", "min 0 max 100", NULL },
{ "Futility Pruning", true, "false", "check", "", NULL },
{ "Futility Margin", true, "100", "spin", "min 0 max 500", NULL },
{ "Delta Pruning", true, "false", "check", "", NULL },
{ "Delta Margin", true, "50", "spin", "min 0 max 500", NULL },
{ "Quiescence Check Plies", true, "1", "spin", "min 0 max 2", NULL },
{ "Material", true, "100", "spin", "min 0 max 400", NULL },
{ "Piece Activity", true, "100", "spin", "min 0 max 400", NULL },
{ "King Safety", true, "100", "spin", "min 0 max 400", NULL },
{ "Pawn Structure", true, "100", "spin", "min 0 max 400", NULL },
{ "Passed Pawns", true, "100", "spin", "min 0 max 400", NULL },
{ "MultiPV", true, "1", "spin", "min 1 max 10", NULL },
{ NULL, false, NULL, NULL, NULL, NULL, },
};
// prototypes
static option_t * option_find (const char var[]);
// functions
// option_init()
void option_init() {
option_t * opt;
for (opt = &Option[0]; opt->var != NULL; opt++) {
option_set(opt->var,opt->init);
}
}
// option_list()
void option_list() {
option_t * opt;
for (opt = &Option[0]; opt->var != NULL; opt++) {
if (opt->declare) {
if (opt->extra != NULL && *opt->extra != '\0') {
send("option name %s type %s default %s
%s",opt->var,opt->type,opt->val,opt->extra);
} else {
send("option name %s type %s default
%s",opt->var,opt->type,opt->val);
}
}
}
}
// option_set()
bool option_set(const char var[], const char val[]) {
option_t * opt;
ASSERT(var!=NULL);
ASSERT(val!=NULL);
opt = option_find(var);
if (opt == NULL) return false;
my_string_set(&opt->val,val);
return true;
}
// option_get()
const char * option_get(const char var[]) {
option_t * opt;
ASSERT(var!=NULL);
opt = option_find(var);
if (opt == NULL) my_fatal("option_get(): unknown option \"%s\"\n",var);
return opt->val;
}
// option_get_bool()
bool option_get_bool(const char var[]) {
const char * val;
val = option_get(var);
if (false) {
} else if (my_string_equal(val,"true") || my_string_equal(val,"yes") ||
my_string_equal(val,"1")) {
return true;
} else if (my_string_equal(val,"false") || my_string_equal(val,"no") ||
my_string_equal(val,"0")) {
return false;
}
ASSERT(false);
return false;
}
// option_get_int()
int option_get_int(const char var[]) {
const char * val;
val = option_get(var);
return atoi(val);
}
// option_get_string()
const char * option_get_string(const char var[]) {
const char * val;
val = option_get(var);
return val;
}
// option_find()
static option_t * option_find(const char var[]) {
option_t * opt;
ASSERT(var!=NULL);
for (opt = &Option[0]; opt->var != NULL; opt++) {
if (my_string_equal(opt->var,var)) return opt;
}
return NULL;
}
// end of option.cpp
/////////////////////////////////////////////////////////////////////////////
// search.cpp
// includes
#include <csetjmp>
#include <string.h>
#include <stdlib.h>
#include <minmax.h>
#include <memory.h>
#include <math.h>
#include "attack.h"
#include "board.h"
#include "book.h"
#include "colour.h"
#include "list.h"
#include "material.h"
#include "move.h"
#include "move_do.h"
#include "move_gen.h"
#include "option.h"
#include "pawn.h"
#include "protocol.h"
#include "pv.h"
#include "search.h"
#include "search_full.h"
#include "sort.h"
#include "trans.h"
#include "util.h"
#include "value.h"
// constants
static const bool UseCpuTime = false; // false
static const bool UseEvent = true; // true
static const bool UseShortSearch = true;
static const int ShortSearchDepth = 1;
static const bool DispBest = true; // true
static const bool DispDepthStart = true; // true
static const bool DispDepthEnd = true; // true
static const bool DispRoot = true; // true
static const bool DispStat = true; // true
static const bool UseEasy = true; // singular move
static const int EasyThreshold = 150;
static const double EasyRatio = 0.20;
static const bool UseEarly = true; // early iteration end
static const double EarlyRatio = 0.60;
static const bool UseBad = true;
static const int BadThreshold = 50; // 50
static const bool UseExtension = true;
// variables
search_input_t SearchInput[1];
search_info_t SearchInfo[1];
search_root_t SearchRoot[1],SearchMultiStart[1];
search_current_t SearchCurrent[1];
search_best_t SearchBest[1];
multi_t multiV[10];
// prototypes
static void search_send_stat ();
// functions
// depth_is_ok()
bool depth_is_ok(int depth) {
return depth > -128 && depth < DepthMax;
}
// height_is_ok()
bool height_is_ok(int height) {
return height >= 0 && height < HeightMax;
}
// search_clear()
void search_clear() {
// SearchInput
SearchInput->infinite = false;
SearchInput->depth_is_limited = false;
SearchInput->depth_limit = 0;
SearchInput->time_is_limited = false;
SearchInput->time_limit_1 = 0.0;
SearchInput->time_limit_2 = 0.0;
// SearchInfo
SearchInfo->can_stop = false;
SearchInfo->stop = false;
SearchInfo->check_nb = 10000; // was 100000
SearchInfo->check_inc = 10000; // was 100000
SearchInfo->last_time = 0.0;
// SearchBest
SearchBest->move = MoveNone;
SearchBest->value = 0;
SearchBest->flags = SearchUnknown;
PV_CLEAR(SearchBest->pv);
// SearchRoot
SearchRoot->depth = 0;
SearchRoot->move = MoveNone;
SearchRoot->move_pos = 0;
SearchRoot->move_nb = 0;
SearchRoot->last_value = 0;
SearchRoot->bad_1 = false;
SearchRoot->bad_2 = false;
SearchRoot->change = false;
SearchRoot->easy = false;
SearchRoot->flag = false;
SearchRoot->multiPV = 1;
// SearchCurrent
SearchCurrent->max_depth = 0;
SearchCurrent->node_nb = 0;
SearchCurrent->time = 0.0;
SearchCurrent->speed = 0.0;
SearchCurrent->cpu = 0.0;
}
void bubblesort( multi_t *sortv,int n)
{
int i,j;
multi_t temp;
for (i=0; i < n-1; i++) {
for (j=0; j < n-1-i; j++)
if (sortv[j+1].value > sortv[j].value) { /* compare the two neighbors */
memcpy(&temp,&sortv[j],sizeof(multi_t)); /* swap a[j] and a[j+1]
*/
memcpy(&sortv[j],&sortv[j+1],sizeof(multi_t));
memcpy(&sortv[j+1], &temp,sizeof(multi_t));
}
}
}
// search()
int multiBegin;
void search() {
int move;
int depth;
const char *mv;
char multi;
int idx,i;
ASSERT(board_is_ok(SearchInput->board));
// opening book
if (option_get_bool("OwnBook") && !SearchInput->infinite) {
move = book_move(SearchInput->board);
if (move != MoveNone) {
// play book move
SearchBest->move = move;
SearchBest->value = 1;
SearchBest->flags = SearchExact;
SearchBest->depth = 1;
SearchBest->pv[0] = move;
SearchBest->pv[1] = MoveNone;
search_update_best();
return;
}
}
// SearchInput
gen_legal_moves(SearchInput->list,SearchInput->board);
if (LIST_SIZE(SearchInput->list) <= 1) {
SearchInput->depth_is_limited = true;
SearchInput->depth_limit = 4; // was 1
}
// SearchInfo
if (setjmp(SearchInfo->buf) != 0) {
ASSERT(SearchInfo->can_stop);
ASSERT(SearchBest->move!=MoveNone);
search_update_current();
return;
}
// SearchRoot
list_copy(SearchRoot->list,SearchInput->list);
// SearchCurrent
board_copy(SearchCurrent->board,SearchInput->board);
my_timer_reset(SearchCurrent->timer);
my_timer_start(SearchCurrent->timer);
// init
trans_inc_date(Trans);
sort_init();
search_full_init(SearchRoot->list,SearchCurrent->board);
// iterative deepening
for (depth = 1; depth < DepthMax; depth++) {
if (DispDepthStart) send("info depth %d",depth);
mv=&multi;
mv=option_get("MultiPV");
multiBegin=min(SearchRoot->multiPV = atoi(mv),SearchRoot->list->size);
SearchRoot->bad_1 = false;
SearchRoot->change = false;
multiPV:
board_copy(SearchCurrent->board,SearchInput->board);
if (UseShortSearch && depth <= ShortSearchDepth) {
search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchShort);
} else {
search_full_root(SearchRoot->list,SearchCurrent->board,depth,SearchNormal);
}
if(SearchRoot->multiPV==multiBegin)
list_copy(SearchMultiStart->list,SearchRoot->list);
search_update_current();
if (DispDepthEnd) {
send("info depth %d seldepth %d time %.0f nodes " S64_FORMAT " nps
%.0f",depth,SearchCurrent->max_depth,SearchCurrent->time*1000.0,SearchCurrent->node_nb,SearchCurrent->speed);
}
if(SearchRoot->multiPV > 1){
idx=list_get_index( SearchRoot->list, SearchBest->move);
list_remove( SearchRoot->list, idx) ;
SearchRoot->multiPV--;
SearchRoot->change = true;
goto multiPV;
}
// update search info
if (depth >= 1) SearchInfo->can_stop = true;
if (depth == 1
&& LIST_SIZE(SearchRoot->list) >= 2
&& LIST_VALUE(SearchRoot->list,0) >= LIST_VALUE(SearchRoot->list,1) +
EasyThreshold) {
SearchRoot->easy = true;
}
if (UseBad && depth > 1) {
SearchRoot->bad_2 = SearchRoot->bad_1;
SearchRoot->bad_1 = false;
ASSERT(SearchRoot->bad_2==(SearchBest->value<=SearchRoot->last_value-BadThreshold));
}
SearchRoot->last_value = SearchBest->value;
// stop search?
if (SearchInput->depth_is_limited
&& depth >= SearchInput->depth_limit) {
SearchRoot->flag = true;
}
if (SearchInput->time_is_limited
&& SearchCurrent->time >= SearchInput->time_limit_1
&& !SearchRoot->bad_2) {
SearchRoot->flag = true;
}
if (UseEasy
&& SearchInput->time_is_limited
&& SearchCurrent->time >= SearchInput->time_limit_1 * EasyRatio
&& SearchRoot->easy) {
ASSERT(!SearchRoot->bad_2);
ASSERT(!SearchRoot->change);
SearchRoot->flag = true;
}
if (UseEarly
&& SearchInput->time_is_limited
&& SearchCurrent->time >= SearchInput->time_limit_1 * EarlyRatio
&& !SearchRoot->bad_2
&& !SearchRoot->change) {
SearchRoot->flag = true;
}
if (SearchInfo->can_stop
&& (SearchInfo->stop || (SearchRoot->flag && !SearchInput->infinite))) {
break;
}
list_copy(SearchRoot->list,SearchMultiStart->list);
for(i=0;i<multiBegin;i++){
idx=list_get_index(SearchRoot->list, multiV[i].move);
SearchRoot->list->value[idx]=multiV[i].value;
}
list_sort(SearchRoot->list);
}
}
// search_update_best()
void search_update_best() {
int move, value, flags, depth, max_depth;
const mv_t * pv;
double time;
sint64 node_nb;
int mate;
char move_string[256], pv_string[512],multi;
const char *mv;
search_update_current();
if (DispBest) {
move = SearchBest->move;
value = SearchBest->value;
flags = SearchBest->flags;
depth = SearchBest->depth;
pv = SearchBest->pv;
max_depth = SearchCurrent->max_depth;
time = SearchCurrent->time;
node_nb = SearchCurrent->node_nb;
move_to_string(move,move_string,256);
pv_to_string(pv,pv_string,512);
mate = value_to_mate(value);
if (mate == 0) {
// normal evaluation
if( multiBegin==1){
if (false) {
} else if (flags == SearchExact) {
send("info depth %d seldepth %d score cp %d time %.0f nodes "
S64_FORMAT " pv %s",depth,max_depth,value,time*1000.0,node_nb,pv_string);
} else if (flags == SearchLower) {
send("info depth %d seldepth %d score cp %d lowerbound time %.0f
nodes " S64_FORMAT " pv
%s",depth,max_depth,value,time*1000.0,node_nb,pv_string);
} else if (flags == SearchUpper) {
send("info depth %d seldepth %d score cp %d upperbound time %.0f
nodes " S64_FORMAT " pv
%s",depth,max_depth,value,time*1000.0,node_nb,pv_string);
}
}
mv=&multi;
mv=option_get("MultiPV");
multiV[multiBegin-SearchRoot->multiPV].value=value;
multiV[multiBegin-SearchRoot->multiPV].move=move;
multiV[multiBegin-SearchRoot->multiPV].nodes=node_nb;
multiV[multiBegin-SearchRoot->multiPV].mate=0;
strcpy(multiV[multiBegin-SearchRoot->multiPV].pv,pv_string);
if(multiBegin-SearchRoot->multiPV+1>1)
bubblesort( multiV, multiBegin-SearchRoot->multiPV+1);
if(SearchRoot->multiPV>=1){
for(int i=0;i<multiBegin-SearchRoot->multiPV+1;i++)
if(multiV[i].mate==1)
send("info multipv %d depth %d seldepth %d score mate %d nodes "
S64_FORMAT " nps 1031 hashfull 0 pv
%s",i+1,depth,max_depth,multiV[i].value,multiV[i].nodes,multiV[i].pv);
else
send("info multipv %d depth %d seldepth %d score cp %d nodes " S64_FORMAT
" nps 1031 hashfull 0 pv
%s",i+1,depth,max_depth,multiV[i].value,multiV[i].nodes,multiV[i].pv);
}
} else {
// mate announcement
if( multiBegin==1){
if (false) {
} else if (flags == SearchExact) {
send("info depth %d seldepth %d score mate %d time %.0f nodes "
S64_FORMAT " pv %s",depth,max_depth,mate,time*1000.0,node_nb,pv_string);
} else if (flags == SearchLower) {
send("info depth %d seldepth %d score mate %d lowerbound time %.0f
nodes " S64_FORMAT " pv %s",depth,max_depth,mate,time*1000.0,node_nb,pv_string);
} else if (flags == SearchUpper) {
send("info depth %d seldepth %d score mate %d upperbound time %.0f
nodes " S64_FORMAT " pv %s",depth,max_depth,mate,time*1000.0,node_nb,pv_string);
}
}
if(SearchRoot->multiPV>=1){
multiV[multiBegin-SearchRoot->multiPV].value=mate;
multiV[multiBegin-SearchRoot->multiPV].move=move;
multiV[multiBegin-SearchRoot->multiPV].nodes=node_nb;
strcpy(multiV[multiBegin-SearchRoot->multiPV].pv,pv_string);
multiV[multiBegin-SearchRoot->multiPV].mate=1;
if(multiBegin-SearchRoot->multiPV+1>1)
bubblesort( multiV, multiBegin-SearchRoot->multiPV+1);
for(int i=0;i<multiBegin-SearchRoot->multiPV+1;i++)
if(multiV[i].mate==1)
send("info multipv %d depth %d seldepth %d score mate %d nodes "
S64_FORMAT " nps 1031 hashfull 0 pv
%s",i+1,depth,max_depth,multiV[i].value,multiV[i].nodes,multiV[i].pv);
else
send("info multipv %d depth %d seldepth %d score cp %d nodes " S64_FORMAT
" nps 1031 hashfull 0 pv
%s",i+1,depth,max_depth,multiV[i].value,multiV[i].nodes,multiV[i].pv);
}
}
}
// update time-management info
if (UseBad && SearchBest->depth > 1) {
if (SearchBest->value <= SearchRoot->last_value - BadThreshold) {
SearchRoot->bad_1 = true;
SearchRoot->easy = false;
SearchRoot->flag = false;
} else {
SearchRoot->bad_1 = false;
}
}
}
// search_update_root()
void search_update_root() {
int move, move_pos, move_nb;
double time;
sint64 node_nb;
char move_string[256];
if (DispRoot) {
search_update_current();
if (SearchCurrent->time >= 1.0) {
move = SearchRoot->move;
move_pos = SearchRoot->move_pos;
move_nb = SearchRoot->move_nb;
time = SearchCurrent->time;
node_nb = SearchCurrent->node_nb;
move_to_string(move,move_string,256);
send("info currmove %s currmovenumber %d",move_string,move_pos+1);
}
}
}
// search_update_current()
void search_update_current() {
my_timer_t *timer;
sint64 node_nb;
double time, speed, cpu;
timer = SearchCurrent->timer;
node_nb = SearchCurrent->node_nb;
time = (UseCpuTime) ? my_timer_elapsed_cpu(timer) :
my_timer_elapsed_real(timer);
speed = (time >= 1.0) ? double(node_nb) / time : 0.0;
cpu = my_timer_cpu_usage(timer);
SearchCurrent->time = time;
SearchCurrent->speed = speed;
SearchCurrent->cpu = cpu;
}
// search_check()
void search_check() {
search_send_stat();
if (UseEvent) event();
if (SearchInput->depth_is_limited
&& SearchRoot->depth > SearchInput->depth_limit) {
SearchRoot->flag = true;
}
if (SearchInput->time_is_limited
&& SearchCurrent->time >= SearchInput->time_limit_2) {
SearchRoot->flag = true;
}
if (SearchInput->time_is_limited
&& SearchCurrent->time >= SearchInput->time_limit_1
&& !SearchRoot->bad_1
&& !SearchRoot->bad_2
&& (!UseExtension || SearchRoot->move_pos == 0)) {
SearchRoot->flag = true;
}
if (SearchInfo->can_stop
&& (SearchInfo->stop || (SearchRoot->flag && !SearchInput->infinite))) {
longjmp(SearchInfo->buf,1);
}
}
// search_send_stat()
static void search_send_stat() {
double time, speed, cpu;
sint64 node_nb;
search_update_current();
if (DispStat && SearchCurrent->time >= SearchInfo->last_time + 1.0) { // at
least one-second gap
SearchInfo->last_time = SearchCurrent->time;
time = SearchCurrent->time;
speed = SearchCurrent->speed;
cpu = SearchCurrent->cpu;
node_nb = SearchCurrent->node_nb;
send("info time %.0f nodes " S64_FORMAT " nps %.0f cpuload
%.0f",time*1000.0,node_nb,speed,cpu*1000.0);
trans_stats(Trans);
}
}
// end of search.cpp
///////////////////////////////////////////////////////////////////////////
// search.h
#ifndef SEARCH_H
#define SEARCH_H
// includes
#include <csetjmp>
#include "board.h"
#include "list.h"
#include "move.h"
#include "util.h"
// constants
const int DepthMax = 64;
const int HeightMax = 256;
const int SearchNormal = 0;
const int SearchShort = 1;
const int SearchUnknown = 0;
const int SearchUpper = 1;
const int SearchLower = 2;
const int SearchExact = 3;
// types
struct search_input_t {
board_t board[1];
list_t list[1];
bool infinite;
bool depth_is_limited;
int depth_limit;
bool time_is_limited;
double time_limit_1;
double time_limit_2;
};
struct search_info_t {
jmp_buf buf;
bool can_stop;
bool stop;
int check_nb;
int check_inc;
double last_time;
};
struct search_root_t {
list_t list[1];
int depth;
int move;
int move_pos;
int move_nb;
int last_value;
bool bad_1;
bool bad_2;
bool change;
bool easy;
bool flag;
int multiPV;
};
struct search_best_t {
int move;
int value;
int flags;
int depth;
mv_t pv[HeightMax];
};
struct search_current_t {
board_t board[1];
my_timer_t timer[1];
int max_depth;
sint64 node_nb;
double time;
double speed;
double cpu;
};
struct multi_t{
int value;
int move;
sint64 nodes;
char pv[512];
int mate;
};
// variables
extern search_input_t SearchInput[1];
extern search_info_t SearchInfo[1];
extern search_best_t SearchBest[1];
extern search_root_t SearchRoot[1];
extern search_current_t SearchCurrent[1];
// functions
extern bool depth_is_ok (int depth);
extern bool height_is_ok (int height);
extern void search_clear ();
extern void search ();
extern void search_update_best ();
extern void search_update_root ();
extern void search_update_current ();
extern void search_check ();
#endif // !defined SEARCH_H
// end of search.h
This page took 0 seconds to execute
Last modified: Thu, 15 Apr 21 08:11:13 -0700
Current Computer Chess Club Forums at Talkchess. This site by Sean Mintz.