package dev.kske.chess.uci; import java.util.*; import dev.kske.chess.board.Move; /** * Project: Chess
* File: UCIInfo.java
* Created: 28.07.2019
* * @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 pv = new ArrayList<>(), refutation = new ArrayList<>(); private Map> 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 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 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 getPv() { return pv; } public List getRefutation() { return refutation; } public Map> 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; } } }