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
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: ecd31f627a41112b511d36b3f229b4f39f16c50db2f30d2152d6d8be6c2a4084
|
4
|
+
data.tar.gz: c4d2ff60f0bc64a148b278f8dc9493a71191298672d0f365fa0a5ce2a3e8ab61
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: eae5231ca258390c2d3b3f2af6979b34f66c9615ed6e55c7c636d96267cdae3f76a8a86475f19a819aa0bdda1746f6b3efb8f84c0547cbb7290099efd6889ba4
|
7
|
+
data.tar.gz: 5a22eb518390c80e4eb7d5ab086ef744588a11de5260043050958a2930286dca62a88efe27f957bd6fccdc2c47c397325a11f5fa143fc5ff6d04399d4f11a2b5
|
data/README.md
ADDED
@@ -0,0 +1,103 @@
|
|
1
|
+
# <img src="https://v20.imgup.net/oakdex_logfbad.png" alt="fixer" width=282>
|
2
|
+
|
3
|
+
[![Build Status](https://travis-ci.org/jalyna/oakdex-battle.svg?branch=master)](https://travis-ci.org/jalyna/oakdex-battle) [![Maintainability](https://api.codeclimate.com/v1/badges/ef91681257a6900f03ac/maintainability)](https://codeclimate.com/github/jalyna/oakdex-battle/maintainability) [![Test Coverage](https://api.codeclimate.com/v1/badges/ef91681257a6900f03ac/test_coverage)](https://codeclimate.com/github/jalyna/oakdex-battle/test_coverage)
|
4
|
+
|
5
|
+
Based on [oakdex-pokedex](https://github.com/jalyna/oakdex-pokedex).
|
6
|
+
|
7
|
+
## Getting Started
|
8
|
+
|
9
|
+
### 1 vs. 1
|
10
|
+
|
11
|
+
```ruby
|
12
|
+
require 'oakdex/battle'
|
13
|
+
|
14
|
+
pok1 = Oakdex::Battle::Pokemon.create('Pikachu', level: 10)
|
15
|
+
pok2 = Oakdex::Battle::Pokemon.create('Bulbasaur', {
|
16
|
+
exp: 120,
|
17
|
+
gender: 'female',
|
18
|
+
ability: 'Soundproof',
|
19
|
+
nature: 'Bashful',
|
20
|
+
item: 'Earth Plate',
|
21
|
+
hp: 2,
|
22
|
+
iv: {
|
23
|
+
hp: 8,
|
24
|
+
atk: 12,
|
25
|
+
def: 31,
|
26
|
+
sp_atk: 12,
|
27
|
+
sp_def: 5,
|
28
|
+
speed: 14
|
29
|
+
},
|
30
|
+
ev: {
|
31
|
+
hp: 8,
|
32
|
+
atk: 12,
|
33
|
+
def: 99,
|
34
|
+
sp_atk: 4,
|
35
|
+
sp_def: 12,
|
36
|
+
speed: 14
|
37
|
+
},
|
38
|
+
moves: [
|
39
|
+
['Swords Dance', 12, 30],
|
40
|
+
['Cut', 40, 44]
|
41
|
+
]
|
42
|
+
})
|
43
|
+
|
44
|
+
trainer1 = Oakdex::Battle::Trainer.new('Ash', [pok1])
|
45
|
+
trainer2 = Oakdex::Battle::Trainer.new('Misty', [pok2])
|
46
|
+
|
47
|
+
battle = Oakdex::Battle.new(trainer1, trainer2)
|
48
|
+
battle.continue # => true
|
49
|
+
battle.log.size # => 1
|
50
|
+
battle.log.last # => [['sends_to_battle', 'Ash', 'Pikachu'], ['sends_to_battle', 'Misty', 'Bulbasaur']]
|
51
|
+
battle.arena # => Snapshot of current state as Hash
|
52
|
+
battle.finished? # => false
|
53
|
+
battle.valid_actions_for(trainer1) # => [{ action: 'move', pokemon: pok1, move: <Move>, target: pok2 }, ...]
|
54
|
+
|
55
|
+
battle.add_action(trainer1, { action: 'move', pokemon: pok1, move: <Move>, target: pok2 }) # => false
|
56
|
+
|
57
|
+
battle.add_action(trainer1, { action: 'move', pokemon: pok1, move: <Move>, target: pok2 }) # => true
|
58
|
+
|
59
|
+
battle.valid_actions_for(trainer1) # => []
|
60
|
+
battle.continue # => false
|
61
|
+
battle.simulate_action(trainer2) # => true
|
62
|
+
battle.valid_actions_for(trainer2) # => []
|
63
|
+
battle.continue # => true
|
64
|
+
|
65
|
+
battle.log.size # => 2
|
66
|
+
battle.log.last # => [['uses_move', 'Ash', 'Pikachu', 'Thunder Shock'], ['received_damage', 'Misty', 'Bulbasaur', 'Thunder Shock'], ['uses_move', 'Misty', 'Bulbasaur', 'Leech Seed'], ['move_failed', 'Misty', 'Bulbasaur', 'Leech Seed']]
|
67
|
+
|
68
|
+
# ...
|
69
|
+
|
70
|
+
battle.finished? # => true
|
71
|
+
battle.winner # => trainer1
|
72
|
+
```
|
73
|
+
|
74
|
+
|
75
|
+
### Other Battle types
|
76
|
+
|
77
|
+
```ruby
|
78
|
+
pok3 = Oakdex::Battle::Pokemon.create('Altaria', level: 20)
|
79
|
+
pok4 = Oakdex::Battle::Pokemon.create('Elekid', level: 14)
|
80
|
+
trainer1 = Oakdex::Battle::Trainer.new('Ash', [pok1, pok3, pok9])
|
81
|
+
trainer2 = Oakdex::Battle::Trainer.new('Misty', [pok2, pok4, pok10])
|
82
|
+
trainer3 = Oakdex::Battle::Trainer.new('Brock', [pok5, pok6])
|
83
|
+
trainer4 = Oakdex::Battle::Trainer.new('Erika', [pok7, pok8])
|
84
|
+
|
85
|
+
# 2 vs. 2
|
86
|
+
battle = Oakdex::Battle.new([trainer1], [trainer2], pokemon_per_side: 2)
|
87
|
+
# 3 vs. 3
|
88
|
+
battle = Oakdex::Battle.new([trainer1], [trainer2], pokemon_per_side: 3)
|
89
|
+
# 2 vs. 2 (1 pokemon each trainer)
|
90
|
+
battle = Oakdex::Battle.new([trainer1, trainer3], [trainer2, trainer4])
|
91
|
+
```
|
92
|
+
|
93
|
+
## Contributing
|
94
|
+
|
95
|
+
I would be happy if you want to add your contribution to the project. In order to contribute, you just have to fork this repository.
|
96
|
+
|
97
|
+
## License
|
98
|
+
|
99
|
+
MIT License. See the included MIT-LICENSE file.
|
100
|
+
|
101
|
+
## Credits
|
102
|
+
|
103
|
+
Logo Icon by [Roundicons Freebies](http://www.flaticon.com/authors/roundicons-freebies).
|
data/lib/oakdex.rb
ADDED
@@ -0,0 +1,111 @@
|
|
1
|
+
require 'oakdex/pokedex'
|
2
|
+
|
3
|
+
require 'oakdex/battle/pokemon'
|
4
|
+
require 'oakdex/battle/trainer'
|
5
|
+
require 'oakdex/battle/move_execution'
|
6
|
+
require 'oakdex/battle/action'
|
7
|
+
require 'oakdex/battle/damage'
|
8
|
+
require 'oakdex/battle/turn'
|
9
|
+
require 'oakdex/battle/valid_action_service'
|
10
|
+
require 'oakdex/battle/side'
|
11
|
+
require 'oakdex/battle/in_battle_pokemon'
|
12
|
+
|
13
|
+
module Oakdex
|
14
|
+
# Represents battle, with has n turns and m sides
|
15
|
+
class Battle
|
16
|
+
attr_reader :log, :actions, :team1, :team2,
|
17
|
+
:sides, :current_log
|
18
|
+
|
19
|
+
def initialize(team1, team2, options = {})
|
20
|
+
@team1 = team1.is_a?(Array) ? team1 : [team1]
|
21
|
+
@team2 = team2.is_a?(Array) ? team2 : [team2]
|
22
|
+
@options = options
|
23
|
+
@sides = []
|
24
|
+
@log = []
|
25
|
+
@current_log = []
|
26
|
+
@actions = []
|
27
|
+
@turns = []
|
28
|
+
end
|
29
|
+
|
30
|
+
def pokemon_per_side
|
31
|
+
@options[:pokemon_per_side] || @team1.size
|
32
|
+
end
|
33
|
+
|
34
|
+
def arena
|
35
|
+
{ sides: sides }
|
36
|
+
end
|
37
|
+
|
38
|
+
def valid_actions_for(trainer)
|
39
|
+
valid_action_service.valid_actions_for(trainer)
|
40
|
+
end
|
41
|
+
|
42
|
+
def add_action(trainer, action)
|
43
|
+
return false unless valid_actions_for(trainer).include?(action)
|
44
|
+
@actions << Action.new(trainer, action)
|
45
|
+
true
|
46
|
+
end
|
47
|
+
|
48
|
+
def simulate_action(trainer)
|
49
|
+
valid_actions = valid_actions_for(trainer)
|
50
|
+
return false if valid_actions.empty?
|
51
|
+
add_action(trainer, valid_actions.sample)
|
52
|
+
end
|
53
|
+
|
54
|
+
def continue
|
55
|
+
return start if sides.empty?
|
56
|
+
return false unless trainers.all? { |t| valid_actions_for(t).empty? }
|
57
|
+
execute_actions
|
58
|
+
true
|
59
|
+
end
|
60
|
+
|
61
|
+
def finished?
|
62
|
+
!fainted_sides.empty?
|
63
|
+
end
|
64
|
+
|
65
|
+
def winner
|
66
|
+
return if fainted_sides.empty?
|
67
|
+
(sides - fainted_sides).flat_map(&:trainers)
|
68
|
+
end
|
69
|
+
|
70
|
+
def add_to_log(*args)
|
71
|
+
@current_log << args.to_a
|
72
|
+
end
|
73
|
+
|
74
|
+
def remove_fainted
|
75
|
+
sides.each(&:remove_fainted)
|
76
|
+
end
|
77
|
+
|
78
|
+
private
|
79
|
+
|
80
|
+
def valid_action_service
|
81
|
+
@valid_action_service ||= ValidActionService.new(self)
|
82
|
+
end
|
83
|
+
|
84
|
+
def fainted_sides
|
85
|
+
sides.select(&:fainted?)
|
86
|
+
end
|
87
|
+
|
88
|
+
def start
|
89
|
+
@sides = [@team1, @team2].map do |team|
|
90
|
+
Side.new(self, team).tap(&:send_to_battle)
|
91
|
+
end
|
92
|
+
finish_turn
|
93
|
+
true
|
94
|
+
end
|
95
|
+
|
96
|
+
def execute_actions
|
97
|
+
@turns << Turn.new(self, @actions).tap(&:execute)
|
98
|
+
finish_turn
|
99
|
+
end
|
100
|
+
|
101
|
+
def trainers
|
102
|
+
sides.flat_map(&:trainers)
|
103
|
+
end
|
104
|
+
|
105
|
+
def finish_turn
|
106
|
+
@log << @current_log
|
107
|
+
@current_log = []
|
108
|
+
@actions = []
|
109
|
+
end
|
110
|
+
end
|
111
|
+
end
|
@@ -0,0 +1,115 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Oakdex
|
4
|
+
class Battle
|
5
|
+
# Represents one Action. One turn has many actions.
|
6
|
+
class Action
|
7
|
+
RECALL_PRIORITY = 6
|
8
|
+
|
9
|
+
extend Forwardable
|
10
|
+
|
11
|
+
def_delegators :@turn, :battle
|
12
|
+
|
13
|
+
attr_reader :trainer, :damage, :turn
|
14
|
+
|
15
|
+
def initialize(trainer, attributes)
|
16
|
+
@trainer = trainer
|
17
|
+
@attributes = attributes
|
18
|
+
end
|
19
|
+
|
20
|
+
def priority
|
21
|
+
move&.priority || RECALL_PRIORITY
|
22
|
+
end
|
23
|
+
|
24
|
+
def pokemon
|
25
|
+
recall? ? pokemon_by_position : @attributes[:pokemon]
|
26
|
+
end
|
27
|
+
|
28
|
+
def pokemon_position
|
29
|
+
recall? ? @attributes[:pokemon] : nil
|
30
|
+
end
|
31
|
+
|
32
|
+
def target
|
33
|
+
recall? ? @attributes[:target] : targets
|
34
|
+
end
|
35
|
+
|
36
|
+
def type
|
37
|
+
@attributes[:action]
|
38
|
+
end
|
39
|
+
|
40
|
+
def move
|
41
|
+
@attributes[:move]
|
42
|
+
end
|
43
|
+
|
44
|
+
def hitting_probability
|
45
|
+
((move.accuracy / 100.0) * (pokemon.accuracy / target.evasion)) * 1000
|
46
|
+
end
|
47
|
+
|
48
|
+
def hitting?
|
49
|
+
@hitting = rand(1..1000) <= hitting_probability ? 1 : 0
|
50
|
+
@hitting == 1
|
51
|
+
end
|
52
|
+
|
53
|
+
def execute(turn)
|
54
|
+
@turn = turn
|
55
|
+
return execute_recall if type == 'recall'
|
56
|
+
targets.each { |t| MoveExecution.new(self, t).execute }
|
57
|
+
end
|
58
|
+
|
59
|
+
private
|
60
|
+
|
61
|
+
def targets
|
62
|
+
target_list.map do |target|
|
63
|
+
target_by_position(target[0], target[1])
|
64
|
+
end.compact
|
65
|
+
end
|
66
|
+
|
67
|
+
def target_list
|
68
|
+
list = @attributes[:target]
|
69
|
+
reutrn [] if list.empty?
|
70
|
+
list = [list] unless list[0].is_a?(Array)
|
71
|
+
list
|
72
|
+
end
|
73
|
+
|
74
|
+
def recall?
|
75
|
+
type == 'recall'
|
76
|
+
end
|
77
|
+
|
78
|
+
def pokemon_by_position
|
79
|
+
trainer.in_battle_pokemon
|
80
|
+
.find { |ibp| ibp.position == @attributes[:pokemon] }&.pokemon
|
81
|
+
end
|
82
|
+
|
83
|
+
def target_by_position(side, position)
|
84
|
+
side.in_battle_pokemon
|
85
|
+
.find { |ibp| ibp.position == position }&.pokemon
|
86
|
+
end
|
87
|
+
|
88
|
+
def side
|
89
|
+
battle.sides.find { |s| s.trainer_on_side?(trainer) }
|
90
|
+
end
|
91
|
+
|
92
|
+
def execute_recall
|
93
|
+
add_recalls_log
|
94
|
+
if pokemon
|
95
|
+
trainer.remove_from_battle(pokemon, side)
|
96
|
+
trainer.send_to_battle(target, side)
|
97
|
+
else
|
98
|
+
trainer.send_to_battle(target, side)
|
99
|
+
end
|
100
|
+
end
|
101
|
+
|
102
|
+
def add_log(*args)
|
103
|
+
battle.add_to_log(*args)
|
104
|
+
end
|
105
|
+
|
106
|
+
def add_recalls_log
|
107
|
+
if pokemon
|
108
|
+
add_log 'recalls', trainer.name, pokemon.name, target.name
|
109
|
+
else
|
110
|
+
add_log 'recalls_for_fainted', trainer.name, target.name
|
111
|
+
end
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
115
|
+
end
|
@@ -0,0 +1,99 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Oakdex
|
4
|
+
class Battle
|
5
|
+
# Calculates damage
|
6
|
+
class Damage
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@action, :move, :pokemon, :target
|
10
|
+
|
11
|
+
def initialize(turn, action)
|
12
|
+
@turn = turn
|
13
|
+
@action = action
|
14
|
+
end
|
15
|
+
|
16
|
+
def damage
|
17
|
+
(simple_damage * modifier).to_i
|
18
|
+
end
|
19
|
+
|
20
|
+
def critical?
|
21
|
+
@critical ||= rand(1..1000) <= pokemon.critical_hit_prob * 1000 ? 1 : 0
|
22
|
+
@critical == 1
|
23
|
+
end
|
24
|
+
|
25
|
+
def effective?
|
26
|
+
type_modifier > 1.0
|
27
|
+
end
|
28
|
+
|
29
|
+
def ineffective?
|
30
|
+
type_modifier < 1.0
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
|
35
|
+
def modifier
|
36
|
+
target_modifier * weather_modifier * critical_hit_modifier *
|
37
|
+
random_modifier * stab_modifier * type_modifier *
|
38
|
+
burn_modifier * status_condition_modifier * other_modifiers
|
39
|
+
end
|
40
|
+
|
41
|
+
def status_condition_modifier
|
42
|
+
pokemon.status_conditions.reduce(1.0) do |modifier, condition|
|
43
|
+
modifier * condition.damage_modifier(@action)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
def target_modifier
|
48
|
+
1.0 # TODO: 0.75 if move has more than one target
|
49
|
+
end
|
50
|
+
|
51
|
+
def weather_modifier
|
52
|
+
1.0 # TODO: 1.5 water at rain or fire at harsh sunlight, 0.5 vice versa
|
53
|
+
end
|
54
|
+
|
55
|
+
def critical_hit_modifier
|
56
|
+
if critical?
|
57
|
+
1.5
|
58
|
+
else
|
59
|
+
1.0
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
def random_modifier
|
64
|
+
@random_modifier ||= rand(850..1000) / 1000.0
|
65
|
+
end
|
66
|
+
|
67
|
+
def stab_modifier
|
68
|
+
pokemon.types.include?(move.type) ? 1.5 : 1.0
|
69
|
+
end
|
70
|
+
|
71
|
+
def type_modifier
|
72
|
+
type_data = Oakdex::Pokedex::Type.find!(move.type)
|
73
|
+
target.types.reduce(1.0) do |factor, type|
|
74
|
+
factor * type_data.effectivness[type]
|
75
|
+
end
|
76
|
+
end
|
77
|
+
|
78
|
+
def burn_modifier
|
79
|
+
1.0 # TODO: 0.5 if attack is burning and physical move
|
80
|
+
end
|
81
|
+
|
82
|
+
def other_modifiers
|
83
|
+
1.0 # TODO: See other https://bulbapedia.bulbagarden.net/wiki/Damage
|
84
|
+
end
|
85
|
+
|
86
|
+
def def_and_atk
|
87
|
+
if move.category == 'special'
|
88
|
+
(pokemon.sp_atk.to_f / target.sp_def.to_f)
|
89
|
+
else
|
90
|
+
(pokemon.atk.to_f / target.def.to_f)
|
91
|
+
end
|
92
|
+
end
|
93
|
+
|
94
|
+
def simple_damage
|
95
|
+
(((2 * pokemon.level) / 5.0 + 2) * move.power * def_and_atk) / 50 + 2
|
96
|
+
end
|
97
|
+
end
|
98
|
+
end
|
99
|
+
end
|
@@ -0,0 +1,159 @@
|
|
1
|
+
require 'forwardable'
|
2
|
+
|
3
|
+
module Oakdex
|
4
|
+
class Battle
|
5
|
+
# Represents a pokemon that is in battle
|
6
|
+
class InBattlePokemon
|
7
|
+
extend Forwardable
|
8
|
+
|
9
|
+
def_delegators :@pokemon, :current_hp, :moves_with_pp
|
10
|
+
def_delegators :@side, :battle
|
11
|
+
|
12
|
+
attr_reader :pokemon, :position, :side
|
13
|
+
|
14
|
+
def initialize(pokemon, side, position = 0)
|
15
|
+
@pokemon = pokemon
|
16
|
+
@side = side
|
17
|
+
@position = position
|
18
|
+
end
|
19
|
+
|
20
|
+
def fainted?
|
21
|
+
current_hp.zero?
|
22
|
+
end
|
23
|
+
|
24
|
+
def action_added?
|
25
|
+
actions.any? { |a| a.pokemon == pokemon }
|
26
|
+
end
|
27
|
+
|
28
|
+
def valid_move_actions
|
29
|
+
return [] if action_added?
|
30
|
+
moves = moves_with_pp
|
31
|
+
moves = [struggle_move] if moves_with_pp.empty?
|
32
|
+
moves.flat_map do |move|
|
33
|
+
targets_in_battle(move).map do |target|
|
34
|
+
{
|
35
|
+
action: 'move',
|
36
|
+
pokemon: pokemon,
|
37
|
+
move: move,
|
38
|
+
target: target
|
39
|
+
}
|
40
|
+
end
|
41
|
+
end
|
42
|
+
end
|
43
|
+
|
44
|
+
private
|
45
|
+
|
46
|
+
def targets_in_battle(move)
|
47
|
+
available_targets(move).map do |targets|
|
48
|
+
if targets.last.is_a?(Array)
|
49
|
+
targets if targets_in_battle?(targets)
|
50
|
+
elsif target_in_battle?(targets)
|
51
|
+
targets
|
52
|
+
end
|
53
|
+
end.compact.reject(&:empty?)
|
54
|
+
end
|
55
|
+
|
56
|
+
def targets_in_battle?(targets)
|
57
|
+
targets.any? { |target| target[0].pokemon_in_battle?(target[1]) }
|
58
|
+
end
|
59
|
+
|
60
|
+
def target_in_battle?(target)
|
61
|
+
target[0].pokemon_in_battle?(target[1]) ||
|
62
|
+
(!target[0].pokemon_left? && target[1] == 0)
|
63
|
+
end
|
64
|
+
|
65
|
+
def struggle_move
|
66
|
+
@struggle_move ||= begin
|
67
|
+
move_type = Oakdex::Pokedex::Move.find('Struggle')
|
68
|
+
Oakdex::Battle::Move.new(move_type, move_type.pp, move_type.pp)
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
72
|
+
def available_targets(move)
|
73
|
+
with_target(move) || multiple_targets_adjacent(move) ||
|
74
|
+
multiple_targets(move) || []
|
75
|
+
end
|
76
|
+
|
77
|
+
def multiple_targets(move)
|
78
|
+
case move.target
|
79
|
+
when 'all_users' then [all_users]
|
80
|
+
when 'all_except_user' then [all_targets - [self_target]]
|
81
|
+
when 'all' then [all_targets]
|
82
|
+
when 'all_foes' then [all_foes]
|
83
|
+
end
|
84
|
+
end
|
85
|
+
|
86
|
+
def multiple_targets_adjacent(move)
|
87
|
+
case move.target
|
88
|
+
when 'all_adjacent' then [adjacent]
|
89
|
+
when 'adjacent_foes_all' then [adjacent_foes]
|
90
|
+
end
|
91
|
+
end
|
92
|
+
|
93
|
+
def with_target(move)
|
94
|
+
case move.target
|
95
|
+
when 'user', 'user_and_random_adjacent_foe' then [self_target]
|
96
|
+
when 'target_adjacent_user_single' then adjacent_users
|
97
|
+
when 'target_adjacent_single' then adjacent
|
98
|
+
when 'target_user_or_adjacent_user'
|
99
|
+
[self_target] + adjacent_users
|
100
|
+
end
|
101
|
+
end
|
102
|
+
|
103
|
+
def all_targets
|
104
|
+
all_foes + all_users
|
105
|
+
end
|
106
|
+
|
107
|
+
def target_adjacent_single
|
108
|
+
adjacent_foes + adjacent_users
|
109
|
+
end
|
110
|
+
|
111
|
+
def adjacent
|
112
|
+
adjacent_foes + adjacent_users
|
113
|
+
end
|
114
|
+
|
115
|
+
def self_target
|
116
|
+
[@side, position]
|
117
|
+
end
|
118
|
+
|
119
|
+
def adjacent_foes
|
120
|
+
[
|
121
|
+
[other_side, position - 1],
|
122
|
+
[other_side, position],
|
123
|
+
[other_side, position + 1]
|
124
|
+
].select { |t| t[1] >= 0 && t[1] < pokemon_per_side }
|
125
|
+
end
|
126
|
+
|
127
|
+
def adjacent_users
|
128
|
+
[
|
129
|
+
[@side, position - 1],
|
130
|
+
[@side, position + 1]
|
131
|
+
].select { |t| t[1] >= 0 && t[1] < pokemon_per_side }
|
132
|
+
end
|
133
|
+
|
134
|
+
def all_users
|
135
|
+
pokemon_per_side.times.map { |i| [@side, i] }
|
136
|
+
end
|
137
|
+
|
138
|
+
def all_foes
|
139
|
+
pokemon_per_side.times.map { |i| [other_side, i] }
|
140
|
+
end
|
141
|
+
|
142
|
+
def pokemon_per_side
|
143
|
+
battle.pokemon_per_side
|
144
|
+
end
|
145
|
+
|
146
|
+
def other_side
|
147
|
+
other_sides.first
|
148
|
+
end
|
149
|
+
|
150
|
+
def other_sides
|
151
|
+
battle.sides - [@side]
|
152
|
+
end
|
153
|
+
|
154
|
+
def actions
|
155
|
+
battle.actions
|
156
|
+
end
|
157
|
+
end
|
158
|
+
end
|
159
|
+
end
|