1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
|
// generate.c changes to restore counter-move scoring. Three pieces, in
// the same function (the one with PRECOMP_KILLERS sKillers[...] and the
// "Pre-populate killer/bonuses" comment -- search for that to find it).
// LOCATION 1: local var decls at top of the function -- add mvLast and
// pi, bump sKillers to 6:
//
// PLY_INFO *pi = &ctx->sPlyInfo[ctx->uPly]; // ADD
// ULONG uPly = ctx->uPly;
// POSITION *pos = &ctx->sPosition;
// ULONG u;
// MOVE mv;
// MOVE mvLast = (pi-1)->mv; // ADD
// SCORE s;
// MOVE_STACK_MOVE_VALUE_FLAGS mvf;
// ULONG uHashMoveLoc = (ULONG)-1;
// ULONG uColor = pos->uToMove;
// PRECOMP_KILLERS sKillers[6]; // was [4]
// COOR cEnprise = FindEnprisePiece(ctx, uColor);
// LOCATION 2: right after the killer sKillers[0..3] population block
// (after the SORT_THESE_FIRST |= lines for sKillers[0..3]), insert:
//
// Pre-populate counter-move bonuses -- keyed by whatever move the
// opponent just played to reach this node, not by ply. A/B test:
// applied as a small *additive* nudge (like history counters),
// not a hard priority-tier flag -- the ~56% measured hit rate
// isn't confident enough to justify unconditionally outranking
// ordinary PSQT-scored quiet moves. Bonus scales with the ply
// depth the entry was recorded at (deeper = more confident),
// capped at the same 400/200 ceiling the flat version used.
//
sKillers[4].mv.uMove = sKillers[5].mv.uMove = 0;
if (mvLast.uMove != 0)
{
u = MOVE_TO_INDEX(mvLast);
sKillers[4].mv = ctx->mvCounter[u][0];
sKillers[4].uBonus = 400;
sKillers[5].mv = ctx->mvCounter[u][1];
sKillers[5].uBonus = 200;
}
// LOCATION 3: in the quiet-move scoring branch (the `else` branch that
// computes `s = g_iPSQT[...]` and applies killer bonuses via `s |= ...`),
// right after the GOOD_MOVE/cEnprise line and before `ASSERT(s >= 0);`,
// add (note: additive `+=`, not `|=` -- this was the measured-best
// config vs. a hard flag):
s += (IS_SAME_MOVE(sKillers[4].mv, mv) * sKillers[4].uBonus);
s += (IS_SAME_MOVE(sKillers[5].mv, mv) * sKillers[5].uBonus);
// This same three-part change applies in BOTH scoring functions in
// generate.c that have this sKillers array (there are two -- one for
// the normal move-scoring path, one for escaping-check; check whether
// the second one had the counter-move block too before assuming it's
// identical -- verify via `grep -n PRECOMP_KILLERS generate.c` and
// diff both call sites against this file's saved state if unsure).
|