This repository has been archived on 2021-02-18. You can view files and clone it, but cannot push or open issues or pull requests.
chess/src/main/java/dev/kske/chess/uci/UCIInfo.java

221 lines
5.5 KiB
Java

package dev.kske.chess.uci;
import java.util.*;
import dev.kske.chess.board.Move;
/**
* Project: <strong>Chess</strong><br>
* File: <strong>UCIInfo.java</strong><br>
* Created: <strong>28.07.2019</strong><br>
*
* @since Chess v0.3-alpha
* @author Kai S. K. Engelbart
*/
public class UCIInfo {
private int depth, seldepth, time, nodes, multipv, currmovenumber, hashfull,
nps, tbhits, sbhits, cpuload, cpunr;
private List<Move> pv = new ArrayList<>(), refutation = new ArrayList<>();
private Map<Integer, List<Move>> currline = new HashMap<>();
private Move currmove;
private Score score;
private String displayString;
/**
* Contains every parameter for the UCI info command. Helpful for parsing
* multi-value parameters.
*/
private static final List<String> params = Arrays.asList(
"depth",
"seldepth",
"time",
"nodes",
"multipv",
"currmove",
"currmovenumber",
"hashfull",
"nps",
"tbhits",
"sbhits",
"cpuload",
"string",
"score",
"pv",
"refutation",
"currline"
);
/**
* Creates an instance of {@link UCIInfo} by parsing the argument list of a
* UCI
* info command generated from an engine.
*
* @param line the UCI info argument list to parse
*/
public UCIInfo(String line) {
String[] tokens = line.split(" ");
for (int i = 0; i < tokens.length; i++)
switch (tokens[i]) {
// Single parameter info
case "depth":
depth = Integer.parseInt(tokens[++i]);
break;
case "seldepth":
seldepth = Integer.parseInt(tokens[++i]);
break;
case "time":
time = Integer.parseInt(tokens[++i]);
break;
case "nodes":
nodes = Integer.parseInt(tokens[++i]);
break;
case "multipv":
multipv = Integer.parseInt(tokens[++i]);
break;
case "currmove":
currmove = Move.fromLAN(tokens[++i]);
break;
case "currmovenumber":
currmovenumber = Integer.parseInt(tokens[++i]);
break;
case "hashfull":
hashfull = Integer.parseInt(tokens[++i]);
break;
case "nps":
nps = Integer.parseInt(tokens[++i]);
break;
case "tbhits":
tbhits = Integer.parseInt(tokens[++i]);
break;
case "sbhits":
sbhits = Integer.parseInt(tokens[++i]);
break;
case "cpuload":
cpuload = Integer.parseInt(tokens[++i]);
break;
case "string":
displayString = tokens[++i];
break;
case "score":
score
= new Score(line.substring(line.indexOf("score") + tokens[i].length() + 1));
i += score.getLength() + 1;
break;
case "pv":
while (++i < tokens.length && !params.contains(tokens[i]))
pv.add(Move.fromLAN(tokens[i]));
break;
case "refutation":
while (++i < tokens.length && !params.contains(tokens[i]))
refutation.add(Move.fromLAN(tokens[i]));
break;
case "currline":
// A CPU number of 1 can be omitted
final Integer cpu = tokens[i].matches("\\d+")
? Integer.parseInt(tokens[i++])
: 1;
final ArrayList<Move> moves = new ArrayList<>();
while (i < tokens.length && !params.contains(tokens[i]))
moves.add(Move.fromLAN(tokens[i++]));
currline.put(cpu, moves);
System.err.println(
"The parameter 'currline' for command 'info' is not yet implemented"
);
break;
default:
System.err.printf(
"Unknown parameter '%s' for command 'info' found!%n",
tokens[i]
);
}
}
public int getDepth() { return depth; }
public int getSeldepth() { return seldepth; }
public int getTime() { return time; }
public int getNodes() { return nodes; }
public int getMultipv() { return multipv; }
public int getCurrmovenumber() { return currmovenumber; }
public int getHashfull() { return hashfull; }
public int getNps() { return nps; }
public int getTbhits() { return tbhits; }
public int getSbhits() { return sbhits; }
public int getCpuload() { return cpuload; }
public int getCpunr() { return cpunr; }
public List<Move> getPv() { return pv; }
public List<Move> getRefutation() { return refutation; }
public Map<Integer, List<Move>> getCurrline() { return currline; }
public Move getCurrmove() { return currmove; }
public Score getScore() { return score; }
public String getDisplayString() { return displayString; }
public static class Score {
private int cp, mate;
private boolean lowerbound, upperbound;
private int length;
public Score(String line) {
String[] tokens = line.split(" ");
int i = 0;
for (; i < tokens.length; i++) {
if (params.contains(tokens[i]))
break;
switch (tokens[i]) {
case "cp":
cp = Integer.parseInt(tokens[++i]);
break;
case "mate":
mate = Integer.parseInt(tokens[++i]);
break;
case "lowerbound":
lowerbound = true;
break;
case "upperbound":
upperbound = true;
break;
default:
System.err.printf(
"Unknown parameter '%s' for command 'score' found!%n",
tokens[i]
);
}
}
length = i + 1;
}
public int getCp() { return cp; }
public int getMate() { return mate; }
public boolean isLowerbound() { return lowerbound; }
public boolean isUpperbound() { return upperbound; }
/**
* @return The number of tokens this 'score' command contains (including
* itself).
*/
public int getLength() { return length; }
}
}