“裁判”的版本间的差异
来自Botzone Wiki
Administrator(讨论 | 贡献) 小 |
(此版本已被标记将进行翻译) |
||
(未显示2个用户的5个中间版本) | |||
第1行: | 第1行: | ||
− | 裁判是[[Botzone]]进行[[对局]]评测的后台程序,同时也是每个[[游戏]]必不可少的部分。 | + | <languages/> |
+ | <translate> | ||
+ | <!--T:1--> | ||
+ | 裁判是[[Special:MyLanguage/Botzone|Botzone]]进行[[Special:MyLanguage/对局|对局]]评测的后台程序,同时也是每个[[Special:MyLanguage/游戏|游戏]]必不可少的部分。 | ||
− | 裁判与[[Bot]]一样可以用各种语言编写,主要作用是通过[[控制器]]接收各个玩家的输入并根据规则进行判断,然后给出下一回合的指令。 | + | <!--T:2--> |
+ | 裁判与[[Special:MyLanguage/Bot|Bot]]一样可以用各种语言编写,主要作用是通过[[Special:MyLanguage/控制器|控制器]]接收各个玩家的输入并根据规则进行判断,然后给出下一回合的指令。 | ||
+ | |||
+ | |||
+ | == 交互 == <!--T:3--> | ||
+ | |||
+ | <!--T:4--> | ||
+ | 裁判每回合开始时会被运行一次,每次生命周期均为一次输入、一次输出,每次输入会包括裁判和所有玩家以往跟平台的所有交互内容。交互格式为'''单行[[Special:MyLanguage/JSON|JSON]]'''。 | ||
+ | |||
+ | <!--T:5--> | ||
+ | 因此,裁判的程序运行流程应当是: | ||
+ | *启动程序 | ||
+ | *从平台获取以往的交互内容和上回合玩家输出的response | ||
+ | *根据获得的交互内容(自己以前发出的request + 玩家输出的response)进行计算 | ||
+ | **恢复局面到最新状态 | ||
+ | **根据玩家的上回合response演算下一局面 | ||
+ | ***如果游戏结束,给出玩家分数 | ||
+ | ***如果游戏继续,则确定哪些玩家应当进行动作,并给这些玩家发送request(只有被发送request的玩家才会启动) | ||
+ | *关闭程序 | ||
+ | |||
+ | |||
+ | ===资源限制=== <!--T:6--> | ||
+ | |||
+ | <!--T:7--> | ||
+ | 同[[Special:MyLanguage/Bot#资源限制|Bot#资源限制]]。 | ||
+ | |||
+ | |||
+ | ===交互格式=== <!--T:8--> | ||
+ | |||
+ | |||
+ | ===='''裁判得到的输入'''==== <!--T:9--> | ||
+ | |||
+ | <!--T:10--> | ||
+ | <syntaxhighlight lang="javascript"> | ||
+ | { | ||
+ | "log": [ | ||
+ | { | ||
+ | "memory": 2, | ||
+ | "output": { | ||
+ | "command": "request", | ||
+ | "content": ..., | ||
+ | "display": ... | ||
+ | }, // 这里是裁判输出的request的主体 | ||
+ | "time": 2, | ||
+ | "verdict": "OK" | ||
+ | }, // 第0、2、4、...项,表示裁判第1、2、3...回合的输出 | ||
+ | { | ||
+ | "0": { | ||
+ | "memory": 2, | ||
+ | "time": 9, | ||
+ | "verdict": "OK", | ||
+ | "response": ... // 这里是玩家输出的response的主体 | ||
+ | } | ||
+ | }, // 第1、3、5、...项,表示玩家们第1、2、3...回合的输出 | ||
+ | ... | ||
+ | ], | ||
+ | "initdata": "" // 初始化数据 | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ===='''裁判应该给出的输出'''==== <!--T:11--> | ||
+ | |||
+ | <!--T:12--> | ||
+ | 如果游戏继续: | ||
+ | <syntaxhighlight lang="javascript"> | ||
+ | { | ||
+ | "command": "request", | ||
+ | "content": { | ||
+ | "0": ... // 要运行的玩家和给它的request | ||
+ | }, | ||
+ | "display": ... // 给播放器的信息,可以是JSON对象 | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | <!--T:13--> | ||
+ | 如果游戏结束: | ||
+ | <syntaxhighlight lang="javascript"> | ||
+ | { | ||
+ | "command": "finish", | ||
+ | "content": { | ||
+ | "0": 1, // 每个玩家的分数 | ||
+ | "1": 2 | ||
+ | }, | ||
+ | "display": ... // 给播放器的信息,可以是JSON对象 | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | |||
+ | ====关于 initdata==== <!--T:14--> | ||
+ | |||
+ | <!--T:15--> | ||
+ | initdata 是指裁判程序的初始化数据,通常用于指定随机种子、地图大小、初始手牌等参数。 | ||
+ | |||
+ | <!--T:16--> | ||
+ | 在第一回合,裁判收到的 initdata 可能是一个字符串或者对象,为用户或比赛开启对局时所指定的 initdata。 | ||
+ | |||
+ | <!--T:17--> | ||
+ | 在第一回合,裁判有机会在输出对象中的 initdata 域里写入初始化数据(字符串或对象)并保存,此后回合收到的 initdata 均为这次输出的 initdata。通常用于当用户没有指定随机种子的时候保存自己产生的随机种子,或者保存一个通过随机种子产生的地图地形或初始手牌信息等。 | ||
+ | |||
+ | |||
+ | ==样例程序== <!--T:18--> | ||
+ | |||
+ | <!--T:19--> | ||
+ | 以下给出C++的[[Special:MyLanguage/JSON|JSON]]裁判样例程序: | ||
+ | |||
+ | <!--T:20--> | ||
+ | 本地编译的方式请查看 [[Special:MyLanguage/JSONCPP|JSONCPP]]。 | ||
+ | |||
+ | <!--T:21--> | ||
+ | <syntaxhighlight lang="cpp"> | ||
+ | #include <iostream> | ||
+ | #include <sstream> | ||
+ | #include <string> | ||
+ | #include "jsoncpp/json.h" | ||
+ | using namespace std; | ||
+ | |||
+ | |||
+ | <!--T:22--> | ||
+ | // 注意黑方为0号玩家 | ||
+ | int currBotColor; // 正在等待输出结果的BOT | ||
+ | int gridInfo[8][8] = { 0 }; // 先x后y | ||
+ | int blackPieceCount = 2, whitePieceCount = 2; | ||
+ | string blackName = "", whiteName = ""; | ||
+ | |||
+ | <!--T:23--> | ||
+ | static bool MoveStep(int &x, int &y, int Direction) | ||
+ | { | ||
+ | if (Direction == 0 || Direction == 6 || Direction == 7) | ||
+ | x++; | ||
+ | if (Direction == 0 || Direction == 1 || Direction == 2) | ||
+ | y++; | ||
+ | if (Direction == 2 || Direction == 3 || Direction == 4) | ||
+ | x--; | ||
+ | if (Direction == 4 || Direction == 5 || Direction == 6) | ||
+ | y--; | ||
+ | if (x < 0 || x > 7 || y < 0 || y > 7) | ||
+ | return false; | ||
+ | return true; | ||
+ | } | ||
+ | |||
+ | <!--T:24--> | ||
+ | bool ProcStep(int xPos, int yPos, int color, bool checkOnly = false) | ||
+ | { | ||
+ | if (xPos == -1) | ||
+ | return true; | ||
+ | if (xPos < 0 || xPos > 7 || yPos < 0 || yPos > 7) | ||
+ | return false; | ||
+ | int effectivePoints[8][2]; | ||
+ | int dir, x, y, currCount; | ||
+ | bool isValidMove = false; | ||
+ | if (gridInfo[xPos][yPos] != 0) | ||
+ | return false; | ||
+ | for (dir = 0; dir < 8; dir++) | ||
+ | { | ||
+ | x = xPos; | ||
+ | y = yPos; | ||
+ | currCount = 0; | ||
+ | while (1) | ||
+ | { | ||
+ | if (!MoveStep(x, y, dir)) | ||
+ | { | ||
+ | currCount = 0; | ||
+ | break; | ||
+ | } | ||
+ | if (gridInfo[x][y] == -color) | ||
+ | { | ||
+ | currCount++; | ||
+ | effectivePoints[currCount][0] = x; | ||
+ | effectivePoints[currCount][1] = y; | ||
+ | } | ||
+ | else if (gridInfo[x][y] == 0) | ||
+ | { | ||
+ | currCount = 0; | ||
+ | break; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | break; | ||
+ | } | ||
+ | } | ||
+ | if (currCount != 0) | ||
+ | { | ||
+ | isValidMove = true; | ||
+ | if (checkOnly) | ||
+ | return true; | ||
+ | if (color == 1) | ||
+ | { | ||
+ | blackPieceCount += currCount; | ||
+ | whitePieceCount -= currCount; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | whitePieceCount += currCount; | ||
+ | blackPieceCount -= currCount; | ||
+ | } | ||
+ | while (currCount > 0) | ||
+ | { | ||
+ | x = effectivePoints[currCount][0]; | ||
+ | y = effectivePoints[currCount][1]; | ||
+ | gridInfo[x][y] *= -1; | ||
+ | currCount--; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | if (isValidMove) | ||
+ | { | ||
+ | gridInfo[xPos][yPos] = color; | ||
+ | if (color == 1) | ||
+ | blackPieceCount++; | ||
+ | else | ||
+ | whitePieceCount++; | ||
+ | return true; | ||
+ | } | ||
+ | else | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | <!--T:25--> | ||
+ | bool CheckIfHasValidMove(int color) | ||
+ | { | ||
+ | int x, y; | ||
+ | for (y = 0; y < 8; y++) | ||
+ | for (x = 0; x < 8; x++) | ||
+ | if (ProcStep(x, y, color, true)) | ||
+ | return true; | ||
+ | return false; | ||
+ | } | ||
+ | |||
+ | <!--T:26--> | ||
+ | int main() | ||
+ | { | ||
+ | string str; | ||
+ | getline(cin, str); | ||
+ | Json::Reader reader; | ||
+ | Json::Value input, output; | ||
+ | reader.parse(str, input); | ||
+ | input = input["log"]; | ||
+ | |||
+ | |||
+ | <!--T:27--> | ||
+ | gridInfo[3][4] = gridInfo[4][3] = 1; //|白|黑| | ||
+ | gridInfo[3][3] = gridInfo[4][4] = -1; //|黑|白| | ||
+ | currBotColor = 1; // 先手为黑 | ||
+ | if (input.size() == 0) | ||
+ | { | ||
+ | output["display"] = ""; | ||
+ | output["command"] = "request"; | ||
+ | output["content"]["0"]["x"] = -1; | ||
+ | output["content"]["0"]["y"] = -1; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | for (int i = 1; i < input.size(); i += 2) | ||
+ | { | ||
+ | bool isLast = i == input.size() - 1; | ||
+ | Json::Value content; | ||
+ | Json::Value display; | ||
+ | if (currBotColor == 1) // 0号玩家 / 黑方 | ||
+ | { | ||
+ | Json::Value answer = input[i]["0"]["response"].isNull() ? input[i]["0"]["content"] : input[i]["0"]["response"]; | ||
+ | if (((answer.isString() && | ||
+ | reader.parse(answer.asString(), content)) || | ||
+ | (answer.isObject() && | ||
+ | (content = answer, true))) && | ||
+ | content["x"].isInt() && content["y"].isInt()) // 保证输入格式正确 | ||
+ | { | ||
+ | int currX = content["x"].asInt(); | ||
+ | int currY = content["y"].asInt(); | ||
+ | if (currX == -1 && isLast) // bot选择PASS | ||
+ | { | ||
+ | if (!CheckIfHasValidMove(currBotColor)) // 他应该PASS | ||
+ | { | ||
+ | output["display"]["x"] = -1; | ||
+ | output["display"]["y"] = -1; | ||
+ | output["command"] = "request"; | ||
+ | output["content"]["1"]["x"] = -1; | ||
+ | output["content"]["1"]["y"] = -1; | ||
+ | } | ||
+ | else // 他不应该PASS | ||
+ | { | ||
+ | // Todo: Bug here-- | ||
+ | output["display"]["err"] = "HE_THOUGHT_THAT_HE_COULDNOT_MOVE_BUT_IN_FACT_HE_CAN"; | ||
+ | output["display"]["winner"] = 1; | ||
+ | output["command"] = "finish"; // 判输 | ||
+ | output["content"]["0"] = 0; | ||
+ | output["content"]["1"] = 2; | ||
+ | } | ||
+ | } | ||
+ | else if (!ProcStep(currX, currY, currBotColor) && isLast) // 不合法棋步! | ||
+ | { | ||
+ | output["display"]["err"] = "INVALIDMOVE"; | ||
+ | output["display"]["winner"] = 1; | ||
+ | output["command"] = "finish"; // 判输 | ||
+ | output["content"]["0"] = 0; | ||
+ | output["content"]["1"] = 2; | ||
+ | } | ||
+ | else if (isLast) // 正常棋步 | ||
+ | { | ||
+ | output["display"]["x"] = currX; | ||
+ | output["display"]["y"] = currY; | ||
+ | if (!CheckIfHasValidMove(currBotColor) && !CheckIfHasValidMove(-currBotColor)) // 游戏结束 | ||
+ | { | ||
+ | if (blackPieceCount > whitePieceCount) | ||
+ | { | ||
+ | output["display"]["winner"] = 0; | ||
+ | output["command"] = "finish"; | ||
+ | output["content"]["0"] = 2; | ||
+ | output["content"]["1"] = 0; | ||
+ | } | ||
+ | else if (blackPieceCount < whitePieceCount) | ||
+ | { | ||
+ | output["display"]["winner"] = 1; | ||
+ | output["command"] = "finish"; | ||
+ | output["content"]["0"] = 0; | ||
+ | output["content"]["1"] = 2; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | output["command"] = "finish"; | ||
+ | output["content"]["0"] = 1; | ||
+ | output["content"]["1"] = 1; | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | |||
+ | <!--T:28--> | ||
+ | output["display"]["x"] = currX; | ||
+ | output["display"]["y"] = currY; | ||
+ | output["command"] = "request"; | ||
+ | output["content"]["1"]["x"] = currX; | ||
+ | output["content"]["1"]["y"] = currY; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | else if (isLast) | ||
+ | { | ||
+ | output["display"]["err"] = "INVALIDMOVE"; | ||
+ | output["display"]["winner"] = 1; | ||
+ | output["command"] = "finish"; // 判输 | ||
+ | output["content"]["0"] = 0; | ||
+ | output["content"]["1"] = 2; | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | Json::Value answer = input[i]["1"]["response"].isNull() ? input[i]["1"]["content"] : input[i]["1"]["response"]; | ||
+ | if (((answer.isString() && | ||
+ | reader.parse(answer.asString(), content)) || | ||
+ | (answer.isObject() && | ||
+ | (content = answer, true))) && | ||
+ | content["x"].isInt() && content["y"].isInt()) // 保证输入格式正确 | ||
+ | { | ||
+ | int currX = content["x"].asInt(); | ||
+ | int currY = content["y"].asInt(); | ||
+ | if (currX == -1 && isLast) // bot选择PASS | ||
+ | { | ||
+ | if (!CheckIfHasValidMove(currBotColor)) // 他应该PASS | ||
+ | { | ||
+ | output["display"]["x"] = -1; | ||
+ | output["display"]["y"] = -1; | ||
+ | output["command"] = "request"; | ||
+ | output["content"]["0"]["x"] = -1; | ||
+ | output["content"]["0"]["y"] = -1; | ||
+ | } | ||
+ | else // 他不应该PASS | ||
+ | { | ||
+ | output["display"]["err"] = "HE_THOUGHT_THAT_HE_COULDNOT_MOVE_BUT_IN_FACT_HE_CAN"; | ||
+ | output["display"]["winner"] = 0; | ||
+ | output["command"] = "finish"; // 判输 | ||
+ | output["content"]["0"] = 2; | ||
+ | output["content"]["1"] = 0; | ||
+ | } | ||
+ | } | ||
+ | else if (!ProcStep(currX, currY, currBotColor) && isLast) // 不合法棋步! | ||
+ | { | ||
+ | output["display"]["err"] = "INVALIDMOVE"; | ||
+ | output["display"]["winner"] = 0; | ||
+ | output["command"] = "finish"; // 判输 | ||
+ | output["content"]["0"] = 2; | ||
+ | output["content"]["1"] = 0; | ||
+ | } | ||
+ | else if (isLast) // 正常棋步 | ||
+ | { | ||
+ | output["display"]["x"] = currX; | ||
+ | output["display"]["y"] = currY; | ||
+ | if (!CheckIfHasValidMove(currBotColor) && !CheckIfHasValidMove(-currBotColor)) // 游戏结束 | ||
+ | { | ||
+ | if (blackPieceCount > whitePieceCount) | ||
+ | { | ||
+ | output["display"]["winner"] = 0; | ||
+ | output["command"] = "finish"; | ||
+ | output["content"]["0"] = 2; | ||
+ | output["content"]["1"] = 0; | ||
+ | } | ||
+ | else if (blackPieceCount < whitePieceCount) | ||
+ | { | ||
+ | output["display"]["winner"] = 1; | ||
+ | output["command"] = "finish"; | ||
+ | output["content"]["0"] = 0; | ||
+ | output["content"]["1"] = 2; | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | output["command"] = "finish"; | ||
+ | output["content"]["0"] = 1; | ||
+ | output["content"]["1"] = 1; | ||
+ | } | ||
+ | } | ||
+ | else | ||
+ | { | ||
+ | output["command"] = "request"; | ||
+ | output["content"]["0"]["x"] = currX; | ||
+ | output["content"]["0"]["y"] = currY; | ||
+ | } | ||
+ | } | ||
+ | } | ||
+ | else if (isLast) | ||
+ | { | ||
+ | output["display"]["err"] = "INVALIDMOVE"; | ||
+ | output["display"]["winner"] = 0; | ||
+ | output["command"] = "finish"; // 判输 | ||
+ | output["content"]["0"] = 2; | ||
+ | output["content"]["1"] = 0; | ||
+ | } | ||
+ | } | ||
+ | currBotColor *= -1; | ||
+ | } | ||
+ | } | ||
+ | Json::FastWriter writer; | ||
+ | cout << writer.write(output) << endl; | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | </translate> |
2020年2月10日 (一) 15:53的最新版本
裁判是Botzone进行对局评测的后台程序,同时也是每个游戏必不可少的部分。
裁判与Bot一样可以用各种语言编写,主要作用是通过控制器接收各个玩家的输入并根据规则进行判断,然后给出下一回合的指令。
交互
裁判每回合开始时会被运行一次,每次生命周期均为一次输入、一次输出,每次输入会包括裁判和所有玩家以往跟平台的所有交互内容。交互格式为单行JSON。
因此,裁判的程序运行流程应当是:
- 启动程序
- 从平台获取以往的交互内容和上回合玩家输出的response
- 根据获得的交互内容(自己以前发出的request + 玩家输出的response)进行计算
- 恢复局面到最新状态
- 根据玩家的上回合response演算下一局面
- 如果游戏结束,给出玩家分数
- 如果游戏继续,则确定哪些玩家应当进行动作,并给这些玩家发送request(只有被发送request的玩家才会启动)
- 关闭程序
资源限制
同Bot#资源限制。
交互格式
裁判得到的输入
{
"log": [
{
"memory": 2,
"output": {
"command": "request",
"content": ...,
"display": ...
}, // 这里是裁判输出的request的主体
"time": 2,
"verdict": "OK"
}, // 第0、2、4、...项,表示裁判第1、2、3...回合的输出
{
"0": {
"memory": 2,
"time": 9,
"verdict": "OK",
"response": ... // 这里是玩家输出的response的主体
}
}, // 第1、3、5、...项,表示玩家们第1、2、3...回合的输出
...
],
"initdata": "" // 初始化数据
}
裁判应该给出的输出
如果游戏继续:
{
"command": "request",
"content": {
"0": ... // 要运行的玩家和给它的request
},
"display": ... // 给播放器的信息,可以是JSON对象
}
如果游戏结束:
{
"command": "finish",
"content": {
"0": 1, // 每个玩家的分数
"1": 2
},
"display": ... // 给播放器的信息,可以是JSON对象
}
关于 initdata
initdata 是指裁判程序的初始化数据,通常用于指定随机种子、地图大小、初始手牌等参数。
在第一回合,裁判收到的 initdata 可能是一个字符串或者对象,为用户或比赛开启对局时所指定的 initdata。
在第一回合,裁判有机会在输出对象中的 initdata 域里写入初始化数据(字符串或对象)并保存,此后回合收到的 initdata 均为这次输出的 initdata。通常用于当用户没有指定随机种子的时候保存自己产生的随机种子,或者保存一个通过随机种子产生的地图地形或初始手牌信息等。
样例程序
以下给出C++的JSON裁判样例程序:
本地编译的方式请查看 JSONCPP。
#include <iostream>
#include <sstream>
#include <string>
#include "jsoncpp/json.h"
using namespace std;
// 注意黑方为0号玩家
int currBotColor; // 正在等待输出结果的BOT
int gridInfo[8][8] = { 0 }; // 先x后y
int blackPieceCount = 2, whitePieceCount = 2;
string blackName = "", whiteName = "";
static bool MoveStep(int &x, int &y, int Direction)
{
if (Direction == 0 || Direction == 6 || Direction == 7)
x++;
if (Direction == 0 || Direction == 1 || Direction == 2)
y++;
if (Direction == 2 || Direction == 3 || Direction == 4)
x--;
if (Direction == 4 || Direction == 5 || Direction == 6)
y--;
if (x < 0 || x > 7 || y < 0 || y > 7)
return false;
return true;
}
bool ProcStep(int xPos, int yPos, int color, bool checkOnly = false)
{
if (xPos == -1)
return true;
if (xPos < 0 || xPos > 7 || yPos < 0 || yPos > 7)
return false;
int effectivePoints[8][2];
int dir, x, y, currCount;
bool isValidMove = false;
if (gridInfo[xPos][yPos] != 0)
return false;
for (dir = 0; dir < 8; dir++)
{
x = xPos;
y = yPos;
currCount = 0;
while (1)
{
if (!MoveStep(x, y, dir))
{
currCount = 0;
break;
}
if (gridInfo[x][y] == -color)
{
currCount++;
effectivePoints[currCount][0] = x;
effectivePoints[currCount][1] = y;
}
else if (gridInfo[x][y] == 0)
{
currCount = 0;
break;
}
else
{
break;
}
}
if (currCount != 0)
{
isValidMove = true;
if (checkOnly)
return true;
if (color == 1)
{
blackPieceCount += currCount;
whitePieceCount -= currCount;
}
else
{
whitePieceCount += currCount;
blackPieceCount -= currCount;
}
while (currCount > 0)
{
x = effectivePoints[currCount][0];
y = effectivePoints[currCount][1];
gridInfo[x][y] *= -1;
currCount--;
}
}
}
if (isValidMove)
{
gridInfo[xPos][yPos] = color;
if (color == 1)
blackPieceCount++;
else
whitePieceCount++;
return true;
}
else
return false;
}
bool CheckIfHasValidMove(int color)
{
int x, y;
for (y = 0; y < 8; y++)
for (x = 0; x < 8; x++)
if (ProcStep(x, y, color, true))
return true;
return false;
}
int main()
{
string str;
getline(cin, str);
Json::Reader reader;
Json::Value input, output;
reader.parse(str, input);
input = input["log"];
gridInfo[3][4] = gridInfo[4][3] = 1; //|白|黑|
gridInfo[3][3] = gridInfo[4][4] = -1; //|黑|白|
currBotColor = 1; // 先手为黑
if (input.size() == 0)
{
output["display"] = "";
output["command"] = "request";
output["content"]["0"]["x"] = -1;
output["content"]["0"]["y"] = -1;
}
else
{
for (int i = 1; i < input.size(); i += 2)
{
bool isLast = i == input.size() - 1;
Json::Value content;
Json::Value display;
if (currBotColor == 1) // 0号玩家 / 黑方
{
Json::Value answer = input[i]["0"]["response"].isNull() ? input[i]["0"]["content"] : input[i]["0"]["response"];
if (((answer.isString() &&
reader.parse(answer.asString(), content)) ||
(answer.isObject() &&
(content = answer, true))) &&
content["x"].isInt() && content["y"].isInt()) // 保证输入格式正确
{
int currX = content["x"].asInt();
int currY = content["y"].asInt();
if (currX == -1 && isLast) // bot选择PASS
{
if (!CheckIfHasValidMove(currBotColor)) // 他应该PASS
{
output["display"]["x"] = -1;
output["display"]["y"] = -1;
output["command"] = "request";
output["content"]["1"]["x"] = -1;
output["content"]["1"]["y"] = -1;
}
else // 他不应该PASS
{
// Todo: Bug here--
output["display"]["err"] = "HE_THOUGHT_THAT_HE_COULDNOT_MOVE_BUT_IN_FACT_HE_CAN";
output["display"]["winner"] = 1;
output["command"] = "finish"; // 判输
output["content"]["0"] = 0;
output["content"]["1"] = 2;
}
}
else if (!ProcStep(currX, currY, currBotColor) && isLast) // 不合法棋步!
{
output["display"]["err"] = "INVALIDMOVE";
output["display"]["winner"] = 1;
output["command"] = "finish"; // 判输
output["content"]["0"] = 0;
output["content"]["1"] = 2;
}
else if (isLast) // 正常棋步
{
output["display"]["x"] = currX;
output["display"]["y"] = currY;
if (!CheckIfHasValidMove(currBotColor) && !CheckIfHasValidMove(-currBotColor)) // 游戏结束
{
if (blackPieceCount > whitePieceCount)
{
output["display"]["winner"] = 0;
output["command"] = "finish";
output["content"]["0"] = 2;
output["content"]["1"] = 0;
}
else if (blackPieceCount < whitePieceCount)
{
output["display"]["winner"] = 1;
output["command"] = "finish";
output["content"]["0"] = 0;
output["content"]["1"] = 2;
}
else
{
output["command"] = "finish";
output["content"]["0"] = 1;
output["content"]["1"] = 1;
}
}
else
{
output["display"]["x"] = currX;
output["display"]["y"] = currY;
output["command"] = "request";
output["content"]["1"]["x"] = currX;
output["content"]["1"]["y"] = currY;
}
}
}
else if (isLast)
{
output["display"]["err"] = "INVALIDMOVE";
output["display"]["winner"] = 1;
output["command"] = "finish"; // 判输
output["content"]["0"] = 0;
output["content"]["1"] = 2;
}
}
else
{
Json::Value answer = input[i]["1"]["response"].isNull() ? input[i]["1"]["content"] : input[i]["1"]["response"];
if (((answer.isString() &&
reader.parse(answer.asString(), content)) ||
(answer.isObject() &&
(content = answer, true))) &&
content["x"].isInt() && content["y"].isInt()) // 保证输入格式正确
{
int currX = content["x"].asInt();
int currY = content["y"].asInt();
if (currX == -1 && isLast) // bot选择PASS
{
if (!CheckIfHasValidMove(currBotColor)) // 他应该PASS
{
output["display"]["x"] = -1;
output["display"]["y"] = -1;
output["command"] = "request";
output["content"]["0"]["x"] = -1;
output["content"]["0"]["y"] = -1;
}
else // 他不应该PASS
{
output["display"]["err"] = "HE_THOUGHT_THAT_HE_COULDNOT_MOVE_BUT_IN_FACT_HE_CAN";
output["display"]["winner"] = 0;
output["command"] = "finish"; // 判输
output["content"]["0"] = 2;
output["content"]["1"] = 0;
}
}
else if (!ProcStep(currX, currY, currBotColor) && isLast) // 不合法棋步!
{
output["display"]["err"] = "INVALIDMOVE";
output["display"]["winner"] = 0;
output["command"] = "finish"; // 判输
output["content"]["0"] = 2;
output["content"]["1"] = 0;
}
else if (isLast) // 正常棋步
{
output["display"]["x"] = currX;
output["display"]["y"] = currY;
if (!CheckIfHasValidMove(currBotColor) && !CheckIfHasValidMove(-currBotColor)) // 游戏结束
{
if (blackPieceCount > whitePieceCount)
{
output["display"]["winner"] = 0;
output["command"] = "finish";
output["content"]["0"] = 2;
output["content"]["1"] = 0;
}
else if (blackPieceCount < whitePieceCount)
{
output["display"]["winner"] = 1;
output["command"] = "finish";
output["content"]["0"] = 0;
output["content"]["1"] = 2;
}
else
{
output["command"] = "finish";
output["content"]["0"] = 1;
output["content"]["1"] = 1;
}
}
else
{
output["command"] = "request";
output["content"]["0"]["x"] = currX;
output["content"]["0"]["y"] = currY;
}
}
}
else if (isLast)
{
output["display"]["err"] = "INVALIDMOVE";
output["display"]["winner"] = 0;
output["command"] = "finish"; // 判输
output["content"]["0"] = 2;
output["content"]["1"] = 0;
}
}
currBotColor *= -1;
}
}
Json::FastWriter writer;
cout << writer.write(output) << endl;
}