kolb 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +4 -0
- data/Gemfile +4 -0
- data/README.markdown +60 -0
- data/Rakefile +1 -0
- data/bin/example.rb +129 -0
- data/bin/kolb.rb +24 -0
- data/config/kolb.yaml +121 -0
- data/kolb.gemspec +24 -0
- data/lib/kolb.rb +8 -0
- data/lib/kolb/action.rb +52 -0
- data/lib/kolb/book.rb +73 -0
- data/lib/kolb/game.rb +69 -0
- data/lib/kolb/version.rb +3 -0
- data/test/action_test.rb +24 -0
- data/test/game_test.rb +9 -0
- metadata +76 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/README.markdown
ADDED
@@ -0,0 +1,60 @@
|
|
1
|
+
# KOLB
|
2
|
+
|
3
|
+
The aim of this project is to create a [Choose Your Own Adventure][CYOA]
|
4
|
+
(CYOA) game engine that can be used to quickly create fun games.
|
5
|
+
|
6
|
+
So far all you can do is play a CYOA called "Kolb & The Dragon"
|
7
|
+
(instructions below).
|
8
|
+
|
9
|
+
This requires ruby >= 1.9.2
|
10
|
+
|
11
|
+
## Instructions
|
12
|
+
|
13
|
+
**To install**, type this into your terminal:
|
14
|
+
|
15
|
+
$ git clone git@github.com:ali/kolb.git
|
16
|
+
$ cd kolb
|
17
|
+
|
18
|
+
You can also [download this game as a zip file][zip].
|
19
|
+
|
20
|
+
[zip]: https://github.com/ali/kolb/zipball/master
|
21
|
+
|
22
|
+
**To play**, type
|
23
|
+
|
24
|
+
$ cd kolb
|
25
|
+
$ ruby bin/kolb.rb
|
26
|
+
|
27
|
+
**When playing**, you interact with the game by choosing between different actions to take.
|
28
|
+
|
29
|
+
> Enter the cold cave (17)
|
30
|
+
> Enter the windy cave (8)
|
31
|
+
> Walk up the trail (12)
|
32
|
+
|
33
|
+
Choose an action by typing the number you see in parenthesis and hitting enter.
|
34
|
+
|
35
|
+
If you want to quit, just enter in `q` or `quit`.
|
36
|
+
|
37
|
+
## What I'd like to do next
|
38
|
+
|
39
|
+
Currently doing cleanup.
|
40
|
+
|
41
|
+
* Gemify project
|
42
|
+
* Add tests
|
43
|
+
* Fix indentation, switch to snake\_case
|
44
|
+
* Games are now Ruby files ([at the recommendation of yorickpeterse](http://www.reddit.com/r/ruby/comments/pd6ur/i_made_a_cyoa_game_engine_in_ruby_need_some_help/c3ogmnq))
|
45
|
+
|
46
|
+
## Feedback
|
47
|
+
|
48
|
+
This project has [a thread on Reddit](http://redd.it/pd6ur).
|
49
|
+
|
50
|
+
|
51
|
+
## Kolb & The Dragon
|
52
|
+
|
53
|
+
I found a [Choose Your Own Adventure][CYOA] book while playing [Skyrim][] called _[Kolb & The Dragon][Kolb]_.
|
54
|
+
|
55
|
+
As a programming exercise, this morning (1/7/12) I decided to create a Choose Your Own Adventure program.
|
56
|
+
|
57
|
+
[CYOA]: http://en.wikipedia.org/wiki/Choose_Your_Own_Adventure "Choose Your Own Adventure - Wikipedia"
|
58
|
+
[Skyrim]: http://en.wikipedia.org/wiki/Skyrim "The Elder Scrolls V - Skyrim"
|
59
|
+
[Kolb]: http://www.uesp.net/wiki/Skyrim:Kolb_%26_the_Dragon "Kolb & The Dragon"
|
60
|
+
|
data/Rakefile
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
require "bundler/gem_tasks"
|
data/bin/example.rb
ADDED
@@ -0,0 +1,129 @@
|
|
1
|
+
#!/bin/env ruby
|
2
|
+
|
3
|
+
# An example of how to create a game using this gem.
|
4
|
+
|
5
|
+
##########################################
|
6
|
+
# Step 1: Require kolb
|
7
|
+
##########################################
|
8
|
+
require 'kolb'
|
9
|
+
|
10
|
+
##########################################
|
11
|
+
# Step 2: Create a book
|
12
|
+
##########################################
|
13
|
+
kolb = KOLB::Book.new("Kolb & The Dragon")
|
14
|
+
|
15
|
+
|
16
|
+
##########################################
|
17
|
+
# Step 3: Write pages, link actions.
|
18
|
+
##########################################
|
19
|
+
|
20
|
+
# 1
|
21
|
+
kolb.pages[0] = "Kolb was a brave Nord warrior. One day his Chief asked Kolb to slay an evil dragon that threatened their village. \"Go through the mountain pass, Kolb\", his Chief said. \"You will find the Dragon on the other side.\"" # The test on page 0 (pages are 0-indexed)
|
22
|
+
|
23
|
+
kolb.link(0, 1, "Turn to page") # Create a link on page 0, that goes to page 1, with some text
|
24
|
+
|
25
|
+
# 2
|
26
|
+
kolb.pages[1] = "Kolb took his favorite axe and shield and walked to the pass, where he found a cold cave, a windy cave, and a narrow trail."
|
27
|
+
|
28
|
+
kolb.link(1, 16, "Enter the cold cave")
|
29
|
+
kolb.link(1, 7, "Enter the windy cave")
|
30
|
+
kolb.link(1, 11, "Walk up the trail")
|
31
|
+
|
32
|
+
# 3
|
33
|
+
kolb.pages[2] = "Kolb stepped onto a rocky hill. He could see the dragon sleeping below, and a tavern off a road nearby."
|
34
|
+
|
35
|
+
kolb.link(2, 15, "Climb down")
|
36
|
+
kolb.link(2, 13, "Visit tavern")
|
37
|
+
|
38
|
+
# 4
|
39
|
+
kolb.pages[3] = "Following the stench, Kolb found a filthy orc! The orc snarled and charged Kolb with his spiked club."
|
40
|
+
|
41
|
+
kolb.link(3, 8, "Raise Shield")
|
42
|
+
kolb.link(3, 12, "Swing Axe")
|
43
|
+
|
44
|
+
# 5
|
45
|
+
kolb.pages[4] = "Treading through the marsh, Kolb discovered a wailing ghost blocking his way."
|
46
|
+
|
47
|
+
kolb.link(4, 14, "Attack Ghost")
|
48
|
+
kolb.link(4, 9, "Give Gold")
|
49
|
+
|
50
|
+
# 6
|
51
|
+
kolb.pages[5] = "The head of the axe lodged itself in the tough, scaly neck of the beast. It wailed and thrashed, but Kolb held on and eventually sawed through the neck, killing the beast. Kolb returned home victorious, and his village was never bothered by the dragon again.
|
52
|
+
THE END"
|
53
|
+
|
54
|
+
# 7
|
55
|
+
kolb.pages[6] = "Leaving the marsh behind him, Kolb could see the dragon's lair nearby, as well as a small, welcoming tavern."
|
56
|
+
|
57
|
+
kolb.link(6, 15, "Go to the Lair")
|
58
|
+
kolb.link(6, 13, "Go to Tavern")
|
59
|
+
|
60
|
+
#8
|
61
|
+
kolb.pages[7] = "A strong gust of wind blew Kolb's torch out, and knocked him into a pit where split [sic] his head and died.
|
62
|
+
THE END"
|
63
|
+
|
64
|
+
#9
|
65
|
+
kolb.pages[8] ="The orc cackled as his club splintered Kolb's shield and smashed into his face. There Kolb died, and the orc had soup from his bones.
|
66
|
+
THE END"
|
67
|
+
|
68
|
+
# 10
|
69
|
+
kolb.pages[9] = "Kolb remembered a story his Gran told him and tossed two gold chits for the ghost, and it faded away, allowing him to pass."
|
70
|
+
|
71
|
+
kolb.link(9, 6, "Turn to Page")
|
72
|
+
|
73
|
+
# 11
|
74
|
+
kolb.pages[10] = "Kolb crept towards the belly of the beast, but no sooner had he taken his eyes off the head of the beast than it snapped him up and ate him whole, axe and all.
|
75
|
+
THE END"
|
76
|
+
|
77
|
+
# 12
|
78
|
+
kolb.pages[11] = "Climbing up, Kolb found a camp. He met a wise man who shared bread and showed two paths to the dragon's lair. One went through the hills, the other through a marsh."
|
79
|
+
|
80
|
+
kolb.link(11, 2, "Take the hills")
|
81
|
+
kolb.link(11, 4, "Take the marsh")
|
82
|
+
|
83
|
+
# 13
|
84
|
+
kolb.pages[12] = "Before the orc could strike, Kolb swung his mighty axe. The orc's head and club fell uselessly to the floor."
|
85
|
+
|
86
|
+
kolb.link(12, 2, "Turn to Page")
|
87
|
+
|
88
|
+
# 14
|
89
|
+
kolb.pages[13] = "Kolb stopped at the tavern to rest before fighting the dragon. High elves ran the tavern, however, and poisoned his mead so they could steal his gold.
|
90
|
+
THE END"
|
91
|
+
|
92
|
+
# 15
|
93
|
+
kolb.pages[14] = "Kolb swung his axe as hard as he could, but the ghost hardly seemed to notice. The ghost drifted into Kolb, and a deep sleep took him over, from which he never awoke.
|
94
|
+
THE END"
|
95
|
+
|
96
|
+
# 16
|
97
|
+
kolb.pages[15] = "Kolb found the lair where the dragon slept, tendrils of smoke wafting from it's [sic] nostrils. The air made Kolb's eyes sting, and he nearly slipped on the bones of men, picked clean. The beast lay on its side, the throat and belly both waiting targets."
|
98
|
+
|
99
|
+
kolb.link(15, 5, "Strike the Neck")
|
100
|
+
kolb.link(15, 10, "Strike the Belly")
|
101
|
+
|
102
|
+
# 17
|
103
|
+
kolb.pages[16] = "Kolb stepped into the frozen cave, but his Nord blood kept him warm. A smelly tunnel climbed ahead of him, and wind howled from another to his left. A ladder was nearby as well."
|
104
|
+
|
105
|
+
kolb.link(16, 3, "Take the smelly tunnel")
|
106
|
+
kolb.link(16, 7, "Take the windy tunnel")
|
107
|
+
kolb.link(16, 11, "Climb the ladder")
|
108
|
+
|
109
|
+
|
110
|
+
##########################################
|
111
|
+
# Step 4: Create a Game, and call 'run'
|
112
|
+
##########################################
|
113
|
+
funtime = KOLB::Game.new(kolb)
|
114
|
+
funtime.run
|
115
|
+
|
116
|
+
|
117
|
+
##########################################
|
118
|
+
# Step 5: Play!
|
119
|
+
#
|
120
|
+
# a: Install the gem
|
121
|
+
# gem install kolb
|
122
|
+
#
|
123
|
+
# b: Find your game file (cd into its
|
124
|
+
# directory or download a game)
|
125
|
+
# wget https://raw.github.com/ali/kolb/master/bin/example.rb
|
126
|
+
#
|
127
|
+
# c: Execute the ruby file
|
128
|
+
# ruby example.rb
|
129
|
+
##########################################
|
data/bin/kolb.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
#!/usr/bin/env ruby
|
2
|
+
|
3
|
+
gem_dir = File.join(File.expand_path(File.dirname(__FILE__)))
|
4
|
+
|
5
|
+
require File.join(gem_dir,'..', 'lib', 'kolb')
|
6
|
+
|
7
|
+
kolb_file = File.join(gem_dir, '..', 'config', 'kolb.yaml')
|
8
|
+
|
9
|
+
|
10
|
+
################
|
11
|
+
# Get the book #
|
12
|
+
################
|
13
|
+
|
14
|
+
# Get YAML
|
15
|
+
file = File.open(kolb_file).read
|
16
|
+
# Parse YAML
|
17
|
+
kolb = KOLB::Book.from_yaml(file)
|
18
|
+
|
19
|
+
##################
|
20
|
+
# Start the game #
|
21
|
+
##################
|
22
|
+
|
23
|
+
game = KOLB::Game.new(kolb)
|
24
|
+
game.run
|
data/config/kolb.yaml
ADDED
@@ -0,0 +1,121 @@
|
|
1
|
+
# Kolb & The Dragon
|
2
|
+
# An Adventure for Nord Boys
|
3
|
+
---
|
4
|
+
title: Kolb & The Dragon
|
5
|
+
pages:
|
6
|
+
- Kolb was a brave Nord warrior. One day his Chief asked Kolb to slay an evil dragon
|
7
|
+
that threatened their village. "Go through the mountain pass, Kolb", his Chief said.
|
8
|
+
"You will find the Dragon on the other side."
|
9
|
+
- Kolb took his favorite axe and shield and walked to the pass, where he found a cold
|
10
|
+
cave, a windy cave, and a narrow trail.
|
11
|
+
- Kolb stepped onto a rocky hill. He could see the dragon sleeping below, and a tavern
|
12
|
+
off a road nearby.
|
13
|
+
- Following the stench, Kolb found a filthy orc! The orc snarled and charged Kolb
|
14
|
+
with his spiked club.
|
15
|
+
- Treading through the marsh, Kolb discovered a wailing ghost blocking his way.
|
16
|
+
- ! 'The head of the axe lodged itself in the tough, scaly neck of the beast. It wailed
|
17
|
+
and thrashed, but Kolb held on and eventually sawed through the neck, killing the
|
18
|
+
beast. Kolb returned home victorious, and his village was never bothered by the
|
19
|
+
dragon again.
|
20
|
+
|
21
|
+
THE END'
|
22
|
+
- Leaving the marsh behind him, Kolb could see the dragon's lair nearby, as well as
|
23
|
+
a small, welcoming tavern.
|
24
|
+
- ! 'A strong gust of wind blew Kolb''s torch out, and knocked him into a pit where
|
25
|
+
split [sic] his head and died.
|
26
|
+
|
27
|
+
THE END'
|
28
|
+
- ! 'The orc cackled as his club splintered Kolb''s shield and smashed into his face.
|
29
|
+
There Kolb died, and the orc had soup from his bones.
|
30
|
+
|
31
|
+
THE END'
|
32
|
+
- Kolb remembered a story his Gran told him and tossed two gold chits for the ghost,
|
33
|
+
and it faded away, allowing him to pass.
|
34
|
+
- ! 'Kolb crept towards the belly of the beast, but no sooner had he taken his eyes
|
35
|
+
off the head of the beast than it snapped him up and ate him whole, axe and all.
|
36
|
+
|
37
|
+
THE END'
|
38
|
+
- Climbing up, Kolb found a camp. He met a wise man who shared bread and showed two
|
39
|
+
paths to the dragon's lair. One went through the hills, the other through a marsh.
|
40
|
+
- Before the orc could strike, Kolb swung his mighty axe. The orc's head and club
|
41
|
+
fell uselessly to the floor.
|
42
|
+
- ! 'Kolb stopped at the tavern to rest before fighting the dragon. High elves ran
|
43
|
+
the tavern, however, and poisoned his mead so they could steal his gold.
|
44
|
+
|
45
|
+
THE END'
|
46
|
+
- ! 'Kolb swung his axe as hard as he could, but the ghost hardly seemed to notice.
|
47
|
+
The ghost drifted into Kolb, and a deep sleep took him over, from which he never
|
48
|
+
awoke.
|
49
|
+
|
50
|
+
THE END'
|
51
|
+
- Kolb found the lair where the dragon slept, tendrils of smoke wafting from it's
|
52
|
+
[sic] nostrils. The air made Kolb's eyes sting, and he nearly slipped on the bones
|
53
|
+
of men, picked clean. The beast lay on its side, the throat and belly both waiting
|
54
|
+
targets.
|
55
|
+
- Kolb stepped into the frozen cave, but his Nord blood kept him warm. A smelly tunnel
|
56
|
+
climbed ahead of him, and wind howled from another to his left. A ladder was nearby
|
57
|
+
as well.
|
58
|
+
actions:
|
59
|
+
- page: 0
|
60
|
+
goto: 1
|
61
|
+
text: Turn to page
|
62
|
+
- page: 1
|
63
|
+
goto: 16
|
64
|
+
text: Enter the cold cave
|
65
|
+
- page: 1
|
66
|
+
goto: 7
|
67
|
+
text: Enter the windy cave
|
68
|
+
- page: 1
|
69
|
+
goto: 11
|
70
|
+
text: Walk up the trail
|
71
|
+
- page: 2
|
72
|
+
goto: 15
|
73
|
+
text: Climb down
|
74
|
+
- page: 2
|
75
|
+
goto: 13
|
76
|
+
text: Visit tavern
|
77
|
+
- page: 3
|
78
|
+
goto: 8
|
79
|
+
text: Raise Shield
|
80
|
+
- page: 3
|
81
|
+
goto: 12
|
82
|
+
text: Swing Axe
|
83
|
+
- page: 4
|
84
|
+
goto: 14
|
85
|
+
text: Attack Ghost
|
86
|
+
- page: 4
|
87
|
+
goto: 9
|
88
|
+
text: Give Gold
|
89
|
+
- page: 6
|
90
|
+
goto: 15
|
91
|
+
text: Go to the Lair
|
92
|
+
- page: 6
|
93
|
+
goto: 13
|
94
|
+
text: Go to Tavern
|
95
|
+
- page: 9
|
96
|
+
goto: 6
|
97
|
+
text: Turn to Page
|
98
|
+
- page: 11
|
99
|
+
goto: 2
|
100
|
+
text: Take the hills
|
101
|
+
- page: 11
|
102
|
+
goto: 4
|
103
|
+
text: Take the marsh
|
104
|
+
- page: 12
|
105
|
+
goto: 2
|
106
|
+
text: Turn to Page
|
107
|
+
- page: 15
|
108
|
+
goto: 5
|
109
|
+
text: Strike the Neck
|
110
|
+
- page: 15
|
111
|
+
goto: 10
|
112
|
+
text: Strike the Belly
|
113
|
+
- page: 16
|
114
|
+
goto: 3
|
115
|
+
text: Take the smelly tunnel
|
116
|
+
- page: 16
|
117
|
+
goto: 7
|
118
|
+
text: Take the windy tunnel
|
119
|
+
- page: 16
|
120
|
+
goto: 11
|
121
|
+
text: Climb the ladder
|
data/kolb.gemspec
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "kolb/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "kolb"
|
7
|
+
s.version = KOLB::VERSION
|
8
|
+
s.authors = ["Ali Ukani"]
|
9
|
+
s.email = ["ali.ukani@gmail.com"]
|
10
|
+
s.homepage = "http://github.com/ali/kolb"
|
11
|
+
s.summary = %q{A CYOA game engine}
|
12
|
+
s.description = %q{A CYOA game engine}
|
13
|
+
|
14
|
+
s.rubyforge_project = "kolb"
|
15
|
+
|
16
|
+
s.files = `git ls-files`.split("\n")
|
17
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
18
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
19
|
+
s.require_paths = ["lib"]
|
20
|
+
|
21
|
+
# specify any dependencies here; for example:
|
22
|
+
# s.add_development_dependency "rspec"
|
23
|
+
s.add_runtime_dependency "psych"
|
24
|
+
end
|
data/lib/kolb.rb
ADDED
data/lib/kolb/action.rb
ADDED
@@ -0,0 +1,52 @@
|
|
1
|
+
module KOLB
|
2
|
+
# Action
|
3
|
+
# * page: The page number you'll find this action on
|
4
|
+
# * goto: The page this action links to
|
5
|
+
# * text: The text describing this action
|
6
|
+
|
7
|
+
class Action
|
8
|
+
attr_accessor :page, :goto, :text
|
9
|
+
|
10
|
+
def initialize(page, goto, text)
|
11
|
+
@page = page
|
12
|
+
@goto = goto
|
13
|
+
@text = text
|
14
|
+
end
|
15
|
+
|
16
|
+
# Returns this Action as a String
|
17
|
+
# Because @goto is 0-indexed, add 1 for the benefit of the user
|
18
|
+
def to_s
|
19
|
+
return "#{@text} (#{@goto + 1})"
|
20
|
+
end
|
21
|
+
|
22
|
+
# Returns this Action as a Hash
|
23
|
+
def to_hash
|
24
|
+
return {"page" => @page,
|
25
|
+
"goto" => @goto,
|
26
|
+
"text" => @text}
|
27
|
+
end
|
28
|
+
|
29
|
+
# Makes an Action from a Hash
|
30
|
+
def self.from_hash(hash)
|
31
|
+
# Verify
|
32
|
+
if hash.class == Hash && hash.has_key?("page") && hash.has_key?("goto") && hash.has_key?("text")
|
33
|
+
# Initialize
|
34
|
+
self.new(hash["page"], hash["goto"], hash["text"])
|
35
|
+
else
|
36
|
+
raise "Invalid hash\n\tGiven: #{hash}"
|
37
|
+
end
|
38
|
+
end
|
39
|
+
|
40
|
+
# # Returns this Action as YAML
|
41
|
+
# def to_yaml
|
42
|
+
# # Use Pysch to create a YAML version of this Action as a Hash
|
43
|
+
# return Psych.dump(to_hash)
|
44
|
+
# end
|
45
|
+
|
46
|
+
# # Creates an Action from YAML
|
47
|
+
# def self.from_yaml(yaml)
|
48
|
+
# # Use Pysch to read a YAML version of an Action as a Hash
|
49
|
+
# from_hash(Psych.load(yaml))
|
50
|
+
# end
|
51
|
+
end
|
52
|
+
end
|
data/lib/kolb/book.rb
ADDED
@@ -0,0 +1,73 @@
|
|
1
|
+
module KOLB
|
2
|
+
|
3
|
+
# Represents the Choose Your Own Adventure book
|
4
|
+
class Book
|
5
|
+
attr_accessor :title, :pages, :actions
|
6
|
+
|
7
|
+
# Creats a Book
|
8
|
+
# title must be a String
|
9
|
+
# pages must be an Array of Strings
|
10
|
+
# actions must be an Array of Actions
|
11
|
+
def initialize(title, pages = [], actions = [])
|
12
|
+
@title = title
|
13
|
+
@pages = pages
|
14
|
+
@actions = actions
|
15
|
+
end
|
16
|
+
|
17
|
+
# Returns a Page given its number.
|
18
|
+
# Word-wraps text by default.
|
19
|
+
def page(num, wrap = true, wraplength = 70)
|
20
|
+
if wrap
|
21
|
+
return wrap_text(@pages[num], wraplength)
|
22
|
+
else
|
23
|
+
return @pages[num]
|
24
|
+
end
|
25
|
+
end
|
26
|
+
|
27
|
+
# Creates an Action linking Page a to Page b
|
28
|
+
def link(a, b, text)
|
29
|
+
@actions << Action.new(a, b, text)
|
30
|
+
end
|
31
|
+
|
32
|
+
# Returns an array of all the Actions available
|
33
|
+
# on a Page given its number
|
34
|
+
def actions_for_page(page)
|
35
|
+
return @actions.select { |a| a.page == page }
|
36
|
+
end
|
37
|
+
|
38
|
+
# Helper function to wrap text to a given length
|
39
|
+
# Source: http://blog.macromates.com/2006/wrapping-text-with-regular-expressions/
|
40
|
+
def wrap_text(txt, col = 70)
|
41
|
+
return txt.gsub(/(.{1,#{col}})( +|$\n?)|(.{1,#{col}})/,
|
42
|
+
"\\1\\3\n")
|
43
|
+
end
|
44
|
+
|
45
|
+
# Returns this Book as a Hash
|
46
|
+
def to_hash
|
47
|
+
hash = {"title" => @title,
|
48
|
+
"pages" => @pages,
|
49
|
+
"actions" => @actions.collect { |a| a.to_hash }}
|
50
|
+
return hash
|
51
|
+
end
|
52
|
+
|
53
|
+
# Creates a Book from a Hash
|
54
|
+
def self.from_hash(hash)
|
55
|
+
# Verify the Hash
|
56
|
+
if hash.class == Hash && hash.keys == ["title", "pages", "actions"]
|
57
|
+
self.new(hash["title"],
|
58
|
+
hash["pages"],
|
59
|
+
hash["actions"].collect { |a| Action.from_hash(a) })
|
60
|
+
end
|
61
|
+
end
|
62
|
+
|
63
|
+
# Returns this Book as a YAML document
|
64
|
+
def to_yaml
|
65
|
+
return Psych.dump(to_hash)
|
66
|
+
end
|
67
|
+
|
68
|
+
# Creates a Book from a YAML document (of a Book as a Hash)
|
69
|
+
def self.from_yaml(yaml)
|
70
|
+
self.from_hash(Psych.load(yaml))
|
71
|
+
end
|
72
|
+
end
|
73
|
+
end
|
data/lib/kolb/game.rb
ADDED
@@ -0,0 +1,69 @@
|
|
1
|
+
module KOLB
|
2
|
+
|
3
|
+
# The interface which the user interacts with.
|
4
|
+
class Game
|
5
|
+
|
6
|
+
attr_accessor :book, :exits
|
7
|
+
|
8
|
+
def initialize(book)
|
9
|
+
@book = book
|
10
|
+
@exits = ["q", "quit", "exit", "end"] # Ways to quit out of the game
|
11
|
+
end
|
12
|
+
|
13
|
+
# Runs the game
|
14
|
+
def run
|
15
|
+
puts "You are now reading \"#{@book.title}\"."
|
16
|
+
|
17
|
+
loc = 0 # The page we're on
|
18
|
+
actions = [] # Available actions
|
19
|
+
|
20
|
+
while true
|
21
|
+
# Get info
|
22
|
+
page = @book.page(loc)
|
23
|
+
actions = @book.actions_for_page(loc)
|
24
|
+
choices = actions.collect { |a| a.goto }
|
25
|
+
|
26
|
+
# Print
|
27
|
+
puts "\n#{page}"
|
28
|
+
actions.each do |a|
|
29
|
+
puts a
|
30
|
+
end
|
31
|
+
|
32
|
+
# If we don't have any choices, end here.
|
33
|
+
break if choices.empty?
|
34
|
+
|
35
|
+
# Get input
|
36
|
+
input = get_input(choices, "You can't do that.\n#{actions.collect { |a| a.to_s }.join("\n")}")
|
37
|
+
|
38
|
+
if @exits.include?(input)
|
39
|
+
break
|
40
|
+
else
|
41
|
+
input = input.to_i - 1
|
42
|
+
end
|
43
|
+
|
44
|
+
# Turn to that page.
|
45
|
+
loc = input
|
46
|
+
end
|
47
|
+
end
|
48
|
+
|
49
|
+
# Gets the user's input and checks it against a list of valid input options.
|
50
|
+
# Choices is a list of valid input options (an array of page numbers as Integers).
|
51
|
+
# Errortext is a String that gets printed if an invalid choice is made.
|
52
|
+
def get_input(choices, errortext)
|
53
|
+
# Add 1 to the list of choices (they're 0-indexed, but what we show the user isn't)
|
54
|
+
# Also, append the exit commands.
|
55
|
+
valid = choices.collect { |c| (c + 1).to_s } + @exits
|
56
|
+
|
57
|
+
begin
|
58
|
+
# Get user input
|
59
|
+
input = gets.strip
|
60
|
+
|
61
|
+
# Helpful error message
|
62
|
+
puts errortext if !valid.include?(input)
|
63
|
+
end while !valid.include?(input) # Loop if invalid
|
64
|
+
|
65
|
+
return input
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
end
|
data/lib/kolb/version.rb
ADDED
data/test/action_test.rb
ADDED
@@ -0,0 +1,24 @@
|
|
1
|
+
require "test/unit"
|
2
|
+
|
3
|
+
class ActionTest < Test::Unit::TestCase
|
4
|
+
|
5
|
+
# Called before every test method runs. Can be used
|
6
|
+
# to set up fixture information.
|
7
|
+
def setup
|
8
|
+
# Do nothing
|
9
|
+
end
|
10
|
+
|
11
|
+
# Called after every test method runs. Can be used to tear
|
12
|
+
# down fixture information.
|
13
|
+
|
14
|
+
def teardown
|
15
|
+
# Do nothing
|
16
|
+
end
|
17
|
+
|
18
|
+
# Fake test
|
19
|
+
def test_fail
|
20
|
+
|
21
|
+
# To change this template use File | Settings | File Templates.
|
22
|
+
fail("Not implemented")
|
23
|
+
end
|
24
|
+
end
|
data/test/game_test.rb
ADDED
metadata
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: kolb
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
version: 0.0.1
|
5
|
+
prerelease:
|
6
|
+
platform: ruby
|
7
|
+
authors:
|
8
|
+
- Ali Ukani
|
9
|
+
autorequire:
|
10
|
+
bindir: bin
|
11
|
+
cert_chain: []
|
12
|
+
date: 2012-02-11 00:00:00.000000000 Z
|
13
|
+
dependencies:
|
14
|
+
- !ruby/object:Gem::Dependency
|
15
|
+
name: psych
|
16
|
+
requirement: &70270677942540 !ruby/object:Gem::Requirement
|
17
|
+
none: false
|
18
|
+
requirements:
|
19
|
+
- - ! '>='
|
20
|
+
- !ruby/object:Gem::Version
|
21
|
+
version: '0'
|
22
|
+
type: :runtime
|
23
|
+
prerelease: false
|
24
|
+
version_requirements: *70270677942540
|
25
|
+
description: A CYOA game engine
|
26
|
+
email:
|
27
|
+
- ali.ukani@gmail.com
|
28
|
+
executables:
|
29
|
+
- example.rb
|
30
|
+
- kolb.rb
|
31
|
+
extensions: []
|
32
|
+
extra_rdoc_files: []
|
33
|
+
files:
|
34
|
+
- .gitignore
|
35
|
+
- Gemfile
|
36
|
+
- README.markdown
|
37
|
+
- Rakefile
|
38
|
+
- bin/example.rb
|
39
|
+
- bin/kolb.rb
|
40
|
+
- config/kolb.yaml
|
41
|
+
- kolb.gemspec
|
42
|
+
- lib/kolb.rb
|
43
|
+
- lib/kolb/action.rb
|
44
|
+
- lib/kolb/book.rb
|
45
|
+
- lib/kolb/game.rb
|
46
|
+
- lib/kolb/version.rb
|
47
|
+
- test/action_test.rb
|
48
|
+
- test/game_test.rb
|
49
|
+
homepage: http://github.com/ali/kolb
|
50
|
+
licenses: []
|
51
|
+
post_install_message:
|
52
|
+
rdoc_options: []
|
53
|
+
require_paths:
|
54
|
+
- lib
|
55
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
56
|
+
none: false
|
57
|
+
requirements:
|
58
|
+
- - ! '>='
|
59
|
+
- !ruby/object:Gem::Version
|
60
|
+
version: '0'
|
61
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
62
|
+
none: false
|
63
|
+
requirements:
|
64
|
+
- - ! '>='
|
65
|
+
- !ruby/object:Gem::Version
|
66
|
+
version: '0'
|
67
|
+
requirements: []
|
68
|
+
rubyforge_project: kolb
|
69
|
+
rubygems_version: 1.8.15
|
70
|
+
signing_key:
|
71
|
+
specification_version: 3
|
72
|
+
summary: A CYOA game engine
|
73
|
+
test_files:
|
74
|
+
- test/action_test.rb
|
75
|
+
- test/game_test.rb
|
76
|
+
has_rdoc:
|