运行军事扩展:从接敌到占领
本教程运行军事参考起步示例。它建立一支野战部队,补充兵员,向有守军的领地行军,结算战斗并占领该地,最后确认保存和重放得到的副本与原运行一致。你会了解 canwu-military 如何接收命令、随机性从哪里来,以及哪些状态交给其他扩展管理。
军事模拟扩展分为三个 crate:
canwu-military:军事领域记录、MilitaryCommand领域命令、边界系统、抽样证据和发给指挥官的报告,构建在canwu-api之上。canwu-military-reference-content:两套带版本的规则集。canwu-military-reference:可替换的参考整合包,为参考世界加入军事目录。
在仓库根目录运行:
cargo run -p canwu-military-reference --example military_startermilitary_gameplan=complete riverine=riverine_preindustrial industrial=industrial_front checkpoint=3b647676eb58a48594665edc09d190b25eb7932e4d630496c3f57fc6ddc2b691military_gameplan=complete 表示所有断言都已通过:战斗得出了结果,占领已经建立,恢复和重放得到的副本与原运行的检查点哈希相同。riverine 和 industrial 打印的是两套参考规则集的名称。
军事命令的执行路径
Section titled “军事命令的执行路径”查看图表源码
flowchart TB
Cmd["military_command()<br/>Command::Plugin"] --> Queue["enqueue_command()<br/>规范化输入"]
Queue --> Admit["准入检查<br/>指挥官、版本、<br/>兵种、战术"]
Admit --> Packet["military_command_v1<br/>输入数据包"]
Packet --> Apply["第 7 阶段<br/>写入记录、抽样"]
Apply --> Report["第 13 阶段<br/>向指挥官报告"]
起步示例通过同一个辅助函数发送所有命令:
fn submit( canwu: &mut Canwu, sequence: u64, issuer: Issuer, command: MilitaryCommand,) -> Result<(), Box<dyn std::error::Error>> { let envelope = CommandEnvelope::new(issuer, military_command(command)?); canwu.enqueue_command( canwu.time(), i32::try_from(sequence)?, CommandRequest::new(CommandRequestId::new(sequence), canwu.revision(), envelope), )?; canwu.advance_canonical(SimDuration::minutes(1))?; Ok(())}军事命令必须走规范化输入(enqueue_command);直接调用 submit 会返回 MixedCommandIngress。准入时,处理器检查签发者是否指挥这支部队、expected_force_revision 是否与部队记录一致,以及兵种或战术是否存在于当前规则集中。检查通过后,它排入一个 military_command_v1 数据包,由第 7 阶段的系统 apply-military-ingress-v1 应用。
每条命令都带一个 MilitaryOperationKey。同一个键配上不同输入,会以 IdempotencyConflict 失败。用同一个键、同样的输入再次发送,只有在这次发送通过准入时才是空操作。带 expected_force_revision 的命令在第一次执行提高了部队修订号之后,再发一次就会在准入时因版本过期(DomainRecordVersionConflict)而失败,这会让边界失败,并把该输入留在队列里。
起步示例做了什么
Section titled “起步示例做了什么”demo_military_scenario() 以参考世界的演示场景为基础,加入使用 riverine_preindustrial 规则集的军事目录。示例注册 ReferenceWorldPlugin 和 military_plugin(),然后发送五条命令:
| 步骤 | 命令 | 结果 |
|---|---|---|
| 1 | CreateForce |
沈将军的野战部队驻在中部节点,编制 2,500 人,实有 2,000 人。 |
| 2 | Recruit |
新增 400 人的 reserve 子单位,部队记录升到版本 2。 |
| 3 | PlanOperation |
一条处于 Planned 阶段的战略行动记录。 |
| 4 | CreateForce |
东部节点上一支 100 人的守军,由罗大臣(Minister Luo)指挥。 |
| 5 | OrderMarch |
野战部队向东部节点行军,以守军为对手。 |
起步示例中的行军命令如下:
MilitaryCommand::OrderMarch { operation: canwu_military::MilitaryOperationKey::new("canwu.military:op:march-front")?, force: force.clone(), operation_id: OperationId::new("canwu.military:operation:march-front")?, destination: MilitaryNodeId::new(format!( "canwu.military:node:{}", ids.eastern_territory ))?, objective: "secure the eastern route".to_owned(), tactic: "crossing_assault".to_owned(), opposing_force: Some(ForceId::new("canwu.military:force:defender")?), expected_force_revision: 2,}随后 canwu.advance_canonical(SimDuration::days(5)) 推进五天:
- 下令一分钟后,部队抵达目的地,接敌产生一条战斗记录。参考插件把行军当作一分钟的一步,并记录路线摘要(部队和目的地的哈希),详见组合移动。
- 交战中的行动每天结算一个战斗轮,每轮从
military_random_stream()抽样一次,并记录为抽样证据。本次运行中,2,400 人的进攻方损失 7 人,在第一轮就全歼 100 人的守军,战斗以AttackerVictory结束。 - 胜利后,目的地建立占领,阶段为
MilitaryControl。占领每天更新一次,安全度和行政覆盖逐步上升;运行结束时分别为 600 和 80(千分比)。
命令与所有权
Section titled “命令与所有权”MilitaryCommand 有 13 个变体(含内部使用的 AdvanceTick)。canwu-military 只写入自己的部队、行动、战斗、占领、账本和提供方结果记录;路线、资源、人口、法律和财政程序留给各自的扩展。每条命令检查和写入什么、战斗与占领规则,以及特种行动的已知问题,见军事系统。
参考规则集是合成数据
Section titled “参考规则集是合成数据”canwu-military-reference-content 提供 riverine_preindustrial 和 industrial_front 两套规则集,都标记为 synthetic_reference:它们用于覆盖不同的兵种、战术、地形、征募、战斗和占领假设,不代表任何历史结论。当前插件读取生效的规则集,用来校验兵种和战术名称;战斗和占领的计算写在 canwu-military 内部。
当前的 canwu-military 插件在下令一分钟后完成行军,只记录路线摘要。需要路线和行军耗时的上层应用,应在自己的整合中围绕行军组合 canwu-routing 与 canwu-transport 或 canwu-movement,参见路线规划与送信执行。
完整的命令序列以及快照和重放检查,见起步示例源码。