# TuringGame2020 选手手册
[TOC]
## **一、背景介绍**
在一颗遥远的星球上,一片四面临海的大陆栖息着四个不同国家的人们。由于国家利益间的冲突日趋激烈,四位国家统领都萌发出了统一这片大陆的野心。而一场突如其来的瘟疫席卷了这片大陆,四个国家的人民都因此不断衰弱,统一大陆的行动迫在眉睫。玩家扮演统治者角色,通过训练士兵增强实力,进攻其它国家的同时,防御他国攻击。夺取大陆中心的净化泉水可以免疫病毒的侵蚀,增强军队抵抗力和战斗力。
游戏中,每位玩家扮演一个国家势力的首领,可以训练不同兵种的士兵。在规定时间和限定的区域内,玩家需要攻击和防御其他玩家的进攻,通过各种策略攻破象征其他玩家政权存活的城池,征服其他国家从而取得游戏胜利。
## **二、游戏进程**
游戏总时间120秒。玩家在由方格块组成的世界中进行游戏,初始时,玩家持有金额$100并占有地图一角的基地。玩家可以在游戏世界中以“格”为单位移动,可以选择兵贵神速征服邻国,也可以先攻击超级泉水获得增益机会而慢慢发育。杀死敌方单位会获得金币,金币可用于购买新的士兵。
至游戏最后30秒时,所有士兵攻击速度变为原来的两倍;在此之前未攻击过泉水国家的所有士兵进入衰弱状态,生命上限降低为原来的2/3。
游戏过程中若只剩一名玩家扮演的政权存在,则比赛立即结束,并进行分数结算。
## **三、单位信息**
### **地图**
尺寸:40*40,起始点坐标为(1,1),终止点坐标为(40,40)
在地图范围内无障碍物,单一方格可以重叠无穷个士兵
### **士兵**
士兵分为三种类型,分别为:近战型士兵、治疗型士兵、远程型士兵
#### 近战型
|基础属性\状态|普通状态|增益状态|
| --- | --- | --- |
生命值|120|150
攻击力|20/次|25/次
攻击范围|1格|1格
攻击频率|1次/s|1次/s
移动速度|2格/s|3格/s
购买价格|$10|$10+1次增益机会
击杀收益|$8|$8
#### 治疗型
|基础属性\状态|普通状态|增益状态|
| --- | --- | --- |
生命值|50|75
攻击力|5/次|10/次
攻击范围|3格|4格
攻击频率|1次/s|1次/s
治疗效果|10/次|15/次
治疗范围|3格|4格
治疗频率|1次/s|1.5次/s
移动速度|2格/s|3格/s
购买价格|$10|$10+1次增益机会
击杀收益|$8|$8
#### 远程型
|基础属性\状态|普通状态|增益状态|
| --- | --- | --- |
生命值|50|75
攻击力|35/次|45/次
攻击范围|3格|4格
攻击频率|1次/s|1次/s
移动速度|2格/s|3格/s
购买价格|$12|$12+1次增益机会
击杀收益|$9|$9
### **基地**
|基础属性|数值|
| --- | --- |
生命值|200
被摧毁收益|对该国基地输出伤害/2+1(其余三国人人有份)
占地面积|2*2
位置|国家一(1:2,1:2),国家二(1:2,39:40),国家三(39:40,1:2),国家四(39:40,39:40)
士兵出生点|国家一(2,2),国家二(2,39),国家三(39,2),国家四(39,39)
### **泉水**
|基础属性|数值|
| --- | --- |
生命值|100
攻击收益|每10点攻击输出转为1次增益机会
占地面积|4*4
位置|(19:22,19:22)
## **四、基础类申明**
### **Ranker**
基础属性
|数据类型|数据名称|数据释义|
|--|--|--|
int|ID|唯一身份编号
int|typeID|兵种(近战型1,治疗型2,远程型3)
int|countryID|国家编号
int|x, y|当前坐标(假设移动时角色从点A移动到点B,则前0.25s坐标为A,后0.25s坐标为B)
int|direction|角色朝向(1:x-,2:x+,3:y-,4:y+)
bool|isMoving|是否处于移动状态
int|state|体质状态(普通0,虚弱1,增益2)
bool|alive|是否存活
int|health|生命值
int|healthLimit|生命值上限
int|atk|攻击力
float|frequency|攻击频率
float|atkCd|攻击的技能冷却时间(frequency=1/atkCd)
int|bonus|该角色被击杀后杀手可获得的奖励
float|speed|移动速度
攻击/治疗通用属性
|数据类型|数据名称|数据释义|
|--|--|--|
int|range|攻击(治疗)范围
float|cdTimer|技能(攻击/治疗)冷却倒计时计时器(值为0时角色可以发动技能,否则需要等待该数据值的时间后才可以发动技能)
治疗型专属属性(非治疗型士兵此条目下的数据值为0)
|数据类型|数据名称|数据释义|
|--|--|--|
int|treat|治疗能力(单次治疗可恢复的血量)
float|treatFrequency|治疗频率
float|treatCd|治疗的技能冷却时间(treatFrequency=1/treatCd)
### **Country**
|数据类型|数据名称|数据释义|
|--|--|--|
bool|alive|是否存活
int|id|国家编号
int|health|该国家基地生命值(初值为200)
int|money|金钱(初值为100)
int|soldierNum|拥有存活士兵数量
int|soldierAllNum|所有士兵数量(含已死亡)
int|chance|拥有增益机会(需要通过攻击泉水获得)
### **Spring**
|数据类型|数据名称|数据释义|
|--|--|--|
bool|alive|是否存活
int|health|生命值(初值为100)
## **五、选手方法**
### **获取信息型**
`Ranker GetRankerInfo(int rankerID)`
**用途**:获取指定士兵信息
**参数**:
rankerID-目标士兵编号
**返回**:返回一个Ranker对象,详情请参考Ranker类申明
<br/> <br/>
`Country GetCountryInfo(int countryID)`
**用途**:获取指定国家信息
**参数**:
countryID-目标国家编号
**返回**:返回一个Country对象,详情请参考Country类申明
<br/> <br/>
`Spring GetSpringInfo()`
**用途**:获取泉水信息
**返回**:返回一个Spring对象,详情请参考Spring类申明
<br/> <br/>
`float GetLeftTime()`
**用途**:获取当前比赛倒计时
**返回**:返回一个范围为[0,120]的浮点型数值
<br/> <br/>
`int GetMapCubeType(int x, int y)`
**用途**:获取地图上指定位置的方格类型
**参数**:
x-坐标X
y-坐标Y
**返回**:返回一个整型:空地0,国家基地1-4,泉水5,超范围-1
<br/> <br/>
`List<int> GetStandList(int x, int y)`
**用途**:获取地图上指定位置的士兵列表
**参数**:
x-坐标X
y-坐标Y
**返回**:返回一个填充了士兵ID的整型List
<br/> <br/>
`List<int> GetRankerList(int countryID)`
**用途**:获取指定国家的现存士兵ID列表
**参数**:
countryID-目标国家编号
**返回**:返回一个填充了士兵ID的整型List
<br/> <br/>
`int GetScore(int countryID)`
**用途**:获取指定国家的当前得分
**参数**:countryID-目标国家编号
**返回**:返回一个整型
<br/> <br/><br/>
### **控制角色型**
`int BuyRanker(int typeID, bool isUpgraded)`
**用途**:购买指定类型的士兵
**参数**:
typeID-类型编号:近战型1,治疗型2,远程型3
isUpgraded-是否为增益士兵(攻击泉水以获取增益机会)
**返回**:返回一个整型,成功则返回新购士兵的编号(编号大于100),否则:余额不足1,增益次数不足2,国家已死亡3,发起非本国交易4,其他错误5
<br/> <br/>
`int AttackRanker(int aID, int bID)`
**用途**:攻击指定的士兵
**参数**:
aID-攻击者编号(只能为本国士兵)
bID-受害者编号
**返回**:返回一个整型:成功0,攻击者冷却中1,超出范围2,攻击者移动中3,受害者为同国士兵4,攻击者或受害者已死亡5,操控非本国士兵6,其他错误7
<br/> <br/>
`int AttackCountry(int aID, int countryID)`
**用途**:攻击指定的国家基地
**参数**:
aID-攻击者编号(只能为本国士兵)
countryID-国家编号
**返回**:返回一个整型:成功0,攻击者冷却中1,超出范围2,攻击者在移动3,攻击自家基地4,攻击者或目标基地已死亡5,操控非本国士兵6,其他错误7
<br/> <br/>
`int AttackSpring(int aID)`
**用途**:攻击泉水
**参数**:
aID-攻击者编号(只能为本国士兵)
**返回**:返回一个整型:成功0,攻击者冷却中1,超出范围2,攻击者在移动3,攻击者或泉水已死亡4,操控非本国士兵5,其他错误6
<br/> <br/>
`int CureRanker(int aID, int bID)`
**用途**:治疗指定的士兵
**参数**:
aID-治疗者编号(只能为本国士兵)
bID-受益者编号(只能为本国士兵)
**返回**:返回一个整型:成功0,治疗者冷却中1,超出范围2,受益者满血3,受益者为敌方4,治疗者不为治疗型士兵5,受益者已死亡6,尝试为自己治疗7,操控非本国士兵8,其他错误9
<br/> <br/>
`int MoveRanker(int aID, int direction)`
**用途**:将指定的士兵向指定方向移动一格
**参数**:
aID-士兵编号(只能为本国士兵)
direction-方向编号,1:x-,2:x+,3:y-,4:y+
**返回**:返回一个整型:成功0,士兵正在移动1,遇到边界2,士兵已死亡3,方向参数错误4,操控非本国士兵5,其他6
<br/> <br/><br/>
### **调试辅助型**
`void TrackRanker(int ID)`
**用途**:跟踪指定的士兵,该士兵的信息将会显示在游戏界面中
**参数**:
ID-士兵编号
<br/> <br/>
`void ControlRanker(int aID, int bID, int countryID)`
**用途**:使用键盘控制指定的士兵a(仅供测试,正式比赛时会被禁用)
WASD移动,H治疗,J攻击士兵bID,K攻击国家countryID,L攻击泉水
**参数**:
aID-被控制士兵a编号
bID-a将会攻击/治疗的士兵b编号(bID会在a执行AttackRanker或CureRanker时作为bID传入)
cID-a将会攻击的国家c编号(countryID会在a执行AttackCountry时作为countryID传入)
<br/> <br/>
`void Log(string msg)`
**用途**:输出调试日志,日志将会显示在游戏界面中
**参数**:
msg-调试信息
## **六、异常处理与游戏公平性**
### **代码被抛出(出现错误)/代码运行超时(超过0.02s)**
* 如果是代码出错被抛出,相关的错误信息会显示在游戏内的控制台面板中(按游戏左上角暂停键或Esc查看);同时此选手的代码会被立即强制停止,平台开始依次运行其后等待执行的所有选手代码
* 如果是代码运行超时,该选手的代码会被强制结束,同时由于单一执行周期的允许时间截止,其后等待执行的所有选手代码也将被强制停止,平台将开始下一周期的运行
### **问题代码对其他代码运行的影响**
#### **平台执行逻辑**
由于Unity游戏引擎自身的原因,选手代码的调用无法使用多线程同时操作的方式,因此平台采用公平轮流单线程制依次调用选手代码;具体的机制如下
> 现有选手A,B,C,D参加图灵杯2020游戏,那么这四位选手的代码执行顺序为:
> 第一个执行周期:A-B-C-D
> 第二个执行周期:B-A-D-C
> 第三个执行周期:C-D-A-B
> 第四个执行周期:D-C-B-A
> 第五个执行周期(同周期一):A-B-C-D
> ……
这样以每四个周期为一个循环的调用顺序使得各位选手的代码都有公平的机会被优先调用,并且任一超时代码对其他选手代码执行的影响次数也相同;出错抛出的代码对其他代码的执行没有影响
我们举两个例子来说明该机制的公平性
**例子1**
> 现有选手A,B,C,D参加图灵杯2020游戏,假设选手B的代码存在超时问题,一周期内实际被有效执行的选手代码如下
> 周期一:A
> 周期二:
> 周期三:C-D-A
> 周期四:D-C
> 其他三个选手的代码均在该周期内被执行了两次,总运行顺序为A-C-D-A-D-C,运行频率由理论值4次/周期降为2次/周期
**例子2**
> 现有选手A,B,C,D参加图灵杯2020游戏,假设选手A、C的代码均存在超时问题,一周期内实际被有效执行的选手代码如下
> 周期一:
> 周期二:B
> 周期三:
> 周期四:D
> 其他两个选手的代码均在该周期内被执行了一次,总运行顺序为B-D,运行频率由理论值4次/周期降为1次/周期
#### **强制退赛机制**
* 当选手的代码第一次出现超时或抛出现象时,平台会发出警告(宽容时间为0.12秒),接下来平台依旧按照正常顺序调用所有代码(包括被警告的代码),并暂停对该选手代码异常现象的警告3秒(即在这3秒内如果代码仍有异常不会发出警告,其他不变),3秒之后平台继续正常监控该选手代码的异常
* 如果一个选手的代码被警告异常超过3次,则该选手所控制国家立即视为死亡,直接等待游戏结束后计算得分,平台自动跳过该选手代码的执行
* 此机制对问题代码的宽容时间大于9s,如果不是严重的代码错误无需过于担心;但是需要注意的是,**正式比赛前我们会要求在试运行时被平台警告过的代码作者修改至代码不出现警告,否则不允许参加比赛**
## **七、评分标准**
**得分=该国家输出的伤害*0.5+存活士兵转击杀收益+剩余金钱**
> 输出伤害指该国家所有士兵对别国士兵、别国基地、泉水造成伤害之和
> 存活士兵转击杀收益可以视为:在结束时平台杀死了该国的所有士兵,击杀这些士兵获得的收益归到该国的得分中
## **八、其他说明**
1. 当某个国家的基地被摧毁时,该国家金钱之外的一切数据都会被清零,该国的所有士兵也会立即死亡,以这样的方式死亡不计算士兵的击杀收益;此后,平台会自动跳过该选手代码的执行,直到游戏结束计算最终得分
2. 本届图灵杯允许玩家自由控制和分配购得的每一个士兵,对于每个单一士兵的控制都会通过该士兵的唯一身份编号(ID)实现
3. 对于技能距离的计算使用以下公式:
![](https://img.kancloud.cn/24/82/2482a1611b18614af2ce807651a7523b_229x32.png)