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