Page 3 of 14

Re: Simplifying code

Posted: Sat Apr 25, 2020 12:13 pm
by Henk
Ras wrote: Sat Apr 25, 2020 11:36 am
Henk wrote: Sat Apr 25, 2020 11:27 amThe 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.

Re: Simplifying code

Posted: Sat Apr 25, 2020 12:20 pm
by Ras
Henk wrote: Sat Apr 25, 2020 12:13 pmThen 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.

Re: Simplifying code

Posted: Sat Apr 25, 2020 12:28 pm
by Henk
Ras wrote: Sat Apr 25, 2020 12:20 pm
Henk wrote: Sat Apr 25, 2020 12:13 pmThen 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]

Re: Simplifying code

Posted: Sat Apr 25, 2020 8:02 pm
by Sven
Henk wrote: Sat Apr 25, 2020 12:28 pm ...
[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.

Re: Simplifying code

Posted: Sat Apr 25, 2020 8:21 pm
by Henk
Sven wrote: Sat Apr 25, 2020 8:02 pm
Henk wrote: Sat Apr 25, 2020 12:28 pm ...
[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).

Re: Simplifying code

Posted: Sat Apr 25, 2020 9:07 pm
by mvanthoor
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.

Re: Simplifying code

Posted: Tue Apr 28, 2020 7:36 pm
by Henk
Sven wrote: Sat Apr 25, 2020 8:02 pm
Henk wrote: Sat Apr 25, 2020 12:28 pm ...
[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.

Re: Simplifying code

Posted: Sun May 10, 2020 12:56 pm
by Henk
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));
 

Re: Simplifying code

Posted: Mon May 11, 2020 10:42 am
by Henk
Main search method still about 270 lines of code. So there should be enough to simplify. But getting difficult.

Re: Simplifying code

Posted: Mon May 11, 2020 11:59 am
by mvanthoor
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.