For Damage this is a Database WinSo at depth=0, what do you do here? Return eval() or try 27-21 and 27-22?
Bert
I return eval() if it fails high, otherwise try the two moves.Rein Halbersma wrote:So at depth=0, what do you do here? Return eval() or try 27-21 and 27-22?
I'm not sure I see the real problem.To my knowledge this is exactly what Michel is doing, so it's certainly possible. I didn't carefully think about it because I assumed that:
1) bitboards would only easily allow base-4 indices instead of base 3. For 8 squares already this would waste 90% of the index space, not to mention larger patterns.
2) bitboards would "prefer" regularly-spaced, identically-shaped patterns. While this is what I have now, I preferred not to commit to such a design at an early stage.
Of course that was just intuition. I might be wrong on both counts.
Code: Select all
// Board Squares
#define SFLD1 6
#define SFLD2 7
#define SFLD3 8
#define SFLD4 9
#define SFLD5 10
#define SFLD6 11
#define SFLD7 12
#define SFLD8 13
#define SFLD9 14
#define SFLD10 15
#define SFLD11 17
...................................
#define SFLD50 59
Code: Select all
value1 += Weight[4 + 0 * 6561 + i9(bd, SFLD1, SFLD2, SFLD6, SFLD7, SFLD11, SFLD12, SFLD16, SFLD17)];
value1 += Weight[4 + 1 * 6561 + i9(bd, SFLD2, SFLD3, SFLD7, SFLD8, SFLD12, SFLD13, SFLD17, SFLD18)];
value1 += Weight[4 + 2 * 6561 + i9(bd, SFLD3, SFLD4, SFLD8, SFLD9, SFLD13, SFLD14, SFLD18, SFLD19)];
value1 += Weight[4 + 3 * 6561 + i9(bd, SFLD4, SFLD5, SFLD9, SFLD10, SFLD14, SFLD15, SFLD19, SFLD20)];
value1 += Weight[4 + 4 * 6561 + i9(bd, SFLD11, SFLD12, SFLD16, SFLD17, SFLD21, SFLD22, SFLD26, SFLD27)];
value1 += Weight[4 + 5 * 6561 + i9(bd, SFLD12, SFLD13, SFLD17, SFLD18, SFLD22, SFLD23, SFLD27, SFLD28)];
value1 += Weight[4 + 6 * 6561 + i9(bd, SFLD13, SFLD14, SFLD18, SFLD19, SFLD23, SFLD24, SFLD28, SFLD29)];
value1 += Weight[4 + 7 * 6561 + i9(bd, SFLD14, SFLD15, SFLD19, SFLD20, SFLD24, SFLD25, SFLD29, SFLD30)];
value1 += Weight[4 + 8 * 6561 + i9(bd, SFLD21, SFLD22, SFLD26, SFLD27, SFLD31, SFLD32, SFLD36, SFLD37)];
value1 += Weight[4 + 9 * 6561 + i9(bd, SFLD22, SFLD23, SFLD27, SFLD28, SFLD32, SFLD33, SFLD37, SFLD38)];
value1 += Weight[4 + 10 * 6561 + i9(bd, SFLD23, SFLD24, SFLD28, SFLD29, SFLD33, SFLD34, SFLD38, SFLD39)];
value1 += Weight[4 + 11 * 6561 + i9(bd, SFLD24, SFLD25, SFLD29, SFLD30, SFLD34, SFLD35, SFLD39, SFLD40)];
value1 += Weight[4 + 12 * 6561 + i9(bd, SFLD31, SFLD32, SFLD36, SFLD37, SFLD41, SFLD42, SFLD46, SFLD47)];
value1 += Weight[4 + 13 * 6561 + i9(bd, SFLD32, SFLD33, SFLD37, SFLD38, SFLD42, SFLD43, SFLD47, SFLD48)];
value1 += Weight[4 + 14 * 6561 + i9(bd, SFLD33, SFLD34, SFLD38, SFLD39, SFLD43, SFLD44, SFLD48, SFLD49)];
value1 += Weight[4 + 15 * 6561 + i9(bd, SFLD34, SFLD35, SFLD39, SFLD40, SFLD44, SFLD45, SFLD49, SFLD50)];
Code: Select all
static int i9(const Board & bd, int s0, int s1, int s2, int s3, int s4, int s5, int s6, int s7) {
bit_t blackman = bd.bit(BM_INDEX), empty = Bit_Squares ^ ( bd.bit(WM_INDEX) | blackman);
return ((((((((
bdtrit(s0, blackman, empty)) * 3 +
bdtrit(s1, blackman, empty)) * 3 +
bdtrit(s2, blackman, empty)) * 3 +
bdtrit(s3, blackman, empty)) * 3 +
bdtrit(s4, blackman, empty)) * 3 +
bdtrit(s5, blackman, empty)) * 3 +
bdtrit(s6, blackman, empty)) * 3 +
bdtrit(s7, blackman, empty));
}
Code: Select all
inline int bdtrit(int square, bit_t blackman, bit_t empty) {
bit_t bitsquare = (bit_t)1 << square;
if (bitsquare & blackman) return (2);
else if (bitsquare & empty) return (1);
else return (0);
}
Of course, bdtrit is rigorously equivalent to my trit array. It was actually on my Todo list for a while. But I assumed it would be too slow, given the large number of times I need it. Do you have any hard figure? If not fast enough, it's also possible to make it branchless I think; not my cup of tea though.BertTuyt wrote:And a inline definition for bdtrit
I have a feeling that a branchless version would be significantly "less slow", perhaps "only" 10-20% slower. Imagine that W and B are 0/1 booleans indicating a white (resp. black) piece on a given square. Then B - W + 1 is what we want. Actually I'm now using -1/0/+1 trits instead of 0/1/2 so it's even easier.BertTuyt wrote:Anyway i will have another quick look, if i can make it ( a little) faster.
Why? Is your definition of "quiescent" that no exchanges are possible? I would expect that to give very large QS trees, especially as you apply this recursively. E.g. in this positionFabien Letouzey wrote:I return eval() if it fails high, otherwise try the two moves.Rein Halbersma wrote:So at depth=0, what do you do here? Return eval() or try 27-21 and 27-22?
Code: Select all
1. 32-27 21x32
2. 38x27 18-22
3. 27x18 13x22
4. 33-28 22x33
5. 39x28 19-23
6. 28x19 14x23
7. 34-29 23x34
8. 40x29 20-24
9. 29x20 15x24
It's probably only a vocabulary issue but I don't think in terms of what is quiescent or not. Instead I focus on what I can do to improve my position (in a drastic way) when the score is bad. And my answer in QS is "try exchanges", recursively.Rein Halbersma wrote:Why? Is your definition of "quiescent" that no exchanges are possible? I would expect that to give very large QS trees, especially as you apply this recursively.
I guess so, IF the score precisely dances around beta after each exchange.So, depending on the search bounds, would your QS fully explore ... before returning eval()?
Ok, I think I understand your reasoning that it requires a very intricate dance around small score window to generate long exchange sequences forboth sides. But after I move-you-take my score has dropped even more, so then your QS would presumably go on to sacrifice even more material in hope of a big counter-combination, is that correct?Fabien Letouzey wrote:It's probably only a vocabulary issue but I don't think in terms of what is quiescent or not. Instead I focus on what I can do to improve my position (in a drastic way) when the score is bad. And my answer in QS is "try exchanges", recursively.Rein Halbersma wrote:Why? Is your definition of "quiescent" that no exchanges are possible? I would expect that to give very large QS trees, especially as you apply this recursively.
I don't understand where the sacrifice is coming from. My definition of "exchange" is: I move, he takes, I take (3 plies). The special move generator makes sure that I will be able to capture on the 3rd ply.Rein Halbersma wrote:Ok, I think I understand your reasoning that it requires a very intricate dance around small score window to generate long exchange sequences forboth sides. But after I move-you-take my score has dropped even more, so then your QS would presumably go on to sacrifice even more material in hope of a big counter-combination, is that correct?
Maybe "pending" is what I call a "pin"? I move a piece, and this allows the opponent to capture another one I was defending? No I haven't tried it. I assumed most would be bad in random positions (contrary to exchanges). Probably some restrictions should be added. I also assumed that "pins" would be rarer than exchanges, especially interesting ones.Did you ever try only extending pending captures or threatened captures? Evidently your search is very good, but it sounds counter-intuitive to me to try exchanges in QS when it is not forced, instead of quickly terminating and calling eval.
I think that's it, we just view QS differently. For me, QS is what you make it. In the 90's when everybody was extending tactical moves, it makes sense to reduce it to a minimum. But remember that I prune a lot, so I'd rather have some tactical safety at low depth. Static eval doesn't take that into account because I filter out capture positions during learning.For me QS means, depth<=0 and resources are up: capture if you must, promote if you can and call eval otherwise. After all, the next iteration of the regular search will initiate the exchange anyway, so you won't miss any tactics, just delay them one iteration. I understand it's a tradeoff in practice
It's not clear to me what positions you have in mind in this large thread. Show me some FENs and I'll make it happen. Note though that I don't view Scan as a tactical engine.Rein Halbersma wrote:I would be interested to learn how quickly Scan sees these difficult tactics posted there.
Just Scan's search output to nominal depth=25 forFabien Letouzey wrote:It's not clear to me what positions you have in mind in this large thread. Show me some FENs and I'll make it happen. Note though that I don't view Scan as a tactical engine.Rein Halbersma wrote:I would be interested to learn how quickly Scan sees these difficult tactics posted there.
4/ 6.4 -2 1482 0.00 0.00 48-42 5-10 39-33 19-23Rein Halbersma wrote:Just Scan's search output to nominal depth=25 for
White to move