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