oakdex-battle 0.1.0 → 0.1.1

Sign up to get free protection for your applications and to get access to all the features.
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