Jelajahi Sumber

quiescence doesn't quite work

Nicolas Winkler 7 tahun lalu
induk
melakukan
e65318b040
3 mengubah file dengan 106 tambahan dan 70 penghapusan
  1. 70 63
      src/Minimax.cpp
  2. 1 5
      src/Minimax.h
  3. 35 2
      src/MoveGeneration.cpp

+ 70 - 63
src/Minimax.cpp

@@ -147,7 +147,7 @@ std::pair<Move, MoveValue> chessy::miniMax(ChessGame& cg, int depth)
             lastValidMove = move;
             val = -negamaxImplementation(cg, depth - 1, -beta, -alpha);
         }
-        //cout << move.asString() << ": " << val << endl;
+        cout << move.asString() << ": " << val << endl;
         cg.undoMove(ui);
         if(val > alpha) {
             alpha = val;
@@ -164,9 +164,10 @@ std::pair<Move, MoveValue> chessy::miniMax(ChessGame& cg, int depth)
 MoveValue chessy::negamaxImplementation(ChessGame& cg, int depth,
         chessy::MoveValue alpha, chessy::MoveValue beta)
 {
+    float x;
     if (depth <= 0)
-        //return quiescence(cg, 2, -beta, -alpha);
-        return evaluate(cg.getTurn(), cg);
+        return x = quiescence(cg, 8, -beta, -alpha);
+        //return evaluate(cg);
 
     const Board& b = cg.getBoard();
     auto isCheck = [&cg, &b] (Side turn) {
@@ -175,7 +176,7 @@ MoveValue chessy::negamaxImplementation(ChessGame& cg, int depth,
     };
 
     std::vector<Move> moves;
-    moves.reserve(200);
+    moves.reserve(80);
     if (cg.getTurn() == WHITE_SIDE) {
         generateAllMoves<WHITE_SIDE, false>(cg, moves);
         orderMoves<WHITE_SIDE>(cg, moves);
@@ -209,10 +210,18 @@ MoveValue chessy::negamaxImplementation(ChessGame& cg, int depth,
 
 
 MoveValue chessy::quiescence(ChessGame& cg, int maxDepth,
-    MoveValue alpha, MoveValue beta)
+        MoveValue alpha, MoveValue beta)
 {
+    MoveValue standingPat = evaluate(cg);
+    if (standingPat == 0.0f)
+        int s = 23;
     if (maxDepth <= 0)
-        return evaluate(cg.getTurn(), cg);
+        return standingPat;
+
+    if(standingPat >= beta)
+        return beta;
+    if(standingPat > alpha)
+        alpha = standingPat;
 
     const Board& b = cg.getBoard();
     auto isCheck = [&cg, &b] (Side turn) {
@@ -222,10 +231,14 @@ MoveValue chessy::quiescence(ChessGame& cg, int maxDepth,
 
     std::vector<Move> moves;
     moves.reserve(50);
-    if (cg.getTurn() == WHITE_SIDE)
+    if (cg.getTurn() == WHITE_SIDE) {
         generateAllMoves<WHITE_SIDE, true>(cg, moves);
-    else
+        orderMoves<WHITE_SIDE>(cg, moves);
+    }
+    else {
         generateAllMoves<BLACK_SIDE, true>(cg, moves);
+        orderMoves<BLACK_SIDE>(cg, moves);
+    }
 
     bool thereIsMove = false;
     for (Move move : moves) {
@@ -248,66 +261,60 @@ MoveValue chessy::quiescence(ChessGame& cg, int maxDepth,
         return isCheck(otherSide(cg.getTurn())) ? -1e+30 : 0.0;
     return alpha;
 }
+/*
+MoveValue chessy::quiescence(ChessGame& cg, int maxDepth,
+    MoveValue alpha, MoveValue beta)
+{
+    MoveValue standingPat = evaluate(cg);
+    if (maxDepth <= 0)
+        return standingPat;
 
+    if (beta <= standingPat)
+        return beta;
+    if (alpha < standingPat)
+        alpha = standingPat;
 
-template<Side side>
-MoveValue chessy::evaluatePositives(const ChessGame& game)
-{
-    MoveValue piecePoints = 0;
-    const Board& bd = game.getBoard();
-    Bitboard p = bd.getPawns<side>();
-    Bitboard n = bd.getKnights<side>();
-    Bitboard b = bd.getBishops<side>();
-    Bitboard r = bd.getRooks<side>();
-    Bitboard q = bd.getQueens<side>();
-    Bitboard k = bd.getKing<side>();
-    piecePoints += 1 * p.popcount();
-    piecePoints += 3 * n.popcount();
-    piecePoints += 3 * b.popcount();
-    piecePoints += 5 * r.popcount();
-    piecePoints += 9 * q.popcount();
-
-    for (auto knight : PositionSet{ n })
-        piecePoints += KnightMoveGenerator{ knight, bd.get<side>() }.getBitboard().popcount() * 0.05;
-    for (auto bishop : PositionSet{ b })
-        piecePoints += PrimitiveBishopMoveGenerator{ bishop, bd.get<otherSide(side)>(), bd.get<side>() }.getBitboard().popcount() * 0.03;
-    for (auto rook : PositionSet{ r })
-        piecePoints += PrimitiveRookMoveGenerator{ rook, bd.get<otherSide(side)>(), bd.get<side>() }.getBitboard().popcount() * 0.03;
-    for (auto queen : PositionSet{ q })
-        piecePoints += PrimitiveQueenMoveGenerator{ queen, bd.get<otherSide(side)>(), bd.get<side>() }.getBitboard().popcount() * 0.02;
+    const Board& b = cg.getBoard();
+    auto isCheck = [&cg, &b] (Side turn) {
+        return turn == BLACK_SIDE ? b.isCheck<WHITE_SIDE>() :
+            b.isCheck<BLACK_SIDE>();
+    };
 
-    return piecePoints;
-    /*
-    constexpr Side other = otherSide(side);
-    p = bd.getPawns<other>();
-    n = bd.getKnights<other>();
-    b = bd.getBishops<other>();
-    r = bd.getRooks<other>();
-    q = bd.getQueens<other>();
-    k = bd.getKing<other>();
-    piecePoints -= 1 * p.popcount();
-    piecePoints -= 3 * n.popcount();
-    piecePoints -= 3 * b.popcount();
-    piecePoints -= 5 * r.popcount();
-    piecePoints -= 9 * q.popcount();
-
-    //for (auto knight : PositionSet{ n })
-    //    piecePoints -= KnightMoveGenerator{ knight, bd.get<otherSide(side)>() }.getBitboard().popcount() * 0.2;
-    for (auto bishop : PositionSet{ b })
-        piecePoints -= PrimitiveBishopMoveGenerator{ bishop, bd.get<side>(), bd.get<otherSide(side)>() }.getBitboard().popcount() * 0.2;
-        */
-}
+    std::vector<Move> moves;
+    moves.reserve(50);
+    if (cg.getTurn() == WHITE_SIDE) {
+        generateAllMoves<WHITE_SIDE, true>(cg, moves);
+        orderMoves<WHITE_SIDE>(cg, moves);
+    }
+    else {
+        generateAllMoves<BLACK_SIDE, true>(cg, moves);
+        orderMoves<BLACK_SIDE>(cg, moves);
+    }
 
+    bool thereIsMove = false;
+    for (Move move : moves) {
+        MoveInfo mi{ move, cg };
+        UndoInfo ui = cg.doMove(mi);
+        MoveValue val;
+        if (isCheck(cg.getTurn()))
+            val = -1e+30;
+        else {
+            val = -quiescence(cg, maxDepth - 1, -beta, -alpha);
+            if (val == 0.0f)
+                int s = 23;
+            thereIsMove = true;
+        }
+        cg.undoMove(ui);
+        if(val >= beta)
+            return beta;
+        if(val > alpha)
+            alpha = val;
+    }
+    if (!thereIsMove)
+        return isCheck(otherSide(cg.getTurn())) ? -1e+30 : 0.0;
+    return alpha;
+}*/
 
-MoveValue chessy::evaluate(Side side, const ChessGame& game)
-{
-    if (side == WHITE_SIDE)
-        return evaluatePositives<WHITE_SIDE>(game) -
-            evaluatePositives<BLACK_SIDE>(game);
-    else
-        return evaluatePositives<BLACK_SIDE>(game) -
-            evaluatePositives<WHITE_SIDE>(game);
-}
 
 
 /*

+ 1 - 5
src/Minimax.h

@@ -5,6 +5,7 @@
 #include <utility>
 
 #include "MoveGeneration.h"
+#include "Evaluate.h"
 
 namespace chessy
 {
@@ -29,11 +30,6 @@ namespace chessy
 
     MoveValue quiescence(ChessGame& cg, int maxDepth,
         MoveValue alpha, MoveValue beta);
-
-    template<Side side>
-    MoveValue evaluatePositives(const ChessGame& game);
-
-    MoveValue evaluate(Side side, const ChessGame& game);
 }
 
 

+ 35 - 2
src/MoveGeneration.cpp

@@ -1,8 +1,11 @@
 #include "MoveGeneration.h"
 #include "ChessGame.h"
 
-using namespace chessy;
+#include "Evaluate.h"
+
+#include <algorithm>
 
+using namespace chessy;
 
 
 template<Side side>
@@ -424,6 +427,36 @@ void chessy::orderMoves(const ChessGame& cg, std::vector<Move>& moves)
 {
     if (moves.empty())
         return;
+    Bitboard enemies[] = {
+        cg.getBoard().getPawns<otherSide(side)>(),
+        cg.getBoard().getKnights<otherSide(side)>(),
+        cg.getBoard().getBishops<otherSide(side)>(),
+        cg.getBoard().getRooks<otherSide(side)>(),
+        cg.getBoard().getQueens<otherSide(side)>(),
+    };
+    MoveValue values[] = {
+        values::PAWN,
+        values::KNIGHT,
+        values::BISHOP,
+        values::ROOK,
+        values::QUEEN
+    };
+
+    auto compareMoves = [&](const Move& a, const Move& b) -> bool
+    {
+        MoveValue va = 0;
+        MoveValue vb = 0;
+        for (int i = 0; i < 6; i++) {
+            if (Bitboard::fromIndex(a.destination) & enemies[i])
+                va = values[i];
+            if (Bitboard::fromIndex(b.destination) & enemies[i])
+                vb = values[i];
+        }
+        return va > vb;
+    };
+
+    std::sort(moves.begin(), moves.end(), compareMoves);
+    /*
     auto a = moves.begin();
     auto b = moves.end() - 1;
     Bitboard enemies = cg.getBoard().get<otherSide(side)>();
@@ -434,7 +467,7 @@ void chessy::orderMoves(const ChessGame& cg, std::vector<Move>& moves)
             --b;
         if (a < b)
             std::iter_swap(a, b);
-    }
+    }*/
 }