From d3c667a61c4855ec3ab6e08adc0d0d3b9f8ab17a Mon Sep 17 00:00:00 2001 From: AwesomeXiangQi Date: Sun, 13 Sep 2026 14:15:28 +0800 Subject: [PATCH] =?UTF-8?q?=E4=BA=91=E5=BA=93=E5=8F=AF=E9=80=89:=20?= =?UTF-8?q?=E6=9C=8D=E5=8A=A1=E6=94=AF=E6=8C=81=20cloud=20=E8=AF=B7?= =?UTF-8?q?=E6=B1=82=E5=8F=82=E6=95=B0,=20=E6=B2=B9=E7=8C=B4=E9=9D=A2?= =?UTF-8?q?=E6=9D=BF=E5=8A=A0'=E4=BD=BF=E7=94=A8=E4=BA=91=E5=BA=93'?= =?UTF-8?q?=E5=BC=80=E5=85=B3(v1.5.0)?= MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --- xiangqi-engine.user.js | 19 ++++++++++++++++--- xiangqi_bot/server.py | 25 ++++++++++++++----------- 2 files changed, 30 insertions(+), 14 deletions(-) diff --git a/xiangqi-engine.user.js b/xiangqi-engine.user.js index 532d216..9d91b05 100644 --- a/xiangqi-engine.user.js +++ b/xiangqi-engine.user.js @@ -2,7 +2,7 @@ // @name Xiangqi.com 本地皮卡鱼引擎对接 // @name:en Xiangqi.com Local Pikafish Engine // @namespace awesome-xiangqi -// @version 1.4.1 +// @version 1.5.0 // @description 在 play.xiangqi.com 对局中调用本地皮卡鱼引擎(http://127.0.0.1:9377)自动/手动走子 // @description:en Hook the site WebSocket and let a local Pikafish engine play for you // @match https://play.xiangqi.com/* @@ -16,7 +16,7 @@ const ENGINE_URL = "http://127.0.0.1:9377"; const NS = "42/xiangqi,"; const FIRST_MOVE_EXTRA_SEC = 5; - const VERSION = "1.4.1"; + const VERSION = "1.5.0"; const PATCH_MARK = Symbol.for("xiangqi.pikafish.ws.patched"); const uW = typeof unsafeWindow !== "undefined" ? unsafeWindow : window; @@ -48,6 +48,7 @@ const cfg = { enabled: storage.get("pf_enabled", "0") === "1", + useCloud: storage.get("pf_usecloud", "1") === "1", movetime: Math.max(50, +storage.get("pf_movetime", 800) || 800), depth: Math.max(0, +storage.get("pf_depth", 0) || 0), firstDelay: Math.max(0, +storage.get("pf_firstdelay", 0) || 0), @@ -60,6 +61,7 @@ function saveCfg() { storage.set("pf_enabled", cfg.enabled ? "1" : "0"); + storage.set("pf_usecloud", cfg.useCloud ? "1" : "0"); storage.set("pf_movetime", cfg.movetime); storage.set("pf_depth", cfg.depth); storage.set("pf_firstdelay", cfg.firstDelay); @@ -195,7 +197,7 @@ let liveWS = null; - async function engineBestmove({ moves, fen, movetime, depth, signal }) { + async function engineBestmove({ moves, fen, movetime, depth, useCloud, signal }) { const timeoutMs = Math.max(15000, movetime * 4 + 2000); const ctrl = new AbortController(); const timer = setTimeout( @@ -216,6 +218,7 @@ fen: fen || undefined, movetime, depth: depth > 0 ? depth : undefined, + cloud: useCloud !== false, }), signal: ctrl.signal, }); @@ -296,6 +299,7 @@ fen: G.fen, movetime: cfg.movetime, depth: cfg.depth, + useCloud: cfg.useCloud, }); if (reqId !== G.reqId) return; if (G.over) throw new Error("对局已结束"); @@ -494,6 +498,7 @@
🐴 皮卡鱼
+
每步用时(ms)
深度(0=用时间)
首步延迟(秒+5)
@@ -519,6 +524,14 @@ if (cfg.enabled) scheduleTurn(0); }); + const cloudCb = panel.querySelector("#pf-cloud"); + cloudCb.checked = cfg.useCloud; + cloudCb.addEventListener("change", () => { + cfg.useCloud = cloudCb.checked; + saveCfg(); + if (cfg.enabled) scheduleTurn(0); + }); + const mt = panel.querySelector("#pf-mt"); mt.value = cfg.movetime; mt.addEventListener("change", () => { diff --git a/xiangqi_bot/server.py b/xiangqi_bot/server.py index e05e811..68b485d 100644 --- a/xiangqi_bot/server.py +++ b/xiangqi_bot/server.py @@ -31,20 +31,22 @@ class Service: await self.engine.quit() await self.cloud.close() - async def bestmove(self, moves_site, fen=None, movetime=None, depth=None): + async def bestmove(self, moves_site, fen=None, movetime=None, depth=None, req_cloud=None): moves_ucci = [site_to_ucci(m) for m in moves_site] fen = fen or fen_from_moves(moves_ucci) - # 1. 云库优先 - try: - cloud_hit = await self.cloud.best(fen, moves_count=len(moves_ucci)) - except Exception as e: - log.warning('cloud error: %s', e) - cloud_hit = None - if cloud_hit and not depth: - mv, score, note = cloud_hit - return {'ok': True, 'source': 'cloud', 'move': ucci_to_site(mv), - 'score': f'cp {score}', 'note': note, 'ms': 0} + # 1. 云库优先(请求可显式关闭; 深度模式强制引擎) + use_cloud = req_cloud if req_cloud is not None else True + if use_cloud and not depth: + try: + cloud_hit = await self.cloud.best(fen, moves_count=len(moves_ucci)) + except Exception as e: + log.warning('cloud error: %s', e) + cloud_hit = None + if cloud_hit: + mv, score, note = cloud_hit + return {'ok': True, 'source': 'cloud', 'move': ucci_to_site(mv), + 'score': f'cp {score}', 'note': note, 'ms': 0} # 2. 皮卡鱼兜底 try: @@ -96,6 +98,7 @@ def make_app(args): fen=req.get('fen'), movetime=req.get('movetime'), depth=req.get('depth'), + req_cloud=req.get('cloud'), ) return web.json_response(out) except Exception as e: