ceml 0.7.13 → 0.8.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (55) hide show
  1. data/Makefile +1 -1
  2. data/VERSION +1 -1
  3. data/ceml.gemspec +62 -50
  4. data/guide/guide.html +69 -14
  5. data/guide/guide.md +74 -15
  6. data/guide/guide.pdf +0 -0
  7. data/lib/ceml/driver.rb +0 -181
  8. data/lib/ceml/lang/basic_instruction.rb +49 -0
  9. data/lib/ceml/{casting_statement.rb → lang/casting_statement.rb} +19 -9
  10. data/lib/ceml/{instruction_statements.rb → lang/instruction_statements.rb} +5 -16
  11. data/lib/ceml/{script.rb → lang/script.rb} +53 -43
  12. data/lib/ceml/lang/tt/casting.rb +432 -0
  13. data/lib/ceml/lang/tt/casting.treetop +29 -0
  14. data/lib/ceml/lang/tt/instructions.rb +1130 -0
  15. data/lib/ceml/lang/tt/instructions.treetop +86 -0
  16. data/lib/ceml/lang/tt/lexer.rb +1804 -0
  17. data/lib/ceml/{tt → lang/tt}/lexer.treetop +70 -7
  18. data/lib/ceml/lang/tt/scripts.rb +647 -0
  19. data/lib/ceml/{tt → lang/tt}/scripts.treetop +2 -2
  20. data/lib/ceml/lang.rb +10 -0
  21. data/lib/ceml/models/audition.rb +65 -0
  22. data/lib/ceml/models/bundle.rb +64 -0
  23. data/lib/ceml/models/cast.rb +108 -0
  24. data/lib/ceml/models/castable.rb +81 -0
  25. data/lib/ceml/{incident.rb → models/incident.rb} +63 -15
  26. data/lib/ceml/models/incident_model.rb +100 -0
  27. data/lib/ceml/models/incident_role_slot.rb +16 -0
  28. data/lib/ceml/models/player.rb +80 -0
  29. data/lib/ceml/models/queue.rb +12 -0
  30. data/lib/ceml/models/waiting_room.rb +40 -0
  31. data/lib/ceml/models.rb +16 -0
  32. data/lib/ceml/processor.rb +162 -0
  33. data/lib/ceml.rb +7 -14
  34. data/test/askchain.ceml +6 -0
  35. data/test/compliment.ceml +4 -0
  36. data/test/dialogues/accept.ceml +24 -0
  37. data/test/dialogues/basic_seed.ceml +26 -0
  38. data/test/dialogues/jordan.ceml +121 -0
  39. data/test/helper.rb +44 -39
  40. data/test/jane.ceml +48 -0
  41. data/test/{test_casting.rb → lang/test_casting.rb} +5 -0
  42. data/test/lang/test_instructions.rb +42 -0
  43. data/test/{test_scripts.rb → lang/test_scripts.rb} +3 -2
  44. data/test/sync.ceml +6 -0
  45. data/test/test_castable.rb +20 -0
  46. data/test/test_dialogues.rb +58 -0
  47. data/test/test_incident.rb +64 -127
  48. metadata +54 -30
  49. data/.gitignore +0 -23
  50. data/lib/ceml/confluence.rb +0 -63
  51. data/lib/ceml/role.rb +0 -61
  52. data/lib/ceml/tt/casting.treetop +0 -65
  53. data/lib/ceml/tt/instructions.treetop +0 -91
  54. data/test/test_instructions.rb +0 -27
  55. 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/script'
5
- require 'ceml/casting_statement'
6
- require 'ceml/instruction_statements'
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
@@ -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,4 @@
1
+ "Overwhelm a specific person with compliments"
2
+ gather 5-20 players within 4 blocks
3
+ ask organizer re target: Describe their appearance and location
4
+ tell agents: Look for |somebody.target| and compliment them briefly, then move on.
@@ -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
- @iid = script && DRIVER.start(nil, script)
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::Driver::JUST_SAID.clear
15
- CEML::Driver::PLAYERS.clear
16
- CEML::Driver::INCIDENTS.clear
26
+ CEML::Processor::JUST_SAID.clear
17
27
  end
18
28
 
19
- def scriptfam *scripts
20
- fam_id = gen_code
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
- DRIVER.ping_all s, candidate
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
- iid = CEML::Driver::INCIDENTS.keys.find do |iid|
34
- CEML::Driver::PLAYERS[iid].find{ |p| p[:id] == id }
35
- end
36
- if str == 'y'
37
- DRIVER.post iid, :id => id, :received => str, :recognized => :yes
38
- else
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 player id, *roles
44
- DRIVER.post @iid, :id => id, :roles => roles
45
- end
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 asked id, rx
52
- assert p = CEML::Driver::JUST_SAID[id]
53
- assert_equal :ask, p[:said]
54
- assert_match rx, p[:q]
55
- CEML::Driver::JUST_SAID.delete id
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 silent id
59
- assert !CEML::Driver::JUST_SAID[id]
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 told id, rx
63
- assert p = CEML::Driver::JUST_SAID[id]
64
- assert_match rx, p[:msg]
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.instructions.tell([:agents]).text
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.instructions.asks([:agents]).first.text
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,6 @@
1
+ await 1 new alpha and 1 new beta
2
+ ask alpha re color: What color?
3
+ ask beta re color: What color?
4
+ sync both
5
+ tell alpha: Hi there
6
+ tell beta: Goodbye
@@ -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