プログラミング

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

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

 

注目の記事

記事を書いてもブログが伸びないのは何故?SEOの評価を下げてしまう絶対にダメな3つのこと【知らない内に損してます】
SEO対策
SEO,ブログ
記事を書いてもブログが伸びないのは何故?SEOの評価を下げてしまう絶対にダメな3つのこと【知らない内に損してます】

  1年ブログを継続したけど、全くPVが伸びない・・・   ブログを育てるためには、毎日または定期的な更新が必ず必要ですが、それでも思うように伸びないという人は、実は他に致命的にな原因があることがほとんどです。 今回はそういった「努力しても結果が出ない」と悩んでいるブロガーやブログ運営者に...

【無料】早起きをして神戸へ行こう!「為になる雑談朝活」
イベント
三宮,朝活,神戸
【無料】早起きをして神戸へ行こう!「為になる雑談朝活」

  朝活を実施することになりましたので、その目的な概要をまとめました。 神戸三宮での開催を予定しておりますので、もしお近くにお住まいの方で日時が会いましたらご参加ください。 土日祝辺りで週1日程度の不定期開催を予定しています。学びにつながる、けど参加しやすい雑談形式ということを主としています...

パーティーの並び替え編 PHPポケモン 82
プログラミング
PHP,PHPポケモン,ポケモン
パーティーの並び替え編 PHPポケモン 82

パーティーの並び替え ポケモンをバトルに選出する際に欠かせないのが「パーティーの並び替え」です。パーティーの先頭(ひんし状態でない)がポケモンでは自動的に選択されるため、戦闘前に並び替えをしておく必要があります。 ゲーム上では簡単に見える処理ですが、これがPHPで行うとなれば少し厄介な問題が出てき...

オブジェクト指向有効活用編 PHPポケモン 93
プログラミング
PHP,PHPポケモン,ポケモン
オブジェクト指向有効活用編 PHPポケモン 93

オブジェクト指向の有効活用 β版に向けたPHPポケモンの構成見直し、今回は「オブジェクト指向」の役割について、より理解を深めつつ、保守性も良くなるように整えていきます。   機能を持たせる 様々なプロパティを定数や静的変数へ以降していますが、今回は「静的メソッド」の活用範囲を増やしていきます。まず...

教師が勝ち組!?出会い&学習の超正統派マッチングサービスとは【ビジネス企画書】
ビジネスモデル
マーケティング
教師が勝ち組!?出会い&学習の超正統派マッチングサービスとは【ビジネス企画書】

  「出会いがない」   社会人になると多くの人が抱く悩みの1つです。職場の男女比率や年齢層が理由の人もいれば、同じ職場での出会いは求めていない人もいるでしょう。 今回はそんな「出会い」を解決するための企画「出会い&学習の超正統派マッチングサービス」について、企画案と考察をまとめました。   ...

なぜ(・・? あなたはMacを使うのか?
雑記
AWS,Linux,MacBook,OS,Windows
なぜ(・・? あなたはMacを使うのか?

  あなたが使っているPCはなんですか?   たまに聞かれることがあります。 そこで「Macを使っています」と答えると「何故?」という次の問いが返ってくることがあります。   あなたがもしMacを使っているのであれば、このときになんと答えますか?   今回のテーマは、「何故Macを使っているの?」と...

今からできる!ブログのアクセスを爆UPさせる3大SNS活用法
マーケティング
Facebook,Instagram,Twitter,ブロガー,ブログ
今からできる!ブログのアクセスを爆UPさせる3大SNS活用法

  ブログを収益化させたいけど、なかなかアクセス数が増えない 記事の質は高いのに、その良さをどうやって伝えれば良いかわからない   SEO対策をする上でも、収益化するためにも記事のクオリティは重要です。 しかし、せっかく良い記事を書いていても、そのブログや記事の存在を伝えることができなけれ...

バズる!ビジネスの見つけ方 〜何で起業するか悩んでいませんか?〜
マーケティング
ビジネス,起業
バズる!ビジネスの見つけ方 〜何で起業するか悩んでいませんか?〜

  独立や起業を志している9割以上の人が「何をビジネスにするか?」を悩んでいます しかし、それは負のサイクルです。 起業するためにビジネスを考えるという行為自体が”矛盾している”ということに気づかなければ、このサイクルからは抜け出すことができません。 その結果、行動できずに終わってしまう人は多...

カテゴリ

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 独立 神戸 福祉 秘密鍵 翻訳 自己啓発 英語 見積書 計算機 読書 起業 迷惑メール 配列 銀の弾丸 集客 雑学力