【解決済み】【RGSS3】自動戦闘AIについてここまでわかったのでどなたかヘルプ願います

返答がない場合、寝落ちの可能性がアリ
記事: 2
登録日時: 2016年8月01日(月) 02:27

【解決済み】【RGSS3】自動戦闘AIについてここまでわかったのでどなたかヘルプ願います

投稿記事by 返答がない場合、寝落ちの可能性がアリ » 2016年8月01日(月) 03:33

RGSS3を読める方に二つほど質問です、自動戦闘AI強化の為にベースのスクリプトを弄ってるのですが

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● スキル/アイテムの評価(ターゲット指定)
  #--------------------------------------------------------------------------
  def evaluate_item_with_target(target)
    target.result.clear
    target.make_damage_value(subject, item)
    if item.for_opponent?
#      return target.result.hp_damage.to_f / [target.hp, 1].max
      n = target.result.hp_damage.to_f / [target.hp, 1].max
      if target.hp > target.mhp / 4
        n += 0.2 if target.result.hp_damage == 0
      end
      if target.result.hp_damage != 0
        n += 0.2 if target.movable? && !target.confusion?
        n += 0.3 if target.result.hp_damage > target.hp
        n += 0.5 if target.result.hp_damage > target.mhp
      end
    else
      recovery = [-target.result.hp_damage, target.mhp - target.hp].min
      n = recovery.to_f / target.mhp
      if target.hp > target.mhp / 4
        n += 0.2 if target.result.hp_damage == 0
        n += 0.1 if target.result.mp_damage != 0 && target.mp < target.mmp / 4
      end
      if target.result.hp_damage != 0
        n += 0.3 if target.hp < target.mhp / 2
        n += 0.2 if target.hp < target.mhp / 4
        n += 0.5 if target.hp == 0
      end
#      return recovery.to_f / target.mhp
    end
    return n
  end
 

これは何をやりたいかと申しますと
敵対象の場合
・対象が瀕死ではない(HPが4分の1以上)場合、ダメージのない行動(弱体や状態異常)を優先します
・ダメージのある行動の場合、行動可能な対象と混乱していない対象を選びたがります
・更に対象のHPを見て一撃で倒せる可能性がある場合はそれを狙います
・最初から一撃で倒せる弱い敵を最優先で倒そうとします
味方対象の場合
・対象が瀕死ではない(HPが4分の1以上)場合、ダメージのない行動(強化や補助)を優先します
・更に対象のMPが少ない(4分の1以下)場合はMPを回復する行動を取りたがります
・回復スキルの場合、対象のHPが2分の1以下で優先し始め、瀕死(HPが4分の1以下)の対象を高確率で回復させます
・死亡した対象を最優先で蘇生させます
数値を微調整しながらテストプレイを繰り返しても前述の仕様になってるか
体感的に微妙すぎてもっといい弄り方があるのではないか…というお話です。

もう一つの質問はSupponの意味不明ブログというサイトのテクニックである
RGSS2備忘録その7 臨機応変に行動できる自動戦闘のアクター
これのACE版を作ろうとしたのですが

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● 戦闘行動の処理
  #--------------------------------------------------------------------------
  def process_action
    return if scene_changing?
    if !@subject || !@subject.current_action
      @subject = BattleManager.next_subject
    end
    return turn_end unless @subject
    if @subject.current_action
      @subject.current_action.prepare

#←ここにですね

      if @subject.current_action.valid?
        @status_window.open
        execute_action
      end
      @subject.remove_current_action
    end
    process_action_end unless @subject.current_action
  end
 

恐らくあの辺りの場所に
if @subject.actor?
@subject.自動行動の再抽選 if @subject.自動戦闘フラグがONか?
end
みたいな感じのものを入れればいいのではないのかと思うのですがそれ以上がわかりません
最後に編集したユーザー 返答がない場合、寝落ちの可能性がアリ on 2016年8月03日(水) 23:21 [ 編集 1 回目 ]

あらゆる状況において寝落ちの常習犯です、それだけはお気を付けください。
(だって眠いんですもの)
faida
記事: 272
登録日時: 2015年12月17日(木) 16:44

Re: 【RGSS3】自動戦闘AIについてここまでわかったのでどなたかヘルプ願います

投稿記事by faida » 2016年8月03日(水) 14:11

前者の質問から行きましょうか。
まず、この「スキル/アイテムの評価(ターゲット指定)」という処理が、「どのように」「どういった対象に行われているか」
というのが理解の基礎となります。

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● スキル/アイテムの評価
  #--------------------------------------------------------------------------
  def evaluate_item
    item_target_candidates.each do |target|
      value = evaluate_item_with_target(target)
      if item.for_all? # 全体対象なら
        @value += value # 全体の合計を優先度とする
      elsif value > @value # 全体対象でなければ
        @value = value
        @target_index = target.index # 最も効果的なキャラに
      end
    end
  end

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● スキル/アイテムの使用対象候補を取得
  #--------------------------------------------------------------------------
  def item_target_candidates
    if item.for_opponent?
      opponents_unit.alive_members
    elsif item.for_user?
      [subject]
    elsif item.for_dead_friend? # 戦闘不能対象なら
      friends_unit.dead_members # 戦闘不能のキャラに
    else # 戦闘不能対象でないなら
      friends_unit.alive_members # 戦闘不能でないキャラに
    end
  end
自動戦闘のキャラは、自分の覚えているスキル全部に対して評価をします。
上のコードを見ると、(特に敵の数が多いほど)全体対象の行動が優先されやすいというのがわかると思います。
下のコードでは、戦闘不能のキャラに対しては戦闘不能対象のスキルしか評価してくれないというのがわかると思います。

次は、実際にあなたの弄ったスクリプトに沿って解説していきましょう。敵側/味方側に分けて考えます。

コード: 全て選択

#      return target.result.hp_damage.to_f / [target.hp, 1].max
      n = target.result.hp_damage.to_f / [target.hp, 1].max # ダメージの効果量
      if target.hp > target.mhp / 4
        n += 0.2 if target.result.hp_damage == 0
      end
      if target.result.hp_damage != 0
        n += 0.2 if target.movable? && !target.confusion? # 行動可能かつ混乱でない
        n += 0.3 if target.result.hp_damage > target.hp
        n += 0.5 if target.result.hp_damage > target.mhp
      end
上記「ダメージの効果量」というところをご覧ください。
計算式は「HPダメージ / 対象のHP」となっています。で、ダメージが対象のHPを超える場合は「nが1以上」となります。
数値をいじる場合、特に「ダメージが敵の最大HPを上回る場合」はこれを参考にするといいかと思います。

コード: 全て選択

recovery = [-target.result.hp_damage, target.mhp - target.hp].min
      n = recovery.to_f / target.mhp # 回復の効果量
      if target.hp > target.mhp / 4
        n += 0.2 if target.result.hp_damage == 0
        n += 0.1 if target.result.mp_damage != 0 && target.mp < target.mmp / 4
      end
      if target.result.hp_damage != 0 # 「ダメージ計算による回復」が0でない場合
        n += 0.3 if target.hp < target.mhp / 2
        n += 0.2 if target.hp < target.mhp / 4
        n += 0.5 if target.hp == 0
      end
#      return recovery.to_f / target.mhp
上記「回復の効果量」というところをご覧ください。
計算式は「HP回復量 / 対象の最大HP」となっております。つまり、対象の最大HPが低いほど効果量が大きくなるわけです。
あと、これはあくまで「ダメージ計算」の値のみを使用しており、「使用効果」の回復などを一切見ていないので、使用効果による回復などを使用している場合はダメージ計算式に入れないと優先されません。
なので、単純に「戦闘不能を解除するだけ」のスキルは絶対といっても過言ではないくらい使用してくれません。通常攻撃します。

で、ここまで見てきたものをぶっ壊すようで申し訳ないのですが、最後にこちらをご覧ください。

コード: 全て選択

  #--------------------------------------------------------------------------
  # ● 行動の価値評価(自動戦闘用)
  #    @value および @target_index を自動的に設定する。
  #--------------------------------------------------------------------------
  def evaluate
    @value = 0
    evaluate_item if valid? # さっきの処理
    @value += rand if @value > 0 # 0~1の乱数を足す
    self
  end
はい、ぶっちゃけ0.5の差があろうが運が悪ければ優先度が低い行動を使ってしまいます。完全に行動を制御するのは難しいので、あくまで「傾向」としてとらえていただければと思います。
まぁ自動戦闘をつけているキャラは「弱点が分かっている」「敵の残りHPが分かっている」「臨機応変にすることも可能」というプレイヤーからすればチート級のキャラなので少々アホでもいいと思うんですけどね……。


後者の質問ですが、単純にあなたの言う通りの文にするなら

コード: 全て選択

@subject.make_auto_battle_actions if @subject.actor? && @subject.auto_battle?
となります。
------------------------------------------------------------------
自作の(改造でない)スクリプト、プラグイン素材に
関しては、リードミーもしくは作中に
「faida」と記名していただければ
利用可能です。
返答がない場合、寝落ちの可能性がアリ
記事: 2
登録日時: 2016年8月01日(月) 02:27

Re: 【RGSS3】自動戦闘AIについてここまでわかったのでどなたかヘルプ願います

投稿記事by 返答がない場合、寝落ちの可能性がアリ » 2016年8月03日(水) 23:20

おおー、元々死んで覚えるタイプのゲームが好きなので
(基本的に敵のHP量や耐性やスキルを考慮して対策しなければ道中の雑魚相手でも全快状態から全滅の危険があるようなゲーム)
自動戦闘NPCがある程度頭が良くないと完全に足手まといになるので特に後者のは助かります。
やりたい事は大体わかっても呼び出すコードがどこなのかがよくわからない事があるという…
基本的に的確な行動をするがちょっとランダム行動を足して乱数が出す笑える奇跡を起こすNPCって良いですよねぇ

ありがとうございました!

追記、前述の超反応AIの敵バージョンは

コード: 全て選択

@subject.make_actions if @subject.enemy?

で出来ますね、更に敵のAIを弄ると面白い事が出来そうかも
あらゆる状況において寝落ちの常習犯です、それだけはお気を付けください。
(だって眠いんですもの)

“VX / Ace:質問” へ戻る