MOE3: 支援付き攻撃の解決

spec/models/main_phase_spec.rb

いよいよ本番といった感じ。

マニュアルの Diagram8、French A Mar–BurFrench A Gas S A Mar-BurGerman A Bur-Holds の支援、攻撃、敗退処理を実装する。

f:id:asagix:20130917115506p:plain:w200

describe MainPhase do
  describe "#resolve_orders" do
    let(:phase) { MainPhase.create }
    let(:resolved_orders) { phase.resolve_orders }

    #(略)

    shared_context "Diagram8 移動支援", diagram: 8 do
      let(:army_mar) { FactoryGirl.create(:army, :f, :mar, phase: phase) }
      let(:army_gas) { FactoryGirl.create(:army, :f, :gas, phase: phase) }
      let(:army_bur) { FactoryGirl.create(:army, :g, :bur, phase: phase) }

      let(:prov_bur) { army_bur.province }

      let!(:move_mar_bur) { FactoryGirl.create(:move_order, unit: army_mar, destination: prov_bur) }
      let!(:supp_gas_mar) { FactoryGirl.create(:support_order, unit: army_gas, target: move_mar_bur) }
      let!(:hold_bur) { FactoryGirl.create(:hold_order, unit: army_bur) }
    end

    context "Diagram8", diagram: 8 do
      subject { resolved_orders }
      example { expect(subject.find(move_mar_bur).status).to eq OrderStatus::SUCCESS }
      example { expect(subject.find(supp_gas_mar).status).to eq OrderStatus::SATISFIED }
      example { expect(subject.find(hold_bur).status).to eq OrderStatus::DISLODGED }
    end
  end
end

MainPhase#resolve_attack メソッド

処理の順番はスタンドオフ解決後。

支援のカットや自軍攻撃支援の無効化などは後回しで、まずはシンプルに。

class MainPhase < Phase
  def resolve_orders
    setup
    resolve_move
    resolve_standoff
    resolve_attack
    resolve_pileup
    resolve_rotation
    cleanup
    orders(true)
  end

  #(略)

  # 維持ユニットへの攻撃
  def resolve_attack
    moves = @orders.select{|o| o.move?}
    moves.each do |move|
      hold = @orders.select{|o| o.hold? && o.province == move.dst}[0]
      next unless hold

      move_supports = @orders.select{|o| o.support? && o.target?(move)}.size
      hold_supports = @orders.select{|o| o.support? && o.target?(hold)}.size

      if move_supports > hold_supports
        move.success!
        hold.dislodged!
      else
        move.failure!
        hold.success! if hold.unexecuted?
      end
    end
  end

  #(略)
end

色々足りてないので、当然エラーになる。

SupportOrder#support? メソッド

とりあえず無条件で true

後々、カットまたは撃退されたら false を返すようになるはず。

class SupportOrder < Order
  def support?
    true
  end
end

もちろん Order#support? は常に false を返すようにしておく。

SupportOrder#target? メソッド

こちらも Order#target?false を返すようにしておく。

ついでに MoveOrder かどうかを意識せずに dst を呼べるように、常に nil を返す Order#dst もこっそり追加。ステータス変更用の Order#dislodged! もね。

class SupportOrder < Order
  def target?(order)
    return false if self.target.unit != order.unit
    return false if self.target.dst != order.dst
    true
  end
end

とりあえずここまで。

現状整理

SupportOrder のステータスを変更する処理を入れていないので、このままでは通らないテストがある。

次回、MainPhase#apply_supports メソッドを実装しよう。