-
Notifications
You must be signed in to change notification settings - Fork 0
/
Copy pathbattle_simulator.rb
executable file
·44 lines (33 loc) · 1.69 KB
/
battle_simulator.rb
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
class BattleSimulator
attr_accessor :unit_a, :unit_b
def initialize a, b
@unit_a = a
@unit_b = b
end
def fight
raise "equal initiative not implemented" if @unit_a.i == @unit_b.i
lead = (@unit_a.i > @unit_b.i) ? @unit_a : @unit_b
follow = (@unit_a.i < @unit_b.i) ? @unit_a : @unit_b
chance_to_wound_for_lead = BattleCalculator::to_wound_on_single_attack lead, follow
chance_to_wound_for_follow = BattleCalculator::to_wound_on_single_attack follow, lead
chance_lead_wins = perform_fight lead, follow, chance_to_wound_for_lead, chance_to_wound_for_follow
end
private
def perform_fight lead, follow, lead_attacks, lead_wounds, follow_attacks, follow_wounds, chance_to_wound_for_lead, chance_to_wound_for_follow, remaining_chance=1
return 0 if (lead_wounds == 0) or (remaining_chance == 0)
return remaining_chance if follow_wounds == 0
eventual_kill_probabilities = []
(follow_wounds - 1).times do |i|
non_kill_probability = BattleCalculator::to_score_exact_wounds lead, follow, i
follow.w -= i
# Let the other figure attack by swapping lead and follow and
# inverting the return value. (this is very similar to a
# minimax algorithm) eg. If it returns .3 chance for follow to
# kill lead, then eventual_kill_probability = .7.
eventual_kill_probabilities << ( 1 - perform_fight(follow, lead, chance_to_wound_for_follow, chance_to_wound_for_lead, remaining_chance*non_kill_probability) ) # todo
end
immediate_kill_probability = BattleCalculator::to_kill lead, follow
# aggregate all kill results
immediate_kill_probability + eventual_kill_probabilities.inject(0){|sum, x| sum + x}
end
end