2 """Faithful translations of calculations the games make."""
3 from __future__
import division
5 from itertools
import izip
10 Thanks for the "compact" solution go to:
11 http://stackoverflow.com/questions/2096573/counting-combinations-and-permutations-efficiently
15 lambda x
, y
: x
* y
[0] / y
[1],
16 izip(xrange(n
- r
+ 1, n
+ 1),
21 def calculated_stat(base_stat
, level
, iv
, effort
, nature
=None):
22 """Returns the calculated stat -- i.e. the value actually shown in the game
23 on a Pokémon's status tab.
26 # Remember: this is from C; use floor division!
27 stat
= (base_stat
* 2 + iv
+ effort
// 4) * level
// 100 + 5
30 stat
= int(stat
* nature
)
34 def calculated_hp(base_stat
, level
, iv
, effort
, nature
=None):
35 """Similar to `calculated_stat`, except with a slightly different formula
36 used specifically for HP.
39 # Shedinja's base stat of 1 is special; its HP is always 1
43 return (base_stat
* 2 + iv
+ effort
// 4) * level
// 100 + 10 + level
45 def earned_exp(base_exp
, level
):
46 """Returns the amount of EXP earned when defeating a Pokémon at the given
50 return base_exp
* level
// 7
52 def capture_chance(percent_hp
, capture_rate
,
53 ball_bonus
=10, status_bonus
=1,
54 capture_bonus
=10, capture_modifier
=0):
55 """Calculates the chance that a Pokémon will be caught, given its capture
56 rate and the percentage of HP it has remaining.
58 Bonuses are such that 10 means "unchanged".
60 Returns five values: the chance of a capture, then the chance of the ball
61 shaking three, two, one, or zero times. Each of these is a float such that
62 0.0 <= n <= 1.0. Feel free to ignore all but the first.
65 # HG/SS Pokéballs modify capture rate rather than the ball bonus
66 capture_rate
= capture_rate
* capture_bonus
// 10 + capture_modifier
69 elif capture_rate
> 255:
73 # The actual formula uses (3 * max_hp - 2 * curr_hp) / (3 * max_hp)
74 # This uses (1 - 2/3 * curr_hp/max_hp)
75 # Integer division is taken into account by flooring immediately
76 # afterwards, so there should be no appreciable rounding error.
78 capture_rate
* ball_bonus
// 10 * (1 - 2/3 * percent_hp
)
80 base_chance
= base_chance
* status_bonus
// 10
82 # Shake index involves integer sqrt. Lovely.
83 isqrt
= lambda x
: int(x
** 0.5)
85 # This is very silly. Due to what must be an oversight, it's possible
86 # for the above formula to end with a zero chance to catch, which is
87 # then thrown blindly into the below denominator. Luckily, the games'
88 # division function is a no-op with a denominator of zero.. which
89 # means a base_chance of 0 is effectively a base chance of 1.
91 shake_index
= 1048560 // isqrt(isqrt(16711680 // base_chance
))
93 # Iff base_chance < 255, then shake_index < 65535.
94 # The Pokémon now has four chances to escape. The game starts picking
95 # random uint16s. If such a random number is < shake_index, the Pokémon
96 # stays in the ball, and it wobbles. If the number is >= shake_index, the
97 # ball breaks open then and there, and the capture fails.
98 # If all four are < shake_index, the Pokémon is caught.
100 # If shake_index >= 65535, all four randoms must be < it, and the Pokémon
101 # will be caught. Skip hard math
102 if shake_index
>= 65535:
103 return (1.0, 0.0, 0.0, 0.0, 0.0)
105 # This brings up an interesting invariant: sum(return_value) == 1.0.
106 # Something is guaranteed to happen.
108 # Alrighty. Here's some probability.
109 # The chance that a single random uint16 will be < shake_index, thus
110 # keeping the Pokémon in the ball, is:
111 p
= shake_index
/ 65536
113 # Now, the chance for n wobbles is the chance that the Pokémon will stay in
114 # the ball for (n-1) attempts, then break out on the nth.
115 # The chance of capture is just the chance that the Pokémon stays in the
116 # ball for all four tries.
118 # There are five cases: captured, wobbled three times, etc.