gambit 0.1.0
Sign up to get free protection for your applications and to get access to all the features.
- data/AUTHORS +2 -0
- data/CHANGELOG +7 -0
- data/COPYING +340 -0
- data/INSTALL +23 -0
- data/LICENSE +7 -0
- data/README +25 -0
- data/Rakefile +87 -0
- data/TODO +6 -0
- data/examples/bird_wars/game.rb +434 -0
- data/examples/bird_wars/html/chest.rhtml +37 -0
- data/examples/bird_wars/html/combat.rhtml +38 -0
- data/examples/bird_wars/html/fight.rhtml +71 -0
- data/examples/bird_wars/html/fridge.rhtml +31 -0
- data/examples/bird_wars/html/help.rhtml +30 -0
- data/examples/bird_wars/html/house.rhtml +36 -0
- data/examples/bird_wars/html/images/albatross.jpg +0 -0
- data/examples/bird_wars/html/images/alka_seltzer_small.png +0 -0
- data/examples/bird_wars/html/images/bazooka_small.png +0 -0
- data/examples/bird_wars/html/images/bb_gun_small.png +0 -0
- data/examples/bird_wars/html/images/cat_small.png +0 -0
- data/examples/bird_wars/html/images/combat.png +0 -0
- data/examples/bird_wars/html/images/crossbow_small.png +0 -0
- data/examples/bird_wars/html/images/cuckoo.jpg +0 -0
- data/examples/bird_wars/html/images/fridge.png +0 -0
- data/examples/bird_wars/html/images/gull.jpg +0 -0
- data/examples/bird_wars/html/images/house.jpg +0 -0
- data/examples/bird_wars/html/images/items.png +0 -0
- data/examples/bird_wars/html/images/not_found.png +0 -0
- data/examples/bird_wars/html/images/note.jpg +0 -0
- data/examples/bird_wars/html/images/oil_small.png +0 -0
- data/examples/bird_wars/html/images/one_stone_small.png +0 -0
- data/examples/bird_wars/html/images/owl.jpg +0 -0
- data/examples/bird_wars/html/images/poisoned_seeds_small.png +0 -0
- data/examples/bird_wars/html/images/rice_small.png +0 -0
- data/examples/bird_wars/html/images/shotgun_small.png +0 -0
- data/examples/bird_wars/html/images/slingshot_small.png +0 -0
- data/examples/bird_wars/html/images/soda_rings_small.png +0 -0
- data/examples/bird_wars/html/images/spear_small.png +0 -0
- data/examples/bird_wars/html/images/stork.jpg +0 -0
- data/examples/bird_wars/html/images/weapons.png +0 -0
- data/examples/bird_wars/html/images/woodpecker.jpg +0 -0
- data/examples/bird_wars/html/images/you.jpg +0 -0
- data/examples/bird_wars/html/index.rhtml +13 -0
- data/examples/bird_wars/html/weapons.rhtml +35 -0
- data/examples/cli/blackjack.rb +86 -0
- data/examples/cli/go.rb +93 -0
- data/examples/cli/space_trader2/planet_data +12280 -0
- data/examples/cli/space_trader2/space_trader2.rb +248 -0
- data/examples/cli/space_trader2/world.rb +127 -0
- data/examples/cli/spacetrader.rb +262 -0
- data/examples/cli/yahtzee.rb +161 -0
- data/examples/galactic_courier/Rakefile +9 -0
- data/examples/galactic_courier/bin/galactic_courier.rb +44 -0
- data/examples/galactic_courier/html/console.rhtml +15 -0
- data/examples/galactic_courier/html/images/barren.jpg +0 -0
- data/examples/galactic_courier/html/images/industrial.jpg +0 -0
- data/examples/galactic_courier/html/images/jungle.jpg +0 -0
- data/examples/galactic_courier/html/images/oceanic.jpg +0 -0
- data/examples/galactic_courier/html/images/tundra.jpg +0 -0
- data/examples/galactic_courier/html/images/volcanic.jpg +0 -0
- data/examples/galactic_courier/lib/galaxy.rb +64 -0
- data/examples/galactic_courier/lib/planet.rb +30 -0
- data/examples/galactic_courier/lib/sector.rb +84 -0
- data/examples/galactic_courier/lib/station.rb +18 -0
- data/examples/galactic_courier/test/tc_galaxy.rb +24 -0
- data/examples/galactic_courier/test/tc_planet.rb +22 -0
- data/examples/galactic_courier/test/tc_sector.rb +55 -0
- data/examples/galactic_courier/test/ts_all.rb +12 -0
- data/examples/gambit_mail/html/compose.rhtml +39 -0
- data/examples/gambit_mail/html/index.rhtml +3 -0
- data/examples/gambit_mail/html/mailbox.rhtml +47 -0
- data/examples/gambit_mail/html/message.rhtml +34 -0
- data/examples/gambit_mail/mail.rb +75 -0
- data/lib/gambit.rb +10 -0
- data/lib/gambit/server.rb +269 -0
- data/lib/gambit/server/gambiterror.rb +28 -0
- data/lib/gambit/server/game.rb +185 -0
- data/lib/gambit/server/game/eventform.rb +174 -0
- data/lib/gambit/server/message.rb +85 -0
- data/lib/gambit/server/player.rb +40 -0
- data/lib/gambit/tools.rb +13 -0
- data/lib/gambit/tools/board.rb +275 -0
- data/lib/gambit/tools/cards.rb +11 -0
- data/lib/gambit/tools/cards/card.rb +158 -0
- data/lib/gambit/tools/cards/deck.rb +99 -0
- data/lib/gambit/tools/cards/hand.rb +86 -0
- data/lib/gambit/tools/cards/pile.rb +107 -0
- data/lib/gambit/tools/currency.rb +148 -0
- data/lib/gambit/tools/dice.rb +219 -0
- data/lib/gambit/tools/movehistory.rb +164 -0
- data/lib/gambit/tools/scorecard.rb +333 -0
- data/lib/gambit/viewable.rb +71 -0
- data/setup.rb +1360 -0
- data/test/tc_board.rb +167 -0
- data/test/tc_cards.rb +182 -0
- data/test/tc_currency.rb +99 -0
- data/test/tc_dice.rb +83 -0
- data/test/tc_error.rb +34 -0
- data/test/tc_event.rb +367 -0
- data/test/tc_game.rb +29 -0
- data/test/tc_message.rb +35 -0
- data/test/tc_movehistory.rb +38 -0
- data/test/tc_player.rb +60 -0
- data/test/tc_scorecard.rb +112 -0
- data/test/tc_views.rb +353 -0
- data/test/test_game.rb +19 -0
- data/test/test_view.rhtml +2 -0
- data/test/ts_all.rb +12 -0
- data/test/ts_server.rb +14 -0
- data/test/ts_tools.rb +14 -0
- metadata +183 -0
@@ -0,0 +1,22 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_planet.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-06-06.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "planet"
|
11
|
+
|
12
|
+
class TestPlanet < Test::Unit::TestCase
|
13
|
+
def test_creation
|
14
|
+
assert_not_nil(planet = Planet.new(:volcanic))
|
15
|
+
assert_equal(:volcanic, planet.type)
|
16
|
+
|
17
|
+
assert_not_nil(planet = Planet.random)
|
18
|
+
assert_instance_of(Planet, planet)
|
19
|
+
assert( [ :volcanic, :tundra, :oceanic,
|
20
|
+
:jungle, :industrial, :barren ].include?(planet.type) )
|
21
|
+
end
|
22
|
+
end
|
@@ -0,0 +1,55 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# tc_sector.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-06-06.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "test/unit"
|
9
|
+
|
10
|
+
require "sector"
|
11
|
+
require "planet"
|
12
|
+
require "station"
|
13
|
+
|
14
|
+
class TestSector < Test::Unit::TestCase
|
15
|
+
def test_creation
|
16
|
+
assert_not_nil(sector = Sector.new(:black_hole))
|
17
|
+
assert_equal(:black_hole, sector.feature)
|
18
|
+
assert_same(sector, sector.create_planet(Planet.new(:tundra)))
|
19
|
+
4.times { assert_same(sector, sector << Planet.new(:jungle)) }
|
20
|
+
assert_raise(RuntimeError) { sector << Planet.new(:jungle) }
|
21
|
+
assert_equal(:tundra, sector[0].type)
|
22
|
+
assert_equal(:jungle, sector[rand(4) + 1].type)
|
23
|
+
assert_not_nil(sector.build_station(Station.random))
|
24
|
+
assert_raise(RuntimeError) { sector.build_station(Station.random) }
|
25
|
+
assert_equal(5, sector.size)
|
26
|
+
|
27
|
+
assert_not_nil(sector = Sector.random)
|
28
|
+
assert_instance_of(Sector, sector)
|
29
|
+
assert( [ :none, :nebula,
|
30
|
+
:asteroids, :black_hole ].include?(sector.feature) )
|
31
|
+
assert(sector.size >= 0)
|
32
|
+
assert(sector.size <= 5)
|
33
|
+
end
|
34
|
+
|
35
|
+
def test_linking
|
36
|
+
sectors = [Sector.random]
|
37
|
+
2.times { sectors << Sector.random }
|
38
|
+
sectors.each_with_index { |sec, index| sec.name = index + 1 }
|
39
|
+
sectors.each { |sec| assert_equal(0, sec.links.size) }
|
40
|
+
sectors.first.link(sectors.last)
|
41
|
+
assert_equal(1, sectors.first.links.size)
|
42
|
+
assert_equal(1, sectors.last.links.size)
|
43
|
+
assert_equal(3, sectors.first.links.first.name)
|
44
|
+
assert_equal(1, sectors.last.links.first.name)
|
45
|
+
|
46
|
+
sectors[0].link(sectors[1], true)
|
47
|
+
sectors[1].link(sectors[2], true)
|
48
|
+
assert_equal(2, sectors[0].links.size)
|
49
|
+
assert_equal(1, sectors[1].links.size)
|
50
|
+
assert_equal(1, sectors[2].links.size)
|
51
|
+
assert_equal([3, 2], sectors[0].links.map { |sec| sec.name })
|
52
|
+
assert_equal([3], sectors[1].links.map { |sec| sec.name })
|
53
|
+
assert_equal([1], sectors[2].links.map { |sec| sec.name })
|
54
|
+
end
|
55
|
+
end
|
@@ -0,0 +1,39 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Compose Mail</title>
|
4
|
+
<style> #Message { height: 300px; width: 400px; border: 2px solid; }
|
5
|
+
.event p { margin: 0 0 0 350; }
|
6
|
+
#To { margin: 0 20 0 36; border: 2px solid;
|
7
|
+
padding: 2px; }
|
8
|
+
#Subject { margin: 2 0 0 8; width: 400px; border: 2px solid;
|
9
|
+
padding: 2px; }
|
10
|
+
form dd {
|
11
|
+
margin: 5;
|
12
|
+
}
|
13
|
+
|
14
|
+
form dt {
|
15
|
+
float: left;
|
16
|
+
padding-right = 10px;
|
17
|
+
}
|
18
|
+
|
19
|
+
label { margin: 0 4 0 0; }
|
20
|
+
</style>
|
21
|
+
</head>
|
22
|
+
<body>
|
23
|
+
<%message = @message ||
|
24
|
+
Gambit::Server::Message.new(@player.name,"","","") %>
|
25
|
+
<% player = @player %>
|
26
|
+
<%= event(nil,"send_message") do
|
27
|
+
if message.to.eql?("")
|
28
|
+
menu "To", Gambit::Server::SERVER.players.keys - [player.name]
|
29
|
+
else
|
30
|
+
menu "To", message.to
|
31
|
+
end
|
32
|
+
hidden "From", message.from
|
33
|
+
text "Subject", "value" => message.subject
|
34
|
+
document "Message"
|
35
|
+
submit "Send"
|
36
|
+
end %>
|
37
|
+
</body>
|
38
|
+
</html>
|
39
|
+
|
@@ -0,0 +1,47 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Mailbox</title>
|
4
|
+
<style type="Text/CSS">
|
5
|
+
.message_short { padding: 2px; margin: 0px; width: 900px;}
|
6
|
+
.message_short li { list-style-type: none;
|
7
|
+
float: left;
|
8
|
+
border: 1px solid; padding: 0px 20px 0px 20px;}
|
9
|
+
.from_short { width: 200px; background-color: #dddddd; }
|
10
|
+
.subject_short { width: 200px; background-color: #eeeeee; }
|
11
|
+
.time_short { background-color: #dddddd; width: 275px; }
|
12
|
+
#mailbox_header_from { width: 200px; background-color: #f8f7d1 }
|
13
|
+
#mailbox_header_subject { width: 200px; background-color: #f8f7d1 }
|
14
|
+
#mailbox_header_time { width: 275px; background-color: #f8f7d1 }
|
15
|
+
</style>
|
16
|
+
</head>
|
17
|
+
<body>
|
18
|
+
<% @message = nil %>
|
19
|
+
<ul class="message_short">
|
20
|
+
<li id="mailbox_header_from">
|
21
|
+
<%= event("Sender","sort","sort_by" => "sender") %>
|
22
|
+
</li>
|
23
|
+
<li id="mailbox_header_subject">
|
24
|
+
<%= event("Subject","sort","sort_by" => "subject") %>
|
25
|
+
</li>
|
26
|
+
<li id="mailbox_header_time">
|
27
|
+
<%= event("Time","sort","sort_by" => "time") %>
|
28
|
+
</li>
|
29
|
+
</ul>
|
30
|
+
<% @player.mailbox.each do |mes| %>
|
31
|
+
<ul class="message_short">
|
32
|
+
<li class="from_short"> <%= mes.from %> </li>
|
33
|
+
<li class="subject_short">
|
34
|
+
<%= event(mes.subject, "show_message",
|
35
|
+
"id" => mes.object_id) %>
|
36
|
+
</li>
|
37
|
+
<li class="time_short"> <%= mes.time %> </li>
|
38
|
+
</ul>
|
39
|
+
<% end %>
|
40
|
+
<p style="clear: both; margin: 0 20 20 520;">
|
41
|
+
<br>
|
42
|
+
<a href="compose.rhtml"> Compose</a> |
|
43
|
+
<%= event("Delete All Messages", "delete_all") %>
|
44
|
+
</p>
|
45
|
+
</body>
|
46
|
+
</html>
|
47
|
+
|
@@ -0,0 +1,34 @@
|
|
1
|
+
<html>
|
2
|
+
<head>
|
3
|
+
<title>Mailbox</title>
|
4
|
+
<style type="Text/CSS">
|
5
|
+
.message { border: 1px ; width: 400px; }
|
6
|
+
.message td { border: 2px solid; padding: 4px }
|
7
|
+
a { text-decoration: none; color : #000000; }
|
8
|
+
ul { padding: 0 0 0 100; }
|
9
|
+
li { float: left; padding: 2 5 2 5; list-style: none;
|
10
|
+
border: 1px solid }
|
11
|
+
#time { text-align: center; background-color: #ffffff;}
|
12
|
+
#from { width: 50%; text-align: center; background-color: #cccccc;
|
13
|
+
vertical-align: top; }
|
14
|
+
#to { width: 50%; text-align: center; background-color: #cccccc;
|
15
|
+
vertical-align: top;}
|
16
|
+
#subject { text-align: center; background-color: #dddddd; }
|
17
|
+
#body { background-color: #aaaaaa; padding: 8px}
|
18
|
+
</style>
|
19
|
+
</head>
|
20
|
+
<body>
|
21
|
+
<%= @message.view(:gambit_html) %>
|
22
|
+
<ul>
|
23
|
+
<li>
|
24
|
+
<%= event("reply", "reply",
|
25
|
+
"id" => @message.object_id) %>
|
26
|
+
</li>
|
27
|
+
<li>
|
28
|
+
<%= event("delete","delete_message",
|
29
|
+
"id" => @message.object_id) %>
|
30
|
+
</li>
|
31
|
+
<li><a href="mailbox.rhtml">Return to mailbox</a></li>
|
32
|
+
</ul>
|
33
|
+
</body>
|
34
|
+
</html>
|
@@ -0,0 +1,75 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# mail.rb
|
4
|
+
#
|
5
|
+
# Created by Gregory Brown on 22005-06-05
|
6
|
+
# Copyright 2005 smtose.org. All rights reserved.
|
7
|
+
|
8
|
+
$:.unshift(File.join(File.dirname(__FILE__), "..", "..", "lib"))
|
9
|
+
require "gambit"
|
10
|
+
require "gambit/server/message"
|
11
|
+
|
12
|
+
class Mail< Gambit::Server::Game
|
13
|
+
def initialize( )
|
14
|
+
super
|
15
|
+
end
|
16
|
+
|
17
|
+
def do_login( player, details )
|
18
|
+
"mailbox.rhtml"
|
19
|
+
end
|
20
|
+
|
21
|
+
def do_show_message( player, details )
|
22
|
+
@message = get_message(details["id"])
|
23
|
+
"message.rhtml"
|
24
|
+
end
|
25
|
+
|
26
|
+
def do_delete_message( player, details )
|
27
|
+
player.mailbox.delete(get_message(details["id"]))
|
28
|
+
"mailbox.rhtml"
|
29
|
+
end
|
30
|
+
|
31
|
+
def do_sort( player, details )
|
32
|
+
sort_by = details["sort_by"]
|
33
|
+
case sort_by
|
34
|
+
when("sender")
|
35
|
+
@player.mailbox.sort! { |a,b| a.from <=> b.from }
|
36
|
+
when("subject")
|
37
|
+
@player.mailbox.sort! { |a,b| a.subject <=> b.subject }
|
38
|
+
when("time")
|
39
|
+
@player.mailbox.sort! { |a,b| a.time <=> b.time }
|
40
|
+
end
|
41
|
+
"mailbox.rhtml"
|
42
|
+
end
|
43
|
+
|
44
|
+
def do_reply( player, details )
|
45
|
+
message = get_message(details["id"])
|
46
|
+
@message = Gambit::Server::Message.new(message.to, message.from,
|
47
|
+
"RE: " + message.subject,"")
|
48
|
+
return "compose.rhtml"
|
49
|
+
end
|
50
|
+
|
51
|
+
def do_send_message( player, details )
|
52
|
+
Gambit::Server::SERVER.players[details["To"]].mailbox <<
|
53
|
+
Gambit::Server::Message.new( details["From"],
|
54
|
+
details["To"],
|
55
|
+
details["Subject"],
|
56
|
+
details["Message"] )
|
57
|
+
return "mailbox.rhtml"
|
58
|
+
end
|
59
|
+
|
60
|
+
def do_delete_all( player, details )
|
61
|
+
player.mailbox.clear
|
62
|
+
return "mailbox.rhtml"
|
63
|
+
end
|
64
|
+
|
65
|
+
def do_configure(player, details)
|
66
|
+
super
|
67
|
+
return "mailbox.rhtml"
|
68
|
+
end
|
69
|
+
|
70
|
+
private
|
71
|
+
|
72
|
+
def get_message( id )
|
73
|
+
@player.mailbox.find { |m| m.object_id == id.to_i }
|
74
|
+
end
|
75
|
+
end
|
data/lib/gambit.rb
ADDED
@@ -0,0 +1,269 @@
|
|
1
|
+
#!/usr/local/bin/ruby -w
|
2
|
+
|
3
|
+
# server.rb
|
4
|
+
#
|
5
|
+
# Created by James Edward Gray II on 2005-06-03.
|
6
|
+
# Copyright 2005 Gray Productions. All rights reserved.
|
7
|
+
|
8
|
+
require "webrick"
|
9
|
+
require "erb"
|
10
|
+
require "monitor"
|
11
|
+
require "gambit/server/gambiterror"
|
12
|
+
require "gambit/server/game"
|
13
|
+
require "gambit/server/player"
|
14
|
+
require "gambit/viewable"
|
15
|
+
|
16
|
+
module Gambit
|
17
|
+
# The controller layer of the Gambit framework. (Docs coming soon...)
|
18
|
+
class Server < WEBrick::HTTPServer
|
19
|
+
include Gambit::Viewable
|
20
|
+
register_view(:game_listing, <<-END_GAME_LIST.gsub(/^\t{2}/, ""))
|
21
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
22
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
23
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
24
|
+
<head>
|
25
|
+
<title>Game List</title>
|
26
|
+
</head><body>
|
27
|
+
<h1>Select a Game</h1>
|
28
|
+
% unless @server_message.nil?
|
29
|
+
<p class="notification"><%= @server_message %></p>
|
30
|
+
% @server_message = nil
|
31
|
+
% end
|
32
|
+
<ul>
|
33
|
+
% @games.each do |(id, game)|
|
34
|
+
<li><a href="/event/<%= id %>/login"><%= game.name %></a></li>
|
35
|
+
% end
|
36
|
+
</ul>
|
37
|
+
<p><a href="/server/new_game">Add a Game!</a>
|
38
|
+
<a href="/server/new_player">Create a Player!</a></p>
|
39
|
+
</body></html>
|
40
|
+
END_GAME_LIST
|
41
|
+
register_view(:new_player, <<-END_GAME_LIST.gsub(/^\t{2}/, ""))
|
42
|
+
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
|
43
|
+
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
|
44
|
+
<html xmlns="http://www.w3.org/1999/xhtml">
|
45
|
+
<head>
|
46
|
+
<title>New Player</title>
|
47
|
+
</head><body>
|
48
|
+
<h1>Create Your Player</h1>
|
49
|
+
% unless @server_message.nil?
|
50
|
+
<p class="notification"><%= @server_message %></p>
|
51
|
+
% @server_message = nil
|
52
|
+
% end
|
53
|
+
<form action="/server/create_player" method="post">
|
54
|
+
<dl>
|
55
|
+
<dt><label for="name">Name:</label></dt>
|
56
|
+
<dd><input type="text" id="name" name="name" /></dd>
|
57
|
+
<dt><label for="password">Password:</label></dt>
|
58
|
+
<dd><input type="password" id="password" name="password" /></dd>
|
59
|
+
<dt><label for="verify">Verify Password:</label></dt>
|
60
|
+
<dd><input type="password" id="verify" name="verify" /></dd>
|
61
|
+
</dl>
|
62
|
+
<p><input type="submit" value="Create" /> <input type="reset" /></p>
|
63
|
+
</form>
|
64
|
+
</body></html>
|
65
|
+
END_GAME_LIST
|
66
|
+
|
67
|
+
include MonitorMixin
|
68
|
+
|
69
|
+
def initialize( game_class,
|
70
|
+
port = 80, html_dir = "html", become_daemon = false )
|
71
|
+
super(:Port => port)
|
72
|
+
|
73
|
+
@html_dir = File.join(File.expand_path(File.dirname($0)), html_dir)
|
74
|
+
self.class.const_set(:SERVER, self)
|
75
|
+
@server_message = nil
|
76
|
+
|
77
|
+
@game_class = game_class
|
78
|
+
@games = Hash.new
|
79
|
+
@players = Hash.new
|
80
|
+
|
81
|
+
WEBrick::Daemon.start if become_daemon
|
82
|
+
|
83
|
+
mount_proc("/") { |req, resp| serve_file(req, resp, req.path) }
|
84
|
+
mount_proc("/view") { |req, resp| serve_view(req, resp) }
|
85
|
+
mount_proc("/event") { |req, resp| serve_event(req, resp) }
|
86
|
+
mount_proc("/server") { |req, resp| serve_server_event(req, resp) }
|
87
|
+
|
88
|
+
['INT', 'TERM'].each { |signal| trap(signal) { shutdown } }
|
89
|
+
end
|
90
|
+
|
91
|
+
attr_reader :players
|
92
|
+
|
93
|
+
def login( req, resp, game, event = nil )
|
94
|
+
if cookie = req.cookies.find { |c| c.name == "player" }
|
95
|
+
cookie.expires = nil # defaults to end of session
|
96
|
+
resp.cookies << cookie
|
97
|
+
cookie.path = "/"
|
98
|
+
@players[cookie.value]
|
99
|
+
elsif (event == "login") and
|
100
|
+
not (req.query["login"].nil? or req.query["login"].empty?)
|
101
|
+
if player = @players[req.query["login"]]
|
102
|
+
if player.login?(req.query["password"])
|
103
|
+
cookie = WEBrick::Cookie.new( "player",
|
104
|
+
req.query["login"] )
|
105
|
+
cookie.expires = nil # defaults to end of session
|
106
|
+
resp.cookies << cookie
|
107
|
+
cookie.path = "/"
|
108
|
+
|
109
|
+
@players[cookie.value]
|
110
|
+
else
|
111
|
+
raise Gambit::Server::GambitError, "Invalid password."
|
112
|
+
end
|
113
|
+
else
|
114
|
+
raise Gambit::Server::GambitError, "Unknown name."
|
115
|
+
end
|
116
|
+
else
|
117
|
+
resp.body = game.view(:login)
|
118
|
+
raise WEBrick::HTTPStatus::OK
|
119
|
+
end
|
120
|
+
end
|
121
|
+
|
122
|
+
def serve_event( req, resp )
|
123
|
+
begin
|
124
|
+
if req.path =~ %r{/event/([^/]+)/([^/]+)}
|
125
|
+
game_name = $1.to_i
|
126
|
+
event_name = $2
|
127
|
+
|
128
|
+
if @games[game_name].nil?
|
129
|
+
raise Gambit::Server::GambitError, "Game not found!"
|
130
|
+
else
|
131
|
+
player = login( req, resp,
|
132
|
+
@games[game_name], event_name )
|
133
|
+
next_page = nil
|
134
|
+
synchronize do
|
135
|
+
next_page = @games[game_name].do_event( player,
|
136
|
+
event_name,
|
137
|
+
req.query )
|
138
|
+
end
|
139
|
+
|
140
|
+
if cookie = req.cookies.find { |c| c.name == "player" }
|
141
|
+
resp.cookies << cookie
|
142
|
+
end
|
143
|
+
resp.set_redirect( WEBrick::HTTPStatus::SeeOther,
|
144
|
+
"/view/#{game_name}/#{next_page}" )
|
145
|
+
raise WEBrick::HTTPStatus::SeeOther
|
146
|
+
end
|
147
|
+
else
|
148
|
+
raise Gambit::Server::GambitError, "Malformed Event!"
|
149
|
+
end
|
150
|
+
rescue Gambit::Server::GambitError => error
|
151
|
+
resp.body = error.view(:error_page)
|
152
|
+
raise WEBrick::HTTPStatus::OK
|
153
|
+
end
|
154
|
+
end
|
155
|
+
|
156
|
+
def serve_server_event( req, resp )
|
157
|
+
if req.path == "/server/new_game"
|
158
|
+
game = @game_class.new
|
159
|
+
if not @players.empty?
|
160
|
+
@games[game.object_id] = game
|
161
|
+
resp.body = game.view(:configure)
|
162
|
+
else
|
163
|
+
@server_message = "No users!"
|
164
|
+
resp.body = view(:game_listing)
|
165
|
+
end
|
166
|
+
raise WEBrick::HTTPStatus::OK
|
167
|
+
elsif req.path == "/server/new_player"
|
168
|
+
resp.body = view(:new_player)
|
169
|
+
raise WEBrick::HTTPStatus::OK
|
170
|
+
elsif req.path == "/server/create_player"
|
171
|
+
if @players.include?(req.query["name"])
|
172
|
+
@server_message = "Sorry, that name is taken."
|
173
|
+
resp.body = view(:new_player)
|
174
|
+
raise WEBrick::HTTPStatus::OK
|
175
|
+
elsif req.query["password"] != req.query["verify"]
|
176
|
+
@server_message = "The provided passwords do not match."
|
177
|
+
resp.body = view(:new_player)
|
178
|
+
raise WEBrick::HTTPStatus::OK
|
179
|
+
else
|
180
|
+
@server_message = "Player created."
|
181
|
+
@players[req.query["name"]] =
|
182
|
+
Gambit::Server::Player.new( req.query["name"],
|
183
|
+
req.query["password"] )
|
184
|
+
cookie = WEBrick::Cookie.new( "player",
|
185
|
+
req.query["name"] )
|
186
|
+
cookie.expires = nil # defaults to end of session
|
187
|
+
resp.cookies << cookie
|
188
|
+
cookie.path = "/"
|
189
|
+
|
190
|
+
resp.body = view(:game_listing)
|
191
|
+
raise WEBrick::HTTPStatus::OK
|
192
|
+
end
|
193
|
+
elsif req.path == "/server/test"
|
194
|
+
test_mode
|
195
|
+
|
196
|
+
cookie = WEBrick::Cookie.new("player", "tester")
|
197
|
+
cookie.expires = nil # defaults to end of session
|
198
|
+
resp.cookies << cookie
|
199
|
+
cookie.path = "/"
|
200
|
+
|
201
|
+
resp.body = view(:game_listing)
|
202
|
+
raise WEBrick::HTTPStatus::OK
|
203
|
+
else
|
204
|
+
resp.body = view(:game_listing)
|
205
|
+
raise WEBrick::HTTPStatus::OK
|
206
|
+
end
|
207
|
+
end
|
208
|
+
|
209
|
+
def serve_file( req, resp, file )
|
210
|
+
if file == "/"
|
211
|
+
resp.body = view(:game_listing)
|
212
|
+
raise WEBrick::HTTPStatus::OK
|
213
|
+
end
|
214
|
+
|
215
|
+
stats = File::stat(file)
|
216
|
+
mtime = stats.mtime
|
217
|
+
resp["etag"] = sprintf( "%x-%x-%x", stats.ino, stats.size,
|
218
|
+
stats.mtime.to_i )
|
219
|
+
mtype = WEBrick::HTTPUtils::mime_type(file, self[:MimeTypes])
|
220
|
+
resp["content-type"] = mtype
|
221
|
+
resp["content-length"] = stats.size
|
222
|
+
resp["last-modified"] = mtime.httpdate
|
223
|
+
resp.body = File.open(file, "rb")
|
224
|
+
raise WEBrick::HTTPStatus::OK
|
225
|
+
end
|
226
|
+
|
227
|
+
def serve_view( req, resp )
|
228
|
+
begin
|
229
|
+
if req.path =~ %r{/view/([^/]+)/(.+)}
|
230
|
+
game_name = $1.to_i
|
231
|
+
view_file = $2
|
232
|
+
|
233
|
+
erb_file = File.join(@html_dir, view_file)
|
234
|
+
|
235
|
+
if test(?e, erb_file)
|
236
|
+
player = login(req, resp, @games[game_name])
|
237
|
+
@games[game_name].player = player
|
238
|
+
|
239
|
+
if File.extname(erb_file) == ".rhtml"
|
240
|
+
erb_page = ERB.new( File.read(erb_file),
|
241
|
+
nil, "%<>" )
|
242
|
+
resp.body = erb_page.result(
|
243
|
+
@games[game_name].event_binding )
|
244
|
+
raise WEBrick::HTTPStatus::OK
|
245
|
+
else
|
246
|
+
serve_file(req, resp, erb_file)
|
247
|
+
end
|
248
|
+
else
|
249
|
+
raise Gambit::Server::GambitError, "View not found!"
|
250
|
+
end
|
251
|
+
else
|
252
|
+
raise Gambit::Server::GambitError, "Malformed View!"
|
253
|
+
end
|
254
|
+
rescue Gambit::Server::GambitError => error
|
255
|
+
resp.body = error.view(:error_page)
|
256
|
+
raise WEBrick::HTTPStatus::OK
|
257
|
+
end
|
258
|
+
end
|
259
|
+
|
260
|
+
def test_mode( )
|
261
|
+
game = @game_class.new
|
262
|
+
@games[game.object_id] = game
|
263
|
+
game.do_configure(nil, "game_name" => "Test Mode Game")
|
264
|
+
@players["tester"] = Gambit::Server::Player.new( "tester",
|
265
|
+
"test" )
|
266
|
+
@server_message = "Test mode active."
|
267
|
+
end
|
268
|
+
end
|
269
|
+
end
|