Class: RedShift::World

Inherits:
Object show all
Includes:
CShadow, Enumerable
Defined in:
lib/redshift/syntax.rb,
lib/redshift/world.rb,
lib/redshift/target/c/world-gen.rb,
lib/redshift/mixins/zeno-debugger.rb,
lib/redshift/target/c/component-gen.rb

Overview

Register the given block to be called for this world just before it is first run. The block is called with the world as self. Any number of blocks can be registered.

Defined Under Namespace

Modules: ZenoDebugger Classes: ComponentList

Constant Summary collapse

CV_CACHE_SIZE =

Initial size for the constant value cache.

64
64
PORT_CACHE_SIZE =

Initial size for the port cache.

64
@@count =
0

Class Attribute Summary collapse

Instance Attribute Summary collapse

Class Method Summary collapse

Instance Method Summary collapse

Constructor Details

#initialize {|_self| ... } ⇒ World

Can override the options using assignments in the block. Note that clock_start should not be assigned after the block.

Yields:

  • (_self)

Yield Parameters:



94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
# File 'lib/redshift/world.rb', line 94

def initialize # :yields: world
  self.curr_A = []; self.curr_P = []; self.curr_CR = []
  self.curr_S = []; self.next_S = []; self.curr_T = []
  self.active_E = []; self.prev_active_E = []
  self.awake = []; self.prev_awake = []
  self.strict_sleep = []; self.inert = []
  self.diff_list = []; self.queue_sleep = {}
  @components = ComponentList.new  \
    awake, prev_awake, curr_T, strict_sleep, inert # _not_ diff_list

  options = default_options

  @name             = options[:name]
  @time_unit        = options[:time_unit]
  self.time_step    = options[:time_step]
  self.zeno_limit   = options[:zeno_limit]
  self.clock_start  = options[:clock_start]
  self.clock_finish = options[:clock_finish]
  
  self.step_count = 0
  
  @@count += 1

  do_defaults
  yield self if block_given?
  
  self.base_step_count = 0
  self.base_clock = clock_start
end

Class Attribute Details

.subclassesObject (readonly)

World is not included in subclasses. This returns nil when called on subs.



60
61
62
# File 'lib/redshift/world.rb', line 60

def subclasses
  @subclasses
end

Instance Attribute Details

#componentsObject (readonly)

Returns the value of attribute components.



72
73
74
# File 'lib/redshift/world.rb', line 72

def components
  @components
end

#nameObject

Returns the value of attribute name.



87
88
89
# File 'lib/redshift/world.rb', line 87

def name
  @name
end

#time_unitObject

Returns the value of attribute time_unit.



87
88
89
# File 'lib/redshift/world.rb', line 87

def time_unit
  @time_unit
end

Class Method Details

.defaults(&block) ⇒ Object Also known as: default

Register the given block to be called for instances of this class of World as they are instantiated (before the block passed to #new is called). The registered code is inherited by subclasses of this World class. The block is called with the world as self. Any number of blocks can be registered. (There are no per-world defaults. Use the #new block instead.)



11
12
13
# File 'lib/redshift/syntax.rb', line 11

def World.defaults(&block)
  (@defaults_procs ||= []) << block if block
end

.do_defaults(instance) ⇒ Object



129
130
131
132
133
134
135
136
# File 'lib/redshift/world.rb', line 129

def self.do_defaults instance
  superclass.do_defaults instance if superclass.respond_to? :do_defaults
  if @defaults_procs
    @defaults_procs.each do |pr|
      instance.instance_eval(&pr)
    end
  end
end

.do_setup(instance) ⇒ Object



149
150
151
152
153
154
155
156
# File 'lib/redshift/world.rb', line 149

def self.do_setup instance
  superclass.do_setup instance if superclass.respond_to? :do_setup
  if @setup_procs
    @setup_procs.each do |pr|
      instance.instance_eval(&pr)
    end
  end
end

.inherited(sub) ⇒ Object



62
63
64
# File 'lib/redshift/world.rb', line 62

def inherited(sub)
  World.subclasses << sub
end

.new(*args, &block) ⇒ Object

Redefines World#new so that a library commit happens first.



144
145
146
147
# File 'lib/redshift/target/c/world-gen.rb', line 144

def self.new(*args, &block)
  RedShift.require_target     # redefines World.new
  new(*args, &block)          # which is what this line calls
end

.open(filename) ⇒ Object



277
278
279
280
281
282
283
284
285
286
287
288
289
290
# File 'lib/redshift/world.rb', line 277

def World.open filename
  RedShift.require_target
  commit
  
  world = nil
  store = PStore.new filename
  store.transaction do
    if store.root? 'world'
      world = store['world']
      yield store if block_given?
    end
  end
  world
end

.setup(&block) ⇒ Object

Register the given block to be called for instances of this class of World just before they are first run. The registered code is inherited by subclasses of this World class. The block is called with the world as self. Any number of blocks can be registered.



22
23
24
# File 'lib/redshift/syntax.rb', line 22

def World.setup(&block)
  (@setup_procs ||= []) << block if block
end

Instance Method Details

#create(component_class) ⇒ Object



158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
# File 'lib/redshift/world.rb', line 158

def create(component_class)
  component = 
    if block_given?
      component_class.new(self) {|c| yield c}
    else
      component_class.new(self)
    end
  
  unless component.is_a? Component # Component is abstract
    raise TypeError, "#{component.class} is not a Component class"
  end
  
  awake << component if component.world == self
  component
end

#default_optionsObject



74
75
76
77
78
79
80
81
82
83
# File 'lib/redshift/world.rb', line 74

def default_options
  {
    :name         =>  "#{self.class}_#{@@count}",
    :time_unit    =>  "second",
    :time_step    =>  0.1,
    :zeno_limit   =>  100,
    :clock_start  =>  0.0,
    :clock_finish =>  Infinity,
  }
end

#each(&b) ⇒ Object



236
237
238
# File 'lib/redshift/world.rb', line 236

def each(&b)
  @components.each(&b)
end

#evolve(time = 1.0, &block) ⇒ Object



218
219
220
# File 'lib/redshift/world.rb', line 218

def evolve(time = 1.0, &block)
  run((time.to_f/time_step).round, &block)
end

#garbage_collectObject

is this a good idea? tests?



228
229
230
231
232
233
234
# File 'lib/redshift/world.rb', line 228

def garbage_collect
  self.components.clear
  GC.start
  ObjectSpace.each_object(Component) do |c|
    components << c if c.world == self
  end
end

#include?(component) ⇒ Boolean Also known as: member?

Returns:

  • (Boolean)


244
245
246
# File 'lib/redshift/world.rb', line 244

def include? component
  component.world == self
end

#inspectObject



249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
# File 'lib/redshift/world.rb', line 249

def inspect
  if @started
    digits = -Math.log10(time_step).floor
    digits = 0 if digits < 0

    data = []
    data << "%d step%s" % [step_count, ("s" if step_count != 1)]
    data << "%.#{digits}f #{@time_unit}%s" % [clock, ("s" if clock != 1)]
    data << "%d component%s" % [size, ("s" if size != 1)]
    data << "discrete step = #{discrete_step}" ## only if in step_discrete?
  else
    data = ["not started. Do 'run 0' to setup, or 'run n' to run."]
  end

  str = [name, data.join("; ")].join(": ")
  "<#{str}>"
end

#remove(c) ⇒ Object

is this a good idea? tests? #add ?



175
176
177
178
179
180
181
182
# File 'lib/redshift/world.rb', line 175

def remove c
  if components.summands.any? {|list| list.delete(c)}
    raise unless c.world == self
    c.__set__world(nil)
  else
    raise "Tried to remove #{c} from #{self}, but its world is #{c.world}."
  end
end

#run(*args, &block) ⇒ Object



213
214
215
216
# File 'lib/redshift/world.rb', line 213

def run(*args, &block)
  ## warn "World#run is deprecated -- use #step or #evolve"
  step(*args, &block)
end

#running?Boolean

Returns:

  • (Boolean)


90
# File 'lib/redshift/world.rb', line 90

def running?; @running; end

#save(filename = @name) ⇒ Object



267
268
269
270
271
272
273
274
275
# File 'lib/redshift/world.rb', line 267

def save filename = @name
  raise "Can't save world during its run method." if @running
  File.delete(filename) rescue SystemCallError
  store = PStore.new filename
  store.transaction do
    store['world'] = self
    yield store if block_given?
  end
end

#setup(&block) ⇒ Object



30
31
32
# File 'lib/redshift/syntax.rb', line 30

def setup(&block)
  (@setup_procs ||= []) << block if block
end

#sizeObject



240
241
242
# File 'lib/redshift/world.rb', line 240

def size
  @components.size
end

#started?Boolean

Returns:

  • (Boolean)


89
# File 'lib/redshift/world.rb', line 89

def started?; @started; end

#step(steps = 1) ⇒ Object

All evolution methods untimately call step, which can be overridden. After each step, yields to block. It is the block’s responsibility to step_discrete at this point after changing any vars.



187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
# File 'lib/redshift/world.rb', line 187

def step(steps = 1)
  @running = true
  
  unless @started
    do_setup
    @started = true
  end
  
  step_discrete
  steps.to_i.times do
    break if clock > clock_finish
    self.step_count += 1
    step_continuous
    step_discrete
    @running = false
    yield self if block_given?
    @running = true
  end
  
  self
  
ensure
  @running = false
  ## how to continue stepping after an exception?
end

#step_zenoObject

Default implementation is to raise RedShift::ZenoError.



223
224
225
# File 'lib/redshift/world.rb', line 223

def step_zeno
  raise RedShift::ZenoError, "Exceeded zeno limit of #{zeno_limit}."
end