From dc17c0f464f47f6e1b33f6bce7df040efb2bb1d9 Mon Sep 17 00:00:00 2001 From: xiaoou Date: Mon, 13 Jul 2026 11:28:45 +0800 Subject: [PATCH] feat: position rotation every 10 games in self-play MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit --mix-rotate: 每10局轮换bot排列 [ISMCTS,ISMCTS,NEURAL] → [NEURAL,ISMCTS,ISMCTS] → [ISMCTS,NEURAL,ISMCTS] Neural 三个位置都练到, 数据分布平衡 orchestrator改用--mix-rotate替换--mix --- hjha-console/Program.cs | 15 +++++++++++++++ scripts/training_orchestrator.py | 2 +- 2 files changed, 16 insertions(+), 1 deletion(-) diff --git a/hjha-console/Program.cs b/hjha-console/Program.cs index 368706f5..8566fade 100644 --- a/hjha-console/Program.cs +++ b/hjha-console/Program.cs @@ -7,10 +7,18 @@ namespace hjha_console { class Program { + public static int RotateInterval = 0; // 0=disabled, N=rotate every N rounds + private static readonly string[][] Rotations = new[] { // 3种排列 + new[] { "ISMCTS", "ISMCTS", "NEURAL" }, + new[] { "NEURAL", "ISMCTS", "ISMCTS" }, + new[] { "ISMCTS", "NEURAL", "ISMCTS" } + }; + static void Main(string[] args) { if (args.Length > 0 && args[0] == "--eval") { PdkGameMain.BotTypes = new[] { "ISMCTS", "ISMCTS", "NEURAL" }; TrainingCollector.Enabled = false; args = new[] { "--stress", args.Length > 1 ? args[1] : "10" }; } if (args.Length > 0 && args[0] == "--mix") { PdkGameMain.BotTypes = new[] { "ISMCTS", "ISMCTS", "NEURAL" }; TrainingCollector.Enabled = true; args = new[] { "--stress", args.Length > 1 ? args[1] : "10" }; } + if (args.Length > 0 && args[0] == "--mix-rotate") { PdkGameMain.BotTypes = new[] { "ISMCTS", "ISMCTS", "NEURAL" }; TrainingCollector.Enabled = true; Program.RotateInterval = 10; args = new[] { "--stress", args.Length > 1 ? args[1] : "10" }; } if (args.Length > 0 && args[0] == "--mix-ismcts") { PdkGameMain.BotTypes = new[] { "ISMCTS", "ISMCTS", "ISMCTS" }; TrainingCollector.Enabled = true; args = new[] { "--stress", args.Length > 1 ? args[1] : "10" }; } if (args.Length > 0 && args[0] == "--bots") { PdkGameMain.BotTypes = args[1].Split(','); TrainingCollector.Enabled = true; args = args.Length > 2 ? new[] { "--stress", args[2] } : new[] { "--stress", "10" }; } if (args.Length > 0 && args[0] == "--stress") @@ -52,6 +60,13 @@ namespace hjha_console for (int r = 1; r <= totalRounds; r++) { + // 位置轮换: 每N局切换排列 + if (RotateInterval > 0 && (r - 1) % RotateInterval == 0) + { + int ri = ((r - 1) / RotateInterval) % Rotations.Length; + PdkGameMain.BotTypes = Rotations[ri]; + } + var roundSw = Stopwatch.StartNew(); try { diff --git a/scripts/training_orchestrator.py b/scripts/training_orchestrator.py index 2317d408..0f31862b 100644 --- a/scripts/training_orchestrator.py +++ b/scripts/training_orchestrator.py @@ -41,7 +41,7 @@ def selfplay(games): env['PATH'] = f"/usr/lib/dotnet:{env.get('PATH','')}" ok, out = run(['/usr/lib/dotnet/dotnet', 'run', '--project', 'hjha-console', '-c', 'Release', - '--', '--mix', str(games)], to=max(36000, games*2)) + '--', '--mix-rotate', str(games)], to=max(36000, games*2)) csv = len(glob.glob(os.path.join(td, 'game_*.csv'))) sf = os.path.join(HJHA_DIR, 'stress_summary.txt')