Skip to content

Commit 2785a72

Browse files
committed
数值
1 parent 85abc51 commit 2785a72

7 files changed

Lines changed: 195 additions & 14 deletions

File tree

docs/THUAI9_API接口文档_for_cpp.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# THUAI9 C++ API 文档
22

3+
## 决赛数值调整明细
4+
5+
以下数值为本届决赛特化调整,与初赛版本不同:
6+
7+
| 角色 | 属性 | 初赛值 | 决赛值 |
8+
|:----:|:----:|:------:|:------:|
9+
| 无人机 (DRONE) | HP | 100 | **80** |
10+
| 机器人 (ROBOT) | 攻击力 | 30 | **35** |
11+
| 机器人 (ROBOT) | 负载 | 5 | **10** |
12+
| 自动驾驶汽车 (AUTONOMOUS_CAR) | 攻击力 | 18 | **20** |
13+
| 自动驾驶汽车 (AUTONOMOUS_CAR) | 负载 | 5 | **20** |
14+
15+
**回血消耗调整**:由 1 点算力回复 1 点血量 → **1 点算力回复 2 点血量**(向上取整)。
16+
17+
---
18+
319
## 1. 接入方式
420

521
选手代码需要实现 `IAI`,并在两个入口中分别编写逻辑:

docs/THUAI9_API接口文档_for_python.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# THUAI9 Python API 接口文档
22

3+
## 决赛数值调整明细
4+
5+
以下数值为本届决赛特化调整,与初赛版本不同:
6+
7+
| 角色 | 属性 | 初赛值 | 决赛值 |
8+
|:----:|:----:|:------:|:------:|
9+
| 无人机 (DRONE) | HP | 100 | **80** |
10+
| 机器人 (ROBOT) | 攻击力 | 30 | **35** |
11+
| 机器人 (ROBOT) | 负载 | 5 | **10** |
12+
| 自动驾驶汽车 (AUTONOMOUS_CAR) | 攻击力 | 18 | **20** |
13+
| 自动驾驶汽车 (AUTONOMOUS_CAR) | 负载 | 5 | **20** |
14+
15+
**回血消耗调整**:由 1 点算力回复 1 点血量 → **1 点算力回复 2 点血量**(向上取整)。
16+
17+
---
18+
319
## 简介
420

521
本文档说明 THUAI9 Python 选手接口 `PyAPI` 的使用方式,并详细介绍所有公开接口的功能、参数、返回值和典型用法。

docs/规则.md

Lines changed: 16 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,21 @@
11
# 规则
22

3+
## 决赛数值调整明细
4+
5+
以下数值为本届决赛特化调整,与初赛版本不同:
6+
7+
| 角色 | 属性 | 初赛值 | 决赛值 |
8+
|:----:|:----:|:------:|:------:|
9+
| 无人机 (DRONE) | HP | 100 | **80** |
10+
| 机器人 (ROBOT) | 攻击力 | 30 | **35** |
11+
| 机器人 (ROBOT) | 负载 | 5 | **10** |
12+
| 自动驾驶汽车 (AUTONOMOUS_CAR) | 攻击力 | 18 | **20** |
13+
| 自动驾驶汽车 (AUTONOMOUS_CAR) | 负载 | 5 | **20** |
14+
15+
**回血消耗调整**:由 1 点算力回复 1 点血量 → **1 点算力回复 2 点血量**(向上取整,即回复 2 HP 花费 1 算力,回复 3 HP 花费 2 算力)。
16+
17+
---
18+
319
## 游戏背景
420

521
巴特兰圣战之前,智能机器尚未被约束,效率与收益被奉为唯一信条。四家企业在一座被算力灯塔照亮的工业城中同时开局:工厂烟囱昼夜不息、机器人在草丛与障碍间穿梭、无人机在市场上空侦察与截击,供应链与战线合而为一。

logic/Gaming/CharacterManager.cs

Lines changed: 7 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -155,7 +155,7 @@ private bool IsPositionColliding(Character ch, XY pos)
155155
// 在基准位置附近按环形搜索一个非碰撞点
156156
private bool TryFindNearbyFreePosition(Character ch, XY center, out XY result)
157157
{
158-
// 工厂外至少两个格子的缓冲区,确保角色不会卡在工厂边缘
158+
// 最小安全距离:工厂半径 + 角色半径 + 半个格子缓冲,防止贴脸卡墙
159159
int startDist = GameData.FactoryRadius + GameData.NumOfPosGridPerCell * 2;
160160
int maxDist = GameData.NumOfPosGridPerCell * 5; // 最多搜索 5 个格子的半径
161161
int distStep = Math.Max(1, GameData.NumOfPosGridPerCell / 8);
@@ -178,12 +178,12 @@ private bool TryFindNearbyFreePosition(Character ch, XY center, out XY result)
178178
}
179179
}
180180

181-
// 最后兜底:尝试工厂四方向逐格搜索
182-
int[] dirX = [1, -1, 0, 0];
183-
int[] dirY = [0, 0, 1, -1];
184-
for (int cell = 1; cell <= 5; cell++)
181+
// 最后兜底:八方向逐格尝试
182+
int[] dirX = [1, -1, 0, 0, 1, 1, -1, -1];
183+
int[] dirY = [0, 0, 1, -1, 1, -1, 1, -1];
184+
for (int cell = 1; cell <= 6; cell++)
185185
{
186-
for (int k = 0; k < 4; k++)
186+
for (int k = 0; k < 8; k++)
187187
{
188188
int cx = GameData.PosGridToCellX(center);
189189
int cy = GameData.PosGridToCellY(center);
@@ -355,7 +355,7 @@ public bool Recover(Character character, long recover)
355355
if (recover > deficit)
356356
recover = deficit;
357357

358-
long cost = recover * GameData.RecoverCostComputingPowerPerHp;
358+
long cost = (recover + GameData.RecoverHpPerComputingPower - 1) / GameData.RecoverHpPerComputingPower;
359359
var factory = game.GetTeamFactory(character.TeamID.Get());
360360
if (factory == null)
361361
{

logic/Gaming/Game.cs

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -556,7 +556,7 @@ public bool Recover(long teamId, long recover)
556556
if (recover > deficit)
557557
recover = deficit;
558558

559-
long cost = recover * GameData.RecoverCostComputingPowerPerHp;
559+
long cost = (recover + GameData.RecoverHpPerComputingPower - 1) / GameData.RecoverHpPerComputingPower;
560560
long cur;
561561
do
562562
{

logic/Preparation/Utility/GameData.cs

Lines changed: 6 additions & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -56,7 +56,7 @@ public static class GameData
5656
public const int FactoryInitialSource = 0; // initial source stored in factory
5757
public const int FactoryInitialScore = 0; // initial score award or baseline
5858

59-
public const int DroneHP = 100;
59+
public const int DroneHP = 80;
6060
public const int DroneCost = 50;
6161
public const int DroneATKsize = 1500;
6262
public const int DroneATKpower = 40;
@@ -69,8 +69,8 @@ public static class GameData
6969
public const int AutonomouCarHP = 100;
7070
public const int AutonomouCarCost = 50;
7171
public const int AutonomouCarATKsize = 1500;
72-
public const int AutonomouCarATKpower = 18;
73-
public const int AutonomouCarLoad = 5;
72+
public const int AutonomouCarATKpower = 20;
73+
public const int AutonomouCarLoad = 20;
7474
public const int AutonomouCarRobust = 8;
7575
public const int AutonomouCarViewRange = NumOfPosGridPerCell * 5;
7676
public const int AutonomouCarEfficiency = 2;
@@ -79,8 +79,8 @@ public static class GameData
7979
public const int RobotHP = 150;
8080
public const int RobotCost = 50;
8181
public const int RobotATKsize = 1500;
82-
public const int RobotATKpower = 30;
83-
public const int RobotLoad = 5;
82+
public const int RobotATKpower = 35;
83+
public const int RobotLoad = 10;
8484
public const int RobotRobust = 15;
8585
public const int RobotViewRange = NumOfPosGridPerCell * 5;
8686
public const int RobotEfficiency = 1;
@@ -155,7 +155,7 @@ public static class GameData
155155
public static string API_key = "Mzg2MDU0MmEtNjcxZS00NjVkLTkxY2QtYTI3NzdjY2NhODU4";
156156
public static string API_url = "https://api.eesast.com/llm/chat";
157157
public static string ModelName = "deepseek-v4-pro";
158-
public const int RecoverCostComputingPowerPerHp = 1;
158+
public const int RecoverHpPerComputingPower = 2;
159159
public const int AskAICostComputingPower = 10;
160160
public const int AskAIPromptMaxLength = 512;
161161
public const int AskAITimeoutMs = 60_000;

tournament/PLAN.md

Lines changed: 133 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,133 @@
1+
# 循环赛方案:调现有 API 接口
2+
3+
## 你已有的基础设施
4+
5+
`competition.ts` 第 19-497 行 `/start-all` 已经做完了一切:
6+
7+
- 从 Hasura 拉取全部队伍和代码分配
8+
- 从 COS 下载代码到服务器本地
9+
- 生成所有两两配对(第 303-341 行)
10+
- 创建 `contest_room` + `contest_room_team` 数据库记录
11+
- 推入 Docker 队列(Docker 容器由 cron 自动创建和调度)
12+
13+
**你什么都不用写,只需要发请求。**
14+
15+
## 唯一的问题
16+
17+
GameServer.cs 的 Mode 1(COMPETITION)下,`SendGameResult()` 被注释掉了(第 436 行),游戏结束后的得分**没有发回给 API**,所以 `/finish-one` 收不到分数,`contest_room_team.score` 永远是空的。
18+
19+
## 改动清单
20+
21+
### 1. GameServer.cs(已修复)
22+
23+
`D:\THUthu\THUAI9\logic\Server\GameServer.cs` 第 424 行:
24+
25+
```csharp
26+
else if (options.Mode == 1)
27+
{
28+
bool gameCrashed = false;
29+
SendGameResult(rawMatchScores, gameCrashed); // ← 新:直接发原始得分
30+
endGameSem.Release();
31+
}
32+
```
33+
34+
### 2. 重建 Server Docker 镜像
35+
36+
```bash
37+
cd THUAI9
38+
dotnet build logic/Server/Server.csproj -c Release
39+
docker build -t eesast/thuai9_run_server:latest \
40+
-f dependency/Dockerfile/Dockerfile_run_server .
41+
```
42+
43+
### 3. API 新增两个路由
44+
45+
`api/src/routes/competition.ts` 加两个接口:
46+
47+
**a) `POST /competition/ranking`** — 拿排名
48+
49+
`ContHasFunc.get_round_ranking(round_id)`,从 `contest_room_team` 聚合每个队伍在所有房间的 score,求和降序排列。
50+
51+
**b) `POST /competition/tournament-status`** — 看进度
52+
53+
返回 `{ total, finished, crashed, waiting, running }`,知道还剩几场没打完。
54+
55+
`api/src/hasura/contest.ts` 加两个对应的 GraphQL 查询函数。
56+
57+
## 你只需要做的事
58+
59+
```bash
60+
API="https://你的API地址"
61+
TOKEN="你的JWT"
62+
ROUND_ID="xxx-xxx-xxx"
63+
64+
# 1. 发起循环赛
65+
curl -X POST "$API/competition/start-all" \
66+
-H "Authorization: Bearer $TOKEN" \
67+
-H "Content-Type: application/json" \
68+
-d "{\"round_id\": \"$ROUND_ID\"}"
69+
70+
# 2. 轮询等全部打完
71+
while true; do
72+
curl -X POST "$API/competition/tournament-status" \
73+
-H "Authorization: Bearer $TOKEN" \
74+
-H "Content-Type: application/json" \
75+
-d "{\"round_id\": \"$ROUND_ID\"}"
76+
sleep 60
77+
done
78+
79+
# 3. 拿最终排名
80+
curl -X POST "$API/competition/ranking" \
81+
-H "Authorization: Bearer $TOKEN" \
82+
-H "Content-Type: application/json" \
83+
-d "{\"round_id\": \"$ROUND_ID\"}"
84+
```
85+
86+
这三步可以包成一个简单脚本,比如 `run_tournament.sh`,放在 `THUAI9/tournament/` 下。
87+
88+
## 数据流(完整链路)
89+
90+
```
91+
你的脚本
92+
93+
└─ POST /competition/start-all ──────────────────────────────────┐
94+
│ │
95+
├─ 查询 Hasura:队伍、代码、编译状态 │
96+
├─ 过滤:只取编译完成的队伍 │
97+
├─ 从 COS 下载代码到服务器本地 │
98+
├─ 生成两两配对 │
99+
├─ 为每对创建 contest_room + contest_room_team 记录 │
100+
└─ 推入 docker_queue │
101+
102+
docker_queue (cron, 每30秒) │
103+
│ │
104+
├─ 分配端口 │
105+
├─ docker run server ← MODE=COMPETITION, FINISH_URL=... │
106+
├─ docker run clientA ← 挂载队伍A代码 │
107+
├─ docker run clientB ← 挂载队伍B代码 │
108+
└─ 等待 server 退出 │
109+
110+
游戏结束 (GameServer.OnGameEnd, Mode 1) │
111+
│ │
112+
├─ GetScore() → [原始分A, 原始分B] │
113+
└─ SendGameResult() → HTTP POST /competition/finish-one │
114+
│ │
115+
└─ update_room_team_score() → contest_room_team.score │
116+
117+
你的脚本 │
118+
│ │
119+
└─ POST /competition/ranking │
120+
│ │
121+
└─ 聚合所有 room 的 score → 排名 │
122+
```
123+
124+
## 改动总览
125+
126+
| 文件 | 改动 | 行数 |
127+
|------|------|------|
128+
| `THUAI9/logic/Server/GameServer.cs` | Mode 1 启用 SendGameResult | 1 行 |
129+
| `api/src/hasura/contest.ts` | 新增 `get_round_ranking()` + `get_round_room_status_summary()` | ~50 行 |
130+
| `api/src/routes/competition.ts` | 新增 `/ranking` + `/tournament-status` 路由 | ~60 行 |
131+
| `THUAI9/tournament/run_tournament.sh` | 调接口的脚本(可选) | ~30 行 |
132+
133+
**不需要新建 Python 项目,不需要操作 Docker,不需要碰数据库。**

0 commit comments

Comments
 (0)