やりたいこと
Botを使ってECの商品検索など作ったのですが、ちょっと違うテイストをやってみたくなったのでチャレンジです。
今回はケンタロス欲しさに頑張ったサファリゾーンの石やエサを投げてサファリボールで捕まえるタイプをLineのボットで遊べるようにします。
イメージは
話しかけるとポケモンが出現して
1と話しかけると石を投げる。
2と話しかけるとエサを投げる。
3と話しかけるとサファリボール投げて判定。
って感じです。
あとは毎ターン逃げる判定。
そんな大層なものではありません。
環境とアカウントセットアップ
記載は省きます。
サーバーはConohaVPS+OnamaeドメインでLetsEncryptを導入済みです。
LINE Botの登録も綺麗にまとめていらっしゃる方が多いので、参考にさせていただきました。
LINE BOT API Trialでできる全ての事を試してみた
ポケモン関連で参考にさせていただいたサイト
- http://wiki.xn--rckteqa2e.com/wiki/%E6%8D%95%E7%8D%B2%E5%87%A6%E7%90%86
- http://pikap.blog.jp/archives/56002339.html
赤・緑の時代の人間なので、最近の話が全くわかっていません。
当時はこんなに細かくパラメータなど考えてプレイしていないので、この歳になってポケモンの実装をWikiで調べる。
作成したBOT
スクリーンショット撮影中・・
サファリゾーン(対戦画面)の再現で最低限必要なデータ
サファリボールの時は「スーパーボール」扱いになるというサイトもありましたが、石やエサで補正されるので、これらが必要です。
必要なパラメータ
- 捕獲率
- 現在の捕獲率
- エサポイント
- エサの回数
- 石ポイント
- 石の回数
- 素早さ
データ
必要な要素のあるポケモンを準備
$pokemons = [];
$pokemons[] = array( "id" => 32 , "name" => "ニドラン♂" , "voice" => "ギャラーララー" , "get" => 235 , "now_get" => 235 , "speed" => 50 , "food" => 0 , "stone" => 0 , "count_food" => 0 , "count_stone" => 0 );
$pokemons[] = array( "id" => 128 , "name" => "ケンタロス" , "voice" => "ギャラーララー" , "get" => 45 , "now_get" => 235 , "speed" => 110 , "food" => 0 , "stone" => 0 , "count_food" => 0 , "count_stone" => 0 );
CallBackが呼び出されると、LineのユーザID?を元にlocalhostのRedisからプレイ中の対戦ポケモンデータを取得します。
いない場合、ランダム(あとで確率を埋めたい)でpokemonsから取得
$user_id = $content->from;
$poke = $redis->get( $user_id );
はじめてのアクセスやコンテニューの場合、ポケモンの出現音をメッセージで表示してredisにデフォルトのステータスのポケモンをLineのユーザID?をKeyに保存します。
$message[] = "トュルトュルトュルトュルトュルトュルトュル♪・テン♪・テン♪・テン♪・ッテッテテデン..\r\n\r\n".$pokemon["name"]."が現れた!\r\n\r\n".$pokemon["voice"]."\r\n";
$redis->set( $user_id , json_encode( $pokemon ) );
ボットへのメッセージ情報はstdinで受け取ります。
angularjsのpostを受け取る時と同じ感じです。
$request = file_get_contents("php://input");
$json = json_decode($request);
$content = $json->result[0]->content;
すでにゲームを始めてる場合、redisからポケモン情報を取得して
受け取ったLineのメッセージの本分をみて処理を分岐します。
エラートラップは記載してません。
$poke = json_decode( $poke , true );
$mode = intval( $content->text );
if( $mode == 1 ){
$message[] = "いしをなげた!";
..補正処理
}else if( $mode == 2 ){
$message[] = "えさをなげた!";
..補正処理
}else if( $mode == 3 ){
$message[] = "サファリボールをなげた!";
..捕獲判定
}
if( !isGameComplete )
//捕まえていなければターン終了処理
//ターン終了時、どちらかのカウンタが1以上であれば、1減少する。
//怒りカウンタが0に戻ると、捕捉率は元の値にリセットされる。
if( $poke["stone"] > 0 || $poke["food"] > 0 ){
if( $poke["stone"] > 0 ){
$poke["stone"] = $poke["stone"] - 1;
}
if( $poke["food"] > 0 ){
$poke["food"] = $poke["food"] - 1;
}
}
// 0~255の乱数を発生させ、それがSより小さければポケモンは逃げる。ただし、Sは、
// エサカウンタが1以上のとき、ポケモンのすばやさの半分(小数点以下切り捨て)
// どちらのカウンタも0のとき、ポケモンのすばやさの2倍
// 怒りカウンタが1以上のとき、ポケモンのすばやさの4倍
// である。また、ポケモンのすばやさが128以上のとき、乱数やカウンタに関わらず逃げる。
$r = mt_rand(0,255);
if( $poke["food"] >= 1 ){
$s = floor( $poke["speed"] / 2 );
}else if( $poke["stone"] >= 1 ){
$s = floor( $poke["speed"] * 4 );
}else if( $poke["stone"] == 0 && $poke["food"] == 0 ){
$s = floor( $poke["speed"] * 2 );
}
if( $s > 128 || $s > $r ){
$message[] = "やせいの".$poke["name"]."は逃げだした。";
$command = "\r\n\r\n----------操作メニュー----------\r\n0 -> コンテニュー";
//逃げた場合、消去
$redis->delete( $user_id );
}else{
//次のメッセージに備えて保存
$redis->set( $user_id , json_encode( $poke ) );
}
あとはメッセージを返却する際に操作メニューを追加します。
$command = "\r\n\r\n----------操作メニュー----------\r\n1 -> いしをなげる\r\n2 -> エサをなげる\r\n3 -> サファリボール";
$message = [];
間に上の補正や判定処理
$post['content']['text'] = implode( "\r\n\r\n" ,$message) .$command;
この下でcurlで
$ch = curl_init("https://trialbot-api.line.me/v1/events");
を呼ぶ
課題
- validation
- サファリボールの判定をもうちょっとちゃんと調べる必要がある。
- 逃げる判定あってるかな?ニドランでさえマッハで逃げていく。。。
とまだまだアップデートが必要