-
Notifications
You must be signed in to change notification settings - Fork 0
/
battle.py
123 lines (90 loc) · 5.89 KB
/
battle.py
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
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
from __future__ import division
import units
import terrain
import random
import operator
from collections import Counter
import math
import numpy as np
from scipy.special import binom
#p = 0.05 * (((A + Ta) - (D + Td))+B) + 0.5
#if p < 0 set p to 0
#if p > 1 set p to 1
#For each sub unit of the attacker six random numbers (r) between 0 and 1 are generated. For each r < p a hit is counted.
#The total number of hits divided by 6 is the number of sub units the opponent loses during the attack.
#Attacker and defender then switch roles and the process starts over. Please note: Losses will only be removed when
#the battle is over. They will not affect the calculations of the current attack.
def get_hit_probability(attacking_power, attacking_terrain_modifier, defending_defense, defending_terrain_modifier, gangup_bonus):
return np.clip(0.05 * (((attacking_power + attacking_terrain_modifier) - (defending_defense + defending_terrain_modifier)) + gangup_bonus) + 0.49, 0.0, 1.0)
def get_single_result(attacking_health, attacking_power, attacking_terrain_modifier, defending_health, defending_defense, defending_terrain_modifier, gangup_bonus):
p = get_hit_probability(attacking_power, attacking_terrain_modifier, defending_defense, defending_terrain_modifier, gangup_bonus)
r = np.random.uniform(0, 1, attacking_health * 6)
hits = np.sum(r < p)
return max(0, defending_health - int(hits / 6))
def calc_probabilities(attacking_health, attacking_power, attacking_terrain_modifier, defending_health, defending_defense, defending_terrain_modifier, gangup_bonus):
p = get_hit_probability(attacking_power, attacking_terrain_modifier, defending_defense, defending_terrain_modifier, gangup_bonus)
n = attacking_health * 6
probs = [binom(n, k) * p ** k * (1 - p) ** (n - k) for k in range(60)]
binned_probs = 100.0 * np.array(probs).reshape(10, -1).sum(axis=1)[::-1]
z = np.zeros(20)
z[defending_health:defending_health + 10] = np.array(binned_probs)
z[9] = sum(z[:10])
return dict(enumerate(z[9:20]))
#@profile
def simulate_probabilities(attacking_health, attacking_power, attacking_terrain_modifier, defending_health, defending_defense, defending_terrain_modifier, gangup_bonus):
num_simulations = 1000000
p = get_hit_probability(attacking_power, attacking_terrain_modifier, defending_defense, defending_terrain_modifier, gangup_bonus)
#res = []
#for x in range(num_simulations):
# #r = np.random.randint(0, 100, attacking_health * 6) + 1
# r = np.random.uniform(0, 1, attacking_health * 6)
# hits = np.sum(r < p)
# res.append(max(0, defending_health - int(hits / 6)))
#return dict([(key, 100.0 * value / num_simulations) for key, value in Counter(res).items()])
r = np.random.uniform(0, 1, (num_simulations, attacking_health * 6))
hits = np.sum(r < p, axis=1)
res = np.clip(defending_health - np.floor(hits / 6), 0, 10).astype(np.int64)
bins = np.bincount(res) * 100.0 / num_simulations
return dict(enumerate(bins))
def evaluate(attacking_type, attacking_health, attacking_terrain, defending_type, defending_health, defending_terrain):
attacking_class = units.type[attacking_type].unitclass
defending_class = units.type[defending_type].unitclass
attacking_power = units.type[attacking_type].power[defending_class]
defending_power = units.type[defending_type].power[attacking_class]
attacking_terrain_modifier = terrain.getTerrainModifier(attacking_class, attacking_terrain)
defending_terrain_modifier = terrain.getTerrainModifier(defending_class, defending_terrain)
## todo: not yet implemented
gangup_bonus = 0
attacking_left = get_single_result(defending_health, defending_power, defending_terrain_modifier[0], attacking_health, units.type[attacking_type].defense, attacking_terrain_modifier[1], gangup_bonus)
defending_left = get_single_result(attacking_health, attacking_power, attacking_terrain_modifier[0], defending_health, units.type[defending_type].defense, defending_terrain_modifier[1], gangup_bonus)
return attacking_left, defending_left
def debug(attacking_type, attacking_health, attacking_terrain, defending_type, defending_health, defending_terrain):
attacking_class = units.type[attacking_type].unitclass
defending_class = units.type[defending_type].unitclass
attacking_power = units.type[attacking_type].power[defending_class]
defending_power = units.type[defending_type].power[attacking_class]
attacking_terrain_modifier = terrain.getTerrainModifier(attacking_class, attacking_terrain)
defending_terrain_modifier = terrain.getTerrainModifier(defending_class, defending_terrain)
## todo: not yet implemented
gangup_bonus = 0
for i in range(0, 11):
print "%10d" % i,
print
print "------------------------------------------------"
r = simulate_probabilities(defending_health, defending_power, defending_terrain_modifier[0], attacking_health, units.type[attacking_type].defense, attacking_terrain_modifier[1], gangup_bonus)
for i in range(0, 11):
print "%10.6f" % (r[i] if i in r else 0),
print
r = calc_probabilities(defending_health, defending_power, defending_terrain_modifier[0], attacking_health, units.type[attacking_type].defense, attacking_terrain_modifier[1], gangup_bonus)
for i in range(0, 11):
print "%10.6f" % (r[i] if i in r else 0),
print
r = simulate_probabilities(attacking_health, attacking_power, attacking_terrain_modifier[0], defending_health, units.type[defending_type].defense, defending_terrain_modifier[1], gangup_bonus)
for i in range(0, 11):
print "%10.6f" % (r[i] if i in r else 0),
print
r = calc_probabilities(attacking_health, attacking_power, attacking_terrain_modifier[0], defending_health, units.type[defending_type].defense, defending_terrain_modifier[1], gangup_bonus)
for i in range(0, 11):
print "%10.6f" % (r[i] if i in r else 0),
print
print