プログラミング

オウムがえし編 PHPポケモン 68

PHP PHPポケモン ポケモン
オウムがえし編 PHPポケモン 68

オウムがえしとは

今回は久々に新しい技を実装します。それが「オウムがえし」です。

オウムがえし(ポケモンwiki

 

初代で登場した技であり、序盤に登場するポッポやオニスズメがレベルアップで覚える技の1つです。最新世代ではオウムがえしという技は実装されなくなった数少ない技の1つでもあります。

それもそのはず、判定がかなり面倒で特別処理が必要な技1つだからです。

※実際の理由は知りません

 

コピーできない技

まず、オウムがえしの技詳細を見てみましょう。

相手が最後に使った技を出す。

 

技名の通り、相手が使った技をそっくりそのまま返してあげる(コピーして使う)のが、この技の仕様となっています。ですが、すべての技をコピーできるわけではありません

 

自分を対象とする技

「せいちょう」や「きあいだめ」など、自身に対してのみ影響を与える技はコピーできません。

自分のフィールドを対象とする技

「しろいきり」や「リフレクター」など、味方フィールドに影響を与える技はコピーできません。

他の技が出る技

「オウムがえし」や「ゆびをふる」など、その技を使うことで別の技が発動する技はコピーできません。

例外

「わるあがき」や「カウンター」はコピーできません。

 

この通り、意外にもコピーできない技は多くあり、それらが相手の最後に使った技と該当する場合は失敗の判定を返す必要があります。

 

ターゲットの設定

まず、大きな括りとして「自分または味方(フィールド)を対象とする技」はコピーできません。なので、技クラスに対して技の対象(target)を設定することで判定ができるようにします。

 

技クラスへのプロパティ追加
/**
* 対象(使ったポケモンから見た立場)
* @var string::friend|enemy
*/
protected $target = 'enemy';

 

この値を取得できるように、親クラスにはgetTargetというメソッドを追加しておきましょう。これで、オウムがえしを発動した際にtargetを確認することで判定することが可能です。

 

では、オウムがえしの技クラスを作成しましょう。

 

オウムがえし(/Classes/Move/MoveMirrorMove.php
<?php
$root_path = __DIR__.'/../..';
require_once($root_path.'/Classes/Move.php');
 
// オウムがえし
class MoveMirrorMove extends Move
{
 
    /**
    * 正式名称
    * @var string
    */
    protected $name = 'オウムがえし';
 
    /**
    * 説明文
    * @var string
    */
    protected $description = '相手が最後に使った技を出す。';
 
    /**
    * タイプ
    * @var string
    */
    protected $type = 'TypeFlying';
 
    /**
    * 分類
    * @var string(physical:物理|special:特殊|status:変化)
    */
    protected $species = 'status';
 
    /**
    * 威力
    * @var integer
    */
    protected $power = null;
 
    /**
    * 命中率
    * @var integer
    */
    protected $accuracy = null;
 
    /**
    * 使用回数
    * @var integer
    */
    protected $pp = 20;
 
    /**
    * 対象(使ったポケモンから見た立場)
    * @var string
    */
    protected $target = 'enemy';
 
    /**
    * オウム返し専用効果
    *
    * @param Pokemon $def 防御ポケモン
    * @param battle_state:object::BattleState バトル状態
    * @return mixed
    */
    public function exMirrorMove($def, $battle_state)
    {
        $black_list = [
            // オウム返し・カウンター・わるあがき・ものまね
            get_class(), 'MoveCounter', 'MoveStruggle', 'Mimic'
        ];
        // 相手が最後に使用した技を取得
        $move_class = $battle_state->getLastMove($def->getPosition());
        // 技が取得できない、またはコピーできない技一覧と一致すれば失敗
        if(
            empty($move_class) ||
            in_array($move_class, $black_list, true)
        ){
            return false;
        }
        // 取得した技をインスタンス化
        $move = new $move_class;
        if($move->getTarget() === 'friend'){
            return false;
        }
        // 成功(技のインスタンスを返却)
        return $move;
    }
 
}

 

オウムがえしでは特別処理が入るため、effectschargeとは違う専用メソッド(exMirrorMove)を作成しました。

まず、先程作成したプロパティ(target)を使って判定できない例外技をブラックリストとして配列を用意します。現在わかる範囲で「オウムがえし」「カウンター」「わるあがき」「ものまね」を用意しました。

※ゆびをふるはターゲット不定のため外しました。ただ、不定を導入する必要がなさそうであれば、自分(friend)の設定にする予定です

 

引数では、判定に必要な相手ポケモンとバトル状態のオブジェクトを取得しています。

まず、バトルオブジェクトから最後に使用した技を取り出します。

※こちらは次項で説明します

もし技使用前(初ターン等)であったり、ブラックリストの技と一致した場合は失敗の判定としてfalseを返却します。その2つをクリアできれば、技をインスタンス化してターゲットを確認、friendであれば失敗とみなしfalseを返却します。

 

技成功の場合は、そのまま取得した技のインスタンスを返り値とします。これで、失敗ならfalse、成功ならコピーできた技を攻撃トレイトへ伝えることができます。

 

バトルシステムへの実装

それでは、バトルで使えるようにするため、バトルシステム内にオウムがえしの判定処理を実装していきましょう。

  

最後に使用した技

まず、前項で登場したバトルシステムから最後に使用した技を取得するための処理を追加します。

 

バトル状態クラス(/Classes/BattleState.php
<?php
/**
* バトル状態クラス
*/
class BattleState
{
 
--省略
 
    /**
    * 最後に使用した技
    * @var array
    */
    private $last_moves;
 
    /**
    * @return void
    */
    public function __construct()
    {
        $this->init();
    }
 
    /**==================================================================
    * 初期化・初期値
    ==================================================================**/
 
    /**
    * 初期化
    * @return void
    */
    public function init() :void
    {
        $this->run = 0;
        $this->dafaultFields();
        $this->dafaultTurnDamages();
        $this->dafaultLastMoves();
    }
 
--省略
 
    /**
    * 最後に使用した技の初期値
    * @return void
    */
    public function dafaultLastMoves() :void
    {
        $this->last_moves = [
            'friend' => '',
            'enemy' => '',
            'all' => '',
        ];
    }
 
--省略
 
    /**==================================================================
    * 最後に使用した技
    ==================================================================**/
 
    /**
    * 最後に使用した技(クラス)の取得
    * @param position:string::friend|enemy|all
    * @return string
    */
    public function getLastMove(string $position = 'all')
    {
        return $this->last_moves[$position];
    }
 
    /**
    * 最後に使用した技(クラス)の格納
    * @param move:object|string::Move
    * @param position:string::friend|enemy
    * @return void
    */
    public function setLastMove(string $position, $move)
    {
        // オブジェクト・文字列(クラス名)両方を許可
        if(is_object($move)){
            $class = get_class($move);
        }else{
            $class = $move;
        }
        $this->last_moves[$position] = $class;
        $this->last_moves['all'] = $class;
    }
 
}

 

他のステータスと同じように、初期値を用意してセット、取得と格納用のメソッドを用意しました。1点異なる点は「すべての最終技」としてallの値をセットできるという点です。こちらは使うかどうかわかりませんが、技や状況によっては必要になる可能性を考慮して実装しておきました。

 

次に、最後に使用した技を格納するタイミングについてです。

ゲームの仕様を確認できていませんが、PHPポケモンでは「発動した技」を最後に使用した技とみなして格納する仕様にしました。

 

例えば以下のような流れが発生したケースで考えてみてください。

「敵:たいあたり」

→「味方:オウムがえし(たいあたり)」

→「敵:オウムがえし(???)」

 

上記の場合、敵が使用した「オウムがえし」ではどの技を返すのが正解なのかです。実際に試してみるとわかるかも知れませんが、技をそのまま格納すると「オウムがえし」が選ばれることになり失敗となります。ですが、実際に発動した技を考慮すれば「たいあたり」をコピーしなければなりません。

PHPポケモンでは「たいあたり」を返せるように、attackメソッドの返り値として技オブジェクトを返却し、attackメソッド直後に最後に使用した技を格納しました。

 

バトルサービス(/App/Services/Battle/FightService.php
/**
* 行動順に攻撃処理
*
* @return boolean (false: ひんしポケモン有り)
*/
private function actionAttack($orders)
{
    foreach($orders as list($atk, $def, $move)){
        // 攻撃ポケモンの怒り解除
        $atk->releaseSc('ScRage');
        // 攻撃(返り値に使用した技を受け取る)
        $attack_move = $this->attack($atk, $def, $move);
        // 最後に使用した技を格納
        $this->battle_state
        ->setLastMove($atk->getPosition(), $attack_move);
        // バトル終了のレスポンスチェック(交代技など)
        if(getResponse('end')){
            break;
        }
        // ひんしチェック
        $this->fainting = [
            $atk->getPosition() => $this->checkFainting($atk),
            $def->getPosition() => $this->checkFainting($def),
        ];
        // どちらかがひんし状態なら処理終了
        if($this->fainting['friend'] || $this->fainting['enemy']){
            $result = false;
            break;
        }
    } # endforeach
    // 結果返却
    return $result ?? true;
}

 

attackメソッドのreturnのタイミングでは、すべて技オブジェクトを返却しています。これで、最終技をバトル状態クラスに格納しています。

 

オウムがえしの特別処理

それでは、attackメソッド内でオウムがえしの判定を追加していきましょう。

 

攻撃トレイト(/App/Traits/Service/Battle/ServiceBattleAttackTrait.php
/**
* 攻撃
* (攻撃→ダメージ計算→ひんし判定)
*
* @param atk_pokemon:object::Pokemon
* @param def_pokemon:object::Pokemon
* @param move:object::Move
* @return object::Move
*/
protected function attack(object $atk_pokemon, object $def_pokemon, object $move) :object
{
    // 補正値の初期化
    $this->m = 1;
    // 行動チェック(状態異常・状態変化)
    if(
        !$this->checkBeforeSa($atk_pokemon) ||
        !$this->checkBeforeSc($atk_pokemon)
    ){
        // 行動失敗
        return $move;
    }
    // 「わるあがき」の確認とPP消費処理
    if(!$this->checkEnabledMove($move, $atk_pokemon)){
        setMessage($atk_pokemon->getPrefixName().'は出すことのできる技がない');
    }
    // 「オウムがえし」の特別処理
    if(get_class($move) === 'MoveMirrorMove'){
        $mirror_move = $this->attackMirrorMove($atk_pokemon, $def_pokemon, $move);
        if(!$mirror_move){
            // 技失敗
            setMessage('しかし上手く決まらなかった');
            return $move;
        }else{
            // ミラー技をセット
            $move = $mirror_move;
        }
    }
    // チャージチェック
    $charge = $move->charge($atk_pokemon);
    if($charge){
        // チャージターンなら行動終了
        setMessage($charge);
        return $move;
    }
 
--省略

 

チャージチェック前にオウムがえしの特別処理を行いました。処理内容が多いのでメソッド分けをしています。

attackMirrorMoveの中身は以下の通りです。

/**
* オウムがえしの特別処理
*
* @param atk:object::Pokemon
* @param def:object::Pokemon
* @param move:object::Move
* @return mixed::Move|false
*/
private function attackMirrorMove($atk, $def, $move)
{
    // オウムがえしで「チャージ状態」になっているかどうかを確認
    $charge = $atk->getChargeMove();
    if($charge){
        return new $charge;
    }
    // オウムがえしで「あばれる状態」になっているかどうかを確認
    $thrash = $atk->getThrashMove();
    if($thrash){
        return new $thrash;
    }
    // オウム返しの発動メッセージ
    setMessage($atk->getPrefixName().'は'.$move->getName().'を使った!');
    return $move->exMirrorMove($def, $this->battle_state);
}

 

ここで注目すべきポイントは「チャージ状態」と「あばれる状態」についてです。この2つの状態ではループが発生するため、状態変化にかかっていれば選択された技がそのまま実行されます。ただオウムがえしの判定をするだけでは「あばれる」をコピーした際に2回目の実行では「あばれる」が選択されず、永久に解除されないという状態に陥ってしまいます。チャージ技をコピーした場合も同じです。

それを回避するためにも2つ状態であれば、オウムがえしの特別処理ではなく「あばれる状態の技」または「チャージ状態の技」を抽出して返却します。

この2つの状態に当てはまらなければ、オウムがえしの処理を発生させ、コピーできた技を返却します。

 

では、実際にオウムがえしを使ってみましょう。

 

通常技に対する「オウムがえし」 

 

「あばれる」に対する「オウムがえし」

 ※「あばれる」は検証用に威力を20にしています。また、ライチュウも検証用として「あばれる」しか使いません

 

それぞれ正常に処理が返りました。これで「オウムがえし」の実装は完了です。

 

まとめ

いかがだったでしょうか。

今回のPHPポケモンでは「オウムがえしの実装方法」をご紹介しました。

プログラミング学習に取り組んでいる方や、ゲームづくりに興味がある人は、ぜひ参考にしてみてくださいね。

 

注目の記事

起業・独立を考えている人に向けた具体的なアドバイス3選
雑記
起業・独立を考えている人に向けた具体的なアドバイス3選

  「どのタイミングで起業すべき?」 「会社を作るためにはどういったことをすればいいの?」   あなたはこんな悩みを抱えていませんか? 今回は、これから独立・起業をしようと考えている方や、そういった野望をいだいている人に向けて、自らの経験を元に具体的なアドバイスを3つピックアップしてご紹...

PHPポケモン「オートローダー編」16
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「オートローダー編」16

  今までは技やタイプを一括requireという荒業で対応していましたが、フシギダネ系列の技を実装した際に「こんなん全部読み込んでられるか!」と流石になったので、簡易ながらオートローダーを実装していきます。 そして、実装したらしたで色々と問題も浮かび上がってきたので、このあたりは回を進めて行きなが...

簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】
ライティング
ブロガー,ブログ
簡単に良質なブログ記事を量産する3箇条【ネタがないとは言わせない】

  ブログの毎日のテーマ決めが大変・・・ そもそも良質な記事をどうやって書けるようになるのかわからない   こんな悩みを抱えていませんか? 始めたばかりで伸び悩んでいる人には多いのではないでしょうか。 今回はブログで収益化や、アクセス数を伸ばそうと考えている人へ向けて「簡単に良質なブログ...

システムエンジニアとプログラマーの違いって?仕事内容や必要スキルについてわかりやすく解説します【SE・PG】
プログラミング
システムエンジニアとプログラマーの違いって?仕事内容や必要スキルについてわかりやすく解説します【SE・PG】

  システムエンジニアってどんな仕事? プログラマーとどう違うの?   プログラミング教育が必修化になり、SEやPGの職業が注目された今、この違いについてわからない、教えて欲しいという質問が後を絶ちません。 今回はそういった人たちのために、システムエンジニア(SE)とプログラマー(PG)という職業に...

PHPポケモン「バトルシステム実装編〜補正値計算・乱数・急所〜」21
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム実装編〜補正値計算・乱数・急所〜」21

バトルシステムの実装  今回は「急所」と「乱数」と「タイプ一致」の判定と補正を実装していきます。 ちなみにですが、ポケモンwikiを熟読したところ、補正値の計算にも順番があり、計算後に小数点の切り捨てや五捨五超入をするなど、そこそこ複雑な計算順序がありましたが、今回はそこまで精密に再現せず、補正値(...

進化の石編(実装)PHPポケモン103
プログラミング
PHP,PHPポケモン,ポケモン
進化の石編(実装)PHPポケモン103

アイテムによる進化 前回作成した、進化アイテムによる構成の続きです。   進化アイテムとして「かみなりのいし」、ピカチュウの進化判定を作成したので、アイテムの使用から進化処理までを作成、実装します。   今回作成する処理は以下の2点です。 アイテムの使用判定 進化画面への移管   それ...

WordPressをローカルと本番環境で同じ状態にするために理解しておきたい3つのポイントを徹底解説
プログラミング
PHP,phpMyAdmin,WordPress
WordPressをローカルと本番環境で同じ状態にするために理解しておきたい3つのポイントを徹底解説

  WordPressで作ったサイトは通常のサイトと違い、DBが絡んでくるためローカル環境と本番環境を同一の状態で稼働させるには設定や更新されるディレクトリの知識が必要になります。 今回は、WordPressを使ったサイトを作成している人や、開発に挑戦しようとしている人に向けて、ローカルで作ったWordPressのサイ...

ネコにこばん編 PHPポケモン73
プログラミング
PHP,PHPポケモン,ポケモン
ネコにこばん編 PHPポケモン73

ネコにこばんとは 初代ポケモンでは、基本的にトレーナーとのバトルでしかお金を増やすことができず、もし手持ち金が0円の状態で金が必要なイベントが発生すると詰んでしまうという隠された落とし穴がありました。 ですが、初代でも唯一トレーナー意外からお金を得る方法があります。それが「ネコにこばん」という...

カテゴリ

SEO対策 イベント デザイン ネットワーク ビジネスモデル フリーランス プログラミング マーケティング ライティング 動画編集 雑記

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss SEO SEO対策 Sequel Pro Skype SNS SSH Symfony TCP/IP title Toastr Trait Twig Twitter UCC V系 WAN WebSub Wi-Fi wiki Windows WordPress XAMPP xml Xserver YouTube YouTuber Zoom アーティスト アウトプット アクセス層 アニメーション アフィリエイト イーブイ インターネット インプット エンジニア オブジェクト指向 お金配り クリック単価 クリック数 コミュニケーション能力 コロナ コンサルティング サムネイル システムエンジニア スタートアップ スタイルシート スパム データベース ディープフェイク デザイナー デザイン テレワーク ナンパ ニュース ネットワークモデル ノマドワーク バナー ピカチュウ ビジネス フィード フリーランス ブロガー ブログ プログラマー プログラミング プログラミング学習 プログラミング教育 プロトコル ホームページ制作 ポケモン マークアップ マーケティング メール リモートワーク レンダリング 三井住友 三宮 仕事依頼 児童デイ 児童デイサービス 児童発達支援 公開鍵 初心者 助成金 勉強法 営業 広告 広告収入 必勝マニュアル 放課後等デイサービス 朝活 楽天 深層学習 無線LAN 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力