// 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).