the-swarm 1.0.3
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.
- checksums.yaml +7 -0
- data/.gitignore +3 -0
- data/.yardopts +8 -0
- data/Gemfile +24 -0
- data/LICENSE.txt +22 -0
- data/README.md +35 -0
- data/Rakefile +26 -0
- data/bin/swarm +11 -0
- data/docs/Swarm.html +296 -0
- data/docs/Swarm/Catalog.html +819 -0
- data/docs/Swarm/Console.html +1050 -0
- data/docs/Swarm/Console/Color.html +160 -0
- data/docs/Swarm/Console/NormalKey.html +410 -0
- data/docs/Swarm/Console/PopUp.html +236 -0
- data/docs/Swarm/Console/VIKey.html +410 -0
- data/docs/Swarm/Five.html +421 -0
- data/docs/Swarm/Four.html +389 -0
- data/docs/Swarm/Game.html +1197 -0
- data/docs/Swarm/Intro.html +419 -0
- data/docs/Swarm/Level.html +700 -0
- data/docs/Swarm/Map.html +2336 -0
- data/docs/Swarm/One.html +353 -0
- data/docs/Swarm/Three.html +383 -0
- data/docs/Swarm/Tile.html +3823 -0
- data/docs/Swarm/Two.html +355 -0
- data/docs/_index.html +313 -0
- data/docs/class_list.html +51 -0
- data/docs/css/common.css +1 -0
- data/docs/css/full_list.css +58 -0
- data/docs/css/style.css +492 -0
- data/docs/file.LICENSE.html +70 -0
- data/docs/file.README.html +101 -0
- data/docs/file_list.html +61 -0
- data/docs/frames.html +17 -0
- data/docs/index.html +101 -0
- data/docs/js/app.js +248 -0
- data/docs/js/full_list.js +216 -0
- data/docs/js/jquery.js +4 -0
- data/docs/method_list.html +1195 -0
- data/docs/top-level-namespace.html +110 -0
- data/lib/swarm.rb +60 -0
- data/lib/swarm/catalog.rb +71 -0
- data/lib/swarm/console.rb +165 -0
- data/lib/swarm/game.rb +173 -0
- data/lib/swarm/level.rb +58 -0
- data/lib/swarm/levels/five.rb +71 -0
- data/lib/swarm/levels/four.rb +55 -0
- data/lib/swarm/levels/intro.rb +36 -0
- data/lib/swarm/levels/one.rb +35 -0
- data/lib/swarm/levels/three.rb +51 -0
- data/lib/swarm/levels/two.rb +38 -0
- data/lib/swarm/map.rb +254 -0
- data/lib/swarm/tile.rb +149 -0
- data/lib/swarm/version.rb +5 -0
- data/swarm.gemspec +24 -0
- metadata +112 -0
@@ -0,0 +1,110 @@
|
|
1
|
+
<!DOCTYPE html>
|
2
|
+
<html>
|
3
|
+
<head>
|
4
|
+
<meta charset="utf-8">
|
5
|
+
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
6
|
+
<title>
|
7
|
+
Top Level Namespace
|
8
|
+
|
9
|
+
— "Swarm" Source Code Documentation
|
10
|
+
|
11
|
+
</title>
|
12
|
+
|
13
|
+
<link rel="stylesheet" href="css/style.css" type="text/css" charset="utf-8" />
|
14
|
+
|
15
|
+
<link rel="stylesheet" href="css/common.css" type="text/css" charset="utf-8" />
|
16
|
+
|
17
|
+
<script type="text/javascript" charset="utf-8">
|
18
|
+
pathId = "";
|
19
|
+
relpath = '';
|
20
|
+
</script>
|
21
|
+
|
22
|
+
|
23
|
+
<script type="text/javascript" charset="utf-8" src="js/jquery.js"></script>
|
24
|
+
|
25
|
+
<script type="text/javascript" charset="utf-8" src="js/app.js"></script>
|
26
|
+
|
27
|
+
|
28
|
+
</head>
|
29
|
+
<body>
|
30
|
+
<div class="nav_wrap">
|
31
|
+
<iframe id="nav" src="class_list.html?1"></iframe>
|
32
|
+
<div id="resizer"></div>
|
33
|
+
</div>
|
34
|
+
|
35
|
+
<div id="main" tabindex="-1">
|
36
|
+
<div id="header">
|
37
|
+
<div id="menu">
|
38
|
+
|
39
|
+
<a href="_index.html">Index</a> »
|
40
|
+
|
41
|
+
|
42
|
+
<span class="title">Top Level Namespace</span>
|
43
|
+
|
44
|
+
</div>
|
45
|
+
|
46
|
+
<div id="search">
|
47
|
+
|
48
|
+
<a class="full_list_link" id="class_list_link"
|
49
|
+
href="class_list.html">
|
50
|
+
|
51
|
+
<svg width="24" height="24">
|
52
|
+
<rect x="0" y="4" width="24" height="4" rx="1" ry="1"></rect>
|
53
|
+
<rect x="0" y="12" width="24" height="4" rx="1" ry="1"></rect>
|
54
|
+
<rect x="0" y="20" width="24" height="4" rx="1" ry="1"></rect>
|
55
|
+
</svg>
|
56
|
+
</a>
|
57
|
+
|
58
|
+
</div>
|
59
|
+
<div class="clear"></div>
|
60
|
+
</div>
|
61
|
+
|
62
|
+
<div id="content"><h1>Top Level Namespace
|
63
|
+
|
64
|
+
|
65
|
+
|
66
|
+
</h1>
|
67
|
+
<div class="box_info">
|
68
|
+
|
69
|
+
|
70
|
+
|
71
|
+
|
72
|
+
|
73
|
+
|
74
|
+
|
75
|
+
|
76
|
+
|
77
|
+
|
78
|
+
|
79
|
+
</div>
|
80
|
+
|
81
|
+
<h2>Defined Under Namespace</h2>
|
82
|
+
<p class="children">
|
83
|
+
|
84
|
+
|
85
|
+
<strong class="modules">Modules:</strong> <span class='object_link'><a href="Swarm.html" title="Swarm (module)">Swarm</a></span>
|
86
|
+
|
87
|
+
|
88
|
+
|
89
|
+
|
90
|
+
</p>
|
91
|
+
|
92
|
+
|
93
|
+
|
94
|
+
|
95
|
+
|
96
|
+
|
97
|
+
|
98
|
+
|
99
|
+
|
100
|
+
</div>
|
101
|
+
|
102
|
+
<div id="footer">
|
103
|
+
Generated on Wed Aug 30 07:17:58 2017 by
|
104
|
+
<a href="http://yardoc.org" title="Yay! A Ruby Documentation Tool" target="_parent">yard</a>
|
105
|
+
0.9.9 (ruby-2.4.1).
|
106
|
+
</div>
|
107
|
+
|
108
|
+
</div>
|
109
|
+
</body>
|
110
|
+
</html>
|
data/lib/swarm.rb
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
require 'curses'
|
2
|
+
require 'io/console'
|
3
|
+
|
4
|
+
$LOAD_PATH.unshift __dir__
|
5
|
+
|
6
|
+
require 'swarm/console'
|
7
|
+
require 'swarm/game'
|
8
|
+
require 'swarm/map'
|
9
|
+
require 'swarm/catalog'
|
10
|
+
|
11
|
+
require 'swarm/tile'
|
12
|
+
|
13
|
+
require 'swarm/level'
|
14
|
+
require 'swarm/levels/intro'
|
15
|
+
require 'swarm/levels/one'
|
16
|
+
require 'swarm/levels/two'
|
17
|
+
require 'swarm/levels/three'
|
18
|
+
require 'swarm/levels/four'
|
19
|
+
require 'swarm/levels/five'
|
20
|
+
|
21
|
+
require 'swarm/version'
|
22
|
+
|
23
|
+
# Namespace for classes and modules of the +Swarm+ application.
|
24
|
+
module Swarm
|
25
|
+
|
26
|
+
# Initialize the console, launch the game, play the game, print the
|
27
|
+
# scoreboard and exit to the shell.
|
28
|
+
#
|
29
|
+
# @return [Kernel#exit] exit to shell with success/failure status code
|
30
|
+
def self.start
|
31
|
+
Signal.trap('INT') { game.stop } # Ctrl-C stops the game gracefully
|
32
|
+
|
33
|
+
game = Game.new
|
34
|
+
|
35
|
+
Console.open do
|
36
|
+
|
37
|
+
game.start
|
38
|
+
|
39
|
+
Level.each do |level|
|
40
|
+
next if game.over?
|
41
|
+
|
42
|
+
game.setup! level
|
43
|
+
game.show!
|
44
|
+
game.play! until game.over? || level.over?
|
45
|
+
end
|
46
|
+
|
47
|
+
game.stop
|
48
|
+
end
|
49
|
+
|
50
|
+
puts game
|
51
|
+
|
52
|
+
exit true # success!
|
53
|
+
rescue => error
|
54
|
+
Console.close
|
55
|
+
|
56
|
+
warn 'Swarm encountered an unhandled error'
|
57
|
+
warn error.message, *error.backtrace
|
58
|
+
exit false # failure!
|
59
|
+
end
|
60
|
+
end
|
@@ -0,0 +1,71 @@
|
|
1
|
+
module Swarm
|
2
|
+
class Catalog
|
3
|
+
|
4
|
+
class << self
|
5
|
+
|
6
|
+
def count(key)
|
7
|
+
instance.synchronize { |categories| categories[key].count }
|
8
|
+
end
|
9
|
+
|
10
|
+
def fetch(key, value, default = nil)
|
11
|
+
instance.synchronize { |categories| categories[key].fetch value, default }
|
12
|
+
end
|
13
|
+
|
14
|
+
def increment(key, value)
|
15
|
+
instance.synchronize do |categories|
|
16
|
+
categories[key][value] ||= 0
|
17
|
+
categories[key][value] += 1
|
18
|
+
end
|
19
|
+
end
|
20
|
+
|
21
|
+
def store(key, value)
|
22
|
+
instance.synchronize { |categories| categories[key].store value, true }
|
23
|
+
end
|
24
|
+
|
25
|
+
def delete(key, value)
|
26
|
+
instance.synchronize { |categories| categories[key].delete value }
|
27
|
+
end
|
28
|
+
|
29
|
+
def flush(key, fetch: :keys)
|
30
|
+
instance.synchronize do |categories|
|
31
|
+
result = categories.delete(key)
|
32
|
+
result ||= Hash.new
|
33
|
+
result.send fetch
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
def select(*keys, fetch: :keys)
|
38
|
+
instance.synchronize do |categories|
|
39
|
+
keys.flat_map { |key| categories[key].send fetch }
|
40
|
+
end
|
41
|
+
end
|
42
|
+
|
43
|
+
def clear(key)
|
44
|
+
instance.synchronize { |categories| categories[key].clear }
|
45
|
+
end
|
46
|
+
|
47
|
+
def instance
|
48
|
+
@instance ||= new
|
49
|
+
end
|
50
|
+
|
51
|
+
private :new,
|
52
|
+
:instance
|
53
|
+
end
|
54
|
+
|
55
|
+
def synchronize
|
56
|
+
yield categories
|
57
|
+
# transaction.synchronize { yield categories }
|
58
|
+
end
|
59
|
+
|
60
|
+
private
|
61
|
+
|
62
|
+
def transaction
|
63
|
+
@transaction ||= Mutex.new
|
64
|
+
end
|
65
|
+
|
66
|
+
def categories
|
67
|
+
@categories ||= Hash.new { |h, k| h[k] = Hash.new }
|
68
|
+
end
|
69
|
+
end
|
70
|
+
end
|
71
|
+
|
@@ -0,0 +1,165 @@
|
|
1
|
+
module Swarm
|
2
|
+
|
3
|
+
module Console
|
4
|
+
|
5
|
+
module Color
|
6
|
+
BLACK = 234
|
7
|
+
SILVER = 240
|
8
|
+
WHITE = 248
|
9
|
+
GREY = 237
|
10
|
+
RED = 167
|
11
|
+
PURPLE = 104
|
12
|
+
GREEN = 120
|
13
|
+
BLUE = 39
|
14
|
+
YELLOW = 186
|
15
|
+
end
|
16
|
+
|
17
|
+
module NormalKey
|
18
|
+
def up; @up ||= Curses::Key::UP end
|
19
|
+
def down; @down ||= Curses::Key::DOWN end
|
20
|
+
def left; @left ||= Curses::Key::LEFT end
|
21
|
+
def right; @right ||= Curses::Key::RIGHT end
|
22
|
+
|
23
|
+
def pause; @pause ||= ?\s.freeze end
|
24
|
+
def quit; @quit ||= ?q.freeze end
|
25
|
+
end
|
26
|
+
|
27
|
+
module VIKey
|
28
|
+
def up; @up ||= ?k.freeze end
|
29
|
+
def down; @down ||= ?j.freeze end
|
30
|
+
def left; @left ||= ?h.freeze end
|
31
|
+
def right; @right ||= ?l.freeze end
|
32
|
+
|
33
|
+
def pause; @pause ||= ?\s.freeze end
|
34
|
+
def quit; @quit ||= ?q.freeze end
|
35
|
+
end
|
36
|
+
|
37
|
+
include Curses
|
38
|
+
include Color
|
39
|
+
|
40
|
+
class PopUp < Window
|
41
|
+
|
42
|
+
def initialize(message, indent: 2)
|
43
|
+
lines = message.split(?\n)
|
44
|
+
height = 2 + lines.count
|
45
|
+
max = lines.map(&:length).max
|
46
|
+
width = max + (indent*2)
|
47
|
+
|
48
|
+
super height,
|
49
|
+
width,
|
50
|
+
(Console.height/2) - (height/2),
|
51
|
+
(Console.width/2) - (max/2) - indent
|
52
|
+
|
53
|
+
box ?|, ?-, ?+
|
54
|
+
|
55
|
+
lines.each.with_index do |line, index|
|
56
|
+
setpos (index + 1), 2
|
57
|
+
addstr line.center(max)
|
58
|
+
end
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
attr_reader :key_info
|
63
|
+
|
64
|
+
extend self
|
65
|
+
|
66
|
+
def init_keys
|
67
|
+
nonl
|
68
|
+
noecho # don't echo keypresses
|
69
|
+
stdscr.nodelay = -1 # don't wait for input, just listen for it
|
70
|
+
stdscr.keypad true
|
71
|
+
|
72
|
+
@key_info = {pause: '<SPACEBAR>', quit: ?q}
|
73
|
+
|
74
|
+
if ENV.fetch('SWARM', 'VIM_MODE') == 'easy'
|
75
|
+
extend NormalKey
|
76
|
+
|
77
|
+
@key_info.merge! north: '<UP>', south: '<DOWN>', west: '<LEFT>', east: '<RIGHT>'
|
78
|
+
else
|
79
|
+
extend VIKey
|
80
|
+
|
81
|
+
@key_info.merge! north: ?k, south: ?j, west: ?h, east: ?l
|
82
|
+
end
|
83
|
+
end
|
84
|
+
|
85
|
+
def init_colors
|
86
|
+
start_color
|
87
|
+
use_default_colors
|
88
|
+
|
89
|
+
#id #fg #bg
|
90
|
+
init_pair BLACK, BLACK, BLACK
|
91
|
+
init_pair SILVER, SILVER, SILVER
|
92
|
+
init_pair WHITE, WHITE, WHITE
|
93
|
+
init_pair GREY, GREY, GREY
|
94
|
+
init_pair RED, RED, BLACK
|
95
|
+
init_pair PURPLE, PURPLE, BLACK
|
96
|
+
init_pair GREEN, GREEN, BLACK
|
97
|
+
init_pair BLUE, BLUE, BLACK
|
98
|
+
init_pair YELLOW, YELLOW, BLACK
|
99
|
+
end
|
100
|
+
|
101
|
+
# @yieldparam command [String] yields +command+ on keypress
|
102
|
+
def keypress
|
103
|
+
command = getch and yield(command)
|
104
|
+
end
|
105
|
+
|
106
|
+
# @macro swarm.console.dimensions
|
107
|
+
# @return [Integer] +$0+ of console
|
108
|
+
|
109
|
+
# @macro swarm.console.dimensions
|
110
|
+
def width
|
111
|
+
@width ||= cols
|
112
|
+
end
|
113
|
+
|
114
|
+
# @macro swarm.console.dimensions
|
115
|
+
def height
|
116
|
+
@height ||= lines
|
117
|
+
end
|
118
|
+
|
119
|
+
# Redraw all +tiles+ given and refresh the console
|
120
|
+
# @param tiles [Array<Tile, ...>]
|
121
|
+
def update(tiles)
|
122
|
+
tiles.each &method(:draw)
|
123
|
+
refresh
|
124
|
+
end
|
125
|
+
|
126
|
+
# @param color [Integer] 0 to 8
|
127
|
+
# @param x [Integer]
|
128
|
+
# @param y [Integer]
|
129
|
+
def draw(tile)
|
130
|
+
setpos *tile.location
|
131
|
+
|
132
|
+
attron(color_pair tile.color) { addstr tile.icon }
|
133
|
+
end
|
134
|
+
|
135
|
+
def wipe
|
136
|
+
clear
|
137
|
+
refresh
|
138
|
+
end
|
139
|
+
|
140
|
+
# Turn line buffering on and close the +Curses+ session.
|
141
|
+
def close
|
142
|
+
return if closed?
|
143
|
+
|
144
|
+
nocbreak
|
145
|
+
close_screen
|
146
|
+
end
|
147
|
+
|
148
|
+
# Initialize the +Curses+ environment, configure it and then clean up
|
149
|
+
# when the caller is done. 9 different bg/fg pairs are initialized for
|
150
|
+
# the colored +Tile+ squares (0-8): (black, red, green, yellow, blue,
|
151
|
+
# magenta, cyan, white, grey)
|
152
|
+
def open
|
153
|
+
init_screen
|
154
|
+
init_colors
|
155
|
+
init_keys
|
156
|
+
|
157
|
+
curs_set 0 # hide the cursor
|
158
|
+
cbreak # turn off line buffering
|
159
|
+
|
160
|
+
yield
|
161
|
+
|
162
|
+
close
|
163
|
+
end
|
164
|
+
end
|
165
|
+
end
|
data/lib/swarm/game.rb
ADDED
@@ -0,0 +1,173 @@
|
|
1
|
+
module Swarm
|
2
|
+
|
3
|
+
class Game
|
4
|
+
|
5
|
+
REFRESH_RATE = 0.05 # This seems to keep the laptop under 750°.
|
6
|
+
|
7
|
+
def play!
|
8
|
+
turn = Time.now.to_f
|
9
|
+
|
10
|
+
@player = @level.find_player
|
11
|
+
@player ||= spawn_player
|
12
|
+
|
13
|
+
listen_for_keypress
|
14
|
+
|
15
|
+
unless @popup
|
16
|
+
if (turn - @turn) >= @rate
|
17
|
+
|
18
|
+
@level.play
|
19
|
+
|
20
|
+
@turn = turn
|
21
|
+
end
|
22
|
+
|
23
|
+
@level.update
|
24
|
+
end
|
25
|
+
|
26
|
+
sleep REFRESH_RATE
|
27
|
+
end
|
28
|
+
|
29
|
+
# Set the "start game" flag.
|
30
|
+
#
|
31
|
+
# @return [true]
|
32
|
+
def start
|
33
|
+
@status = true
|
34
|
+
|
35
|
+
true
|
36
|
+
end
|
37
|
+
|
38
|
+
# Set the "stop game" flag.
|
39
|
+
#
|
40
|
+
# @return [true]
|
41
|
+
def stop
|
42
|
+
@status = false
|
43
|
+
|
44
|
+
true
|
45
|
+
end
|
46
|
+
|
47
|
+
# @return [Boolean]
|
48
|
+
def stopped?
|
49
|
+
!@status
|
50
|
+
end
|
51
|
+
|
52
|
+
# A game is "over" when any of these conditions are met
|
53
|
+
#
|
54
|
+
# - the game has been stopped via {Game#stop}
|
55
|
+
# - all of the player's lives are gone
|
56
|
+
# - all of the invaders are dead
|
57
|
+
#
|
58
|
+
# @return [Boolean]
|
59
|
+
def over?
|
60
|
+
stopped? || @players.zero?
|
61
|
+
end
|
62
|
+
|
63
|
+
# @return [String]
|
64
|
+
def to_s
|
65
|
+
<<-TO_S.gsub(/^[ ]{8}/, '') % statistics
|
66
|
+
GAME OVER!
|
67
|
+
|
68
|
+
+ %<eggs>4i x oo (eggs) squished (x20)
|
69
|
+
+ %<workers>4i x ├┤ (workers) killed (x20)
|
70
|
+
+ %<soldiers>4i x ╟╢ (soldiers) crushed (x50)
|
71
|
+
+ %<queens>4i x ╬╬ (queens) defeated (x50)
|
72
|
+
|
73
|
+
- %<deaths>4i x ◄▶ (players) destroyed (x100)
|
74
|
+
-------------------------------
|
75
|
+
%<points>6i points
|
76
|
+
TO_S
|
77
|
+
end
|
78
|
+
|
79
|
+
def pause
|
80
|
+
if @popup
|
81
|
+
@popup.close
|
82
|
+
@popup = false
|
83
|
+
|
84
|
+
@level.update!
|
85
|
+
else
|
86
|
+
@popup = Console::PopUp.new(yield)
|
87
|
+
@popup.refresh
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
def setup!(level)
|
92
|
+
@level = level
|
93
|
+
@level.define_singleton_method(:pause, &method(:pause))
|
94
|
+
|
95
|
+
@popup = false
|
96
|
+
|
97
|
+
@status = true
|
98
|
+
@turn = Time.now.to_f
|
99
|
+
|
100
|
+
@level.setup
|
101
|
+
end
|
102
|
+
|
103
|
+
def show!
|
104
|
+
@level.update # update the level and refresh the console before displaying anything
|
105
|
+
|
106
|
+
@level.show(@players)
|
107
|
+
end
|
108
|
+
|
109
|
+
private
|
110
|
+
|
111
|
+
# @return [Hash]
|
112
|
+
def statistics
|
113
|
+
Hash.new(0).tap do |stats|
|
114
|
+
stats[:eggs] += Catalog.fetch(:destroyed, :egg, 0)
|
115
|
+
stats[:workers] += Catalog.fetch(:destroyed, :worker, 0)
|
116
|
+
stats[:soldiers] += Catalog.fetch(:destroyed, :soldier, 0)
|
117
|
+
stats[:queens] += Catalog.fetch(:destroyed, :queen, 0)
|
118
|
+
stats[:deaths] += Catalog.fetch(:destroyed, :player, 0)
|
119
|
+
stats[:points] +=
|
120
|
+
(stats[:eggs] * 20) +
|
121
|
+
(stats[:workers] * 20) +
|
122
|
+
(stats[:soldiers] * 50) +
|
123
|
+
(stats[:queens] * 50) -
|
124
|
+
(stats[:deaths] * 100)
|
125
|
+
end
|
126
|
+
end
|
127
|
+
|
128
|
+
# # @return [Tile]
|
129
|
+
# def find_or_spawn_player
|
130
|
+
# find_player || spawn_player
|
131
|
+
# end
|
132
|
+
|
133
|
+
# def find_player
|
134
|
+
# @player = @level.find_player
|
135
|
+
# end
|
136
|
+
|
137
|
+
def spawn_player
|
138
|
+
@players -= 1
|
139
|
+
|
140
|
+
pause do
|
141
|
+
<<-POPUP.gsub(/[ ]{10}/, '') % Console.key_info
|
142
|
+
YOU HAVE BEEN KILLED!
|
143
|
+
----------------------------------------------
|
144
|
+
Press %<pause>s to continue.
|
145
|
+
|
146
|
+
(#@players lives remaining)
|
147
|
+
POPUP
|
148
|
+
end
|
149
|
+
|
150
|
+
@player = @level.spawn_player
|
151
|
+
end
|
152
|
+
|
153
|
+
def listen_for_keypress
|
154
|
+
Console.keypress do |command|
|
155
|
+
case command
|
156
|
+
when Console.up; @popup || @level.move_player(:north)
|
157
|
+
when Console.down; @popup || @level.move_player(:south)
|
158
|
+
when Console.left; @popup || @level.move_player(:west)
|
159
|
+
when Console.right; @popup || @level.move_player(:east)
|
160
|
+
when Console.pause; pause { 'PAUSED' }
|
161
|
+
when Console.quit; stop
|
162
|
+
end
|
163
|
+
STDIN.iflush # prevent command queueing
|
164
|
+
end
|
165
|
+
end
|
166
|
+
|
167
|
+
def initialize
|
168
|
+
@players = 5
|
169
|
+
|
170
|
+
@rate = 2.0
|
171
|
+
end
|
172
|
+
end
|
173
|
+
end
|