From f664e8c3dcb776587c0824a54368deab4648667d Mon Sep 17 00:00:00 2001 From: cyqsimon <28627918+cyqsimon@users.noreply.github.com> Date: Thu, 5 Jan 2023 19:07:21 +0800 Subject: [PATCH 01/16] Fix icon paths --- files/scripts/install.sh | 5 +++-- 1 file changed, 3 insertions(+), 2 deletions(-) diff --git a/files/scripts/install.sh b/files/scripts/install.sh index 62d70f44..236f8309 100755 --- a/files/scripts/install.sh +++ b/files/scripts/install.sh @@ -64,11 +64,12 @@ ICON_SVG_PATH="/usr/local/share/icons/hicolor/scalable/apps/nibbler.svg" echo "Installing Nibbler to ${INSTALL_DIR}" echo "Creating binary symlink at ${BIN_SYMLINK_PATH}" echo "Installing desktop entry to ${DESKTOP_ENTRY_PATH}" -echo "Installing icon to ${ICON_PATH}" +echo "Installing icons to ${ICON_PNG_PATH} and ${ICON_SVG_PATH}" echo "This will require sudo privilege." # remove old and make sure directories are created -for FILE in "${INSTALL_DIR}" "${BIN_SYMLINK_PATH}" "${DESKTOP_ENTRY_PATH}" "${ICON_PATH}"; do +for FILE in "${INSTALL_DIR}" "${BIN_SYMLINK_PATH}" "${DESKTOP_ENTRY_PATH}" \ + "${ICON_PNG_PATH}" "${ICON_SVG_PATH}"; do sudo rm -rf "$FILE" sudo mkdir -p $(dirname "$FILE") done From eb377961087a01cd448b774cd7a9e0489441dc7f Mon Sep 17 00:00:00 2001 From: rooklift <16438795+rooklift@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:41:22 +0000 Subject: [PATCH 02/16] In the abnormal situation where there are 2 or more castling rights on the same side, use the closest when parsing PGN --- files/src/renderer/40_position.js | 1 + 1 file changed, 1 insertion(+) diff --git a/files/src/renderer/40_position.js b/files/src/renderer/40_position.js index 8ce13f48..ef1835b9 100644 --- a/files/src/renderer/40_position.js +++ b/files/src/renderer/40_position.js @@ -727,6 +727,7 @@ const position_prototype = { if (long_flag) { possible_rights_chars = possible_rights_chars.slice(0, king_loc.x); + possible_rights_chars.reverse(); // So we propose the shortest move first, if more than 1 is allowed by the rights. } else { possible_rights_chars = possible_rights_chars.slice(king_loc.x + 1); } From 3bcbbf5bab747d46a83230fd91a80264f1293a2e Mon Sep 17 00:00:00 2001 From: rooklift <16438795+rooklift@users.noreply.github.com> Date: Wed, 25 Jan 2023 15:51:12 +0000 Subject: [PATCH 03/16] Update .gitignore --- files/.gitignore | 1 + 1 file changed, 1 insertion(+) diff --git a/files/.gitignore b/files/.gitignore index 43f17e38..de61c20e 100644 --- a/files/.gitignore +++ b/files/.gitignore @@ -1,3 +1,4 @@ .DS_Store scripts/dist scripts/electron_zipped +scripts/update_my_installation.py From 53b815375edca23a7e4bab5af063c4095e90b67d Mon Sep 17 00:00:00 2001 From: rooklift <16438795+rooklift@users.noreply.github.com> Date: Thu, 27 Apr 2023 15:38:38 +0100 Subject: [PATCH 04/16] config.logfile_timestamp --- files/src/main.js | 11 +++++++++ files/src/modules/config_io.js | 1 + files/src/renderer/20_utils.js | 45 ++++++++++++++++++++++++++++++++-- 3 files changed, 55 insertions(+), 2 deletions(-) diff --git a/files/src/main.js b/files/src/main.js index 120233f6..341618c9 100644 --- a/files/src/main.js +++ b/files/src/main.js @@ -4130,6 +4130,17 @@ function menu_build() { }); } }, + { + label: "Use unique logfile each time", + type: "checkbox", + checked: config.logfile_timestamp, + click: () => { + win.webContents.send("call", { + fn: "toggle", + args: ["logfile_timestamp"], + }); + } + }, { type: "separator" }, diff --git a/files/src/modules/config_io.js b/files/src/modules/config_io.js index 0b7a9b08..51da48e0 100644 --- a/files/src/modules/config_io.js +++ b/files/src/modules/config_io.js @@ -141,6 +141,7 @@ exports.defaults = { "logfile": null, "clear_log": true, + "logfile_timestamp": false, "log_info_lines": false, "log_useless_info": false, "log_illegal_moves": true, diff --git a/files/src/renderer/20_utils.js b/files/src/renderer/20_utils.js index 4c11f173..9eec1da0 100644 --- a/files/src/renderer/20_utils.js +++ b/files/src/renderer/20_utils.js @@ -313,9 +313,13 @@ function Log(s) { Log.stream = undefined; Log.logfilename = undefined; } - console.log(`Logging to ${config.logfile}`); + + let actual_filepath = config.logfile_timestamp ? UniqueFilepath(config.logfile) : config.logfile; + // Note that this isn't saved even temporarily - as far as the rest of the logic is concerned, we are logging to config.logfile + + console.log(`Logging to ${actual_filepath}`); let flags = (config.clear_log) ? "w" : "a"; - let stream = fs.createWriteStream(config.logfile, {flags: flags}); // Want var "stream" available via closure for the below... + let stream = fs.createWriteStream(actual_filepath, {flags: flags}); // Want var "stream" available via closure for the below... stream.on("error", (err) => { console.log(err); @@ -340,6 +344,43 @@ function LogBoth(s) { Log(s); } +function UniqueFilepath(filepath) { + + const alpha = "abcdefghijklmnopqrstuvwxyz"; + + let extname = path.extname(filepath); + let basename = path.basename(filepath, extname); + let dirname = path.dirname(filepath); + + let dt = new Date(); + + let y = dt.getFullYear().toString(); + let m = (dt.getMonth() + 1).toString(); + let d = dt.getDate().toString(); + let h = dt.getHours().toString(); + let n = dt.getMinutes().toString(); + let s = dt.getSeconds().toString(); + + if (m.length === 1) m = "0" + m; + if (d.length === 1) d = "0" + d; + if (h.length === 1) h = "0" + h; + if (n.length === 1) n = "0" + n; + if (s.length === 1) s = "0" + s; + + let newbase = `${basename}-${y}-${m}-${d}-${h}${n}${s}`; + + for (let n = 0; n < 26; n++) { + let test = path.join(dirname, newbase) + alpha[n] + extname; + if (!fs.existsSync(test)) { + return test; + } + } + + // If you start 27 instances of Nibbler within a second, that's your problem. + + return filepath; +} + function New2DArray(width, height, defval) { let ret = []; From 4d65c519cf94ac7cec68b9517e7816a957803b2c Mon Sep 17 00:00:00 2001 From: dav <63931154+dav1312@users.noreply.github.com> Date: Thu, 16 Feb 2023 22:02:06 +0100 Subject: [PATCH 05/16] Custom --- README.md | 2 +- files/src/main.js | 334 +++++++++++++++---------- files/src/modules/config_io.js | 60 ++--- files/src/nibbler.css | 103 ++++++++ files/src/renderer/50_table.js | 4 +- files/src/renderer/51_node.js | 2 +- files/src/renderer/55_winrate_graph.js | 18 ++ files/src/renderer/72_tree_draw.js | 4 - files/src/renderer/82_infobox.js | 8 +- files/src/renderer/95_hub.js | 2 +- 10 files changed, 357 insertions(+), 180 deletions(-) diff --git a/README.md b/README.md index 5653af76..dc85fe34 100644 --- a/README.md +++ b/README.md @@ -8,7 +8,7 @@ These days, Nibbler more-or-less works with traditional engines like [Stockfish] For prebuilt binary releases, see the [Releases](https://github.com/rooklift/nibbler/releases) section. For help, the [Discord](https://discordapp.com/invite/pKujYxD) may be your best bet, or open an issue here. -![Screenshot](https://user-images.githubusercontent.com/16438795/190862093-f6a9b37e-cad3-418a-8b70-521000bef778.png) +![Screenshot](https://user-images.githubusercontent.com/63931154/200676493-016aa50d-f45e-457e-9461-9bed2cc453a4.png) ## Features diff --git a/files/src/main.js b/files/src/main.js index 341618c9..eae4aabe 100644 --- a/files/src/main.js +++ b/files/src/main.js @@ -2579,6 +2579,30 @@ function menu_build() { { type: "separator" }, + { + label: "10,000,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit", + args: [10 * billion] + }); + // Will receive an ack IPC which sets menu checks. + } + }, + { + label: "5,000,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit", + args: [5 * billion] + }); + // Will receive an ack IPC which sets menu checks. + } + }, { label: "1,000,000,000", type: "checkbox", @@ -2591,6 +2615,30 @@ function menu_build() { // Will receive an ack IPC which sets menu checks. } }, + { + label: "500,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit", + args: [500 * million] + }); + // Will receive an ack IPC which sets menu checks. + } + }, + { + label: "250,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit", + args: [250 * million] + }); + // Will receive an ack IPC which sets menu checks. + } + }, { label: "100,000,000", type: "checkbox", @@ -2604,97 +2652,97 @@ function menu_build() { } }, { - label: "10,000,000", + label: "50,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [10 * million] + args: [50 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "1,000,000", + label: "25,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [1 * million] + args: [25 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "100,000", + label: "10,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [100000] + args: [10 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "10,000", + label: "5,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [10000] + args: [5 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "1,000", + label: "1,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [1000] + args: [1 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "100", + label: "100,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [100] + args: [100000] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "10", + label: "10,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [10] + args: [10000] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "2", + label: "1,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit", - args: [2] + args: [1000] }); // Will receive an ack IPC which sets menu checks. } @@ -2739,6 +2787,30 @@ function menu_build() { { label: "Limit - auto-eval / play", submenu: [ + { + label: "10,000,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit_special", + args: [10 * billion] + }); + // Will receive an ack IPC which sets menu checks. + } + }, + { + label: "5,000,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit_special", + args: [5 * billion] + }); + // Will receive an ack IPC which sets menu checks. + } + }, { label: "1,000,000,000", type: "checkbox", @@ -2751,6 +2823,30 @@ function menu_build() { // Will receive an ack IPC which sets menu checks. } }, + { + label: "500,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit_special", + args: [500 * million] + }); + // Will receive an ack IPC which sets menu checks. + } + }, + { + label: "250,000,000", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_node_limit_special", + args: [250 * million] + }); + // Will receive an ack IPC which sets menu checks. + } + }, { label: "100,000,000", type: "checkbox", @@ -2764,97 +2860,97 @@ function menu_build() { } }, { - label: "10,000,000", + label: "50,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [10 * million] + args: [50 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "1,000,000", + label: "25,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [1 * million] + args: [25 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "100,000", + label: "10,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [100000] + args: [10 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "10,000", + label: "5,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [10000] + args: [5 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "1,000", + label: "1,000,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [1000] + args: [1 * million] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "100", + label: "100,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [100] + args: [100000] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "10", + label: "10,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [10] + args: [10000] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "2", + label: "1,000", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_node_limit_special", - args: [2] + args: [1000] }); // Will receive an ack IPC which sets menu checks. } @@ -2911,369 +3007,333 @@ function menu_build() { label: "Threads", submenu: [ { - label: "128", + label: "12", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 128], + args: ["Threads", 12], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "96", + label: "10", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 96], + args: ["Threads", 10], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "64", + label: "8", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 64], + args: ["Threads", 8], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "48", + label: "7", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 48], + args: ["Threads", 7], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "32", + label: "6", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 32], + args: ["Threads", 6], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "24", + label: "5", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 24], + args: ["Threads", 5], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "16", + label: "4", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 16], + args: ["Threads", 4], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "14", + label: "3", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 14], + args: ["Threads", 3], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "12", + label: "2", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 12], + args: ["Threads", 2], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "10", + label: "1", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 10], + args: ["Threads", 1], }); // Will receive an ack IPC which sets menu checks. } }, { - label: "8", - type: "checkbox", - checked: false, - click: () => { - win.webContents.send("call", { - fn: "set_uci_option_permanent", - args: ["Threads", 8], - }); - // Will receive an ack IPC which sets menu checks. - } + type: "separator" }, { - label: "7", - type: "checkbox", - checked: false, + label: "Warning about threads", click: () => { - win.webContents.send("call", { - fn: "set_uci_option_permanent", - args: ["Threads", 7], - }); - // Will receive an ack IPC which sets menu checks. + alert(messages.thread_warning); } }, + ] + }, + { + label: "Hash", + submenu: [ { - label: "6", + label: "16 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 6], + args: ["Hash", 16 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "5", + label: "12 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 5], + args: ["Hash", 12 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "4", + label: "10 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 4], + args: ["Hash", 10 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "3", + label: "8 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 3], + args: ["Hash", 8 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "2", + label: "6 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 2], + args: ["Hash", 6 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "1", + label: "4 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Threads", 1], + args: ["Hash", 4 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - type: "separator" - }, - { - label: "Warning about threads", - click: () => { - alert(win, messages.thread_warning); - } - }, - ] - }, - { - label: "Hash", - submenu: [ - { - label: "120 GB", + label: "2 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 120 * 1024] + args: ["Hash", 2 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "56 GB", + label: "1 GB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 56 * 1024] + args: ["Hash", 1 * 1024] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "24 GB", + label: "512 MB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 24 * 1024] + args: ["Hash", 1 * 512] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "12 GB", + label: "256 MB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 12 * 1024] + args: ["Hash", 1 * 256] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "8 GB", + label: "128 MB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 8 * 1024] + args: ["Hash", 1 * 128] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "6 GB", + label: "64 MB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 6 * 1024] + args: ["Hash", 1 * 64] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "4 GB", + label: "16 MB", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 4 * 1024] + args: ["Hash", 1 * 16] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "2 GB", - type: "checkbox", - checked: false, + type: "separator" + }, + { + label: "I want other hash options!", click: () => { - win.webContents.send("call", { - fn: "set_uci_option_permanent", - args: ["Hash", 2 * 1024] - }); - // Will receive an ack IPC which sets menu checks. + alert(messages.about_hashes); } - }, + } + ] + }, + { + label: "MultiPV", + submenu: [ { - label: "1 GB", + label: "500", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 1 * 1024] + args: ["MultiPV", 500] }); // Will receive an ack IPC which sets menu checks. } }, { - label: "0 GB", + label: "10", type: "checkbox", checked: false, click: () => { win.webContents.send("call", { fn: "set_uci_option_permanent", - args: ["Hash", 1] // 1 MB is Stockfish actual minimum. + args: ["MultiPV", 10] }); // Will receive an ack IPC which sets menu checks. } }, - { - type: "separator" - }, - { - label: "I want other hash options!", - click: () => { - alert(win, messages.about_hashes); - } - } - ] - }, - { - label: "MultiPV", - submenu: [ { label: "5", type: "checkbox", diff --git a/files/src/modules/config_io.js b/files/src/modules/config_io.js index 51da48e0..9933bfe7 100644 --- a/files/src/modules/config_io.js +++ b/files/src/modules/config_io.js @@ -28,28 +28,28 @@ exports.defaults = { "width": 1280, "height": 835, - "board_size": 640, - "info_font_size": 16, - "pgn_font_size": 16, - "fen_font_size": 16, + "board_size": 416, + "info_font_size": 18, + "pgn_font_size": 18, + "fen_font_size": 18, "arrow_width": 8, "arrowhead_radius": 12, "board_font": "18px Arial", - "graph_height": 96, + "graph_height": 192, "graph_line_width": 2, "graph_minimum_length": 41, // Desired depth + 1 - "light_square": "#dadada", - "dark_square": "#b4b4b4", - "active_square": "#66aaaa", - "move_squares_with_alpha": "#ffff0026", + "light_square": "#f0d9b5", + "dark_square": "#b58863", + "active_square": "#ffff0080", + "move_squares_with_alpha": "#ffff0080", - "best_colour": "#66aaaa", - "good_colour": "#66aa66", - "bad_colour": "#cccc66", - "terrible_colour": "#cc6666", - "actual_move_colour": "#cc9966", + "best_colour": "#4da3ff", + "good_colour": "#6fc383", + "bad_colour": "#ffac38", + "terrible_colour": "#e0525d", + "actual_move_colour": "#fff", "searchmoves_buttons": true, "focus_on_text": "focused:", @@ -58,50 +58,50 @@ exports.defaults = { "accept_bounds": false, "max_info_lines": null, // Hidden option - "bad_move_threshold": 0.02, - "terrible_move_threshold": 0.04, - "ab_filter_threshold": 0.1, + "bad_move_threshold": 0.05, + "terrible_move_threshold": 0.1, + "ab_filter_threshold": 0.25, "arrow_filter_type": "N", "arrow_filter_value": 0.01, "arrows_enabled": true, "click_spotlight": true, - "next_move_arrow": false, - "next_move_outline": false, + "next_move_arrow": true, + "next_move_outline": true, "next_move_unique_colour": false, "arrowhead_type": 0, "ev_pov": null, - "cp_pov": null, - "wdl_pov": null, + "cp_pov": "w", + "wdl_pov": "w", - "show_cp": false, + "show_cp": true, "show_n": true, "show_n_abs": true, "show_depth": true, - "show_p": true, + "show_p": false, "show_v": false, "show_q": false, "show_u": false, "show_s": false, "show_m": false, "show_wdl": true, - "infobox_stats_newline": false, - "infobox_pv_move_numbers": false, - "hover_draw": false, - "hover_method": 2, + "infobox_stats_newline": true, + "infobox_pv_move_numbers": true, + "hover_draw": true, + "hover_method": 1, "looker_api": null, "look_past_25": false, "pv_click_event": 1, // 0: nothing, 1: goto, 2: tree - "pgn_ev": true, + "pgn_ev": false, "pgn_cp": false, - "pgn_n": true, + "pgn_n": false, "pgn_n_abs": false, - "pgn_of_n": true, + "pgn_of_n": false, "pgn_depth": false, "pgn_p": false, "pgn_v": false, diff --git a/files/src/nibbler.css b/files/src/nibbler.css index e6d20863..00ae681d 100644 --- a/files/src/nibbler.css +++ b/files/src/nibbler.css @@ -253,3 +253,106 @@ span.movelist_highlight_yellow { span.nobr { white-space: nowrap; /* Used for O-O and O-O-O moves */ } + +/* ----------------------------------- */ + +#rightgridder { + position: relative; +} + +#graph { + border-top: 1px solid #666666; + border-bottom: 1px solid #666666; +} + +.pink { + color: #999999; +} + +.infoline > .gray:last-child { + color: #ff8a8ab3; +} + +#infobox { + margin-top: .5em; + margin-left: calc(1em - 5px); +} + +#infobox > .infoline { + margin-bottom: 0; + padding-top: .5em; + padding-bottom: .5em; + border-bottom: .5px solid #99999969; + overflow: hidden; + text-overflow: ellipsis; + white-space: nowrap; +} + +#infobox > .infoline:hover { + white-space: normal; + word-break: break-all; +} + +#infobox > .infoline > .gray { + margin-left: 5px; +} + +#infobox > .infoline > [id^="infobox_"] { + word-break: break-all; + white-space: nowrap; + padding: 0 5px 0 5px; + border-radius: 3px; + transition: .1s; +} + +#infobox > .infoline > [id^="infobox_"]:first-child { + margin-left: -6px; +} + +#infobox > .infoline > [id^="infobox_"]:hover { + background-color: #eeeeee1f; + transition: .1s; +} + +#fenbox { + margin: calc(.5em - 4px) calc(1em - 4px); + padding: 8px; +} + +#fenbox:focus { + outline-offset: 0; +} + +#movelist { + margin: 0; + padding: 0 1em 1em calc(1em - 2px); +} + +#movelist > span { + display: inline-block; + padding: 0 5px 0 5px; + border-radius: 3px; + transition: .1s; +} + +#movelist > span:hover { + background-color: #eeeeee33; + transition: .1s; +} + +#movelist > .movelist_highlight_blue { + background-color: #eeeeee40; + color: #eeeeee; +} + +#movelist > .movelist_highlight_yellow { + background-color: #ffff0033; +} + +#movelist > .movelist_highlight_yellow:hover { + background-color: #ffff0040; +} + +#statusbox > .gray { + white-space: normal; +} diff --git a/files/src/renderer/50_table.js b/files/src/renderer/50_table.js index f6661d0e..bcd2db3d 100644 --- a/files/src/renderer/50_table.js +++ b/files/src/renderer/50_table.js @@ -201,9 +201,9 @@ const info_prototype = { mate = 0 - mate; } if (mate < 0) { - return `(-M${0 - mate})`; + return `-M${0 - mate}`; } else { - return `(+M${mate})`; + return `+M${mate}`; } }, diff --git a/files/src/renderer/51_node.js b/files/src/renderer/51_node.js index b6e4099c..89bb648f 100644 --- a/files/src/renderer/51_node.js +++ b/files/src/renderer/51_node.js @@ -285,7 +285,7 @@ const node_prototype = { let s = ""; if (need_number_string) { - s += this.parent.board.next_number_string() + " "; + s += this.parent.board.next_number_string(); } s += this.nice_move(); diff --git a/files/src/renderer/55_winrate_graph.js b/files/src/renderer/55_winrate_graph.js index d174d222..133a1989 100644 --- a/files/src/renderer/55_winrate_graph.js +++ b/files/src/renderer/55_winrate_graph.js @@ -34,6 +34,8 @@ function NewGrapher() { let eval_list = node.future_eval_history(); this.draw_50_percent_line(width, height); + this.draw_percent_lines(width, height); + this.draw_white_side(width, height); this.draw_position_line(eval_list.length, node); // We make lists of contiguous edges that can be drawn at once... @@ -152,6 +154,22 @@ function NewGrapher() { graphctx.stroke(); }; + grapher.draw_percent_lines = function(width, height) { + + graphctx.fillStyle = "#ffffff33"; + for (let i = 0; i < 5; i++) { + graphctx.fillRect(0, height / 10 * i * 2, width, height / 10); + } + graphctx.stroke(); + }; + + grapher.draw_white_side = function(width, height) { + + graphctx.fillStyle = "#ffffff1a"; + graphctx.fillRect(0, 0, width, height / 2); + graphctx.stroke(); + }; + grapher.draw_position_line = function(eval_list_length, node) { if (eval_list_length < 2) { diff --git a/files/src/renderer/72_tree_draw.js b/files/src/renderer/72_tree_draw.js index 79df7e16..9ea7c4ec 100644 --- a/files/src/renderer/72_tree_draw.js +++ b/files/src/renderer/72_tree_draw.js @@ -108,10 +108,6 @@ let tree_draw_props = { let p = pseudoelements[n]; let nextp = pseudoelements[n + 1]; // Possibly undefined - if (!nextp || (p.text !== "(" && nextp.text !== ")")) { - p.text += " "; - } - all_spans.push(`${p.opener}${p.text}${p.closer}`); } diff --git a/files/src/renderer/82_infobox.js b/files/src/renderer/82_infobox.js index 27712514..c0cd0a49 100644 --- a/files/src/renderer/82_infobox.js +++ b/files/src/renderer/82_infobox.js @@ -190,13 +190,13 @@ let infobox_props = { let numstring = ""; if (config.infobox_pv_move_numbers) { if (colour === "w") { - numstring = `${movenum}. `; + numstring = `${movenum}.`; } else if (colour === "b" && i === 0) { - numstring = `${movenum}... `; + numstring = `${movenum}...`; } } - substrings.push(`${numstring}${nice_pv[i]} `); + substrings.push(`${numstring}${nice_pv[i]}`); this.info_clickers.push({ move: info.pv[i], is_start: i === 0, @@ -253,7 +253,7 @@ let infobox_props = { if (config.infobox_stats_newline) { substrings.push("
"); } - substrings.push(`(${extra_stat_strings.join(', ')})`); + substrings.push(`${extra_stat_strings.join(' | ')}`); } // Close the whole div... diff --git a/files/src/renderer/95_hub.js b/files/src/renderer/95_hub.js index d2d1782c..47e5df73 100644 --- a/files/src/renderer/95_hub.js +++ b/files/src/renderer/95_hub.js @@ -1035,7 +1035,7 @@ let hub_props = { if (!this.engine.leelaish && !engineconfig[this.engine.filepath].options["MultiPV"]) { // This likely indicates the engine is new to the config. - engineconfig[this.engine.filepath].options["MultiPV"] = 3; // Will get ack'd when engine_send_all_options() happens + engineconfig[this.engine.filepath].options["MultiPV"] = 1; // Will get ack'd when engine_send_all_options() happens engineconfig[this.engine.filepath].search_nodes_special = 10000000; this.send_ack_node_limit(true); } From 36679391b86613f2676cba4f449a07ca03d33b95 Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Thu, 16 Feb 2023 22:02:06 +0100 Subject: [PATCH 06/16] Rearrange elements --- files/src/nibbler.css | 22 ++++++++++------------ files/src/nibbler.html | 10 +++++----- 2 files changed, 15 insertions(+), 17 deletions(-) diff --git a/files/src/nibbler.css b/files/src/nibbler.css index 00ae681d..ad38d961 100644 --- a/files/src/nibbler.css +++ b/files/src/nibbler.css @@ -28,11 +28,12 @@ body { display: grid; height: 100vh; grid-template-columns: min-content 1fr; - grid-template-rows: min-content min-content 1fr; + grid-template-rows: min-content min-content min-content 1fr; grid-template-areas: "a b" + "e e" "f f" - "g g"; + "g g" } #rightgridder { @@ -41,11 +42,9 @@ body { margin: 1em 0 0 0; height: 0; /* js needs to keep this equal to the boardsize */ grid-template-columns: none; - grid-template-rows: min-content 1fr min-content; grid-template-areas: "c" - "d" - "e"; + "d"; } #boardsquares { @@ -75,18 +74,17 @@ body { } #statusbox { - grid-area: c; + grid-area: f; margin: 0 0 0 1em; border: none; display: block; font-family: monospace, monospace; pointer-events: auto; - overflow: hidden; white-space: pre; } #infobox { - grid-area: d; + grid-area: g; margin: 1em 1em 0 1em; display: block; color: #cccccc; /* only used for Lc0 stderr output at startup */ @@ -99,7 +97,7 @@ body { } #graph { - grid-area: e; + grid-area: d; align-self: end; display: block; margin: 10px 0 0 1em; @@ -112,7 +110,7 @@ input[type=text]:focus { } #fenbox { - grid-area: f; + grid-area: e; margin: 1em 1em 0 1em; background-color: #080808; border: none; @@ -126,7 +124,7 @@ input[type=text]:focus { } #movelist { - grid-area: g; + grid-area: c; margin: 1em 1em 1em 1em; display: block; color: #999999; @@ -325,7 +323,7 @@ span.nobr { #movelist { margin: 0; - padding: 0 1em 1em calc(1em - 2px); + padding: 0 1em 0 calc(1em - 2px); } #movelist > span { diff --git a/files/src/nibbler.html b/files/src/nibbler.html index 97c8c546..c3706c84 100644 --- a/files/src/nibbler.html +++ b/files/src/nibbler.html @@ -20,15 +20,15 @@
-
Starting up...
-
+
- +
- + -
+
Starting up...
+
From 6a3aa17199b1ccb746883b62b86ba118edab5360 Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Thu, 16 Feb 2023 22:02:06 +0100 Subject: [PATCH 07/16] Automatically request analysis of positions to Chessdb if: - It isn't in Chessdb yet - It wasn't requested before - The Chessdb API is selected - There are enough pieces on the board --- files/src/renderer/75_looker.js | 25 ++++++++++++++++++++++++- 1 file changed, 24 insertions(+), 1 deletion(-) diff --git a/files/src/renderer/75_looker.js b/files/src/renderer/75_looker.js index 5ad26a0e..ea0dcf6d 100644 --- a/files/src/renderer/75_looker.js +++ b/files/src/renderer/75_looker.js @@ -21,6 +21,19 @@ function NewLooker() { return looker; } +function chessDbEnoughPieces(fen) { + const MIN_TOTAL = 10, MIN_NON_PAWN = 4; + return (countPieces(fen) >= MIN_TOTAL && countPieces(fen, true) >= MIN_NON_PAWN) +} + +function countPieces(fen, attackers = false) { + let board = fen.toLowerCase().split(" ")[0].split(""); + let pieces = "qrbn"; + if (!attackers) pieces += "kp"; + const count = board.length - board.filter((fenPiece) => !pieces.includes(fenPiece)).length; + return count; +} + let looker_props = { clear_queue: function() { @@ -143,10 +156,11 @@ let looker_props = { let friendly_fen = query.board.fen(true); let fen_for_web = ReplaceAll(friendly_fen, " ", "%20"); - let url; + let url, url_queue = ""; if (query.db_name === "chessdbcn") { url = `http://www.chessdb.cn/cdb.php?action=queryall&json=1&board=${fen_for_web}`; + url_queue = `http://www.chessdb.cn/cdb.php?action=queue&board=${fen_for_web}`; } else if (query.db_name === "lichess_masters") { url = `http://explorer.lichess.ovh/masters?topGames=0&fen=${fen_for_web}`; } else if (query.db_name === "lichess_plebs") { @@ -167,6 +181,15 @@ let looker_props = { return response.json(); }).then(raw_object => { this.handle_response_object(query, raw_object); + console.log(raw_object); + if ( + chessDbEnoughPieces(friendly_fen) && + url_queue != "" && + (raw_object.status == "unknown" || raw_object.moves?.length < 5) + ) { + fetch(url_queue); + hub.set_special_message("Requested to ChessDB", "green", 250); + } }); }, From c7ea22ee66c4f81179e6b88000d4e70a6a32b4da Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Thu, 16 Feb 2023 22:02:06 +0100 Subject: [PATCH 08/16] Add backwards analysis and self-play with ucinewgame between positions --- files/src/main.js | 20 ++++++++++++++++++++ files/src/renderer/83_statusbox.js | 4 ++++ files/src/renderer/95_hub.js | 17 +++++++++++++++-- 3 files changed, 39 insertions(+), 2 deletions(-) diff --git a/files/src/main.js b/files/src/main.js index eae4aabe..2ab18859 100644 --- a/files/src/main.js +++ b/files/src/main.js @@ -810,6 +810,16 @@ function menu_build() { }); } }, + { + label: "Auto-evaluate line, backwards (ucinewgame)", + accelerator: "Ctrl+Shift+F12", + click: () => { + win.webContents.send("call", { + fn: "set_behaviour", + args: ["back_analysis_ucinewgame"] + }); + } + }, { type: "separator" }, @@ -3443,6 +3453,16 @@ function menu_build() { }); } }, + { + label: "Start self-play (ucinewgame)", + accelerator: "Ctrl+F11", + click: () => { + win.webContents.send("call", { + fn: "set_behaviour", + args: ["self_play_ucinewgame"], + }); + } + }, { label: "Halt", click: () => { diff --git a/files/src/renderer/83_statusbox.js b/files/src/renderer/83_statusbox.js index 50eff1b1..65392f95 100644 --- a/files/src/renderer/83_statusbox.js +++ b/files/src/renderer/83_statusbox.js @@ -87,10 +87,14 @@ function NewStatusHandler() { status_string += `YOUR MOVE `; } else if (config.behaviour === "self_play") { status_string += `Self-play! `; + } else if (config.behaviour === "self_play_ucinewgame") { + status_string += `Self-play! (ucinewgame between positions) `; } else if (config.behaviour === "auto_analysis") { status_string += `Auto-eval! `; } else if (config.behaviour === "back_analysis") { status_string += `Back-eval! `; + } else if (config.behaviour === "back_analysis_ucinewgame") { + status_string += `Back-eval! (ucinewgame between positions) `; } else if (config.behaviour === "analysis_free") { status_string += `ANALYSIS (halt?) `; } diff --git a/files/src/renderer/95_hub.js b/files/src/renderer/95_hub.js index 47e5df73..cb5df7d6 100644 --- a/files/src/renderer/95_hub.js +++ b/files/src/renderer/95_hub.js @@ -74,10 +74,14 @@ let hub_props = { case "auto_analysis": case "back_analysis": + case "back_analysis_ucinewgame": if (this.tree.node.terminal_reason()) { this.continue_auto_analysis(); // This can get a bit recursive, do we care? } else if (this.engine.search_desired.node !== this.tree.node || this.engine.search_desired.limit !== this.node_limit()) { + if (config.behaviour === "back_analysis_ucinewgame") { + this.engine.send_ucinewgame(); + } this.__go(this.tree.node); } break; @@ -105,10 +109,12 @@ let hub_props = { break; case "self_play": + case "self_play_ucinewgame": case "play_white": case "play_black": if ((config.behaviour === "self_play") || + (config.behaviour === "self_play_ucinewgame") || (config.behaviour === "play_white" && this.tree.node.board.active === "w") || (config.behaviour === "play_black" && this.tree.node.board.active === "b")) { @@ -118,6 +124,9 @@ let hub_props = { } if (this.engine.search_desired.node !== this.tree.node || this.engine.search_desired.limit !== this.node_limit()) { + if (config.behaviour === "self_play_ucinewgame") { + this.engine.send_ucinewgame(); + } this.__go(this.tree.node); } @@ -165,7 +174,7 @@ let hub_props = { // Caller can tell us the change would cause user confusion for some modes... if (avoid_confusion) { - if (["play_white", "play_black", "self_play", "auto_analysis", "back_analysis"].includes(config.behaviour)) { + if (["play_white", "play_black", "self_play", "self_play_ucinewgame", "auto_analysis", "back_analysis", "back_analysis_ucinewgame"].includes(config.behaviour)) { this.set_behaviour("halt"); } } @@ -245,7 +254,7 @@ let hub_props = { if (config.behaviour === "auto_analysis") { ok = this.tree.next(); - } else if (config.behaviour === "back_analysis") { + } else if (config.behaviour === "back_analysis" || config.behaviour === "back_analysis_ucinewgame") { ok = this.tree.prev(); } @@ -959,6 +968,7 @@ let hub_props = { switch (config.behaviour) { case "self_play": + case "self_play_ucinewgame": case "play_white": case "play_black": @@ -984,6 +994,7 @@ let hub_props = { case "auto_analysis": case "back_analysis": + case "back_analysis_ucinewgame": if (relevant_node !== this.tree.node) { LogBoth(`(ignored bestmove, relevant_node !== hub.tree.node, config.behaviour was "${config.behaviour}")`); @@ -1120,8 +1131,10 @@ let hub_props = { case "play_white": case "play_black": case "self_play": + case "self_play_ucinewgame": case "auto_analysis": case "back_analysis": + case "back_analysis_ucinewgame": cfg_value = engineconfig[this.engine.filepath].search_nodes_special; break; From 3132718bc0f46662ffd1fbf10507591504064c3b Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Wed, 29 Mar 2023 08:40:11 +0200 Subject: [PATCH 09/16] Fix hash selection and update piece limit --- files/src/main.js | 34 ++++++++++++++++++--------------- files/src/renderer/75_looker.js | 15 +++++++-------- 2 files changed, 26 insertions(+), 23 deletions(-) diff --git a/files/src/main.js b/files/src/main.js index 2ab18859..f1c435be 100644 --- a/files/src/main.js +++ b/files/src/main.js @@ -244,8 +244,12 @@ function startup() { case "hash": let mb = parseInt(msg.val, 10); if (Number.isNaN(mb) === false) { - let gb = Math.floor(mb / 1024); - set_checks("Engine", "Hash", `${gb} GB`); + if (mb >= 1024) { + let gb = Math.floor(mb / 1024); + set_checks("Engine", "Hash", `${gb} GiB`); + } else { + set_checks("Engine", "Hash", `${mb} MiB`); + } } else { set_checks("Engine", "Hash", ""); // i.e. clear all } @@ -3151,7 +3155,7 @@ function menu_build() { label: "Hash", submenu: [ { - label: "16 GB", + label: "16 GiB", type: "checkbox", checked: false, click: () => { @@ -3163,7 +3167,7 @@ function menu_build() { } }, { - label: "12 GB", + label: "12 GiB", type: "checkbox", checked: false, click: () => { @@ -3175,7 +3179,7 @@ function menu_build() { } }, { - label: "10 GB", + label: "10 GiB", type: "checkbox", checked: false, click: () => { @@ -3187,7 +3191,7 @@ function menu_build() { } }, { - label: "8 GB", + label: "8 GiB", type: "checkbox", checked: false, click: () => { @@ -3199,7 +3203,7 @@ function menu_build() { } }, { - label: "6 GB", + label: "6 GiB", type: "checkbox", checked: false, click: () => { @@ -3211,7 +3215,7 @@ function menu_build() { } }, { - label: "4 GB", + label: "4 GiB", type: "checkbox", checked: false, click: () => { @@ -3223,7 +3227,7 @@ function menu_build() { } }, { - label: "2 GB", + label: "2 GiB", type: "checkbox", checked: false, click: () => { @@ -3235,7 +3239,7 @@ function menu_build() { } }, { - label: "1 GB", + label: "1 GiB", type: "checkbox", checked: false, click: () => { @@ -3247,7 +3251,7 @@ function menu_build() { } }, { - label: "512 MB", + label: "512 MiB", type: "checkbox", checked: false, click: () => { @@ -3259,7 +3263,7 @@ function menu_build() { } }, { - label: "256 MB", + label: "256 MiB", type: "checkbox", checked: false, click: () => { @@ -3271,7 +3275,7 @@ function menu_build() { } }, { - label: "128 MB", + label: "128 MiB", type: "checkbox", checked: false, click: () => { @@ -3283,7 +3287,7 @@ function menu_build() { } }, { - label: "64 MB", + label: "64 MiB", type: "checkbox", checked: false, click: () => { @@ -3295,7 +3299,7 @@ function menu_build() { } }, { - label: "16 MB", + label: "16 MiB", type: "checkbox", checked: false, click: () => { diff --git a/files/src/renderer/75_looker.js b/files/src/renderer/75_looker.js index ea0dcf6d..1788fadb 100644 --- a/files/src/renderer/75_looker.js +++ b/files/src/renderer/75_looker.js @@ -21,19 +21,18 @@ function NewLooker() { return looker; } -function chessDbEnoughPieces(fen) { - const MIN_TOTAL = 10, MIN_NON_PAWN = 4; - return (countPieces(fen) >= MIN_TOTAL && countPieces(fen, true) >= MIN_NON_PAWN) -} - -function countPieces(fen, attackers = false) { +function countPieces(fen) { let board = fen.toLowerCase().split(" ")[0].split(""); - let pieces = "qrbn"; - if (!attackers) pieces += "kp"; + let pieces = "qrbnkp"; const count = board.length - board.filter((fenPiece) => !pieces.includes(fenPiece)).length; return count; } +function chessDbEnoughPieces(fen) { + const MIN_TOTAL = 7; + return countPieces(fen) > MIN_TOTAL; +} + let looker_props = { clear_queue: function() { From d0c5d1ea7a924417a4c1cc653fa589852b2f070b Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Fri, 28 Apr 2023 14:48:23 +0200 Subject: [PATCH 10/16] Create release draft automatically --- .github/workflows/create_release.yml | 53 ++++++++++++++++++++++++++++ 1 file changed, 53 insertions(+) create mode 100644 .github/workflows/create_release.yml diff --git a/.github/workflows/create_release.yml b/.github/workflows/create_release.yml new file mode 100644 index 00000000..3f8e1638 --- /dev/null +++ b/.github/workflows/create_release.yml @@ -0,0 +1,53 @@ +name: Create GitHub Release + +on: + push: + tags: + - '*' + +jobs: + create_release: + name: Create Release + runs-on: ubuntu-latest + + steps: + - name: Checkout code + uses: actions/checkout@v3 + + - name: Set up Node.js + uses: actions/setup-node@v3 + with: + node-version: 16 + + - name: Set up Python + uses: actions/setup-python@v4 + with: + python-version: 3.8 + + - name: Set up + run: | + cd files/scripts + mkdir electron_zipped + cd electron_zipped + wget https://github.com/electron/electron/releases/download/v9.4.4/electron-v9.4.4-win32-x64.zip + wget https://github.com/electron/electron/releases/download/v9.4.4/electron-v9.4.4-linux-x64.zip + + - name: Install + run: python files/scripts/builder.py + + - name: Compress + run: | + cd files/scripts/dist/ + zip -r nibbler-windows.zip nibbler-*-windows + zip -r nibbler-linux.zip nibbler-*-linux + mv nibbler-*.zip $GITHUB_WORKSPACE/ + + - name: Create GitHub Release + uses: softprops/action-gh-release@v1 + with: + tag_name: ${{ github.ref_name }} + name: ${{ github.ref_name }} + draft: true + files: | + nibbler-linux.zip + nibbler-windows.zip From 62b8d92ccb6459cd49cc5d3559e6ff63042871c5 Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Mon, 15 May 2023 14:02:47 +0200 Subject: [PATCH 11/16] Show mate and tablebase scores --- files/src/renderer/75_looker.js | 13 ++++++++++++- 1 file changed, 12 insertions(+), 1 deletion(-) diff --git a/files/src/renderer/75_looker.js b/files/src/renderer/75_looker.js index 1788fadb..6194dddd 100644 --- a/files/src/renderer/75_looker.js +++ b/files/src/renderer/75_looker.js @@ -247,6 +247,16 @@ function new_chessdbcn_move(board, raw_item) { // The object with info about a return ret; } +function convert_tb_mate_scores(score) { + if (score > 250) return `M${Math.ceil((300 - score) * 100 / 2).toFixed()}`; + if (score < -250) return `-M${Math.ceil((300 + score) * 100 / 2).toFixed()}`; + if (score > 200) return `DTZ ${((250 - score) * 100).toFixed()}`; + if (score < -200) return `-DTZ ${((250 + score) * 100).toFixed()}`; + if (score > 150) return `DTZ ${((200 - score) * 100).toFixed()}`; + if (score < -150) return `-DTZ ${((200 + score) * 100).toFixed()}`; + return score.toFixed(2); +} + let chessdbcn_move_props = { text: function(pov) { // pov can be null for current @@ -257,7 +267,8 @@ let chessdbcn_move_props = { score = 0 - this.score; } - let s = score.toFixed(2); + let s = score; + s = convert_tb_mate_scores(s); if (s !== "0.00" && s[0] !== "-") { s = "+" + s; } From 0ba54724a1d78c19a1ec28b6c8e7a9ec1dbeb662 Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Thu, 4 Jan 2024 17:55:49 +0100 Subject: [PATCH 12/16] Fix mate scores and add new 256 multipv --- files/src/main.js | 12 ++++++++++++ files/src/renderer/75_looker.js | 18 ++++++++++-------- 2 files changed, 22 insertions(+), 8 deletions(-) diff --git a/files/src/main.js b/files/src/main.js index f1c435be..eef39c13 100644 --- a/files/src/main.js +++ b/files/src/main.js @@ -3336,6 +3336,18 @@ function menu_build() { // Will receive an ack IPC which sets menu checks. } }, + { + label: "256", + type: "checkbox", + checked: false, + click: () => { + win.webContents.send("call", { + fn: "set_uci_option_permanent", + args: ["MultiPV", 256] + }); + // Will receive an ack IPC which sets menu checks. + } + }, { label: "10", type: "checkbox", diff --git a/files/src/renderer/75_looker.js b/files/src/renderer/75_looker.js index 6194dddd..fbb239c3 100644 --- a/files/src/renderer/75_looker.js +++ b/files/src/renderer/75_looker.js @@ -243,18 +243,18 @@ let looker_props = { function new_chessdbcn_move(board, raw_item) { // The object with info about a single move in a chessdbcn object. let ret = Object.create(chessdbcn_move_props); ret.active = board.active; - ret.score = raw_item.score / 100; + ret.score = raw_item.score; return ret; } function convert_tb_mate_scores(score) { - if (score > 250) return `M${Math.ceil((300 - score) * 100 / 2).toFixed()}`; - if (score < -250) return `-M${Math.ceil((300 + score) * 100 / 2).toFixed()}`; - if (score > 200) return `DTZ ${((250 - score) * 100).toFixed()}`; - if (score < -200) return `-DTZ ${((250 + score) * 100).toFixed()}`; - if (score > 150) return `DTZ ${((200 - score) * 100).toFixed()}`; - if (score < -150) return `-DTZ ${((200 + score) * 100).toFixed()}`; - return score.toFixed(2); + if (score > 25000) return `M${Math.ceil((30000 - score) / 2)}`; + if (score < -25000) return `-M${Math.ceil((30000 + score) / 2)}`; + if (score > 20000) return `DTZ ${25000 - score}`; + if (score < -20000) return `-DTZ ${25000 + score}`; + if (score > 15000) return `DTZ ${20000 - score}`; + if (score < -15000) return `-DTZ ${20000 + score}`; + return (score / 100).toFixed(2); } let chessdbcn_move_props = { @@ -273,6 +273,8 @@ let chessdbcn_move_props = { s = "+" + s; } + console.log(s); + return `API: ${s}`; }, From 49fc3321c1e7cc6c996ca98a5632f757e46cf3fd Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:33:21 +0100 Subject: [PATCH 13/16] Support UCI string --- files/src/renderer/40_position.js | 30 +++++++++++++++++++++++------- 1 file changed, 23 insertions(+), 7 deletions(-) diff --git a/files/src/renderer/40_position.js b/files/src/renderer/40_position.js index ef1835b9..43dd21d0 100644 --- a/files/src/renderer/40_position.js +++ b/files/src/renderer/40_position.js @@ -753,6 +753,29 @@ const position_prototype = { s = ReplaceAll(s, String.fromCodePoint(n), "-"); } + // If the string contains any dots it'll be something like "1.e4" or "...e4" or whatnot... + + let lio = s.lastIndexOf("."); + if (lio !== -1) { + s = s.slice(lio + 1); + } + + // At this point, if s is actually a UCI string (which it won't be in real PGN) we can return it. + // This is a hack to allow pasting of stuff from non-PGN sources I guess... + + if (s.length === 4 || (s.length === 5 && ["q", "r", "b", "n"].includes(s[4]))) { + if (s[0] >= "a" && s[0] <= "h" && + s[1] >= "1" && s[1] <= "8" && + s[2] >= "a" && s[2] <= "h" && + s[3] >= "1" && s[3] <= "8" + ) { + let tmp = this.c960_castling_converter(s); + if (!this.illegal(tmp)) { + return [tmp, ""]; + } + } + } + // Delete things we don't need... s = ReplaceAll(s, "x", ""); @@ -761,13 +784,6 @@ const position_prototype = { s = ReplaceAll(s, "!", ""); s = ReplaceAll(s, "?", ""); - // If the string contains any dots it'll be something like "1.e4" or "...e4" or whatnot... - - let lio = s.lastIndexOf("."); - if (lio !== -1) { - s = s.slice(lio + 1); - } - // Fix castling with zeroes... s = ReplaceAll(s, "0-0-0", "O-O-O"); From 31d681a79a25ca08f36b10c2ab1722b1a76da3fb Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:33:43 +0100 Subject: [PATCH 14/16] If there is no castling, it is basically like normal chess --- files/src/renderer/75_looker.js | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/files/src/renderer/75_looker.js b/files/src/renderer/75_looker.js index fbb239c3..fcfc598b 100644 --- a/files/src/renderer/75_looker.js +++ b/files/src/renderer/75_looker.js @@ -42,7 +42,7 @@ let looker_props = { add_to_queue: function(board) { - if (!config.looker_api || !board.normalchess) { + if (!config.looker_api || (!board.normalchess && board.castling !== "")) { return; } From c8edab2fd3b02ef8053bc9af2b03c5b121940207 Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:35:39 +0100 Subject: [PATCH 15/16] Prevent an issue where Nibbler might temporarily display a very stale PV. --- files/src/renderer/80_info.js | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/files/src/renderer/80_info.js b/files/src/renderer/80_info.js index 8b99569d..b5af31db 100644 --- a/files/src/renderer/80_info.js +++ b/files/src/renderer/80_info.js @@ -143,6 +143,7 @@ let info_receiver_props = { } let move_cycle_pre_update = move_info.cycle; + let move_depth_pre_update = move_info.depth; // --------------------------------------------------------------------------------------------------------------------- @@ -237,8 +238,12 @@ let info_receiver_props = { if (CompareArrays(new_pv, move_info.pv) === false) { if (!board.sequence_illegal(new_pv)) { - if (move_cycle_pre_update === move_info.cycle && ArrayStartsWith(move_info.pv, new_pv)) { + if (move_cycle_pre_update === move_info.cycle + && ArrayStartsWith(move_info.pv, new_pv) + && move_depth_pre_update >= move_info.depth - 1 + ) { // Skip the update. This partially mitigates Stockfish sending unresolved PVs. + // We don't skip the update if the old PV is too old - issue noticed by Nagisa. } else { move_info.set_pv(new_pv); } From bc40b67ab142ec468538459de08ed6ee57287fc2 Mon Sep 17 00:00:00 2001 From: dav1312 <63931154+dav1312@users.noreply.github.com> Date: Sun, 3 Mar 2024 12:38:23 +0100 Subject: [PATCH 16/16] Encourage .pgn filenames when saving --- files/src/main.js | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/files/src/main.js b/files/src/main.js index eef39c13..543f20c8 100644 --- a/files/src/main.js +++ b/files/src/main.js @@ -375,7 +375,10 @@ function menu_build() { alert(win, messages.save_not_enabled); return; } - let file = save_dialog(win, {defaultPath: config.pgn_dialog_folder}); + let file = save_dialog(win, { + defaultPath: config.pgn_dialog_folder, + filters: [{name: "PGN", extensions: ["pgn"]}, {name: "All files", extensions: ["*"]}] + }); if (typeof file === "string" && file.length > 0) { win.webContents.send("call", { fn: "save",