Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP

Comparing changes

Choose two branches to see what’s changed or to start a new pull request. If you need to, you can also compare across forks.

Open a pull request

Create a new pull request by comparing changes across two branches. If you need to, you can also compare across forks.
base fork: lorenzo-stoakes/weak
base: b015978d4d
...
head fork: lorenzo-stoakes/weak
compare: d9fb574612
  • 4 commits
  • 4 files changed
  • 0 commit comments
  • 1 contributor
Showing with 194 additions and 13 deletions.
  1. +7 −3 eval.c
  2. +137 −1 movegen.c
  3. +46 −9 search.c
  4. +4 −0 weak.h
View
10 eval.c
@@ -32,9 +32,13 @@ Eval(Game *game, Side side)
// Very basic evaluation for now.
- for(piece = Pawn; piece <= Queen; piece++) {
- ret += weights[piece]*PopCount(game->ChessSet.Sets[White].Boards[piece]);
- ret -= weights[piece]*PopCount(game->ChessSet.Sets[Black].Boards[piece]);
+ if(Checkmated(game)) {
+ ret = SMALL * (1 - 2*game->WhosTurn);
+ } else {
+ for(piece = Pawn; piece <= Queen; piece++) {
+ ret += weights[piece]*PopCount(game->ChessSet.Sets[White].Boards[piece]);
+ ret -= weights[piece]*PopCount(game->ChessSet.Sets[Black].Boards[piece]);
+ }
}
return ret * (1 - 2*side);
View
138 movegen.c
@@ -24,14 +24,41 @@
static FORCE_INLINE Move* bishopMoves(Position*, Move*, BitBoard, BitBoard);
static Move* evasions(Move*, Game*);
+static Move* evasionsCaptures(Move*, Game*);
static FORCE_INLINE Move* kingMoves(Position, Move*, BitBoard);
static FORCE_INLINE Move* knightMoves(Position*, Move*, BitBoard);
static Move* nonEvasions(Move*, Game*);
+static Move* nonEvasionsCaptures(Move*, Game*);
static Move* pawnMovesBlack(ChessSet*, Position, Move*, BitBoard, bool);
static Move* pawnMovesWhite(Game*, Move*, BitBoard, bool);
static FORCE_INLINE Move* queenMoves(Position*, Move*, BitBoard, BitBoard);
static FORCE_INLINE Move* rookMoves(Position*, Move*, BitBoard, BitBoard);
+// TODO: Horrible duplication due to perf considerations. Review.
+
+Move*
+AllCaptures(Move *start, Game *game)
+{
+ Move *curr = start, *end = start;
+
+ end = game->CheckStats.CheckSources ?
+ evasionsCaptures(start, game) :
+ nonEvasionsCaptures(start, game);
+
+ // Filter out illegal moves.
+ while(curr != end) {
+ if(!PseudoLegal(game, *curr, game->CheckStats.Pinned)) {
+ // Switch last move with the one we are rejecting.
+ end--;
+ *curr = *end;
+ } else {
+ curr++;
+ }
+ }
+
+ return end;
+}
+
Move*
AllMoves(Move *start, Game *game)
{
@@ -186,9 +213,9 @@ evasions(Move *end, Game *game)
{
BitBoard attacks, moves, targets;
BitBoard checks = game->CheckStats.CheckSources;
- BitBoard occupancy = game->ChessSet.Occupancy;
BitBoard slideAttacks = EmptyBoard;
ChessSet *chessSet = &game->ChessSet;
+ BitBoard occupancy = chessSet->Occupancy;
int checkCount = 0;
Piece piece;
Position check;
@@ -262,6 +289,88 @@ evasions(Move *end, Game *game)
return end;
}
+static Move*
+evasionsCaptures(Move *end, Game *game)
+{
+ BitBoard attacks, targets;
+ BitBoard checks = game->CheckStats.CheckSources;
+ BitBoard slideAttacks = EmptyBoard;
+ ChessSet *chessSet = &game->ChessSet;
+ BitBoard occupancy = chessSet->Occupancy;
+ int checkCount = 0;
+ Piece piece;
+ Position check;
+ Position king = game->CheckStats.DefendedKing;
+ Side side = game->WhosTurn;
+ Side opposite = OPPOSITE(side);
+ BitBoard opposition = chessSet->Sets[opposite].Occupancy;
+
+ while(checks) {
+ check = PopForward(&checks);
+
+ checkCount++;
+
+ piece = PieceAt(chessSet, check);
+
+ switch(piece) {
+ case Bishop:
+ slideAttacks |= EmptyAttacks[Bishop][check];
+
+ break;
+ case Rook:
+ slideAttacks |= EmptyAttacks[Rook][check];
+
+ break;
+ case Queen:
+ // If king and queen are far away, i.e. there are squares between them, or they are not
+ // on a diagonal, we can remove all squares in all directions as the king can't get to them.
+ if(Between[king][check] ||
+ !(EmptyAttacks[Bishop][check] & POSBOARD(king))) {
+ slideAttacks |= EmptyAttacks[Queen][check];
+ } else {
+ slideAttacks |= EmptyAttacks[Bishop][check] |
+ RookAttacksFrom(check, occupancy);
+ }
+
+ break;
+ default:
+ break;
+ }
+ }
+
+ attacks = KingAttacksFrom(king) & ~slideAttacks & opposition;
+
+ // King evasion moves.
+
+ while(attacks) {
+ *end++ = MAKE_MOVE_QUICK(king, PopForward(&attacks));
+ }
+
+ // If there is more than 1 check, blocking won't achieve anything.
+ if(checkCount > 1) {
+ return end;
+ }
+
+ // Blocking/capturing the checking piece.
+ // We use check from the loop above, since we have only 1 check this will
+ // be the sole checker.
+ targets = opposition & (Between[check][king] | game->CheckStats.CheckSources);
+
+ if(side == White) {
+ end = pawnMovesWhite(game, end, targets, true);
+ } else {
+ end = pawnMovesBlack(chessSet, game->EnPassantSquare, end, targets, true);
+ }
+
+ // King already handled.
+ end = knightMoves(chessSet->PiecePositions[side][Knight], end, targets);
+ end = bishopMoves(chessSet->PiecePositions[side][Bishop], end, occupancy, targets);
+ end = rookMoves (chessSet->PiecePositions[side][Rook], end, occupancy, targets);
+ end = queenMoves (chessSet->PiecePositions[side][Queen], end, occupancy, targets);
+
+ return end;
+}
+
static FORCE_INLINE Move*
bishopMoves(Position *positions, Move *end, BitBoard occupancy, BitBoard mask)
{
@@ -336,6 +445,33 @@ nonEvasions(Move *end, Game *game)
return end;
}
+
+static Move*
+nonEvasionsCaptures(Move *end, Game *game)
+{
+ Side side = game->WhosTurn;
+ Side opposite = OPPOSITE(side);
+ ChessSet *chessSet = &game->ChessSet;
+ BitBoard occupancy = chessSet->Occupancy;
+ BitBoard opposition = chessSet->Sets[opposite].Occupancy;
+
+ if(side == White) {
+ end = pawnMovesWhite(game, end, opposition, false);
+ } else {
+ end = pawnMovesBlack(chessSet, game->EnPassantSquare, end, opposition, false);
+ }
+
+ end = knightMoves(chessSet->PiecePositions[side][Knight], end, opposition);
+ end = bishopMoves(chessSet->PiecePositions[side][Bishop], end, occupancy, opposition);
+ end = rookMoves(chessSet->PiecePositions[side][Rook], end, occupancy, opposition);
+ end = queenMoves(chessSet->PiecePositions[side][Queen], end, occupancy, opposition);
+ end = kingMoves(game->CheckStats.DefendedKing, end, opposition);
+
+ end = CastleMoves(game, end);
+
+ return end;
+}
+
static Move*
pawnMovesBlack(ChessSet *chessSet, Position enPassant, Move *curr, BitBoard mask, bool evasion)
{
View
55 search.c
@@ -21,11 +21,9 @@
#include "weak.h"
-#define DEPTH 8
-
-#define SMALL -1E10
-#define BIG 1E10
+#define DEPTH 6
+static double quiesce(Game*, double, double, uint64_t*, Side);
static double miniMax(Game*, double, double, int, uint64_t*);
static double negaMax(Game*, double, double, int, uint64_t*);
@@ -80,7 +78,7 @@ miniMax(Game *game, double alpha, double beta, int depth, uint64_t *count)
Side side = game->WhosTurn;
if(depth == DEPTH) {
- return Eval(game, White);
+ return quiesce(game, alpha, beta, count, White);
}
end = AllMoves(moves, game);
@@ -128,13 +126,13 @@ miniMax(Game *game, double alpha, double beta, int depth, uint64_t *count)
static double
negaMax(Game *game, double alpha, double beta, int depth, uint64_t *count)
{
- double max, val;
+ double val;
Move moves[INIT_MOVE_LEN];
Move *start = moves;
Move *curr, *end;
if(depth == DEPTH) {
- return Eval(game, game->WhosTurn);
+ return quiesce(game, alpha, beta, count, game->WhosTurn);
}
end = AllMoves(moves, game);
@@ -144,8 +142,6 @@ negaMax(Game *game, double alpha, double beta, int depth, uint64_t *count)
// Iterate through all moves looking for the best, whose definition
// varies based on who's turn it is.
- max = SMALL;
-
for(curr = start; curr != end; curr++) {
DoMove(game, *curr);
val = -negaMax(game, -beta, -alpha, depth+1, count);
@@ -162,3 +158,44 @@ negaMax(Game *game, double alpha, double beta, int depth, uint64_t *count)
return alpha;
}
+
+// Quiescent search. See http://chessprogramming.wikispaces.com/Quiescence+Search
+static double
+quiesce(Game *game, double alpha, double beta, uint64_t *count, Side evalSide)
+{
+ double val;
+ double standPat = Eval(game, evalSide);
+ Move buffer[INIT_MOVE_LEN];
+ Move move;
+ Move *end;
+ Move *curr = buffer;
+
+ if(standPat >= beta) {
+ return beta;
+ }
+
+ if(alpha < standPat) {
+ alpha = standPat;
+ }
+
+ end = AllCaptures(curr, game);
+
+ *count += end-curr;
+
+ for(; curr != end; curr++) {
+ move = *curr;
+
+ DoMove(game, move);
+ val = -quiesce(game, -beta, -alpha, count, evalSide);
+ Unmove(game);
+
+ if(val >= beta) {
+ return beta;
+ }
+ if(val > alpha) {
+ val = alpha;
+ }
+ }
+
+ return alpha;
+}
View
4 weak.h
@@ -46,6 +46,9 @@
#define MAX_PIECE_LOCATION 10
#define APPEND_STRING_BUFFER_LENGTH 2000
+#define BIG 1E10
+#define SMALL -1E10
+
/*
From 1 size = 6
@@ -550,6 +553,7 @@ void RunInterface(Game*);
void InitMagics(void);
// movegen.c
+Move* AllCaptures(Move*, Game*);
Move* AllMoves(Move*, Game*);
bool AnyMoves(Game*);
Move* CastleMoves(Game*, Move*);

No commit comments for this range

Something went wrong with that request. Please try again.