diff --git a/README.md b/README.md index f5af16652..49f64c5cc 100644 --- a/README.md +++ b/README.md @@ -13,7 +13,7 @@ Just follow the instructions in the provided readme in the [release](https://github.com/featurecat/lizzie/releases/tag/0.5). The first run may take a while because Leela Zero needs to set up the -OpenCL tunings and download the latest network if it is not present. Just hang tight, and wait for it to finish, then you +OpenCL tunings. Just hang tight, and wait for it to finish, then you will see Leela Zero's analysis displayed on the board. Feel free to supply your own tunings, as this will speed up the process. Do this by copying any `leelaz_opencl_tuning` file you have into the directory. @@ -24,14 +24,15 @@ any `leelaz_opencl_tuning` file you have into the directory. First, you will need to have a version of Leela Zero that continually outputs pondering information. You can get this from one -of the Lizzie releases or build it yourself; just compile from the **next** branch of Leela Zero (see http://github.com/gcp/leela-zero/tree/next for more details). +of the Lizzie releases or build it yourself; just compile from the **next** +branch of Leela Zero (see http://github.com/gcp/leela-zero/tree/next for more +details). - git clone -b next http://github.com/gcp/leela-zero.git + $ git clone --recursive --branch next http://github.com/gcp/leela-zero.git ### Building Lizzie -The simplest way to build Lizzie is to use -[Maven](https://maven.apache.org/). +The simplest way to build Lizzie is to use [Maven](https://maven.apache.org/). To build the code and package it: diff --git a/src/main/java/featurecat/lizzie/Config.java b/src/main/java/featurecat/lizzie/Config.java index 169880605..780044a54 100644 --- a/src/main/java/featurecat/lizzie/Config.java +++ b/src/main/java/featurecat/lizzie/Config.java @@ -249,7 +249,6 @@ private JSONObject createDefaultConfig() { leelaz.put("max-game-thinking-time-seconds", 2); leelaz.put("print-comms", false); leelaz.put("analyze-update-interval-centisec", 10); - leelaz.put("automatically-download-latest-network", false); config.put("leelaz", leelaz); diff --git a/src/main/java/featurecat/lizzie/Util.java b/src/main/java/featurecat/lizzie/Util.java deleted file mode 100644 index 94def40a9..000000000 --- a/src/main/java/featurecat/lizzie/Util.java +++ /dev/null @@ -1,110 +0,0 @@ -package featurecat.lizzie; - -import java.awt.FontMetrics; -import java.io.*; -import java.net.URL; -import java.nio.channels.Channels; -import java.nio.channels.ReadableByteChannel; -import java.security.DigestInputStream; -import java.security.MessageDigest; -import java.security.NoSuchAlgorithmException; -import java.util.stream.Collectors; -import java.util.zip.GZIPInputStream; - -public class Util { - /** - * @param val the value we want to clamp - * @param min the minimum value that will be returned - * @param max the maximum value that will be returned - * @return the closest number to val within the range [min, max] - */ - public static > T clamp(T val, T min, T max) { - if (val.compareTo(min) < 0) return min; - else if (val.compareTo(max) > 0) return max; - else return val; - } - - /** @return the sha 256 checksum of decompressed contents from a GZIPed file */ - public static String getSha256Sum(File file) { - try (InputStream inputStream = new GZIPInputStream(new FileInputStream(file))) { - MessageDigest messageDigest = MessageDigest.getInstance("SHA-256"); - DigestInputStream digestInputStream = new DigestInputStream(inputStream, messageDigest); - - // we have to read the file. additionally, using a buffer is efficient. - // 8192 was tested as the best value among 4096, 8192, 16384, and 32768. - byte[] buffer = new byte[8192]; - while (digestInputStream.read(buffer) != -1) ; - - MessageDigest digest = digestInputStream.getMessageDigest(); - digestInputStream.close(); - - byte[] sha256 = digest.digest(); - StringBuilder sb = new StringBuilder(); - for (byte b : sha256) { - sb.append(String.format("%02X", b)); - } - return sb.toString().toLowerCase(); - } catch (NoSuchAlgorithmException e) { - e.printStackTrace(); - } catch (EOFException e) { - // do nothing, just means we need to download a new one - } catch (IOException e) { - e.printStackTrace(); - } - return null; - } - - /** @return the url's contents, downloaded as a string */ - public static String downloadAsString(URL url) { - try (BufferedReader br = new BufferedReader(new InputStreamReader(url.openStream()))) { - return br.lines().collect(Collectors.joining("\n")); - } catch (IOException e) { - e.printStackTrace(); - } - - return null; - } - - /** Downloads the contents of the url, and saves them in a file. */ - public static void saveAsFile(URL url, File file) { - try { - ReadableByteChannel rbc = Channels.newChannel(url.openStream()); - FileOutputStream fos = new FileOutputStream(file); - fos.getChannel().transferFrom(rbc, 0, Long.MAX_VALUE); - } catch (IOException e) { - e.printStackTrace(); - } - } - - /** - * Truncate text that is too long for the given width - * - * @param line - * @param fm - * @param fitWidth - * @return fitted - */ - public static String truncateStringByWidth(String line, FontMetrics fm, int fitWidth) { - if (line == null || line.length() == 0) { - return ""; - } - int width = fm.stringWidth(line); - if (width > fitWidth) { - int guess = line.length() * fitWidth / width; - String before = line.substring(0, guess).trim(); - width = fm.stringWidth(before); - if (width > fitWidth) { - int diff = width - fitWidth; - int i = 0; - for (; (diff > 0 && i < 5); i++) { - diff = diff - fm.stringWidth(line.substring(guess - i - 1, guess - i)); - } - return line.substring(0, guess - i).trim(); - } else { - return before; - } - } else { - return line; - } - } -} diff --git a/src/main/java/featurecat/lizzie/analysis/Leelaz.java b/src/main/java/featurecat/lizzie/analysis/Leelaz.java index b294b7f2c..67812e324 100644 --- a/src/main/java/featurecat/lizzie/analysis/Leelaz.java +++ b/src/main/java/featurecat/lizzie/analysis/Leelaz.java @@ -1,13 +1,11 @@ package featurecat.lizzie.analysis; import featurecat.lizzie.Lizzie; -import featurecat.lizzie.Util; import featurecat.lizzie.rules.Stone; import java.io.BufferedInputStream; import java.io.BufferedOutputStream; import java.io.File; import java.io.IOException; -import java.net.URL; import java.util.*; import java.util.concurrent.CopyOnWriteArrayList; import java.util.concurrent.Executors; @@ -29,7 +27,6 @@ public class Leelaz { ResourceBundle.getBundle("l10n.DisplayStrings"); private static final long MINUTE = 60 * 1000; // number of milliseconds in a minute - private static final String baseURL = "http://zero.sjeng.org"; private long maxAnalyzeTimeMillis; // , maxThinkingTimeMillis; private int cmdNumber; @@ -94,10 +91,6 @@ public Leelaz() throws IOException, JSONException { printCommunication = config.getBoolean("print-comms"); maxAnalyzeTimeMillis = MINUTE * config.getInt("max-analyze-time-minutes"); - if (config.getBoolean("automatically-download-latest-network")) { - updateToLatestNetwork(); - } - // command string for starting the engine engineCommand = config.getString("engine-command"); // substitute in the weights file @@ -207,43 +200,6 @@ public void normalQuit() { } } - private void updateToLatestNetwork() { - try { - if (needToDownloadLatestNetwork()) { - int dialogResult = - JOptionPane.showConfirmDialog( - null, - resourceBundle.getString("LizzieFrame.display.download-latest-network-prompt")); - if (dialogResult == JOptionPane.YES_OPTION) { - Util.saveAsFile( - new URL(baseURL + "/networks/" + getBestNetworkHash() + ".gz"), - new File(Lizzie.config.leelazConfig.getString("network-file"))); - } - } - } catch (IOException e) { - e.printStackTrace(); - // now we're probably still ok. Maybe we're offline -- then it's not a big problem. - } - } - - private String getBestNetworkHash() throws IOException { - return Util.downloadAsString(new URL(baseURL + "/best-network-hash")).split("\n")[0]; - } - - private boolean needToDownloadLatestNetwork() throws IOException { - File networkFile = new File(Lizzie.config.leelazConfig.getString("network-file")); - if (!networkFile.exists()) { - return true; - } else { - String currentNetworkHash = Util.getSha256Sum(networkFile); - if (currentNetworkHash == null) return true; - - String bestNetworkHash = getBestNetworkHash(); - - return !currentNetworkHash.equals(bestNetworkHash); - } - } - /** Initializes the input and output streams */ private void initializeStreams() { inputStream = new BufferedInputStream(process.getInputStream()); diff --git a/src/main/java/featurecat/lizzie/gui/LizzieFrame.java b/src/main/java/featurecat/lizzie/gui/LizzieFrame.java index 3c02ac9d3..22b314aa2 100644 --- a/src/main/java/featurecat/lizzie/gui/LizzieFrame.java +++ b/src/main/java/featurecat/lizzie/gui/LizzieFrame.java @@ -1,8 +1,10 @@ package featurecat.lizzie.gui; +import static java.lang.Math.max; +import static java.lang.Math.min; + import com.jhlabs.image.GaussianFilter; import featurecat.lizzie.Lizzie; -import featurecat.lizzie.Util; import featurecat.lizzie.analysis.GameInfo; import featurecat.lizzie.analysis.Leelaz; import featurecat.lizzie.rules.Board; @@ -320,8 +322,8 @@ public void paint(Graphics g0) { int topInset = this.getInsets().top; // board - int maxSize = (int) (Math.min(getWidth(), getHeight() - topInset) * 0.98); - maxSize = Math.max(maxSize, Board.BOARD_SIZE + 5); // don't let maxWidth become too small + int maxSize = (int) (min(getWidth(), getHeight() - topInset) * 0.98); + maxSize = max(maxSize, Board.BOARD_SIZE + 5); // don't let maxWidth become too small int boardX = (getWidth() - maxSize) / 2; int boardY = topInset + (getHeight() - topInset - maxSize) / 2 + 3; @@ -387,7 +389,7 @@ public void paint(Graphics g0) { int subBoardY = gry + grh; int subBoardWidth = grw; int subBoardHeight = ponderingY - subBoardY; - int subBoardLength = Math.min(subBoardWidth, subBoardHeight); + int subBoardLength = min(subBoardWidth, subBoardHeight); if (Lizzie.config.showLargeSubBoard()) { boardX = getWidth() - maxSize - panelMargin; @@ -423,7 +425,7 @@ public void paint(Graphics g0) { subBoardY = topInset + panelH; subBoardWidth = spaceW; subBoardHeight = ponderingY - subBoardY; - subBoardLength = Math.min(subBoardWidth, subBoardHeight); + subBoardLength = min(subBoardWidth, subBoardHeight); } // initialize @@ -439,13 +441,13 @@ public void paint(Graphics g0) { if (Lizzie.leelaz != null && Lizzie.leelaz.isLoaded()) { if (Lizzie.config.showStatus) { - String pondKey = "LizzieFrame.display." + (Lizzie.leelaz.isPondering() ? "on" : "off"); - String pondText = - resourceBundle.getString("LizzieFrame.display.pondering") - + resourceBundle.getString(pondKey); - String switchText = resourceBundle.getString("LizzieFrame.prompt.switching"); + String statusKey = "LizzieFrame.display." + (Lizzie.leelaz.isPondering() ? "on" : "off"); + String statusText = resourceBundle.getString(statusKey); + String ponderingText = resourceBundle.getString("LizzieFrame.display.pondering"); + String switching = resourceBundle.getString("LizzieFrame.prompt.switching"); + String switchingText = Lizzie.leelaz.switching() ? switching : ""; String weightText = Lizzie.leelaz.currentWeight(); - String text = pondText + " " + weightText + (Lizzie.leelaz.switching() ? switchText : ""); + String text = ponderingText + " " + statusText + " " + weightText + " " + switchingText; drawPonderingState(g, text, ponderingX, ponderingY, ponderingSize); } @@ -530,8 +532,8 @@ private Graphics2D createBackground() { Graphics2D g = cachedBackground.createGraphics(); BufferedImage wallpaper = boardRenderer.getWallpaper(); - int drawWidth = Math.max(wallpaper.getWidth(), getWidth()); - int drawHeight = Math.max(wallpaper.getHeight(), getHeight()); + int drawWidth = max(wallpaper.getWidth(), getWidth()); + int drawHeight = max(wallpaper.getHeight(), getHeight()); // Support seamless texture boardRenderer.drawTextureImage(g, wallpaper, 0, 0, drawWidth, drawHeight); @@ -549,7 +551,7 @@ private void drawVariationTreeContainer(Graphics2D g, int vx, int vy, int vw, in } private void drawPonderingState(Graphics2D g, String text, int x, int y, double size) { - int fontSize = (int) (Math.max(getWidth(), getHeight()) * size); + int fontSize = (int) (max(getWidth(), getHeight()) * size); Font font = new Font(systemDefaultFontName, Font.PLAIN, fontSize); FontMetrics fm = g.getFontMetrics(font); int stringWidth = fm.stringWidth(text); @@ -560,7 +562,7 @@ private void drawPonderingState(Graphics2D g, String text, int x, int y, double ? boardRenderer.getLocation().x : 0; if ((mainBoardX > x) && stringWidth > (mainBoardX - x)) { - text = Util.truncateStringByWidth(text, fm, mainBoardX - x); + text = truncateStringByWidth(text, fm, mainBoardX - x); stringWidth = fm.stringWidth(text); } } @@ -585,6 +587,38 @@ private void drawPonderingState(Graphics2D g, String text, int x, int y, double text, x + (width - stringWidth) / 2, y + stringHeight + (height - stringHeight) / 2); } + /** + * Truncate text that is too long for the given width + * + * @param line + * @param fm + * @param fitWidth + * @return fitted + */ + private static String truncateStringByWidth(String line, FontMetrics fm, int fitWidth) { + if (line == null || line.length() == 0) { + return ""; + } + int width = fm.stringWidth(line); + if (width > fitWidth) { + int guess = line.length() * fitWidth / width; + String before = line.substring(0, guess).trim(); + width = fm.stringWidth(before); + if (width > fitWidth) { + int diff = width - fitWidth; + int i = 0; + for (; (diff > 0 && i < 5); i++) { + diff = diff - fm.stringWidth(line.substring(guess - i - 1, guess - i)); + } + return line.substring(0, guess - i).trim(); + } else { + return before; + } + } else { + return line; + } + } + private void drawWinrateGraphContainer(Graphics g, int statx, int staty, int statw, int stath) { if (g == null || statw <= 0 || stath <= 0) return; @@ -613,7 +647,7 @@ void drawControls() { Graphics2D g = cachedImage.createGraphics(); - int maxSize = Math.min(getWidth(), getHeight()); + int maxSize = min(getWidth(), getHeight()); Font font = new Font(systemDefaultFontName, Font.PLAIN, (int) (maxSize * 0.034)); g.setFont(font); @@ -621,11 +655,11 @@ void drawControls() { int maxCmdWidth = commandsToShow.stream().mapToInt(c -> metrics.stringWidth(c)).max().orElse(0); int lineHeight = (int) (font.getSize() * 1.15); - int boxWidth = Util.clamp((int) (maxCmdWidth * 1.4), 0, getWidth()); - int boxHeight = Util.clamp(commandsToShow.size() * lineHeight, 0, getHeight()); + int boxWidth = min((int) (maxCmdWidth * 1.4), getWidth()); + int boxHeight = min(commandsToShow.size() * lineHeight, getHeight()); - int commandsX = Util.clamp(getWidth() / 2 - boxWidth / 2, 0, getWidth()); - int commandsY = Util.clamp(getHeight() / 2 - boxHeight / 2, 0, getHeight()); + int commandsX = min(getWidth() / 2 - boxWidth / 2, getWidth()); + int commandsY = min(getHeight() / 2 - boxHeight / 2, getHeight()); BufferedImage result = new BufferedImage(boxWidth, boxHeight, BufferedImage.TYPE_INT_ARGB); filter10.filter( @@ -675,7 +709,7 @@ void drawControls() { private void drawCommandString(Graphics2D g) { if (userAlreadyKnowsAboutCommandString) return; - int maxSize = (int) (Math.min(getWidth(), getHeight()) * 0.98); + int maxSize = (int) (min(getWidth(), getHeight()) * 0.98); Font font = new Font(systemDefaultFontName, Font.PLAIN, (int) (maxSize * 0.03)); String commandString = resourceBundle.getString("LizzieFrame.prompt.showControlsHint"); @@ -758,7 +792,7 @@ private void drawMoveStatistics(Graphics2D g, int posX, int posY, int width, int strokeRadius = 2; g.setRenderingHint(RenderingHints.KEY_ANTIALIASING, RenderingHints.VALUE_ANTIALIAS_ON); g.setColor(Color.WHITE); - setPanelFont(g, (int) (Math.min(width, height) * 0.2)); + setPanelFont(g, (int) (min(width, height) * 0.2)); // Last move if (validLastWinrate && validWinrate) { @@ -1128,7 +1162,7 @@ private int drawComment(Graphics2D g, int x, int y, int w, int h, boolean full) ? Lizzie.board.getHistory().getData().comment : ""; int cHeight = full ? h : (int) (h * 0.5); - int fontSize = (int) (Math.min(getWidth(), getHeight()) * 0.0294); + int fontSize = (int) (min(getWidth(), getHeight()) * 0.0294); if (Lizzie.config.commentFontSize > 0) { fontSize = Lizzie.config.commentFontSize; } else if (fontSize < 16) { diff --git a/src/main/resources/l10n/DisplayStrings.properties b/src/main/resources/l10n/DisplayStrings.properties index be3e5dce7..4e2db2212 100644 --- a/src/main/resources/l10n/DisplayStrings.properties +++ b/src/main/resources/l10n/DisplayStrings.properties @@ -47,11 +47,10 @@ LizzieFrame.prompt.sgfExists=The SGF file already exists, do you want to replace LizzieFrame.prompt.showControlsHint=hold x = view controls LizzieFrame.prompt.switching=switching... LizzieFrame.display.lastMove=Last move -LizzieFrame.display.pondering=Pondering +LizzieFrame.display.pondering=Pondering LizzieFrame.display.on=on LizzieFrame.display.off=off LizzieFrame.display.loading=Leela Zero is loading... -LizzieFrame.display.download-latest-network-prompt=Download the latest network file? This may take some time. LizzieFrame.display.leelaz-missing=Did not find Leela Zero, update config.txt or download from Leela Zero homepage LizzieFrame.display.network-missing=Did not find network weights.\nUpdate config.txt (network-file) or download from Leela Zero homepage LizzieFrame.display.dynamic-komi=dyn. komi: diff --git a/src/main/resources/l10n/DisplayStrings_RO.properties b/src/main/resources/l10n/DisplayStrings_RO.properties index 14c54dce5..e0c930a6c 100644 --- a/src/main/resources/l10n/DisplayStrings_RO.properties +++ b/src/main/resources/l10n/DisplayStrings_RO.properties @@ -50,4 +50,3 @@ LizzieFrame.display.pondering=Analizeză LizzieFrame.display.on=pornit LizzieFrame.display.off=oprit LizzieFrame.display.loading=Leela Zero se încarcă... -LizzieFrame.display.download-latest-network-prompt=Descărcați cel mai nou fișier rețea? Poate să dureze. diff --git a/src/main/resources/l10n/DisplayStrings_zh_CN.properties b/src/main/resources/l10n/DisplayStrings_zh_CN.properties index c7effab3e..69778adba 100644 --- a/src/main/resources/l10n/DisplayStrings_zh_CN.properties +++ b/src/main/resources/l10n/DisplayStrings_zh_CN.properties @@ -39,7 +39,6 @@ LizzieFrame.display.pondering=\u5206\u6790 LizzieFrame.display.on=\u5F00\u542F LizzieFrame.display.off=\u6682\u505C LizzieFrame.display.loading=Leela Zero\u6B63\u5728\u8F7D\u5165\u4E2D... -LizzieFrame.display.download-latest-network-prompt=Download the latest network file? This may take some time. LizzieFrame.display.leelaz-missing=Did not find Leela Zero, update config.txt or download from Leela Zero homepage LizzieFrame.display.network-missing=Did not find network weights.\nUpdate config.txt (network-file) or download from Leela Zero homepage LizzieFrame.display.dynamic-komi=dyn. komi: