zyps 0.7.5 → 0.7.6

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