oakdex-battle 0.1.0 → 0.1.1
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +5 -5
- data/README.md +4 -4
- data/lib/oakdex/battle/action.rb +55 -4
- data/lib/oakdex/battle/in_battle_pokemon.rb +4 -2
- data/lib/oakdex/battle/side.rb +1 -0
- data/lib/oakdex/battle/trainer.rb +91 -2
- data/lib/oakdex/battle/valid_action_service.rb +85 -4
- data/lib/oakdex/battle/version.rb +1 -1
- metadata +19 -6
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: fb6705359f3c133ea6fe2ed3402b0afa848b008c3d546cc2f5ccb641c3967415
|
4
|
+
data.tar.gz: 94556920e80e6b1d273ded0be30fcc0058ebbf2ccd0d663049ba06b941e96c15
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: c456d5bdccf1f8fca681f8438137c4814c1ee4aa0a023c80feab4178e458110a2df0a84895db08d5e44ed11177f4b65afb556776385f9b8c40ea114f6b628883
|
7
|
+
data.tar.gz: 6240ad289a2b5d6ac010d620bcf10535610118f94dbe7af8aed8d89134780043c7291f9dc976c31fd4d08fbb736cdfbc5479bc2b7917381c72b8dd47fecf4251
|
data/README.md
CHANGED
@@ -41,8 +41,8 @@ pok2 = Oakdex::Pokemon.create('Bulbasaur', {
|
|
41
41
|
]
|
42
42
|
})
|
43
43
|
|
44
|
-
trainer1 = Oakdex::Battle::Trainer.new('Ash', [pok1])
|
45
|
-
trainer2 = Oakdex::Battle::Trainer.new('Misty', [pok2])
|
44
|
+
trainer1 = Oakdex::Battle::Trainer.new('Ash', [pok1], ['Potion', 'Elixir', 'Ether'], enable_grow: true, using_exp_share: true) # trainer's pokemon receive exp and ev
|
45
|
+
trainer2 = Oakdex::Battle::Trainer.new('Misty', [pok2], ['Potion', 'Potion', 'Revive', 'Soda Pop'])
|
46
46
|
|
47
47
|
battle = Oakdex::Battle.new(trainer1, trainer2)
|
48
48
|
battle.continue # => true
|
@@ -52,10 +52,10 @@ battle.arena # => Snapshot of current state as Hash
|
|
52
52
|
battle.finished? # => false
|
53
53
|
battle.valid_actions_for(trainer1) # => [{ action: 'move', pokemon: pok1, move: <Move>, target: pok2 }, ...]
|
54
54
|
|
55
|
-
battle.add_action(trainer1, { action: 'move', pokemon: pok1, move: <Move>, target: pok2 }) # => false
|
56
|
-
|
57
55
|
battle.add_action(trainer1, { action: 'move', pokemon: pok1, move: <Move>, target: pok2 }) # => true
|
58
56
|
|
57
|
+
battle.add_action(trainer1, { action: 'move', pokemon: pok1, move: <Move>, target: pok2 }) # => false
|
58
|
+
|
59
59
|
battle.valid_actions_for(trainer1) # => []
|
60
60
|
battle.continue # => false
|
61
61
|
battle.simulate_action(trainer2) # => true
|
data/lib/oakdex/battle/action.rb
CHANGED
@@ -4,7 +4,8 @@ module Oakdex
|
|
4
4
|
class Battle
|
5
5
|
# Represents one Action. One turn has many actions.
|
6
6
|
class Action
|
7
|
-
RECALL_PRIORITY =
|
7
|
+
RECALL_PRIORITY = 7
|
8
|
+
ITEM_PRIORITY = 6
|
8
9
|
|
9
10
|
extend Forwardable
|
10
11
|
|
@@ -18,10 +19,11 @@ module Oakdex
|
|
18
19
|
end
|
19
20
|
|
20
21
|
def priority
|
21
|
-
move&.priority || RECALL_PRIORITY
|
22
|
+
move&.priority || (recall? ? RECALL_PRIORITY : ITEM_PRIORITY)
|
22
23
|
end
|
23
24
|
|
24
25
|
def pokemon
|
26
|
+
return pokemon_by_team_position if item?
|
25
27
|
recall? ? pokemon_by_position : @attributes[:pokemon]
|
26
28
|
end
|
27
29
|
|
@@ -52,10 +54,16 @@ module Oakdex
|
|
52
54
|
|
53
55
|
def execute(turn)
|
54
56
|
@turn = turn
|
55
|
-
return
|
57
|
+
return execute_growth if growth?
|
58
|
+
return execute_recall if recall?
|
59
|
+
return execute_use_item if item?
|
56
60
|
targets.each { |t| MoveExecution.new(self, t).execute }
|
57
61
|
end
|
58
62
|
|
63
|
+
def item_id
|
64
|
+
@attributes[:item_id]
|
65
|
+
end
|
66
|
+
|
59
67
|
private
|
60
68
|
|
61
69
|
def targets
|
@@ -66,7 +74,7 @@ module Oakdex
|
|
66
74
|
|
67
75
|
def target_list
|
68
76
|
list = @attributes[:target]
|
69
|
-
|
77
|
+
return [] if (list || []).empty?
|
70
78
|
list = [list] unless list[0].is_a?(Array)
|
71
79
|
list
|
72
80
|
end
|
@@ -75,11 +83,23 @@ module Oakdex
|
|
75
83
|
type == 'recall'
|
76
84
|
end
|
77
85
|
|
86
|
+
def item?
|
87
|
+
type == 'use_item_on_pokemon'
|
88
|
+
end
|
89
|
+
|
90
|
+
def growth?
|
91
|
+
type == 'growth_event'
|
92
|
+
end
|
93
|
+
|
78
94
|
def pokemon_by_position
|
79
95
|
trainer.active_in_battle_pokemon
|
80
96
|
.find { |ibp| ibp.position == @attributes[:pokemon] }&.pokemon
|
81
97
|
end
|
82
98
|
|
99
|
+
def pokemon_by_team_position
|
100
|
+
trainer.team[@attributes[:pokemon_team_pos]]
|
101
|
+
end
|
102
|
+
|
83
103
|
def target_by_position(side, position)
|
84
104
|
side.active_in_battle_pokemon
|
85
105
|
.find { |ibp| ibp.position == position }&.pokemon
|
@@ -99,6 +119,37 @@ module Oakdex
|
|
99
119
|
end
|
100
120
|
end
|
101
121
|
|
122
|
+
def item_actions
|
123
|
+
@attributes[:item_actions]
|
124
|
+
end
|
125
|
+
|
126
|
+
def execute_growth
|
127
|
+
trainer.growth_event.execute(@attributes[:option])
|
128
|
+
while trainer.growth_event? && trainer.growth_event.read_only?
|
129
|
+
e = trainer.growth_event
|
130
|
+
add_log e.message
|
131
|
+
e.execute
|
132
|
+
end
|
133
|
+
end
|
134
|
+
|
135
|
+
def execute_use_item
|
136
|
+
add_log 'uses_item_on_pokemon', trainer.name, pokemon.name, item_id
|
137
|
+
consumed = pokemon.use_item(item_id, in_battle: true)
|
138
|
+
trainer.consume_item(item_id) if consumed
|
139
|
+
action_id = 0
|
140
|
+
while pokemon.growth_event? do
|
141
|
+
event = pokemon.growth_event
|
142
|
+
if event.read_only?
|
143
|
+
add_log trainer.name, pokemon.name, event.message
|
144
|
+
event.execute
|
145
|
+
else
|
146
|
+
raise 'Invalid Item Usage' unless item_actions[action_id]
|
147
|
+
event.execute(item_actions[action_id])
|
148
|
+
action_id += 1
|
149
|
+
end
|
150
|
+
end
|
151
|
+
end
|
152
|
+
|
102
153
|
def add_log(*args)
|
103
154
|
battle.add_to_log(*args)
|
104
155
|
end
|
@@ -59,9 +59,10 @@ module Oakdex
|
|
59
59
|
|
60
60
|
def_delegators :@pokemon, :types, :trainer, :trainer=,
|
61
61
|
:name, :moves, :moves_with_pp, :change_hp_by,
|
62
|
-
:change_pp_by, :level, :fainted
|
62
|
+
:change_pp_by, :level, :fainted?, :usable_item?,
|
63
|
+
:use_item, :growth_event?, :growth_event, :grow_from_battle
|
63
64
|
|
64
|
-
attr_reader :status_conditions
|
65
|
+
attr_reader :status_conditions, :pokemon
|
65
66
|
|
66
67
|
def initialize(pokemon, options = {})
|
67
68
|
@pokemon = pokemon
|
@@ -69,6 +70,7 @@ module Oakdex
|
|
69
70
|
if @pokemon.primary_status_condition
|
70
71
|
add_status_condition(@pokemon.primary_status_condition)
|
71
72
|
end
|
73
|
+
@pokemon.enable_battle_mode
|
72
74
|
reset_stats
|
73
75
|
end
|
74
76
|
|
data/lib/oakdex/battle/side.rb
CHANGED
@@ -2,19 +2,42 @@ module Oakdex
|
|
2
2
|
class Battle
|
3
3
|
# Represents a Pokemon Trainer. Owns Pokemon and has a name
|
4
4
|
class Trainer
|
5
|
-
attr_reader :name, :team, :active_in_battle_pokemon
|
5
|
+
attr_reader :name, :team, :active_in_battle_pokemon, :items
|
6
|
+
attr_accessor :side
|
6
7
|
|
7
|
-
def initialize(name, pokemon)
|
8
|
+
def initialize(name, pokemon, items = [], options = {})
|
8
9
|
@name = name
|
9
10
|
pokemon.each { |p| p.trainer = self }
|
10
11
|
@team = pokemon.map { |p| Oakdex::Battle::InBattlePokemon.new(p) }
|
11
12
|
@active_in_battle_pokemon = []
|
13
|
+
@items = items
|
14
|
+
@options = options
|
12
15
|
end
|
13
16
|
|
14
17
|
def fainted?
|
15
18
|
@team.all?(&:fainted?)
|
16
19
|
end
|
17
20
|
|
21
|
+
def growth_event?
|
22
|
+
!growth_events.empty?
|
23
|
+
end
|
24
|
+
|
25
|
+
def growth_event
|
26
|
+
growth_events.first
|
27
|
+
end
|
28
|
+
|
29
|
+
def remove_growth_event
|
30
|
+
remove_growth_event = growth_event
|
31
|
+
return unless remove_growth_event
|
32
|
+
pokemon = team.find { |p| p.growth_event == remove_growth_event }
|
33
|
+
pokemon.remove_growth_event
|
34
|
+
end
|
35
|
+
|
36
|
+
def consume_item(item_id)
|
37
|
+
first_index = @items.index(item_id)
|
38
|
+
@items.delete_at(first_index)
|
39
|
+
end
|
40
|
+
|
18
41
|
def send_to_battle(pokemon, side)
|
19
42
|
@active_in_battle_pokemon << ActiveInBattlePokemon.new(
|
20
43
|
pokemon,
|
@@ -39,6 +62,7 @@ module Oakdex
|
|
39
62
|
ibp.battle.add_to_log('pokemon_fainted', name, ibp.pokemon.name)
|
40
63
|
ibp.pokemon.status_conditions
|
41
64
|
.each { |s| s.after_fainted(ibp.battle) }
|
65
|
+
other_side_gains(ibp)
|
42
66
|
end
|
43
67
|
@active_in_battle_pokemon = @active_in_battle_pokemon.reject(&:fainted?)
|
44
68
|
end
|
@@ -47,6 +71,71 @@ module Oakdex
|
|
47
71
|
@team.select { |p| !p.fainted? } -
|
48
72
|
@active_in_battle_pokemon.map(&:pokemon)
|
49
73
|
end
|
74
|
+
|
75
|
+
def grow(defeated_pokemon)
|
76
|
+
return unless @options[:enable_grow]
|
77
|
+
active_in_battle_pokemon.each do |ibp|
|
78
|
+
next if ibp.fainted?
|
79
|
+
execute_grow_for_pokemon(ibp.pokemon, defeated_pokemon)
|
80
|
+
end
|
81
|
+
grow_team_pokemon(defeated_pokemon)
|
82
|
+
end
|
83
|
+
|
84
|
+
private
|
85
|
+
|
86
|
+
def battle
|
87
|
+
side.battle
|
88
|
+
end
|
89
|
+
|
90
|
+
def grow_team_pokemon(defeated_pokemon)
|
91
|
+
return unless @options[:using_exp_share]
|
92
|
+
exclude_pokemon = active_in_battle_pokemon.map(&:pokemon)
|
93
|
+
|
94
|
+
(team - exclude_pokemon).each do |pok|
|
95
|
+
next if pok.fainted?
|
96
|
+
execute_grow_for_pokemon(pok, defeated_pokemon)
|
97
|
+
end
|
98
|
+
end
|
99
|
+
|
100
|
+
def execute_grow_for_pokemon(bp, defeated_pokemon)
|
101
|
+
bp.grow_from_battle(defeated_pokemon.pokemon.pokemon)
|
102
|
+
execute_read_only_events(bp)
|
103
|
+
return unless bp.growth_event?
|
104
|
+
add_choice_to_log(bp)
|
105
|
+
end
|
106
|
+
|
107
|
+
def execute_read_only_events(bp)
|
108
|
+
while bp.growth_event? && bp.growth_event.read_only?
|
109
|
+
battle.add_to_log(bp.growth_event.message)
|
110
|
+
bp.growth_event.execute
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
def add_choice_to_log(bp)
|
115
|
+
battle.add_to_log(
|
116
|
+
'choice_for',
|
117
|
+
name,
|
118
|
+
bp.growth_event.message,
|
119
|
+
bp.growth_event.possible_actions.join(',')
|
120
|
+
)
|
121
|
+
end
|
122
|
+
|
123
|
+
def other_side_gains(ibp)
|
124
|
+
winner_sides = ibp.battle.sides - side_of_trainer(ibp.battle.sides)
|
125
|
+
winner_sides.each do |side|
|
126
|
+
side.trainers.each do |trainer|
|
127
|
+
trainer.grow(ibp)
|
128
|
+
end
|
129
|
+
end
|
130
|
+
end
|
131
|
+
|
132
|
+
def side_of_trainer(sides)
|
133
|
+
sides.select { |s| s.trainer_on_side?(self) }
|
134
|
+
end
|
135
|
+
|
136
|
+
def growth_events
|
137
|
+
team.map(&:growth_event).compact
|
138
|
+
end
|
50
139
|
end
|
51
140
|
end
|
52
141
|
end
|
@@ -13,17 +13,97 @@ module Oakdex
|
|
13
13
|
end
|
14
14
|
|
15
15
|
def valid_actions_for(trainer)
|
16
|
-
return [] if
|
17
|
-
|
18
|
-
|
16
|
+
return [] if no_actions_for?(trainer)
|
17
|
+
growth_events = growth_event_actions(trainer)
|
18
|
+
return growth_events unless growth_events.empty?
|
19
|
+
valid_move_actions_for(trainer) +
|
20
|
+
valid_recall_actions_for(trainer) +
|
21
|
+
valid_item_actions_for(trainer)
|
19
22
|
end
|
20
23
|
|
21
24
|
private
|
22
25
|
|
26
|
+
def actions_for_trainer(trainer)
|
27
|
+
actions.select { |a| a.trainer == trainer }
|
28
|
+
end
|
29
|
+
|
30
|
+
def no_actions_for?(trainer)
|
31
|
+
growth_events = growth_event_actions(trainer)
|
32
|
+
sides.empty? ||
|
33
|
+
(no_battle_pokemon?(trainer) && growth_events.empty?) ||
|
34
|
+
(other_is_growing?(trainer) && growth_events.empty?) ||
|
35
|
+
added_growth_action_already?(trainer)
|
36
|
+
end
|
37
|
+
|
38
|
+
def added_growth_action_already?(trainer)
|
39
|
+
growth_events = growth_event_actions(trainer)
|
40
|
+
|
41
|
+
!growth_events.empty? && !actions_for_trainer(trainer).empty?
|
42
|
+
end
|
43
|
+
|
44
|
+
def growth_event_actions(trainer)
|
45
|
+
while trainer.growth_event? && trainer.growth_event.read_only?
|
46
|
+
@battle.add_to_log(trainer.growth_event.message)
|
47
|
+
trainer.growth_event.execute
|
48
|
+
end
|
49
|
+
|
50
|
+
if trainer.growth_event?
|
51
|
+
trainer.growth_event.possible_actions.map do |option|
|
52
|
+
{
|
53
|
+
action: 'growth_event',
|
54
|
+
option: option
|
55
|
+
}
|
56
|
+
end
|
57
|
+
else
|
58
|
+
[]
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
def other_is_growing?(trainer)
|
63
|
+
other_trainers = sides.flat_map(&:trainers) - [trainer]
|
64
|
+
other_trainers.any? do |t|
|
65
|
+
t.growth_event? && !t.growth_event.read_only?
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
23
69
|
def valid_move_actions_for(trainer)
|
24
70
|
trainer.active_in_battle_pokemon.flat_map(&:valid_move_actions)
|
25
71
|
end
|
26
72
|
|
73
|
+
def valid_item_actions_for(trainer)
|
74
|
+
return [] if actions.select { |a| a.trainer == trainer }.size >= pokemon_per_trainer
|
75
|
+
trainer.items.flat_map do |item_id|
|
76
|
+
trainer.team.flat_map.with_index do |pokemon, i|
|
77
|
+
next if actions.any? { |a| a.item_id == item_id }
|
78
|
+
next unless pokemon.usable_item?(item_id, in_battle: true)
|
79
|
+
possible_item_actions(pokemon, item_id).map do |item_actions|
|
80
|
+
{
|
81
|
+
action: 'use_item_on_pokemon',
|
82
|
+
pokemon_team_pos: i,
|
83
|
+
item_id: item_id,
|
84
|
+
item_actions: item_actions
|
85
|
+
}
|
86
|
+
end
|
87
|
+
end.compact
|
88
|
+
end - actions
|
89
|
+
end
|
90
|
+
|
91
|
+
def possible_item_actions(battle_pokemon, item_id, prevActions = [])
|
92
|
+
dup_pokemon = battle_pokemon.pokemon.dup
|
93
|
+
dup_pokemon.use_item(item_id, in_battle: true)
|
94
|
+
e = dup_pokemon.growth_event
|
95
|
+
return [[]] if !e || e.read_only?
|
96
|
+
prevActions.each do |a|
|
97
|
+
e.execute(a)
|
98
|
+
e = dup_pokemon.growth_event
|
99
|
+
end
|
100
|
+
return [prevActions] if e.read_only?
|
101
|
+
e.possible_actions.flat_map do |a|
|
102
|
+
r = possible_item_actions(battle_pokemon, item_id, prevActions + [a])
|
103
|
+
r
|
104
|
+
end
|
105
|
+
end
|
106
|
+
|
27
107
|
def valid_recall_actions_for(trainer)
|
28
108
|
trainer.left_pokemon_in_team.flat_map do |pokemon|
|
29
109
|
pokemon_per_trainer.times.map do |position|
|
@@ -70,7 +150,8 @@ module Oakdex
|
|
70
150
|
end
|
71
151
|
|
72
152
|
def no_battle_pokemon?(trainer)
|
73
|
-
other_sides(trainer).all? { |s| s.active_in_battle_pokemon.empty? }
|
153
|
+
other_sides(trainer).all? { |s| s.active_in_battle_pokemon.empty? } &&
|
154
|
+
own_battle_pokemon?(trainer)
|
74
155
|
end
|
75
156
|
|
76
157
|
def own_battle_pokemon?(trainer)
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: oakdex-battle
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.1.
|
4
|
+
version: 0.1.1
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Jalyna Schroeder
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2019-
|
11
|
+
date: 2019-03-24 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: oakdex-pokemon
|
@@ -16,14 +16,28 @@ dependencies:
|
|
16
16
|
requirements:
|
17
17
|
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
|
-
version: 0.0.
|
19
|
+
version: 0.0.12
|
20
20
|
type: :runtime
|
21
21
|
prerelease: false
|
22
22
|
version_requirements: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
|
-
version: 0.0.
|
26
|
+
version: 0.0.12
|
27
|
+
- !ruby/object:Gem::Dependency
|
28
|
+
name: oakdex-pokedex
|
29
|
+
requirement: !ruby/object:Gem::Requirement
|
30
|
+
requirements:
|
31
|
+
- - ">="
|
32
|
+
- !ruby/object:Gem::Version
|
33
|
+
version: 0.4.5
|
34
|
+
type: :runtime
|
35
|
+
prerelease: false
|
36
|
+
version_requirements: !ruby/object:Gem::Requirement
|
37
|
+
requirements:
|
38
|
+
- - ">="
|
39
|
+
- !ruby/object:Gem::Version
|
40
|
+
version: 0.4.5
|
27
41
|
description: Pokémon Battle Engine Gen 7 Gem, based on oakdex-pokedex
|
28
42
|
email: jalyna.schroeder@gmail.com
|
29
43
|
executables: []
|
@@ -71,8 +85,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
71
85
|
- !ruby/object:Gem::Version
|
72
86
|
version: '0'
|
73
87
|
requirements: []
|
74
|
-
|
75
|
-
rubygems_version: 2.5.2
|
88
|
+
rubygems_version: 3.0.1
|
76
89
|
signing_key:
|
77
90
|
specification_version: 4
|
78
91
|
summary: Pokémon Battle Engine in Ruby
|