# 公平模式

> 注入进游戏的客户端能读到全图。公平模式让 Bot 只看得见视野里的东西 —— 和人类玩家一样，也和擂台规则一样。

来源: https://war3ai.com/docs/fair-mode/

本项目的观察能力来自「客户端持有全部玩家的状态」：快照里有整张地图的所有单位，包括迷雾里的敌人。这对调试很方便，但对比赛不公平。

**公平模式**让 SDK 按你的视野过滤：

```bash
python tools/play.py --bot my_bot.py --fair
python -m openwar3 run my_bot.py --inst 5 --fair
```

```python
from openwar3 import Game, run
g = Game(inst=5, fair=True)            # 直接用 Game
run(MyBot, inst=5, fair=True)          # 或者交给运行器
```

## 过滤了什么

| 内容 | 公平模式下 |
|---|---|
| 单位 | 我方全部 + 此刻我方看得见的敌方和中立单位 |
| 地上物品 | 只留我方单位视野内的（白天 / 夜里视野按数据表分别算） |
| 生产表 | 只留看得见的建筑（看不见对手在练什么） |
| 事件 | 自己的；看得见的（或 1 秒内看得见过的）；我方打出的伤害 |

## 视野从哪来

- 快照里每个单位带一个**可见性掩码**：第 p 位 = 玩家 p 此刻看得见它（只算场上有单位的 0 ~ 11 号；自己的单位对自己恒可见）。`u.visible_to(g.me())` 直接读它，零等待。
- 任意一点：`g.visible(x, y)` 问引擎（看得见 / 迷雾 / 黑区），走快车道，每次约一帧。一拍里要判断很多单位时，用快照里的 `u.visible_to()`，别逐个调 `g.visible()`。

## 敌人的记忆：`last_seen`

人类玩家会记得「刚才在那边看到过一队狼骑」。SDK 也帮你记：每次刷新快照，记下我方此刻看得见的敌方和野怪单位（最后的位置、血量、时间）；看见它死了就删，换局清空。

```python
for u, t, age in g.last_seen(max_age=60):         # 60 游戏秒内看到过的敌人
    print(u.type, u.x, u.y, f"{age:.0f}s 前")

heroes = [r for r in g.last_seen() if r[0].is_hero]   # 对面英雄上次在哪
camps  = g.last_seen(owner="creep")                   # 见过的野怪
```

公平模式下，这是你唯一的「对手信息来源」—— 和人类玩家一样。普通模式也按视野记，所以可以用同一套代码。

## 以几号玩家的身份指挥

```bash
python tools/play.py --bot my_bot.py --player 1 --attach
```

`--player N`（或 `Game(player=N)`）让 Bot 以 N 号玩家的身份指挥，只能指挥 N 号玩家的单位。两个 AI 对打，就是同一局里开两条这样的通道。

> **本机模式下，公平是约定，不是安全边界**
>
> 在你自己的机器上，没有任何办法阻止一个程序读全图。`--fair` 是你对自己的约束；真正的比赛由 [对战平台](https://war3ai.com/arena/) 的裁判进程保证：Bot 永远碰不到共享内存，只能拿到裁判按视野过滤过的观察，只能提交动作，每条动作先校验单位归属。

## 为什么现在就该开

- 将来上擂台时规则就是这样，现在按公平模式写，到时候一行不用改；
- 离开全图信息，才知道你的 Bot 真实水平如何（参考大脑目前大量依赖全图信息，比如电脑队长的目标点 —— 这正好是一次检验）；
- 公平模式下写出来的侦察、记忆、判断，才是真正有价值的 AI 能力。
