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.
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