“裁判”的版本间的差异
来自Botzone Wiki
Administrator(讨论 | 贡献) 小 |
Administrator(讨论 | 贡献) |
||
第2行: | 第2行: | ||
裁判与[[Bot]]一样可以用各种语言编写,主要作用是通过[[控制器]]接收各个玩家的输入并根据规则进行判断,然后给出下一回合的指令。 | 裁判与[[Bot]]一样可以用各种语言编写,主要作用是通过[[控制器]]接收各个玩家的输入并根据规则进行判断,然后给出下一回合的指令。 | ||
+ | |||
+ | == 交互 == | ||
+ | |||
+ | 裁判每回合开始时会被运行一次,每次生命周期均为一次输入、一次输出,每次输入会包括裁判和所有玩家以往跟平台的所有交互内容。交互格式为'''单行[[JSON]]'''。 | ||
+ | |||
+ | 因此,裁判的程序运行流程应当是: | ||
+ | *启动程序 | ||
+ | *从平台获取以往的交互内容和上回合玩家输出的response | ||
+ | *根据获得的交互内容(自己以前发出的request + 玩家输出的response)进行计算 | ||
+ | **恢复局面到最新状态 | ||
+ | **根据玩家的上回合response演算下一局面 | ||
+ | ***如果游戏结束,给出玩家分数 | ||
+ | ***如果游戏继续,则确定哪些玩家应当进行动作,并给这些玩家发送request | ||
+ | *关闭程序 | ||
+ | |||
+ | ===资源限制=== | ||
+ | |||
+ | 同[[Bot#.E8.B5.84.E6.BA.90.E9.99.90.E5.88.B6]]。 | ||
+ | |||
+ | ===交互格式=== | ||
+ | |||
+ | ===='''裁判得到的输入'''==== | ||
+ | <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> | ||
+ | |||
+ | ===='''裁判应该给出的输出'''==== | ||
+ | |||
+ | 如果游戏继续: | ||
+ | <syntaxhighlight lang="javascript"> | ||
+ | { | ||
+ | "command": "request", | ||
+ | "content": { | ||
+ | "0": ... // 要运行的玩家和给它的request | ||
+ | }, | ||
+ | "display": ... // 给播放器的信息,可以是JSON对象 | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | 如果游戏结束: | ||
+ | <syntaxhighlight lang="javascript"> | ||
+ | { | ||
+ | "command": "finish", | ||
+ | "content": { | ||
+ | "0": 1, // 每个玩家的分数 | ||
+ | "1": 2 | ||
+ | }, | ||
+ | "display": ... // 给播放器的信息,可以是JSON对象 | ||
+ | } | ||
+ | </syntaxhighlight> | ||
+ | |||
+ | ===样例程序=== | ||
+ | 以下给出C++的[[JSON]]裁判样例程序: | ||
+ | |||
+ | 本地编译的方式请查看 [[JSONCPP]]。 | ||
+ | |||
+ | <syntaxhighlight lang="cpp"> | ||
+ | #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; | ||
+ | } | ||
+ | </syntaxhighlight> |
2017年6月18日 (日) 17:09的版本
裁判是Botzone进行对局评测的后台程序,同时也是每个游戏必不可少的部分。
裁判与Bot一样可以用各种语言编写,主要作用是通过控制器接收各个玩家的输入并根据规则进行判断,然后给出下一回合的指令。
交互
裁判每回合开始时会被运行一次,每次生命周期均为一次输入、一次输出,每次输入会包括裁判和所有玩家以往跟平台的所有交互内容。交互格式为单行JSON。
因此,裁判的程序运行流程应当是:
- 启动程序
- 从平台获取以往的交互内容和上回合玩家输出的response
- 根据获得的交互内容(自己以前发出的request + 玩家输出的response)进行计算
- 恢复局面到最新状态
- 根据玩家的上回合response演算下一局面
- 如果游戏结束,给出玩家分数
- 如果游戏继续,则确定哪些玩家应当进行动作,并给这些玩家发送request
- 关闭程序
资源限制
同Bot#.E8.B5.84.E6.BA.90.E9.99.90.E5.88.B6。
交互格式
裁判得到的输入
{
"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对象
}
样例程序
以下给出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;
}