LoginSignup
7
5

More than 5 years have passed since last update.

LINE-Botでポケモンのサファリゾーンを作ってポケモ◯ゲットだぜ!(Callback側はPHP+Redis)

Last updated at Posted at 2016-06-23

やりたいこと

Botを使ってECの商品検索など作ったのですが、ちょっと違うテイストをやってみたくなったのでチャレンジです。
今回はケンタロス欲しさに頑張ったサファリゾーンの石やエサを投げてサファリボールで捕まえるタイプをLineのボットで遊べるようにします。

イメージは
話しかけるとポケモンが出現して
1と話しかけると石を投げる。
2と話しかけるとエサを投げる。
3と話しかけるとサファリボール投げて判定。
って感じです。
あとは毎ターン逃げる判定。

そんな大層なものではありません。

環境とアカウントセットアップ

記載は省きます。
サーバーはConohaVPS+OnamaeドメインでLetsEncryptを導入済みです。
LINE Botの登録も綺麗にまとめていらっしゃる方が多いので、参考にさせていただきました。
LINE BOT API Trialでできる全ての事を試してみた

ポケモン関連で参考にさせていただいたサイト

赤・緑の時代の人間なので、最近の話が全くわかっていません。
当時はこんなに細かくパラメータなど考えてプレイしていないので、この歳になってポケモンの実装をWikiで調べる。

作成したBOT

スクリーンショット撮影中・・

サファリゾーン(対戦画面)の再現で最低限必要なデータ

サファリボールの時は「スーパーボール」扱いになるというサイトもありましたが、石やエサで補正されるので、これらが必要です。

必要なパラメータ
- 捕獲率
- 現在の捕獲率
- エサポイント
- エサの回数
- 石ポイント
- 石の回数
- 素早さ

データ

必要な要素のあるポケモンを準備

callback_poke.php
$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から取得

callback_poke.php
$user_id    = $content->from;
$poke = $redis->get( $user_id );

はじめてのアクセスやコンテニューの場合、ポケモンの出現音をメッセージで表示してredisにデフォルトのステータスのポケモンをLineのユーザID?をKeyに保存します。

callback_poke.php
$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を受け取る時と同じ感じです。

callback_poke.php

$request = file_get_contents("php://input");
$json = json_decode($request);
$content = $json->result[0]->content;

すでにゲームを始めてる場合、redisからポケモン情報を取得して
受け取ったLineのメッセージの本分をみて処理を分岐します。
エラートラップは記載してません。

callback_poke.php

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

あとはメッセージを返却する際に操作メニューを追加します。

callback_poke.php
$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
  • サファリボールの判定をもうちょっとちゃんと調べる必要がある。
  • 逃げる判定あってるかな?ニドランでさえマッハで逃げていく。。。 とまだまだアップデートが必要
7
5
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
7
5