screeps

game
screeps
moon add Kaida-Amethyst/screeps@0.1.0
Download zip
Version
0.1.0
License
Apache-2.0
Last updated
4 months ago
Downloads
25

Dependencies

README

#Screeps Arena 的 MoonBit Binding

这个项目提供了一套面向 Screeps Arena 的 MoonBit binding,目标是让你用 MoonBit 编写 bot 逻辑,再编译成 JavaScript,接入 Screeps Arena 运行。

目前项目包含:

  • 面向 Screeps Arena 的正式 MoonBit API
  • 一个固定的 main.mjs wrapper,用来补宿主环境 glue
  • 可直接用于 Screeps Arena 的 moonbit-main.mjs + main.mjs 运行流程

#如何使用

#1. 安装包

在你的 MoonBit 项目里执行:

moon add Kaida-Amethyst/screeps

然后确保你的 moon.mod.json 里启用了 JS 目标:

{ ... "preferred-target": "js" }

#2. 添加 main.mjs

把下面这段代码保存成 main.mjs

import { getObjectsByPrototype, createConstructionSite } from "game/utils"; import { ConstructionSite, Creep, Flag, Source, StructureContainer, StructureExtension, StructureRampart, StructureRoad, StructureSpawn, Structure, StructureTower, StructureWall, } from "game/prototypes"; import { loop as moonbitLoop } from "./moonbit-main.mjs"; const prototypeTable = { ConstructionSite, Creep, Flag, Source, StructureContainer, StructureExtension, StructureRampart, StructureRoad, Structure, StructureSpawn, StructureTower, StructureWall, }; globalThis.__moonbit_screeps_host = globalThis.__moonbit_screeps_host ?? {}; globalThis.__moonbit_screeps_host.getObjectsByPrototypeName = (name) => { const prototype = prototypeTable[name]; if (!prototype) { throw new Error(`Unknown Screeps prototype: ${name}`); } return getObjectsByPrototype(prototype); }; globalThis.__moonbit_screeps_host.createConstructionSiteByPrototypeName = ( pos, name, ) => { const prototype = prototypeTable[name]; if (!prototype) { throw new Error(`Unknown Screeps prototype: ${name}`); } return createConstructionSite(pos, prototype); }; export function loop() { moonbitLoop(); }

#3. 编写 MoonBit 逻辑并构建

完成你的 MoonBit bot 逻辑后,执行:

moon build

构建完成后,把生成出来的 JS 和 main.mjs 一起拷贝到 Screeps Arena 实际运行脚本的目录。

例如:

cp _build/js/debug/build/main/main.js /path/to/ScreepsArena/moonbit-main.mjs cp main.mjs /path/to/ScreepsArena/main.mjs

请把上面的 /path/to/ScreepsArena/ 替换成你自己实际运行 main.mjs 的目录。

#4. 在 Screeps Arena 中运行

完成拷贝后,就可以在 Screeps Arena 中加载这两个文件并尝试运行你的 bot。

当前推荐的约定是:

  • moonbit-main.mjs:MoonBit 编译生成的主逻辑
  • main.mjs:宿主环境 wrapper,并对外导出最终 loop

#Tutorial

#1. Loop and import

第一关的目标很简单:调用 get_ticks(),然后用 MoonBit 的 println 打印当前 tick。

这一关需要注意两件事:

  • main 包需要通过 moon.pkg 把 MoonBit 函数导出成 Screeps 需要的 loop
  • main/main.mbt 里的 fn main 需要保持空实现,真正的逻辑放在导出的函数里

#main/moon.pkg

main/moon.pkg 需要像这样配置:

import {
"Kaida-Amethyst/screeps",
}

options(
"is-main": true,
link: { "js": { "exports": [ "main_loop:loop" ] } },
)

这里的意思是:

  • 这个包是一个 is-main
  • MoonBit 里的 main_loop 会被导出成 JavaScript 侧的 loop

#main/main.mbt

然后在 main/main.mbt 里实现:

///|
pub fn main_loop() -> Unit {
println(@screeps.get_ticks())
}

///|
fn main {

}

这里有一个关键点:

  • fn main 保持空实现
  • Screeps 实际调用的是 main_loop

这样可以避免模块加载时就执行额外副作用,把真正的每 tick 逻辑放到导出的 loop 里。

#构建与拷贝

写完之后执行:

moon build

然后把生成的主逻辑和 main.mjs wrapper 一起拷贝到 Screeps Arena 的运行目录:

cp _build/js/debug/build/main/main.js /path/to/ScreepsArena/moonbit-main.mjs cp main.mjs /path/to/ScreepsArena/main.mjs

/path/to/ScreepsArena/ 替换成你自己的实际目录。

完成后,就可以在 Screeps Arena 中加载并运行,效果等价于:

import { getTicks } from "game/utils"; export function loop() { console.log("Current tick:", getTicks()); }

只是这里我们用的是 MoonBit 的:

  • @screeps.get_ticks()
  • println(...)

#2. Simple Move

第二关的目标是:

  • 取出场上的 creep
  • 取出场上的 flag
  • 让第一只 creep 朝第一个 flag 移动

Screeps 的 sample code 是:

import { getObjectsByPrototype } from "game/utils"; import { Creep, Flag } from "game/prototypes"; export function loop() { var creeps = getObjectsByPrototype(Creep); var flags = getObjectsByPrototype(Flag); creeps[0].moveTo(flags[0]); }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
guard @screeps.my_creeps() is [creep, ..] else { return }
guard @screeps.flags() is [flag, ..] else { return }
creep.move_to(flag) |> ignore
}

///|
fn main {

}

代码的意思是:

  • @screeps.my_creeps():拿到己方 creep 列表,注意这里与sample code的区别是,sample code这里实际上得到的全部的creep,而我们这里是得到的所有己方的creep。
  • @screeps.flags():拿到 flag 列表
  • creep.move_to(flag):让 creep 朝 flag 移动

这段 MoonBit 代码里多出来的部分主要是两点:

  • guard ... else { return } 这用来处理“当前没有 creep”或者“当前没有 flag”的情况,避免直接访问空数组。
  • |> ignore move_to 会返回一个动作结果,但这一关我们只关心“发出移动指令”,所以把返回值忽略掉即可。

#3. First Attack

第三关的目标是:

  • 找到一只己方 creep
  • 找到一只敌方 creep
  • 尝试攻击敌方 creep
  • 如果敌人不在攻击范围内,就朝它移动

Screeps 的 sample code 是:

import { getObjectsByPrototype } from "game/utils"; import { Creep } from "game/prototypes"; import { ERR_NOT_IN_RANGE } from "game/constants"; export function loop() { var myCreep = getObjectsByPrototype(Creep).find((creep) => creep.my); var enemyCreep = getObjectsByPrototype(Creep).find((creep) => !creep.my); if (myCreep.attack(enemyCreep) == ERR_NOT_IN_RANGE) { myCreep.moveTo(enemyCreep); } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
guard @screeps.my_creeps() is [my_creep, ..] else { return }
guard @screeps.enemy_creeps() is [enemy_creep, ..] else { return }
my_creep.attack_or_move(enemy_creep)
}

///|
fn main {

}

这里和原始 JS sample 的对应关系是:

  • @screeps.my_creeps():拿到己方 creep 列表
  • @screeps.enemy_creeps():拿到敌方 creep 列表
  • my_creep.attack_or_move(enemy_creep):先尝试攻击;如果不在范围内,就自动移动过去

和第二关相比,这一关的重点是:

  • 我们不再直接自己匹配 ERR_NOT_IN_RANGE
  • 而是使用库里已经提供好的 convenience helper:attack_or_move

它把这段常见逻辑收起来了:

  • 先调用 attack
  • 如果结果是 NotInRange
  • 再补一个 move_to

所以主循环里看到的代码会更短,也更接近“我要做什么”这层意图。

#4. Creep Bodies

第四关的目标是:

  • 找到所有己方 creep
  • 找到一只敌方 creep
  • 根据 creep 身上的 body part,不同职责地执行动作
    • ATTACK 的 creep 负责近战攻击
    • RANGED_ATTACK 的 creep 负责远程攻击
    • HEAL 的 creep 负责治疗己方伤员

Screeps 的 sample code 是:

import { getObjectsByPrototype } from "game/utils"; import { Creep } from "game/prototypes"; import { ERR_NOT_IN_RANGE, ATTACK, RANGED_ATTACK, HEAL } from "game/constants"; export function loop() { var myCreeps = getObjectsByPrototype(Creep).filter((creep) => creep.my); var enemyCreep = getObjectsByPrototype(Creep).find((creep) => !creep.my); for (var creep of myCreeps) { if (creep.body.some((bodyPart) => bodyPart.type == ATTACK)) { if (creep.attack(enemyCreep) == ERR_NOT_IN_RANGE) { creep.moveTo(enemyCreep); } } if (creep.body.some((bodyPart) => bodyPart.type == RANGED_ATTACK)) { if (creep.rangedAttack(enemyCreep) == ERR_NOT_IN_RANGE) { creep.moveTo(enemyCreep); } } if (creep.body.some((bodyPart) => bodyPart.type == HEAL)) { var myDamagedCreeps = myCreeps.filter((i) => i.hits < i.hitsMax); if (myDamagedCreeps.length > 0) { if (creep.heal(myDamagedCreeps[0]) == ERR_NOT_IN_RANGE) { creep.moveTo(myDamagedCreeps[0]); } } } } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
let my_creeps = @screeps.my_creeps()
guard @screeps.enemy_creeps() is [enemy_creep, ..] else { return }
let damaged_creeps = my_creeps.filter(creep => creep.hp() < creep.max_hp())
let melee_creeps = my_creeps.filter(creep => {
creep.has_body_part(@screeps.Attack)
})
let healers = my_creeps.filter(creep => creep.has_body_part(@screeps.Heal))
let ranged_creeps = my_creeps.filter(creep => {
creep.has_body_part(@screeps.RangedAttack)
})

for creep in melee_creeps {
creep.attack_or_move(enemy_creep)
}

for creep in ranged_creeps {
creep.ranged_attack_or_move(enemy_creep)
}

if damaged_creeps is [damaged_creep, ..] {
for creep in healers {
creep.heal_or_move(damaged_creep)
}
}
}

///|
fn main {

}

这段 MoonBit 代码的结构和 sample code 是一致的,只是写法更偏 MoonBit 风格:

  • my_creeps.filter(creep => creep.has_body_part(@screeps.Attack)) 对应 JS 里的 creep.body.some(bodyPart => bodyPart.type == ATTACK)
  • creep.attack_or_move(enemy_creep) 对应 “先攻击,不在范围内就移动”
  • creep.ranged_attack_or_move(enemy_creep) 对应 “先远程攻击,不在范围内就移动”
  • creep.heal_or_move(damaged_creep) 对应 “先治疗,不在范围内就移动”

这一关有两个比较关键的点:

  • body part 在正式 binding 里已经被收成了 BodyPartKind,所以这里直接用 @screeps.Attack / Heal / RangedAttack
  • 代码结构上按职责拆成了三段循环:
    • melee_creeps
    • ranged_creeps
    • healers

这样会比“单个大循环里套很多 if”更清楚,也更适合后面继续扩展 bot 行为。

#5. Store and transfer

第五关的目标是:

  • 先检查塔里的能量够不够
  • 如果塔的能量不足,就让己方 creep 去补能量
  • 如果 creep 自己没有能量,就先去 container 取能量
  • 如果塔的能量已经够了,就让塔攻击敌方 creep

Screeps 的 sample code 是:

import { prototypes, utils, constants } from "game"; export function loop() { const tower = utils.getObjectsByPrototype(prototypes.StructureTower)[0]; if (tower.store[constants.RESOURCE_ENERGY] < 10) { var myCreep = utils .getObjectsByPrototype(prototypes.Creep) .find((creep) => creep.my); if (myCreep.store[constants.RESOURCE_ENERGY] == 0) { var container = utils.getObjectsByPrototype(prototypes.StructureContainer)[0]; myCreep.withdraw(container, constants.RESOURCE_ENERGY); } else { myCreep.transfer(tower, constants.RESOURCE_ENERGY); } } else { var target = utils .getObjectsByPrototype(prototypes.Creep) .find((creep) => !creep.my); tower.attack(target); } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
guard @screeps.my_towers() is [tower, ..] else { return }
guard @screeps.my_creeps() is [my_creep, ..] else { return }
guard @screeps.containers() is [container, ..] else { return }
guard @screeps.enemy_creeps() is [target, ..] else { return }

if tower.store().energy() >= 10 {
tower.attack(target) |> ignore
return
}

match my_creep.store().energy() {
0 => my_creep.withdraw_energy_or_move(container)
_ => my_creep.transfer_energy_or_move(tower)
}
}

///|
fn main {

}

这段 MoonBit 代码对应的逻辑是:

  • @screeps.my_towers():拿到己方 tower
  • tower.store().energy():读取 tower 当前储存的能量
  • @screeps.my_creeps():拿到己方 creep
  • @screeps.containers():拿到 container
  • @screeps.enemy_creeps():拿到敌方 creep,作为 tower 的攻击目标

主循环的判断顺序是:

  • 如果 tower.store().energy() >= 10 说明塔的能量已经够了,这时直接让塔攻击敌人,然后 return
  • 否则说明塔还缺能量,需要让 creep 参与补给
  • 如果 my_creep.store().energy()0 就说明 creep 身上没能量,需要先去 container 取能量
  • 如果不为 0 就说明 creep 身上已经带着能量,可以直接把能量送给 tower

这里有两个地方和原始 JS sample 相比更偏 MoonBit 风格:

  • store[RESOURCE_ENERGY] 被整理成了 store().energy()
  • withdraw(...) / transfer(...) 再加上“如果不在范围内就移动”的逻辑,被整理成了:
    • withdraw_energy_or_move(container)
    • transfer_energy_or_move(tower)

这样主循环里保留的是“这一 tick 打算做什么”,而不是把每个动作的细节都展开写一遍。

#6. Terrain

第六关的目标是:

  • 取出所有己方 creep
  • 取出所有 flag
  • 对每一只 creep,都找到一面按路径距离最近的 flag
  • 然后让 creep 朝那面 flag 移动

Screeps 的 sample code 是:

import { getObjectsByPrototype } from "game/utils"; import { Creep, Flag } from "game/prototypes"; export function loop() { var creeps = getObjectsByPrototype(Creep).filter((i) => i.my); var flags = getObjectsByPrototype(Flag); for (var creep of creeps) { var flag = creep.findClosestByPath(flags); creep.moveTo(flag); } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
let flags = @screeps.flags()
for creep in @screeps.my_creeps() {
guard creep.find_closest(flags) is Some(flag) else { continue }
creep.move_to(flag) |> ignore
}
}

///|
fn main {

}

这段 MoonBit 代码和 sample code 的对应关系是:

  • @screeps.my_creeps():拿到所有己方 creep
  • @screeps.flags():拿到所有 flag
  • creep.find_closest(flags):从这组 flag 里,找出对当前 creep 来说最近的目标
  • creep.move_to(flag) |> ignore:让 creep 朝找到的 flag 移动

这一关最关键的点是 find_closest

  • 它对应 JS 里的 findClosestByPath
  • 默认使用的是 Path 这套距离度量
  • 所以这里不用额外写 by=Path

如果以后你想按直线距离来找最近目标,也可以显式写成:

creep.find_closest(flags, by=Range)

但这一关和原始 sample code 对应的,就是默认的按路径寻找最近目标。

另外,这里用了:

  • guard creep.find_closest(flags) is Some(flag) else { continue }

意思是:

  • 如果这一只 creep 能找到最近的 flag,就继续执行移动
  • 如果当前没有可用的 flag,就跳过这一只 creep,处理下一只

这样可以避免直接对空结果调用 move_to

#7. Spawn creeps

第七关的目标是:

  • 先拿到己方的 spawn
  • 拿到场上的 flags
  • 如果当前 creep 数量还不够,就继续 spawn 新 creep
  • 已经出生的 creep 按顺序走向对应的 flag

Screeps 的 sample code 是:

import { getObjectsByPrototype } from "game/utils"; import { Creep, Flag, StructureSpawn } from "game/prototypes"; import { MOVE } from "game/constants"; var creep1, creep2; export function loop() { var mySpawn = getObjectsByPrototype(StructureSpawn)[0]; var flags = getObjectsByPrototype(Flag); if (!creep1) { creep1 = mySpawn.spawnCreep([MOVE]).object; } else { creep1.moveTo(flags[0]); if (!creep2) { creep2 = mySpawn.spawnCreep([MOVE]).object; } else { creep2.moveTo(flags[1]); } } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
guard @screeps.my_spawns() is [my_spawn, ..] else { return }

let flags = @screeps.flags()
let creeps = @screeps.my_creeps()

let num_of_flags = flags.length()
let num_of_creeps = creeps.length()

if num_of_creeps < num_of_flags {
my_spawn.spawn_creep([Move]) |> ignore
}

for i in 0..<min(num_of_creeps, num_of_flags) {
creeps[i].move_to(flags[i]) |> ignore
}
}

///|
fn min(a : Int, b : Int) -> Int {
match a < b {
true => a
false => b
}
}

///|
fn main {

}

这段 MoonBit 代码和 sample code 的核心逻辑是一致的,只是写法更通用:

  • @screeps.my_spawns():拿到己方 spawn
  • @screeps.flags():拿到所有 flag
  • @screeps.my_creeps():拿到已经出生的所有己方 creep
  • my_spawn.spawn_creep([Move]) |> ignore:生成一个只带 MOVE body part 的 creep

这版代码没有像 sample code 那样显式维护 creep1creep2 两个变量,而是换成了更通用的写法:

  • 如果 num_of_creeps < num_of_flags 就说明当前 creep 数量还不够,需要继续 spawn
  • 然后用 for i in 0..<min(num_of_creeps, num_of_flags) 把已经存在的 creep 和 flags 按顺序配对

所以这里的含义就是:

  • 0 个 creep 去第 0 个 flag
  • 1 个 creep 去第 1 个 flag
  • 以此类推

这种写法比直接写死 creep1 / creep2 更适合后面继续扩展,也更接近真正 bot 代码里常见的“按集合和索引分配目标”的写法。

#8. Harvest energy

第八关的目标是:

  • 找到一只己方 creep
  • 找到一个 source
  • 找到己方 spawn
  • 如果 creep 还有空余容量,就去采集能量
  • 如果 creep 已经装满了,就把能量送回 spawn

Screeps 的 sample code 是:

import { prototypes, utils, constants } from "game"; export function loop() { var creep = utils.getObjectsByPrototype(prototypes.Creep).find((i) => i.my); var source = utils.getObjectsByPrototype(prototypes.Source)[0]; var spawn = utils .getObjectsByPrototype(prototypes.StructureSpawn) .find((i) => i.my); if (creep.store.getFreeCapacity(constants.RESOURCE_ENERGY)) { if (creep.harvest(source) == constants.ERR_NOT_IN_RANGE) { creep.moveTo(source); } } else { if (creep.transfer(spawn, constants.RESOURCE_ENERGY) == constants.ERR_NOT_IN_RANGE) { creep.moveTo(spawn); } } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
guard @screeps.my_creeps() is [creep, ..] else { return }
guard @screeps.sources() is [source, ..] else { return }
guard @screeps.my_spawns() is [spawn, ..] else { return }

match creep.store().free_energy() {
0 => creep.transfer_energy_or_move(spawn)
_ => creep.harvest_or_move(source)
}
}

///|
fn main {

}

这段 MoonBit 代码和 sample code 的对应关系是:

  • @screeps.my_creeps():拿到己方 creep
  • @screeps.sources():拿到 source
  • @screeps.my_spawns():拿到己方 spawn
  • creep.store().free_energy():读取 creep 还剩多少能量容量

这里的 match 逻辑可以直接理解成:

  • 0 表示 creep 已经没有空余容量了,这时应该把能量送回 spawn
  • _ 表示 creep 还有空位,这时继续去 source 采集能量

对应的动作分别是:

  • creep.transfer_energy_or_move(spawn)
  • creep.harvest_or_move(source)

这两个 helper 做的事情和前几关是一致的:

  • 先尝试执行动作
  • 如果目标不在范围内,就自动移动过去

所以这一关的主循环写出来会非常短,重点只剩下“当前该采集,还是该回送”这个判断。

#9. Construction

第九关的目标是:

  • 找到一只己方 creep
  • 如果 creep 身上没有能量,就去最近的 container 取能量
  • 如果 creep 身上有能量,就寻找己方 construction site
  • 如果还没有 construction site,就先创建一个 tower 的工地
  • 如果已经有工地,就去建造它

Screeps 的 sample code 是:

import { prototypes, utils } from "game"; import { RESOURCE_ENERGY, ERR_NOT_IN_RANGE } from "game/constants"; export function loop() { const creep = utils.getObjectsByPrototype(prototypes.Creep).find((i) => i.my); if (!creep.store[RESOURCE_ENERGY]) { const container = utils.findClosestByPath( creep, utils.getObjectsByPrototype(prototypes.StructureContainer), ); if (creep.withdraw(container, RESOURCE_ENERGY) == ERR_NOT_IN_RANGE) { creep.moveTo(container); } } else { const constructionSite = utils .getObjectsByPrototype(prototypes.ConstructionSite) .find((i) => i.my); if (!constructionSite) { utils.createConstructionSite(50, 55, prototypes.StructureTower); } else { if (creep.build(constructionSite) == ERR_NOT_IN_RANGE) { creep.moveTo(constructionSite); } } } }

用现在这套 MoonBit binding,可以写成:

///|
pub fn main_loop() -> Unit {
guard @screeps.my_creeps() is [creep, ..] else { return }
let containers = @screeps.containers()

if creep.store().energy() == 0 {
if creep.find_closest(containers) is Some(container) {
creep.withdraw_energy_or_move(container) |> ignore
}
return
}

match @screeps.my_construction_sites() {
[construction_site, ..] => creep.build_or_move(construction_site)
_ => @screeps.create_construction_site(50, 55, Tower) |> ignore
}
}

///|
fn main {

}

这段 MoonBit 代码和 sample code 的对应关系是:

  • @screeps.my_creeps():拿到己方 creep
  • @screeps.containers():拿到所有 container
  • creep.find_closest(containers):找到对当前 creep 来说最近的 container
  • creep.withdraw_energy_or_move(container):先尝试取能量,不在范围内就移动过去
  • @screeps.my_construction_sites():拿到己方 construction site
  • creep.build_or_move(construction_site):先尝试建造,不在范围内就移动过去
  • @screeps.create_construction_site(50, 55, Tower):在指定坐标创建一个 tower 工地

这关的主流程可以拆成两段:

  • 第一段先判断 creep 身上有没有能量
  • 第二段再决定是“创建工地”还是“建造已有工地”

具体来说:

  • 如果 creep.store().energy() == 0 就说明现在要先补充能量
  • 这时通过 creep.find_closest(containers) 找到最近的 container
  • 找到之后调用 withdraw_energy_or_move(container),把“取能量或移动过去”这层逻辑收起来

如果 creep 身上已经有能量,那么就进入建造阶段:

  • 如果 @screeps.my_construction_sites() 里已经有工地 就直接 build_or_move
  • 如果还没有工地 就调用 create_construction_site(50, 55, Tower) 先放下一个 tower 工地

这一关和前面几关相比,多了两个关键点:

  • 最近目标查询不只是能用于找 flag,也可以直接用来找最近的 container
  • create_construction_site(...) 这类创建型操作,也已经被正式 binding 收成了高层接口

所以这关本质上是在把“找资源 -> 建工地 -> 施工”这条基础建造链路串起来。

#10. Final test

最后一关没有单独的 sample code,更像是把前面几关的能力拼起来,写出一个能真正活下来的小 bot。

这一关当前直接使用 main/main.mbt 里的实现:

///|
using @screeps {
type BodyPartKind,
type MyCreep,
type EnemyCreep,
type Source,
type MySpawn,
}

///|
let worker_body : Array[BodyPartKind] = [Work, Carry, Move]

///|
let light_fighter_body : Array[BodyPartKind] = [Attack, Move]

///|
let heavy_fighter_body : Array[BodyPartKind] = [Attack, Attack, Move, Move]

///|
fn is_worker(creep : MyCreep) -> Bool {
creep.store().capacity(@screeps.Energy) > 0
}

///|
fn workers(creeps : Array[MyCreep]) -> Array[MyCreep] {
creeps.filter(is_worker)
}

///|
fn fighters(creeps : Array[MyCreep]) -> Array[MyCreep] {
creeps.filter(creep => !is_worker(creep))
}

///|
fn worker_action(
creep : MyCreep,
sources : Array[Source],
spawn : MySpawn,
) -> Unit {
if creep.store().free_energy() > 0 {
guard creep.find_closest(sources, by=Range) is Some(source) else { return }
creep.harvest_or_move(source)
} else {
creep.transfer_energy_or_move(spawn)
}
}

///|
fn fighter_action(creep : MyCreep, enemies : Array[EnemyCreep]) -> Unit {
guard creep.find_closest(enemies, by=Range) is Some(enemy) else { return }
creep.attack_or_move(enemy)
}

///|
fn spawn_worker_if_possible(spawn : MySpawn) -> Unit {
ignore(spawn.spawn_creep(worker_body))
}

///|
fn spawn_fighter_if_possible(spawn : MySpawn) -> Unit {
let heavy_result = spawn.spawn_creep(heavy_fighter_body)
match heavy_result {
Spawned(_) => ()
SpawnFailed(SpawnNotEnoughEnergy) =>
spawn.spawn_creep(light_fighter_body) |> ignore
SpawnFailed(_) => ()
}
}

///|
enum SpawnRole {
Worker
Fighter
}

///|
fn next_spawn_role(my_creeps : Array[MyCreep]) -> SpawnRole {
let worker_count = workers(my_creeps).length()
let fighter_count = fighters(my_creeps).length()
if worker_count == 0 {
Worker
} else if fighter_count == 0 {
Fighter
} else if worker_count < 2 {
Worker
} else {
Fighter
}
}

///|
fn spawn_action(spawn : MySpawn, my_creeps : Array[MyCreep]) -> Unit {
match next_spawn_role(my_creeps) {
Worker => spawn_worker_if_possible(spawn)
Fighter => spawn_fighter_if_possible(spawn)
}
}

///|
fn fallback_sources() -> Array[Source] {
let live_sources = @screeps.active_sources()

match live_sources.is_empty() {
true => @screeps.sources()
false => live_sources
}
}

///|
pub fn main_loop() -> Unit {
guard @screeps.my_spawns() is [spawn, ..] else { return }
let my_creeps = @screeps.my_creeps()
let enemies = @screeps.enemy_creeps()
let sources = fallback_sources()
spawn_action(spawn, my_creeps)
workers(my_creeps).each(creep => worker_action(creep, sources, spawn))
fighters(my_creeps).each(creep => fighter_action(creep, enemies))
}

///|
fn main {

}

这一版 final test 的思路很直接:把我方单位分成两类。

  • worker 负责采矿和回送能量
  • fighter 负责找最近的敌人并追上去攻击

对应的 body 也分成了三种:

  • worker_body = [Work, Carry, Move]
  • light_fighter_body = [Attack, Move]
  • heavy_fighter_body = [Attack, Attack, Move, Move]

其中 workerfighter 的区分方式也很简单:

  • 如果一个 creep 的 store().capacity(Energy) > 0 就把它当成 worker
  • 否则就把它当成 fighter

也就是说,这里不是额外记录“职业标签”,而是直接根据 body 结构来判断单位职责。

worker_action 负责经济循环:

  • 如果 creep 身上还有空余容量 就找最近的 source,然后 harvest_or_move
  • 如果已经装满 就把能量送回 spawn,调用 transfer_energy_or_move

这里特意用了:

  • creep.find_closest(sources, by=Range)

也就是按直线距离找最近的 source。 这样写的原因很简单:这一关里 source 选择主要只是为了快速找到一个最近资源点,按 Range 就够了。

fighter_action 则更简单:

  • 找最近的敌人
  • attack_or_move

同样,这里也用了 by=Range,让 fighter 先锁定一个最近敌人,然后一路追过去。

spawn 的逻辑是这关最核心的策略部分。这里先定义了:

  • SpawnRole = Worker | Fighter

然后通过 next_spawn_role 来决定下一个应该补什么单位。

规则是:

  • 如果还没有 worker,先补 worker
  • 如果还没有 fighter,先补 fighter
  • 如果 worker 少于 2,继续补 worker
  • 其余情况补 fighter

这背后的想法是:

  • 先确保经济能运转
  • 再确保有基本战斗力
  • 然后维持一个比较朴素的“2 个 worker + 持续补 fighter”的节奏

spawn_fighter_if_possible 里还多了一层小策略:

  • 先尝试生成 heavy_fighter_body
  • 如果失败原因是 SpawnNotEnoughEnergy 就退一步生成 light_fighter_body

这样做的好处是:

  • 能量够的时候,尽量上更强的近战单位
  • 能量暂时不够的时候,也不会什么都不做,而是先出一个轻量 fighter

最后的 main_loop 就比较清楚了:

  • 先拿到 spawn
  • 再拿到当前所有己方 creep、敌方 creep、可用 source
  • 先执行一次 spawn_action
  • 然后让所有 worker 跑经济逻辑
  • 所有 fighter 跑战斗逻辑

也就是说,这个 final test 本质上是把前面几关学到的这些能力全部串起来:

  • spawn_creep
  • harvest_or_move
  • transfer_energy_or_move
  • find_closest
  • attack_or_move

最后得到一个能自己出兵、自己采矿、自己打人的最小可用 bot。

#
AttackTarget

pub(open) trait AttackTarget : GameObjectLike {
as_attack_target(Self) -> GameObject
}

近战攻击目标。

#
BuildTarget

pub(open) trait BuildTarget {
as_build_target(Self) -> ConstructionSite
}

建造目标。

#
GameObjectLike

pub(open) trait GameObjectLike {
as_game_object(Self) -> GameObject
id(Self) -> String
x(Self) -> Int
y(Self) -> Int
exists(Self) -> Bool
}

所有可作为游戏对象观察视图的类型都应满足这一层最小能力。

#
HarvestTarget

pub(open) trait HarvestTarget {
as_harvest_target(Self) -> Source
}

采集目标。

#
HasHits

pub(open) trait HasHits {
hits(Self) -> Int
hits_max(Self) -> Int
}

带有 hits / hits_max 语义的对象应实现这一 trait。

#
HasStore

pub(open) trait HasStore {
store(Self) -> Store
}

带有 Store 的对象应实现这一 trait。

#
HealTarget

pub(open) trait HealTarget : GameObjectLike {
as_heal_target(Self) -> GameObject
}

治疗目标。

#
MoveTarget

pub(open) trait MoveTarget : GameObjectLike {
as_move_target(Self) -> GameObject
}

Move 的目标对象。

#
MyLike

pub(open) trait MyLike {
relation(Self) -> Relation
is_my(Self) -> Bool
is_enemy(Self) -> Bool
}

带有所有权关系语义的对象应实现这一 trait。

#
RangedAttackTarget

pub(open) trait RangedAttackTarget : GameObjectLike {
as_ranged_attack_target(Self) -> GameObject
}

远程攻击目标。

#
TowerAttackTarget

pub(open) trait TowerAttackTarget : GameObjectLike {
as_tower_attack_target(Self) -> GameObject
}

Tower 的攻击目标。

#
TransferTarget

pub(open) trait TransferTarget : GameObjectLike {
as_transfer_target(Self) -> GameObject
}

转移资源目标。

#
WithdrawTarget

pub(open) trait WithdrawTarget : GameObjectLike {
as_withdraw_target(Self) -> GameObject
}

提取资源目标。

#
ActionFailure

pub(all) enum ActionFailure {
NotOwner
Busy
NotEnoughEnergy
InvalidTarget
Full
NotInRange
InvalidArgs
Tired
NoBodyPart
UnknownRawError(Int)
} derive(Eq, Show)

Screeps 普通动作失败原因在第一阶段统一映射到共享类型。

#
ActionResult

pub(all) enum ActionResult {
Success
Failed(ActionFailure)
} derive(Eq, Show)

Screeps 普通动作在第一阶段统一映射到共享结果类型。

#
BodyPart

pub struct BodyPart {
// private fields
}

creep 身上的一个 body part 视图。

#
BodyPart::create

从 raw body part 构造高层视图。

#
BodyPart::hits

fn BodyPart::hits(self : BodyPart) -> Int

返回该 body part 当前剩余的生命值。

#
BodyPart::kind

fn BodyPart::kind(self : BodyPart) -> BodyPartKind

返回 body part 的种类。

#
BodyPartKind

pub(all) enum BodyPartKind {
Move
Work
Carry
Attack
RangedAttack
Heal
Tough
} derive(Compare, Eq, Show)

正式 API 中使用枚举表达 body part,而不是直接暴露原始字符串。

#
BodyPartKind::to_raw

fn BodyPartKind::to_raw(self : BodyPartKind) -> String

转换为 raw 层使用的原始 body part 字符串。

#
ClosestMetric

pub(all) enum ClosestMetric {
Path
Range
} derive(Compare, Eq, Show)

指定“最近”查询使用路径距离还是线性距离。

#
ConstructionSite

pub struct ConstructionSite {
// private fields
}

ConstructionSite 的通用观察视图。

#
ConstructionSite::as_game_object

fn ConstructionSite::as_game_object(self : ConstructionSite) -> GameObject

将 construction site 转成通用 GameObject 视图。

#
ConstructionSite::create

从 raw construction site 构造高层视图。通常下游无需直接调用。

#
ConstructionSite::exists

fn ConstructionSite::exists(self : ConstructionSite) -> Bool

返回工地当前是否仍存在于场上。

#
ConstructionSite::find_closest

fn[T : GameObjectLike] ConstructionSite::find_closest(self : ConstructionSite, candidates : Array[T], by? : ClosestMetric) -> T?

从当前工地出发,按指定度量寻找最近目标。

#
ConstructionSite::find_in_range

fn[T : GameObjectLike] ConstructionSite::find_in_range(self : ConstructionSite, candidates : Array[T], range : Int) -> Array[T]

返回当前工地周围指定范围内的全部目标。

#
ConstructionSite::id

fn ConstructionSite::id(self : ConstructionSite) -> String

返回工地的唯一 id。

#
ConstructionSite::is_enemy

fn ConstructionSite::is_enemy(self : ConstructionSite) -> Bool

返回该工地是否属于敌方。

#
ConstructionSite::is_my

fn ConstructionSite::is_my(self : ConstructionSite) -> Bool

返回该工地是否属于己方。

#
ConstructionSite::progress

fn ConstructionSite::progress(self : ConstructionSite) -> Int

返回工地当前建造进度。

#
ConstructionSite::progress_total

fn ConstructionSite::progress_total(self : ConstructionSite) -> Int

返回工地完成建造所需的总进度。

#
ConstructionSite::range_to

fn[T : GameObjectLike] ConstructionSite::range_to(self : ConstructionSite, target : T) -> Int

返回当前工地与目标之间的线性距离。

#
ConstructionSite::relation

返回工地的敌我关系。

#
ConstructionSite::remove

fn ConstructionSite::remove(self : ConstructionSite) -> Unit

移除该工地。

#
ConstructionSite::to_raw

返回底层 raw construction site 句柄。通常下游无需直接调用。

#
ConstructionSite::x

fn ConstructionSite::x(self : ConstructionSite) -> Int

返回工地当前的 x 坐标。

#
ConstructionSite::y

fn ConstructionSite::y(self : ConstructionSite) -> Int

返回工地当前的 y 坐标。

#
CreateConstructionSiteFailure

pub(all) enum CreateConstructionSiteFailure {
CreateInvalidArgs
CreateInvalidTarget
CreateFull
CreateUnknownRawError(Int)
} derive(Eq, Show)

create_construction_site 的失败原因。

#
CreateConstructionSiteResult

pub(all) enum CreateConstructionSiteResult {
Created(ConstructionSite)
CreateFailed(CreateConstructionSiteFailure)
}

create_construction_site 的正式高层结果。

#
Creep

pub struct Creep {
// private fields
}

Creep 的通用观察视图。
impl HasHits for Creep
impl HasStore for Creep
impl HealTarget for Creep
impl MoveTarget for Creep
impl MyLike for Creep

#
Creep::as_enemy

fn Creep::as_enemy(self : Creep) -> EnemyCreep?

若当前 creep 属于敌方,则转成 EnemyCreep 视图。

#
Creep::as_game_object

fn Creep::as_game_object(self : Creep) -> GameObject

将 creep 转成通用 GameObject 视图。

#
Creep::as_my

fn Creep::as_my(self : Creep) -> MyCreep?

若当前 creep 属于己方,则转成 MyCreep 视图。

#
Creep::body

fn Creep::body(self : Creep) -> Array[BodyPart]

返回 creep 身上的 body part 列表。

#
Creep::create

从 raw creep 构造通用 creep 视图。通常下游无需直接调用。

#
Creep::exists

fn Creep::exists(self : Creep) -> Bool

返回 creep 当前是否仍存在于场上。

#
Creep::find_closest

fn[T : GameObjectLike] Creep::find_closest(self : Creep, candidates : Array[T], by? : ClosestMetric) -> T?

从当前 creep 出发,按指定度量寻找最近目标。

#
Creep::find_in_range

fn[T : GameObjectLike] Creep::find_in_range(self : Creep, candidates : Array[T], range : Int) -> Array[T]

返回当前 creep 周围指定范围内的全部目标。

#
Creep::has_body_part

fn Creep::has_body_part(self : Creep, kind : BodyPartKind) -> Bool

判断 creep 是否拥有指定种类的 body part。

#
Creep::hits

#alias(hp)
fn Creep::hits(self : Creep) -> Int

返回 creep 当前生命值。

#
Creep::hits_max

#alias(max_hp)
fn Creep::hits_max(self : Creep) -> Int

返回 creep 最大生命值。

#
Creep::id

fn Creep::id(self : Creep) -> String

返回 creep 的唯一 id。

#
Creep::is_enemy

fn Creep::is_enemy(self : Creep) -> Bool

返回该 creep 是否属于敌方。

#
Creep::is_my

fn Creep::is_my(self : Creep) -> Bool

返回该 creep 是否属于己方。

#
Creep::range_to

fn[T : GameObjectLike] Creep::range_to(self : Creep, target : T) -> Int

返回当前 creep 与目标之间的线性距离。

#
Creep::relation

fn Creep::relation(self : Creep) -> Relation

返回 creep 的敌我关系。

#
Creep::spawning

fn Creep::spawning(self : Creep) -> Bool

返回该 creep 是否仍在孵化中。

#
Creep::store

fn Creep::store(self : Creep) -> Store

返回 creep 的存储视图。

#
Creep::to_raw

返回底层 raw creep 句柄。通常下游无需直接调用。

#
Creep::x

fn Creep::x(self : Creep) -> Int

返回 creep 当前的 x 坐标。

#
Creep::y

fn Creep::y(self : Creep) -> Int

返回 creep 当前的 y 坐标。

#
EnemyCreep

pub struct EnemyCreep {
// private fields
}

敌方 creep 的强约束视图。

#
EnemyCreep::as_creep

fn EnemyCreep::as_creep(self : EnemyCreep) -> Creep

将敌方 creep 放宽成通用 Creep 视图。

#
EnemyCreep::as_game_object

fn EnemyCreep::as_game_object(self : EnemyCreep) -> GameObject

将敌方 creep 转成通用 GameObject 视图。

#
EnemyCreep::body

fn EnemyCreep::body(self : EnemyCreep) -> Array[BodyPart]

返回敌方 creep 身上的 body part 列表。

#
EnemyCreep::create

从 raw creep 构造敌方 creep 视图。通常下游无需直接调用。

#
EnemyCreep::exists

fn EnemyCreep::exists(self : EnemyCreep) -> Bool

返回敌方 creep 当前是否仍存在于场上。

#
EnemyCreep::find_closest

fn[T : GameObjectLike] EnemyCreep::find_closest(self : EnemyCreep, candidates : Array[T], by? : ClosestMetric) -> T?

从当前敌方 creep 出发,按指定度量寻找最近目标。

#
EnemyCreep::find_in_range

fn[T : GameObjectLike] EnemyCreep::find_in_range(self : EnemyCreep, candidates : Array[T], range : Int) -> Array[T]

返回当前敌方 creep 周围指定范围内的全部目标。

#
EnemyCreep::has_body_part

fn EnemyCreep::has_body_part(self : EnemyCreep, kind : BodyPartKind) -> Bool

判断敌方 creep 是否拥有指定种类的 body part。

#
EnemyCreep::hits

#alias(hp)
fn EnemyCreep::hits(self : EnemyCreep) -> Int

返回敌方 creep 当前生命值。

#
EnemyCreep::hits_max

#alias(max_hp)
fn EnemyCreep::hits_max(self : EnemyCreep) -> Int

返回敌方 creep 最大生命值。

#
EnemyCreep::id

fn EnemyCreep::id(self : EnemyCreep) -> String

返回敌方 creep 的唯一 id。

#
EnemyCreep::is_enemy

fn EnemyCreep::is_enemy(_self : EnemyCreep) -> Bool

返回 true,表示这是敌方 creep 视图。

#
EnemyCreep::is_my

fn EnemyCreep::is_my(_self : EnemyCreep) -> Bool

返回 false,表示这不是己方 creep 视图。

#
EnemyCreep::range_to

fn[T : GameObjectLike] EnemyCreep::range_to(self : EnemyCreep, target : T) -> Int

返回当前敌方 creep 与目标之间的线性距离。

#
EnemyCreep::relation

fn EnemyCreep::relation(_self : EnemyCreep) -> Relation

返回固定为敌方的敌我关系。

#
EnemyCreep::spawning

fn EnemyCreep::spawning(self : EnemyCreep) -> Bool

返回该敌方 creep 是否仍在孵化中。

#
EnemyCreep::store

fn EnemyCreep::store(self : EnemyCreep) -> Store

返回敌方 creep 的存储视图。

#
EnemyCreep::to_raw

返回底层 raw creep 句柄。通常下游无需直接调用。

#
EnemyCreep::x

fn EnemyCreep::x(self : EnemyCreep) -> Int

返回敌方 creep 当前的 x 坐标。

#
EnemyCreep::y

fn EnemyCreep::y(self : EnemyCreep) -> Int

返回敌方 creep 当前的 y 坐标。

#
EnemySpawn

pub struct EnemySpawn {
// private fields
}

敌方 spawn 的强约束视图。

#
EnemySpawn::as_game_object

fn EnemySpawn::as_game_object(self : EnemySpawn) -> GameObject

将敌方 spawn 转成通用 GameObject 视图。

#
EnemySpawn::as_structure_spawn

fn EnemySpawn::as_structure_spawn(self : EnemySpawn) -> StructureSpawn

将敌方 spawn 放宽成通用 StructureSpawn 视图。

#
EnemySpawn::create

从 raw spawn 构造敌方 spawn 视图。通常下游无需直接调用。

#
EnemySpawn::exists

fn EnemySpawn::exists(self : EnemySpawn) -> Bool

返回敌方 spawn 当前是否仍存在于场上。

#
EnemySpawn::find_closest

fn[T : GameObjectLike] EnemySpawn::find_closest(self : EnemySpawn, candidates : Array[T], by? : ClosestMetric) -> T?

从当前敌方 spawn 出发,按指定度量寻找最近目标。

#
EnemySpawn::find_in_range

fn[T : GameObjectLike] EnemySpawn::find_in_range(self : EnemySpawn, candidates : Array[T], range : Int) -> Array[T]

返回当前敌方 spawn 周围指定范围内的全部目标。

#
EnemySpawn::hits

fn EnemySpawn::hits(self : EnemySpawn) -> Int

返回敌方 spawn 当前生命值。

#
EnemySpawn::hits_max

fn EnemySpawn::hits_max(self : EnemySpawn) -> Int

返回敌方 spawn 最大生命值。

#
EnemySpawn::id

fn EnemySpawn::id(self : EnemySpawn) -> String

返回敌方 spawn 的唯一 id。

#
EnemySpawn::is_enemy

fn EnemySpawn::is_enemy(_self : EnemySpawn) -> Bool

返回 true,表示这是敌方 spawn 视图。

#
EnemySpawn::is_my

fn EnemySpawn::is_my(_self : EnemySpawn) -> Bool

返回 false,表示这不是己方 spawn 视图。

#
EnemySpawn::range_to

fn[T : GameObjectLike] EnemySpawn::range_to(self : EnemySpawn, target : T) -> Int

返回当前敌方 spawn 与目标之间的线性距离。

#
EnemySpawn::relation

fn EnemySpawn::relation(_self : EnemySpawn) -> Relation

返回固定为敌方的敌我关系。

#
EnemySpawn::spawning

fn EnemySpawn::spawning(self : EnemySpawn) -> Spawning?

返回敌方 spawn 当前的孵化任务;若当前未在孵化,则返回 None。

#
EnemySpawn::store

fn EnemySpawn::store(self : EnemySpawn) -> Store

返回敌方 spawn 的存储视图。

#
EnemySpawn::to_raw

返回底层 raw spawn 句柄。通常下游无需直接调用。

#
EnemySpawn::x

fn EnemySpawn::x(self : EnemySpawn) -> Int

返回敌方 spawn 当前的 x 坐标。

#
EnemySpawn::y

fn EnemySpawn::y(self : EnemySpawn) -> Int

返回敌方 spawn 当前的 y 坐标。

#
EnemyTower

pub struct EnemyTower {
// private fields
}

敌方 tower 的强约束视图。

#
EnemyTower::as_game_object

fn EnemyTower::as_game_object(self : EnemyTower) -> GameObject

将敌方 tower 转成通用 GameObject 视图。

#
EnemyTower::as_structure_tower

fn EnemyTower::as_structure_tower(self : EnemyTower) -> StructureTower

将敌方 tower 放宽成通用 StructureTower 视图。

#
EnemyTower::cooldown

fn EnemyTower::cooldown(self : EnemyTower) -> Int

返回敌方 tower 剩余冷却时间。

#
EnemyTower::create

从 raw tower 构造敌方 tower 视图。通常下游无需直接调用。

#
EnemyTower::exists

fn EnemyTower::exists(self : EnemyTower) -> Bool

返回敌方 tower 当前是否仍存在于场上。

#
EnemyTower::find_closest

fn[T : GameObjectLike] EnemyTower::find_closest(self : EnemyTower, candidates : Array[T], by? : ClosestMetric) -> T?

从当前敌方 tower 出发,按指定度量寻找最近目标。

#
EnemyTower::find_in_range

fn[T : GameObjectLike] EnemyTower::find_in_range(self : EnemyTower, candidates : Array[T], range : Int) -> Array[T]

返回当前敌方 tower 周围指定范围内的全部目标。

#
EnemyTower::hits

fn EnemyTower::hits(self : EnemyTower) -> Int

返回敌方 tower 当前生命值。

#
EnemyTower::hits_max

fn EnemyTower::hits_max(self : EnemyTower) -> Int

返回敌方 tower 最大生命值。

#
EnemyTower::id

fn EnemyTower::id(self : EnemyTower) -> String

返回敌方 tower 的唯一 id。

#
EnemyTower::is_enemy

fn EnemyTower::is_enemy(_self : EnemyTower) -> Bool

返回 true,表示这是敌方 tower 视图。

#
EnemyTower::is_my

fn EnemyTower::is_my(_self : EnemyTower) -> Bool

返回 false,表示这不是己方 tower 视图。

#
EnemyTower::range_to

fn[T : GameObjectLike] EnemyTower::range_to(self : EnemyTower, target : T) -> Int

返回当前敌方 tower 与目标之间的线性距离。

#
EnemyTower::relation

fn EnemyTower::relation(_self : EnemyTower) -> Relation

返回固定为敌方的敌我关系。

#
EnemyTower::store

fn EnemyTower::store(self : EnemyTower) -> Store

返回敌方 tower 的存储视图。

#
EnemyTower::to_raw

返回底层 raw tower 句柄。通常下游无需直接调用。

#
EnemyTower::x

fn EnemyTower::x(self : EnemyTower) -> Int

返回敌方 tower 当前的 x 坐标。

#
EnemyTower::y

fn EnemyTower::y(self : EnemyTower) -> Int

返回敌方 tower 当前的 y 坐标。

#
Flag

pub struct Flag {
// private fields
}

Flag 的通用观察视图。
impl MoveTarget for Flag
impl MyLike for Flag

#
Flag::as_game_object

fn Flag::as_game_object(self : Flag) -> GameObject

将 flag 转成通用 GameObject 视图。

#
Flag::create

从 raw flag 构造高层视图。通常下游无需直接调用。

#
Flag::exists

fn Flag::exists(self : Flag) -> Bool

返回 flag 当前是否仍存在于场上。

#
Flag::find_closest

fn[T : GameObjectLike] Flag::find_closest(self : Flag, candidates : Array[T], by? : ClosestMetric) -> T?

从当前 flag 出发,按指定度量寻找最近目标。

#
Flag::find_in_range

fn[T : GameObjectLike] Flag::find_in_range(self : Flag, candidates : Array[T], range : Int) -> Array[T]

返回当前 flag 周围指定范围内的全部目标。

#
Flag::id

fn Flag::id(self : Flag) -> String

返回 flag 的唯一 id。

#
Flag::is_enemy

fn Flag::is_enemy(self : Flag) -> Bool

返回该 flag 是否属于敌方。

#
Flag::is_my

fn Flag::is_my(self : Flag) -> Bool

返回该 flag 是否属于己方。

#
Flag::range_to

fn[T : GameObjectLike] Flag::range_to(self : Flag, target : T) -> Int

返回当前 flag 与目标之间的线性距离。

#
Flag::relation

fn Flag::relation(self : Flag) -> Relation

返回 flag 的敌我关系。

#
Flag::to_raw

返回底层 raw flag 句柄。通常下游无需直接调用。

#
Flag::x

fn Flag::x(self : Flag) -> Int

返回 flag 当前的 x 坐标。

#
Flag::y

fn Flag::y(self : Flag) -> Int

返回 flag 当前的 y 坐标。

#
GameObject

pub struct GameObject {
// private fields
}

所有正式 wrapper 的共同基础视图。

#
GameObject::as_construction_site

fn GameObject::as_construction_site(self : GameObject) -> ConstructionSite?

若对象实际是 construction site,则返回其高层视图。

#
GameObject::as_creep

fn GameObject::as_creep(self : GameObject) -> Creep?

若对象实际是 creep,则返回其高层视图。

#
GameObject::as_flag

fn GameObject::as_flag(self : GameObject) -> Flag?

若对象实际是 flag,则返回其高层视图。

#
GameObject::as_source

fn GameObject::as_source(self : GameObject) -> Source?

若对象实际是 source,则返回其高层视图。

#
GameObject::as_structure

fn GameObject::as_structure(self : GameObject) -> Structure?

若对象实际是 structure,则返回其通用结构视图。

#
GameObject::as_structure_container

fn GameObject::as_structure_container(self : GameObject) -> StructureContainer?

若对象实际是 container,则返回其高层视图。

#
GameObject::as_structure_spawn

fn GameObject::as_structure_spawn(self : GameObject) -> StructureSpawn?

若对象实际是 spawn,则返回其高层视图。

#
GameObject::as_structure_tower

fn GameObject::as_structure_tower(self : GameObject) -> StructureTower?

若对象实际是 tower,则返回其高层视图。

#
GameObject::create

从 raw game object 构造高层视图。通常下游无需直接调用。

#
GameObject::exists

fn GameObject::exists(self : GameObject) -> Bool

返回对象当前是否仍存在于场上。

#
GameObject::find_closest

fn[T : GameObjectLike] GameObject::find_closest(self : GameObject, candidates : Array[T], by? : ClosestMetric) -> T?

从当前对象出发,按指定度量寻找最近目标。

#
GameObject::find_in_range

fn[T : GameObjectLike] GameObject::find_in_range(self : GameObject, candidates : Array[T], range : Int) -> Array[T]

返回当前对象周围指定范围内的全部目标。

#
GameObject::id

fn GameObject::id(self : GameObject) -> String

返回对象的唯一 id。

#
GameObject::prototype_name

fn GameObject::prototype_name(self : GameObject) -> String

返回对象的原始 prototype 名称。

#
GameObject::range_to

fn[T : GameObjectLike] GameObject::range_to(self : GameObject, target : T) -> Int

返回当前对象与目标之间的线性距离。

#
GameObject::to_raw

返回底层 raw game object 句柄。通常下游无需直接调用。

#
GameObject::x

fn GameObject::x(self : GameObject) -> Int

返回对象当前的 x 坐标。

#
GameObject::y

fn GameObject::y(self : GameObject) -> Int

返回对象当前的 y 坐标。

#
MyCreep

pub struct MyCreep {
// private fields
}

己方 creep 的强约束视图。
impl HasHits for MyCreep
impl HasStore for MyCreep
impl MyLike for MyCreep

#
MyCreep::as_creep

fn MyCreep::as_creep(self : MyCreep) -> Creep

将己方 creep 放宽成通用 Creep 视图。

#
MyCreep::as_game_object

fn MyCreep::as_game_object(self : MyCreep) -> GameObject

将己方 creep 转成通用 GameObject 视图。

#
MyCreep::attack

fn[T : AttackTarget + GameObjectLike] MyCreep::attack(self : MyCreep, target : T) -> ActionResult

让己方 creep 对目标执行近战攻击。

#
MyCreep::attack_or_move

fn[T : AttackTarget + GameObjectLike] MyCreep::attack_or_move(self : MyCreep, target : T) -> Unit

尝试近战攻击目标;若目标不在范围内,则自动朝目标移动。

#
MyCreep::body

fn MyCreep::body(self : MyCreep) -> Array[BodyPart]

返回己方 creep 身上的 body part 列表。

#
MyCreep::build

fn[T : BuildTarget] MyCreep::build(self : MyCreep, target : T) -> ActionResult

让己方 creep 建造目标工地。

#
MyCreep::build_or_move

fn[T : BuildTarget] MyCreep::build_or_move(self : MyCreep, target : T) -> Unit

尝试建造目标工地;若目标不在范围内,则自动朝目标移动。

#
MyCreep::create

从 raw creep 构造己方 creep 视图。通常下游无需直接调用。

#
MyCreep::exists

fn MyCreep::exists(self : MyCreep) -> Bool

返回己方 creep 当前是否仍存在于场上。

#
MyCreep::find_closest

fn[T : GameObjectLike] MyCreep::find_closest(self : MyCreep, candidates : Array[T], by? : ClosestMetric) -> T?

从当前己方 creep 出发,按指定度量寻找最近目标。

#
MyCreep::find_in_range

fn[T : GameObjectLike] MyCreep::find_in_range(self : MyCreep, candidates : Array[T], range : Int) -> Array[T]

返回当前己方 creep 周围指定范围内的全部目标。

#
MyCreep::harvest

fn[T : HarvestTarget] MyCreep::harvest(self : MyCreep, target : T) -> ActionResult

让己方 creep 采集目标 source。

#
MyCreep::harvest_or_move

fn[T : HarvestTarget] MyCreep::harvest_or_move(self : MyCreep, target : T) -> Unit

尝试采集目标;若目标不在范围内,则自动朝目标移动。

#
MyCreep::has_body_part

fn MyCreep::has_body_part(self : MyCreep, kind : BodyPartKind) -> Bool

判断己方 creep 是否拥有指定种类的 body part。

#
MyCreep::heal

fn[T : HealTarget + GameObjectLike] MyCreep::heal(self : MyCreep, target : T) -> ActionResult

让己方 creep 治疗目标 creep。

#
MyCreep::heal_or_move

fn[T : HealTarget + GameObjectLike] MyCreep::heal_or_move(self : MyCreep, target : T) -> Unit

尝试治疗目标;若目标不在范围内,则自动朝目标移动。

#
MyCreep::hits

#alias(hp)
fn MyCreep::hits(self : MyCreep) -> Int

返回己方 creep 当前生命值。

#
MyCreep::hits_max

#alias(max_hp)
fn MyCreep::hits_max(self : MyCreep) -> Int

返回己方 creep 最大生命值。

#
MyCreep::id

fn MyCreep::id(self : MyCreep) -> String

返回己方 creep 的唯一 id。

#
MyCreep::is_enemy

fn MyCreep::is_enemy(_self : MyCreep) -> Bool

返回 false,表示这不是敌方 creep 视图。

#
MyCreep::is_my

fn MyCreep::is_my(_self : MyCreep) -> Bool

返回 true,表示这是己方 creep 视图。

#
MyCreep::move_if_not_in_range

fn[T : MoveTarget + GameObjectLike] MyCreep::move_if_not_in_range(self : MyCreep, target : T, result : ActionResult) -> Unit

若给定动作结果为不在范围内,则自动朝目标移动。

#
MyCreep::move_to

fn[T : MoveTarget + GameObjectLike] MyCreep::move_to(self : MyCreep, target : T) -> ActionResult

让己方 creep 朝目标移动。

#
MyCreep::range_to

fn[T : GameObjectLike] MyCreep::range_to(self : MyCreep, target : T) -> Int

返回当前己方 creep 与目标之间的线性距离。

#
MyCreep::ranged_attack

fn[T : RangedAttackTarget + GameObjectLike] MyCreep::ranged_attack(self : MyCreep, target : T) -> ActionResult

让己方 creep 对目标执行远程攻击。

#
MyCreep::ranged_attack_or_move

fn[T : RangedAttackTarget + GameObjectLike] MyCreep::ranged_attack_or_move(self : MyCreep, target : T) -> Unit

尝试远程攻击目标;若目标不在范围内,则自动朝目标移动。

#
MyCreep::relation

fn MyCreep::relation(_self : MyCreep) -> Relation

返回固定为己方的敌我关系。

#
MyCreep::spawning

fn MyCreep::spawning(self : MyCreep) -> Bool

返回该己方 creep 是否仍在孵化中。

#
MyCreep::store

fn MyCreep::store(self : MyCreep) -> Store

返回己方 creep 的存储视图。

#
MyCreep::to_raw

返回底层 raw creep 句柄。通常下游无需直接调用。

#
MyCreep::transfer

fn[T : TransferTarget + GameObjectLike] MyCreep::transfer(self : MyCreep, target : T, resource : ResourceKind) -> ActionResult

让己方 creep 向目标转移指定资源。

#
MyCreep::transfer_energy

fn[T : TransferTarget + GameObjectLike] MyCreep::transfer_energy(self : MyCreep, target : T) -> ActionResult

让己方 creep 向目标转移能量。

#
MyCreep::transfer_energy_or_move

fn[T : TransferTarget + GameObjectLike] MyCreep::transfer_energy_or_move(self : MyCreep, target : T) -> Unit

尝试向目标转移能量;若目标不在范围内,则自动朝目标移动。

#
MyCreep::transfer_or_move

fn[T : TransferTarget + GameObjectLike] MyCreep::transfer_or_move(self : MyCreep, target : T, resource : ResourceKind) -> Unit

尝试向目标转移指定资源;若目标不在范围内,则自动朝目标移动。

#
MyCreep::withdraw

fn[T : WithdrawTarget + GameObjectLike] MyCreep::withdraw(self : MyCreep, target : T, resource : ResourceKind) -> ActionResult

让己方 creep 从目标提取指定资源。

#
MyCreep::withdraw_energy

fn[T : WithdrawTarget + GameObjectLike] MyCreep::withdraw_energy(self : MyCreep, target : T) -> ActionResult

让己方 creep 从目标提取能量。

#
MyCreep::withdraw_energy_or_move

fn[T : WithdrawTarget + GameObjectLike] MyCreep::withdraw_energy_or_move(self : MyCreep, target : T) -> Unit

尝试从目标提取能量;若目标不在范围内,则自动朝目标移动。

#
MyCreep::withdraw_or_move

fn[T : WithdrawTarget + GameObjectLike] MyCreep::withdraw_or_move(self : MyCreep, target : T, resource : ResourceKind) -> Unit

尝试从目标提取指定资源;若目标不在范围内,则自动朝目标移动。

#
MyCreep::x

fn MyCreep::x(self : MyCreep) -> Int

返回己方 creep 当前的 x 坐标。

#
MyCreep::y

fn MyCreep::y(self : MyCreep) -> Int

返回己方 creep 当前的 y 坐标。

#
MySpawn

pub struct MySpawn {
// private fields
}

己方 spawn 的强约束视图。
impl HasHits for MySpawn
impl HasStore for MySpawn
impl MyLike for MySpawn

#
MySpawn::as_game_object

fn MySpawn::as_game_object(self : MySpawn) -> GameObject

将己方 spawn 转成通用 GameObject 视图。

#
MySpawn::as_structure_spawn

fn MySpawn::as_structure_spawn(self : MySpawn) -> StructureSpawn

将己方 spawn 放宽成通用 StructureSpawn 视图。

#
MySpawn::create

从 raw spawn 构造己方 spawn 视图。通常下游无需直接调用。

#
MySpawn::exists

fn MySpawn::exists(self : MySpawn) -> Bool

返回己方 spawn 当前是否仍存在于场上。

#
MySpawn::find_closest

fn[T : GameObjectLike] MySpawn::find_closest(self : MySpawn, candidates : Array[T], by? : ClosestMetric) -> T?

从当前己方 spawn 出发,按指定度量寻找最近目标。

#
MySpawn::find_in_range

fn[T : GameObjectLike] MySpawn::find_in_range(self : MySpawn, candidates : Array[T], range : Int) -> Array[T]

返回当前己方 spawn 周围指定范围内的全部目标。

#
MySpawn::hits

fn MySpawn::hits(self : MySpawn) -> Int

返回己方 spawn 当前生命值。

#
MySpawn::hits_max

fn MySpawn::hits_max(self : MySpawn) -> Int

返回己方 spawn 最大生命值。

#
MySpawn::id

fn MySpawn::id(self : MySpawn) -> String

返回己方 spawn 的唯一 id。

#
MySpawn::is_enemy

fn MySpawn::is_enemy(_self : MySpawn) -> Bool

返回 false,表示这不是敌方 spawn 视图。

#
MySpawn::is_my

fn MySpawn::is_my(_self : MySpawn) -> Bool

返回 true,表示这是己方 spawn 视图。

#
MySpawn::range_to

fn[T : GameObjectLike] MySpawn::range_to(self : MySpawn, target : T) -> Int

返回当前己方 spawn 与目标之间的线性距离。

#
MySpawn::relation

fn MySpawn::relation(_self : MySpawn) -> Relation

返回固定为己方的敌我关系。

#
MySpawn::spawn_creep

fn MySpawn::spawn_creep(self : MySpawn, body : Array[BodyPartKind]) -> SpawnResult

让己方 spawn 开始孵化一个指定 body 的 creep。

#
MySpawn::spawning

fn MySpawn::spawning(self : MySpawn) -> Spawning?

返回己方 spawn 当前的孵化任务;若当前未在孵化,则返回 None。

#
MySpawn::store

fn MySpawn::store(self : MySpawn) -> Store

返回己方 spawn 的存储视图。

#
MySpawn::to_raw

返回底层 raw spawn 句柄。通常下游无需直接调用。

#
MySpawn::x

fn MySpawn::x(self : MySpawn) -> Int

返回己方 spawn 当前的 x 坐标。

#
MySpawn::y

fn MySpawn::y(self : MySpawn) -> Int

返回己方 spawn 当前的 y 坐标。

#
MyTower

pub struct MyTower {
// private fields
}

己方 tower 的强约束视图。
impl HasHits for MyTower
impl HasStore for MyTower
impl MyLike for MyTower

#
MyTower::as_game_object

fn MyTower::as_game_object(self : MyTower) -> GameObject

将己方 tower 转成通用 GameObject 视图。

#
MyTower::as_structure_tower

fn MyTower::as_structure_tower(self : MyTower) -> StructureTower

将己方 tower 放宽成通用 StructureTower 视图。

#
MyTower::attack

fn[T : TowerAttackTarget + GameObjectLike] MyTower::attack(self : MyTower, target : T) -> ActionResult

让己方 tower 远程攻击目标。

#
MyTower::cooldown

fn MyTower::cooldown(self : MyTower) -> Int

返回己方 tower 剩余冷却时间。

#
MyTower::create

从 raw tower 构造己方 tower 视图。通常下游无需直接调用。

#
MyTower::exists

fn MyTower::exists(self : MyTower) -> Bool

返回己方 tower 当前是否仍存在于场上。

#
MyTower::find_closest

fn[T : GameObjectLike] MyTower::find_closest(self : MyTower, candidates : Array[T], by? : ClosestMetric) -> T?

从当前己方 tower 出发,按指定度量寻找最近目标。

#
MyTower::find_in_range

fn[T : GameObjectLike] MyTower::find_in_range(self : MyTower, candidates : Array[T], range : Int) -> Array[T]

返回当前己方 tower 周围指定范围内的全部目标。

#
MyTower::heal

fn[T : HealTarget + GameObjectLike] MyTower::heal(self : MyTower, target : T) -> ActionResult

让己方 tower 远程治疗目标 creep。

#
MyTower::hits

fn MyTower::hits(self : MyTower) -> Int

返回己方 tower 当前生命值。

#
MyTower::hits_max

fn MyTower::hits_max(self : MyTower) -> Int

返回己方 tower 最大生命值。

#
MyTower::id

fn MyTower::id(self : MyTower) -> String

返回己方 tower 的唯一 id。

#
MyTower::is_enemy

fn MyTower::is_enemy(_self : MyTower) -> Bool

返回 false,表示这不是敌方 tower 视图。

#
MyTower::is_my

fn MyTower::is_my(_self : MyTower) -> Bool

返回 true,表示这是己方 tower 视图。

#
MyTower::range_to

fn[T : GameObjectLike] MyTower::range_to(self : MyTower, target : T) -> Int

返回当前己方 tower 与目标之间的线性距离。

#
MyTower::relation

fn MyTower::relation(_self : MyTower) -> Relation

返回固定为己方的敌我关系。

#
MyTower::store

fn MyTower::store(self : MyTower) -> Store

返回己方 tower 的存储视图。

#
MyTower::to_raw

返回底层 raw tower 句柄。通常下游无需直接调用。

#
MyTower::x

fn MyTower::x(self : MyTower) -> Int

返回己方 tower 当前的 x 坐标。

#
MyTower::y

fn MyTower::y(self : MyTower) -> Int

返回己方 tower 当前的 y 坐标。

#
Relation

pub enum Relation {
Mine
Enemy
Neutral
} derive(Compare, Eq, Show)

所有权关系在 model 层以枚举形式保存,避免重复的布尔字段。

#
ResourceKind

pub(all) enum ResourceKind {
Energy
} derive(Compare, Eq, Show)

第一阶段资源类型先只覆盖 Energy,但正式 API 仍采用枚举结构。

#
ResourceKind::to_raw

fn ResourceKind::to_raw(self : ResourceKind) -> String

转换为 raw 层使用的原始资源字符串。

#
Source

pub struct Source {
// private fields
}

Source 的通用观察视图。

#
Source::as_game_object

fn Source::as_game_object(self : Source) -> GameObject

将 source 转成通用 GameObject 视图。

#
Source::create

从 raw source 构造高层视图。通常下游无需直接调用。

#
Source::energy

fn Source::energy(self : Source) -> Int

返回 source 当前剩余的能量。

#
Source::energy_capacity

fn Source::energy_capacity(self : Source) -> Int

返回 source 的最大能量容量。

#
Source::exists

fn Source::exists(self : Source) -> Bool

返回 source 当前是否仍存在于场上。

#
Source::find_closest

fn[T : GameObjectLike] Source::find_closest(self : Source, candidates : Array[T], by? : ClosestMetric) -> T?

从当前 source 出发,按指定度量寻找最近目标。

#
Source::find_in_range

fn[T : GameObjectLike] Source::find_in_range(self : Source, candidates : Array[T], range : Int) -> Array[T]

返回当前 source 周围指定范围内的全部目标。

#
Source::id

fn Source::id(self : Source) -> String

返回 source 的唯一 id。

#
Source::range_to

fn[T : GameObjectLike] Source::range_to(self : Source, target : T) -> Int

返回当前 source 与目标之间的线性距离。

#
Source::to_raw

返回底层 raw source 句柄。通常下游无需直接调用。

#
Source::x

fn Source::x(self : Source) -> Int

返回 source 当前的 x 坐标。

#
Source::y

fn Source::y(self : Source) -> Int

返回 source 当前的 y 坐标。

#
SpawnFailure

pub(all) enum SpawnFailure {
SpawnNotOwner
SpawnBusy
SpawnNotEnoughEnergy
SpawnInvalidArgs
SpawnUnknownRawError(Int)
} derive(Eq, Show)

spawn_creep 的失败原因。

#
SpawnResult

pub(all) enum SpawnResult {
Spawned(MyCreep)
SpawnFailed(SpawnFailure)
}

spawn_creep 的正式高层结果。

#
Spawning

pub struct Spawning {
// private fields
}

spawn 当前进行中的孵化任务观察视图。

#
Spawning::create

从 raw spawning 构造高层视图。通常下游无需直接调用。

#
Spawning::creep

fn Spawning::creep(self : Spawning) -> Creep

返回当前正在被孵化的 creep。

#
Spawning::need_time

fn Spawning::need_time(self : Spawning) -> Int

返回这次孵化总共需要的时间。

#
Spawning::remaining_time

fn Spawning::remaining_time(self : Spawning) -> Int

返回当前剩余的孵化时间。

#
Spawning::to_raw

返回底层 raw spawning 句柄。通常下游无需直接调用。

#
Store

pub struct Store {
// private fields
}

Store 的 MoonBit wrapper。

#
Store::amount

fn Store::amount(self : Store, resource : ResourceKind) -> Int

返回指定资源当前实际存量。

#
Store::capacity

fn Store::capacity(self : Store, resource : ResourceKind) -> Int

返回指定资源的总容量。

#
Store::create

从 raw store 构造高层视图。通常下游无需直接调用。

#
Store::energy

fn Store::energy(self : Store) -> Int

返回当前存储中的能量数量。

#
Store::free

fn Store::free(self : Store, resource : ResourceKind) -> Int

返回指定资源当前剩余可用容量。

#
Store::free_energy

fn Store::free_energy(self : Store) -> Int

返回当前还能容纳多少能量。

#
Store::to_raw

返回底层 raw store 句柄。通常下游无需直接调用。

#
Store::used

fn Store::used(self : Store, resource : ResourceKind) -> Int

返回指定资源当前已使用的容量。

#
Structure

pub struct Structure {
// private fields
}

通用 Structure 观察视图,主要用于共享结构属性与 object_by_id 下转。
impl MyLike for Structure

#
Structure::as_game_object

fn Structure::as_game_object(self : Structure) -> GameObject

将结构转成通用 GameObject 视图。

#
Structure::create

从 raw game object 构造通用结构视图。通常下游无需直接调用。

#
Structure::exists

fn Structure::exists(self : Structure) -> Bool

返回结构当前是否仍存在于场上。

#
Structure::find_closest

fn[T : GameObjectLike] Structure::find_closest(self : Structure, candidates : Array[T], by? : ClosestMetric) -> T?

从当前结构出发,按指定度量寻找最近目标。

#
Structure::find_in_range

fn[T : GameObjectLike] Structure::find_in_range(self : Structure, candidates : Array[T], range : Int) -> Array[T]

返回当前结构周围指定范围内的全部目标。

#
Structure::hits

fn Structure::hits(self : Structure) -> Int

返回结构当前生命值。

#
Structure::hits_max

fn Structure::hits_max(self : Structure) -> Int

返回结构最大生命值。

#
Structure::id

fn Structure::id(self : Structure) -> String

返回结构的唯一 id。

#
Structure::is_enemy

fn Structure::is_enemy(self : Structure) -> Bool

返回该结构是否属于敌方。

#
Structure::is_my

fn Structure::is_my(self : Structure) -> Bool

返回该结构是否属于己方。

#
Structure::prototype_name

fn Structure::prototype_name(self : Structure) -> String

返回结构的原始 prototype 名称。

#
Structure::range_to

fn[T : GameObjectLike] Structure::range_to(self : Structure, target : T) -> Int

返回当前结构与目标之间的线性距离。

#
Structure::relation

fn Structure::relation(self : Structure) -> Relation

返回结构的敌我关系。

#
Structure::to_raw

返回底层 raw 结构句柄。通常下游无需直接调用。

#
Structure::x

fn Structure::x(self : Structure) -> Int

返回结构当前的 x 坐标。

#
Structure::y

fn Structure::y(self : Structure) -> Int

返回结构当前的 y 坐标。

#
StructureContainer

pub struct StructureContainer {
// private fields
}

StructureContainer 的通用观察视图。

#
StructureContainer::as_game_object

fn StructureContainer::as_game_object(self : StructureContainer) -> GameObject

将 container 转成通用 GameObject 视图。

#
StructureContainer::create

从 raw container 构造高层视图。通常下游无需直接调用。

#
StructureContainer::exists

fn StructureContainer::exists(self : StructureContainer) -> Bool

返回 container 当前是否仍存在于场上。

#
StructureContainer::find_closest

fn[T : GameObjectLike] StructureContainer::find_closest(self : StructureContainer, candidates : Array[T], by? : ClosestMetric) -> T?

从当前 container 出发,按指定度量寻找最近目标。

#
StructureContainer::find_in_range

fn[T : GameObjectLike] StructureContainer::find_in_range(self : StructureContainer, candidates : Array[T], range : Int) -> Array[T]

返回当前 container 周围指定范围内的全部目标。

#
StructureContainer::hits

fn StructureContainer::hits(self : StructureContainer) -> Int

返回 container 当前生命值。

#
StructureContainer::hits_max

fn StructureContainer::hits_max(self : StructureContainer) -> Int

返回 container 最大生命值。

#
StructureContainer::id

fn StructureContainer::id(self : StructureContainer) -> String

返回 container 的唯一 id。

#
StructureContainer::is_enemy

fn StructureContainer::is_enemy(self : StructureContainer) -> Bool

返回该 container 是否属于敌方。

#
StructureContainer::is_my

fn StructureContainer::is_my(self : StructureContainer) -> Bool

返回该 container 是否属于己方。

#
StructureContainer::range_to

fn[T : GameObjectLike] StructureContainer::range_to(self : StructureContainer, target : T) -> Int

返回当前 container 与目标之间的线性距离。

#
StructureContainer::relation

返回 container 的敌我关系。

#
StructureContainer::store

返回 container 的存储视图。

#
StructureContainer::to_raw

返回底层 raw container 句柄。通常下游无需直接调用。

#
StructureContainer::x

返回 container 当前的 x 坐标。

#
StructureContainer::y

返回 container 当前的 y 坐标。

#
StructureKind

pub(all) enum StructureKind {
Spawn
Extension
Road
Rampart
Wall
Tower
Container
} derive(Compare, Eq, Show)

结构原型名称用于创建 construction site。

#
StructureKind::to_prototype_name

fn StructureKind::to_prototype_name(self : StructureKind) -> String

转换为 raw 层使用的原始结构 prototype 名称。

#
StructureSpawn

pub struct StructureSpawn {
// private fields
}

StructureSpawn 的通用观察视图。

#
StructureSpawn::as_enemy

fn StructureSpawn::as_enemy(self : StructureSpawn) -> EnemySpawn?

若当前 spawn 属于敌方,则转成 EnemySpawn 视图。

#
StructureSpawn::as_game_object

fn StructureSpawn::as_game_object(self : StructureSpawn) -> GameObject

将 spawn 转成通用 GameObject 视图。

#
StructureSpawn::as_my

fn StructureSpawn::as_my(self : StructureSpawn) -> MySpawn?

若当前 spawn 属于己方,则转成 MySpawn 视图。

#
StructureSpawn::create

从 raw spawn 构造通用 spawn 视图。通常下游无需直接调用。

#
StructureSpawn::exists

fn StructureSpawn::exists(self : StructureSpawn) -> Bool

返回 spawn 当前是否仍存在于场上。

#
StructureSpawn::find_closest

fn[T : GameObjectLike] StructureSpawn::find_closest(self : StructureSpawn, candidates : Array[T], by? : ClosestMetric) -> T?

从当前 spawn 出发,按指定度量寻找最近目标。

#
StructureSpawn::find_in_range

fn[T : GameObjectLike] StructureSpawn::find_in_range(self : StructureSpawn, candidates : Array[T], range : Int) -> Array[T]

返回当前 spawn 周围指定范围内的全部目标。

#
StructureSpawn::hits

fn StructureSpawn::hits(self : StructureSpawn) -> Int

返回 spawn 当前生命值。

#
StructureSpawn::hits_max

fn StructureSpawn::hits_max(self : StructureSpawn) -> Int

返回 spawn 最大生命值。

#
StructureSpawn::id

fn StructureSpawn::id(self : StructureSpawn) -> String

返回 spawn 的唯一 id。

#
StructureSpawn::is_enemy

fn StructureSpawn::is_enemy(self : StructureSpawn) -> Bool

返回该 spawn 是否属于敌方。

#
StructureSpawn::is_my

fn StructureSpawn::is_my(self : StructureSpawn) -> Bool

返回该 spawn 是否属于己方。

#
StructureSpawn::range_to

fn[T : GameObjectLike] StructureSpawn::range_to(self : StructureSpawn, target : T) -> Int

返回当前 spawn 与目标之间的线性距离。

#
StructureSpawn::relation

fn StructureSpawn::relation(self : StructureSpawn) -> Relation

返回 spawn 的敌我关系。

#
StructureSpawn::spawning

fn StructureSpawn::spawning(self : StructureSpawn) -> Spawning?

返回 spawn 当前的孵化任务;若当前未在孵化,则返回 None。

#
StructureSpawn::store

fn StructureSpawn::store(self : StructureSpawn) -> Store

返回 spawn 的存储视图。

#
StructureSpawn::to_raw

返回底层 raw spawn 句柄。通常下游无需直接调用。

#
StructureSpawn::x

fn StructureSpawn::x(self : StructureSpawn) -> Int

返回 spawn 当前的 x 坐标。

#
StructureSpawn::y

fn StructureSpawn::y(self : StructureSpawn) -> Int

返回 spawn 当前的 y 坐标。

#
StructureTower

pub struct StructureTower {
// private fields
}

StructureTower 的通用观察视图。

#
StructureTower::as_enemy

fn StructureTower::as_enemy(self : StructureTower) -> EnemyTower?

若当前 tower 属于敌方,则转成 EnemyTower 视图。

#
StructureTower::as_game_object

fn StructureTower::as_game_object(self : StructureTower) -> GameObject

将 tower 转成通用 GameObject 视图。

#
StructureTower::as_my

fn StructureTower::as_my(self : StructureTower) -> MyTower?

若当前 tower 属于己方,则转成 MyTower 视图。

#
StructureTower::cooldown

fn StructureTower::cooldown(self : StructureTower) -> Int

返回 tower 剩余冷却时间。

#
StructureTower::create

从 raw tower 构造通用 tower 视图。通常下游无需直接调用。

#
StructureTower::exists

fn StructureTower::exists(self : StructureTower) -> Bool

返回 tower 当前是否仍存在于场上。

#
StructureTower::find_closest

fn[T : GameObjectLike] StructureTower::find_closest(self : StructureTower, candidates : Array[T], by? : ClosestMetric) -> T?

从当前 tower 出发,按指定度量寻找最近目标。

#
StructureTower::find_in_range

fn[T : GameObjectLike] StructureTower::find_in_range(self : StructureTower, candidates : Array[T], range : Int) -> Array[T]

返回当前 tower 周围指定范围内的全部目标。

#
StructureTower::hits

fn StructureTower::hits(self : StructureTower) -> Int

返回 tower 当前生命值。

#
StructureTower::hits_max

fn StructureTower::hits_max(self : StructureTower) -> Int

返回 tower 最大生命值。

#
StructureTower::id

fn StructureTower::id(self : StructureTower) -> String

返回 tower 的唯一 id。

#
StructureTower::is_enemy

fn StructureTower::is_enemy(self : StructureTower) -> Bool

返回该 tower 是否属于敌方。

#
StructureTower::is_my

fn StructureTower::is_my(self : StructureTower) -> Bool

返回该 tower 是否属于己方。

#
StructureTower::range_to

fn[T : GameObjectLike] StructureTower::range_to(self : StructureTower, target : T) -> Int

返回当前 tower 与目标之间的线性距离。

#
StructureTower::relation

fn StructureTower::relation(self : StructureTower) -> Relation

返回 tower 的敌我关系。

#
StructureTower::store

fn StructureTower::store(self : StructureTower) -> Store

返回 tower 的存储视图。

#
StructureTower::to_raw

返回底层 raw tower 句柄。通常下游无需直接调用。

#
StructureTower::x

fn StructureTower::x(self : StructureTower) -> Int

返回 tower 当前的 x 坐标。

#
StructureTower::y

fn StructureTower::y(self : StructureTower) -> Int

返回 tower 当前的 y 坐标。

#
active_sources

fn active_sources() -> Array[Source]

返回当前仍有能量可采集的 source。

#
closest_metrics

fn closest_metrics() -> Array[ClosestMetric]

返回当前支持的最近距离度量方式。

#
construction_sites

fn construction_sites() -> Array[ConstructionSite]

返回当前场上的全部 construction site。

#
containers

fn containers() -> Array[StructureContainer]

返回当前场上的全部 container。

#
create_construction_site

fn create_construction_site(x : Int, y : Int, kind : StructureKind) -> CreateConstructionSiteResult

在指定坐标创建目标结构类型的 construction site。

#
creeps

fn creeps() -> Array[Creep]

返回当前场上的全部 creep 观察视图。

#
enemy_creeps

fn enemy_creeps() -> Array[EnemyCreep]

返回当前全部敌方 creep 的强约束视图。

#
enemy_spawns

fn enemy_spawns() -> Array[EnemySpawn]

返回当前全部敌方 spawn 的强约束视图。

#
enemy_towers

fn enemy_towers() -> Array[EnemyTower]

返回当前全部敌方 tower 的强约束视图。

#
find_closest

fn[From : GameObjectLike, T : GameObjectLike] find_closest(from : From, candidates : Array[T], by? : ClosestMetric) -> T?

在候选列表中按指定度量寻找距离起点最近的目标。

#
find_in_range

fn[From : GameObjectLike, T : GameObjectLike] find_in_range(from : From, candidates : Array[T], range : Int) -> Array[T]

返回候选列表中位于指定范围内的全部目标。

#
flags

fn flags() -> Array[Flag]

返回当前场上的全部 flag。

#
get_ticks

fn get_ticks() -> Int

当前游戏已运行的 tick 数。

#
my_construction_sites

fn my_construction_sites() -> Array[ConstructionSite]

返回当前全部己方 construction site。

#
my_creeps

fn my_creeps() -> Array[MyCreep]

返回当前全部己方 creep 的强约束视图。

#
my_spawns

fn my_spawns() -> Array[MySpawn]

返回当前全部己方 spawn 的强约束视图。

#
my_towers

fn my_towers() -> Array[MyTower]

返回当前全部己方 tower 的强约束视图。

#
object_by_id

fn object_by_id(id : String) -> GameObject?

通过唯一 id 获取正式高层 GameObject 视图。

#
range_between

fn[A : GameObjectLike, B : GameObjectLike] range_between(a : A, b : B) -> Int

返回两个对象之间的线性距离。

#
relation_of_my_bool

fn relation_of_my_bool(my : Bool) -> Relation

将非空的 my 布尔值转换为统一的 Relation

#
relation_of_my_flag

fn relation_of_my_flag(my : Bool?) -> Relation

将可能为 Nonemy 标记转换为统一的 Relation

#
sources

fn sources() -> Array[Source]

返回当前场上的全部 source。

#
spawns

fn spawns() -> Array[StructureSpawn]

返回当前场上的全部 spawn 通用视图。

#
structure_kinds

fn structure_kinds() -> Array[StructureKind]

返回当前已知的结构原型种类列表。

#
structures

fn structures() -> Array[Structure]

返回当前场上的全部通用结构观察视图。

#
towers

fn towers() -> Array[StructureTower]

返回当前场上的全部 tower 通用视图。