2006-09-13
          RPGの戦闘みたいなプログラム
中学から高校のころこういうプログラムを実現したくて Basic で何度も書いていた。でも当時こんなにすっきり書けるはずもなく、ひたすら力押しで長いコードを書いては途中で挫折していたものだ。それでも楽しかったのだけど。
この問題の解決を容易にしている要因の1つはオブジェクト思考。今では無意識にこういうコードを書いてしまうけど、意識して見ると attack メソッド内でキャラクターオブジェクトのポリモフィズムを利用することで攻撃手と受け手の処理をうまく共通化している。さりげなく hp > 0 を alive? メソッドに置き換えているのも心憎い。こんなの昔はできなかったよなあ。あのころの自分にこういうのうまく理解させることはできるだろうか……。
class Character
  attr_accessor :name, :str, :def, :agi, :hp
  def initialize(name, str, _def, agi, hp)
    @name = name
    @str = str
    @def = _def
    @agi = agi
    @hp = hp
  end
  def alive?
    hp > 0
  end
end
def attack(attacker, target)
  return unless attacker.alive?
  d = rand(attacker.str) - rand(target.def)
  if d > 0
    target.hp -= d
    puts "#{attacker.name} の攻撃 => #{d} のダメージ!"
  else
    puts "#{attacker.name} の攻撃 => ミス!"
  end
  unless target.alive?
    puts "#{attacker.name} は #{target.name} を倒した"
  end
end
a = Character.new('A', 25, 25, 25, 25)
b = Character.new('B', 25, 25, 25, 25)
while a.alive? && b.alive?
  d = rand(a.agi) - rand(b.agi)
  if d > 0
    attack a, b
    attack b, a
  elsif d < 0
    attack b, a
    attack a, b
  end
end
            実行結果。
A の攻撃 => 8 のダメージ! B の攻撃 => 14 のダメージ! A の攻撃 => 12 のダメージ! B の攻撃 => ミス! B の攻撃 => 11 のダメージ! B は A を倒した