oakdex-battle 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +7 -0
- data/README.md +103 -0
- data/lib/oakdex.rb +3 -0
- data/lib/oakdex/battle.rb +111 -0
- data/lib/oakdex/battle/action.rb +115 -0
- data/lib/oakdex/battle/damage.rb +99 -0
- data/lib/oakdex/battle/in_battle_pokemon.rb +159 -0
- data/lib/oakdex/battle/move.rb +27 -0
- data/lib/oakdex/battle/move_execution.rb +148 -0
- data/lib/oakdex/battle/pokemon.rb +168 -0
- data/lib/oakdex/battle/pokemon_factory.rb +118 -0
- data/lib/oakdex/battle/pokemon_stat.rb +109 -0
- data/lib/oakdex/battle/side.rb +76 -0
- data/lib/oakdex/battle/status_conditions.rb +16 -0
- data/lib/oakdex/battle/status_conditions/badly_poisoned.rb +36 -0
- data/lib/oakdex/battle/status_conditions/base.rb +36 -0
- data/lib/oakdex/battle/status_conditions/burn.rb +26 -0
- data/lib/oakdex/battle/status_conditions/freeze.rb +36 -0
- data/lib/oakdex/battle/status_conditions/non_volatile.rb +12 -0
- data/lib/oakdex/battle/status_conditions/paralysis.rb +26 -0
- data/lib/oakdex/battle/status_conditions/poison.rb +22 -0
- data/lib/oakdex/battle/status_conditions/sleep.rb +37 -0
- data/lib/oakdex/battle/trainer.rb +50 -0
- data/lib/oakdex/battle/turn.rb +70 -0
- data/lib/oakdex/battle/valid_action_service.rb +89 -0
- data/lib/oakdex/battle/version.rb +5 -0
- metadata +82 -0
@@ -0,0 +1,109 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
# Calculates Pokemon Stats
|
4
|
+
class PokemonStat
|
5
|
+
STAGE_MULTIPLIERS = {
|
6
|
+
-6 => Rational(2, 8),
|
7
|
+
-5 => Rational(2, 7),
|
8
|
+
-4 => Rational(2, 6),
|
9
|
+
-3 => Rational(2, 5),
|
10
|
+
-2 => Rational(2, 4),
|
11
|
+
-1 => Rational(2, 3),
|
12
|
+
0 => Rational(2, 2),
|
13
|
+
1 => Rational(3, 2),
|
14
|
+
2 => Rational(4, 2),
|
15
|
+
3 => Rational(5, 2),
|
16
|
+
4 => Rational(6, 2),
|
17
|
+
5 => Rational(7, 2),
|
18
|
+
6 => Rational(8, 2)
|
19
|
+
}
|
20
|
+
|
21
|
+
STAGE_MULTIPLIERS_CRITICAL_HIT = {
|
22
|
+
0 => Rational(1, 24),
|
23
|
+
1 => Rational(1, 8),
|
24
|
+
2 => Rational(1, 2),
|
25
|
+
3 => Rational(1, 1)
|
26
|
+
}
|
27
|
+
|
28
|
+
STAGE_MULTIPLIERS_ACC_EVA = {
|
29
|
+
-6 => Rational(3, 9),
|
30
|
+
-5 => Rational(3, 8),
|
31
|
+
-4 => Rational(3, 7),
|
32
|
+
-3 => Rational(3, 6),
|
33
|
+
-2 => Rational(3, 5),
|
34
|
+
-1 => Rational(3, 4),
|
35
|
+
0 => Rational(3, 3),
|
36
|
+
1 => Rational(4, 3),
|
37
|
+
2 => Rational(5, 3),
|
38
|
+
3 => Rational(6, 3),
|
39
|
+
4 => Rational(7, 3),
|
40
|
+
5 => Rational(8, 3),
|
41
|
+
6 => Rational(9, 3)
|
42
|
+
}
|
43
|
+
|
44
|
+
class << self
|
45
|
+
def initial_stat(stat, options = {})
|
46
|
+
first_part = initial_stat_first_part(stat, options)
|
47
|
+
(
|
48
|
+
if stat == :hp
|
49
|
+
first_part + options[:level] + 10
|
50
|
+
elsif stat.to_s == options[:nature].increased_stat
|
51
|
+
(first_part + 5) * 1.1
|
52
|
+
elsif stat.to_s == options[:nature].decreased_stat
|
53
|
+
(first_part + 5) * 0.9
|
54
|
+
else
|
55
|
+
first_part + 5
|
56
|
+
end
|
57
|
+
).to_i
|
58
|
+
end
|
59
|
+
|
60
|
+
def exp_by_level(leveling_rate, level)
|
61
|
+
case leveling_rate
|
62
|
+
when 'Fast' then ((4.0 * level**3) / 5).to_i
|
63
|
+
when 'Slow' then ((5.0 * level**3) / 4).to_i
|
64
|
+
when 'Medium Slow' then medium_slow_exp(level)
|
65
|
+
when 'Fluctuating' then fluctuating_exp(level)
|
66
|
+
else level**3
|
67
|
+
end
|
68
|
+
end
|
69
|
+
|
70
|
+
def level_by_exp(leveling_rate, exp)
|
71
|
+
level = 2
|
72
|
+
level += 1 while exp_by_level(leveling_rate, level) <= exp
|
73
|
+
level - 1
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
|
78
|
+
def medium_slow_exp(level)
|
79
|
+
(
|
80
|
+
((6.0 / 5) * level**3) - 15 * level**2 + (100 * level) - 140
|
81
|
+
).to_i
|
82
|
+
end
|
83
|
+
|
84
|
+
def fluctuating_exp(level)
|
85
|
+
(
|
86
|
+
if level <= 15
|
87
|
+
level**3 * ((((level + 1) / 3.0) + 24) / 50)
|
88
|
+
elsif level <= 36
|
89
|
+
level**3 * ((level + 14) / 50.0)
|
90
|
+
else
|
91
|
+
level**3 * (((level / 2.0) + 32) / 50)
|
92
|
+
end
|
93
|
+
).to_i
|
94
|
+
end
|
95
|
+
|
96
|
+
def initial_stat_first_part(stat, options = {})
|
97
|
+
(
|
98
|
+
(
|
99
|
+
2.0 *
|
100
|
+
options[:base_stats][stat.to_s] +
|
101
|
+
options[:iv][stat] +
|
102
|
+
(options[:ev][stat] / 4)
|
103
|
+
) * options[:level]
|
104
|
+
) / 100
|
105
|
+
end
|
106
|
+
end
|
107
|
+
end
|
108
|
+
end
|
109
|
+
end
|
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Oakdex
|
4
|
+
class Battle
|
5
|
+
# Represents a side in an active battle, has n trainers
|
6
|
+
class Side
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@battle, :add_to_log
|
10
|
+
|
11
|
+
attr_reader :trainers, :battle
|
12
|
+
|
13
|
+
def initialize(battle, trainers)
|
14
|
+
@battle = battle
|
15
|
+
@trainers = trainers
|
16
|
+
end
|
17
|
+
|
18
|
+
def next_position
|
19
|
+
left_position.first
|
20
|
+
end
|
21
|
+
|
22
|
+
def send_to_battle
|
23
|
+
@trainers.map do |trainer|
|
24
|
+
pokemon_per_trainer.times do |i|
|
25
|
+
break unless trainer.team[i]
|
26
|
+
trainer.send_to_battle(trainer.team[i], self)
|
27
|
+
end
|
28
|
+
end
|
29
|
+
end
|
30
|
+
|
31
|
+
def remove_fainted
|
32
|
+
@trainers.each(&:remove_fainted)
|
33
|
+
end
|
34
|
+
|
35
|
+
def trainer_on_side?(trainer)
|
36
|
+
@trainers.include?(trainer)
|
37
|
+
end
|
38
|
+
|
39
|
+
def pokemon_in_battle?(position)
|
40
|
+
in_battle_pokemon.any? do |ibp|
|
41
|
+
ibp.position == position
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def pokemon_left?
|
46
|
+
!in_battle_pokemon.empty?
|
47
|
+
end
|
48
|
+
|
49
|
+
def in_battle_pokemon
|
50
|
+
@trainers.map(&:in_battle_pokemon).flatten(1)
|
51
|
+
end
|
52
|
+
|
53
|
+
def fainted?
|
54
|
+
@trainers.all?(&:fainted?)
|
55
|
+
end
|
56
|
+
|
57
|
+
private
|
58
|
+
|
59
|
+
def pokemon_per_trainer
|
60
|
+
(battle.pokemon_per_side / trainers.size)
|
61
|
+
end
|
62
|
+
|
63
|
+
def left_position
|
64
|
+
all_position - taken_positions
|
65
|
+
end
|
66
|
+
|
67
|
+
def taken_positions
|
68
|
+
in_battle_pokemon.map(&:position).sort
|
69
|
+
end
|
70
|
+
|
71
|
+
def all_position
|
72
|
+
battle.pokemon_per_side.times.to_a
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
@@ -0,0 +1,16 @@
|
|
1
|
+
require 'oakdex/battle/status_conditions/base'
|
2
|
+
require 'oakdex/battle/status_conditions/non_volatile'
|
3
|
+
require 'oakdex/battle/status_conditions/poison'
|
4
|
+
require 'oakdex/battle/status_conditions/burn'
|
5
|
+
require 'oakdex/battle/status_conditions/freeze'
|
6
|
+
require 'oakdex/battle/status_conditions/paralysis'
|
7
|
+
require 'oakdex/battle/status_conditions/badly_poisoned'
|
8
|
+
require 'oakdex/battle/status_conditions/sleep'
|
9
|
+
|
10
|
+
module Oakdex
|
11
|
+
class Battle
|
12
|
+
# Status conditions that belong to a pokemon
|
13
|
+
module StatusConditions
|
14
|
+
end
|
15
|
+
end
|
16
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents BadlyPoisoned status condition
|
5
|
+
class BadlyPoisoned < NonVolatile
|
6
|
+
def initialize(pokemon)
|
7
|
+
super
|
8
|
+
@turn_count = 0
|
9
|
+
end
|
10
|
+
|
11
|
+
def after_turn(turn)
|
12
|
+
return if pokemon.current_hp.zero?
|
13
|
+
turn.battle.add_to_log('damage_by_badly_poisoned',
|
14
|
+
pokemon.trainer.name,
|
15
|
+
pokemon.name, hp_by_turn)
|
16
|
+
pokemon.change_hp_by(hp_by_turn)
|
17
|
+
@turn_count += 1
|
18
|
+
end
|
19
|
+
|
20
|
+
def after_switched_out(_battle)
|
21
|
+
@turn_count = 0
|
22
|
+
end
|
23
|
+
|
24
|
+
private
|
25
|
+
|
26
|
+
def hp_by_turn
|
27
|
+
[-(pokemon.hp * percent).to_i, -1].min
|
28
|
+
end
|
29
|
+
|
30
|
+
def percent
|
31
|
+
([@turn_count.to_f, 15].min + 1) / 16.0
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents Abstract Class Base
|
5
|
+
class Base
|
6
|
+
attr_reader :pokemon
|
7
|
+
|
8
|
+
def initialize(pokemon)
|
9
|
+
@pokemon = pokemon
|
10
|
+
end
|
11
|
+
|
12
|
+
def before_turn(turn); end
|
13
|
+
|
14
|
+
def after_turn(turn); end
|
15
|
+
|
16
|
+
def after_fainted(battle); end
|
17
|
+
|
18
|
+
def after_switched_out(battle); end
|
19
|
+
|
20
|
+
def after_received_damage(move_execution); end
|
21
|
+
|
22
|
+
def stat_modifier(_stat)
|
23
|
+
1.0
|
24
|
+
end
|
25
|
+
|
26
|
+
def damage_modifier(_move_execution)
|
27
|
+
1.0
|
28
|
+
end
|
29
|
+
|
30
|
+
def prevents_move?(_move_execution)
|
31
|
+
false
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents Burn status condition
|
5
|
+
class Burn < NonVolatile
|
6
|
+
def after_turn(turn)
|
7
|
+
return if pokemon.current_hp.zero?
|
8
|
+
turn.battle.add_to_log('damage_by_burn',
|
9
|
+
pokemon.trainer.name,
|
10
|
+
pokemon.name, hp_by_turn)
|
11
|
+
pokemon.change_hp_by(hp_by_turn)
|
12
|
+
end
|
13
|
+
|
14
|
+
def damage_modifier(move_execution)
|
15
|
+
move_execution.move.category == 'physical' ? 0.5 : super
|
16
|
+
end
|
17
|
+
|
18
|
+
private
|
19
|
+
|
20
|
+
def hp_by_turn
|
21
|
+
[-(pokemon.hp / 16).to_i, -1].min
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,36 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents Freeze status condition
|
5
|
+
class Freeze < NonVolatile
|
6
|
+
def prevents_move?(move_execution)
|
7
|
+
move_execution
|
8
|
+
.battle
|
9
|
+
.add_to_log('frozen',
|
10
|
+
move_execution.pokemon.trainer.name,
|
11
|
+
move_execution.pokemon.name)
|
12
|
+
true
|
13
|
+
end
|
14
|
+
|
15
|
+
def after_received_damage(move_execution)
|
16
|
+
return unless move_execution.move.type == 'fire'
|
17
|
+
defrost(move_execution.battle)
|
18
|
+
end
|
19
|
+
|
20
|
+
def before_turn(turn)
|
21
|
+
return unless rand(1..100) <= 20
|
22
|
+
defrost(turn.battle)
|
23
|
+
end
|
24
|
+
|
25
|
+
private
|
26
|
+
|
27
|
+
def defrost(battle)
|
28
|
+
pokemon.remove_status_condition(self)
|
29
|
+
battle.add_to_log('defrosts',
|
30
|
+
pokemon.trainer.name,
|
31
|
+
pokemon.name)
|
32
|
+
end
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
@@ -0,0 +1,26 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents Paralysis status condition
|
5
|
+
class Paralysis < NonVolatile
|
6
|
+
def stat_modifier(stat)
|
7
|
+
return 0.5 if stat == :speed
|
8
|
+
super
|
9
|
+
end
|
10
|
+
|
11
|
+
def prevents_move?(move_execution)
|
12
|
+
if rand(1..100) <= 25
|
13
|
+
move_execution
|
14
|
+
.battle
|
15
|
+
.add_to_log('paralysed',
|
16
|
+
move_execution.pokemon.trainer.name,
|
17
|
+
move_execution.pokemon.name)
|
18
|
+
true
|
19
|
+
else
|
20
|
+
false
|
21
|
+
end
|
22
|
+
end
|
23
|
+
end
|
24
|
+
end
|
25
|
+
end
|
26
|
+
end
|
@@ -0,0 +1,22 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents Poison status condition
|
5
|
+
class Poison < NonVolatile
|
6
|
+
def after_turn(turn)
|
7
|
+
return if pokemon.current_hp.zero?
|
8
|
+
turn.battle.add_to_log('damage_by_poison',
|
9
|
+
pokemon.trainer.name,
|
10
|
+
pokemon.name, hp_by_turn)
|
11
|
+
pokemon.change_hp_by(hp_by_turn)
|
12
|
+
end
|
13
|
+
|
14
|
+
private
|
15
|
+
|
16
|
+
def hp_by_turn
|
17
|
+
[-(pokemon.hp / 8).to_i, -1].min
|
18
|
+
end
|
19
|
+
end
|
20
|
+
end
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,37 @@
|
|
1
|
+
module Oakdex
|
2
|
+
class Battle
|
3
|
+
module StatusConditions
|
4
|
+
# Represents Sleep status condition
|
5
|
+
class Sleep < NonVolatile
|
6
|
+
def initialize(pokemon)
|
7
|
+
super
|
8
|
+
@turn_count = 0
|
9
|
+
@max_turn_count = rand(1..3)
|
10
|
+
end
|
11
|
+
|
12
|
+
def after_turn(turn)
|
13
|
+
wake_up(turn.battle) if @turn_count >= @max_turn_count
|
14
|
+
@turn_count += 1
|
15
|
+
end
|
16
|
+
|
17
|
+
def prevents_move?(move_execution)
|
18
|
+
move_execution
|
19
|
+
.battle
|
20
|
+
.add_to_log('sleeping',
|
21
|
+
pokemon.trainer.name,
|
22
|
+
pokemon.name)
|
23
|
+
true
|
24
|
+
end
|
25
|
+
|
26
|
+
private
|
27
|
+
|
28
|
+
def wake_up(battle)
|
29
|
+
pokemon.remove_status_condition(self)
|
30
|
+
battle.add_to_log('wake_up',
|
31
|
+
pokemon.trainer.name,
|
32
|
+
pokemon.name)
|
33
|
+
end
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
37
|
+
end
|