how to continue

Discussion of chess software programming and technical issues.

Moderators: hgm, Rebel, chrisw

tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

Mergi wrote: Wed Sep 08, 2021 12:14 am I'll dare to venture a guess. The reason why for others disregarding the ply might work is because they use iterative deepening. So for each particular depth, if they find a mate, they can keep track of it, and then they can select the shortest one overall. But in your case, it appears that you dont use iterative deepening (?), meaning that you search every single move to a fixed depth. Now if the first move leads to a mate in 5, from your engine's point of view it's the same as if another move lead to mate in 2. So the move returned is a mating move, just perhaps it will shuffle the king back and forth 4 times before delivering the mate, instead of doing it immediately.
i don't use iterative deepening, my whole search module is it that 76 lines pieces of code i posted above.
i'm 99% sure i have no bugs in my move generator nor in my make/undo move functions because i tested them with hundreds of perft testing suites.
algerbrex mentioned something about the engine rewarding finding mate as playing mate so you both seem to agree.
User avatar
algerbrex
Posts: 596
Joined: Sun May 30, 2021 5:03 am
Location: United States
Full name: Christian Dean

Re: how to continue

Post by algerbrex »

tcusr wrote: Tue Sep 07, 2021 11:13 pm
The only odd thing I can see in the code you posted above is that you have a beta cutoff in the root (how could a root move ever be too good?) and I think you could safely remove it. I have the hunch that it is responsible for your random moves. If it helps I can explain to you why exactly... but let's try that first.
tbf i copied it from algerbrex code (it seemed off to me too, i just kept it because i was desperate), i removed it now and it still finds mate if depth > 1 as before, thank you for that.
but still, if i remove "+ ply" it gives me random moves, only check extensions solve this
I was just surprised that you added check extensions (which I still don't have in my engine) before quiescence search.
i don't understand, why? check extensions is literally one statement. to add quiescence i have to first implement MVV/LVA ordering otherwise i will get a "quiescence explosion" which slows down search massively.
You can do whatever you want. But most engines only call the static evaluation on quiet positions where no captures are possible anymore
so you check for checkmate in the quiescence search?
Yeah, Lithander’s right. I added that code months ago, and never removed it, even after I realized it didn’t really make sense, mostly bc it didn’t have any negative consequences afaik could tell. So ignore that.
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

algerbrex wrote: Wed Sep 08, 2021 12:31 am
tcusr wrote: Tue Sep 07, 2021 11:13 pm
The only odd thing I can see in the code you posted above is that you have a beta cutoff in the root (how could a root move ever be too good?) and I think you could safely remove it. I have the hunch that it is responsible for your random moves. If it helps I can explain to you why exactly... but let's try that first.
tbf i copied it from algerbrex code (it seemed off to me too, i just kept it because i was desperate), i removed it now and it still finds mate if depth > 1 as before, thank you for that.
but still, if i remove "+ ply" it gives me random moves, only check extensions solve this
I was just surprised that you added check extensions (which I still don't have in my engine) before quiescence search.
i don't understand, why? check extensions is literally one statement. to add quiescence i have to first implement MVV/LVA ordering otherwise i will get a "quiescence explosion" which slows down search massively.
You can do whatever you want. But most engines only call the static evaluation on quiet positions where no captures are possible anymore
so you check for checkmate in the quiescence search?
Yeah, Lithander’s right. I added that code months ago, and never removed it, even after I realized it didn’t really make sense, mostly bc it didn’t have any negative consequences afaik could tell. So ignore that.
i removed it, i've only added the extra parameter for the ply and now it works perfectly and i also know why now (thanks mergi)
now it's time to move on.

btw i looked at your evaluation function and it seems pretty simple, is blunder really 2000 elo? that's impressive
what features should i add to get to that point?
in the following days i intend to add MVV/LVA ordering, quiescence search, PSQT tables, after that i don't really know
User avatar
algerbrex
Posts: 596
Joined: Sun May 30, 2021 5:03 am
Location: United States
Full name: Christian Dean

Re: how to continue

Post by algerbrex »

tcusr wrote: Wed Sep 08, 2021 12:52 am
algerbrex wrote: Wed Sep 08, 2021 12:31 am
tcusr wrote: Tue Sep 07, 2021 11:13 pm
The only odd thing I can see in the code you posted above is that you have a beta cutoff in the root (how could a root move ever be too good?) and I think you could safely remove it. I have the hunch that it is responsible for your random moves. If it helps I can explain to you why exactly... but let's try that first.
tbf i copied it from algerbrex code (it seemed off to me too, i just kept it because i was desperate), i removed it now and it still finds mate if depth > 1 as before, thank you for that.
but still, if i remove "+ ply" it gives me random moves, only check extensions solve this
I was just surprised that you added check extensions (which I still don't have in my engine) before quiescence search.
i don't understand, why? check extensions is literally one statement. to add quiescence i have to first implement MVV/LVA ordering otherwise i will get a "quiescence explosion" which slows down search massively.
You can do whatever you want. But most engines only call the static evaluation on quiet positions where no captures are possible anymore
so you check for checkmate in the quiescence search?
Yeah, Lithander’s right. I added that code months ago, and never removed it, even after I realized it didn’t really make sense, mostly bc it didn’t have any negative consequences afaik could tell. So ignore that.
i removed it, i've only added the extra parameter for the ply and now it works perfectly and i also know why now (thanks mergi)
now it's time to move on.

btw i looked at your evaluation function and it seems pretty simple, is blunder really 2000 elo? that's impressive
what features should i add to get to that point?
in the following days i intend to add MVV/LVA ordering, quiescence search, PSQT tables, after that i don't really know
Thank you!

From personal testing and testing on the CCRL, Blunder is around 2000 Elo, maybe slightly above. Officially, it's listed at ~2038 Elo (+/- 39 Elo).

And yes, the evaluation function is pretty simple code-wise, and currently only uses piece-square tables for the middle and endgame, interpolated together using tapered evaluation. The piece-square tables are from Lithander, who has done a lot of great work with texel tuning and creating strong piece-square tables, and I hope in the next several versions of Blunder, I can create my own custom piece-square tables with automated tuning.

But piece-square tables and tapered evaluation can be quite powerful, combined with a good search. Ronald Friederich's PeSTO engine is a testament to this, which only has piece-square tables and tapered evaluation, but plays at a +3000 Elo level.

If you go and look at the README page for Blunder, all of the features I'm currently using should be listed there.

Here are several ideas I think you should look into after you've finished the above:
  • Killer moves (50-70 Elo)
  • Null-Move pruning (50-100 Elo)
The above are pretty simple and have very nice gains. After that, look into implementing:
These features should get you around ~1900-2100 Elo, depending on the overall speed of your engine. You'll probably need to do a bit of work debugging the later features, but the Elo gains they give you are well worth the trouble.

After the above, there are a lot of different directions you can take. Some ideas I'm currently considering are:
  • Late move reductions
  • Static null move pruning
  • Futility pruning, in main search and quiesence search
  • Pawn structure evaluation.
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

algerbrex wrote: Wed Sep 08, 2021 1:36 am
tcusr wrote: Wed Sep 08, 2021 12:52 am
algerbrex wrote: Wed Sep 08, 2021 12:31 am
tcusr wrote: Tue Sep 07, 2021 11:13 pm
The only odd thing I can see in the code you posted above is that you have a beta cutoff in the root (how could a root move ever be too good?) and I think you could safely remove it. I have the hunch that it is responsible for your random moves. If it helps I can explain to you why exactly... but let's try that first.
tbf i copied it from algerbrex code (it seemed off to me too, i just kept it because i was desperate), i removed it now and it still finds mate if depth > 1 as before, thank you for that.
but still, if i remove "+ ply" it gives me random moves, only check extensions solve this
I was just surprised that you added check extensions (which I still don't have in my engine) before quiescence search.
i don't understand, why? check extensions is literally one statement. to add quiescence i have to first implement MVV/LVA ordering otherwise i will get a "quiescence explosion" which slows down search massively.
You can do whatever you want. But most engines only call the static evaluation on quiet positions where no captures are possible anymore
so you check for checkmate in the quiescence search?
Yeah, Lithander’s right. I added that code months ago, and never removed it, even after I realized it didn’t really make sense, mostly bc it didn’t have any negative consequences afaik could tell. So ignore that.
i removed it, i've only added the extra parameter for the ply and now it works perfectly and i also know why now (thanks mergi)
now it's time to move on.

btw i looked at your evaluation function and it seems pretty simple, is blunder really 2000 elo? that's impressive
what features should i add to get to that point?
in the following days i intend to add MVV/LVA ordering, quiescence search, PSQT tables, after that i don't really know
Thank you!

From personal testing and testing on the CCRL, Blunder is around 2000 Elo, maybe slightly above. Officially, it's listed at ~2038 Elo (+/- 39 Elo).

And yes, the evaluation function is pretty simple code-wise, and currently only uses piece-square tables for the middle and endgame, interpolated together using tapered evaluation. The piece-square tables are from Lithander, who has done a lot of great work with texel tuning and creating strong piece-square tables, and I hope in the next several versions of Blunder, I can create my own custom piece-square tables with automated tuning.

But piece-square tables and tapered evaluation can be quite powerful, combined with a good search. Ronald Friederich's PeSTO engine is a testament to this, which only has piece-square tables and tapered evaluation, but plays at a +3000 Elo level.

If you go and look at the README page for Blunder, all of the features I'm currently using should be listed there.

Here are several ideas I think you should look into after you've finished the above:
  • Killer moves (50-70 Elo)
  • Null-Move pruning (50-100 Elo)
The above are pretty simple and have very nice gains. After that, look into implementing:
These features should get you around ~1900-2100 Elo, depending on the overall speed of your engine. You'll probably need to do a bit of work debugging the later features, but the Elo gains they give you are well worth the trouble.

After the above, there are a lot of different directions you can take. Some ideas I'm currently considering are:
  • Late move reductions
  • Static null move pruning
  • Futility pruning, in main search and quiesence search
  • Pawn structure evaluation.
many thanks, this is going to be fun!
User avatar
lithander
Posts: 881
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: how to continue

Post by lithander »

algerbrex wrote: Wed Sep 08, 2021 1:36 am And yes, the evaluation function is pretty simple code-wise, and currently only uses piece-square tables for the middle and endgame, interpolated together using tapered evaluation. The piece-square tables are from Lithander, who has done a lot of great work with texel tuning and creating strong piece-square tables, and I hope in the next several versions of Blunder, I can create my own custom piece-square tables with automated tuning.
It makes me very happy to see that I could contribute tables to the community that programmers are adapting for their own engines. (If only temporary!)

As you are listing improvements and their worth in ELO it might be interesting to add that my current version of MinimalChess uses a 13th table in addition to the 12 tapered, tuned PSTs. This 13th table is also auto-tuned and used to modify the PST based evaluation based on the squares each individual piece threatens.

I just tested it again and this modification to the former pure PST-only evaluation is worth 124 ELO in selfplay! (MMC 0.6 is about 2400 ELO strong)
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

update:
i implemented MVV/LVA ordering and quiescence search (a search of depth 10 from here "8/1k6/4r1q1/1K1b3p/5N2/8/8/8 w - - 0 1" went from 13s to less than 1!!)

i have a few questions. in quiescence what kind of moves should i generate? at the moment i generate captures, all promotions and en passant, but how do i solve the problem we talked about yesterday, detecting checkmate?
since being in check is not a quiet position i need to check for it right?

also i think that after PSQT tables i will implement the UCI protocol so i can see it play against other engines to get a feel of how strong it actually is

[edit]
another thing, i also decided to order moves in my negamax function instead of only at the root (i still don't have an iterative deepening loop) and i noticed that it is 2x faster, even though mergi, i think, told me it was not a good idea.
User avatar
lithander
Posts: 881
Joined: Sun Dec 27, 2020 2:40 am
Location: Bremen, Germany
Full name: Thomas Jahn

Re: how to continue

Post by lithander »

tcusr wrote: Wed Sep 08, 2021 12:27 pm i have a few questions. in quiescence what kind of moves should i generate? at the moment i generate captures, all promotions and en passant, but how do i solve the problem we talked about yesterday, detecting checkmate?
since being in check is not a quiet position i need to check for it right?
when in check I generate all the moves.
tcusr wrote: Wed Sep 08, 2021 12:27 pm also i think that after PSQT tables i will implement the UCI protocol so i can see it play against other engines to get a feel of how strong it actually is
you can even do that now. 1000 ELO is already achievable.
tcusr wrote: Wed Sep 08, 2021 12:27 pm another thing, i also decided to order moves in my negamax function instead of only at the root (i still don't have an iterative deepening loop) and i noticed that it is 2x faster, even though mergi, i think, told me it was not a good idea.
move ordering? like MVVLVA? I would do that everywhere even in QSearch.

my takeaway from what mergi said was that you can order the root moves differently e.g. by node count. But I tried that and didn't work for me and so I use the same move ordering everywhere: PV move first, then MVV/LVA, then killers, then quiet moves ordered by history.
Minimal Chess (simple, open source, C#) - Youtube & Github
Leorik (competitive, in active development, C#) - Github & Lichess
User avatar
algerbrex
Posts: 596
Joined: Sun May 30, 2021 5:03 am
Location: United States
Full name: Christian Dean

Re: how to continue

Post by algerbrex »

lithander wrote: Wed Sep 08, 2021 12:07 pm
algerbrex wrote: Wed Sep 08, 2021 1:36 am And yes, the evaluation function is pretty simple code-wise, and currently only uses piece-square tables for the middle and endgame, interpolated together using tapered evaluation. The piece-square tables are from Lithander, who has done a lot of great work with texel tuning and creating strong piece-square tables, and I hope in the next several versions of Blunder, I can create my own custom piece-square tables with automated tuning.
It makes me very happy to see that I could contribute tables to the community that programmers are adapting for their own engines. (If only temporary!)

As you are listing improvements and their worth in ELO it might be interesting to add that my current version of MinimalChess uses a 13th table in addition to the 12 tapered, tuned PSTs. This 13th table is also auto-tuned and used to modify the PST based evaluation based on the squares each individual piece threatens.

I just tested it again and this modification to the former pure PST-only evaluation is worth 124 ELO in selfplay! (MMC 0.6 is about 2400 ELO strong)
Of course!

I was originally going to stick PeSTO's classic tables into Blunder for the time being, but I remember coming across yours and seeing the excellent results you had, and so I wanted to try those instead. And so far they've helped out Blunder quite nicely! If I remember correctly, they added around ~50-100 Elo and made up a lot of gaps in Blunder's evaluation knowledge.

And I remember reading about that 13th table and you explaining it before, and I thought that was pretty amazing how you could get those kinds of results with only the addition of another table. It's motivated me to do some more experimenting with PST tables in terms of mobility in the future.

Have you considered yet trying to tune any more tables for something like passed pawns or what not? It sounds like those results would be interesting at least.
tcusr
Posts: 323
Joined: Tue Aug 31, 2021 10:32 pm
Full name: tcusr

Re: how to continue

Post by tcusr »

when in check I generate all the moves.
this clears all my doubts
[edit]
no it doesn't

after i get out of the move/unamake loop with no moves played, what do i need check for?

Code: Select all

if (no_moves && in_check)
    return -MAX_EVAL
this seems correct but i have no way to detect stalemate in quiescence
you can even do that now. 1000 ELO is already achievable.
i really hope im not at 1000 elo because even though i only have the most basic features the engine works correctly and is fast (it's written in C++ vs algerbrex's engine which is written in Go, so even when i'll reach his amount of features i expect (hope) my engine performs a bit better)
move ordering? like MVVLVA? I would do that everywhere even in QSearch.

my takeaway from what mergi said was that you can order the root moves differently e.g. by node count. But I tried that and didn't work for me and so I use the same move ordering everywhere: PV move first, then MVV/LVA, then killers, then quiet moves ordered by history.
yes i meant MVVLVA, i only have that way to order moves for now. it seems like there are no downsides in using MVVLVA in negamax, i'll leave it there