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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
- SHA1:
3
- metadata.gz: 2066dbb4e78aff0e298029c4eb76f345326e172e
4
- data.tar.gz: bf2201bd2ebfdb085b1fa2b766ec344e41c8a97c
2
+ SHA256:
3
+ metadata.gz: fb6705359f3c133ea6fe2ed3402b0afa848b008c3d546cc2f5ccb641c3967415
4
+ data.tar.gz: 94556920e80e6b1d273ded0be30fcc0058ebbf2ccd0d663049ba06b941e96c15
5
5
  SHA512:
6
- metadata.gz: 30127361db91d8748335a8a58609a045ddf3c7faceac02a034e8da966496c89271f9c4ebe2cd3e3af3e83b6e819b2904e6ae80b823d22501b28696cb3fb5e7d7
7
- data.tar.gz: 61482125d2312a029a6de584efc8069be965e9c21b26cdf7163e3501e3273c7d519b8578b61284adb770a5d6570c7e4b320e94371d8126d769d1ba228ad2f4a0
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
@@ -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 = 6
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 execute_recall if type == 'recall'
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
- reutrn [] if list.empty?
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
 
@@ -13,6 +13,7 @@ module Oakdex
13
13
  def initialize(battle, trainers)
14
14
  @battle = battle
15
15
  @trainers = trainers
16
+ @trainers.each { |t| t.side = self }
16
17
  end
17
18
 
18
19
  def next_position
@@ -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 sides.empty?
17
- return [] if no_battle_pokemon?(trainer) && own_battle_pokemon?(trainer)
18
- valid_move_actions_for(trainer) + valid_recall_actions_for(trainer)
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)
@@ -1,5 +1,5 @@
1
1
  module Oakdex
2
2
  class Battle
3
- VERSION = '0.1.0'
3
+ VERSION = '0.1.1'
4
4
  end
5
5
  end
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.0
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-01-21 00:00:00.000000000 Z
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.4
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.4
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
- rubyforge_project:
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