ceml 0.7.13 → 0.8.0
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/Makefile +1 -1
- data/VERSION +1 -1
- data/ceml.gemspec +62 -50
- data/guide/guide.html +69 -14
- data/guide/guide.md +74 -15
- data/guide/guide.pdf +0 -0
- data/lib/ceml/driver.rb +0 -181
- data/lib/ceml/lang/basic_instruction.rb +49 -0
- data/lib/ceml/{casting_statement.rb → lang/casting_statement.rb} +19 -9
- data/lib/ceml/{instruction_statements.rb → lang/instruction_statements.rb} +5 -16
- data/lib/ceml/{script.rb → lang/script.rb} +53 -43
- data/lib/ceml/lang/tt/casting.rb +432 -0
- data/lib/ceml/lang/tt/casting.treetop +29 -0
- data/lib/ceml/lang/tt/instructions.rb +1130 -0
- data/lib/ceml/lang/tt/instructions.treetop +86 -0
- data/lib/ceml/lang/tt/lexer.rb +1804 -0
- data/lib/ceml/{tt → lang/tt}/lexer.treetop +70 -7
- data/lib/ceml/lang/tt/scripts.rb +647 -0
- data/lib/ceml/{tt → lang/tt}/scripts.treetop +2 -2
- data/lib/ceml/lang.rb +10 -0
- data/lib/ceml/models/audition.rb +65 -0
- data/lib/ceml/models/bundle.rb +64 -0
- data/lib/ceml/models/cast.rb +108 -0
- data/lib/ceml/models/castable.rb +81 -0
- data/lib/ceml/{incident.rb → models/incident.rb} +63 -15
- data/lib/ceml/models/incident_model.rb +100 -0
- data/lib/ceml/models/incident_role_slot.rb +16 -0
- data/lib/ceml/models/player.rb +80 -0
- data/lib/ceml/models/queue.rb +12 -0
- data/lib/ceml/models/waiting_room.rb +40 -0
- data/lib/ceml/models.rb +16 -0
- data/lib/ceml/processor.rb +162 -0
- data/lib/ceml.rb +7 -14
- data/test/askchain.ceml +6 -0
- data/test/compliment.ceml +4 -0
- data/test/dialogues/accept.ceml +24 -0
- data/test/dialogues/basic_seed.ceml +26 -0
- data/test/dialogues/jordan.ceml +121 -0
- data/test/helper.rb +44 -39
- data/test/jane.ceml +48 -0
- data/test/{test_casting.rb → lang/test_casting.rb} +5 -0
- data/test/lang/test_instructions.rb +42 -0
- data/test/{test_scripts.rb → lang/test_scripts.rb} +3 -2
- data/test/sync.ceml +6 -0
- data/test/test_castable.rb +20 -0
- data/test/test_dialogues.rb +58 -0
- data/test/test_incident.rb +64 -127
- metadata +54 -30
- data/.gitignore +0 -23
- data/lib/ceml/confluence.rb +0 -63
- data/lib/ceml/role.rb +0 -61
- data/lib/ceml/tt/casting.treetop +0 -65
- data/lib/ceml/tt/instructions.treetop +0 -91
- data/test/test_instructions.rb +0 -27
- data/test/test_release.rb +0 -78
@@ -0,0 +1,162 @@
|
|
1
|
+
require 'redis/objects'
|
2
|
+
|
3
|
+
module Kernel
|
4
|
+
def gen_code(size = 8)
|
5
|
+
rand(36**size).to_s(36)
|
6
|
+
end
|
7
|
+
end
|
8
|
+
|
9
|
+
module CEML
|
10
|
+
class Processor
|
11
|
+
|
12
|
+
# ===================
|
13
|
+
# = scripts/bundles =
|
14
|
+
# ===================
|
15
|
+
|
16
|
+
def set_bundle(id, castables)
|
17
|
+
# log "set_bundle(): #{id}, #{castables.inspect}"
|
18
|
+
Bundle.new(id).castables = castables
|
19
|
+
end
|
20
|
+
|
21
|
+
def reset_bundle(id)
|
22
|
+
Bundle.new(id).reset
|
23
|
+
end
|
24
|
+
|
25
|
+
def run_latest
|
26
|
+
IncidentModel.run_latest(self)
|
27
|
+
end
|
28
|
+
|
29
|
+
|
30
|
+
# =============
|
31
|
+
# = incidents =
|
32
|
+
# =============
|
33
|
+
|
34
|
+
def launch(incident_id, bytecode)
|
35
|
+
incident_id ||= gen_code
|
36
|
+
IncidentModel.new(incident_id).bytecode.value = bytecode
|
37
|
+
end
|
38
|
+
|
39
|
+
def add_cast(incident_id, castings)
|
40
|
+
i = IncidentModel.new(incident_id)
|
41
|
+
i.add_castings(castings)
|
42
|
+
i.run(self)
|
43
|
+
end
|
44
|
+
|
45
|
+
|
46
|
+
# ============
|
47
|
+
# = requests =
|
48
|
+
# ============
|
49
|
+
|
50
|
+
def ping(bundle_id, player)
|
51
|
+
# log "ping(): #{bundle_id}, #{player[:id]}"
|
52
|
+
Player.update(bundle_id, player, self) do |player|
|
53
|
+
if incident_id = Player.new(player[:id]).top_incident_id
|
54
|
+
IncidentModel.new(incident_id).run(self)
|
55
|
+
else
|
56
|
+
if player[:received]
|
57
|
+
player_did_report({:player => player, :squad_id => bundle_id, :city => player[:city]}, nil)
|
58
|
+
end
|
59
|
+
simple_audition(bundle_id, player)
|
60
|
+
end
|
61
|
+
end
|
62
|
+
end
|
63
|
+
|
64
|
+
def reset_player(bundle_id, player_id)
|
65
|
+
Player.new(player_id).reset
|
66
|
+
end
|
67
|
+
|
68
|
+
# =============
|
69
|
+
# = internals =
|
70
|
+
# =============
|
71
|
+
|
72
|
+
def simple_audition(bundle_id, player)
|
73
|
+
log "audition(): #{bundle_id}, #{player[:id]}"
|
74
|
+
b = Bundle.new(bundle_id)
|
75
|
+
b.clear_from_all_rooms(player)
|
76
|
+
if incident_id = b.absorb?(player)
|
77
|
+
IncidentModel.new(incident_id).run(self)
|
78
|
+
return true
|
79
|
+
end
|
80
|
+
player_did_report({:player => player, :squad_id => bundle_id, :city => player[:city]}, nil)
|
81
|
+
b.register_in_rooms(player)
|
82
|
+
end
|
83
|
+
|
84
|
+
def seed(bundle_id, stanza_name, player)
|
85
|
+
log "seed(): #{bundle_id}, #{stanza_name}, #{player[:id]}"
|
86
|
+
b = Bundle.new(bundle_id)
|
87
|
+
if incident_id = b.absorb?(player, stanza_name)
|
88
|
+
IncidentModel.new(incident_id).run(self)
|
89
|
+
return true
|
90
|
+
end
|
91
|
+
b.register_in_rooms(player, stanza_name)
|
92
|
+
end
|
93
|
+
|
94
|
+
# =============
|
95
|
+
# = callbacks =
|
96
|
+
# =============
|
97
|
+
|
98
|
+
def recognize_override(cmd, new_message, player, player_obj)
|
99
|
+
if respond_to?("override_#{cmd}")
|
100
|
+
send("override_#{cmd}", new_message, player, player_obj)
|
101
|
+
true
|
102
|
+
end
|
103
|
+
end
|
104
|
+
|
105
|
+
def override_abort(new_message, player, player_obj)
|
106
|
+
incident = player_obj.top_incident
|
107
|
+
if incident
|
108
|
+
incident.release(player_obj.id)
|
109
|
+
unlatch(player[:squad_id], player[:id], incident.id)
|
110
|
+
player_obj.reset
|
111
|
+
tell(player[:squad_id], player[:id], :message, :msg => 'aborted')
|
112
|
+
else
|
113
|
+
player_obj.reset
|
114
|
+
tell(player[:squad_id], player[:id], :message, :msg => 'nothing to abort from')
|
115
|
+
end
|
116
|
+
end
|
117
|
+
|
118
|
+
def log(s)
|
119
|
+
puts s
|
120
|
+
end
|
121
|
+
|
122
|
+
def player_said(data, what)
|
123
|
+
tell('_', data[:player][:id], what[:key], what)
|
124
|
+
end
|
125
|
+
|
126
|
+
def unlatch(sqid, player_id, incident_id)
|
127
|
+
#no op
|
128
|
+
end
|
129
|
+
|
130
|
+
JUST_SAID = {}
|
131
|
+
def tell(sqid, player_id, key, meta)
|
132
|
+
JUST_SAID[player_id] ||= []
|
133
|
+
JUST_SAID[player_id] << meta.merge(:key => key)
|
134
|
+
# puts "Said #{key} #{meta.inspect}"
|
135
|
+
end
|
136
|
+
|
137
|
+
def player_answered_q(data, what)
|
138
|
+
Player.update data[:player][:bundle_id], data[:player].like(:id, :qs_answers), self
|
139
|
+
end
|
140
|
+
alias_method :player_set, :player_answered_q
|
141
|
+
|
142
|
+
def player_seeded(data, what)
|
143
|
+
p = data[:player].dup
|
144
|
+
p.delete(:roles)
|
145
|
+
p[:seeded] = "#{what[:target]}:#{what[:role]}"
|
146
|
+
puts "SEEDED #{p[:id]} AS #{what[:target]}:#{what[:role]}"
|
147
|
+
|
148
|
+
self.class.seed(p[:bundle_id], what[:target], p)
|
149
|
+
end
|
150
|
+
|
151
|
+
def player_did_report(*args)
|
152
|
+
end
|
153
|
+
|
154
|
+
|
155
|
+
# ====================
|
156
|
+
# = queue processing =
|
157
|
+
# ====================
|
158
|
+
|
159
|
+
def self.method_missing(*args); Queue.new.calls << args; end
|
160
|
+
def self.run(); Queue.new.run(self); end
|
161
|
+
end
|
162
|
+
end
|
data/lib/ceml.rb
CHANGED
@@ -1,30 +1,23 @@
|
|
1
1
|
require 'forwardable'
|
2
|
-
require 'treetop'
|
3
2
|
|
4
|
-
require 'ceml/
|
5
|
-
require 'ceml/
|
6
|
-
require 'ceml/
|
7
|
-
require 'ceml/tt/lexer'
|
8
|
-
require 'ceml/tt/casting'
|
9
|
-
require 'ceml/tt/instructions'
|
10
|
-
require 'ceml/tt/scripts'
|
11
|
-
|
12
|
-
require 'ceml/role'
|
13
|
-
require 'ceml/confluence'
|
14
|
-
require 'ceml/incident'
|
15
|
-
require 'ceml/driver'
|
3
|
+
require 'ceml/models'
|
4
|
+
require 'ceml/lang'
|
5
|
+
require 'ceml/processor'
|
16
6
|
|
17
7
|
module CEML
|
18
8
|
extend self
|
19
9
|
@extra_seconds = 0
|
20
10
|
def clock; Time.now.utc.to_i + @extra_seconds; end
|
21
11
|
def incr_clock(s); @extra_seconds += s; end
|
12
|
+
def dur(n, unit)
|
13
|
+
n * case unit
|
14
|
+
when /^h/; 60*60; when /^mi/; 60; else 1; end
|
15
|
+
end
|
22
16
|
end
|
23
17
|
|
24
18
|
module CEML
|
25
19
|
def parse(what, string)
|
26
20
|
string = string.dup
|
27
|
-
string.gsub!(/\n +/, ' ')
|
28
21
|
what = case what
|
29
22
|
when :script then :free_script
|
30
23
|
when :scripts then :free_scripts
|
data/test/askchain.ceml
ADDED
@@ -0,0 +1,6 @@
|
|
1
|
+
"Meet your neighbor"
|
2
|
+
gather 2 players within 1 block
|
3
|
+
ask players re color: what's your favorite color?
|
4
|
+
ask players re observation: find someone near you with the color |somebody.color|. what are they wearing?
|
5
|
+
ask players re rightmatch: are you wearing |somebody.observation|?
|
6
|
+
ask players re task: take your new partner and see if you can find something beautiful in the park.
|
@@ -0,0 +1,24 @@
|
|
1
|
+
accept 2 new first_signups, many new later_signups
|
2
|
+
seed signup1 with first_signups
|
3
|
+
seed signup2 with later_signups
|
4
|
+
|
5
|
+
(signup1)
|
6
|
+
accept 1 signup
|
7
|
+
tell signup: you're first!
|
8
|
+
|
9
|
+
(signup2)
|
10
|
+
accept 1 signup
|
11
|
+
tell signup: you're second!
|
12
|
+
|
13
|
+
---
|
14
|
+
|
15
|
+
A > hi
|
16
|
+
A < first
|
17
|
+
B > hi
|
18
|
+
B < first
|
19
|
+
C > hi
|
20
|
+
C < second
|
21
|
+
D > hi
|
22
|
+
D < second
|
23
|
+
E > hi
|
24
|
+
E < second
|
@@ -0,0 +1,26 @@
|
|
1
|
+
await 1 new signup
|
2
|
+
ask signup re boots: Do you like boots?
|
3
|
+
tell signup: ok, seeding you now
|
4
|
+
seed match with signup
|
5
|
+
|
6
|
+
(match)
|
7
|
+
await 1 alpha and 1 beta
|
8
|
+
tell alpha: you're alpha
|
9
|
+
tell beta: you're beta
|
10
|
+
|
11
|
+
---
|
12
|
+
|
13
|
+
A > hi
|
14
|
+
A < boots
|
15
|
+
A > of course
|
16
|
+
A < ok
|
17
|
+
A <
|
18
|
+
|
19
|
+
B > hi
|
20
|
+
B < boots
|
21
|
+
B > of course
|
22
|
+
B < ok
|
23
|
+
|
24
|
+
A < alpha
|
25
|
+
B < beta
|
26
|
+
|
@@ -0,0 +1,121 @@
|
|
1
|
+
"Challenge"
|
2
|
+
await 1 new alpha and 1 new beta
|
3
|
+
record both name
|
4
|
+
set both location: San Francisco, CA
|
5
|
+
tell both: Welcome to "The Challenge!"
|
6
|
+
ask both re play: You wanna play?
|
7
|
+
release both unless yes
|
8
|
+
|
9
|
+
tell alpha: Ok, you'll have to complete the following challenge. Let's start with something small.
|
10
|
+
|
11
|
+
tell beta: Great! We'll be in touch soon.
|
12
|
+
|
13
|
+
ask alpha re task: I need you to stop what you're doing, immediately go outside, and run twice around the nearest building. Can you complete this task in 15 minutes or less?
|
14
|
+
|
15
|
+
release alpha unless yes
|
16
|
+
//this will become replace in the future.
|
17
|
+
|
18
|
+
assign alpha: Great! Please text the word 'done' when you're done. And remember, you only have 15 minutes!
|
19
|
+
ask alpha: Amazing work! Now, you get a chance to issue a challenge to a stranger. You in???
|
20
|
+
release alpha unless yes
|
21
|
+
|
22
|
+
ask alpha re challenge: Ok. Text in a new challenge that can be completed from any location. Think of physical or social things that are difficult but still attainable from any location.
|
23
|
+
tell alpha: Thanks for playing! We'll let you know when someone has completed your challenge.
|
24
|
+
|
25
|
+
ask beta re do_it: Another player has issued you a challenge. |alpha.challenge| Can you complete this task in 15 minutes or less?
|
26
|
+
release beta unless yes
|
27
|
+
|
28
|
+
assign beta: Great! Please text the word 'done' when you're done. And remember, you only have 15 minutes!
|
29
|
+
seed challenge_loop with beta as alpha, alpha as omega
|
30
|
+
//seed challenge_loop with beta as alpha, alpha as omega
|
31
|
+
|
32
|
+
|
33
|
+
(challenge_loop)
|
34
|
+
await omega and alpha and beta
|
35
|
+
record beta name
|
36
|
+
set beta location: San Francisco, CA
|
37
|
+
tell beta: Welcome to "The Challenge!"
|
38
|
+
ask beta re play: You wanna play?
|
39
|
+
release beta unless yes
|
40
|
+
|
41
|
+
tell beta: Great! We'll be in touch soon.
|
42
|
+
|
43
|
+
tell alpha: Amazing work! Now, you get a chance to issue a challenge to a stranger. You in???
|
44
|
+
release alpha unless yes
|
45
|
+
|
46
|
+
ask alpha re challenge: Ok. Text in a new challenge that can be completed from any location. Think of physical or social things that are difficult but still attainable from any location.
|
47
|
+
|
48
|
+
ask beta re do_it: Another player has issued you a challenge. |alpha.challenge| Can you complete this task in 15 minutes or less?
|
49
|
+
release beta unless yes
|
50
|
+
|
51
|
+
assign beta: Great! Please text the word 'done' when you're done. And remember, you only have 15 minutes!
|
52
|
+
seed challenge_loop with beta as alpha and alpha as omega and omega as beta
|
53
|
+
//seed challenge_loop with beta as alpha and alpha as omega
|
54
|
+
|
55
|
+
|
56
|
+
---
|
57
|
+
|
58
|
+
J > Jordan
|
59
|
+
J <
|
60
|
+
D > Derek
|
61
|
+
D < Welcome
|
62
|
+
J < Welcome
|
63
|
+
J < You wanna
|
64
|
+
D < You wanna
|
65
|
+
J > Yes
|
66
|
+
D > Yes
|
67
|
+
J < complete the following
|
68
|
+
D < be in touch soon
|
69
|
+
J < need you to stop
|
70
|
+
J > Yes
|
71
|
+
J < Please text
|
72
|
+
J > done
|
73
|
+
J < Amazing work
|
74
|
+
J > Yes
|
75
|
+
J < new challenge
|
76
|
+
J > Do 20 pushups
|
77
|
+
J < Thanks for playing
|
78
|
+
D < Another player has issued
|
79
|
+
D > Yes
|
80
|
+
D < Please text
|
81
|
+
D > done
|
82
|
+
D <
|
83
|
+
|
84
|
+
// K > Kiley
|
85
|
+
// K < Welcome
|
86
|
+
// K < You wanna
|
87
|
+
// K > Yes
|
88
|
+
// K < Awesome!
|
89
|
+
// (20s)
|
90
|
+
// K < If you want to opt out
|
91
|
+
//
|
92
|
+
// P > Paul
|
93
|
+
// P < Welcome
|
94
|
+
// P < You wanna
|
95
|
+
// P > Yes
|
96
|
+
// P < Awesome!
|
97
|
+
// (20s)
|
98
|
+
// P < If you want to opt out
|
99
|
+
//
|
100
|
+
// D < Amazing work
|
101
|
+
// D > Yes
|
102
|
+
// D < new challenge
|
103
|
+
// D > Wave and smile at three strangers on the street
|
104
|
+
// D < Thanks for playing
|
105
|
+
// K < Another player has issued
|
106
|
+
// K > Yes
|
107
|
+
// K < Please text
|
108
|
+
// K > done
|
109
|
+
// K <
|
110
|
+
//
|
111
|
+
// # (challenge_loop2)
|
112
|
+
// # K < Amazing work
|
113
|
+
// # K > Yes
|
114
|
+
// # K < new challenge
|
115
|
+
// # K > Wave and smile at three strangers on the street
|
116
|
+
// # K < Thanks for playing
|
117
|
+
// # P < Another player has issued
|
118
|
+
// # P > Yes
|
119
|
+
// # P < Please text
|
120
|
+
// # P > done
|
121
|
+
// # P <
|
data/test/helper.rb
CHANGED
@@ -1,67 +1,72 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'test/unit'
|
3
3
|
|
4
|
+
SCRIPTS = {}
|
5
|
+
Dir["test/*.ceml"].each do |f|
|
6
|
+
name = File.basename(f, '.ceml')
|
7
|
+
SCRIPTS[name] = File.new(f).read
|
8
|
+
end
|
9
|
+
|
4
10
|
$LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
|
5
11
|
$LOAD_PATH.unshift(File.dirname(__FILE__))
|
6
12
|
require 'ceml'
|
7
13
|
|
8
14
|
class Test::Unit::TestCase
|
9
|
-
DRIVER = CEML::Driver.new
|
10
|
-
|
11
15
|
def play script = nil
|
12
|
-
|
16
|
+
if String === script
|
17
|
+
script = CEML.parse(:script, script)
|
18
|
+
end
|
19
|
+
if script
|
20
|
+
@iid = gen_code
|
21
|
+
puts "launching w. bytecode #{script.bytecode.inspect}"
|
22
|
+
CEML::Processor.launch(@iid, script.bytecode)
|
23
|
+
CEML::Processor.run
|
24
|
+
end
|
13
25
|
yield
|
14
|
-
CEML::
|
15
|
-
CEML::Driver::PLAYERS.clear
|
16
|
-
CEML::Driver::INCIDENTS.clear
|
26
|
+
CEML::Processor::JUST_SAID.clear
|
17
27
|
end
|
18
28
|
|
19
|
-
def scriptfam
|
20
|
-
|
21
|
-
scripts.each do |script|
|
22
|
-
script = CEML.parse(:script, script) if String === script
|
23
|
-
DRIVER.add_script fam_id, script
|
24
|
-
end
|
25
|
-
fam_id
|
29
|
+
def scriptfam scripts
|
30
|
+
CEML.parse(:scripts, scripts).map(&:castable)
|
26
31
|
end
|
27
32
|
|
28
33
|
def ping s, candidate
|
29
|
-
|
34
|
+
CEML::Processor.set_bundle(s.hash.to_s, s)
|
35
|
+
CEML::Processor.ping(s.hash.to_s, candidate)
|
36
|
+
CEML::Processor.run
|
30
37
|
end
|
31
38
|
|
32
39
|
def says id, str
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
DRIVER.post iid, :id => id, :received => str
|
40
|
-
end
|
40
|
+
player = {:id => id.to_s, :received => str}
|
41
|
+
player[:recognized] = :yes if str.downcase == 'y' || str.downcase == 'yes'
|
42
|
+
player[:recognized] = :abort if str == 'abort'
|
43
|
+
puts "SAYING(#{id}): #{str}"
|
44
|
+
CEML::Processor.ping(nil, player)
|
45
|
+
CEML::Processor.run
|
41
46
|
end
|
42
47
|
|
43
|
-
def
|
44
|
-
|
45
|
-
|
46
|
-
|
47
|
-
def roll
|
48
|
-
DRIVER.post @iid
|
48
|
+
def silent id
|
49
|
+
id = id.to_s
|
50
|
+
p = CEML::Processor::JUST_SAID[id]
|
51
|
+
assert !p || p.empty?
|
49
52
|
end
|
50
53
|
|
51
|
-
def
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
54
|
+
def told id, rx
|
55
|
+
id = id.to_s
|
56
|
+
assert CEML::Processor::JUST_SAID[id]
|
57
|
+
assert p = CEML::Processor::JUST_SAID[id].shift
|
58
|
+
assert_match rx, p[:msg] || p[:q]
|
56
59
|
end
|
60
|
+
alias_method :asked, :told
|
57
61
|
|
58
|
-
def
|
59
|
-
|
62
|
+
def player id, role
|
63
|
+
CEML::Player.new(id.to_s).clear_answers
|
64
|
+
CEML::Processor.add_cast(@iid, { role => [{ :id => id.to_s }]})
|
65
|
+
CEML::Processor.run
|
60
66
|
end
|
61
67
|
|
62
|
-
def
|
63
|
-
|
64
|
-
|
65
|
-
CEML::Driver::JUST_SAID.delete id
|
68
|
+
def roll
|
69
|
+
CEML::Processor.run_latest
|
70
|
+
CEML::Processor.run
|
66
71
|
end
|
67
72
|
end
|
data/test/jane.ceml
ADDED
@@ -0,0 +1,48 @@
|
|
1
|
+
await 1 new signup
|
2
|
+
record signup first_name
|
3
|
+
ask signup re shoeless:
|
4
|
+
Hello |his.first_name|. You are Level Zero. Lowly level zero.
|
5
|
+
To advance to Level 1, please remove a shoe. Keep it off,
|
6
|
+
and text back "shoeless".
|
7
|
+
tell signup:
|
8
|
+
O ho! Well done |his.first_name|. Now the other players
|
9
|
+
know you're in the game, too. But you're still a sad Level 1.
|
10
|
+
ask signup re game:
|
11
|
+
To advance to Level 2, answer this question. What was your
|
12
|
+
favorite game when you were 10 years old? Tell me now.
|
13
|
+
tell signup:
|
14
|
+
Ah yes. |his.game| WAS an amazing game. You should try to play
|
15
|
+
it again--sometime this week, perhaps?
|
16
|
+
In the meantime you are but a mere Level 2. Let's see if we can do
|
17
|
+
something about that. (You still have your shoe off, right?)
|
18
|
+
ask signup re friend:
|
19
|
+
While you're texting... Pick someone in your address book you
|
20
|
+
haven't talked to in a while. Send them an SMS
|
21
|
+
just to say hello. Then tell me their first name.
|
22
|
+
tell signup:
|
23
|
+
That was awfully nice of you to message |his.friend|
|
24
|
+
Welcome to the amazing Level 3. You'll like it here. Stay awhile.
|
25
|
+
tell signup:
|
26
|
+
Just kidding. Level 4 is way better than this. To get to
|
27
|
+
Level 4, wait for an appropriate moment in Jane's talk
|
28
|
+
and shout an encouraging "Amen!" Yes. Out loud.
|
29
|
+
ask signup re amen:
|
30
|
+
If you're not the spiritual type, a forceful "YEAH!" will do.
|
31
|
+
When you've accomplished your mission, text me "amen".
|
32
|
+
tell signup:
|
33
|
+
Wow. I didn't think you had it in you. No one has ever gotten to
|
34
|
+
Level 4 before. This is VERY exciting.
|
35
|
+
tell signup:
|
36
|
+
If you get to Level 5, I'll give you a secret password. Tell it to
|
37
|
+
Jane, and you'll get some very fancy loot.
|
38
|
+
ask signup re ovation:
|
39
|
+
All you have to do is wait until the end of Jane's talk--and try to
|
40
|
+
spark a standing ovation. Good luck! Text ovation afterward for your
|
41
|
+
password.
|
42
|
+
tell signup:
|
43
|
+
You did it! You are Level 5. You are AMAZING. The conquering hero of
|
44
|
+
the entire audience! Now I can give you your password.
|
45
|
+
tell signup:
|
46
|
+
Ask Jane to sign a copy of her book to Mr. Gamey McGameful. Of course,
|
47
|
+
this will only work if she saw you standing in that ovation. You were
|
48
|
+
standing, right?
|
@@ -19,6 +19,7 @@ class TestCasting < Test::Unit::TestCase
|
|
19
19
|
assert_bad "gather 4 *runners"
|
20
20
|
assert_bad "gather 4 run*ners"
|
21
21
|
assert_bad "gather 4 runners*"
|
22
|
+
assert_bad "() gather a-b runners"
|
22
23
|
end
|
23
24
|
|
24
25
|
def test_range
|
@@ -74,4 +75,8 @@ class TestCasting < Test::Unit::TestCase
|
|
74
75
|
assert !pcs("gather 3 runners and 5 hot_babes").radius
|
75
76
|
end
|
76
77
|
|
78
|
+
def test_stanza
|
79
|
+
assert_equal 'woot', pcs("(woot)\nawait 3 runners and 5 hot_babes within 3 blocks").stanza_name
|
80
|
+
end
|
81
|
+
|
77
82
|
end
|
@@ -0,0 +1,42 @@
|
|
1
|
+
require 'ceml'
|
2
|
+
|
3
|
+
class TestInstructions < Test::Unit::TestCase
|
4
|
+
def pi text
|
5
|
+
CEML.parse(:instructions, text)
|
6
|
+
end
|
7
|
+
|
8
|
+
def ps text
|
9
|
+
CEML.parse(:script, text)
|
10
|
+
end
|
11
|
+
|
12
|
+
def assert_bad text
|
13
|
+
assert_raise(RuntimeError){ pi text }
|
14
|
+
end
|
15
|
+
|
16
|
+
def test_bad
|
17
|
+
assert_bad "love your mother"
|
18
|
+
assert_bad "tell jim re susan: i hate you"
|
19
|
+
assert_bad "tell phil"
|
20
|
+
assert_bad "ask susan re clothing"
|
21
|
+
assert_bad "ask susan re clothing: "
|
22
|
+
assert_bad "seed X with"
|
23
|
+
assert_bad "seed X with foo as "
|
24
|
+
assert_bad "pick X from"
|
25
|
+
end
|
26
|
+
|
27
|
+
def test_instructions
|
28
|
+
ps("seed X with Y").bytecode
|
29
|
+
ps("seed X with Y as Z").bytecode
|
30
|
+
# puts x.bytecode.inspect
|
31
|
+
# pi "pick X from a, b, c or d"
|
32
|
+
pi "pick foo bar:\n lalalala\n babababa"
|
33
|
+
pi "replace finder unless yes"
|
34
|
+
x = ps('tell joe: run to the kitchen')
|
35
|
+
# p x
|
36
|
+
assert_equal "run to the kitchen", x.simple_message
|
37
|
+
# assert_equal ["favorite color?", "favorite soup?"], pi(
|
38
|
+
# "ask joe re color: favorite color?\nask joe re soup: favorite soup?"
|
39
|
+
# ).i_asks([:joe]).map(&:text)
|
40
|
+
end
|
41
|
+
|
42
|
+
end
|
@@ -4,6 +4,7 @@ class TestScripts < Test::Unit::TestCase
|
|
4
4
|
|
5
5
|
SCRIPTS = <<END_OF_SCRIPTS
|
6
6
|
"Help moving |an object|" // okay?
|
7
|
+
(stanza_title)
|
7
8
|
gather 2-6 movers within 8 blocks
|
8
9
|
|
9
10
|
"Cleaning up |a public place|"
|
@@ -43,14 +44,14 @@ END_OF_SCRIPTS
|
|
43
44
|
def test_ceml_tell
|
44
45
|
cs = CEML.parse(:script, "tell agents: run and jump")
|
45
46
|
assert cs.roles.include? :agents
|
46
|
-
assert_equal "run and jump", cs.
|
47
|
+
assert_equal "run and jump", cs.simple_message
|
47
48
|
assert cs.concludes_immediately?
|
48
49
|
assert !cs.title
|
49
50
|
end
|
50
51
|
|
51
52
|
def test_ceml_questions
|
52
53
|
s = CEML.parse(:script, "ask agents: wassup party people?")
|
53
|
-
assert_equal "wassup party people?", s.
|
54
|
+
assert_equal "wassup party people?", s.simple_question
|
54
55
|
assert !s.concludes_immediately?
|
55
56
|
end
|
56
57
|
|
data/test/sync.ceml
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
require 'test/unit'
|
2
|
+
require 'ceml'
|
3
|
+
|
4
|
+
class TestCastable < Test::Unit::TestCase
|
5
|
+
|
6
|
+
def test_castable
|
7
|
+
s = CEML.parse(:script, "await 1 alpha and 1 beta\ntell both: hi")
|
8
|
+
assert cast = s.castable.cast_from([{ :id => 'jim' }, { :id => 'bob' }])
|
9
|
+
assert cast.folks.size == 2
|
10
|
+
assert cast['alpha'].size == 1
|
11
|
+
assert cast['beta'].size == 1
|
12
|
+
end
|
13
|
+
|
14
|
+
# next, create a waiting room and add jim and bob and verify that an incident is started
|
15
|
+
|
16
|
+
# add jim and bob one at a time, and verify that an incident is started
|
17
|
+
|
18
|
+
# add two people that don't satisfy the criteria, then a third who matches
|
19
|
+
|
20
|
+
end
|