Subversion Repositories Games.Chess Giants

Rev

Details | Last modification | View Log | RSS feed

Rev Author Line No. Line
99 pmbaty 1
/*
2
    Texel - A UCI chess engine.
3
    Copyright (C) 2012-2014  Peter Ă–sterlund, peterosterlund2@gmail.com
4
 
5
    This program is free software: you can redistribute it and/or modify
6
    it under the terms of the GNU General Public License as published by
7
    the Free Software Foundation, either version 3 of the License, or
8
    (at your option) any later version.
9
 
10
    This program is distributed in the hope that it will be useful,
11
    but WITHOUT ANY WARRANTY; without even the implied warranty of
12
    MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13
    GNU General Public License for more details.
14
 
15
    You should have received a copy of the GNU General Public License
16
    along with this program.  If not, see <http://www.gnu.org/licenses/>.
17
*/
18
 
19
/*
20
 * computerPlayer.cpp
21
 *
22
 *  Created on: Feb 25, 2012
23
 *      Author: petero
24
 */
25
 
26
#include "computerPlayer.hpp"
27
#include "textio.hpp"
28
#include "tbprobe.hpp"
29
 
30
#include <iostream>
31
 
32
std::string ComputerPlayer::engineName;
33
 
34
 
35
static StaticInitializer<ComputerPlayer> cpInit;
36
 
37
void
38
ComputerPlayer::staticInitialize() {
39
    std::string name = "Texel 1.05";
40
    if (sizeof(char*) == 4)
41
        name += " 32-bit";
42
    if (sizeof(char*) == 8)
43
        name += " 64-bit";
44
    engineName = name;
45
}
46
 
47
void
48
ComputerPlayer::initEngine() {
49
    Parameters::instance();
50
 
51
    auto tbInit = []() {
52
        TBProbe::initialize(UciParams::gtbPath->getStringPar(),
53
                            UciParams::gtbCache->getIntPar(),
54
                            UciParams::rtbPath->getStringPar());
55
    };
56
    UciParams::gtbPath->addListener(tbInit);
57
    UciParams::gtbCache->addListener(tbInit, false);
58
    UciParams::rtbPath->addListener(tbInit, false);
59
 
60
    knightMobScore.addListener(Evaluate::updateEvalParams);
61
    castleFactor.addListener(Evaluate::updateEvalParams, false);
62
    pV.addListener([]() { pieceValue[Piece::WPAWN]   = pieceValue[Piece::BPAWN]   = pV; });
63
    nV.addListener([]() { pieceValue[Piece::WKNIGHT] = pieceValue[Piece::BKNIGHT] = nV; });
64
    bV.addListener([]() { pieceValue[Piece::WBISHOP] = pieceValue[Piece::BBISHOP] = bV; });
65
    rV.addListener([]() { pieceValue[Piece::WROOK]   = pieceValue[Piece::BROOK]   = rV; });
66
    qV.addListener([]() { pieceValue[Piece::WQUEEN]  = pieceValue[Piece::BQUEEN]  = qV; });
67
    kV.addListener([]() { pieceValue[Piece::WKING]   = pieceValue[Piece::BKING]   = kV; });
68
}
69
 
70
ComputerPlayer::ComputerPlayer()
71
    : tt(15), pd(tt),
72
      book(false)
73
{
74
    initEngine();
75
    et = Evaluate::getEvalHashTables();
76
    minTimeMillis = 10000;
77
    maxTimeMillis = 10000;
78
    maxDepth = 100;
79
    maxNodes = -1;
80
    verbose = true;
81
    bookEnabled = true;
82
    currentSearch = nullptr;
83
}
84
 
85
std::string
86
ComputerPlayer::getCommand(const Position& posIn, bool drawOffer, const std::vector<Position>& history) {
87
    // Create a search object
88
    std::vector<U64> posHashList(200 + history.size());
89
    int posHashListSize = 0;
90
    for (size_t i = 0; i < history.size(); i++)
91
        posHashList[posHashListSize++] = history[i].zobristHash();
92
    tt.nextGeneration();
93
    Position pos(posIn);
94
    KillerTable kt;
95
    History ht;
96
    Search::SearchTables st(tt, kt, ht, *et);
97
    TreeLogger treeLog;
98
    Search sc(pos, posHashList, posHashListSize, st, pd, nullptr, treeLog);
99
 
100
    // Determine all legal moves
101
    MoveList moves;
102
    MoveGen::pseudoLegalMoves(pos, moves);
103
    MoveGen::removeIllegal(pos, moves);
104
    sc.scoreMoveList(moves, 0);
105
 
106
    // Test for "game over"
107
    if (moves.size == 0) {
108
        // Switch sides so that the human can decide what to do next.
109
        return "swap";
110
    }
111
 
112
    if (bookEnabled) {
113
        Move bookMove;
114
        book.getBookMove(pos, bookMove);
115
        if (!bookMove.isEmpty()) {
116
            std::cout << "Book moves: " << book.getAllBookMoves(pos) << std::endl;
117
            return TextIO::moveToString(pos, bookMove, false);
118
        }
119
    }
120
 
121
    // Find best move using iterative deepening
122
    currentSearch = &sc;
123
    sc.setListener(listener);
124
    Move bestM;
125
    if ((moves.size == 1) && (canClaimDraw(pos, posHashList, posHashListSize, moves[0]) == "")) {
126
        bestM = moves[0];
127
        bestM.setScore(0);
128
    } else {
129
        sc.timeLimit(minTimeMillis, maxTimeMillis);
130
        bestM = sc.iterativeDeepening(moves, maxDepth, maxNodes, verbose, 1, false, 100);
131
    }
132
    currentSearch = nullptr;
133
    //        tt.printStats();
134
    std::string strMove = TextIO::moveToString(pos, bestM, false);
135
 
136
    // Claim draw if appropriate
137
    if (bestM.score() <= 0) {
138
        std::string drawClaim = canClaimDraw(pos, posHashList, posHashListSize, bestM);
139
        if (drawClaim != "")
140
            strMove = drawClaim;
141
    }
142
    return strMove;
143
}
144
 
145
std::string
146
ComputerPlayer::canClaimDraw(Position& pos, std::vector<U64>& posHashList,
147
                             int posHashListSize, const Move& move) {
148
    std::string drawStr;
149
    if (Search::canClaimDraw50(pos)) {
150
        drawStr = "draw 50";
151
    } else if (Search::canClaimDrawRep(pos, posHashList, posHashListSize, posHashListSize)) {
152
        drawStr = "draw rep";
153
    } else {
154
        std::string strMove = TextIO::moveToString(pos, move, false);
155
        posHashList[posHashListSize++] = pos.zobristHash();
156
        UndoInfo ui;
157
        pos.makeMove(move, ui);
158
        if (Search::canClaimDraw50(pos)) {
159
            drawStr = "draw 50 " + strMove;
160
        } else if (Search::canClaimDrawRep(pos, posHashList, posHashListSize, posHashListSize)) {
161
            drawStr = "draw rep " + strMove;
162
        }
163
        pos.unMakeMove(move, ui);
164
    }
165
    return drawStr;
166
}
167
 
168
void
169
ComputerPlayer::timeLimit(int minTimeLimit, int maxTimeLimit) {
170
    minTimeMillis = minTimeLimit;
171
    maxTimeMillis = maxTimeLimit;
172
    if (currentSearch != nullptr)
173
        currentSearch->timeLimit(minTimeLimit, maxTimeLimit);
174
}
175
 
176
std::pair<Move, std::string>
177
ComputerPlayer::searchPosition(Position& pos, int maxTimeMillis) {
178
    // Create a search object
179
    std::vector<U64> posHashList(200);
180
    tt.nextGeneration();
181
    KillerTable kt;
182
    History ht;
183
    Search::SearchTables st(tt, kt, ht, *et);
184
    TreeLogger treeLog;
185
    Search sc(pos, posHashList, 0, st, pd, nullptr, treeLog);
186
 
187
    // Determine all legal moves
188
    MoveList moves;
189
    MoveGen::pseudoLegalMoves(pos, moves);
190
    MoveGen::removeIllegal(pos, moves);
191
    sc.scoreMoveList(moves, 0);
192
 
193
    // Find best move using iterative deepening
194
    sc.timeLimit(maxTimeMillis, maxTimeMillis);
195
    Move bestM = sc.iterativeDeepening(moves, -1, -1, false);
196
 
197
    // Extract PV
198
    std::string PV = TextIO::moveToString(pos, bestM, false) + " ";
199
    UndoInfo ui;
200
    pos.makeMove(bestM, ui);
201
    PV += tt.extractPV(pos);
202
    pos.unMakeMove(bestM, ui);
203
 
204
//    tt.printStats();
205
 
206
    // Return best move and PV
207
    return std::pair<Move, std::string>(bestM, PV);
208
}