Sven Schüle wrote:If you can implement those 10 rules for a perfect KRKR draw recognizer without such a "costly memory access" then you're indeed a magician.
That is totally trivial, not? The rules (at least those Thomas posted here) only use quite simple conditions on board, piece list or other kernel data. You don't need a costly memory access to determine if your King is on the edge, if your King and Rook are skewered, etc. E.g. the skewer can be calculated from the piece locations as
You still have to code a bitbase or table base access for testing the modules. I wrote my own table base generator for that and verified the rules against my table base.
For my 5 mans I saved some processing time and just used the Gaviota ones for validation. So far the only exception were I relied on something I did not do myself.
Sven Schüle wrote:If you can implement those 10 rules for a perfect KRKR draw recognizer without such a "costly memory access" then you're indeed a magician.
That is totally trivial, not? The rules (at least those Thomas posted here) only use quite simple conditions on board, piece list or other kernel data. You don't need a costly memory access to determine if your King is on the edge, if your King and Rook are skewered, etc. E.g. the skewer can be calculated from the piece locations as
So you say, deltaVec[] and distance[] are not in memory? Or you say, they are but you *always* access them through the cache? And one bitbase access including one index calculation needed for it is more costly than processing up to 10 complex rules, where in most cases you need to process all of them since most positions do not match any of these rules and are drawn?
Indeed, such small tables belonging to the 'kernel data' of your engine should always be in the L1 cache.
Last time I measured this a DRAM access took about 75 clocks, and the CPU could do 3 instructions per clock. As CPU clock speeds rise, this usually get worse. And nowadays they do 4 instructions per clock. So yes, you can do a lot of rules in the time of one memory access.
Prayer is very powerful. When you casually say you're going to pray, you are already alloted 50% of the bonus. You go about the day forgetting about it and you exclaimed "OMG!" - the Great Evaluator parses it as 'prayer' and you get the other half bonus.
I have found the bug that caused my evaluation not to enter evalBR() for the case KBKR. There was a bug when the material flag failed to include KBKR in the case of _at_most_1pawn.
I would not say it is a silly bug. Any engine that implements most of all commonly known features of a chess program is complex - mine is one such full feature engine. Bugs can easily creep in even when seemingly trivial changes are made.
So now, I have to see why my KPK routine is not working. I'll try a more well rounded and holistic approach...
Chan Rasjid wrote:I have found the bug that caused my evaluation not to enter evalBR() for the case KBKR. There was a bug when the material flag failed to include KBKR in the case of _at_most_1pawn.
Well, I hope you remember my post from four days ago ...
Sven Schüle wrote:
Chan Rasjid wrote:evalBR() is called within evalAtMost1Pawn() with the codes shown.
...
But if I put the condition blocks,etc at the very beginning of eval(), then the condition is satisfied and evalBR() is used:
That means that the condition to call evalAtMost1Pawn() is false.
In Spartacus I implemented stuff like this through the material table. This table is indexed by the material composition, and contains a single (unsigned) byte for each composition. If the encoded value X is below 200, it adds X-100 to the score, which can be used to implement cooperative material effects such as the Bishop pair, dependence of the B-N difference on the number of Pawns, or gradients that encourage / discourage Piece or Pawn trading, upto +/- 100cP. (I forgot if I multiply this by 2 or 4 to extend the range somewhat.)
All codes > 200 are reserved for drawish end-games and recognizers. You only need a single compare+branch to catch them, causing minimal burden to the search in middle-game positions. When a code > 200 occurs, it is further distinguished in two cases: drawishness corrections, where they are used as an index in a table that contains the white and black factor for that case (should that side be ahead), or an index in a table of pointers too specialized evaluation routines.
I'm having trouble coming up with a heuristic that helps find 3. Rc6 more quickly.
I tried making a fairly complete KRKB evaluator (during the search), which recognises 27% of table-base draws and 93% of tablebase wins (all the other ones are evaluated as "drawish", so it's actually quite good in practice) but it's not enough.
Apart from that, it's also pretty slow at the moment. Node counts are down, but time-to-depth has increased...
Tablebase percentages are usually totally misleading, so I am not sure how I should interpret this. For all I know 93% of the tablebase wins could be positions where the Bishop hangs, and recognizing those is hardly helpful. Which side to move are we talking about anyway? For tablebase statistics that makes quite a difference!
hgm wrote:Tablebase percentages are usually totally misleading, so I am not sure how I should interpret this. For all I know 93% of the tablebase wins could be positions where the Bishop hangs, and recognizing those is hardly helpful. Which side to move are we talking about anyway? For tablebase statistics that makes quite a difference!
Well, positions where a piece outright hangs are about 10%, off the top of my head (I can check to make sure). You're right that they're not important to identify, but they are trivial and so I included them.
I discard positions where one side is in check because those are also not very useful and tricky to evaluate properly. Of the remaining positions patterns identify 93% of the won positions as "won". If I identify all positions with the defending party on move as "unknown" the heuristic still recognises 92% of won tablebase positions as won.