プログラミング

オウムがえし編 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ポケモンでは「オウムがえしの実装方法」をご紹介しました。

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

 

注目の記事

AIが人類にもたらす驚異!深層学習が与える影響とは
ネットワーク
AI,ディープフェイク,深層学習
AIが人類にもたらす驚異!深層学習が与える影響とは

  海外の記事でAIについて記述した興味深いものが掲載されました。   今回は「AIが人類にもたらす驚異!深層学習が与える影響とは」について、上記サイトを参考にまとめましたのでご紹介します。 ※直訳ではありません、あくまで記事の内容を参考にして自らの考えを記述したものです     AIの驚異と...

ゆびをふる編 PHPポケモン 69
プログラミング
PHP,PHPポケモン,ポケモン
ゆびをふる編 PHPポケモン 69

ゆびをふるとは 今回PHPポケモンで実装する技は「ゆびをふる」です。  ゆびをふる(ポケモンwiki) https://wiki.ポケモン.com/wiki/ゆびをふる   「ゆびをふる大会」というゆびをふるのみを使った大会なども開催されているということもあり、ポケモンの技の中でも初代から長く愛されてきた1つです。で...

わざマシン編 作成 PHPポケモン104
プログラミング
PHP,PHPポケモン,ポケモン
わざマシン編 作成 PHPポケモン104

わざマシンとは ポケモンはレベルアップ以外でも技を習得することができます。それが「わざマシン」というアイテムです。  わざマシン(ポケモンwiki) https://wiki.ポケモン.com/wiki/わざマシン   最新世代では「技レコード」というものが有り、使い切りとなっています。初代ではわざマシン自体も使い...

PHPポケモン「バトルシステム編〜状態変化〜」32
プログラミング
PHP,PHPポケモン,ポケモン
PHPポケモン「バトルシステム編〜状態変化〜」32

状態変化とは  状態異常の実装が完了したので、いよいよ状態変化の実装に移ります。PHPポケモンで実装する状態変化とは以下の4つです。 こんらん ひるみ バインド やどりぎのタネ   上記4つを実装していきます。状態異常と異なり、技によっては追加になる可能性があります。 ※いかり状態など  ...

【Laravel7】既存makeテンプレートのカスタマイズ Requestサンプル有り
プログラミング
Laravel,Linux,PHP
【Laravel7】既存makeテンプレートのカスタマイズ Requestサンプル有り

  Laravel7では新しい機能が様々導入されており、Webアプリケーションの開発がよりスムーズなものとなってきています。その中でも、もどかしい場所へ手を届いたと感じさせてくれたのが、既存makeコマンドのstubを簡単にカスタマイズできるようになったことです。   今回は既存make用stubの取得コマンドと、リ...

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

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

なぜプロは有線のマウスやキーボードを選ぶのか?【有線VS無線】
雑記
Bluetooth
なぜプロは有線のマウスやキーボードを選ぶのか?【有線VS無線】

  無線が普及する現代、何故有線のマウスやキーボードは売れているのか   いろんなものが製品の進化と共に無線化している一方、有線の需要も高く、とくにプロなど上層で活躍する人は有線を選択するケースが少なくありません。 今回は、そんな有線と無線の違いや、それぞれのメリットについて解説していき...

ポケモン預かりシステム編 ボックスの作成 PHPポケモン 86
プログラミング
PHP,PHPポケモン,ポケモン
ポケモン預かりシステム編 ボックスの作成 PHPポケモン 86

ポケモン預かりシステムの実装 今回は、前回ざっくりと仕様決めをした「ポケモン預かりシステム」を実装していきます。ボックス内では操作する項目が多いため、ボックス自体に1つの画面を用意して、できる限りPHPによる制御だけで完結できるように作成していきます。   ボックスクラスの作成 それではまず、今...

カテゴリ

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

タグ

5G Adobe AfterEffects AI ajax amazon Animate api artisan atom Automator AWS Bluetooth CSS CVR description EC-CUBE4 ECショップ ESLint Facebook feedly foreach fortify function Google Google AdSense Honeycode htaccess HTML IEEE 802.11ax Illustrator Instagram IoT JavaScript jetstream jQuery jQuery UI keyword LAN Laravel Linux MacBook MAMP meta MLM MySQL NoCode note OS OSI参照モデル Paypal Photoshop PHP phpMyAdmin PHPポケモン PremierePro rss 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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 認証 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力