跳到主要内容

Python SDK 接口参考

  • 安装包:arena-hero
  • 导入名:arena_hero
  • Python:3.11 或更高版本

所有公开模型都有完整类型,底层是不可变的 Pydantic 模型。服务端状态会先通过校验, 然后才交给你的循环。

客户端

ArenaHeroClient

同步客户端:

ArenaHeroClient(
*,
api_key: str,
base_url: str = "https://api.arenahero.io",
websocket_url: str | None = None,
request_timeout: float = 5.0,
request_retries: int = 2,
reconnect_min_delay: float = 0.25,
reconnect_max_delay: float = 5.0,
max_message_size: int = 2 * 1024 * 1024,
)

AsyncArenaHeroClient

异步客户端接受完全相同的参数:

AsyncArenaHeroClient(
*,
api_key: str,
base_url: str = "https://api.arenahero.io",
websocket_url: str | None = None,
request_timeout: float = 5.0,
request_retries: int = 2,
reconnect_min_delay: float = 0.25,
reconnect_max_delay: float = 5.0,
max_message_size: int = 2 * 1024 * 1024,
)
参数含义
api_key必填。通过 Authorization: Bearer … 发送的凭据。
base_urlHTTP API 基址,命令地址会从这里推导。
websocket_urlWebSocket 地址。省略时从 base_url 推导。
request_timeout单次 HTTP 命令请求的超时秒数。
request_retries第一次请求失败后,最多再安全重试多少次。
reconnect_min_delayWebSocket 首次重连前等待的秒数。
reconnect_max_delayWebSocket 重连等待上限,单位为秒。
max_message_size接受的 WebSocket 单条消息最大字节数。

SDK 不会从环境变量读取这些参数。

turns()

同步:ArenaHeroClient.turns() -> Iterator[Turn]

异步:AsyncArenaHeroClient.turns() -> AsyncIterator[AsyncTurn]

每个可操作的 Tick 只返回一次。回执仍然会在内部处理,并写入 latest_receipts

events()

同步:ArenaHeroClient.events() -> Iterator[Tick | Turn | Received]

异步:AsyncArenaHeroClient.events() -> AsyncIterator[Tick | AsyncTurn | Received]

返回完整的应用层 WebSocket 事件流:

事件何时出现你该做什么
Tick新 Tick 已经宣布。记下编号;这时还没有状态可以操作。
Turn / AsyncTurn完整玩家状态已经准备好。读取状态、排好动作,然后提交。
ReceivedAGENTMANUAL 的计划已保存。替换这个来源、这个 Tick 之前的回执。

一个客户端同一时间只能有一个 events()turns() 迭代器。

latest_receipts

from arena_hero import CommandSource


agent_receipt = game.latest_receipts.get(CommandSource.AGENT)
manual_receipt = game.latest_receipts.get(CommandSource.MANUAL)

这个只读映射保存当前 Tick 每个来源最新的 Received。新 Tick 开始时会清空。

submit()

提交一份已经构造好的完整计划:

accepted = game.submit(plan, idempotency_key="agent-10583-plan-1")

异步写法:

accepted = await game.submit(plan, idempotency_key="agent-10583-plan-1")

返回类型是 Accepted。不传 idempotency_key 时,SDK 会自动生成。如果网络失败导致 结果不确定,SDK 会带着同一个 Key 重试完全相同的请求字节。

自定义 Key 必须是 8–128 个可见 ASCII 字节,不能包含空格。

close()

关闭当前 WebSocket 和 HTTP 连接池。优先使用 withasync with,这样退出时会 自动关闭。

Turn

TurnAsyncTurn 的状态与控制接口完全一致。唯一的区别是 AsyncTurn.submit() 需要 await

状态

属性类型含义
tickint这份状态和计划所属的 Tick。
statePlayerState完整、权威的玩家状态模型。
resourcesint当前存放在 Core 里的资源。
resource_capacityint当前容量:max(10, state.population * 5)
resource_spaceint还能接收多少资源;最小为 0。
core`CoreNone`
unitstuple[Unit, ...]自己控制的所有 Unit。
workerstuple[Worker, ...]自己控制的 Worker。
vanguardstuple[Vanguard, ...]自己控制的 Vanguard。
rangerstuple[Ranger, ...]自己控制的 Ranger。
visible_enemies`tuple[UnitViewCoreView, ...]`
terraintuple[TerrainView, ...]可见障碍与当前可用资源的批次。
resource_cellsfrozenset[Position]仅本 Turn 可见且可用的资源点。
obstacle_cellsfrozenset[Position]当前可见的障碍格。
beaconChampionBeacon经过视野裁剪的信标状态。
eventstuple[ResolutionEvent, ...]上一个 Tick 的私有结算结果。
planCommandPlan当前在内存里排好的完整计划。

Position(x, y) 顺序的 tuple[int, int]

生产价格动态变化。用 unit_cost(unit_type, state.population) 计算当前状态显示的价格。 服务端会在 SPAWN 结算时按同 Tick 自毁和战斗死亡后的实际人口重新计算。

方法

方法含义
unit(unit_id)按 UUID 或 UUID 字符串查找一个受控 Unit。
clear()清掉所有 Unit 和 Core 的待提交动作。
submit(idempotency_key=None)提交当前排好的完整计划。

新的 Tick 到来后,再调用旧 Turn 上的动作会抛出 TurnClosedError。不要跨 Tick 保存并 复用 Unit 或 Core 控制对象。

Unit 控制接口

所有受控 Unit 都有这些成员:

成员类型或签名
viewUnitView
idUUID
positionPosition
hpint
unit_typeUnitType
move(direction)移动一格。
pickup_beacon()拾取当前格的信标。
drop_beacon()放下携带的信标。
heal()与己方静止 Core 同格时,在战斗后恢复 HP。
self_destruct()在移动前移除这个 Unit;不返还资源,也不造成范围伤害。
wait()明确提交 WAIT
clear_action()把这个 Unit 从待提交计划里移除。

每个 Unit 最多只有一个待提交动作。后调用的方法会替换之前的动作。

Worker

额外状态:

成员类型含义
cargoint当前携带的资源量。

额外控制:

方法含义
harvest()尝试消耗当前格的资源点。
deposit()与 Core 同格时存入能装下的量,剩余 Cargo 留在 Worker 身上。

一次成功采集消耗一个自然资源点。普通赢家携带 1 资源;所属玩家持有 Beacon 的赢家 从同一个点携带 2。死亡 Worker 留下的 Cargo 资源堆会被优先回收,而且不会取得超过 实际剩余量的资源。多个合格 Worker 采同一格时,只有最低 UUID 成功,其他人收到 HARVEST_FAILED,reason 是 RESOURCE_DEPLETED

Core 已满时,交付结算为 DEPOSIT_FAILED / CORE_RESOURCE_FULL。人口下降后,高于 新容量的资源会立刻销毁,并通过 CORE_RESOURCE_OVERFLOW_DESTROYED 返回。

Worker 因战斗、Core 摧毁或主动自毁死亡时,携带的全部 Cargo 都会留在最后所在格形成 资源堆。

摧毁敌方 Core 后可能收到 CORE_RESOURCES_CAPTURED。通过 event.core_resource_capture 读取实际存入量、受害者原库存、销毁量和获胜者容量。对该 Core 总伤害最高者获胜,伤害相同时按玩家 UUID 原始字节序;超额资源销毁,获胜方 Core 同 Tick 也死亡时全部战利品销毁。

Vanguard

方法含义
sweep(direction)攻击指定方向的相邻格。

Ranger

ranger.shoot_cell((120, 85))
ranger.shoot(target)
ranger.shoot(target_id, expected_cell=(120, 85))

shoot_cell(expected_cell) 不需要当前目标。移动先结算;服务端命中届时格内 HP 最低的 敌方对象,HP 相同时按 UUID 排序;格子为空则返回 SHOT_MISSED

target 可以是可见的 UnitCoreUnitViewCoreView。SDK 会把目标 UUID 和当前位置一起写入命令。只传 UUID 或 UUID 字符串时,必须同时传 expected_cell

服务端仍会按照游戏规则结算射击。命令能成功构造,不代表一定命中。

Core 控制接口

Core 控制对象有这些成员:

成员类型或签名
viewCoreView
idUUID
owner_usernamestr
positionPosition
hpint
shieldint
spawn(unit_type)生产 WORKERVANGUARDRANGER
heal()战斗后恢复 Core HP。
repair_shield()消耗资源修复护盾。
start_move(direction)开始移动 Core。
cancel_move()取消 Core 当前的移动。
pickup_beacon()拾取当前格的信标。
drop_beacon()放下携带的信标。
self_destruct()战斗后销毁 Core、库存和所有己方 Unit,然后进入普通重生流程。
wait()明确提交 WAIT
clear_action()清掉 Core 的待提交动作。

Core 也只有一个动作槽。后调用的方法会替换之前排好的动作。

Core 自毁在迁移中也有效,不检查资源、Unit 数量或冷却。战斗摧毁优先;否则 Core 销毁 库存和全军,让 Cargo 与 Beacon 掉落,不产生摧毁归属或战利品,并立即进入普通重生流程。

状态模型

PlayerState

字段类型
statusPlayerStatus
respawn_at_tick`int
resourcesint
populationint
champion_beaconChampionBeacon
objects`tuple[TerrainView
eventstuple[ResolutionEvent, ...]

每个字段的含义和视野规则见状态模型

对象模型

模型主要字段
UnitViewkindidcontrolledpositionhpunit_typecargo
CoreViewkindidowner_usernamecontrolledpositionhpshieldstate、移动字段
TerrainViewkindpositionsRESOURCE 表示当前可见的可用位置
ChampionBeaconpositionstatuscarrier_id

控制类(WorkerVanguardRangerCore)是受控对象的便捷接口。敌方对象仍然是 不可变的 UnitViewCoreView

每个 CoreView 都有 owner_username,值不含 @。显示时写成 f"@{core.owner_username}"。Unit 没有这个字段,也不会暴露所属玩家。

ResolutionEvent

字段类型
event_idUUID
tickint
event_typestr
reason_code`str
actor_id`UUID
target_id`UUID
position`Position
values`dict[str, Any]
resource_amount`int
core_resource_capture`CoreResourceCapture
healing`HealingResult
harvest_source`HarvestSource

事件名和原因码保留为字符串,这样服务端以后新增值时,旧版 SDK 不会直接崩掉。具体 含义见结算结果

其中 HARVEST_FAILED/RESOURCE_DEPLETED 表示同 Tick 有 UUID 更低的合格 Worker 消耗了被竞争的资源点。resource_amount 可以读取 CORE_RESOURCES_CAPTUREDCORE_RESOURCE_OVERFLOW_DESTROYEDDEPOSIT_SUCCEEDEDWORKER_CARGO_DROPPEDHARVEST_SUCCEEDED 中的正数 amountcore_resource_capture 会把格式正确的 CORE_RESOURCES_CAPTURED 解析成带 amountavailabledestroyedcapacity 的类型化模型。满仓时 amount 可以为零,并且始终满足 amount + destroyed == availablehealing 会把成功的 Unit 或 Core 恢复解析成带 amount、恢复后 hpcost 的 类型化模型。恢复失败时它是 None,具体原因读取 reason_codeharvest_source is HarvestSource.DROPPED_CARGO 表示正在回收掉落资源; HarvestSource.RESOURCE_NODE 表示普通自然资源采集。不适用或无法识别的值会返回 None

规则辅助函数

from arena_hero import (
CORE_RESOURCE_CAPACITY_PER_UNIT,
CORE_RESOURCE_MINIMUM_CAPACITY,
UNIT_BASE_COSTS,
UnitType,
core_resource_capacity,
unit_cost,
)

CORE_RESOURCE_CAPACITY_PER_UNIT 的值是 5CORE_RESOURCE_MINIMUM_CAPACITY 的值是 10core_resource_capacity(population) 返回 max(10, population * 5);人口为负数时会报错。 UNIT_BASE_COSTS 是只读映射,Worker、Vanguard、Ranger 分别为 5、10、12。 unit_cost(unit_type, population) 使用当前精确生产公式,并拒绝负人口:

exponent = max(0, floor((population - 20) / 5) + 1)
price = round_half_up(base_price × (13 / 10)^exponent)

只在最终结果上舍入一次。第 21 个 Unit 是第一个涨价的 Unit。实际结算价格以 CORE_SPAWN_SUCCEEDED.values.costCORE_SPAWN_FAILED/INSUFFICIENT_RESOURCES.values.required 为准。

TickReceivedAccepted

模型字段
Ticktick
Receivedticksourcereceived_atplan
Acceptedacceptedticksourcereceived_at

Accepted 是 HTTP 202 确认。Received 是 WebSocket 广播给这名玩家所有在线客户端 的权威计划。

命令模型

大多数代码应该通过 Turn 排动作。需要直接控制协议模型时,也可以自己构造:

from uuid import UUID

from arena_hero import CommandPlan, Direction, MoveAction


plan = CommandPlan(
tick=10583,
unit_actions={
UUID("9d3e4941-2816-4a39-a220-df8cd95e877d"): MoveAction(
direction=Direction.UP
)
},
)

accepted = game.submit(plan)

公开的 Unit 动作模型:

Unit 动作必填数据
WaitAction
MoveActiondirection
HarvestAction
DepositAction
SweepActiondirection
ShootActionexpected_cell;可选 target_id
PickupBeaconAction
DropBeaconAction
SelfDestructAction
HealAction
Core 动作必填数据
WaitAction
SpawnActionunit_type
RepairShieldAction
HealAction
StartMoveActiondirection
CancelMoveAction
PickupBeaconAction
DropBeaconAction
SelfDestructAction

CommandPlan.unit_actions 是 Unit UUID 到动作的映射。 CommandPlan.core_action 是一个 Core 动作,也可以是 None

枚举

枚举可选值
DirectionUPDOWNLEFTRIGHT
UnitTypeWORKERVANGUARDRANGER
PlayerStatusACTIVERESPAWNING
CoreStateNORMALMOVING
CommandSourceAGENTMANUAL
BeaconStatusGROUNDCARRIED
HarvestSourceRESOURCE_NODEDROPPED_CARGO

Direction.delta 会返回对应的 (dx, dy)

异常

所有 SDK 异常都继承自 ArenaHeroError

异常含义
ConfigurationError构造参数或幂等键无效、客户端已关闭,或者同时启动了两个迭代器。
AuthenticationErrorWebSocket 握手拒绝了 API Key。
PolicyViolationErrorWebSocket 以策略违规码 1008 关闭。
ProtocolError服务端消息不符合公开协议。
APIError命令 API 返回了结构化拒绝。
TransportError安全重试用完后,网络操作仍然失败。
TurnClosedError代码试图修改已经过期的 Turn。
InvalidActionError本地目标或动作无法安全表示成协议命令。

APIError 提供 status_codeerrormessagedetails

游戏里的动态失败不是 Python 异常。它们会作为 ResolutionEvent 出现在下一次 Turn.events 里。

连接行为

SDK 会:

  • 只在 Authorization 请求头中发送 API Key;
  • 关闭 WebSocket 消息压缩,保持与服务端约定一致;
  • 自动处理协议层 Ping/Pong;
  • 对临时 WebSocket 故障使用带随机抖动的指数退避重连;
  • 遇到关闭码 1008 后停止重连;
  • 把每个 state 都当成完整替换;
  • 对结果不确定的命令提交,使用相同字节和同一个幂等键安全重试。

服务端命令窗口是全局的,Turn 到达时可能已经过去一部分。计划算好就尽快提交。完整的 时间与恢复规则见可靠的命令循环