00001
00002
00003 #include "osl/search/quiescenceSearch.h"
00004 #include "osl/search/quiescenceLog.h"
00005
00006
00007 #include "osl/search/simpleHashTable.h"
00008 #include "osl/search/analyzer/dotAnalyzerAll.h"
00009 #include "osl/state/hashEffectState.h"
00010 #include "osl/effect_util/effectUtil.h"
00011 #include "osl/record/csaString.h"
00012 #include "osl/record/csaRecord.h"
00013 #include "osl/eval/pieceEval.h"
00014 #include "osl/eval/progressEval.h"
00015 #include "osl/misc/perfmon.h"
00016
00017 #include <iostream>
00018 #include <fstream>
00019
00020 using namespace osl;
00021 using namespace osl::search;
00022 using namespace osl::misc;
00023
00024 void qsearch(const char *filename);
00025
00026 void usage(const char *program_name)
00027 {
00028 std::cerr << program_name << " [-C] [-P] [-d depth] [-s skip] [-v] csafiles\n";
00029 std::cerr << "-C comparison w,w/o table\n";
00030 exit(1);
00031 }
00032
00033 int depth = -6;
00034 bool verbose = false;
00035 size_t skip_first = 0;
00036 bool comparison = false;
00037 bool use_progress_eval = false;
00038
00039 template <class Eval>
00040 void qsearch(const char *filename);
00041
00042 int main(int argc, char **argv)
00043 {
00044 const char *program_name = argv[0];
00045 bool error_flag = false;
00046
00047 extern char *optarg;
00048 extern int optind;
00049 char c;
00050 while ((c = getopt(argc, argv, "C:Pd:s:vh")) != EOF)
00051 {
00052 switch(c)
00053 {
00054 case 'C': comparison = true;
00055 break;
00056 case 'd': depth = atoi(optarg);
00057 break;
00058 case 'P': use_progress_eval = true;
00059 break;
00060 case 's': skip_first = atoi(optarg);
00061 break;
00062 case 'v': verbose = true;
00063 break;
00064 default: error_flag = true;
00065 }
00066 }
00067 argc -= optind;
00068 argv += optind;
00069
00070 if (error_flag || (argc < 1))
00071 usage(program_name);
00072
00073 std::cerr << "using table record depth " << depth << "\n";
00074 try
00075 {
00076 for (int i=0; i<argc; ++i)
00077 {
00078 if (use_progress_eval)
00079 qsearch<eval::ProgressEval>(argv[i]);
00080 else
00081 qsearch<PieceEval>(argv[i]);
00082 }
00083 }
00084 catch (std::exception& e)
00085 {
00086 std::cerr << e.what() << "\n";
00087 return 1;
00088 }
00089 catch (...)
00090 {
00091 throw;
00092 }
00093 }
00094
00095 template <class Eval>
00096 void qsearch(const char *filename)
00097 {
00098 unsigned long long total_cycles=0;
00099 unsigned long long positions = 0;
00100 Record rec=CsaFile(filename).getRecord();
00101 HashEffectState state(rec.getInitialState());
00102 const vector<osl::Move> moves=rec.getMoves();
00103
00104 typedef QuiescenceSearch<Eval> qsearch_t;
00105
00106 SimpleHashTable table(1000000,depth,verbose);
00107 SimpleHashTable nulltable(0,0,false);
00108 SearchStateCore::checkmate_t checkmate_searcher;
00109 Eval ev(state);
00110 size_t i=0;
00111 while (true)
00112 {
00113 if (i >= skip_first)
00114 {
00115 SearchStateCore core(state, checkmate_searcher);
00116 qsearch_t qs(core, table);
00117 qsearch_t qsnull(core, nulltable);
00118 const Move last_move = (i > 0) ? moves[i-1] : Move::PASS(alt(moves[0].player()));
00119 if (verbose)
00120 std::cerr << i << " " << last_move << "\n";
00121 if (verbose)
00122 {
00123 const char *logfile = "/tmp/q-w-table.log";
00124 unlink(logfile);
00125 QuiescenceLog::init(logfile);
00126 }
00127 PerfMon clock;
00128 const int val = qs.search(state.getTurn(), ev, last_move);
00129 total_cycles += clock.stop();
00130 if (comparison)
00131 {
00132 if (verbose)
00133 {
00134 const char *logfile = "/tmp/q-wo-table.log";
00135 unlink(logfile);
00136 QuiescenceLog::init(logfile);
00137 }
00138 const int valnull = qsnull.search(state.getTurn(), ev, last_move);
00139 if (verbose || (valnull != val))
00140 {
00141 std::cerr << state << "\n";
00142 std::cerr << ev.value() << " " ;
00143 if (! EffectUtil::isKingInCheck(state.getTurn(), state))
00144 std::cerr << ((state.getTurn() == BLACK)
00145 ? qs.template staticValueWithThreat<BLACK>(ev)
00146 : qs.template staticValueWithThreat<WHITE>(ev)) << " ";
00147 std::cerr << val << " " << valnull << "\n";
00148
00149 }
00150 }
00151 positions += qs.nodeCount();
00152 }
00153 if (i >= moves.size())
00154 break;
00155 const Move move = moves[i++];
00156 ApplyMoveOfTurn::doMove(state, move);
00157 ev.update(state, move);
00158 }
00159 const size_t checkmate_count = checkmate_searcher.totalNodeCount();
00160 std::cerr << total_cycles << " / ( " << positions
00161 << " + " << checkmate_count << " ) = "
00162 << total_cycles/(double)(positions + checkmate_count) << "\n";
00163 if (verbose)
00164 {
00165 std::ofstream os("quiescencestat.dot");
00166 search::analyzer::DotAnalyzerAll analyzer(table, os);
00167 analyzer.analyzeQuiescence(state.getHash());
00168 }
00169 }
00170
00171
00172
00173
00174
00175