Bot

来自Botzone Wiki
Administrator讨论 | 贡献2017年1月28日 (六) 01:45的版本 样例程序
跳转至: 导航搜索

何为Bot

Bot是Botzone上用户提交的程序,具有一定的人工智能,可以根据已有的游戏规则跟其他的Bot或人类玩家进行对抗。

支持的语言

Bot可以用以下语言编写:

  • C/C++(平台上编译时会定义 _BOTZONE_ONLINE 宏)
  • Java
  • JavaScript
  • C# (Mono)
  • python2
  • python3
  • Pascal

提供的运行库

交互

Bot的每次生命周期均为一次输入、一次输出,每次输入会包括该Bot以往跟平台的所有交互内容。交互格式为单行JSON

因此,Bot的程序运行流程应当是:

  • 启动程序
  • 从平台获取JSON数据
  • 根据获得的JSON数据进行计算
    • 根据以往自己的输入输出恢复到最新状态
    • 根据本次输入给出本次的决策输出
  • 输出结果以及保存信息
  • 关闭程序

资源限制

如果没有特别指出,每次运行,平台都要求程序在 1秒 内结束、使用的内存在 256 MB 内。

由于不同语言运行效率有别,我们对不同语言的时限也有不同的调整。

  • C/C++:1倍
  • Java:3倍
  • C#:6倍
  • JavaScript:2倍
  • python:3倍
  • Pascal:1倍

交互格式

Bot 得到的输入

 {
 	"requests" : [
 		"Judge request in Turn 1", // 第 1 回合从平台获取的信息
 		"Judge request in Turn 2", // 第 2 回合从平台获取的信息
 		...
 	],
 	"responses" : [
 		"Bot response in Turn 1", // 第 1 回合输出的信息
 		"Bot response in Turn 2", // 第 2 回合输出的信息
 		...
 	],
 	"data" : "saved data", // 上回合保存的信息,最大长度为100KB
 	"globaldata" : "globally saved data", // 来自上次对局的、Bot全局保存的信息,最大长度为100KB
 	"time_limit" : "", // 时间限制
 	"memory_limit" : "" // 内存限制
 }

Bot 应该给出的输出

 {
 	"response" : "response msg", // 此回合的输出信息
 	"debug" : "debug info", // 调试信息,将被写入log,最大长度为1KB
 	"data" : "saved data" // 此回合的保存信息,将在下回合输入
 	"globaldata" : "globally saved data" // Bot的全局保存信息,将会在下回合输入,对局结束后也会保留,下次对局可以继续利用
 }

样例程序

以下给出C++、C#、Java和JavaScript的交互样例程序:

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));
	}
}