Skip to content

GPU加速分支合入:围棋MCTS性能优化、棋类引擎修复与全项目无头压测回归 - #1

Merged
Barbatosishere merged 129 commits into
mainfrom
gpu-accel
Sep 10, 2026
Merged

GPU加速分支合入:围棋MCTS性能优化、棋类引擎修复与全项目无头压测回归#1
Barbatosishere merged 129 commits into
mainfrom
gpu-accel

Conversation

@Barbatosishere

Copy link
Copy Markdown
Owner

Summary

gpu-accel 分支整体合入 main:GPU/引擎性能加速 + 全游戏多轮 bug 修复 + 全项目无头压力测试回归。分支领先 main 约 128 个提交。

Changes

围棋引擎(本分支核心)

  • MCTS 三轮性能优化:候选生成/提子/增量哈希/打分融合进单次遍历,热路径全面原语化(ThreadLocal 零分配),每迭代耗时降低 47–61%;优化前后行为快照逐字节一致
  • PASS 建模为真实搜索动作(策略槽 361)、扩展/回传叶子修正、双 PASS 终局计分
  • NeuralEvaluator:Windows 并发保存 AccessDeniedException 指数退避修复、64KB 缓冲 IO
  • OpenCL 后端、KataGo 适配、自对弈/对抗训练器持续改进
  • GoGame 暴露纯规则盘面 API(xorStone/快照/计分协议)

棋类与其他游戏

  • 象棋:内置 AI PVS/aspiration 修复、Pikafish 常驻读线程、局代号守卫、三次重复/易位权贯穿
  • 斗地主:四带二/飞机翼/倍数/multiset 扣牌/LAN 预校验等修复
  • 五子棋多尺寸、井字棋双角叉防御、打地鼠/冰火人/钢琴 Tiles 等小游戏屏修复
  • 联机层:协议版本/邀请取消/断线广播/数据信封、大厅工具增强

质量保障(本轮新增)

  • 全项目无头压力测试通过:象棋差分 68.4 万用例、井字棋全博弈树 60.5 万、斗地主 9.5 万、五子棋 3300、围棋 fuzz/树不变量/并发/持久化——产品代码 0 未决缺陷
  • 新增 25 个回归测试文件(chess/gogame/landlord/network/util)

构建

  • JNA 改为 compileOnly(不进最终 JAR,消除 Java 22 模块冲突)
  • GitHub Actions 构建工作流、资源排除、版本号对齐

Testing

  • gradle test 全套件通过(含新增 25 个回归测试)
  • 全项目无头压测 6 域 144 万+ 用例 0 失败
  • MCTS 优化与 HEAD 行为快照逐字节一致
  • clean build 生成 beta7 构建产物

Barbatosishere and others added 30 commits August 19, 2026 14:45
HUD 底部一直显示"ESC 退出 R 重开"提示,但 R 键只在 GAME_OVER
状态处理,导致游戏进行中按 R 无响应。

修复:PLAYING 状态也处理 R 键重开(与 GAME_OVER 一致,
LAN_CLIENT 仍禁止单方面重开)。

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
ColorChase/FlappyBird/Tetris/Snake 的 HUD 底部一直显示"R 重开",
但 keyPressed 中 R 键只在 GAME_OVER 状态处理,游戏进行中按 R 无效。

修复:R 键改为 state != MENU 时均生效(进行中+结算均可重开),
与 IceFire 修复保持一致。

Co-Authored-By: Claude Haiku 4.5 <noreply@anthropic.com>
- GoAI 接口+工厂,mcts/katago 引擎配置(GameSettings)
- MCTSGoAI:PUCT并行搜索/树重用/Dirichlet探索;自对弈/对局模式分离、温度采样
- NeuralEvaluator:三级分块隔离网络369K参数、双头策略/价值、NEV2持久化
- OpenCLBackend:JNA绑定OpenCL,GPU前向+sgd权重更新管道
- GoSelfPlayTrainer:30路并行自对弈、8-fold增强、Replay Buffer、余弦退火LR
- KataGoGoAI GTP 集成 + GoAdversarialTrainer 对抗训练
- GoGame 公共规则方法(rulesOnly/calcTerritory/getScore/super-ko)
- build.gradle 训练任务 + .gitignore 排除实验残留

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- ChessAI 接口+工厂,从 ChessGameScreen 抽离 AI 逻辑
- BuiltInChessAI 纯Java增强搜索(迭代加深/置换表/LMR/空步裁剪/静态搜索)
- PikafishChessAI UCI 协议封装 + ChessSimulationMain 自对弈模拟
- 新增 ChessRulesTest 5 测试用例

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 增加 aiGeneration 代次标记,重开/退出后丢弃残留 AI 结果
- aiPending/aiDone/aiComputing 同步,避免接管过时思考结果

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MCTS节点缓存:expand/simulate共享一次前向同时拿到policy+value,
  避免同一节点重复前向(每个MCTS迭代的前向次数减半)
- 修复:simulate中使用node.move作为plane3输入,替代node.linkedMove
  (linkedMove语义为最后展开的子走法,与节点自身棋盘不对应)
- 训练8-fold对称:extractAuxFeatures在D4下不变,算一次baseAux复用8份,
  输入构建成本降为1/8
- heuristicSort用int[361]数组替代HashMap<String,Integer>,减少分配和装箱

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 合并走法生成与评分:evaluateMoveScore 一次计算所有昂贵原语
  (countCaptures/棋群遍历等),替代原先 evaluateMovePruning 全盘
  扫描后再 heuristicSort 全盘重扫的两轮冗余,每个 expand 省的 BFS
  量与合法走法数成正比
- 删除 heuristicSort 的重新评估逻辑(改为直接按预计算值排序),
  删除 evaluateMovePruning/hasFriendlyNeighbor 死代码
- 共享树 + virtual loss 并行 MCTS:各线程从独立树克隆+merge
  改为共享一棵树,virtual loss 迫使线程分散到不同分支,消除
  独立树下各线程扎堆探索相同高 UCB 走法的冗余,搜索宽度显著提升
- 删除 ~200 行死代码(cloneNodeTree/Recursive/mergeResults/Children/SearchResult)
- shouldTerminateEarly 快照 children 防并发修改
- expand/backpropagate 添加 synchronized 保证共享树线程安全

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 策略头引导展开顺序:expand()首次算出policyCache后,按策略概率
  升序排列untriedMoves,remove(size-1)优先展开高概率走法,让搜索
  更听神经网络的话,对齐AlphaZero风格
- 修复getAllValidMoves/heuristicSort排序方向bug:此前降序排列但
  remove(size-1)从末尾取,等价于最低分走法优先展开;改为升序,
  让remove(size-1)正确取出最高分走法
- Momentum优化器(μ=0.9):v = μ·v + lr·(g+L2·w), w -= v,
  惰性分配速度缓冲(首次momentum>0创建),apply()时重置防止
  旧动量污染新权重
- 两个Trainer(GoSelfPlayTrainer/GoAdversarialTrainer)Config
  均新增momentum字段,默认0.9

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 策略Top-K剪枝:expand按策略概率只保留累积95%的走法(至少3个),
  搜索树宽度收窄,相同时间搜更深
- 局部战术搜索升级:tacticalReading从单层启发式评估改为受限α-β
  深度搜索(气≤2用深度5,气=3用深度3),限定目标棋群周围2格区域,
  叶子用神经网络价值头评估,超时通过deadline控制
- 删除废弃的TACTICAL_WINDOW/findTacticalKill/evaluateTacticalMove
- getBestMove为战术搜索分配 baseSearchTime/4 的时间预算(200~800ms)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MCTSGoAI:探索强度倍率 setExplorationScale(scale),随训练代次
  从1.0衰减至0.2;影响Dirichlet噪声比例和采样温度,早期
  多探索、后期收敛
- GoSelfPlayTrainer:内部代次计数器,playGame时按代次设置
  探索强度(gen 0→1.0, gen 40→0.2)
- GoTrainingMain:新增--warmup N参数,前N代线性从0升到
  目标LR,配合Momentum稳定起步;之后余弦退火不变

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- NEV2→NEV3:魔数0x4E455633,格式编号3
- 所有权重 save/load 用 writeFloat/readFloat 替代 writeDouble/readDouble
- 内部计算保持 double 精度,推理和训练不受影响
- 权重文件:2.95MB→1.48MB(-50%)
- 注意:NEV3 不兼容旧版 NEV2 权重,需重新训练

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- OpenCLBackend 新增 batchPass0Forward 公共方法:在 GPU 上执行
  子块→字块→顶级三层前向,一次批量完成,填充所有中间值
- 修复子块权重布局 bug:NeuralEvaluator 存储 [9][36][16](9块
  共享),GPU 内核期望 [81][36][16](81子块独立索引),新增
  batchPass0Forward 内复制展开
- 原 CPU 循环的 133M 乘加/批现在在 RTX 2060 上运行
- 训练时 GPU 加速,MCTS 推理保持 CPU(单样本前向无批量收益)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 加载 NEV2(double 8字节)和 NEV3(float 4字节)权重,读
  取方法按 magic 自动选择 readDouble/readFloat
- 修正之前 save 用 writeFloat 但 read 用 readDouble 的格式不
  匹配问题(跨代 checkpoint 会崩溃)
- 为 readMatrix/readVector 增加 isDouble 参数控制读精度
- 权重文件格式:保存始终 NEV3(float),从 NEV2 加载也能继续

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- batchPass0Forward 扩展为完整前向:子块→字块→顶级→策略头→价值头
- 新增 policyW/policyB/valW1/valB1/valW2/valB2 参数和 policyOut/valueOut 输出
- NeuralEvaluator 的 per-sample 循环 GPU 路径直接复用 GPU softmax 和 tanh 输出
- 价值头隐藏层 vh/vhZ 仍在 CPU 重算(256→128→1 仅 33K 乘加,供反向使用)
- 策略头反向只需 shared+dLogit,GPU softmax 输出可直接使用

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
高严重性修复:
- deepCopyNode 树重用:递归时按子走法推进棋盘,不再全传同一引用
- selectBestChild 并发安全:快照 children 避免 ConcurrentModificationException
- valueCached volatile:防止双检锁失效读到0值
- virtual loss 双倍计数:移除 totalScore--,仅保留 visits++ 分流
- value_fwd 内核:添加缺失的 b2 输出偏置参数
- 展开中 untriedMoves 排序移入 synchronized 保护
- children 初始化移入 synchronized 防止竞争丢失

中/低严重性修复:
- forward() softmax 添加 sumExp=0 保护防 NaN
- fromWeights 跳过随机 init(私有构造参数控制)
- opencl 字段加 volatile 修复双重检查锁定
- batchPass0Forward 添加 policyOut/valueOut null 检查
- 其他 16 项微优化和边界修复

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- policy_fwd 内核 softmax 添加 max(se,1e-30) 防 NaN(与 CPU 路径一致)
- 移除未定义的 fwd_reduce 内核名(clCreateKernel 会静默失败)
- trainBatch 添加 subOut/blkOut/shared/policy/value 的 null 检查
- launch3D x 维度保持裸值(取整会导致 sub_fwd 越界;NULL local
  work_size 由驱动自动选择合法值,无 CL_INVALID_WORK_GROUP_SIZE 风险)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- GoSelfPlayTrainer: planes 数组改惰性分配,消除 1024 个废弃 [4][19][19] 分配的 GC 压力
- GoTrainingMain: 预热注释修正(实际从 LR/warmup 起步而非 0)
- MCTSGoAI: 移除冗余 heuristicSort(getAllValidMoves 已按价值升序排好)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
高严重性:
- MCTS价值视角反转:backpropagate每层取反+选择/评估对子节点Q取反,
  修复AI选对手最有利走法的致命bug(棋力上不去的根因)
- deepCopyNode丢弃untriedMoves:树重用后expand永不执行,改为复制
- GPU坐标转置:extractSubInputs块/子块坐标与CPU不一致(b%3/b/3互换),
  改为与NeuralEvaluator一致,修复GPU训练与CPU推理函数不一致

中/低严重性:
- 移除虚拟损失visits++(叶子visits双倍膨胀、胜率稀释)
- shouldTerminateEarly NEGATIVE_INFINITY误判早停
- 早退路径(killer/book/endgame/tactical)未记录lastMove导致策略目标全pass
- getVisitDistribution无MCTS分布时返回lastMove one-hot
- tryReuseTree校验棋盘一致(对抗对局不重用错位子树)
- Future join完全等待(残留线程竞态)
- countCaptures棋群双倍计数去重
- apply()恢复持久化模型版本
- evaluationCache键纳入lastMove
- plane3训练/推理一致:训练器记录lastMove并对称变换

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- MCTS super-ko:MCTSNode加hash字段,expand时落子后局面若与
  GoGame历史或祖先链重复则跳过(覆盖单劫回提和全局同型);
  GoGame暴露getPositionHistory/getCurrentHash
- trainBatch死代码:subW从[9][36][16]展开为GPU内核期望的[81][36][16],
  修复权重缓冲区越界读
- GPU缓冲泄漏:run3D/run2D/gpuValueFwd/batchWeightUpdate错误路径
  用try/finally保证free;free对null安全

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 早退路径(killer/book/endgame/tactical/唯一走法)设置currentRoot=null,
  使getVisitDistribution正确回退到lastMove one-hot(此前返回旧位置分布污染策略目标)
- 新鲜根节点用game.getLastMove()设置move,plane3与训练分布一致
  (此前根节点move=null导致serve端plane3空)
- GoAdversarialTrainer:KataGo同步改用实际落子坐标(fallback时不再分叉)、
  删除死代码gameEvaluator
- MCTSGoAI构造器改用NeuralEvaluator.fromWeights跳过随机init
- getCurrentWinRate防御NEGATIVE_INFINITY
- GPU缓冲:JNA Memory显式close、init()队列降级catch(Throwable)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- getAllValidMoves 增加 super-ko 过滤(isKoIllegal),untriedMoves
  不再含劫争非法走法,策略Top-K剪枝基于正确走法集
- getBestMove 在生成根节点走法前同步 koHistory(此前根走法无过滤)
- 移除 expand 中重复的 koHistory 设置
- 全局历史检查 koHistory.contains + 树内祖先检查 isAncestorKoRepeat 双保险

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
高严重性:
- shouldTerminateEarly: margin仅在有>=2子节点被访问时判断,修复
  宽局面(>=100合法走法)搜索在第1个子节点被访问后立即提前终止
- gValueB1 遗漏累加:价值头隐藏层偏置梯度从未累积,偏置永久冻结
  在0.01,补 gValueB1[i] += dVh[i]
- policy_fwd 2D launch y=368冗余重算:内核只用get_global_id(0),
  改1D launch消除~80倍冗余计算

中/低严重性:
- value_fwd launch(k,B,1) y取整到16冗余 → 改launch1D
- targetIsCaptured符号反转:negamax按攻击/防守方返回±1
- killer/tactical走法绕过super-ko过滤 → 补isKoIllegal
- getVisitDistribution passVisits虚高(根展开误算为pass)→ pass概率=0
- sub_fwd/block_fwd内核加s>=S边界检查+launch3D x填充
- validMoves.isEmpty清currentRoot、evaluate缓存键(0,0)碰撞、
  buildInputPlanes长度保护、evaluateSeparation去重失败、
  valueB2 L2正则与其它bias不一致

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- forward()/forwardValue()/forwardPolicy()/snapshot() 用读锁
  (MCTS 并行搜索时多线程可同时推理,此前全串行化)
- trainMiniBatch()/apply() 用写锁(独占,训练时阻塞推理)
- 自对弈搜索时神经网络评估不再排队,8线程并行搜索吞吐
  预计提升数倍(具体取决于前向 vs 搜索其他部分的比例)

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
高严重性:
- GoMove.player语义不一致:placeStone先记录落子者再switchPlayer(与pass一致),
  修复KataGo同步时黑白颠倒(所有棋盘走法颜色发反)
- makeAiMove尊重AI返回null=pass(不再强行扫描落子,修复KataGo的pass/resign
  被覆盖导致赢棋变输棋)
- tick()后台线程:MCTS搜索在go-ai-worker线程运行,客户端不再冻结1~12秒

中/低严重性:
- moveHistory/positionHistory线程安全:stateLock同步读写
- getMoveHistory/getPositionHistory同步快照
- GoGameScreen.onClose()补game.close(),修复KataGo进程泄漏
- 搜索时间slider接线:initAi改用MCTSGoAI.createFromSettings(),设置生效
- 单机构造器补充ai==null/aiMode防御
- 构造函数初始化ai&aiMode,修复LAN构造器未初始化AI
- 后台线程结果用aiComputed/aiPendingMove/aiThinking标志正确消费
- makeAiMove重构为computeAiMove+applyAiMove,支持后台线程+客户端落子

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- FPU:selectBestChild移除强制展开(visits==0返回子节点),改FPU=0
  用PUCT统一排序,宽局面(100+合法走法)下搜索聚焦而非遍历所有点,
  显著提升搜索深度
- 新增FPU_VALUE常量(默认0.0),未访问子节点视为均势
- GPU可选:NeuralEvaluator新增isGpuEnabled(),优先读系统属性
  go.gpu,回退到GameSettings配置,默认为true
- GoTrainingMain新增--gpu参数,训练时可在纯CPU/GPU间切换
- 验证:GPU默认启用(RTX 2060)与禁用(--gpu false)均正常工作

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
- 扫雷:首击安全布雷(首次点击区域3x3内不埋雷)
- 数独:通关后停止计时 + 选中格子数字改为白字加深对比度
- 鼠标反应:100分后正确结算胜利
- 接水管:开局保证不自动接通(生成后验证可解性)
- 五子棋:新增9/13/15/19自定义棋盘大小(菜单按钮+S键切换,星位自适应)
- 象棋:渲染层次修复(flush中间层确保遮罩遮挡棋盘不穿透)
- 森林冰火人:坠落检测连锁到gameOver(死亡状态传播到结算)
- 水果忍者:炸弹改为方形+叉号标识,视觉上明显区别于圆形水果
- 跳一跳:修复渲染/贴图对齐/碰撞体
- 迷宫:关卡递进+鬼怪可躲避
- 推箱子:按关卡递增难度
- 打地鼠:贴图绘制修正

Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
Barbatosishere and others added 25 commits August 27, 2026 23:39
importSongFromDialog 的 frame.dispose() 此前只在成功路径末尾无条件调用,
中途抛异常(权限/IO错误等)会跳过dispose直接进catch,AWT Frame泄漏。frame
提到try外,finally里无条件dispose,覆盖所有路径。
Co-Authored-By: Claude Sonnet 5 <noreply@anthropic.com>
第二个 [[mods]] 块(modId 同为 game_console)原本是想给 mod 加 side=CLIENT,
但 TOML 里一个 [[mods]] 块即一个 mod 定义,同 modId 声明两次会让
UniqueModListBuilder 报 'Mod game_console is present in multiple files'
且两个条目文件名相同(同一 jar 被解析成两个 mod),游戏启动即失败。
现合并为单一块,side = "CLIENT" 直接挂在本体属性里。
- LandlordGame.playCards: contains+remove 两段式改为副本整体校验,重复牌 token 不再漏扣
- GoGame.getLastMove/moveHistorySize: 补 stateLock 读锁,与 MCTS 后台线程竞争不再撕裂
- NeuralEvaluator.release() + MCTSGoAI.SHARED_POOL.shutdown(): OpenCL 资源退出链闭合
- BuiltInChessAI: activeGen/myGen 代际失效,同实例新搜索立即作废旧线程的 shouldStop
- GoGameScreen/WesternChessScreen: aiGeneration/boardGen 代际守卫,重开新局后迟到 AI 线程不再落地污染
- AIPlayer 顺子/连对/飞机: >= targetValue 改 > ,等值在 canBeat 严格大于下压不住只空耗一手
- LandlordFullGameSimulationTest: 三家 AI 全程打到 ENDED 且零和;重复 token 整体拒绝(原子性)
- GoKoSimulationTest: 互咬单气双劫子完整劫争循环——白提劫合法(先提后判自杀)、
  无劫材立即回提被 super-ko 拒且轮次不翻转、双方各下新棋后提劫/回提合法、
  再次立即回提仍被拒。全部 35 测试通过
…ml 删无效 side

- JNA 5.x 改用 [5.14,6) 区间 jarJar 打包,玩家环境缺 jna.dll 时也能跑 GPU 路径
  (JOGL/JOCL 未使用,删除 jogamp maven 仓库)
- mods.toml 删 side=CLIENT 行(FML 不解析该键,静默忽略);
  本 mod 走 handleServer 转发,专用服务器必须加载(双端 + @onlyin 隔离客户端类)
- item/game_console.json 的 display.thirdperson/firstperson 拆为
  _righthand/_lefthand + _righthand/_lefthand 四个键(旧键被新版 Mojang 模型加载器静默忽略)
- root 处 pathKeys[0]=rootKey + 路径重复检测(同方隔 2 层回扫),
  解决中盘反复在循环局面上打转
- negamax 入口 TT 探测按 ply 归一(杀分 ±(INF-ply)),存分还原
- PVS 零窗口在 α=-INF 退化为不可能窗口 (INF-1,INF) → quiescence 恒 fail-low
  返回 ±(INF-1) 垃圾分;aspiration 重搜条件对照初始窗口
- PVS 入口 depth<=0 分支改为分两步:先零窗试、若 reject 全开窗
- searchDepth<=0 入口 quiescence 区分将军/非将军,被将军不 stand-pat 且
  moves.isEmpty 返回 -(INF-ply) 杀分
- 空步保存/恢复 nullMovePly 替代硬重置
- 移除 ChessRules.legalMoves 已过滤送将后的冗余 isCheck 复检
- ChessSimulationMain awaitTermination 按 max(120, 总局数*600) 伸缩
- ChessSimulationMain AI 走法合法性兜底(复用合法走法列表)
- PikafishChessAI 超时发 stop+5s 排空 + acceptedMove 对照 legalMoves 校验
- GomokuAI SituationCache 加 FLAG_EXACT/LOWER/UPPER 三态分类,
  入口按 flag 收紧 α-β 边界、存储按初窗分类
- appendChess 越界按对方棋子 '2' 处理(不再丢字符)
- TicTacToeGame 加双角叉防御:对手占对角双角且己方仅中心→走边
- GoGame 贴目改为中国规则 7.5 点(1 子超半值=2 点分差)
- GoGame 全局加 stateLock 防止 getStone/getCurrentPlayer/isGameOver
  /getBlackCaptured/getWhiteCaptured/getBoardCopy/getCurrentHash 撕裂快照
- placeStone 整段(backup→提子→劫争→自杀→记录→switchPlayer)持锁
- calcTerritory 拆为持锁 public + 无锁 internal 供内部回溯用
…除 + 崩溃保存

KataGoGoAI:原版 sendCommand 已读一次响应、调用方 expectSuccess/readResponse 再读一次,
  genmove 必然超时失败,引擎 100% 不可用。重构为驻留读线程+阻塞队列:
  - sendCommand 单次发送+读取,'?' 错误响应抛 IOException
  - 驻留线程把 GTP 行入队(空行 GTP 终止符不入队),poll 带整体 deadline
  - 解析首行时剥离回显的命令 id 前缀('5 D4' → 'D4')
  - readLoop 改 catch (IOException|InterruptedException) + EOF 哨兵
  - 关闭时 running=false + 哨兵入队唤醒等待者
  - stderr 不并入 stdout(引擎日志走进程 stderr,stdout 保持纯 GTP 流)

MCTSGoAI:getBestMCTSMove 改按 child.visits 最大(标准 AlphaZero 终局选着,
  鲁棒性优于胜率均值受方差影响)
  PUCT 改标准 sqrt(parent.visits) 而非 sqrt(log parent.visits)(先验引导探索更充分)
  sampleMCTSMove 早期温度改 0.9*scale+0.1 默认=1.0(修复原 1.5*scale+0.1 默认 1.6)
  shouldTerminateEarly 加最高胜率子至少 32 visits 门槛(防 2 连胜假信号截断)
  deepCopyNode 还原纯策略先验(policyCache×361),上代根 Dirichlet 噪声不污染新搜索

GoAdversarialTrainer:去 redirectErrorStream+逐行找 '=' 响应(startup banner 干扰清除)
  parseGTPMove 区分 resign(对手认输→我方胜+±1 价值,结束对局)
  runGeneration 加 future.get 单局超时+goAdversarialTrainer trimReplayBuffer 用 subList 批量清除

GoAdversarialMain:catch (RuntimeException|Error) 中崩保存权重(OOM/GTP 异常多代训练不可丢)

OpenCLBackend:构造器 catch Throwable(JNA UnsatisfiedLinkError 是 Error 不是 Exception)
  关键内核数<5 时回退 CPU 避免 batchPass0Forward 拿到 null 当成功
  删死代码:trainBatch/batchTopForward/batchWeightUpdate×3/matmul/matmul_tA/sgd 内核

NeuralEvaluator:ensureOpenCL 捕获 Throwable 回退 CPU(不炸推理路径)
  删死代码:evaluate(×2)/getGpuDevice(无任何调用点)
CardPattern.Type 加 FOUR_WITH_TWO_SINGLES/FOUR_WITH_TWO_PAIRS
LandlordGame.analyzePattern:四带两单 (size==6 count[4]==1) / 四带两对 (size==8 count[4]==1 && count[2]==2)
  飞机带单翅牌改为任意散牌(valueCount 按整值分组,三张值不会混入翅牌)
  playCounts/rocketPlayed 累计;calculateScores 春天/反春天/王炸 各×2 可叠加
  scores 跨局保留不重置(积分累计),playCounts/rocketPlayed 局初清零

AIPlayer.decideBid(hand) 单参(去 isFirst 强阈值,统用 40 阈)
  chooseCardsToPlay 加 myIdx/lastPlayerIdx/landlordIdx/handCounts 身份重载
  队友报牌默认过牌(≤2 张才帮压)
  对手报牌 ≤2 张禁过牌/禁保炸(必压否则对手下回合出完)
  TreeMap 升序分组保证 findMinimal* 最小可压
  chooseActivePlay 散牌 5 连顺子领出 + pickGroupExact 不拆炸弹

LandlordGameScreen:
  - 主机 PLAY 拒收回 REJECT 报文(客机不再面对静默黑洞)
  - 客机 doPlay/doPass 发送前预校验(领出轮禁过牌、非领出轮压不过提示)
  - drawMyHand sx 双边钳制防止 17+ 张手牌溢出右边
  - 新增 isLeaveFromPeer 重写(HOST 任一客机退出都合法)

getPatternName switch 补新枚举(编译期枚举 switch 必穷尽)
- LanMultiplayerScreen 加 isLeaveFromPeer 默认方法(仅接受 getLanPeer 一人,
  斗地主 HOST 端重写以接受 peer1/peer2 任一)
- MultiplayerLobbyScreen.LEAVE_GAME 改走 isLeaveFromPeer 来源校验
- DECLINE_INVITE 加斗地主批量邀请路径:候选人拒绝移出名单,不足两人时终止等待
- WAITING 接受邀请后补 waitingStartTick(客机不再无限等)
- INVITE_CANCELLED 仅 pendingInvite 匹配时提示(防伪造包顶掉)
- 新增 PLAYER_QUIT case + ServerDisconnectWatcher 监听 PlayerLoggedOutEvent
  广播(data=退出者 UUID,客机按对端判定后关屏)
- ModNetworks 反射 Method 静态缓存(避免每包 Class.forName+getMethod)
- catch (Throwable) 替 catch (Exception) + LOGGER.error 替静默吞(JNA 失败可见)
- MultiplayerGamePacket.handleServer 转发限流 120 包/秒(防刷包占带宽)
  + 自动清理 10s 无流量窗口
- PacketType.PLAYER_QUIT 末尾追加(保持序号兼容)
- GAME_OVER 保留注释说明(序号已引用不可移除)
- ModMain 通过 NeoForge.EVENT_BUS.addListener 注册看门狗(避开 @EventBusSubscriber 包路径变动)
…SIGN 发送

ChessGameScreen:重写 removed()(ESC 全路径走 setScreen→removed;之前未重写导致 Pikafish 进程泄漏)
  aiGen/aiPendingGen 代际守卫(旧 AI 线程的迟到结果在落地前作废)
  checkNoLegalMovesEnd 移出 render 入口(doMove/undoMove/resetBoard 末尾统一触发,
  避免每帧全盘 legalMoves 扫描)
  tick 入口 aiPendingMove != null && aiPendingGen != aiGen 时直接丢弃

WesternChessScreen:
  - 50 回合规则(halfmoveClock 兵动/吃子清零,其余+1)
  - 三次重复和棋(positionKey 含棋盘+行棋方+易位权+ep)
  - 车被吃/王车易位移动时相应易位权清除(不再保留已失车的易位权)
  - resultOutcome 字段(1白胜/-1黑胜/0和棋),renderOver 按实际胜方渲染
  - LAN 再来一局:CLIENT 无权重开;HOST 重开并广播 RESTART

GomokuScreen:RESTART 报文带 boardSize 同步,接收端钳制 9-19 防两端棋盘错位

GoGameScreen:联机模式 R 键认输(sendLanMove('RESIGN:')),对方 onRemoteMove 已有 RESIGN 处理
A 区(子代理):
- KlotskiScreen board 初始 null(避免 init() 首次判断恒 false 棋盘空白)
- BreakoutScreen 砖块/挡板改用 drawBlock3D(w,h) 矩形重载(原按正方形画)
- Match3/Minesweeper/Klotski 点击负坐标守卫((int) 向零截断会误命中第 0 行/列)
- GameRenderHelper 拆 tickParticles/renderParticles(弹窗暂停冻结物理 + 帧率解耦)
  + drawBlock3D(w,h) 矩形重载 + drawCircle 新增(供 Minesweeper 自绘地雷用)
- JumpGameScreen 平台排序缓存 + 浮字缓冲复用 + 渐变 fillGradient(消除 4 个新增 alloc/帧)
- Minesweeper 自绘旗/雷(默认字体无 U+1F4A3/U+1F6A9 豆腐块)
- Breakout/FruitNinja/WhackAMole/IceFire emoji 换 ASCII(避免字体豆腐块)
- ColorChaseGameScreen resumeFromExitConfirm 平移 lastColorChangeTime(弹窗超变色间隔后免白送分)
- ColorChase parseInt 自增后 catch 不能再 idx++(避免坏格之后整列错位)
- Match3GameScreen 初始化 + 填满后 50 次重 roll 防死局
- Match3GameScreen ItemStack 缓存(render 每帧省 64 个 new ItemStack)
- FruitNinjaScreen 浮字更新移入状态守卫后
- WhackAMoleScreen 拦截上移(弹窗期间 R 不再跳过弹窗)
- PianoTilesGameScreen resume(long audioScheduledTime) 未到起播时刻不 start
  + \u 转义修复 ×2 + maxCombo 重置
- SudokuGameScreen countSolutions 唯一解挖洞(每挖一格验证,多解回填)

B 区(子代理):
- SokobanScreen generateLevelOnce 零箱重试外壳(生成局无箱时整关重生)
- GameSelectorScreen importSettingsFromFile Frame dispose 移入 finally(防 AWT 泄漏)
- GameSettings writeTextFile 原子写(tmp + Files.move ATOMIC_MOVE)
- ExternalFileManager getMusicDir/getVoiceDir rootDir==null 时再尝试 init
  + isSafeFileName 路径穿越守卫(拒绝 '..' / '/' / '\' 文件名)

不含:斗地主/围棋/网络/棋类引擎/构建资源(已分别独立提交)
根因: jna-5.19.1.jar 嵌入 mod jar 后, META-INF/jarjar/ 下形成 com.sun.jna
自动模块。当玩家环境有其他 mod(Iris/Sodium/NeoForge 间接)也提供 JNA 时,
Java 22 模块系统检测到两个同名模块, 抛出:
  java.lang.module.ResolutionException: Module com.sun.jna reads another module named com.sun.jna

修复: 移除 jarJar 'net.java.dev.jna:jna:[5.14.0,6)', 改为 compileOnly。
JNA 不再随 mod 发布, 由玩家环境 classloader 解析(已有 mod 提供则复用,
没有则 OpenCLBackend.canExecute() catch(Throwable) 安静回退到 CPU,
围棋 AI 主流程不受影响)。

产物: Game Console-1.0.0-NeoForge-1.21.1-beta5.jar (918K, 较 beta4 的 2.8M
下降 67%, 即移除 1.9M 的 jna 内嵌体积)。
…d/pass 锁

1. GoAdversarialTrainer:301 — KataGo 执黑认输时 blackValue 按我方颜色正确取 ±1.0,修复训练梯度反向
2. GoGameScreen:197 — 终局贴目 3.75 → 7.5(两侧原始目数等效贴目减半)
3. KataGoGoAI + GoAdversarialTrainer — pb.redirectError(INHERIT) 防止 stderr 缓冲写满挂死引擎
4. MCTSGoAI:544 — worker 循环加 Thread.interrupted() 检查,让 cancel(true) 真正生效
5. GoGameScreen — AI 模式行棋方为 AI 时拒绝玩家代落子/代虚着
6. MCTSGoAI expand — 有界自旋等待 policyCache(forwardInFlight 清理加 finally),先验 1.0 兜底
7. KataGoGoAI syncBoard — 任何收缩触发全量重同步,pass 补发 GTP 'play ... pass'
8. GoGame pass()/resign() — 状态变更统一在 stateLock 内,消除与 placeStone 持锁协议不一致
1. GomokuAI — SIZE 改按 board.length 推导,9~19 路任意棋盘尺寸均正常工作(原 9/11/13 路 AIOOBE 卡死)
2. ChessRules pstBonus — PST_xxx[col][r] → [r][col] 修正转置索引,士象位置表恢复正常分
3. ChessGameScreen AI finally — 仅当本线程代数仍是当前代数才清 aiThinking
4. WesternChessScreen alphaBeta 叶子 — hasLegal 标记,伪合法全非法时按被将军返回 MATE 分,非被将军(僵局)返回 0
5. PikafishChessAI — readerExecutor 替换为常驻 daemon 读线程 + LinkedBlockingQueue,readLine 改为 queue.poll(timeout),消除僵尸任务吞行
6. ChessGameScreen/WesternChessScreen onRemoteMove — LAN 远程走法校验回合归属+棋子归属+合法走法列表,失败丢弃并 WARN
7. WesternChessScreen initBoard — positionKeys 预置初始局面,三次重复判定少一拍
8. WesternChessScreen 搜索内易位权 — pseudoMoves/addMoves/castleMoves 贯穿节点级 cf,搜索深处不再生成非法易位
1. MazeGameScreen — '重新开始'按钮先按 levelMazeSize() 同步尺寸再 generateMaze(),第 2+ 关重开出口不再落在可达区外
2. BlackHoleGameScreen — initGame() 末尾设 gameState=PLAYING,R 键重开不再卡结算画面
3. SokobanScreen — 打乱阶段加死角校验重试 + loadLevel() 混入 nanoTime 盐,R 键可生成不同布局
4. PianoTilesGameScreen — startGame() 补全 score/combo/判定统计重置(原只重置 noteIndex/activeTiles)
5. PianoTilesGameScreen — 3-2-1 倒计时加 !showExitConfirm && !songSelectMode 守卫,弹窗/选歌期间冻结
6. SnakeGameScreen — 新增 lastDx/lastDy 同 tick 防反检查,连按两方向键不再 180° 掉头
7. MouseTunnelGameScreen — init() 开头 clearWidgets(),playing 时新按钮 visible=false
8. TowerDefenseScreen — mouseClicked 塔放置分支加 gameOver/!gameStarted 守卫
9. IceFireGameScreen — init() LAN 启动改 session==null 守卫,缩放不再重置
10. IceFire/ColorChase/Minecraft2D/Platformer/Jump — tick() 内 isWindowActive 探针清按键/蓄力(Screen 基类无 windowFocusChanged 钩子)
11. TetrisGameScreen/PlatformerScreen — 粒子拆为 tick()+render() 分别调用 tickParticles/renderParticles
12. Minecraft2DScreen — 菜单态 ESC 拦截回 GameSelectorScreen;Platformer/IceFire emoji 替换
…AI 翅膀/设置容错

1. ModNetworks — versioned('1.1.0') → '1.2.0',INVITE_CANCELLED/PLAYER_QUIT 追加后升版防混布踢线
2. MultiplayerLobbyScreen — INVITE_CANCELLED 增加对非大厅界面兜底(接受后切到对局界面的候选者收到通知)
3. MultiplayerLobbyScreen — 新增 onPeerQuit(UUID) 移除 selectedLanPeers + 提前终止等待,共享 terminateWaiting 公共方法
4. MultiplayerLobbyScreen — GAME_SELECT 列表分页 7 张/页 + mouseScrolled/PageUp/PageDown 翻页,1080p 4x 缩放全部可达
5. GameSelectorScreen — FileDialog 创建与 setVisible 移至 daemon 后台线程,选中后 mc.execute 回主线程导入
6. LandlordGameScreen — STATE 分支补 Arrays.fill(cardSelected,false)
7. AIPlayer — 三带翅膀优先 size==1/==2 精确组,永不从 size==4(炸弹)拆
8. GameSettings — JSON 损坏时 loaded=true 锁定默认配置,不再每帧重读盘
- 围棋 removed/onClose 统一清理 worker、棋局与原生资源,LAN 不启动 KataGo
- 修正围棋数目 BFS 空区与边界棋子归属
- 象棋 AI 生命周期串行化,修复困毙、三次重复和棋与 LAN 走法校验
- 斗地主状态报文完整校验,飞机牌型分离比较并支持 AI 带翅膀
- 修复本地人机/双人模式、邀请 ESC 拒绝、LAN 座位映射与积分累加
- 修复棋盘负坐标命中和未处理按键吞事件
- 修复窗口缩放、重开、粒子、输入焦点等状态问题
围棋引擎:
- MCTS 候选生成/提子/增量哈希/打分融合与热路径原语化(ThreadLocal 零分配), 每迭代耗时降低 47-61%, 行为快照与 HEAD 逐字节一致
- NeuralEvaluator.save Windows 并发替换 AccessDeniedException 指数退避修复
- GoGame 暴露纯规则盘面 API(xorStone/快照/计分协议), 供搜索与联机复用

压测回归(新增单测):
- 象棋差分/UCI 往返/AI 自对弈合法性, 井字棋全博弈树黄金数, 斗地主牌型属性+2000 局全局模拟, 五子棋 AI 自对弈
- 围棋差分 fuzz/树不变量/并发/持久化回归

其他:
- 多游戏屏(钢琴/冰火人/国际象棋/五子棋/打地鼠等)与联机大厅、网络层更新
- GameSettings/ExternalFileManager 容错增强
- .gitignore 增补 /.bench/ 压测工作目录
gValueB2 += dValue;

// ── 策略头 ──────────────────────────────────────────────
double[] dLogit = new double[POLICY_SIZE];

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: GPU path allocates large intermediate arrays on every trainMiniBatch call

The batchPass0Forward method creates bSubIn [batchSize][9][9][36], bSubZ [batchSize][9][9][16], bBlkIn [batchSize][9][144], bBlkZ [batchSize][9][64], bTopIn [batchSize][600], bShared [batchSize][256], bShZ [batchSize][256], bPolicyOut [batchSize][362], bValueOut [batchSize] as new arrays every invocation. For batchSize=32 this is ~200KB+ per array, causing significant GC pressure during training loops. Consider reusing buffers or pooling.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

for (int s = 0; s < SUBS_PER_BLOCK; s++) {
for (int h = 0; h < SUB_HIDDEN; h++) {
double dSub = dBlkIn[s * SUB_HIDDEN + h] * (subZ[b][s][h] > 0 ? 1 : 0);
gSubB[b][h] += dSub;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: Gradient norm NaN check comment slightly misleading

Comment says "NaN 与裁剪阈值比较恒为 false" but the code correctly checks !Double.isFinite(norm) before the clipping comparison and returns early. The current logic is correct (NaN gradients are skipped), but the comment implies the comparison would silently pass NaN through, which it doesn't. Suggest updating comment to clarify the early return prevents NaN propagation.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

// ══════════════════════════════════════════════════════════════════════

private static class EyeInfo { boolean isTrue, isPotential; }

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: readFinite promotes float to double for NEV3 format, losing precision silently

NEV3 format stores weights as 4-byte floats. readFinite reads them as float then promotes to double. The Double.isFinite(value) check passes (since finite floats promote to finite doubles), but precision is already lost. This is intentional for NEV3 compatibility, but worth documenting that NEV3 checkpoints have ~7 decimal digits precision vs NEV2's ~15.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

/**
* 评估走子的气数
*/
private int evaluateMoveLiberties(GoPlayer[][] board, int x, int y, GoPlayer player) {

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: tacticalReading deadline not consistently checked in localAlphaBeta recursion

The tacticalReading method passes deadline to localAlphaBeta, which checks it at the start: if (System.currentTimeMillis() > deadline) return 0;. However, the recursive calls to localAlphaBeta inside the loop don't re-check the deadline before each recursive call - they only check at the next frame's entry. For deep searches (depth 5) with many branches, this could exceed the time budget significantly before returning. Add deadline check before each recursive call or at loop entry.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

double sqrtParentVisits = Math.sqrt(Math.max(parentVisits, 1));

for (MCTSNode child : children) {
double visits;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: findFirstStone/findSecondStone scan entire board on every opening book call

getOpeningBookMove calls findFirstStone and findSecondStone which each scan the full 19x19 board (361 iterations). This is called on every move during the first 30 moves. While 361 iterations is trivial, it's called repeatedly for the same board state. Consider caching the opponent stone positions or computing them once per getBestMove call.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

|| parsedHand.size() > 54 || parsedLastCards.size() > 54 || parsedBottom.size() > 3) {
throw new IllegalArgumentException("invalid card list size");
}
validateStatePhase(parsedState, parsedCurrent, parsedLandlord, parsedLast,

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: applyState validation rejects valid states with duplicate cards in hand

ensureUnique throws if any card appears twice in hand/lastCards/bottomCards. However, the deserialization path deserializeCardsStrict already validates each card's suit/rank combo. If a malicious or buggy sender sends duplicate cards, this correctly rejects it. But the error message "duplicate cards in hand" doesn't distinguish between actual duplicates vs. a card appearing in both hand and lastCards (which validateNoCardOverlap catches separately). The messages could be more specific.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

/**
* 获取 AI 的执棋颜色。
*
* @return AI 执棋颜色

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: readLoop comment says blank lines are enqueued but code skips them

Comment: "空行(GTP 响应块终止符)与引擎日志行全部入队" (blank lines and engine log lines all enqueued). Code: if (line.isBlank()) continue; skips blank lines. Since readResponse only processes lines starting with "=" or "?", skipping blank lines is functionally correct (they're just GTP response terminators). But the comment is wrong. Update comment to match behavior.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


/** 转发限流:每玩家每秒最多包数 */
private static final int FORWARD_RATE_LIMIT = 120;
/** 玩家 → {窗口起始 nanoTime, 窗口内已计数};long[] 复合值避免每包分配两个条目 */

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: Rate limit cleanup only triggers when map size > 512, not time-based

tryAcquireForward only runs cleanup (FORWARD_WINDOWS.entrySet().removeIf) when FORWARD_WINDOWS.size() > 512. If fewer than 512 unique players connect over the server lifetime, stale entries (players who left >10s ago) are never removed, causing a slow memory leak. Consider running cleanup periodically or on every N-th call.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

inner.put(value.getKey(), freezeValue(value.getValue()));
}
}
outer.put(gameId, Collections.unmodifiableMap(inner));

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

SUGGESTION: freezeSettings creates deep immutable copies on every load/import

freezeSettings recursively wraps all Maps/Lists in Collections.unmodifiableXxx and creates new LinkedHashMap/ArrayList instances. For small settings this is fine, but if a mod adds many game configs with large nested structures, this could be expensive. The settings are loaded once at startup and on explicit import, so impact is low. Acceptable but worth noting.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.


static Set<Long> parseMarks(String encoded) {
Set<Long> marks = new LinkedHashSet<>();
if (encoded == null || encoded.isEmpty()) return marks;

Copy link
Copy Markdown

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

WARNING: parseKomi rejects valid numeric representations like "7.50" vs "7.5"

parseKomi parses the input, normalizes it via GoGame.normalizeKomi, then checks Double.toString(normalized).equals(value). This means "7.50" (parsed as 7.5, normalized to 7.5, toString = "7.5") fails because "7.5".equals("7.50") is false. This is overly strict for a network protocol. Consider comparing the parsed double values directly with a tolerance, or accepting any valid double representation.


Reply with @kilocode-bot fix it to have Kilo Code address this issue.

@kilo-code-bot

kilo-code-bot Bot commented Sep 10, 2026

Copy link
Copy Markdown

Code Review Summary

Status: No Issues Found | Recommendation: Merge

Files Reviewed (1 file)
  • src/test/java/com/wzz/game_console/client/screens/games/gogame/MCTSGoAIRegressionTest.java
Previous Review Summary (commit 33fdeb7)

Current summary above is authoritative. Previous snapshots are kept for context only.

Previous review (commit 33fdeb7)

Status: 14 Issues Found | Recommendation: Address before merge

Overview

Severity Count
CRITICAL 1
WARNING 6
SUGGESTION 7
Issue Details (click to expand)

CRITICAL

File Line Issue
src/main/java/com/wzz/game_console/client/screens/games/gogame/GoGame.java 483 canPlaceStone does full simulation with backup/restore - expensive for validation

WARNING

File Line Issue
src/main/java/com/wzz/game_console/client/screens/games/gogame/NeuralEvaluator.java 847 GPU path allocates large intermediate arrays on every trainMiniBatch call
src/main/java/com/wzz/game_console/client/screens/games/gogame/NeuralEvaluator.java 1068 readFinite promotes float to double for NEV3 format, losing precision silently
src/main/java/com/wzz/game_console/client/screens/games/gogame/MCTSGoAI.java 1120 tacticalReading deadline not consistently checked in localAlphaBeta recursion
src/main/java/com/wzz/game_console/client/screens/games/gogame/GoGame.java 395 calcTerritory static and instance methods have same name but different semantics
src/main/java/com/wzz/game_console/client/screens/games/gogame/OpenCLBackend.java 200 batchPass0Forward allocates many large arrays on each call causing GC pressure
src/main/java/com/wzz/game_console/network/MultiplayerGamePacket.java 260 Rate limit cleanup only triggers when map size > 512, not time-based

SUGGESTION

File Line Issue
src/main/java/com/wzz/game_console/client/screens/games/gogame/NeuralEvaluator.java 903 Gradient norm NaN check comment slightly misleading
src/main/java/com/wzz/game_console/client/screens/games/gogame/MCTSGoAI.java 1250 findFirstStone/findSecondStone scan entire board on every opening book call
src/main/java/com/wzz/game_console/client/screens/games/chess/BuiltInChessAI.java 180 nodeCount incremented without volatile/atomic in single-threaded search
src/main/java/com/wzz/game_console/client/screens/games/chess/BuiltInChessAI.java 250 quiescence hard limit ply >= 96 may truncate legitimate deep lines
src/main/java/com/wzz/game_console/client/screens/games/landlord/LandlordGame.java 580 applyState validation rejects valid states with duplicate cards in hand
src/main/java/com/wzz/game_console/client/screens/games/gogame/KataGoGoAI.java 180 readLoop comment says blank lines are enqueued but code skips them
src/main/java/com/wzz/game_console/util/GameSettings.java 150 freezeSettings creates deep immutable copies on every load/import
src/main/java/com/wzz/game_console/client/screens/games/gogame/GoScoringProtocol.java 95 parseKomi rejects valid numeric representations like "7.50" vs "7.5"
Files Reviewed (28 files)
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/MCTSGoAI.java - 2 issues
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/NeuralEvaluator.java - 3 issues
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/GoGame.java - 2 issues
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/OpenCLBackend.java - 1 issue
  • src/main/java/com/wzz/game_console/client/screens/games/chess/BuiltInChessAI.java - 2 issues
  • src/main/java/com/wzz/game_console/client/screens/games/chess/ChessRules.java - 0 issues
  • src/main/java/com/wzz/game_console/client/screens/games/landlord/LandlordGame.java - 1 issue
  • src/main/java/com/wzz/game_console/client/screens/games/landlord/CardPattern.java - 0 issues
  • src/main/java/com/wzz/game_console/network/MultiplayerGamePacket.java - 1 issue
  • src/main/java/com/wzz/game_console/network/MultiplayerGameDataEnvelope.java - 0 issues
  • src/main/java/com/wzz/game_console/network/MultiplayerInviteAttempt.java - 0 issues
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/KataGoGoAI.java - 1 issue
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/GoGameScreen.java - 0 issues
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/GoScoringProtocol.java - 1 issue
  • src/main/java/com/wzz/game_console/util/GameSettings.java - 1 issue
  • src/main/java/com/wzz/game_console/client/screens/games/gogame/GoTrainingMain.java - 0 issues
  • build.gradle - 0 issues

Fix these issues in Kilo Cloud


Reviewed by free · Input: 99.3K · Output: 1.8K · Cached: 77.8K

@Barbatosishere
Barbatosishere merged commit b86ab48 into main Sep 10, 2026
3 checks passed
@Barbatosishere
Barbatosishere deleted the gpu-accel branch September 10, 2026 09:02
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant