Simplifying code

Discussion of chess software programming and technical issues.

Moderators: bob, hgm, Harvey Williamson

Forum rules
This textbox is used to restore diagrams posted with the [d] tag before the upgrade.
Henk
Posts: 6353
Joined: Mon May 27, 2013 8:31 am

Re: Simplifying code

Post by Henk » Sat Apr 25, 2020 10:13 am

Ras wrote:
Sat Apr 25, 2020 9:36 am
Henk wrote:
Sat Apr 25, 2020 9:27 am
The nodes near the root need not care much about efficiency of move ordering.
I don't think so. True, there are only few nodes near root, but they have the largest search trees beneath them.
Then one can increase reduction to make trees smaller as much as you like. Of course then you get worse move ordering.

Ras
Posts: 1348
Joined: Tue Aug 30, 2016 6:19 pm
Full name: Rasmus Althoff
Contact:

Re: Simplifying code

Post by Ras » Sat Apr 25, 2020 10:20 am

Henk wrote:
Sat Apr 25, 2020 10:13 am
Then one can increase reduction to make trees smaller as much as you like.
The whole idea of move ordering is to make the trees smaller without sacrificing move quality. That's not only in plain alpha-beta, but even more so with pruning because you want to just prune random moves, only the probably useless ones.
Rasmus Althoff
https://www.ct800.net

Henk
Posts: 6353
Joined: Mon May 27, 2013 8:31 am

Re: Simplifying code

Post by Henk » Sat Apr 25, 2020 10:28 am

Ras wrote:
Sat Apr 25, 2020 10:20 am
Henk wrote:
Sat Apr 25, 2020 10:13 am
Then one can increase reduction to make trees smaller as much as you like.
The whole idea of move ordering is to make the trees smaller without sacrificing move quality. That's not only in plain alpha-beta, but even more so with pruning because you want to just prune random moves, only the probably useless ones.
Or maybe forget about the idea it finds the best move. If it plays an acceptable move it might even prune excellent moves.
[At the stage of my engine I should be glad it does not blunder. If it would only play acceptable moves it may win from engines that blunder]

Sven
Posts: 3833
Joined: Thu May 15, 2008 7:57 pm
Location: Berlin, Germany
Full name: Sven Schüle
Contact:

Re: Simplifying code

Post by Sven » Sat Apr 25, 2020 6:02 pm

Henk wrote:
Sat Apr 25, 2020 10:28 am
...
[At the stage of my engine I should be glad it does not blunder. If it would only play acceptable moves it may win from engines that blunder]
At the current stage of your engine I think you should focus on finding those severe bugs that make it play very weak, and change nothing else ;-) If simplifying the code helps to find those bugs then do it, but it can also introduce new bugs ... Only after fixing the most important bugs you will be able to see any benefit in making small changes to the code, otherwise they are just that: changes.
Sven Schüle (engine author: Jumbo, KnockOut, Surprise)

Henk
Posts: 6353
Joined: Mon May 27, 2013 8:31 am

Re: Simplifying code

Post by Henk » Sat Apr 25, 2020 6:21 pm

Sven wrote:
Sat Apr 25, 2020 6:02 pm
Henk wrote:
Sat Apr 25, 2020 10:28 am
...
[At the stage of my engine I should be glad it does not blunder. If it would only play acceptable moves it may win from engines that blunder]
At the current stage of your engine I think you should focus on finding those severe bugs that make it play very weak, and change nothing else ;-) If simplifying the code helps to find those bugs then do it, but it can also introduce new bugs ... Only after fixing the most important bugs you will be able to see any benefit in making small changes to the code, otherwise they are just that: changes.
These severe bugs often are bugs you can't reproduce. You know in the game it plays a very bad move but when you extract the position and use it to test your engine it plays a normal move. So it tries to fool me.

Maybe best is to remove all code you don't trust or understand for 100%. But very often code is based on statistics and statistics are equivalent to lies.

At this moment I am somewhat inspired by test driven development. So I try to make source code easy to test (separately).

User avatar
mvanthoor
Posts: 204
Joined: Wed Jul 03, 2019 2:42 pm
Full name: Marcel Vanthoor

Re: Simplifying code

Post by mvanthoor » Sat Apr 25, 2020 7:07 pm

Remove everything except your board representation, move generator, perft, make, and unmake, and perft. Then make them bug free, and then as fast as possible. Then start adding in the other code one tiny bit at a time, testing each change extensively, until you can play very simple games using a bare-bones search and a very simple evaluation.

I'm now writing the draft of my search routine. The first version will basically be a brute force to depth 4 or 5 (because I know the code is fast enough to handle it) without iterative deepening, and the evaluation will just be material count and a small random value to differentiate moves. After that works, I'll put in some piece-square tables, and switch to a very simple alpha/beta. Then I'll add iterative deepening... and then time management.

I keep iterating like this until I have a program that will be able to play reliably, al be it weak, for the very first version.

You have the code already, but you can try and follow this process by removing it, and adding it in piece by piece, testing as you go.

Henk
Posts: 6353
Joined: Mon May 27, 2013 8:31 am

Re: Simplifying code

Post by Henk » Tue Apr 28, 2020 5:36 pm

Sven wrote:
Sat Apr 25, 2020 6:02 pm
Henk wrote:
Sat Apr 25, 2020 10:28 am
...
[At the stage of my engine I should be glad it does not blunder. If it would only play acceptable moves it may win from engines that blunder]
At the current stage of your engine I think you should focus on finding those severe bugs that make it play very weak, and change nothing else ;-) If simplifying the code helps to find those bugs then do it, but it can also introduce new bugs ... Only after fixing the most important bugs you will be able to see any benefit in making small changes to the code, otherwise they are just that: changes.
Already found something

Code: Select all

 if (mv == IDMove && IDMove != null)
 {
           if (!TimeManagement.SearchExpired(Level, TimeControl))
            {
                  // IDMove has been searched through in time
                   IDMoveProcessed = true;
             }
  }
  
I forgot the !SearchExpired check which is added in the code above.

So it thought Iterative deepening move had been calculated if IDMoveProcessed is set to true but that is only true if search had been completed in time (for that move)

See simplification helps. Or maybe useless rewriting helps finding bugs.

By the way my engine does not play much better but maybe blunders less now.

This also explains why these bugs where not reproducable because during analysis you wait until you stop analysis.

O wait: IDMove is always the move with highest priority. So forget this story.

Henk
Posts: 6353
Joined: Mon May 27, 2013 8:31 am

Re: Simplifying code

Post by Henk » Sun May 10, 2020 10:56 am

Next step is to make this code work. Don't know why it took seven years to find out.
Even the idea of using a priority queue for move generation is from say two or three years ago.
Probably blinded by low level efficiency.

Code: Select all

 
 var movePrioQ = SearchHelper.BuildMovePrioQ(depth, generateNonCaptures,  (IDMove, ttEntry, IIDMove));
 

Henk
Posts: 6353
Joined: Mon May 27, 2013 8:31 am

Re: Simplifying code

Post by Henk » Mon May 11, 2020 8:42 am

Main search method still about 270 lines of code. So there should be enough to simplify. But getting difficult.

User avatar
mvanthoor
Posts: 204
Joined: Wed Jul 03, 2019 2:42 pm
Full name: Marcel Vanthoor

Re: Simplifying code

Post by mvanthoor » Mon May 11, 2020 9:59 am

Isn't it possible to refactor bit by bit?

What I always do is to create a small new part (struct, method, object, whatever), and use this where possible. If that works, I throw away the old code that it replaces. If there are errors in the program (in Rust, the static analyzer immediately points those out), then fix those to use the new part.

Rinse, repeat...

I did a very large refactor this way over the weekend, cutting out several forwarding functions and 'references-to-references' from the engine. The actual result of the code didn't change, but it simplified the structure of the move generator very much, and it (almost) disconnected it from the board.

Post Reply