文件 玩法擴展

玩法模組

方案不只是一個替你打的 AI,也可以是一套規則:你自己在遊戲視窗裡玩,模組負責布置開局、刷怪、給獎勵、在螢幕上提供按鈕和選項卡片、判定勝負。繼承 openwar3.Mod,一個檔案就是一套玩法。

AI 方案 有兩種:kind: bot 是一個 AI,替你打;kind: mod 是一套規則 —— 你自己在遊戲視窗裡玩,模組出題:開局怎麼布置、依時間或事件刷怪、給什麼獎勵、螢幕上提供哪些按鈕和選項卡片、什麼時候算贏。

模組用到的全是現成的能力:介面與輸入(能點的按鈕、卡片、熱鍵、點地面)、畫板(面板、進度條、路線)、JASS 通道(刷單位、改屬性、給物品)、事件流(死亡、升級、放技能、聊天)。

兩個範例

在遠見的「AI 方案」→「內建」裡就能選:

模組玩法用到的能力
英雄 Roguelike builtin/hero-roguelike你只有一個聖騎士,怪物一波波從四面包圍上來;每升一級,螢幕中間三選一強化(選擇時遊戲暫停);撐過 10 波就贏,英雄死了就輸g.ui.choice(可點擊卡片 + 暫停)、hero.levelup / killed / spell.cast 事件、聊天 -help、JASS 改英雄屬性、給物品
無盡守城 builtin/endless-defense怪物從對面出生點沿著地上的紅線衝向主城;每守住一波就給金幣;點螢幕按鈕或按 F7 提前叫下一波,獎勵 ×1.5;按 F8 再用左鍵點地面,放一座免費箭塔(右鍵取消)g.ui.button、g.ui.hotkey、g.ui.mouse(擷取地面點擊)、畫板面板 / 進度條 / 路線、JASS 刷怪和加金幣

兩個範例各 150 行左右,程式碼在 brains/examples/mod_hero_roguelike.py 和 brains/examples/mod_endless_defense.py。

python tools/play.py --bot brains/examples/mod_hero_roguelike.py --inst 9     # 開一局,模組接手,你在遊戲視窗裡玩

寫一個模組

from openwar3 import Mod

class Survive(Mod):
    name = "survive"

    def on_start(self, g):
        super().on_start(g)                        # 單人局檢查 + 壓住電腦對手
        self.foe = self.wave_player(g)             # 用一個空槽位玩家當「刷怪方」:不和任何人結盟、沒有電腦 AI
        self.every(30, self.wave)                  # 每 30 遊戲秒一波(暫停時不計時)
        g.ui.hotkey("F7", lambda g, ev: self.wave(g))

    def wave(self, g):
        self.spawn_ring(g, self.foe, "ugho", 6, self.home(g), 1400, attack_to=self.home(g))

    def on_event(self, g, ev):
        if ev.kind == "unit.died" and ev.type == "htow":
            self.finish("loss", "主城被推倒了")

Mod 在 Bot 的基礎上多了這些:

方法 / 屬性說明
on_start / on_tick / on_event / on_end和 Bot 一樣;覆寫 on_start / on_tick 時記得先呼叫 super()
every(秒, fn, first=) / after(秒, fn)依遊戲時間計時的計時器,回呼是 fn(g)
finish(result, reason)結束這一局('win' / 'loss' / 'unknown'):執行器下一拍停止,螢幕中間畫出結果面板,方案戰績依它記錄
wave_player(g)第一個空槽位玩家,拿來當刷怪方
spawn_ring(g, 玩家, 單位, 個數, 中心, 半徑, attack_to=)在一圈上刷單位,一波幾十個也不卡;回傳 JASS 控制代碼
alive_of(g, 玩家) / attack_move_all(g, 玩家, 點)某個玩家還活著的單位 / 全部攻擊移動過去(每隔幾秒呼叫一次,怪物就會追著走)
home(g) / hud(g, 標題, 行)我方主城的位置 / 右上角的資訊面板
neutralize_ai = True開局把電腦對手壓住:它的單位每 5 秒暫停一次,金幣和木材歸零。對戰地圖裡總有一個電腦,模組自訂規則時不要讓它攪局
single_player_only = True有其他真人玩家就拒絕執行(改動世界的 JASS 會讓別人不同步)
linger_s = 6分出勝負後,在結果畫面停留幾秒再結束

finish() 在 Bot 上也能用:一般 Bot 也可以自己宣布結束。

做成方案、分享

scheme.json 裡寫 "kind": "mod",入口檔案裡定義一個 Mod 的子類別:

{"id": "survive", "name": "堅守 10 波", "kind": "mod", "entry": "survive.py", "class": "Survive"}

模組固定不走公平模式(它是出題的裁判,要看全圖、改動世界),也不依對戰規則判定勝負(勝負由 finish 回報);說明書裡寫了 fair / judge 也不會生效。匯出 zip、匯入、信任、戰績都和 Bot 方案完全一樣,見 AI 方案。模組也是程式碼,別人的模組第一次執行前同樣要確認信任。

實測

2026-09-25,測試實例上:

  • 英雄 Roguelike:第一波刷出來,右上角面板在更新;把英雄提升到 3 級 → 螢幕中間跳出卡片、遊戲時鐘停住;點兩次卡片 → 兩次強化生效(力量 22 → 27),時鐘恢復。
  • 無盡守城:面板、地上的路線、按鈕都在;F8 + 點地面 → 主城旁邊多了一座防禦塔;這一波還沒清完就點按鈕 → 提示「這一波還沒清完」。

邊界

  • 只能用於單人局:刷單位、改屬性走的是 JASS 通道,在多人局裡會不同步。這是鎖步模型決定的,多人玩法要等同步通道(見 路線圖)。
  • 模組看得到全圖 —— 它是出題的,不是玩家。
  • 對戰地圖裡的電腦對手只是被「壓住」,並沒有被移除(移除會觸發對戰規則的勝利判定)。