166 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
			
		
		
	
	
			166 lines
		
	
	
		
			5.7 KiB
		
	
	
	
		
			Markdown
		
	
	
	
	
	
# MisskeyリバーシBotの開発
 | 
						|
Misskeyのリバーシ機能に対応したBotの開発方法をここに記します。
 | 
						|
 | 
						|
1. `reversi`ストリームに以下のパラメータを付けて接続する:
 | 
						|
	* `i`: botアカウントのAPIキー
 | 
						|
 | 
						|
2. 対局への招待が来たら、ストリームから`invited`イベントが流れてくる
 | 
						|
	* イベントの中身に、`parent`という名前で対局へ誘ってきたユーザーの情報が含まれている
 | 
						|
 | 
						|
3. `reversi/match`へ、`user_id`として`parent`の`id`が含まれたリクエストを送信する
 | 
						|
 | 
						|
4. 上手くいくとゲーム情報が返ってくるので、`reversi-game`ストリームへ、以下のパラメータを付けて接続する:
 | 
						|
	* `i`: botアカウントのAPIキー
 | 
						|
	* `game`: `game`の`id`
 | 
						|
 | 
						|
5. この間、相手がゲームの設定を変更するとその都度`update-settings`イベントが流れてくるので、必要であれば何かしらの処理を行う
 | 
						|
 | 
						|
6. 設定に満足したら、`{ type: 'accept' }`メッセージをストリームに送信する
 | 
						|
 | 
						|
7. ゲームが開始すると、`started`イベントが流れてくる
 | 
						|
	* イベントの中身にはゲーム情報が含まれている
 | 
						|
 | 
						|
8. 石を打つには、ストリームに`{ type: 'set', pos: <位置> }`を送信する(位置の計算方法は後述)
 | 
						|
 | 
						|
9. 相手または自分が石を打つと、ストリームから`set`イベントが流れてくる
 | 
						|
	* `color`として石の色が含まれている
 | 
						|
	* `pos`として位置情報が含まれている
 | 
						|
 | 
						|
## 位置の計算法
 | 
						|
8x8のマップを考える場合、各マスの位置(Posと呼びます)は次のようになっています:
 | 
						|
```
 | 
						|
+--+--+--+--+--+--+--+--+
 | 
						|
| 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 に変換する
 | 
						|
```
 | 
						|
pos = x + (y * mapWidth)
 | 
						|
```
 | 
						|
`mapWidth`は、ゲーム情報の`settings.map`から、次のようにして計算できます:
 | 
						|
```
 | 
						|
mapWidth = settings.map[0].length
 | 
						|
```
 | 
						|
 | 
						|
### Pos から X,Y座標 に変換する
 | 
						|
```
 | 
						|
x = pos % mapWidth
 | 
						|
y = Math.floor(pos / mapWidth)
 | 
						|
```
 | 
						|
 | 
						|
## マップ情報
 | 
						|
マップ情報は、ゲーム情報の`settings.map`に入っています。
 | 
						|
文字列の配列になっており、ひとつひとつの文字がマス情報を表しています。
 | 
						|
それをもとにマップのデザインを知る事が出来ます:
 | 
						|
* `(スペース)` ... マス無し
 | 
						|
* `-` ... マス
 | 
						|
* `b` ... 初期配置される黒石
 | 
						|
* `w` ... 初期配置される白石
 | 
						|
 | 
						|
例えば、4*4の次のような単純なマップがあるとします:
 | 
						|
```text
 | 
						|
+---+---+---+---+
 | 
						|
|   |   |   |   |
 | 
						|
+---+---+---+---+
 | 
						|
|   | ○ | ● |   |
 | 
						|
+---+---+---+---+
 | 
						|
|   | ● | ○ |   |
 | 
						|
+---+---+---+---+
 | 
						|
|   |   |   |   |
 | 
						|
+---+---+---+---+
 | 
						|
```
 | 
						|
 | 
						|
この場合、マップデータはこのようになります:
 | 
						|
```javascript
 | 
						|
['----', '-wb-', '-bw-', '----']
 | 
						|
```
 | 
						|
 | 
						|
## ユーザーにフォームを提示して対話可能Botを作成する
 | 
						|
ユーザーとのコミュニケーションを行うため、ゲームの設定画面でユーザーにフォームを提示することができます。
 | 
						|
例えば、Botの強さをユーザーが設定できるようにする、といったシナリオが考えられます。
 | 
						|
 | 
						|
フォームを提示するには、`reversi-game`ストリームに次のメッセージを送信します:
 | 
						|
```javascript
 | 
						|
{
 | 
						|
  type: 'init-form',
 | 
						|
  body: [フォームコントロールの配列]
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
フォームコントロールの配列については今から説明します。
 | 
						|
フォームコントロールは、次のようなオブジェクトです:
 | 
						|
```javascript
 | 
						|
{
 | 
						|
  id: 'button1',
 | 
						|
  type: 'button',
 | 
						|
  label: 'Enable hoge',
 | 
						|
  value: false
 | 
						|
}
 | 
						|
```
 | 
						|
`id` ... コントロールのID。
 | 
						|
`type` ... コントロールの種類。後述します。
 | 
						|
`label` ... コントロールと一緒に表記するテキスト。
 | 
						|
`value` ... コントロールのデフォルト値。
 | 
						|
 | 
						|
### フォームの操作を受け取る
 | 
						|
ユーザーがフォームを操作すると、ストリームから`update-form`イベントが流れてきます。
 | 
						|
イベントの中身には、コントロールのIDと、ユーザーが設定した値が含まれています。
 | 
						|
例えば、上で示したボタンをユーザーがオンにしたとすると、次のイベントが流れてきます:
 | 
						|
```javascript
 | 
						|
{
 | 
						|
  id: 'button1',
 | 
						|
  value: true
 | 
						|
}
 | 
						|
```
 | 
						|
 | 
						|
### フォームコントロールの種類
 | 
						|
#### ボタン
 | 
						|
type: `button`
 | 
						|
ボタンを表示します。何かの機能をオン/オフさせたい場合に有用です。
 | 
						|
 | 
						|
##### プロパティ
 | 
						|
`desc` ... ボタンの詳細な説明。
 | 
						|
 | 
						|
#### ラジオボタン
 | 
						|
type: `radio`
 | 
						|
ラジオボタンを表示します。選択肢を提示するのに有用です。例えば、Botの強さを設定させるなどです。
 | 
						|
 | 
						|
##### プロパティ
 | 
						|
`items` ... ラジオボタンの選択肢。例:
 | 
						|
```javascript
 | 
						|
items: [{
 | 
						|
  label: '弱',
 | 
						|
  value: 1
 | 
						|
}, {
 | 
						|
  label: '中',
 | 
						|
  value: 2
 | 
						|
}, {
 | 
						|
  label: '強',
 | 
						|
  value: 3
 | 
						|
}]
 | 
						|
```
 | 
						|
 | 
						|
#### テキストボックス
 | 
						|
type: `textbox`
 | 
						|
テキストボックスを表示します。ユーザーになにか入力させる一般的な用途に利用できます。
 | 
						|
 | 
						|
## ユーザーにメッセージを表示する
 | 
						|
設定画面でユーザーと対話する、フォーム以外のもうひとつの方法がこれです。ユーザーになにかメッセージを表示することができます。
 | 
						|
例えば、ユーザーがBotの対応していないモードやマップを選択したとき、警告を表示するなどです。
 | 
						|
メッセージを表示するには、次のメッセージをストリームに送信します:
 | 
						|
```javascript
 | 
						|
{
 | 
						|
  type: 'message',
 | 
						|
  body: {
 | 
						|
    text: 'メッセージ内容',
 | 
						|
    type: 'メッセージの種類'
 | 
						|
  }
 | 
						|
}
 | 
						|
```
 | 
						|
メッセージの種類: `success`, `info`, `warning`, `error`。
 |