“Bot”的版本间的差异
来自Botzone Wiki
Administrator(讨论 | 贡献) (→简化交互) |
Administrator(讨论 | 贡献) (→提供的运行库) |
||
第19行: | 第19行: | ||
*Java: 提供 [[JSON.simple]] | *Java: 提供 [[JSON.simple]] | ||
*C#: 提供 [http://www.newtonsoft.com/json Newtonsoft.Json] | *C#: 提供 [http://www.newtonsoft.com/json Newtonsoft.Json] | ||
− | *python(2/3): 提供 numpy, scipy | + | *python(2/3): 提供 numpy, scipy 以及 CPU 下的 TensorFlow |
== 交互 == | == 交互 == |
2017年9月1日 (五) 15:40的版本
目录
何为Bot
Bot是Botzone上用户提交的程序,具有一定的人工智能,可以根据已有的游戏规则跟其他的Bot或人类玩家进行对抗。
支持的语言
Bot可以用以下语言编写:
- C/C++(平台上编译时会定义
_BOTZONE_ONLINE
宏) - Java
- JavaScript
- C# (Mono)
- python2
- python3
- Pascal
提供的运行库
- C/C++: 提供 JSONCPP
- Java: 提供 JSON.simple
- C#: 提供 Newtonsoft.Json
- python(2/3): 提供 numpy, scipy 以及 CPU 下的 TensorFlow
交互
Bot的每次生命周期均为一次输入、一次输出,每次输入会包括该Bot以往跟平台的所有交互内容。交互格式为单行JSON或简化交互。
因此,Bot的程序运行流程应当是:
- 启动程序
- 从平台获取以往的交互内容和最新输入
- 根据获得的交互内容(request + response)进行计算
- 根据以往自己的输入(request)输出(response)恢复局面到最新状态
- 根据本次输入(request)给出本次的决策输出
- 输出结果以及保存信息
- 关闭程序
资源限制
如果没有特别指出,每次运行,平台都要求程序在 1秒 内结束、使用的内存在 256 MB 内。
由于不同语言运行效率有别,我们对不同语言的时限也有不同的调整。
- C/C++:1倍
- Java:3倍
- C#:6倍
- JavaScript:2倍
- python:3倍
- Pascal:1倍
交互格式
为了照顾初学者,交互形式有两种:JSON交互和简化交互。
提示:为了限制对局 Log 的大小,data、globaldata 域作为对局的中间变量,在对局结束后将不会被存入 Log 中。
如果希望能进行调试,请使用 debug 域,该域会在对局结束后仍保留在 Log 中。
JSON交互
使用这种交互,可能需要在自己的程序中增加JSON处理相关的库,具体请参见下方样例程序的说明。
Bot 得到的输入
{
"requests" : [
"Judge request in Turn 1", // 第 1 回合 Bot 从平台获取的信息(request),具体格式依游戏而定
"Judge request in Turn 2", // 第 2 回合 Bot 从平台获取的信息(request),具体格式依游戏而定
...
],
"responses" : [
"Bot response in Turn 1", // 第 1 回合 Bot 输出的信息(response),具体格式依游戏而定
"Bot response in Turn 2", // 第 2 回合 Bot 输出的信息(response),具体格式依游戏而定
...
],
"data" : "saved data", // 上回合 Bot 保存的信息,最大长度为100KB【注意不会保留在 Log 中】
"globaldata" : "globally saved data", // 来自上次对局的、Bot 全局保存的信息,最大长度为100KB【注意不会保留在 Log 中】
"time_limit" : "", // 时间限制
"memory_limit" : "" // 内存限制
}
Bot 应该给出的输出
{
"response" : "response msg", // Bot 此回合的输出信息(response)
"debug" : "debug info", // 调试信息,将被写入log,最大长度为1KB
"data" : "saved data" // Bot 此回合的保存信息,将在下回合输入【注意不会保留在 Log 中】
"globaldata" : "globally saved data" // Bot 的全局保存信息,将会在下回合输入,对局结束后也会保留,下次对局可以继续利用【注意不会保留在 Log 中】
}
简化交互
使用这种交互,只需使用标准输入输出按行操作即可。
Bot 得到的输入
- 你的 Bot 首先会收到一行,其中只有一个数字 n,表示目前是第 n 回合(从 1 开始)。
- 接下来,是 2 * n - 1 条信息,这些信息由 Bot 从平台获取的信息(request)与 Bot 以前每个回合输出的信息(response)交替组成。
- 从 1 开始计数,(1 <= i < n)
- 第 2 * i - 1 条信息为第 i 回合 Bot 从平台获取的信息(request),共 n - 1 条
- 第 2 * i 条信息为 Bot 在第 i 回合输出的信息(response),共 n - 1 条
- 最后一条,即第 2 * n - 1 条信息,为当前回合 Bot 从平台获取的新信息(request)
- 每条信息可能是 1 行,也可能是多行,具体格式依游戏而定。
- 你的 Bot 需要根据以上信息,推演出当前局面,并给出当前局面下的最好决策。
- 从 1 开始计数,(1 <= i < n)
- 接下来是data,一行 Bot 上回合保存的信息,最大长度为100KB【注意不会保留在 Log 中】。
- 接下来是globaldata,一行或多行 Bot 上回合或上次对局保存的全局信息,最大长度为100KB【注意不会保留在 Log 中】。
- 可以认为 data 行之后的所有内容都是 globaldata,直到文件结尾。
样例输入
3 第一回合游戏信息(request),即 Bot 当时得到的输入 第一回合 Bot 的输出(response) 第二回合游戏信息 第二回合 Bot 的输出 第三回合游戏信息 Bot 上回合保存了这句话作为data! Bot 上次运行程序保存了这句话作为globaldata!
Bot 应该给出的输出
你的 Bot 应当输出四段数据,以换行符隔开。
- 首先是本回合你的 Bot 做出的决策,请按照游戏要求输出。一定只占一行。
- 接下来是debug,一行用于回放时候进行调试的信息,最大长度为1KB【注意会保留在 Log 中】。
- 接下来是data,一行 Bot 本回合想保存的信息,将在下回合输入,最大长度为100KB【注意不会保留在 Log 中】。
- 接下来是globaldata,一行或多行 Bot 想保存的全局信息,将会在下回合输入,对局结束后也会保留,最大长度为100KB【注意不会保留在 Log 中】。
样例输出
本回合 Bot 的输出 Bot 这回合想保存这句话作为debug,到时候回放看! Bot 这回合保存了这句话作为data,下回合想用! Bot 这次运行程序保存了这句话作为globaldata,以后想用!
JSON交互的样例程序
以下给出C++、C#、Java和JavaScript的JSON交互样例程序:
C++
本地编译的方式请查看 JSONCPP。
#include <iostream>
#include <string>
#include <sstream>
#include "jsoncpp/json.h" // C++编译时默认包含此库
using namespace std;
int main()
{
// 读入JSON
string str;
getline(cin, str);
Json::Reader reader;
Json::Value input;
reader.parse(str, input);
// 分析自己收到的输入和自己过往的输出,并恢复状态
string data = input["data"].asString(); // 该对局中,以前该Bot运行时存储的信息
int turnID = input["responses"].size();
for (int i = 0; i < turnID; i++)
{
istringstream in(input["requests"][i].asString()),
out(input["responses"][i].asString());
// 根据这些输入输出逐渐恢复状态到当前回合
}
// 看看自己本回合输入
istringstream in(input["requests"][turnID].asString());
// 做出决策存为myAction
// 输出决策JSON
Json::Value ret;
ret["response"] = myAction;
ret["data"] = myData; // 可以存储一些前述的信息,在整个对局中使用
Json::FastWriter writer;
cout << writer.write(ret) << endl;
return 0;
}
C#
本地编译的方式请查看 Newtonsoft.Json。
using System;
using Newtonsoft.Json;
struct InputData
{
public dynamic[] // 类型请根据具体游戏决定
requests, // 从平台获取的信息集合
responses; // 自己曾经输出的信息集合
public string
data, // 该对局中,上回合该Bot运行时存储的信息
globaldata; // 来自上次对局的、Bot全局保存的信息
public int time_limit, memory_limit;
}
struct OutputData
{
public dynamic response; // 此回合的输出信息
public string
debug, // 调试信息,将被写入log
data, // 此回合的保存信息,将在下回合输入
globaldata; // Bot的全局保存信息,将会在下回合输入,对局结束后也会保留,下次对局可以继续利用
}
class Program
{
static void Main(string[] args) // 请保证文件中只有一个类定义了Main方法
{
// 将输入解析为结构体
var input = JsonConvert.DeserializeObject<InputData>(
Console.ReadLine()
);
// 分析自己收到的输入和自己过往的输出,并恢复状态
int turnID = input.responses.Length;
for (int i = 0; i < turnID; i++)
{
dynamic inputOfThatTurn = input.requests[i], // 当时的输入
outputOfThatTurn = input.responses[i]; // 当时的输出
// 根据这些输入输出逐渐恢复状态到当前回合
}
// 看看自己本回合输入
dynamic inputOfCurrentTurn = input.requests[turnID];
// 做出决策存为myAction
// 输出决策JSON
OutputData output = new OutputData();
output.response = myAction;
output.debug = "hhh";
Console.WriteLine(
JsonConvert.SerializeObject(output)
);
}
}
JavaScript
// 初始化标准输入流
process.stdin.resume();
process.stdin.setEncoding('utf8');
var fullInput = "";
// 收到一个输入片段
process.stdin.on('data', function (chunk) {
fullInput += chunk;
});
// 输入全部结束
process.stdin.on('end', function () {
// 解析读入的JSON
var input = JSON.parse(fullInput);
var data = input.data; // 该对局中,以前该Bot运行时存储的信息
// 分析自己收到的输入和自己过往的输出,并恢复状态
for (var i = 0; i < input.responses.length; i++) {
var myInput = input.requests[i], myOutput = input.responses[i];
// 根据这些输入输出逐渐恢复状态到当前回合
}
// 看看自己本回合输入
var currInput = input.requests[input.requests.length - 1];
// 作出决策并输出
console.log(JSON.stringify({
response: myAction,
data: myData // 可以存储一些前述的信息,在整个对局中使用
}));
});
Java
本地编译的方式请查看 JSON.simple。
import java.util.*;
import org.json.simple.JSONValue; // Java 库中自动包含此库
class Main { // 注意!!类名""必须""为 Main,且不要有package语句,但上传的 java 代码文件名可以任意
static class SomeClass {
// 如果要定义类,请使用 static inner class
}
public static void main(String[] args) {
String input = new Scanner(System.in).nextLine();
Map<String, List> inputJSON = (Map) JSONValue.parse(input);
// 下面的 TYPE 为单条 response / request 类型,有较大可能为 Map<String, Long> 或 String
List<TYPE> requests = inputJSON.get("requests");
List<TYPE> responses = inputJSON.get("responses");
for (TYPE rec : requests) {
// 处理一下
}
for (TYPE rec : responses) {
// 再处理一下
}
// 这边运算得出一个 output,注意类型也为 TYPE
Map<String, TYPE> outputJSON = new HashMap();
outputJSON.put("response", output);
System.out.print(JSONValue.toJSONString(outputJSON));
}
}