zyps 0.7.5 → 0.7.6

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_windows.txt CHANGED
@@ -28,6 +28,9 @@ your efforts so long ago.
28
28
 
29
29
  Alex Fenton and Mario Steele for wxRuby advice.
30
30
 
31
+ The authors of the Nullsoft Scriptable Install System
32
+ (NSIS), which is used for the Windows installer.
33
+
31
34
  My lovely wife, Diana, for patience and usability testing.
32
35
 
33
36
 
data/bin/zyps CHANGED
@@ -126,11 +126,14 @@ class Application < Wx::App
126
126
  @log.debug "Create an interface."
127
127
  @controls = ControlPanel.new(frame)
128
128
  @controls.clear_button.evt_button(@controls.clear_button.get_id) do |event|
129
- @environment.objects = []
129
+ @environment.objects.clear
130
130
  end
131
131
  @controls.length_slider.evt_slider(@controls.length_slider.get_id) do |event|
132
132
  @view.trail_length = @controls.length_slider.value
133
133
  end
134
+ @controls.speed_slider.evt_slider(@controls.speed_slider) do |event|
135
+ Clock.speed = @controls.speed_slider.value.to_f / 5.0
136
+ end
134
137
  frame.sizer.add(@controls, 0, Wx::GROW)
135
138
 
136
139
  @log.debug "Create an environment, and link it to the view."
@@ -525,6 +528,7 @@ class ControlPanel < Wx::Panel
525
528
  attr_accessor :breed_flag
526
529
  attr_accessor :eat_flag
527
530
  attr_accessor :length_slider
531
+ attr_accessor :speed_slider
528
532
  attr_accessor :clear_button
529
533
 
530
534
 
@@ -546,11 +550,14 @@ class ControlPanel < Wx::Panel
546
550
 
547
551
  display_controls = add_panel(self, :proportion => 1)
548
552
  add_label(display_controls, :label => "Length")
549
- @length_slider = add_slider(display_controls, :min_value => 2, :max_value => 100)
553
+ @length_slider = add_slider(display_controls, :min_value => 2, :max_value => 20)
550
554
  @length_slider.value = 5
551
555
 
552
556
  environment_controls = add_panel(self, :proportion => 1)
553
557
  add_label(environment_controls, :label => "Environment")
558
+ add_label(environment_controls, :label => "Speed")
559
+ @speed_slider = add_slider(environment_controls, :min_value => 0, :max_value => 15)
560
+ @speed_slider.value = 5
554
561
  @clear_button = add_button(environment_controls, :label => "Clear")
555
562
 
556
563
  end
@@ -720,15 +727,14 @@ class CreatureGenerator
720
727
  )
721
728
 
722
729
  #Set up actions and merge colors according to selected behaviors.
723
- color = Color.new(0.5, 0.5, 0.5)
724
730
  if options[:turn]
725
- color.blue += 1
731
+ color = color ? color + Color.blue : Color.blue
726
732
  creature.behaviors << Behavior.new(
727
733
  :actions => [TurnAction.new(@turn_rate, @turn_angle)]
728
734
  )
729
735
  end
730
736
  if options[:approach]
731
- color.red += 1
737
+ color = color ? color + Color.red : Color.red
732
738
  creature.behaviors << Behavior.new(
733
739
  :actions => [ApproachAction.new(@approach_rate)],
734
740
  :conditions => [ProximityCondition.new(options[:action_proximity])],
@@ -736,7 +742,7 @@ class CreatureGenerator
736
742
  )
737
743
  end
738
744
  if options[:flee]
739
- color.red += 0.5; color.green += 0.5 #Yellow.
745
+ color = color ? color + Color.yellow : Color.yellow
740
746
  creature.behaviors << Behavior.new(
741
747
  :actions => [FleeAction.new(@flee_rate)],
742
748
  :conditions => [ProximityCondition.new(options[:action_proximity] * 0.5)],
@@ -744,7 +750,7 @@ class CreatureGenerator
744
750
  )
745
751
  end
746
752
  if options[:push]
747
- color.red += 0.5; color.blue += 0.5 #Purple.
753
+ color = color ? color + Color.violet : Color.violet
748
754
  creature.behaviors << Behavior.new(
749
755
  :actions => [PushAction.new(@push_strength)],
750
756
  :conditions => [ProximityCondition.new(options[:action_proximity] * 0.25)],
@@ -752,7 +758,7 @@ class CreatureGenerator
752
758
  )
753
759
  end
754
760
  if options[:pull]
755
- color.blue += 0.75; color.green += 0.75 #Aqua.
761
+ color = color ? color + Color.indigo : Color.indigo
756
762
  creature.behaviors << Behavior.new(
757
763
  :actions => [PullAction.new(@pull_strength)],
758
764
  :conditions => [ProximityCondition.new(options[:action_proximity] * 0.75)],
@@ -760,8 +766,7 @@ class CreatureGenerator
760
766
  )
761
767
  end
762
768
  if options[:breed]
763
- color.green -= 0.1 #Make a bit redder.
764
- color.blue -= 0.1
769
+ color = color ? color + Color.orange : Color.orange
765
770
  creature.behaviors << Behavior.new(
766
771
  :actions => [BreedAction.new(@environment, @breed_rate)],
767
772
  :conditions => [CollisionCondition.new], #The default ProximityCondition won't do.
@@ -769,7 +774,7 @@ class CreatureGenerator
769
774
  )
770
775
  end
771
776
  if options[:eat]
772
- color.green += 1
777
+ color = color ? color + Color.green : Color.green
773
778
  creature.behaviors << Behavior.new(
774
779
  :actions => [EatAction.new(@environment)],
775
780
  :conditions => [
@@ -780,7 +785,7 @@ class CreatureGenerator
780
785
  )
781
786
  end
782
787
 
783
- creature.color = color
788
+ creature.color = color || Color.white
784
789
 
785
790
  @log.debug "Created creature: #{creature.to_s}"
786
791
 
data/bin/zyps-175 ADDED
@@ -0,0 +1,514 @@
1
+ #!/usr/local/bin/ruby
2
+
3
+ # Copyright 2007 Jay McGavren, jay@mcgavren.com.
4
+ #
5
+ # This file is part of Zyps.
6
+ #
7
+ # Zyps is free software; you can redistribute it and/or modify
8
+ # it under the terms of the GNU Lesser General Public License as published by
9
+ # the Free Software Foundation; either version 3 of the License, or
10
+ # (at your option) any later version.
11
+ #
12
+ # This program is distributed in the hope that it will be useful,
13
+ # but WITHOUT ANY WARRANTY; without even the implied warranty of
14
+ # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15
+ # GNU General Public License for more details.
16
+ #
17
+ # You should have received a copy of the GNU Lesser General Public License
18
+ # along with this program. If not, see <http://www.gnu.org/licenses/>.
19
+
20
+
21
+ gems_loaded = false
22
+ begin
23
+ require 'gtk2'
24
+ require 'optparse'
25
+ require 'zyps'
26
+ require 'zyps/actions'
27
+ require 'zyps/conditions'
28
+ require 'zyps/environmental_factors'
29
+ require 'zyps/remote'
30
+ require 'zyps/views/trails'
31
+ require 'zyps/views/canvas/gtk2'
32
+ rescue LoadError
33
+ if gems_loaded == false
34
+ require 'rubygems'
35
+ gems_loaded = true
36
+ retry
37
+ else
38
+ raise
39
+ end
40
+ end
41
+
42
+
43
+ include Zyps
44
+
45
+
46
+ DEFAULT_VIEW_WIDTH = 800
47
+ DEFAULT_VIEW_HEIGHT = 600
48
+ DEFAULT_MAX_SPEED = 200
49
+ DEFAULT_MAX_POPULATION = 100
50
+ DEFAULT_FPS = 60
51
+
52
+
53
+ class Application
54
+
55
+ #Port to open service on.
56
+ attr_accessor :uri
57
+ #Maximum allowed number of objects.
58
+ attr_accessor :max_population
59
+ #View dimensions.
60
+ attr_accessor :view_width, :view_height
61
+
62
+ #Create app window, game environment, and view.
63
+ #Set up default values.
64
+ #Takes a hash with these keys and defaults:
65
+ # :uri => nil,
66
+ # :view_width => DEFAULT_VIEW_WIDTH,
67
+ # :view_height => DEFAULT_VIEW_HEIGHT,
68
+ # :fps => DEFAULT_FPS,
69
+ # :max_population => DEFAULT_MAX_POPULATION,
70
+ # :max_speed => DEFAULT_MAX_SPEED,
71
+ # :enclosure => true
72
+ def initialize(options = {})
73
+
74
+ options = {
75
+ :uri => nil,
76
+ :view_width => DEFAULT_VIEW_WIDTH,
77
+ :view_height => DEFAULT_VIEW_HEIGHT,
78
+ :fps => DEFAULT_FPS,
79
+ :max_population => DEFAULT_MAX_POPULATION,
80
+ :max_speed => DEFAULT_MAX_SPEED,
81
+ :enclosure => true
82
+ }.merge(options)
83
+
84
+ @uri, @view_width, @view_height, @fps, @max_population, @max_speed, @enclosure =
85
+ options[:uri], options[:view_width], options[:view_height], options[:fps], options[:max_population], options[:max_speed], options[:enclosure]
86
+
87
+ end
88
+
89
+
90
+ def main
91
+
92
+ #Create a window, and set GTK up to quit when it is closed.
93
+ window = Gtk::Window.new
94
+ window.resizable = false
95
+ window.signal_connect("delete_event") {false}
96
+ window.signal_connect("destroy") {Gtk.main_quit}
97
+
98
+ #Create environment.
99
+ @environment = Environment.new
100
+
101
+ #Set up controls.
102
+ #Also initializes @view.
103
+ window.add(
104
+ create_controls(
105
+ :view_width => @view_width,
106
+ :view_height => @view_height,
107
+ :spacing => 2
108
+ )
109
+ )
110
+
111
+ #Show all widgets.
112
+ window.show_all
113
+
114
+ #Point view at environment.
115
+ @environment.add_observer(@view)
116
+
117
+ #Keep objects on screen.
118
+ if @enclosure
119
+ enclosure = Enclosure.new(
120
+ :left => 0,
121
+ :bottom => 0,
122
+ :top => @view_height,
123
+ :right => @view_width
124
+ )
125
+ @environment.environmental_factors << enclosure
126
+ end
127
+
128
+ #Keep all objects under a certain speed.
129
+ @environment.environmental_factors << SpeedLimit.new(@max_speed) if @max_speed
130
+
131
+ #Limit population.
132
+ @environment.environmental_factors << PopulationLimit.new(@max_population) if @max_population
133
+
134
+ #Set up a creature generator.
135
+ @generator = CreatureGenerator.new(@environment)
136
+
137
+ #Create thread to update environment.
138
+ thread = Thread.new do
139
+
140
+ begin
141
+
142
+ drawing_clock = Clock.new
143
+ time_per_frame = 1.0 / @fps
144
+
145
+ loop do
146
+
147
+ @environment.interact
148
+
149
+ #Determine how much time is left in this frame.
150
+ time_left_in_frame = (time_per_frame) - drawing_clock.elapsed_time
151
+ #Sleep for the remaining time.
152
+ if time_left_in_frame > 0
153
+ sleep time_left_in_frame
154
+ #Skip a frame if things are going too slow.
155
+ else
156
+ sleep time_per_frame
157
+ end
158
+
159
+ end
160
+
161
+ rescue Exception => exception
162
+ puts exception, exception.backtrace
163
+ end
164
+
165
+ end
166
+
167
+
168
+ #Start a network service.
169
+ if @uri
170
+ server = EnvironmentServer.new(@environment, @uri)
171
+ server.start
172
+ #Disable file system access.
173
+ $SAFE = 2
174
+ end
175
+
176
+
177
+ #Activate the GUI.
178
+ Gtk.main
179
+
180
+ end
181
+
182
+
183
+ #Create a view and controls.
184
+ #Takes a hash with these defaults:
185
+ # :view_width => @view_width
186
+ # :view_height => @view_height
187
+ # :homogeneous => false
188
+ # :spacing => 0
189
+ # :expand => false
190
+ # :fill => false
191
+ # :padding => 0
192
+ def create_controls(options = {})
193
+
194
+ options = {
195
+ :view_width => @view_width,
196
+ :view_height => @view_height,
197
+ :homogeneous => false,
198
+ :spacing => 0,
199
+ :expand => false,
200
+ :fill => false,
201
+ :padding => 0,
202
+ }.merge(options)
203
+
204
+ #Create a container for the view and controls.
205
+ interface = Gtk::HBox.new(options[:homogeneous], options[:spacing])
206
+
207
+ #Add view to interface.
208
+ @view = TrailsView.new(
209
+ :width => options[:view_width],
210
+ :height => options[:view_height],
211
+ :trail_length => 5
212
+ )
213
+ drawing_window = Gtk::DrawingArea.new
214
+ @view.canvas = GTK2Canvas.new(drawing_window)
215
+ interface.pack_start(drawing_window, options[:expand], options[:fill], options[:padding])
216
+
217
+ #When mouse button pressed, record location for use in release event handler.
218
+ drawing_window.add_events(Gdk::Event::BUTTON_PRESS_MASK)
219
+ drawing_window.signal_connect("button-press-event") do |canvas, event|
220
+ @press_location = Location.new(event.x, event.y)
221
+ end
222
+
223
+ #Create a creature on button release.
224
+ drawing_window.add_events(Gdk::Event::BUTTON_RELEASE_MASK)
225
+ drawing_window.signal_connect("button-release-event") do |canvas, event|
226
+ #Ensure the mouse was pressed within the canvas.
227
+ if @press_location
228
+ #Create creature at release location.
229
+ @release_location = Location.new(event.x, event.y)
230
+ @generator.create_creature(
231
+ :x => event.x,
232
+ :y => event.y,
233
+ :speed => Utility.find_distance(@press_location, @release_location) * 2, #Use distance dragged as speed.
234
+ :pitch => Utility.find_angle(@press_location, @release_location), #Move in direction of drag.
235
+ :turn => @turn_flag.active?,
236
+ :approach => @approach_flag.active?,
237
+ :flee => @flee_flag.active?,
238
+ :push => @push_flag.active?,
239
+ :pull => @pull_flag.active?,
240
+ :breed => @breed_flag.active?,
241
+ :eat => @eat_flag.active?
242
+ )
243
+ #Nullify press location, as it is no longer applicable.
244
+ @press_location = nil
245
+ end
246
+ end
247
+
248
+ #Create a VBox for all controls.
249
+ control_panel = Gtk::VBox.new(options[:homogeneous], options[:spacing])
250
+
251
+ #Create a group for the actions.
252
+ action_controls = Gtk::VBox.new(options[:homogeneous], options[:spacing])
253
+ action_controls.pack_start(Gtk::Label.new("Actions"), options[:expand], options[:fill], options[:padding])
254
+ @turn_flag = Gtk::CheckButton.new("Turn")
255
+ action_controls.pack_start(@turn_flag, options[:expand], options[:fill], options[:padding])
256
+ @approach_flag = Gtk::CheckButton.new("Chase")
257
+ action_controls.pack_start(@approach_flag, options[:expand], options[:fill], options[:padding])
258
+ @flee_flag = Gtk::CheckButton.new("Flee")
259
+ action_controls.pack_start(@flee_flag, options[:expand], options[:fill], options[:padding])
260
+ @push_flag = Gtk::CheckButton.new("Push")
261
+ action_controls.pack_start(@push_flag, options[:expand], options[:fill], options[:padding])
262
+ @pull_flag = Gtk::CheckButton.new("Pull")
263
+ action_controls.pack_start(@pull_flag, options[:expand], options[:fill], options[:padding])
264
+ @breed_flag = Gtk::CheckButton.new("Breed")
265
+ action_controls.pack_start(@breed_flag, options[:expand], options[:fill], options[:padding])
266
+ @eat_flag = Gtk::CheckButton.new("Eat")
267
+ action_controls.pack_start(@eat_flag, options[:expand], options[:fill], options[:padding])
268
+ #Add the action controls to the panel.
269
+ control_panel.pack_start(action_controls, options[:expand], options[:fill], options[:padding])
270
+
271
+ #Create a group for environment controls.
272
+ environment_controls = Gtk::VBox.new(options[:homogeneous], options[:spacing])
273
+ environment_controls.pack_start(Gtk::Label.new("Length"), options[:expand], options[:fill], options[:padding])
274
+ @trail_length_slider = Gtk::HScale.new(2, 100, 1)
275
+ @trail_length_slider.signal_connect("value-changed") {
276
+ @view.trail_length = @trail_length_slider.value
277
+ }
278
+ @trail_length_slider.value = 5
279
+ environment_controls.pack_start(@trail_length_slider, options[:expand], options[:fill], options[:padding])
280
+ @trails_flag = Gtk::CheckButton.new("Trails")
281
+ @trails_flag.signal_connect("toggled") {
282
+ @view.erase_flag = ! @trails_flag.active?
283
+ }
284
+ @trails_flag.active = false
285
+ environment_controls.pack_start(@trails_flag, options[:expand], options[:fill], options[:padding])
286
+ @clear_button = Gtk::Button.new("Clear")
287
+ @clear_button.signal_connect("clicked") {
288
+ @environment.objects = []
289
+ }
290
+ environment_controls.pack_start(@clear_button, options[:expand], options[:fill], options[:padding])
291
+ #Add the environment controls to the BOTTOM of the panel.
292
+ control_panel.pack_end(environment_controls, options[:expand], options[:fill], options[:padding])
293
+
294
+ #Add the control panel to the interface.
295
+ interface.pack_start(control_panel, options[:expand], options[:fill], options[:padding])
296
+
297
+ interface
298
+
299
+ end
300
+
301
+
302
+ #Set attributes according to command-line arguments.
303
+ def process_options(arguments)
304
+
305
+ #Set up option parser.
306
+ options = OptionParser.new
307
+
308
+ #Define valid options.
309
+ options.on("-h", "--help", TrueClass, "Display program help.") {
310
+ puts options.help
311
+ exit
312
+ }
313
+ options.on(
314
+ "-m",
315
+ "--max-population [number]",
316
+ Integer,
317
+ "The maximum number of allowed game objects. #{DEFAULT_MAX_POPULATION} by default."
318
+ ) {|value| @max_population = value}
319
+ options.on(
320
+ "-s",
321
+ "--max-speed [number]",
322
+ Integer,
323
+ "The fastest an object can go. #{DEFAULT_MAX_SPEED ? DEFAULT_MAX_SPEED : 'No limit'} by default."
324
+ ) {|value| @max_speed = value}
325
+ options.on(
326
+ "-n",
327
+ "--no-enclosure",
328
+ "Disables the barrier that normally keeps objects on the screen."
329
+ ) {|value| @enclosure = false}
330
+ options.on(
331
+ "-u",
332
+ "--uri [uri]",
333
+ String,
334
+ "URI to serve the environment on via dRuby. If not specified, no server will be started."
335
+ ) {|value| @uri = value}
336
+ options.on(
337
+ "-f",
338
+ "--fps [frames]",
339
+ Integer,
340
+ "Number of frames to draw per second. #{DEFAULT_FPS} by default."
341
+ ) {|value| @fps = value}
342
+ options.on(
343
+ "--view-width [pixels]",
344
+ Integer,
345
+ "Window width. #{DEFAULT_VIEW_WIDTH} by default."
346
+ ) {|value| @view_width = value}
347
+ options.on(
348
+ "--view-height [pixels]",
349
+ Integer,
350
+ "Window height. #{DEFAULT_VIEW_HEIGHT} by default."
351
+ ) {|value| @view_height = value}
352
+
353
+ #Parse the options, printing usage if parsing fails.
354
+ options.parse(arguments) rescue puts "#{$!}\nType '#{$0} --help' for valid options."
355
+
356
+ end
357
+
358
+
359
+ end
360
+
361
+
362
+
363
+ class CreatureGenerator
364
+
365
+ #Environment creatures will be added to.
366
+ attr_accessor :environment
367
+ #Default required proximity for actions.
368
+ attr_accessor :default_proximity
369
+ #Rate of new TurnActions.
370
+ attr_accessor :turn_rate
371
+ #Acceleration rate of new ApproachActions.
372
+ attr_accessor :approach_rate
373
+ #Acceleration rate of new FleeActions.
374
+ attr_accessor :flee_rate
375
+ #Strength of new PullActions.
376
+ attr_accessor :pull_strength
377
+ #Strength of new PushActions.
378
+ attr_accessor :push_strength
379
+
380
+ def initialize(environment)
381
+
382
+ @environment = environment
383
+
384
+ #Set up defaults for attributes.
385
+ @default_proximity = 200
386
+ @approach_rate = 200
387
+ @flee_rate = @approach_rate
388
+ @push_strength = @approach_rate * 2
389
+ @pull_strength = @push_strength * 0.75
390
+ @turn_rate = @approach_rate * 1.1
391
+ @turn_angle = 90
392
+ @breed_rate = 10
393
+
394
+ end
395
+
396
+
397
+ #Create a creature and add it to the environment.
398
+ def create_creature(options = {})
399
+
400
+ options = {
401
+ :x => 0,
402
+ :y => 0,
403
+ :speed => 1,
404
+ :pitch => 0,
405
+ :action_proximity => @default_proximity,
406
+ :turn => false,
407
+ :approach => false,
408
+ :flee => false,
409
+ :push => false,
410
+ :pull => false,
411
+ :breed => false,
412
+ :eat => false,
413
+ }.merge(options)
414
+
415
+ #Create a creature.
416
+ creature = Creature.new(
417
+ :location => Location.new(options[:x], options[:y]),
418
+ :vector => Vector.new(options[:speed], options[:pitch]),
419
+ :size => 5
420
+ )
421
+
422
+ #Set up actions and merge colors according to selected behaviors.
423
+ color = Color.new(0.25, 0.25, 0.25)
424
+ if options[:turn]
425
+ color.blue += 1
426
+ creature.behaviors << Behavior.new(
427
+ :actions => [TurnAction.new(@turn_rate, @turn_angle)],
428
+ :conditions => [ProximityCondition.new(options[:action_proximity] * 2)]
429
+ )
430
+ end
431
+ if options[:approach]
432
+ color.red += 1
433
+ creature.behaviors << create_behavior(
434
+ :actions => [ApproachAction.new(@approach_rate)],
435
+ :conditions => [ProximityCondition.new(options[:action_proximity])]
436
+ )
437
+ end
438
+ if options[:flee]
439
+ color.red += 0.5; color.green += 0.5 #Yellow.
440
+ creature.behaviors << create_behavior(
441
+ :actions => [FleeAction.new(@flee_rate)],
442
+ :conditions => [ProximityCondition.new(options[:action_proximity] * 0.5)]
443
+ )
444
+ end
445
+ if options[:push]
446
+ color.red += 0.5; color.blue += 0.5 #Purple.
447
+ creature.behaviors << create_behavior(
448
+ :actions => [PushAction.new(@push_strength)],
449
+ :conditions => [ProximityCondition.new(options[:action_proximity] * 0.25)]
450
+ )
451
+ end
452
+ if options[:pull]
453
+ color.blue += 0.75; color.green += 0.75 #Aqua.
454
+ creature.behaviors << create_behavior(
455
+ :actions => [PullAction.new(@pull_strength)],
456
+ :conditions => [ProximityCondition.new(options[:action_proximity] * 0.75)]
457
+ )
458
+ end
459
+ if options[:breed]
460
+ color.green -= 0.1 #Make a bit redder.
461
+ color.blue -= 0.1
462
+ creature.behaviors << create_behavior(
463
+ :actions => [BreedAction.new(@environment, @breed_rate)],
464
+ :conditions => [CollisionCondition.new] #The default ProximityCondition won't do.
465
+ )
466
+ end
467
+ if options[:eat]
468
+ color.green += 1
469
+ creature.behaviors << create_behavior(
470
+ :actions => [EatAction.new(@environment)],
471
+ :conditions => [
472
+ CollisionCondition.new, #The default ProximityCondition won't do.
473
+ StrengthCondition.new #The eater should be as strong or stronger than its dinner.
474
+ ]
475
+ )
476
+ end
477
+
478
+ creature.color = color
479
+
480
+ @environment.objects << creature
481
+
482
+ end
483
+
484
+
485
+ def create_behavior(options = {})
486
+
487
+ options = {
488
+ :actions => [],
489
+ :conditions => [ProximityCondition.new(@default_proximity)],
490
+ }.merge(options)
491
+
492
+ behavior = Behavior.new
493
+ behavior.actions = options[:actions]
494
+ behavior.conditions = options[:conditions]
495
+ behavior
496
+
497
+ end
498
+
499
+
500
+ end
501
+
502
+
503
+
504
+ begin
505
+ #Create a server.
506
+ application = Application.new
507
+ #Parse the command line.
508
+ application.process_options(ARGV)
509
+ #Start the server.
510
+ application.main
511
+ rescue => exception
512
+ #Print error to STDERR and exit with an abnormal status.
513
+ abort "Error: " + exception.message + exception.backtrace.join("\n")
514
+ end