zyps 0.6.3 → 0.7.0
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.
- data/README.txt +11 -27
- data/bin/zyps +355 -296
- data/bin/zyps_demo +267 -249
- data/lib/zyps/actions.rb +104 -139
- data/lib/zyps/conditions.rb +39 -15
- data/lib/zyps/environmental_factors.rb +60 -48
- data/lib/zyps/views/canvas/gtk2.rb +152 -0
- data/lib/zyps/views/canvas/wx.rb +191 -0
- data/lib/zyps/views/trails.rb +56 -59
- data/lib/zyps.rb +101 -84
- data/test/test_zyps.rb +48 -75
- data/test/zyps/test_actions.rb +24 -73
- data/test/zyps/test_conditions.rb +30 -11
- data/test/zyps/test_environmental_factors.rb +28 -22
- data/test/zyps/test_remote.rb +3 -3
- metadata +16 -8
- data/bin/zyps_server +0 -235
data/lib/zyps/actions.rb
CHANGED
@@ -48,7 +48,13 @@ class TimedAction < Action
|
|
48
48
|
end
|
49
49
|
|
50
50
|
#Begin tracking time between actions.
|
51
|
-
def start(actor,
|
51
|
+
def start(actor, targets)
|
52
|
+
super
|
53
|
+
@clock.reset_elapsed_time
|
54
|
+
end
|
55
|
+
|
56
|
+
#Halt tracking time between actions.
|
57
|
+
def stop(actor, targets)
|
52
58
|
super
|
53
59
|
@clock.reset_elapsed_time
|
54
60
|
end
|
@@ -58,9 +64,9 @@ end
|
|
58
64
|
|
59
65
|
#Head toward a target.
|
60
66
|
class FaceAction < Action
|
61
|
-
#Set the actor's heading to point directly at target.
|
62
|
-
def do(actor,
|
63
|
-
actor.vector.pitch = Utility.find_angle(actor.location,
|
67
|
+
#Set the actor's heading to point directly at first target.
|
68
|
+
def do(actor, targets)
|
69
|
+
actor.vector.pitch = Utility.find_angle(actor.location, targets[0].location)
|
64
70
|
end
|
65
71
|
end
|
66
72
|
|
@@ -71,111 +77,56 @@ class AccelerateAction < TimedAction
|
|
71
77
|
#Can be negative to slow down or go in reverse.
|
72
78
|
attr_accessor :rate
|
73
79
|
#Increase or decrease speed according to elapsed time.
|
74
|
-
def do(actor,
|
80
|
+
def do(actor, targets)
|
75
81
|
actor.vector.speed += delta
|
76
82
|
end
|
77
83
|
end
|
78
84
|
|
79
85
|
|
80
|
-
#
|
86
|
+
#Apply a thrust that turns actor.
|
81
87
|
class TurnAction < TimedAction
|
82
|
-
#
|
83
|
-
|
84
|
-
|
85
|
-
|
86
|
-
|
87
|
-
|
88
|
+
#Angle to turn at.
|
89
|
+
attr_accessor :angle
|
90
|
+
def initialize(rate, angle)
|
91
|
+
super
|
92
|
+
@angle = angle
|
93
|
+
end
|
94
|
+
def do(actor, targets)
|
95
|
+
actor.vector += Vector.new(
|
96
|
+
delta,
|
97
|
+
actor.vector.pitch + @angle
|
98
|
+
)
|
88
99
|
end
|
89
100
|
end
|
90
101
|
|
91
102
|
|
92
103
|
#Approaches the target, but obeys law of inertia.
|
93
104
|
class ApproachAction < TimedAction
|
94
|
-
#
|
95
|
-
|
96
|
-
|
97
|
-
|
98
|
-
|
99
|
-
|
100
|
-
|
101
|
-
end
|
102
|
-
#Make a deep copy.
|
103
|
-
def copy
|
104
|
-
copy = super
|
105
|
-
copy.heading = @heading.copy
|
106
|
-
copy
|
107
|
-
end
|
108
|
-
#Accelerate toward the target, but limited by turn rate.
|
109
|
-
def do(actor, target)
|
110
|
-
#Find the difference between the current heading and the angle to the target.
|
111
|
-
turn_angle = Utility.find_angle(actor.location, target.location) - @heading.pitch
|
112
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
113
|
-
if turn_angle > 180 then
|
114
|
-
turn_angle -= 360.0
|
115
|
-
elsif turn_angle < -180 then
|
116
|
-
turn_angle += 360.0
|
117
|
-
end
|
118
|
-
#The creature can only turn as fast as the elapsed time, of course.
|
119
|
-
maximum_turn = delta
|
120
|
-
if turn_angle.abs > maximum_turn
|
121
|
-
if turn_angle > 0
|
122
|
-
turn_angle = maximum_turn
|
123
|
-
else
|
124
|
-
turn_angle = maximum_turn * -1
|
125
|
-
end
|
126
|
-
end
|
127
|
-
#Turn the appropriate amount.
|
128
|
-
@heading.pitch += turn_angle
|
129
|
-
#Apply the heading to the creature's movement vector.
|
130
|
-
actor.vector += @heading
|
105
|
+
#Accelerate toward the first target, but limited by rate.
|
106
|
+
def do(actor, targets)
|
107
|
+
#Apply thrust to the creature's movement vector, adjusted by elapsed time.
|
108
|
+
actor.vector += Vector.new(
|
109
|
+
delta,
|
110
|
+
Utility.find_angle(actor.location, targets[0].location)
|
111
|
+
)
|
131
112
|
end
|
132
113
|
end
|
133
114
|
|
134
115
|
|
135
116
|
#Flees from the target, but obeys law of inertia.
|
136
117
|
class FleeAction < TimedAction
|
137
|
-
#
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
144
|
-
end
|
145
|
-
#Make a deep copy.
|
146
|
-
def copy
|
147
|
-
copy = super
|
148
|
-
copy.heading = @heading.copy
|
149
|
-
copy
|
150
|
-
end
|
151
|
-
#Accelerate away from the target, but limited by turn rate.
|
152
|
-
def do(actor, target)
|
153
|
-
#Find the difference between the current heading and the angle to the target.
|
154
|
-
turn_angle = Utility.find_angle(actor.location, target.location) - @heading.pitch + 180
|
155
|
-
#If the angle is the long way around from the current heading, change it to the smaller angle.
|
156
|
-
if turn_angle > 180 then
|
157
|
-
turn_angle -= 360.0
|
158
|
-
elsif turn_angle < -180 then
|
159
|
-
turn_angle += 360.0
|
160
|
-
end
|
161
|
-
#The creature can only turn as fast as the elapsed time, of course.
|
162
|
-
maximum_turn = delta
|
163
|
-
if turn_angle.abs > maximum_turn
|
164
|
-
if turn_angle > 0
|
165
|
-
turn_angle = maximum_turn
|
166
|
-
else
|
167
|
-
turn_angle = maximum_turn * -1
|
168
|
-
end
|
169
|
-
end
|
170
|
-
#Turn the appropriate amount.
|
171
|
-
@heading.pitch += turn_angle
|
172
|
-
#Apply the heading to the creature's movement vector.
|
173
|
-
actor.vector += @heading
|
118
|
+
#Accelerate away from the first target, but limited by turn rate.
|
119
|
+
def do(actor, targets)
|
120
|
+
#Apply thrust to the creature's movement vector, adjusted by elapsed time.
|
121
|
+
actor.vector += Vector.new(
|
122
|
+
delta,
|
123
|
+
Utility.find_angle(actor.location, targets[0].location) + 180
|
124
|
+
)
|
174
125
|
end
|
175
126
|
end
|
176
127
|
|
177
128
|
|
178
|
-
#Destroy the
|
129
|
+
#Destroy the targets.
|
179
130
|
class DestroyAction < Action
|
180
131
|
#The environment to remove objects from.
|
181
132
|
attr_accessor :environment
|
@@ -183,19 +134,23 @@ class DestroyAction < Action
|
|
183
134
|
self.environment = environment
|
184
135
|
end
|
185
136
|
#Remove the target from the environment.
|
186
|
-
def do(actor,
|
187
|
-
|
137
|
+
def do(actor, targets)
|
138
|
+
targets.each do |target|
|
139
|
+
@environment.objects.delete(target)
|
140
|
+
end
|
188
141
|
end
|
189
142
|
end
|
190
143
|
|
191
144
|
|
192
|
-
#Destroy the
|
145
|
+
#Destroy the targets and grow in size.
|
193
146
|
class EatAction < DestroyAction
|
194
|
-
#Remove the
|
195
|
-
def do(actor,
|
147
|
+
#Remove the targets from the environment, and increase actor's size by size of targets.
|
148
|
+
def do(actor, targets)
|
196
149
|
#Grow in size.
|
197
|
-
|
198
|
-
|
150
|
+
targets.each do |target|
|
151
|
+
actor.size += target.size
|
152
|
+
end
|
153
|
+
#Remove the targets from the environment.
|
199
154
|
super
|
200
155
|
end
|
201
156
|
end
|
@@ -203,44 +158,50 @@ end
|
|
203
158
|
|
204
159
|
#Add a tag to the target.
|
205
160
|
class TagAction < Action
|
206
|
-
#Tag to apply to
|
161
|
+
#Tag to apply to targets.
|
207
162
|
attr_accessor :tag
|
208
163
|
def initialize(tag)
|
209
164
|
self.tag = tag
|
210
165
|
end
|
211
|
-
#Apply the given tag to the
|
212
|
-
def do(actor,
|
213
|
-
|
166
|
+
#Apply the given tag to the targets.
|
167
|
+
def do(actor, targets)
|
168
|
+
targets.each do |target|
|
169
|
+
target.tags << tag unless target.tags.include?(tag)
|
170
|
+
end
|
214
171
|
end
|
215
172
|
end
|
216
173
|
|
217
174
|
|
218
175
|
#Blend the target's color with another color.
|
219
176
|
class BlendAction < Action
|
220
|
-
#Color to apply to
|
177
|
+
#Color to apply to targets.
|
221
178
|
attr_accessor :color
|
222
179
|
def initialize(color)
|
223
180
|
self.color = color
|
224
181
|
end
|
225
|
-
#Blend the
|
226
|
-
def do(actor,
|
227
|
-
|
182
|
+
#Blend the targets' color with the assigned color.
|
183
|
+
def do(actor, targets)
|
184
|
+
targets.each do |target|
|
185
|
+
target.color += @color
|
186
|
+
end
|
228
187
|
end
|
229
188
|
end
|
230
189
|
|
231
190
|
|
232
191
|
#Pushes target away.
|
233
192
|
class PushAction < TimedAction
|
234
|
-
#Units/second to accelerate
|
193
|
+
#Units/second to accelerate targets by.
|
235
194
|
attr_accessor :rate
|
236
|
-
#
|
237
|
-
def do(actor,
|
238
|
-
#Angle to target is also angle of push force.
|
239
|
-
push_angle = Utility.find_angle(actor.location, target.location)
|
195
|
+
#Push the targets away from the actor, with force limited by elapsed time.
|
196
|
+
def do(actor, targets)
|
240
197
|
#Acceleration will be limited by elapsed time.
|
241
198
|
push_force = delta
|
242
|
-
|
243
|
-
|
199
|
+
targets.each do |target|
|
200
|
+
#Angle to target is also angle of push force.
|
201
|
+
push_angle = Utility.find_angle(actor.location, target.location)
|
202
|
+
#Apply the force to the creature's movement vector.
|
203
|
+
target.vector += Vector.new(push_force, push_angle)
|
204
|
+
end
|
244
205
|
end
|
245
206
|
end
|
246
207
|
|
@@ -249,14 +210,16 @@ end
|
|
249
210
|
class PullAction < TimedAction
|
250
211
|
#Units/second to accelerate target by.
|
251
212
|
attr_accessor :rate
|
252
|
-
#
|
253
|
-
def do(actor,
|
254
|
-
#Angle from target to actor is also angle of pull force (opposite of that for push).
|
255
|
-
pull_angle = Utility.find_angle(target.location, actor.location)
|
213
|
+
#Pull the targets toward the actor, with force limited by elapsed time.
|
214
|
+
def do(actor, targets)
|
256
215
|
#Acceleration will be limited by elapsed time.
|
257
216
|
pull_force = delta
|
258
|
-
|
259
|
-
|
217
|
+
targets.each do |target|
|
218
|
+
#Angle from target to actor is also angle of pull force (opposite of that for push).
|
219
|
+
pull_angle = Utility.find_angle(target.location, actor.location)
|
220
|
+
#Apply the force to the creature's movement vector.
|
221
|
+
target.vector += Vector.new(pull_force, pull_angle)
|
222
|
+
end
|
260
223
|
end
|
261
224
|
end
|
262
225
|
|
@@ -272,31 +235,33 @@ class BreedAction < Action
|
|
272
235
|
@clock = Clock.new
|
273
236
|
@time_since_last_action = 0
|
274
237
|
end
|
275
|
-
def do(actor,
|
276
|
-
|
277
|
-
|
278
|
-
|
279
|
-
|
280
|
-
|
281
|
-
|
282
|
-
|
283
|
-
|
284
|
-
|
285
|
-
|
286
|
-
|
287
|
-
|
238
|
+
def do(actor, targets)
|
239
|
+
targets.each do |target|
|
240
|
+
#Skip action if target is not a Creature.
|
241
|
+
next unless target.is_a?(Creature)
|
242
|
+
#Get time since last action, and skip if it hasn't been long enough.
|
243
|
+
@time_since_last_action += @clock.elapsed_time
|
244
|
+
return unless @time_since_last_action >= @delay
|
245
|
+
#Create a child.
|
246
|
+
child = Creature.new
|
247
|
+
#Combine colors.
|
248
|
+
child.color = actor.color + target.color
|
249
|
+
#Combine behaviors EXCEPT those with BreedActions.
|
250
|
+
behaviors = (actor.behaviors + target.behaviors).find_all do |behavior|
|
251
|
+
! behavior.actions.any?{|action| action.is_a?(BreedAction)}
|
252
|
+
end
|
253
|
+
behaviors.each {|behavior| child.behaviors << behavior.copy}
|
254
|
+
#Location should equal actor's.
|
255
|
+
child.location = actor.location.copy
|
256
|
+
#Add parents' vectors to get child's vector.
|
257
|
+
child.vector = actor.vector + target.vector
|
258
|
+
#Child's size should be half the average size of the parents'.
|
259
|
+
child.size = ((actor.size + target.size) / 2) / 2
|
260
|
+
#Add child to environment.
|
261
|
+
@environment.objects << child
|
262
|
+
#Reset elapsed time.
|
263
|
+
@time_since_last_action = 0
|
288
264
|
end
|
289
|
-
behaviors.each {|behavior| child.behaviors << behavior.copy}
|
290
|
-
#Location should equal actor's.
|
291
|
-
child.location = actor.location.copy
|
292
|
-
#Add parents' vectors to get child's vector.
|
293
|
-
child.vector = actor.vector + target.vector
|
294
|
-
#Child's size should be half the average size of the parents'.
|
295
|
-
child.size = ((actor.size + target.size) / 2) / 2
|
296
|
-
#Add child to environment.
|
297
|
-
@environment.objects << child
|
298
|
-
#Reset elapsed time.
|
299
|
-
@time_since_last_action = 0
|
300
265
|
end
|
301
266
|
end
|
302
267
|
|
data/lib/zyps/conditions.rb
CHANGED
@@ -21,53 +21,77 @@ require 'zyps'
|
|
21
21
|
module Zyps
|
22
22
|
|
23
23
|
|
24
|
-
#
|
24
|
+
#Select objects with the correct tag.
|
25
25
|
class TagCondition < Condition
|
26
26
|
#The tag to look for on the target.
|
27
27
|
attr_accessor :tag
|
28
28
|
def initialize(tag)
|
29
29
|
self.tag = tag
|
30
30
|
end
|
31
|
-
#
|
32
|
-
def
|
33
|
-
target.tags.include?(@tag)
|
31
|
+
#Returns an array of targets which have the assigned tag.
|
32
|
+
def select(actor, targets)
|
33
|
+
targets.find_all {|target| target.tags.include?(@tag)}
|
34
34
|
end
|
35
35
|
end
|
36
36
|
|
37
37
|
|
38
|
-
#
|
38
|
+
#Select objects older than the given age.
|
39
39
|
class AgeCondition < Condition
|
40
40
|
#The minimum age in seconds.
|
41
41
|
attr_accessor :age
|
42
42
|
def initialize(age)
|
43
43
|
self.age = age
|
44
44
|
end
|
45
|
-
#
|
46
|
-
def
|
47
|
-
target.age > @age
|
45
|
+
#Returns an array of targets which are older than the assigned age.
|
46
|
+
def select(actor, targets)
|
47
|
+
targets.find_all {|target| target.age > @age}
|
48
48
|
end
|
49
49
|
end
|
50
50
|
|
51
51
|
|
52
|
-
#
|
52
|
+
#Select objects that are closer than the given distance.
|
53
53
|
class ProximityCondition < Condition
|
54
54
|
#The maximum number of units away the target can be.
|
55
55
|
attr_accessor :distance
|
56
56
|
def initialize(distance)
|
57
57
|
self.distance = distance
|
58
58
|
end
|
59
|
-
#
|
60
|
-
def
|
61
|
-
Utility.find_distance(actor.location, target.location) <= @distance
|
59
|
+
#Returns an array of targets that are at the given distance or closer.
|
60
|
+
def select(actor, targets)
|
61
|
+
targets.find_all {|target| Utility.find_distance(actor.location, target.location) <= @distance}
|
62
62
|
end
|
63
63
|
end
|
64
64
|
|
65
65
|
|
66
66
|
#True only if collided with target.
|
67
67
|
class CollisionCondition < Condition
|
68
|
-
#
|
69
|
-
def
|
70
|
-
Utility.collided?(actor, target)
|
68
|
+
#Returns an array of targets that have collided with the actor.
|
69
|
+
def select(actor, targets)
|
70
|
+
targets.find_all {|target| Utility.collided?(actor, target)}
|
71
|
+
end
|
72
|
+
end
|
73
|
+
|
74
|
+
|
75
|
+
#True if the actor's strength is equal to or greater than the target's.
|
76
|
+
class StrengthCondition < Condition
|
77
|
+
#Returns an array of targets that are weaker than the actor.
|
78
|
+
#For now, strength is based merely on size.
|
79
|
+
def select(actor, targets)
|
80
|
+
targets.find_all {|target| actor.size >= target.size}
|
81
|
+
end
|
82
|
+
end
|
83
|
+
|
84
|
+
|
85
|
+
#True if the actor and target are of the same Ruby class.
|
86
|
+
class ClassCondition < Condition
|
87
|
+
#The class of target to look for.
|
88
|
+
attr_accessor :target_class
|
89
|
+
def initialize(target_class)
|
90
|
+
self.target_class = target_class
|
91
|
+
end
|
92
|
+
#Returns an array of targets that are of the selected Ruby class.
|
93
|
+
def select(actor, targets)
|
94
|
+
targets.grep(target_class)
|
71
95
|
end
|
72
96
|
end
|
73
97
|
|
@@ -33,32 +33,44 @@ class Enclosure < EnvironmentalFactor
|
|
33
33
|
#Y coordinate of bottom boundary.
|
34
34
|
attr_accessor :bottom
|
35
35
|
|
36
|
-
|
37
|
-
|
36
|
+
#Takes a hash with these keys and defaults:
|
37
|
+
# :left => 0
|
38
|
+
# :top => 0
|
39
|
+
# :right => 0
|
40
|
+
# :bottom => 0
|
41
|
+
def initialize(options = {})
|
42
|
+
options = {
|
43
|
+
:left => 0,
|
44
|
+
:top => 0,
|
45
|
+
:right => 0,
|
46
|
+
:bottom => 0
|
47
|
+
}.merge(options)
|
48
|
+
self.left, self.top, self.right, self.bottom = options[:left], options[:top], options[:right], options[:bottom]
|
38
49
|
end
|
39
50
|
|
40
51
|
#If object is beyond a boundary, set its position equal to the boundary and reflect it.
|
41
|
-
def act(
|
42
|
-
|
43
|
-
object.location.x
|
44
|
-
|
45
|
-
|
46
|
-
object.location.x
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
object.location.y
|
51
|
-
|
52
|
-
|
53
|
-
object.location.y
|
54
|
-
|
52
|
+
def act(environment)
|
53
|
+
environment.objects.each do |object|
|
54
|
+
if (object.location.x < @left) then
|
55
|
+
object.location.x = @left
|
56
|
+
object.vector.pitch = Utility.find_reflection_angle(90, object.vector.pitch)
|
57
|
+
elsif (object.location.x > @right) then
|
58
|
+
object.location.x = @right
|
59
|
+
object.vector.pitch = Utility.find_reflection_angle(270, object.vector.pitch)
|
60
|
+
end
|
61
|
+
if (object.location.y > @top) then
|
62
|
+
object.location.y = @top
|
63
|
+
object.vector.pitch = Utility.find_reflection_angle(0, object.vector.pitch)
|
64
|
+
elsif (object.location.y < @bottom) then
|
65
|
+
object.location.y = @bottom
|
66
|
+
object.vector.pitch = Utility.find_reflection_angle(180, object.vector.pitch)
|
67
|
+
end
|
55
68
|
end
|
56
69
|
end
|
57
70
|
|
58
71
|
end
|
59
72
|
|
60
73
|
|
61
|
-
|
62
74
|
#Keeps all objects at/under the assigned speed.
|
63
75
|
class SpeedLimit < EnvironmentalFactor
|
64
76
|
|
@@ -70,8 +82,10 @@ class SpeedLimit < EnvironmentalFactor
|
|
70
82
|
end
|
71
83
|
|
72
84
|
#If object is over the speed, reduce its speed.
|
73
|
-
def act(
|
74
|
-
|
85
|
+
def act(environment)
|
86
|
+
environment.objects.each do |object|
|
87
|
+
object.vector.speed = Utility.constrain_value(object.vector.speed, @maximum)
|
88
|
+
end
|
75
89
|
end
|
76
90
|
|
77
91
|
end
|
@@ -85,15 +99,16 @@ class Accelerator < EnvironmentalFactor
|
|
85
99
|
|
86
100
|
def initialize(vector)
|
87
101
|
self.vector = vector
|
88
|
-
@
|
102
|
+
@clock = Clock.new
|
89
103
|
end
|
90
104
|
|
91
105
|
#Accelerate the target away from the actor, but limited by elapsed time.
|
92
|
-
def act(
|
93
|
-
|
94
|
-
|
95
|
-
|
96
|
-
|
106
|
+
def act(environment)
|
107
|
+
elapsed_time = @clock.elapsed_time
|
108
|
+
environment.objects.each do |object|
|
109
|
+
#Push on object.
|
110
|
+
object.vector += Vector.new(@vector.speed * elapsed_time, @vector.pitch)
|
111
|
+
end
|
97
112
|
end
|
98
113
|
|
99
114
|
end
|
@@ -124,25 +139,26 @@ class Friction < EnvironmentalFactor
|
|
124
139
|
|
125
140
|
def initialize(force)
|
126
141
|
self.force = force
|
127
|
-
#Track time since last action
|
128
|
-
@
|
142
|
+
#Track time since last action.
|
143
|
+
@clock = Clock.new
|
129
144
|
end
|
130
145
|
|
131
146
|
#Reduce the target's speed at the given rate.
|
132
|
-
def act(
|
133
|
-
|
134
|
-
|
135
|
-
|
136
|
-
|
137
|
-
|
138
|
-
|
139
|
-
|
140
|
-
|
141
|
-
|
142
|
-
|
143
|
-
|
147
|
+
def act(environment)
|
148
|
+
elapsed_time = @clock.elapsed_time
|
149
|
+
environment.objects.each do |object|
|
150
|
+
#Slow object.
|
151
|
+
acceleration = @force * elapsed_time
|
152
|
+
speed = object.vector.speed
|
153
|
+
if speed > 0
|
154
|
+
speed -= acceleration
|
155
|
+
speed = 0 if speed < 0
|
156
|
+
elsif speed < 0
|
157
|
+
speed += acceleration
|
158
|
+
speed = 0 if speed > 0
|
159
|
+
end
|
160
|
+
object.vector.speed = speed
|
144
161
|
end
|
145
|
-
object.vector.speed = speed
|
146
162
|
end
|
147
163
|
|
148
164
|
end
|
@@ -150,21 +166,17 @@ end
|
|
150
166
|
|
151
167
|
class PopulationLimit < EnvironmentalFactor
|
152
168
|
|
153
|
-
#Environment to remove objects from.
|
154
|
-
attr_accessor :environment
|
155
169
|
#Maximum allowed population.
|
156
170
|
attr_accessor :count
|
157
171
|
|
158
|
-
def initialize(
|
159
|
-
self.environment = environment
|
172
|
+
def initialize(count)
|
160
173
|
self.count = count
|
161
174
|
end
|
162
175
|
|
163
176
|
#Remove target if there are too many objects in environment.
|
164
|
-
def act(
|
165
|
-
|
166
|
-
|
167
|
-
end
|
177
|
+
def act(environment)
|
178
|
+
excess = environment.objects.length - @count
|
179
|
+
environment.objects.slice!(0, excess) if excess > 0
|
168
180
|
end
|
169
181
|
|
170
182
|
end
|