Attack table

Programming Topics (Computer Chess) and technical aspects as test techniques, book building, program tuning etc

Moderator: Andres Valverde

Re: Attack table

Postby Tord Romstad » 14 Oct 2004, 14:40

Reinhard Scharnagl wrote:Hi Uri,
You do not need to validate all moves in legal move generator.

that seems to be a semantic problem - I think it would need a sort of validation in any case.
If you find that a piece is not pinned then you can be sure that all of it's moves are legal.

With the exceptions of King moves, e.p. captures, and Fischer castlings, where the rook is pinned though it would move along the pinning line.

True, but these exceptions are so rare that you can handle them in the stupid and expensive way without a noticable slowdown. My legality tester simply makes the move, tests whether the moving side is in check, and unmakes the move again in the case of e.p. captures and Fischer castlings.
But to everything else I agree. There is a great benefit of having the full information to any move: capture, check with its direction, double-check, mate, e.p.-preparing double pawn step ...

This is all true, but why do you need to find this information when the moves are generated? Isn't it just as good to have simple and fast functions to compute this kind of information when needed? Instead of identifying a move as a double check during move generation, I would rather do an "if is_double_check(move) { ... }" if/when I need this information.
Overmore the engine procedures will of course become more transparent.

How? Could you give an example of pseudo code with and without this type of stuff computed in the move generator, and explain why you consider the former to be more transparent?

Tord
User avatar
Tord Romstad
 
Posts: 639
Joined: 09 Oct 2004, 12:49
Location: Oslo, Norway

Re: Attack table

Postby Reinhard Scharnagl » 14 Oct 2004, 14:53

Hi Tord,
This is all true, but why do you need to find this information when the moves are generated? Isn't it just as good to have simple and fast functions to compute this kind of information when needed? Instead of identifying a move as a double check during move generation, I would rather do an "if is_double_check(move) { ... }" if/when I need this information.

I need It during preevaluating generated moves to prepare move ordering, therefore doing it when it would be cheap: at move generation.
How? Could you give an example of pseudo code with and without this type of stuff computed in the move generator, and explain why you consider the former to be more transparent?

Code: Select all
if (generated_moves_and_count() == 0) stalemate();

which only will be called when not already been mated, which has been checked long before, as the previous move would have been a mating move.

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Tord Romstad » 14 Oct 2004, 14:55

Reinhard Scharnagl wrote:Hi Tord,

still I am thinking on attack tables, still I am not convinced, but I am also still learning.

I am also not convinced, and I am also still learning. :D

Using attack tables or not is an important design choice, which will probably have a big influence on the structure of your engine. It is perfectly possible to write a world-class engine both ways, but the program will be very different.
I don't really understand the discussion about legal vs pseudo-legal move generators. As far as I can see, the difference has no practical importance. With a pseudo-legal move generator, I have to do an "if(is_legal(move))" before making and searching a move. I can't see why this single extra line of code matters.

Does this "single" line (with some following calculations) help you when to decide a situation to be mate or stalemate?

All engines I know, including both of mine, generate legal moves when the side to move is in check. When the move generator returns zero moves and the side to move is in check, my search immediately returns a mate score. I handle stalemate at the end of the loop through all moves in my search function. During the move loop, I increment a counter for each move considered (this counter is also used for other purposes; I prune more heavily towards the end of the move list). If this counter is zero when the move loop is finished, I return a stalemate score. So you are right, I need another extra line of code to handle stalemates correctly.

Tord
User avatar
Tord Romstad
 
Posts: 639
Joined: 09 Oct 2004, 12:49
Location: Oslo, Norway

Re: Attack table

Postby Uri Blass » 14 Oct 2004, 14:59

Hi Tord.

The point of detecting the information in move generation isthat you have the information earlier.

You may want to prune based on evaluation and remaining depth and knowing only by generating moves that there is no mate is clearly less expensive than checking every legal move to find that it is not mate.

Note that I added some information to my last reply to you by editing it(I deleted nothing).

I will not do it again in the future unless I decide to correct some clerical error because I think that it can be confusing.


Uri
User avatar
Uri Blass
 
Posts: 727
Joined: 09 Oct 2004, 05:59
Location: Tel-Aviv

Re: Attack table

Postby Sven Schüle » 15 Oct 2004, 17:28

Hi, Reinhard,

replying to an old posting:
Reinhard Scharnagl wrote:to enhance your position it would be good to describe an example, where you recognize a move to be a check threat and you are not interested to know, whether this move would be a mate or not. I think that in most cases it would of course be interesting to decide this, thus providing such information would not be a wasted efford.

Of course I would be interested in such information in general during move generation, but I would not get it for free. It's really a question of the effort spent.

The searcher will find the mate after making the move. If you move the complete mate detection into the move generator then you have to analyze each move which you recognize as check to see if it mates. In nearly all cases this analysis fails.

Let's compare.
- For P1 percent of (full search) nodes, there is no mating move. Assume you waste an average additional effort for mate checking within move generation of W1 time units per node, and there is nothing you save for the search.
- For the remaining (100-P1) percent of nodes, there is a mating move. Your additional effort might be about W1, too, but depending on your move ordering criteria regarding checks, you might save more or less search effort, e.g. you might save searching one or more subtrees if the mating move would not appear on first position in the move list. Say you save some effort of W2 time units on average.

Now adding all additional efforts and subtracting all savings, if (100-P1)*W2 - 100*W1 is positive "in the average case", your strategy might be successful. Trying to solve this by assuming some factor K in W2=K*W1, I get (for W1>0 and K>1):
Code: Select all
      (100-P1)*K*W1 - 100*W1 > 0
<=>   (100-P1)*K > 100

Let's further assume that 90 <= P1 <= 99,9, i.e. depending on the type of position (excluding some endgames here of course, I know!) the percentage of mating moves within the set of all generated moves might lie between 0,1% and 10% over all positions ever considered.

For P1=90 (many mating moves), you are successful with K>10, i.e. the saving W2 is more than 10* the "wasted" effort W1 for mate detection in movegen.
For P1=99,9 (few mating moves), you are successful with K>1000.

I would expect that the "reality" is closer to the latter case, and I am not sure whether the expected saving will be of that order of magnitude.

Hopefully I did not mess up something in my formulas, and everyone's laughing now :wink:

I know that this is no scientific approach, please don't assume that I wanted to give any kind of proof. Just I wanted to express my feeling that there is a tradeoff to be considered, and that it is not clear for me why you are sure that your approach will be an improvement compared to normal mate detection during search.

Sven
User avatar
Sven Schüle
 
Posts: 240
Joined: 26 Sep 2004, 20:19
Location: Berlin, Germany

Re: Attack table

Postby Uri Blass » 15 Oct 2004, 18:25

Hi Sven.

You say:
"Let's compare.
- For P1 percent of (full search) nodes, there is no mating move. Assume you waste an average additional effort for mate checking within move generation of W1 time units per node, and there is nothing you save for the search."

Here is your mistake.

There is clearly something that you save for the search because you may decide not to continue to search based on the fact that there is no mate when without knowing that there is no mate it may be too risky.

Uri
User avatar
Uri Blass
 
Posts: 727
Joined: 09 Oct 2004, 05:59
Location: Tel-Aviv

Re: Attack table

Postby Reinhard Scharnagl » 15 Oct 2004, 18:34

Hi Sven,

I am still conviced that the knowledge, whether a move is a check thread and moreover then whether it is a mating move or not, is important and could not be skipped. To lift this efforts from the move generator to the searcher (as you said) will nothing change on that situation.

May be I am interested in having clear readable procedures and therefore use fully informed moves, and may be it is slowing down my generator, but finally that work has to be done at some moment - so what?

I am still satisfied with the speed of my generator. Recent values on an Intel P4 2.8 GHz are:
Code: Select all
FEN: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

  +-*--b--c--d--*--f--g--*-+ MS Vis. Studio C++ Vers. 13.10
8 |[r][n][b][q][k][b][n][r]|
7 |[p][p][p][p][p][p][p][p]| Perft Testseries
6 |   :::   :::   :::   :::|
5 |:::   :::   :::   :::   | (without caching)
4 |   :::   :::   :::   :::|
3 |:::   :::   :::   :::   | Test #:      00
2 |<P><P><P><P><P><P><P><P>|
1 |<R><N><B><Q><K><B><N><R>| Break Time 75.0 Sec.
=>+-*--b--c--d--*--f--g--*-+

Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
01         20          0        0          0        0          0         0    0
02        400          0        0          0        0          0         0    0
03       8902         34        0         12        0          0         0    0
04     197281       1576        0        469        8          0         0    0
05    4865609      82719      258      27351      347          0         0  0.3
06  119060324    2812008     5248     809099    10828          0         0  5.7
07 3195901860  108329926   319617   33103848   435767          0    883453  154
-------------------------------------------------------------------------------


FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 25

  +-*--b--c--d--*--f--g--*-+ MS Vis. Studio C++ Vers. 13.10
8 |[r]:::   :::[k]:::   [r]|
7 |[p]   [p][p][q][p][b]   | Perft Testseries
6 |[b][n]   :::[p][n][p]:::|
5 |:::   :::<P><N>   :::   | (without caching)
4 |   [p]   :::<P>:::   :::|
3 |:::   <N>   :::<Q>:::[p]| Test #:      01
2 |<P><P><P><B><B><P><P><P>|
1 |<R>   :::   <K>   :::<R>| Break Time 75.0 Sec.
=>+-*--b--c--d--*--f--g--*-+

Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
01         48          8        0          0        0          0         2    0
02       2039        351        1          3        0          0        91    0
03      97862      17102       45        993        1          0      3162    0
04    4085603     757163     1929      25523       43      15172    128013  0.2
05  193690690   35043416    73365    3309887    30171       8392   4993637  9.9
06 8031647685 1558445089  3577504   92238050   360003   56627920 184513607  405
-------------------------------------------------------------------------------

If you would omit all those informations my moves have, you must be able to write a much faster generator, if your arguments would hold.

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Sven Schüle » 15 Oct 2004, 21:45

Uri Blass wrote:There is clearly something that you save for the search because you may decide not to continue to search based on the fact that there is no mate when without knowing that there is no mate it may be too risky.

Hi Uri,
knowing that there is no mate in 1 (i.e. none of the generated moves is a checkmate) does not mean to know that there is no forced mate in 2, 3, ... So I am not sure if this kind of pruning is safely applicable at all. Do you do this in Movei? If yes, what do you think about positions where you prune knowing it's not mate in 1 but they are in reality mate in 2 and you do not see this? Is it relevant?

For my engine Surprise, I am still very careful with forward pruning. (There must be some reason why Surprise is much weaker than Movei :) ) More exactly, I don't do it up to know, I only use something like lazy eval. If I had to decide about pruning, I would say that: if either the side to move has any check or the opponent has a very unsafe king, I would never prune away the current node's subtree, because mate threats or moves towards the unsafe king have great potential to change the evaluation drastically. A mating move is just a very rare special case of this, and I would not spend the effort to detect it before entering the node itself.

I know it's hard to convince you if my own engine is far away from really competing with yours, but at least this discussion may be helpful for some people (including ourselves) to form an opinion.

Sven
User avatar
Sven Schüle
 
Posts: 240
Joined: 26 Sep 2004, 20:19
Location: Berlin, Germany

Re: Attack table

Postby Sven Schüle » 15 Oct 2004, 22:36

Reinhard Scharnagl wrote:I am still conviced that the knowledge, whether a move is a check thread and moreover then whether it is a mating move or not, is important and could not be skipped. To lift this efforts from the move generator to the searcher (as you said) will nothing change on that situation.

Hi Reinhard,
I would only move mate detection into the searcher but leave check detection itself within the move generator to improve move ordering, allow for something like including checks for the first N plies of qsearch, and perhaps support the searcher which does not have to test again if the current side is in check. Mate detection for the searcher is simple: "(in check) and (no legal moves found)", no substantial effort.

Reinhard Scharnagl wrote:May be I am interested in having clear readable procedures and therefore use fully informed moves, and may be it is slowing down my generator, but finally that work has to be done at some moment - so what?

With the exception of mating moves, I don't see anything "false" in your concept of fully informed moves. Regarding mating, see above; nevertheless I don't really know if it's "false" to do it your way, but you should think about it again.

Reinhard Scharnagl wrote:I am still satisfied with the speed of my generator. Recent values on an Intel P4 2.8 GHz are:
Code: Select all
...
FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 25
...
Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
...
06 8031647685 1558445089  3577504   92238050   360003   56627920 184513607  405

Yes, you are right when stating that your move generator is very fast (nearly 20 Mnps with perft, sounds like less than 150 CPU cycles per node?). But obviously static mate detection is not cheap, so I suspect your generator would even be slightly faster without it. Of course, move generation is only one thing, and as I had already tried to demonstrate, the savings for the search might not compensate the additional effort for static mate detection.

By the way, in your perft example which I have quoted, the percentage of mate positions within the set of "in check" positions is about 0,004%, so my estimated "99,9%" for the remainder were not that bad ... o.k., that's not scientific at all, so I leave it to you to judge about this tradeoff I mentioned.

Sven
User avatar
Sven Schüle
 
Posts: 240
Joined: 26 Sep 2004, 20:19
Location: Berlin, Germany

Re: Attack table

Postby Uri Blass » 15 Oct 2004, 23:05

I do not detect mates in the move generator of movei and I still do not detect checks in the move generator and only have a function to detect checks after generating moves.

I believe that it is one of many reasons that movei is relatively weak to what it can be.

Uri
User avatar
Uri Blass
 
Posts: 727
Joined: 09 Oct 2004, 05:59
Location: Tel-Aviv

Re: Attack table

Postby Reinhard Scharnagl » 16 Oct 2004, 06:28

Hi Sven,
By the way, in your perft example which I have quoted, the percentage of mate positions within the set of "in check" positions is about 0,004%, so my estimated "99,9%" for the remainder were not that bad ... o.k., that's not scientific at all, so I leave it to you to judge about this tradeoff I mentioned.

well, I think that the effort to get the mating information is ideed much greater. When about 1.15% of all moves are checks in the example you have cited, all of them have to be partially expanded which might in average costs a lot of move generation trials, in my engine starting with king moves which are really expensive to be generated legally. Thus I am estimating the total costs of that mating information approach to be between 15% and 20% of the total calculating time. In other words, without this feature my generator would be able to produce 25 million moves each second on my hardware.

Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Uri Blass » 16 Oct 2004, 08:11

Reinhard Scharnagl wrote:

"When about 1.15% of all moves are checks in the example you have cited, all of them have to be partially expanded which might in average costs a lot of move generation trials, in my engine starting with king moves which are really expensive to be generated legally."

Hi Reinhard,

I guess that it is possible to generate mate information faster.

The simplest way to generate mates after generating checks(not the optimal way) is to have function that makes the checking move and try to generate all moves and stop after finding one legal moves and undo the move.

I do not think that this is the best way and I think that there are better ideas.

One idea is to start with detecting squares that the king may play into them and later detect checks as non mating moves only because they do not attack all the squares(for example after 1.e4 e5 2.d4 you can detect that e2 is not attacked and that Bf8-b4+ does not attack e2).

Another idea is that some table may help here and if you find that
after 1.e4 d5 Bb5+ Nc6 defends against the check then you may learn from that experience and after 1.e4 d6 you may see that Bb5+ is not mate because savingmate[f1b5]=b8c6 is legal and works.

Uri
User avatar
Uri Blass
 
Posts: 727
Joined: 09 Oct 2004, 05:59
Location: Tel-Aviv

Re: Attack table

Postby Reinhard Scharnagl » 16 Oct 2004, 08:23

Hi Uri,
The simplest way to generate mates after generating checks(not the optimal way) is to have function that makes the checking move and try to generate all moves and stop after finding one legal moves and undo the move.

that is the way it works in Smirf, where the most important step is to stop after the fist legal move that would be found.

Your second idea is worth thinking over. To have something like testing a killer move in that case, which would be a check threat surviving move, really might help. I have not implemented yet something like that.

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Reinhard Scharnagl » 17 Oct 2004, 15:05

Hi Uri,

after some test I am back in this older thread.
Your second idea is worth thinking over. To have something like testing a killer move in that case, which would be a check threat surviving move, really might help. I have not implemented yet something like that.

I tried some tests in that direction, but they have not been very successful. But I continue thinking it over.

To estimate the influence of testing checks being mates or not I have made som experiments. After some newly improvements I get the following results now:
Code: Select all
FEN: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

  +-*--b--c--d--*--f--g--*-+ MS Vis. Studio C++ Vers. 13.10
8 |[r][n][b][q][k][b][n][r]|
7 |[p][p][p][p][p][p][p][p]| Perft Testseries
6 |   :::   :::   :::   :::|
5 |:::   :::   :::   :::   | (without caching) (with mate detecting)
4 |   :::   :::   :::   :::|
3 |:::   :::   :::   :::   | Test #:      00
2 |<P><P><P><P><P><P><P><P>|
1 |<R><N><B><Q><K><B><N><R>| Break Time 5.0 Sec.
=>+-*--b--c--d--*--f--g--*-+

Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
01         20          0        0          0        0          0         0    0
02        400          0        0          0        0          0         0    0
03       8902         34        0         12        0          0         0    0
04     197281       1576        0        469        8          0         0    0
05    4865609      82719      258      27351      347          0         0  0.2
06  119060324    2812008     5248     809099    10828          0         0  5.4
-------------------------------------------------------------------------------


FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 25

  +-*--b--c--d--*--f--g--*-+ MS Vis. Studio C++ Vers. 13.10
8 |[r]:::   :::[k]:::   [r]|
7 |[p]   [p][p][q][p][b]   | Perft Testseries
6 |[b][n]   :::[p][n][p]:::|
5 |:::   :::<P><N>   :::   | (without caching) (with mate detecting)
4 |   [p]   :::<P>:::   :::|
3 |:::   <N>   :::<Q>:::[p]| Test #:      01
2 |<P><P><P><B><B><P><P><P>|
1 |<R>   :::   <K>   :::<R>| Break Time 5.0 Sec.
=>+-*--b--c--d--*--f--g--*-+

Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
01         48          8        0          0        0          0         2    0
02       2039        351        1          3        0          0        91    0
03      97862      17102       45        993        1          0      3162    0
04    4085603     757163     1929      25523       43      15172    128013  0.2
05  193690690   35043416    73365    3309887    30171       8392   4993637  9.1
-------------------------------------------------------------------------------

Code: Select all
FEN: rnbqkbnr/pppppppp/8/8/8/8/PPPPPPPP/RNBQKBNR w KQkq - 0 1

  +-*--b--c--d--*--f--g--*-+ MS Vis. Studio C++ Vers. 13.10
8 |[r][n][b][q][k][b][n][r]|
7 |[p][p][p][p][p][p][p][p]| Perft Testseries
6 |   :::   :::   :::   :::|
5 |:::   :::   :::   :::   | (without caching) (without mate detecting)
4 |   :::   :::   :::   :::|
3 |:::   :::   :::   :::   | Test #:      00
2 |<P><P><P><P><P><P><P><P>|
1 |<R><N><B><Q><K><B><N><R>| Break Time 1.0 Sec.
=>+-*--b--c--d--*--f--g--*-+

Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
01         20          0        0          0        0          0         0    0
02        400          0        0          0        0          0         0    0
03       8902         34        0         12        0          0         0    0
04     197281       1576        0        469        0          0         0    0
05    4865609      82719      258      27351        0          0         0  0.2
06  119060324    2812008     5248     809099        0          0         0  4.9
-------------------------------------------------------------------------------


FEN: r3k2r/p1ppqpb1/bn2pnp1/3PN3/1p2P3/2N2Q1p/PPPBBPPP/R3K2R w KQkq - 0 25

  +-*--b--c--d--*--f--g--*-+ MS Vis. Studio C++ Vers. 13.10
8 |[r]:::   :::[k]:::   [r]|
7 |[p]   [p][p][q][p][b]   | Perft Testseries
6 |[b][n]   :::[p][n][p]:::|
5 |:::   :::<P><N>   :::   | (without caching) (without mate detecting)
4 |   [p]   :::<P>:::   :::|
3 |:::   <N>   :::<Q>:::[p]| Test #:      01
2 |<P><P><P><B><B><P><P><P>|
1 |<R>   :::   <K>   :::<R>| Break Time 1.0 Sec.
=>+-*--b--c--d--*--f--g--*-+

Ply     Nodes    all (x)   (e.p.)    all (+)      (#)    Promot.    Castl. Sec.
-------------------------------------------------------------------------------
01         48          8        0          0        0          0         2    0
02       2039        351        1          3        0          0        91    0
03      97862      17102       45        993        0          0      3162    0
04    4085603     757163     1929      25523        0      15172    128013  0.2
05  193690690   35043416    73365    3309887        0       8392   4993637  8.0
-------------------------------------------------------------------------------

The two (not bad case) examples give an estimated growing rate within 9.1% to 11.4%, thus something less than my estimation of 15% to 20%. If the mating information would be helpful, I think it would be worth this additional time consuming effort.

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Tord Romstad » 17 Oct 2004, 21:07

Reinhard Scharnagl wrote:Hi Tord,
This is all true, but why do you need to find this information when the moves are generated? Isn't it just as good to have simple and fast functions to compute this kind of information when needed? Instead of identifying a move as a double check during move generation, I would rather do an "if is_double_check(move) { ... }" if/when I need this information.

I need It during preevaluating generated moves to prepare move ordering, therefore doing it when it would be cheap: at move generation.

This may or may not be true, depending on how your program is structured. It may in fact be more efficient to delay this kind of stuff, because the hash table move will often give you a cutoff before you start searching the remaining moves. In cases like this, you don't need to compute any complicated information in the move generator (in fact, you don't even need to call the move generator before you have finished searching the hash table move).
How? Could you give an example of pseudo code with and without this type of stuff computed in the move generator, and explain why you consider the former to be more transparent?

Code: Select all
if (generated_moves_and_count() == 0) stalemate();

which only will be called when not already been mated, which has been checked long before, as the previous move would have been a mating move.

Remarkably similar to my own stalemate detection code:
Code: Select all
if(legal_moves==0) return DRAW_VALUE;

The only difference is that I have this line of code after the main move loop. Doesn't matter much, IMHO.

Regarding mate detection, if you want to do this without search, I find it more natural to do it *before* move generation, in the static evaluation function. If you can detect mate without a search, what's the point in generating any moves (except perhaps the mating move)?

I used to do mate detection in my eval myself, but decided to remove it in order to simplify my code. It didn't hurt the playing strength noticably (neither in test suites nor in real games).

Tord
User avatar
Tord Romstad
 
Posts: 639
Joined: 09 Oct 2004, 12:49
Location: Oslo, Norway

Re: Attack table

Postby Reinhard Scharnagl » 17 Oct 2004, 23:33

Hi Tord,

you seem to be talking of a kind of lazy generator. I have already had a sequential generator, which started to generate the killer move first. But though there may be profits in some cases (less than half of knots), most knots have to be primarily fully generated and expanded. Therefore I regarded the overhead of having a sequential generator to be more significant that the time the unnecessarily produced moves would consume. So finally I switched to an en block move generator.

To the early mate detection: I found out that it consumes about 12% additional time. Indeed there are avoidable cases with several mates within a node. Only one would be used. That would be the very rare cases of unnecessary work. To avoid this also would cost efforts. So there is nearly nothing to save from that calculation. But you are right: it might be possible and not less transparent to delay that checking into the evaluation of nodes, where those silly double mates would not be "expanded". That would make my Perft results about that percentage (12%) better :-) .

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Zach Wegner » 19 Oct 2004, 03:16

One new point that I'd like to add (because I just implemented it) is O(n) mobility is easily possible with attack tables.
User avatar
Zach Wegner
 
Posts: 182
Joined: 26 Sep 2004, 22:02
Location: Austin, Texas, USA

Re: Attack table

Postby Reinhard Scharnagl » 19 Oct 2004, 06:16

Hi Zach,

a) I do not really understand what you mean with "O(n)".
b) I thought mobility information would be interesting only above quiescence search.

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

Re: Attack table

Postby Zach Wegner » 19 Oct 2004, 23:41

Hello Reinhard,

1. O(n) is the computer science term for complexity. IE a bubble sort is O(n^2) because for the number of elements n it will take time n*n to complete the algorithm. In this case I use it to say that in evaluation the mobility calculation always takes the same amount of time, regardless of the position (n=number of squares).

2. Well that depends on where you call evaluation.

Regards,
Zach
User avatar
Zach Wegner
 
Posts: 182
Joined: 26 Sep 2004, 22:02
Location: Austin, Texas, USA

Re: Attack table

Postby Reinhard Scharnagl » 20 Oct 2004, 00:56

Hi Zach,

well I knew the "O(...)" terminology. But it is not clear, what there should be "n" within that term.

The move sort I use in Smirf is a fast type about O(n*log(n)) (but not quicksort), where n is the number of moves. To compare both complexities you must specify what you would count as n. I prosume it depends on the product of the pieces of both colors, whereas the number of moves depends only on the number of pieces. Thus when both parties normally have comparable number of pieces, it would really be a complexity of O(n^2) in your table. But to claim this definitly one has to know your procedure exactly.

Overmore because of the limited nature of that problem (8x8 or 10x8 boards in Smirf as maximum) this argument is not really impressive, because it would matter for sure at 100x100 boards. As an example: bubble sort is faster than quicksort when ordering just two elements. But to hear from exact time consumption maybe could give a better estimation on the efficiency of those approaches.

I add an example (for testing?)
Code: Select all
FEN: R6R/3Q4/1Q4Q1/4Q3/2Q4Q/Q4Q2/pp1Q4/kBNN1KB1 w - - 0 1

  +-a--b--c--d--e--f--g--h-+ MS Vis. Studio C++ Vers. 13.10
8 |<R>:::   :::   :::   <R>|
7 |:::   :::<Q>:::   :::   | Testscenario (sorted):
6 |   <Q>   :::   :::<Q>:::| Move generation
5 |:::   :::   <Q>   :::   |
4 |   :::<Q>:::   :::   <Q>| Smirf Test No.: 13
3 |<Q>   :::   :::<Q>:::   |
2 |[p][p]   <Q>   :::   :::| Move Count:  218*750000
1 |[k]<B><N><N>:::<K><B>   | per Second:  13146257
=>+-a--b--c--d--e--f--g--h-+ Time:        12.437 sec

  1.405 Qe5xb2+  1.349 Qb6xb2+  1.240 Qc4xa2+  1.153 Qd2xb2+  1.078 Qa3xa2+
  1.036 Qa3xb2+  0.973 Nd1xb2   0.913 Nc1xa2   0.789 Bb1xa2   0.563 Qg6-c2
  0.476 Nc1-b3+  0.425 Qg6-d3   0.404 Ra8-a4   0.374 Qd7-a4   0.365 Qh4-e1
  0.341 Qh4-d4   0.318 Qf3-b3   0.313 Qd7-d3   0.303 Ra8-a5   0.289 Qb6-b3
  0.286 Qe5-c3   0.286 Rh8-b8   0.284 Qg6-e4   0.265 Rh8-c8   0.264 Qh4-e4
  0.261 Qd7-b5   0.258 Qf3-c3   0.254 Qh4-f2   0.249 Qd7-d4   0.245 Qg6-c6
  0.231 Rh8-d8   0.202 Ra8-a6   0.200 Qg6-d6   0.196 Qb6-b4   0.186 Rh8-h5
  0.186 Rh8-e8   0.180 Qh4-f4   0.180 Qf3-d3   0.177 Bg1-d4   0.174 Qg6-g2
  0.173 Qd7-d5   0.167 Qe5-e1   0.167 Qe5-a5   0.155 Qe5-e2   0.155 Qe5-b5
  0.154 Bg1-e3   0.154 Bg1-c5   0.150 Qg6-g3   0.143 Qe5-d4   0.142 Qg6-f5
  0.142 Qg6-e6   0.138 Qc4-c2   0.138 Qc4-b3   0.134 Qd7-c6   0.131 Rh8-h6
  0.131 Rh8-f8   0.130 Qh4-g3   0.127 Qf3-e2   0.120 Qe5-e3   0.120 Qe5-c5
  0.111 Qg6-g4   0.111 Qb6-a5   0.101 Ra8-a7   0.101 Kf1-e1   0.099 Qb6-b5
  0.094 Qd2-c2   0.092 Qf3-e3   0.092 Qh4-g4   0.091 Bg1-f2   0.089 Qd7-d6
  0.089 Kf1-e2   0.087 Qb6-d4   0.079 Qc4-c3   0.075 Qg6-f6   0.071 Qd7-a7
  0.069 Rh8-h7   0.069 Rh8-g8   0.066 Qe5-e4   0.066 Qe5-d5   0.063 Qb6-e3
  0.063 Qb6-c5   0.063 Qd7-b7   0.062 Qh4-h1   0.061 Qc4-a4   0.061 Qg6-g5
  0.055 Qh4-h2   0.055 Qh4-f6   0.045 Qc4-b4   0.041 Qh4-g5   0.041 Qh4-e7
  0.039 Qf3-e4   0.039 Qf3-d5   0.039 Qd7-c7   0.034 Qh4-h3   0.034 Qd2-c3
  0.031 Qd7-f5   0.031 Qd7-e6   0.029 Qf3-f2   0.017 Nd1-c3   0.010 Qb6-a6
  0.000 Qb6-f2   0.000 Qd7-g4   0.000 Qc4-d3  -0.000 Qg6-f7  -0.000 Qh4-d8
 -0.000 Qd2-b4  -0.000 Qf3-c6  -0.007 Ra8-b8  -0.010 Kf1-f2  -0.018 Qe5-f4
 -0.018 Qe5-d6  -0.024 Qa3-b3  -0.025 Qg6-h5  -0.025 Qg6-e8  -0.028 Ra8-c8
 -0.029 Qb6-c6  -0.045 Qd2-d3  -0.045 Qf3-f4  -0.045 Qh4-h5  -0.051 Qd7-e7
 -0.052 Qc4-e2  -0.052 Qc4-b5  -0.058 Qd7-h3  -0.058 Qd7-c8  -0.062 Ra8-d8
 -0.064 Qc4-d4  -0.067 Qe5-g3  -0.067 Qe5-c7  -0.068 Qg6-g7  -0.070 Qf3-g2
 -0.071 Qf3-b7  -0.074 Qb6-d6  -0.075 Qe5-f5  -0.075 Qe5-e6  -0.080 Qg6-h6
 -0.084 Qa3-c3  -0.085 Qd2-e1  -0.085 Qd2-a5  -0.088 Qc4-c5  -0.091 Qb6-a7
 -0.092 Qd7-d8  -0.095 Qf3-g3  -0.097 Qd2-e2  -0.099 Qb6-b7  -0.100 Qh4-h6
 -0.101 Qa3-a4  -0.103 Qf3-f5  -0.107 Ra8-e8  -0.108 Bg1-h2  -0.109 Qd2-d4
 -0.109 Kf1-g2  -0.111 Qd7-f7  -0.117 Qa3-b4  -0.124 Qb6-c7  -0.125 Bb1-c2
 -0.132 Qb6-e6  -0.132 Qd2-e3  -0.134 Qf3-g4  -0.137 Qd7-e8  -0.141 Qc4-e4
 -0.141 Qc4-d5  -0.141 Qc4-a6  -0.142 Qg6-h7  -0.142 Qg6-g8  -0.143 Qe5-h2
 -0.143 Qe5-f6  -0.143 Qe5-b8  -0.149 Nd1-e3  -0.157 Qe5-g5  -0.157 Qe5-e7
 -0.162 Ra8-f8  -0.162 Qh4-h7  -0.162 Qa3-d3  -0.162 Nc1-d3  -0.163 Qf3-h1
 -0.170 Qf3-f6  -0.179 Qd7-g7  -0.180 Qc4-c6  -0.186 Qd2-d5  -0.191 Qf3-h3
 -0.196 Qd2-f2  -0.199 Qb6-f6  -0.199 Qb6-b8  -0.202 Qa3-a5  -0.212 Nd1-f2
 -0.214 Nc1-e2  -0.224 Ra8-g8  -0.225 Qc4-f4  -0.243 Qe5-h5  -0.243 Qe5-e8
 -0.245 Qf3-f7  -0.250 Qa3-e3  -0.250 Qa3-c5  -0.254 Qd7-h7  -0.254 Qb6-d8
 -0.263 Bb1-d3  -0.270 Qd2-f4  -0.270 Qd2-d6  -0.270 Qf3-h5  -0.275 Qc4-c7
 -0.283 Qc4-e6  -0.286 Qe5-g7  -0.295 Qd2-g2  -0.303 Qa3-a6  -0.313 Qc4-g4
 -0.325 Qf3-f8  -0.371 Qc4-c8  -0.387 Qa3-d6  -0.395 Qd2-h2  -0.404 Qa3-a7
 -0.404 Bb1-e4  -0.409 Qd2-g5  -0.425 Qc4-f7  -0.526 Qa3-e7  -0.546 Bb1-f5
 -0.549 Qd2-h6  -0.567 Qc4-g8  -0.667 Qa3-f8


PS.: what would be your answer to question b) ? (depending on YOU)

Regards, Reinhard.
Reinhard Scharnagl
 
Posts: 608
Joined: 01 Oct 2004, 08:36
Location: Klein-Gerau, Germany

PreviousNext

Return to Programming and Technical Discussions

Who is online

Users browsing this forum: No registered users and 5 guests