Dann Corbit wrote:I'm still not sure what to think of this one. Stockfish does change it's mind to the Serpent move (of course R.S. is in the Stockfish lineage). However, Rybka and Naum never waver from the key move, and get stronger and stronger scores. I think my next move will be to force the key move for both positions and analyze that position. Sometimes, after forcing a key move, the truth comes to light.
Aussi, Aussis, Aussie, oy, oy, oy! {veiled R.S. reference}
Thanks very much for your efforts Dann! I have neither Rybka 3 nor Naum 4 so it really helps me to be able to compare your analysis with that of Rainbow Serpent. On my Athlon it would take days to get some verification on this kind of timescale.
It's a pity that after every programchange, it is simply impossible to repeat this whole testing thing time and time again. That is of course the advantage of rigourous/standard testing, at least you don't have to be afraid that you break the code without noticing it in time and you can compare every test. It is best to automate that as probably is the basis for Rybka's tuning. But you need to have the hardware and patience to test every change.
I'm not completely sure but I suppose that Naum and Rybka are right that some moves here may actually be winning. The draw tendency of Stockfish is then not real, but the score for 1...Bd2 is only slowly going up and it requires accuracy not to lose the thread. Assuming Bd2 really should lead to a slowly rising eval like Naum and Rybka are showing, then Stockfish does seem to have some problems lifting the signal out of the background noise as it were, especially on deeper iterations. One thing that plays a role I think is that the plus 1 score of Rybka and Naum usually mean more of an advantage than +1 for Stockfish, so for Rybka there is less chance that one of the other moves crosses alpha.
That is partly an evaluation difference between the programs and may be the other way round in other cases, all the testpositions are mainly from Rybka games I believe so Rybka is not really an independant measure here. Naum 4 is not Rybka, but sometimes the evaluations do bear a striking resemblance
. If one of you would have access to Shredder 12, I would see that program as a better independant check of the positions than Naum 4. But I don't have Shredder 12 myself yet.
Shredder probably would also have some more fluctuating evals than Rybka unless it has changed a lot, the latest Stockfish 1.5.1 actually reminds me of the older Shredder especially now that Fail Highs and Fail Lows get a PV retrieved from the hashtable, and the output with the small aspiration windows that Joona introduced in Stockfish, that was a bit the signature of the older Shredders as well.
So I'm trying now to get a Rainbow Serpent version that can hold the 1... Bd2 but because the evaluation is a bit different from Rybka's it is not so easy. Maybe Rybka simply has a higher eval of the Bishop pair here so that would explain preference for 1...Bd2 or 1...Bb2, the remaining Bishop is at the moment at the same color squares as the White pawns so a bit weak. But Black's Knight is also in a cramped position. I analysed some leaf evals after 1...Bd2 and they turned out to be winning for Black, I only tried two leafpositions but that is a small indication because I could also backtrack the PV quite a few moves back to the root position.
(See a response to Jarkko for the analysis)
The code in search () is now beginning to be more different from Stockfish but it is little tested. In evaluate.cpp, I could not quite figure out Marco's use of templates in Stockfish the way I wanted it, I wanted more attack information in computing mobilty but at the moment only the side to move can have full details of the other sides attack bitboards, so now mobility is asymmetric. Not very pretty as the first change in eval but I figure that most of the times that you are doing a static eval that is not at the leaftips of Q-search, this is done in a stand pat situation, just when you cross the blue event horizon at depth = 0 having just entered quiescence search, so there you have the right to move, static eval then should be an upper bound from the perspective of side to move, if larger than beta you choose to stand pat. So being a bit conservative in mobility for the side to move should be correct there, static evals at the end of quiescence search are more governed by the material gain so postional accuracy, was my hypothesis, can be a bit neglected or a bit more optimistic there. I hope this is true because I could not find an easy way to compute full attack information for both sides without big changes in evaluate_mobility() and messing with the template structure
Too difficult for me at the moment.
The slightly changed mobility routine looks like this:
Code: Select all
template<PieceType Piece, Color Us, bool HasPopCnt>
int evaluate_mobility(const Position& pos, Bitboard b, EvalInfo& ei) {
const Color Them = (Us == WHITE ? BLACK : WHITE);
static const int AttackWeight[] = { 0, 0, KnightAttackWeight, BishopAttackWeight, RookAttackWeight, QueenAttackWeight };
static const Value* MgBonus[] = { 0, 0, MidgameKnightMobilityBonus, MidgameBishopMobilityBonus, MidgameRookMobilityBonus, MidgameQueenMobilityBonus };
static const Value* EgBonus[] = { 0, 0, EndgameKnightMobilityBonus, EndgameBishopMobilityBonus, EndgameRookMobilityBonus, EndgameQueenMobilityBonus };
static const int lastIndex[] = { 0, 0, 8, 15, 15, 31 };
// Update attack info
ei.attackedBy[Us][Piece] |= b;
// King attacks
if (b & ei.kingZone[Us])
{
ei.kingAttackersCount[Us]++;
ei.kingAttackersWeight[Us] += AttackWeight[Piece];
Bitboard bb = (b & ei.attackedBy[Them][KING]);
if (bb)
ei.kingAdjacentZoneAttacksCount[Us] += count_1s_max_15<HasPopCnt>(bb);
}
// Remove squares protected by enemy pawns or occupied by our pieces
b &= ~(ei.attackedBy[Them][PAWN] | pos.pieces_of_color(Us));
if (Us == pos.side_to_move())
{
if (Piece == QUEEN) b &= (~ei.attackedBy[Them][ROOK] & ~ei.attackedBy[Them][BISHOP] & ~ei.attackedBy[Them][KNIGHT]);
if (Piece == ROOK) b &= (~ei.attackedBy[Them][BISHOP] & ~ei.attackedBy[Them][KNIGHT]);
//[EdG: Experimental, asymmetric because we don't have the attack information in the first pass]
}
The last bit
Code: Select all
if (Us == pos.side_to_move())
{
if (Piece == QUEEN) b &= (~ei.attackedBy[Them][ROOK] & ~ei.attackedBy[Them][BISHOP] & ~ei.attackedBy[Them][KNIGHT]);
if (Piece == ROOK) b &= (~ei.attackedBy[Them][BISHOP] & ~ei.attackedBy[Them][KNIGHT]);
//[EdG: Experimental, asymmetric because we don't have the attack information in the first pass]
}
is new and is a crude first order approximation of safe mobility, maybe the asymmetry is too much of a showstopper though, and the bitboards are expensive. Maybe I should include the pieces of equal value so a Rook can't safely go to a square attacked by an enemy Rook and vice versa. Have not tried that yet.
Regards, Eelco