Skip to content

Sprint 6 - v6 - 5 hrs

From now on, most of my sprints are going to have multiple sub-sprints, as I want to tackle multiple goals in each big sprint.

v6.1 - 3 hrs

Goals

  • Making the evaluation function more efficient and increasing it's speed in general.

Logs

Now that I had a fast chess library, I wanted to make the evaluation function faster. I had to try multiple approaches to this, as I was not sure what would work best. All of the results below are comparing v5.2 to v6.1 in a complex middle game position (displayed below).

8/7p/5kp1/p1b1r3/P1P5/1P3B1P/4p2K/4B3 w - - 2 45

Approach 1: Inside the evaluation function, multiplying boolean values by piece values

VersionTime 1 (ns)Time 2 (ns)Time 3 (ns)Average (ns/s)
v5.27000860081007900/0.0000079
v6.1.16700800078007500/0.0000075

This resulted in a MASSIVE 5.33% improvement. (This was a lot smaller of an improvement than I expected, but it was still an improvement nonetheless)

Approach number 2: For loop unrolling.

VersionTime 1 (ns)Time 2 (ns)Time 3 (ns)Average (ns/s)
v5.272001170074008767/0.000008767
v6.1.17100680070006967/0.000006967
v6.1.211700140001300012900/0.0000129

Well … This was quite an improvement … of -46% over v6.1.1. Turns out g++ is a very smart compiler and it is optimised for this already, and instead explicit for loop unrolling just makes it worse.

Approach number 3: Trying to use switches instead of boolean multiplication

VersionTime 1 (ns)Time 2 (ns)Time 3 (ns)Average (ns/s)
v5.274001170078008966/0.000008966
v6.1.12900300031003000/0.000003
v6.1.33100230023002,567/0.000002

Now this is good: A massive 249.3% improvement over v5.2 and a respectable 16.9% improvement over v6.1.1

Approach number 4: Incremental evaluation deepening.

For these tests, we are running the find best move algorithm on the position above at a depth of 5 to see if this helped or hindered.

  • While working on this, I found a bug that led to the evaluation being an integer instead of a float. It was promptly fixed.
VersionMove FoundTime 1 (ms)Time 2 (ms)Time 3 (ms)Average (ms/s)
v5.2e1a57272765575077478/7.478
v6.1.1e1a57375728872017288/7.288
v6.1.3e1a55840580758805842/5.842
v6.1.4f3d5

Results are irrelevant as it doesn’t find the best move, probably because there was some bug in my implementation.

v6.1.5 - 1 hr

Alongside of all of these fancy optimisations, in v6.1.5 I added different depth based on game state but I did not test it as it would not have been an accurate comparison as v6.1.5 would look through fewer nodes, but it does find the best move and is significantly faster.

v6.2 - 1 hr

Goals

  • Implement quiescence search

It really was not that hard to implement and I got it done quite fast as it is just a second MiniMax function.