My first tests revealed that the match results are much less sensitive to an initial material imbalance than in orthodox Chess: Knight odds resulted in a score of only 70%, while in orthodox Chess Pawn odds is already nearly that (65-68%). Pawn odds here gave only a 54.5% score, hardly more than the white advantage in Chess.
I figured this could be not so much a problem intrinsic to Metamachy, but an artifact caused by Fairy-Max. The latter has no real Pawn-structure evaluation, and in particular cannot recognize passers. While passers in Metamachy are much more dangerous than in Chess: the double push makes them outrun most pieces, and allows them to move over an attacked square in their path, so that you really have to block them in order to prevent advance. (Fortunately other Pawns can still e.p. capture them on the skipped square, so the concept of passer is identical in Chess and Metamachy.) This situation leads to many 'surprise wins', where one of the players (which could very well be the one that is behind) suddenly finds an unstoppable promotion appearing within the horizon. Which causes significant additional randomization of the results, pushing them towards 50%.
So the value of Pawn structure is on average much larger in Metamachy than in Chess, also because you start with 12 Pawns instead of 8 each. During the middle game the value of the Pawn structure randomly drifts when both players are totally ignorant of it. To cure that I made a special version of Fairy-Max for these tests, which does identify passers and can score them. Of course this will only be any good if the scoring is sensible as well.
For identifying the passers I used the 2-pass algorithm I first saw in TSCP: the first pass determines the backward-most Pawn in every file (for each player), and the second pass determines whether you have any opponent Pawns in front of you in your own or the adjacent files. Because this process is rather expensive (Fairy-Max has no piece list, so it has to scan the entire 144-square board to find its Pawns), I use a Pawn-hash table to store the result. Perhaps I was a bit stingy on sizes there: it has only 16K entires, and uses a 32-bit pawn key, so that the signature is only 18 bits.
Any way, it seems to work. I gave passers a 16cP bonus on their starting rank, which increases to 96cP when they are only one step from promotion. I also gave some extra bonus for when they are protected. A quick tests shows there is no terrible slowdown of nps, and the passer-aware version appears to beat the ignorant one with 58.5% (plus a rather large error margin).
This was just a first try; it is possible that much better play could still be achieved by different scoring of the passers. In other engines I noted that scoring passers can be a mixed blessing, especially w.r.t. encouraging their advance. Because advancing them too early often makes them undefensible, so that you will needlessly lose the most valuable Pawns you had. So perhaps I should switch to game-phase-dependent scoring. Holding back the Pawns early on to keep them safe when they are not protected by another Pawn, and only encourage pushing without protection late in the game.
Code: Select all
int ww[16], bb[16] = { 16 };
int Peval()
{
static int bonus[] = { 0, 0, 4, 6, 6, 10, 10, 16, 16, 24, 24, 0 },
prot[] = { 0, 0, 0, 2, 2, 3, 3, 4, 4, 5, 5, 0 };
int f, r, s=2000;
bb[BW+1] = 16;
for(f=0; f<BW; f++) {
ww[f+1] = 0; bb[f+1] = 16;
for(r=1; r<BH-1; r++) {
int p = b[f+16*r] & 15;
if(p == 1) ww[f+1] = r;
if(p == 2 && bb[f+1] == 16) bb[f+1] = r;
}
}
for(f=0; f<BW; f++) {
r = ww[f+1];
if(r && r < bb[f+1] && r <= bb[f] && r <= bb[f+2]) s += bonus[11-r] + (ww[f] == r+1 || ww[f+2] == r+1)*prot[11-r];
r = bb[f+1];
if(r != 16 && r > ww[f+1] && r >= ww[f] && r >= ww[f+2]) s -= bonus[r] + (bb[f] == r-1 || bb[f+2] == r-1)*prot[r];
}
return s;
}
int JJ; // pawn key
int pawnTab[1<<14];
int Probe(int k)
{
int i=JJ&0x3FFF, s=pawnTab[i]^JJ;
if(s & 0xFFFFC000) s = Peval(), pawnTab[i] = s ^ JJ;
return (s - 2000)*k >> 1;
}