# Misskey的黑白棋Bot开发
本页会说明如何为Misskey的黑白棋功能开发一个Bot机器人。

1. 使用以下参数来连接`games/reversi`流式API：
    * `i`: bot账号的API key

2. 当出现对局邀请时，流中会触发`invited`事件
    * 事件内容中包含邀请您参加游戏的用户信息，名字为`parent`。

3. 向`games/reversi/match`发送请求，其中`user_id`包含`parent`的`id`

4. 请求成功时将返回游戏信息，然后可以使用以下参数连接到`games/reversi-game`流：
    * `i`: bot账号的API key
    * `game`: `game`的`id`

5. 与此同时，每次对手更改游戏设置时，都会触发`update-settings`事件，如果有必要的话，需要对其进行处理。

6. 一旦符合设置，则向流发送`{ type: 'accept' }`消息

7. 游戏开始时会触发`started`事件
    * 游戏状态信息会包含在该事件中

8. 要放置棋子，向流发送`{ type: 'set', pos: <位置> }`(后面会说明位置的计算方法)

9. 当对方或者您放置棋子时，会触发`set`事件
    * `color`中包含该棋子的颜色
    * `pos`中包含该棋子的位置

## 位置计算方法
当棋盘尺寸为8x8时，每个方格的位置（称为索引）如下所示：
```
+--+--+--+--+--+--+--+--+
| 0| 1| 2| 3| 4| 5| 6| 7|
+--+--+--+--+--+--+--+--+
| 8| 9|10|11|12|13|14|15|
+--+--+--+--+--+--+--+--+
|16|17|18|19|20|21|22|23|
...
```

### 从X,Y坐标转换为索引
```
pos = x + (y * mapWidth)
```
`mapWidth`可以根据游戏信息中的`map`，通过如下方法计算出来：
```
mapWidth = map[0].length
```

### 从索引转换为X,Y坐标
```
x = pos % mapWidth
y = Math.floor(pos / mapWidth)
```

## 棋盘信息
棋盘信息包含在游戏信息的`map`中。 它是一个字符串数组，每个字符代表一块格子的信息。 您可以根据这些来了解地图如何设计：
* `(空)` ... 没有格子
* `-` ... 格子
* `b` ... 黑子先下
* `w` ... 白子先下

以下面这个4*4的简单棋盘为例：
```text
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
|   | ○ | ● |   |
+---+---+---+---+
|   | ● | ○ |   |
+---+---+---+---+
|   |   |   |   |
+---+---+---+---+
```

这种情况下，棋盘数据是这样的：
```javascript
['----', '-wb-', '-bw-', '----']
```

## 能和用户互动的交互式Bot机器人的创建
要和用户交互，您可以在游戏设置屏幕上向用户显示对话框。 例如，可以让用户选择Bot机器人的难度。

要显示提示框，需要向`reversi-game`流发送下列消息：
```javascript
{
  type: 'init-form',
  body: [表单控件数组]
}
```

下面说明表单控件数组的结构。 表单控件指的是如下面所示的对象：
```javascript
{
  id: 'switch1',
  type: 'switch',
  label: 'Enable hoge',
  value: false
}
```
`id` ... 控件ID。 `type` ... 控件类型。说明详见后文。 `label` ... 控件元素上显示的文字。 `value` ... 控件元素的默认值。

### 控件行为的处理
当用户与对话框交互时将会触发流的`update-form`事件。 事件的内容包含控件的ID和用户设置的值。 例如，如果用户将上面显示的开关控件打开，则将触发以下事件：
```javascript
{
  id: 'switch1',
  value: true
}
```

### 表单控件的类型
#### 开关
type: `switch` 显示一个开关。当您想要打开/关闭某些功能时非常有用。

##### 属性
`label` ... 开关上显示的文字。

#### 单选按钮
type: `radio` 显示一个单选按钮。用来表示单项选择。例如，可以选择Bot机器人的难度。

##### 属性
`items` ... 单元按钮的选择项。例：
```javascript
items: [{
  label: '弱',
  value: 1
}, {
  label: '中',
  value: 2
}, {
  label: '强',
  value: 3
}]
```

#### 滑块
type: `slider` 显示一个滑块。

##### 属性
`min` ... 滑块最小值。 `max` ... 滑块最大值。 `step` ... 滑块值的步长。

#### 文本框
type: `textbox` 显示一个文本框。可以在各种需要用户输入的地方使用。

## 向用户显示消息
设置屏幕上与用户交互，是除了对话框外的另一种方法。您可以向用户显示一条消息。 例如，当用户选择Bot机器人不支持的模式或棋盘时显示警告。 要显示消息，请将以下消息发送到流：
```javascript
{
  type: 'message',
  body: {
    text: '消息内容',
    type: '消息类型'
  }
}
```
消息类型：`success`, `info`, `warning`, `error`。

## 认输
要认输，请发送请求到这个终端。
