Advertisement
Not a member of Pastebin yet?
Sign Up,
it unlocks many cool features!
- #include "Board.h"
- #include <gcl/GCL.h>
- #include <ctype.h>
- #include <cmath>
- #include <cstdlib>
- #include <climits>
- #include <thread>
- #include <vector>
- #include "pieces/Bishop.h"
- #include "pieces/Queen.h"
- #include "pieces/King.h"
- #include "pieces/Knight.h"
- #include "pieces/None.h"
- #include "pieces/Rook.h"
- #include "pieces/Pawn.h"
- #include "Piece.h"
- const static char start[8][8] = { { 'r', 'p', '.', '.', '.', '.', 'P', 'R' },
- { 'h', 'p', '.', '.', '.', '.', 'P', 'H' },
- { 'b', 'p', '.', '.', '.', '.', 'P', 'B' },
- { 'q', 'p', '.', '.', '.', '.', 'P', 'Q' },
- { 'k', 'p', '.', '.', '.', '.', 'P', 'K' },
- { 'b', 'p', '.', '.', '.', '.', 'P', 'B' },
- { 'h', 'p', '.', '.', '.', '.', 'P', 'H' },
- { 'r', 'p', '.', '.', '.', '.', 'P', 'R' } };
- const static Piece::Type promotionTypes[4] = { Piece::KNIGHT, Piece::QUEEN, Piece::BISHOP, Piece::ROOK };
- Board::Board() : turn(Piece::WHITE), phase(MOVE), value(0), blackKing(true), whiteKing(true), enPas(-1) {
- uchar wi = 0, bi = 0;
- for (char x = 0; x < 8; x++) {
- for (char y = 0; y < 8; y++) {
- Piece::Color col = isupper(start[x][y]) ? Piece::BLACK : Piece::WHITE;
- if (start[x][y] == '.') board[x + y * 8] = &None::get(), pieceref[x + y * 8] = -1;
- else if (start[x][y] == 'r' || start[x][y] == 'R') board[x + y * 8] = &Piece::get<Rook>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
- else if (start[x][y] == 'h' || start[x][y] == 'H') board[x + y * 8] = &Piece::get<Knight>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
- else if (start[x][y] == 'b' || start[x][y] == 'B') board[x + y * 8] = &Piece::get<Bishop>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
- else if (start[x][y] == 'q' || start[x][y] == 'Q') board[x + y * 8] = &Piece::get<Queen>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
- else if (start[x][y] == 'k' || start[x][y] == 'K') board[x + y * 8] = &Piece::get<King>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
- else if (start[x][y] == 'p' || start[x][y] == 'P') board[x + y * 8] = &Piece::get<Pawn>(col), pieceref[x + y * 8] = (col == Piece::WHITE ? wi : (16 + bi));
- if (start[x][y] != '.') {
- if (col == Piece::WHITE) whites[wi++] = x + y * 8;
- if (col == Piece::BLACK) blacks[bi++] = x + y * 8;
- }
- }
- }
- }
- Board::Board(const Board& other) : turn(other.turn), phase(other.phase), promotee(other.promotee),
- value(other.value), blackKing(other.blackKing), whiteKing(other.whiteKing), enPas(other.enPas) {
- std::copy(&other.board[0], &other.board[0] + 64, &board[0]);
- std::copy(&other.pieceref[0], &other.pieceref[0] + 64, &pieceref[0]);
- std::copy(&other.pieces[0], &other.pieces[0] + 32, &pieces[0]);
- }
- void Board::move(char from, char to) noexcept {
- if (enPas != -1 && (board[enPas]->col == turn || board[enPas]->type != Piece::PAWN)) enPas = -1;
- board[from]->move(*this, from, to);
- }
- void Board::removePiece(char from) noexcept {
- value += board[from]->col == Piece::WHITE ? -board[from]->getVal(from, *this) : board[from]->getVal(from, *this);
- pieces[pieceref[from]] = -1;
- board[from] = &None::get();
- pieceref[from] = -1;
- }
- void Board::movePiece(char from, char to) noexcept {
- value += board[from]->col == Piece::WHITE ? -board[from]->getVal(from, *this) : board[from]->getVal(from, *this);
- if (board[to]->type == Piece::KING) {
- if (board[to]->col == Piece::WHITE) whiteKing = false;
- if (board[to]->col == Piece::BLACK) blackKing = false;
- }
- if (pieceref[to] != -1) {
- pieces[pieceref[to]] = -1;
- value += board[to]->col == Piece::WHITE ? -board[to]->getVal(to, *this) : board[to]->getVal(to, *this);
- }
- pieceref[to] = pieceref[from];
- board[to] = board[from]->hasMoved ? board[from] : &Piece::get(turn, board[from]->type, true);
- pieceref[from] = -1;
- board[from] = &None::get();
- pieces[pieceref[to]] = to;
- value += board[to]->col == Piece::WHITE ? board[to]->getVal(to, *this) : -board[to]->getVal(to, *this);
- }
- void Board::promote(Piece::Type type) {
- phase = MOVE;
- value += board[promotee]->col == Piece::WHITE ? -board[promotee]->getVal(promotee, *this) : board[promotee]->getVal(promotee, *this);
- if (type == Piece::QUEEN) board[promotee] = &Piece::get<Queen>(turn, true);
- else if (type == Piece::BISHOP) board[promotee] = &Piece::get<Bishop>(turn, true);
- else if (type == Piece::ROOK) board[promotee] = &Piece::get<Rook>(turn, true);
- else if (type == Piece::KNIGHT) board[promotee] = &Piece::get<Knight>(turn, true);
- value += board[promotee]->col == Piece::WHITE ? board[promotee]->getVal(promotee, *this) : -board[promotee]->getVal(promotee, *this);
- turn = !turn;
- }
- Board::alphabetareturn Board::_alphabeta(uchar depth, int a, int b, Piece::Color col) {
- if (depth == 0 || !whiteKing || !blackKing) {
- int val;
- if (!whiteKing) val = col == Piece::WHITE ? -400000 : +400000;
- else if (!blackKing) val = col == Piece::BLACK ? -400000 : +400000;
- else val = col == Piece::WHITE ? value : -value;
- return { val + depth * (val > 0 ? 1 : -1) };
- }
- int v = (col == turn ? INT_MIN : INT_MAX);
- char from = -1, to = -1;
- Piece::Type promo = Piece::NOTYPE;
- char* pieces = turn == Piece::WHITE ? whites : blacks;
- if (phase == MOVE) {
- for (uchar i = 0; i < 16; i++) {
- if (pieces[i] == -1) continue;
- if (board[pieces[i]]->listMoves(*this, pieces[i], [&](char mto) -> bool {
- Board child(*this);
- child.move(pieces[i], mto);
- alphabetareturn abr = child._alphabeta(depth - (child.phase == MOVE ? 1 : 0), a, b, col);
- int r = abr.score;
- if (col == turn) {
- if (r > v) {
- v = r;
- from = pieces[i];
- to = mto;
- promo = abr.promo;
- }
- a = GCL_MAX(a, v);
- } else {
- v = GCL_MIN(v, r);
- b = GCL_MIN(b, v);
- }
- return b <= a;
- })) break;
- }
- } else if (phase == PROMOTE) {
- for (uchar i = 0; i < 4; i++) {
- Board child(*this);
- child.promote(promotionTypes[i]);
- alphabetareturn abr = child._alphabeta(depth - 1, a, b, col);
- int r = abr.score;
- if (col == turn) {
- if (r > v) {
- v = r;
- promo = promotionTypes[i];
- }
- a = GCL_MAX(a, v);
- } else {
- v = GCL_MIN(v, r);
- b = GCL_MIN(b, v);
- }
- if (b <= a) break;
- }
- }
- return { v, from, to, promo };
- }
- Board::alphabetareturn Board::alphabeta(uchar depth) {
- if (depth == 0) return {};
- return _alphabeta(depth, INT_MIN, INT_MAX, turn);
- }
- Board::alphabetareturn Board::threadedalphabeta(uchar depth, uchar maxThreads) {
- if (depth <= 1) return {};
- int v = INT_MIN, a = INT_MIN;
- char from = -1, to = -1;
- Piece::Type promo = Piece::NOTYPE;
- std::thread** threads = new std::thread*[maxThreads];
- bool* threadStates = new bool[maxThreads];
- for (uchar i = 0; i < maxThreads; i++)
- threads[i] = nullptr, threadStates[i] = false;
- char* pieces = turn == Piece::WHITE ? whites : blacks;
- for (uchar i = 0; i < 16; i++) {
- if (pieces[i] == -1) continue;
- board[pieces[i]]->listMoves(*this, pieces[i], [&](char mto) -> bool {
- char ti = -1;
- while (ti == -1) {
- for (char tii = 0; tii < maxThreads; tii++) {
- if (!threadStates[tii]) {
- if (threads[tii]) {
- threads[tii]->join();
- delete threads[tii];
- }
- threadStates[tii] = true;
- ti = tii;
- break;
- }
- }
- if (ti == -1) std::this_thread::sleep_for(std::chrono::milliseconds(2));
- }
- threads[ti] = new std::thread([&](char mfrom, char mto, char ti) {
- Board child(*this);
- child.move(mfrom, mto);
- alphabetareturn abr = child._alphabeta(depth - (child.phase == MOVE ? 1 : 0), a, INT_MAX, turn);
- int r = abr.score;
- if (r > v) {
- v = r;
- from = mfrom;
- to = mto;
- promo = abr.promo;
- }
- a = GCL_MAX(a, v);
- threadStates[ti] = false;
- }, pieces[i], mto, ti);
- return false;
- });
- }
- for (uchar i = 0; i < maxThreads; i++) {
- if (threads[i]) {
- threads[i]->join();
- delete threads[i];
- }
- }
- delete[] threads;
- delete[] threadStates;
- return { v, from, to, promo };
- }
Advertisement
Add Comment
Please, Sign In to add comment
Advertisement