/*
DroidFish - An Android chess program.
Copyright (C) 2014,2016 Peter Ă–sterlund, peterosterlund2@gmail.com
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package org.petero.droidfish.tb;
/** Tablebase probe result. */
public final class ProbeResult implements Comparable<ProbeResult> {
public static enum Type {
DTM, // score is distance (full moves) to mate, or 0
DTZ, // score is distance (full moves) to zeroing move, or 0
WDL, // score is +-1 or 0
NONE, // No info available, score is 0
}
public Type type;
public int wdl; // +1 if if side to move wins, 0 for draw, -1 for loss
public int score; // Distance to win in plies. Always >= 0.
// Note! Zero if side to move is checkmated.
ProbeResult(Type type, int wdl, int score) {
this.type = type;
this.wdl = wdl;
this.score = score;
}
/**
* Return > 0 if other is "better" than this.
* A win is better than a draw, which is better than a loss.
* A DTM win is better than a DTZ win, which is better than a WDL win.
* A WDL loss is better than a DTZ loss, which is better than a DTM loss.
*/
@Override
public final int compareTo(ProbeResult other) {
final Type type1 = this.type;
final Type type2 = other.type;
final boolean none1 = type1 == Type.NONE;
final boolean none2 = type2 == Type.NONE;
if (none1 != none2)
return none2 ? -1 : 1;
if (none1)
return 0;
final int wdl1 = this.wdl;
final int wdl2 = other.wdl;
final boolean win1 = wdl1 > 0;
final boolean win2 = wdl2 > 0;
if (win1 != win2)
return win2 ? 1 : -1;
final boolean draw1 = wdl1 == 0;
final boolean draw2 = wdl2 == 0;
if (draw1 != draw2)
return draw2 ? 1 : -1;
final int score1 = this.score;
final int score2 = other.score;
if (win1) {
final boolean dtm1 = type1 == Type.DTM;
final boolean dtm2 = type2 == Type.DTM;
if (dtm1 != dtm2)
return dtm2 ? 1 : -1;
if (dtm1)
return -compareScore(wdl1, score1, wdl2, score2);
final boolean dtz1 = type1 == Type.DTZ;
final boolean dtz2 = type2 == Type.DTZ;
if (dtz1 != dtz2)
return dtz2 ? 1 : -1;
return -compareScore(wdl1, score1, wdl2, score2);
} else if (draw1) {
return 0;
} else {
final boolean wdlType1 = type1 == Type.WDL;
final boolean wdlType2 = type2 == Type.WDL;
if (wdlType1 != wdlType2)
return wdlType2 ? 1 : -1;
if (wdlType1)
return -compareScore(wdl1, score1, wdl2, score2);
final boolean dtzType1 = type1 == Type.DTZ;
final boolean dtzType2 = type2 == Type.DTZ;
if (dtzType1 != dtzType2)
return dtzType2 ? 1 : -1;
return -compareScore(wdl1, score1, wdl2, score2);
}
}
/** Return f((wdl1,score1)) - f((wdl2,score2)), where f(x) modifies
* the score so that larger values are better. */
final static int compareScore(int wdl1, int score1,
int wdl2, int score2) {
final int M = 1000;
if (wdl1 > 0)
score1 = M - score1;
else if (wdl1 < 0)
score1 = -M + score1;
if (wdl2 > 0)
score2 = M - score2;
else if (wdl2 < 0)
score2 = -M + score2;
return score1 - score2;
}
}