Compare commits
5 Commits
604950e4e0
...
7a4c7dd46d
| Author | SHA1 | Date | |
|---|---|---|---|
| 7a4c7dd46d | |||
| 033bba0a12 | |||
| cb47cc3c8b | |||
| edfa430db3 | |||
| 2b8820a863 |
11
README.md
11
README.md
@@ -33,8 +33,6 @@ No official rating yet. Estimated around **2300 Elo**, based on self-play SPRT r
|
||||
|
||||
Requires Rust ([rustup](https://rustup.rs)).
|
||||
|
||||
### Linux / macOS
|
||||
|
||||
```sh
|
||||
git clone https://github.com/stefiosif/zeal.git
|
||||
cd zeal
|
||||
@@ -42,15 +40,6 @@ cargo build --release
|
||||
./target/release/zeal
|
||||
```
|
||||
|
||||
### Windows
|
||||
|
||||
```powershell
|
||||
git clone https://github.com/stefiosif/zeal.git
|
||||
cd zeal
|
||||
cargo build --release
|
||||
.\target\release\zeal.exe
|
||||
```
|
||||
|
||||
## Credits
|
||||
|
||||
Thanks to CodeMonkeyKing's YouTube series and the [Engine Programming Discord](https://discord.gg/F6W6mMsTGN).
|
||||
|
||||
90
justfile
Normal file
90
justfile
Normal file
@@ -0,0 +1,90 @@
|
||||
RELEASE_DIR := "target/release"
|
||||
CUTECHESS_CLI_DIR := "$(pwd)/../cutechess-cli"
|
||||
|
||||
# Run all tests
|
||||
test-all:
|
||||
cargo test -r
|
||||
|
||||
# Run all tests except the perft suite
|
||||
test:
|
||||
cargo test -r -- --skip perft
|
||||
|
||||
# Run only the perft suite
|
||||
test-perft:
|
||||
cargo test -r perft
|
||||
|
||||
# Re-run tests (minus perft) on every change under src/
|
||||
watch:
|
||||
cargo watch -c -w src -x 'test -r -- --skip perft'
|
||||
|
||||
# Build, rotate current zeal -> zeal-old, install new as zeal (for SPRT).
|
||||
release-switch:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cargo b -r
|
||||
mv {{CUTECHESS_CLI_DIR}}/zeal {{CUTECHESS_CLI_DIR}}/zeal-old
|
||||
cp {{RELEASE_DIR}}/zeal {{CUTECHESS_CLI_DIR}}/zeal
|
||||
|
||||
# Build and install as zeal (no old-version rotation; for non-SPRT runs)
|
||||
release:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cargo b -r
|
||||
cp {{RELEASE_DIR}}/zeal {{CUTECHESS_CLI_DIR}}/zeal
|
||||
|
||||
# Run SPRT tests between 2 zeal versions
|
||||
run-sprt concurrency="1":
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd {{CUTECHESS_CLI_DIR}}
|
||||
./cutechess-cli \
|
||||
-engine cmd=./zeal name="zeal-new" proto=uci \
|
||||
-engine cmd=./zeal-old name="zeal-old" proto=uci \
|
||||
-openings file="8moves_v3.pgn" order=random format=pgn \
|
||||
-concurrency {{concurrency}} \
|
||||
-ratinginterval 100 \
|
||||
-games 10000 \
|
||||
-resign movecount=3 score=400 \
|
||||
-draw movenumber=40 movecount=3 score=10 \
|
||||
-repeat \
|
||||
-each tc=8+0.08 \
|
||||
-sprt elo0=0 elo1=10 alpha=0.05 beta=0.1 \
|
||||
-pgnout "$(pwd)/games.pgn" 2>&1 | tee {{CUTECHESS_CLI_DIR}}/sprt_log.txt
|
||||
|
||||
# Run SPRT tests between 2 zeal versions with debug LOG enabled (10 games)
|
||||
run-debug:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd {{CUTECHESS_CLI_DIR}}
|
||||
./cutechess-cli \
|
||||
-engine cmd=./zeal name="zeal-new" proto=uci \
|
||||
-engine cmd=./zeal-old name="zeal-old" proto=uci \
|
||||
-openings file="8moves_v3.pgn" order=random format=pgn \
|
||||
-concurrency 1 \
|
||||
-ratinginterval 100 \
|
||||
-games 10 \
|
||||
-resign movecount=3 score=400 \
|
||||
-draw movenumber=40 movecount=3 score=10 \
|
||||
-repeat \
|
||||
-each tc=8+0.08 \
|
||||
-sprt elo0=0 elo1=10 alpha=0.05 beta=0.1 \
|
||||
-pgnout "$(pwd)/games.pgn" \
|
||||
-debug \
|
||||
2> "$(pwd)/debug_log.txt"
|
||||
|
||||
# Run tests between zeal and a stash version
|
||||
run-ccrl:
|
||||
#!/usr/bin/env bash
|
||||
set -euo pipefail
|
||||
cd {{CUTECHESS_CLI_DIR}}
|
||||
./cutechess-cli \
|
||||
-engine cmd=./zeal name="zeal" proto=uci \
|
||||
-engine cmd=./stash-15.0-linux-64 name="stash-15.0-linux-64" proto=uci \
|
||||
-openings file="8moves_v3.pgn" order=random format=pgn \
|
||||
-concurrency 6 \
|
||||
-ratinginterval 100 \
|
||||
-games 2000 \
|
||||
-resign movecount=3 score=400 \
|
||||
-draw movenumber=40 movecount=3 score=10 \
|
||||
-repeat \
|
||||
-each tc=8+0.08
|
||||
@@ -1,25 +0,0 @@
|
||||
#!/bin/sh
|
||||
|
||||
# Create a batch file to connect with cutechess GUI on windows
|
||||
|
||||
if ! cargo build --release --target x86_64-pc-windows-gnu; then
|
||||
echo "cargo build failed"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BUILD_DIR="../target/x86_64-pc-windows-gnu/release"
|
||||
if ! cd "$BUILD_DIR"; then
|
||||
echo "failed to navigate to the build directory: $BUILD_DIR"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
BAT_FILE_NAME="zeal.bat"
|
||||
echo ".\zeal --mode uci" > "$BAT_FILE_NAME"
|
||||
echo "created "$BAT_FILE_NAME" in directory: $(pwd)"
|
||||
|
||||
if ! unix2dos "$BAT_FILE_NAME"; then
|
||||
echo "failed to convert line endings for Windows"
|
||||
exit 1
|
||||
fi
|
||||
|
||||
echo "converted line endings for Windows successfully"
|
||||
@@ -11,7 +11,7 @@ pub fn score_move(
|
||||
mv: Move,
|
||||
killer_move: Option<Move>,
|
||||
color: Color,
|
||||
history_heuristic: &[[[i32; 64]; 64]; 2],
|
||||
history_heuristic: Option<&[[[i32; 64]; 64]; 2]>,
|
||||
tt_move: Option<Move>,
|
||||
) -> i32 {
|
||||
if Some(mv) == tt_move {
|
||||
@@ -30,7 +30,9 @@ pub fn score_move(
|
||||
return 6;
|
||||
}
|
||||
|
||||
-history_heuristic[color][mv.src()][mv.dst()] + MAX_HISTORY + 6 + 1
|
||||
history_heuristic.map_or(MAX_HISTORY + 6 + 1, |hh| {
|
||||
-hh[color][mv.src()][mv.dst()] + MAX_HISTORY + 6 + 1
|
||||
})
|
||||
}
|
||||
|
||||
#[cfg(test)]
|
||||
@@ -53,14 +55,7 @@ mod tests {
|
||||
|
||||
let mut moves = vec![castle, queen_takes_pawn, pawn_takes_queen];
|
||||
moves.sort_unstable_by_key(|mv| {
|
||||
score_move(
|
||||
&game.mailbox,
|
||||
*mv,
|
||||
None,
|
||||
game.current_player(),
|
||||
&[[[0; 64]; 64]; 2],
|
||||
None,
|
||||
)
|
||||
score_move(&game.mailbox, *mv, None, game.current_player(), None, None)
|
||||
});
|
||||
|
||||
assert_eq!(moves, vec![pawn_takes_queen, queen_takes_pawn, castle]);
|
||||
@@ -71,7 +66,7 @@ mod tests {
|
||||
*mv,
|
||||
None,
|
||||
game.current_player(),
|
||||
&[[[0; 64]; 64]; 2],
|
||||
None,
|
||||
Some(castle),
|
||||
)
|
||||
});
|
||||
|
||||
@@ -25,7 +25,7 @@ pub fn negamax(
|
||||
nodes: &mut u64,
|
||||
do_nmp: bool,
|
||||
) -> Result<i16> {
|
||||
if *nodes & 1024 == 0 && time.exceed_hard_limit() {
|
||||
if *nodes & 1023 == 0 && time.exceed_hard_limit() {
|
||||
bail!("Hard limit exceeded in negamax");
|
||||
}
|
||||
|
||||
@@ -101,11 +101,14 @@ pub fn negamax(
|
||||
*mv,
|
||||
game.killer[plies as usize],
|
||||
color,
|
||||
&game.history_heuristic,
|
||||
Some(&game.history_heuristic),
|
||||
entry.and_then(|entry| entry.mv),
|
||||
)
|
||||
});
|
||||
|
||||
// Keep alpha before the loop raises it, so the TT node type uses
|
||||
// the window we actually searched for this node
|
||||
let alpha_original = alpha;
|
||||
let mut legal_moves = 0;
|
||||
let mut best_move = entry.and_then(|entry| entry.mv);
|
||||
let mut best_score = MIN_SCORE;
|
||||
@@ -187,7 +190,7 @@ pub fn negamax(
|
||||
|
||||
let node_type = match best_score {
|
||||
s if s >= beta => NodeType::LowerBound,
|
||||
s if s <= alpha => NodeType::UpperBound,
|
||||
s if s <= alpha_original => NodeType::UpperBound,
|
||||
_ => NodeType::Exact,
|
||||
};
|
||||
|
||||
|
||||
@@ -15,7 +15,7 @@ pub fn quiescence(
|
||||
time: &TimeInfo,
|
||||
nodes: &mut u64,
|
||||
) -> Result<i16> {
|
||||
if *nodes & 1024 == 0 && time.exceed_hard_limit() {
|
||||
if *nodes & 1023 == 0 && time.exceed_hard_limit() {
|
||||
bail!("Hard limit exceeded in quiescence");
|
||||
}
|
||||
|
||||
@@ -48,7 +48,7 @@ pub fn quiescence(
|
||||
*mv,
|
||||
None,
|
||||
color,
|
||||
&[[[0; 64]; 64]; 2],
|
||||
None,
|
||||
entry.and_then(|entry| entry.mv),
|
||||
)
|
||||
});
|
||||
|
||||
Reference in New Issue
Block a user