silver-tongue 0.5.0 → 0.6.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.
package/README.md CHANGED
@@ -2,7 +2,7 @@
2
2
 
3
3
  > You arrive speaking pidgin; you leave with a silver tongue.
4
4
 
5
- A language-learning life game. Your phone is dead, your wallet is gone, and you're standing on a street in a Chinese city with ¥20 in your pocket. An old man on a bench teaches you your first words, and later explains how the language works when you ask; after that you earn your living by understanding people. Every job, purchase and conversation happens in the language you're learning.
5
+ A language-learning life game. Your phone is dead, your wallet is gone, and you're standing on a street in a Chinese city with ¥20 in your pocket. You start by telling the game your name. An old man on a bench teaches you your first words, and later explains how the language works when you ask; after that you earn your living by understanding people. Every job, purchase and conversation happens in the language you're learning.
6
6
 
7
7
  The first course is Mandarin (HSK 1), in a Chinese city, explained in English.
8
8
 
@@ -1 +1 @@
1
- {"id":"zh-china-en","typing":false,"words":{"w0003":{"id":"w0003","w":"三","lv":"1","gloss":"three; 3","pron":"sān"},"w0009":{"id":"w0009","w":"不","lv":"1","gloss":"no; not","pron":"bù"},"w0010":{"id":"w0010","w":"不客气","lv":"1","gloss":"you're welcome; don't mention it","pron":"bùkèqi"},"w0018":{"id":"w0018","w":"了","lv":"1","gloss":"(completed action marker)","pron":"le"},"w0020":{"id":"w0020","w":"五","lv":"1","gloss":"five; 5","pron":"wǔ"},"w0023":{"id":"w0023","w":"什么","lv":"1","gloss":"what?; something","pron":"shénme"},"w0028":{"id":"w0028","w":"你","lv":"1","gloss":"you (informal)","pron":"nǐ"},"w0034":{"id":"w0034","w":"再见","lv":"1","gloss":"goodbye","pron":"zàijiàn"},"w0037":{"id":"w0037","w":"几","lv":"1","gloss":"how much; how many","pron":"jǐ"},"w0046":{"id":"w0046","w":"叫","lv":"1","gloss":"to shout; to call","pron":"jiào"},"w0047":{"id":"w0047","w":"吃","lv":"1","gloss":"to eat; to consume; to eat at (a cafeteria etc)","pron":"chī"},"w0049":{"id":"w0049","w":"名字","lv":"1","gloss":"name (of a person or thing)","pron":"míngzi"},"w0051":{"id":"w0051","w":"吗","lv":"1","gloss":"(question particle for \"yes-no\" questions)","pron":"ma"},"w0053":{"id":"w0053","w":"呢","lv":"1","gloss":"particle indicating that a previously asked question is…","pron":"ne"},"w0058":{"id":"w0058","w":"喜欢","lv":"1","gloss":"to like; to be fond of","pron":"xǐhuan"},"w0060":{"id":"w0060","w":"四","lv":"1","gloss":"four; 4","pron":"sì"},"w0072":{"id":"w0072","w":"好","lv":"1","gloss":"good; appropriate; proper","pron":"hǎo"},"w0079":{"id":"w0079","w":"对不起","lv":"1","gloss":"I'm sorry; excuse me; I beg your pardon","pron":"duìbuqǐ"},"w0084":{"id":"w0084","w":"工作","lv":"1","gloss":"to work; (of a machine) to operate","pron":"gōngzuò"},"w0087":{"id":"w0087","w":"很","lv":"1","gloss":"(adverb of degree); quite","pron":"hěn"},"w0091":{"id":"w0091","w":"我","lv":"1","gloss":"I; me; my","pron":"wǒ"},"w0099":{"id":"w0099","w":"是","lv":"1","gloss":"to be (followed by substantives only); correct; right; true","pron":"shì"},"w0101":{"id":"w0101","w":"有","lv":"1","gloss":"to have; there is","pron":"yǒu"},"w0102":{"id":"w0102","w":"朋友","lv":"1","gloss":"friend","pron":"péngyou"},"w0108":{"id":"w0108","w":"水","lv":"1","gloss":"water; river","pron":"shuǐ"},"w0112":{"id":"w0112","w":"没关系","lv":"1","gloss":"it doesn't matter","pron":"méiguānxi"},"w0133":{"id":"w0133","w":"茶","lv":"1","gloss":"tea; tea plant","pron":"chá"},"w0141":{"id":"w0141","w":"谢谢","lv":"1","gloss":"to thank; thanks","pron":"xièxie"},"w0143":{"id":"w0143","w":"那","lv":"1","gloss":"(specifier) that; the; those (colloquial pr. [nèi])","pron":"nà"},"w0145":{"id":"w0145","w":"里","lv":"1","gloss":"lining; interior","pron":"lǐ"},"w0149":{"id":"w0149","w":"饭馆","lv":"1","gloss":"restaurant","pron":"fànguǎn"},"w0583":{"id":"w0583","w":"面条","lv":"3","gloss":"noodles","pron":"miàntiáo","bonus":true},"w0587":{"id":"w0587","w":"饿","lv":"3","gloss":"to be hungry; hungry","pron":"è","bonus":true},"x0001":{"id":"x0001","w":"杯","lv":"1","gloss":"cup; glass (measure word for drinks)","pron":"bēi","bonus":true},"x0002":{"id":"x0002","w":"老王","lv":"1","gloss":"Old Wang (a name: 老 \"old\" + the surname Wang)","pron":"Lǎo Wáng","bonus":true},"x0003":{"id":"x0003","w":"小马","lv":"1","gloss":"Xiao Ma, your Chinese name (小 \"little\" + 马 \"horse\")","pron":"Xiǎo Mǎ","bonus":true},"x0004":{"id":"x0004","w":"小张","lv":"1","gloss":"Xiao Zhang, the cook (小 \"little\" + the surname Zhang)","pron":"Xiǎo Zhāng","bonus":true}},"concepts":{"tea":["w0133"],"water":["w0108"],"three":["w0003"],"four":["w0060"],"five":["w0020"],"hello":["w0028","w0072"],"thanks":["w0141"],"sorry":["w0079"],"bye":["w0034"]},"groups":{"courtesies":["hello","thanks","sorry"],"drinks":["tea","water"],"numbers_3_5":["three","four","five"]},"world":{"start":"street","currency":"¥","slotsPerDay":4,"startWallet":20,"foodPerDay":5,"rentPerWeek":50,"places":{"street":{"links":["noodle_shop"]},"noodle_shop":{"links":["street"]}},"npcs":{"wang":{"place":"street"},"cook":{"place":"noodle_shop"}},"mentor":{"npc":"wang","after":"street-hello"}},"scenes":[{"id":"noodle-intro","place":"noodle_shop","npc":"cook","stage":1,"after":["street-hungry"],"requires":{},"repeatable":false,"trustGain":1,"exchanges":[{"id":"greet","slots":{},"expect":{"action":"greet"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!你叫什么名字?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":4,"word":"w0028"},{"start":4,"end":5,"word":"w0046"},{"start":5,"end":7,"word":"w0023"},{"start":7,"end":9,"word":"w0049"}],"meaning":"Hello! What's your name?"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"你叫小马。","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"Your name is Xiao Ma."}]}}},{"id":"names","slots":{},"expect":{"action":"names"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"我叫小张。你呢?","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0004"},{"start":5,"end":6,"word":"w0028"},{"start":6,"end":7,"word":"w0053"}],"meaning":"My name is Xiao Zhang. And you?"},"reply":{"text":"我叫小马。老王是我朋友。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"},{"start":5,"end":7,"word":"x0002"},{"start":7,"end":8,"word":"w0099"},{"start":8,"end":9,"word":"w0091"},{"start":9,"end":11,"word":"w0102"}],"meaning":"My name is Xiao Ma. Old Wang is my friend."},"alts":[{"text":"我叫小张。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0004"}],"meaning":"My name is Xiao Zhang."},{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}]}}},{"id":"job","slots":{},"expect":{"action":"job"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"工作,好吗?","tokens":[{"start":0,"end":2,"word":"w0084"},{"start":3,"end":4,"word":"w0072"},{"start":4,"end":5,"word":"w0051"}],"meaning":"Want to work here?"},"reply":{"text":"好。","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"OK."},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."}]}}}]},{"id":"noodle-shift","place":"noodle_shop","npc":"cook","stage":1,"after":["noodle-intro"],"requires":{"trust":{"cook":1}},"repeatable":true,"trustGain":1,"exchanges":[{"id":"drink","slots":{"item":"drinks"},"expect":{"action":"fetch","item":"$item"},"hinges":["$item"],"pay":1,"missCost":1,"variants":{"item=tea":{"npc":{"text":"茶。","tokens":[{"start":0,"end":1,"word":"w0133"}],"meaning":"Tea."},"reply":{"text":"好,茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0133"}],"meaning":"OK, tea."}},"item=water":{"npc":{"text":"水。","tokens":[{"start":0,"end":1,"word":"w0108"}],"meaning":"Water."},"reply":{"text":"好,水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0108"}],"meaning":"OK, water."}}}},{"id":"order","slots":{"item":"drinks","count":"numbers_3_5"},"expect":{"action":"serve","item":"$item","count":"$count"},"hinges":["$item","$count"],"pay":3,"missCost":2,"variants":{"count=three|item=tea":{"npc":{"text":"三杯茶。","tokens":[{"start":0,"end":1,"word":"w0003"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0133"}],"meaning":"Three cups of tea."},"reply":{"text":"好,三杯茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0133"}],"meaning":"OK, three cups of tea."},"rephrase":{"text":"茶。三杯。","tokens":[{"start":0,"end":1,"word":"w0133"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Tea. Three cups."}},"count=three|item=water":{"npc":{"text":"三杯水。","tokens":[{"start":0,"end":1,"word":"w0003"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0108"}],"meaning":"Three cups of water."},"reply":{"text":"好,三杯水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0108"}],"meaning":"OK, three cups of water."},"rephrase":{"text":"水。三杯。","tokens":[{"start":0,"end":1,"word":"w0108"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Water. Three cups."}},"count=four|item=tea":{"npc":{"text":"四杯茶。","tokens":[{"start":0,"end":1,"word":"w0060"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0133"}],"meaning":"Four cups of tea."},"reply":{"text":"好,四杯茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0133"}],"meaning":"OK, four cups of tea."},"rephrase":{"text":"茶。四杯。","tokens":[{"start":0,"end":1,"word":"w0133"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Tea. Four cups."}},"count=four|item=water":{"npc":{"text":"四杯水。","tokens":[{"start":0,"end":1,"word":"w0060"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0108"}],"meaning":"Four cups of water."},"reply":{"text":"好,四杯水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0108"}],"meaning":"OK, four cups of water."},"rephrase":{"text":"水。四杯。","tokens":[{"start":0,"end":1,"word":"w0108"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Water. Four cups."}},"count=five|item=tea":{"npc":{"text":"五杯茶。","tokens":[{"start":0,"end":1,"word":"w0020"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0133"}],"meaning":"Five cups of tea."},"reply":{"text":"好,五杯茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0133"}],"meaning":"OK, five cups of tea."},"rephrase":{"text":"茶。五杯。","tokens":[{"start":0,"end":1,"word":"w0133"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Tea. Five cups."}},"count=five|item=water":{"npc":{"text":"五杯水。","tokens":[{"start":0,"end":1,"word":"w0020"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0108"}],"meaning":"Five cups of water."},"reply":{"text":"好,五杯水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0108"}],"meaning":"OK, five cups of water."},"rephrase":{"text":"水。五杯。","tokens":[{"start":0,"end":1,"word":"w0108"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Water. Five cups."}}}}]},{"id":"street-hello","place":"street","npc":"wang","stage":1,"after":[],"requires":{},"repeatable":false,"trustGain":1,"exchanges":[{"id":"hello","slots":{},"expect":{"action":"hello"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"alts":[{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Good!"}]}}},{"id":"wang","slots":{},"expect":{"action":"wang"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"老王!","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang!"},"reply":{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"},"alts":[{"text":"老王!","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang!"},{"text":"好,老王!","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":4,"word":"x0002"}],"meaning":"OK, Old Wang!"}]}}},{"id":"how","slots":{},"expect":{"action":"how"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":2,"end":3,"word":"w0051"}],"meaning":"How are you?"},"reply":{"text":"很好!你好吗?","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":4,"word":"w0028"},{"start":4,"end":5,"word":"w0072"},{"start":5,"end":6,"word":"w0051"}],"meaning":"Very well! How are you?"},"alts":[{"text":"老王!","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang!"},{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"}]}}},{"id":"name","slots":{},"expect":{"action":"name"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"很好!叫我老王。","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":4,"word":"w0046"},{"start":4,"end":5,"word":"w0091"},{"start":5,"end":7,"word":"x0002"}],"meaning":"Very well! Call me Old Wang."},"reply":{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"},"alts":[{"text":"我叫老王。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0002"}],"meaning":"My name is Old Wang."},{"text":"很好!","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Very well!"}]}}},{"id":"naming","slots":{},"expect":{"action":"naming"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你叫小马!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"Your name is Xiao Ma!"},"reply":{"text":"我叫小马?","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma?"},"alts":[{"text":"你叫小马!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"Your name is Xiao Ma!"},{"text":"我叫老王?","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0002"}],"meaning":"My name is Old Wang?"}]}}},{"id":"ask","slots":{},"expect":{"action":"ask"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你叫什么名字?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"w0023"},{"start":4,"end":6,"word":"w0049"}],"meaning":"What's your name?"},"reply":{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."},"alts":[{"text":"我叫老王。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0002"}],"meaning":"My name is Old Wang."},{"text":"你叫小马。","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"Your name is Xiao Ma."},{"text":"很好!","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Very well!"}]}}},{"id":"bye","slots":{},"expect":{"action":"bye"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},"reply":{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},"alts":[{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},{"text":"很好!","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Very well!"}]}}}]},{"id":"street-hungry","place":"street","npc":"wang","stage":1,"after":["street-hello"],"requires":{},"repeatable":false,"trustGain":1,"exchanges":[{"id":"hungry","slots":{},"expect":{"action":"hungry"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"小马,你好吗?","tokens":[{"start":0,"end":2,"word":"x0003"},{"start":3,"end":4,"word":"w0028"},{"start":4,"end":5,"word":"w0072"},{"start":5,"end":6,"word":"w0051"}],"meaning":"Xiao Ma, how are you?"},"reply":{"text":"我饿了。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0587"},{"start":2,"end":3,"word":"w0018"}],"meaning":"I'm hungry."},"alts":[{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."},{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"}]}}},{"id":"noodles","slots":{},"expect":{"action":"noodles"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"吃面条吗?","tokens":[{"start":0,"end":1,"word":"w0047"},{"start":1,"end":3,"word":"w0583"},{"start":3,"end":4,"word":"w0051"}],"meaning":"Want some noodles?"},"reply":{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Yes, please!"},"alts":[{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."},{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"}]}}},{"id":"like","slots":{},"expect":{"action":"like"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你喜欢面条吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":3,"word":"w0058"},{"start":3,"end":5,"word":"w0583"},{"start":5,"end":6,"word":"w0051"}],"meaning":"Do you like noodles?"},"reply":{"text":"喜欢!我喜欢面条。","tokens":[{"start":0,"end":2,"word":"w0058"},{"start":3,"end":4,"word":"w0091"},{"start":4,"end":6,"word":"w0058"},{"start":6,"end":8,"word":"w0583"}],"meaning":"I do! I like noodles."},"alts":[{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."},{"text":"再见,老王!","tokens":[{"start":0,"end":2,"word":"w0034"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Goodbye, Old Wang!"}]}}},{"id":"there","slots":{},"expect":{"action":"there"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"那里!","tokens":[{"start":0,"end":1,"word":"w0143"},{"start":1,"end":2,"word":"w0145"}],"meaning":"There!"},"reply":{"text":"那里?","tokens":[{"start":0,"end":1,"word":"w0143"},{"start":1,"end":2,"word":"w0145"}],"meaning":"There?"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."}]}}},{"id":"shop","slots":{},"expect":{"action":"shop"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"那里有饭馆。","tokens":[{"start":0,"end":1,"word":"w0143"},{"start":1,"end":2,"word":"w0145"},{"start":2,"end":3,"word":"w0101"},{"start":3,"end":5,"word":"w0149"}],"meaning":"There's a restaurant there."},"reply":{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Good!"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"你叫小马。","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"Your name is Xiao Ma."}]}}},{"id":"zhang","slots":{},"expect":{"action":"zhang"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"小张!","tokens":[{"start":0,"end":2,"word":"x0004"}],"meaning":"Xiao Zhang!"},"reply":{"text":"小张?","tokens":[{"start":0,"end":2,"word":"x0004"}],"meaning":"Xiao Zhang?"},"alts":[{"text":"老王?","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang?"},{"text":"小马?","tokens":[{"start":0,"end":2,"word":"x0003"}],"meaning":"Xiao Ma?"}]}}},{"id":"friend","slots":{},"expect":{"action":"friend"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"小张是我朋友。","tokens":[{"start":0,"end":2,"word":"x0004"},{"start":2,"end":3,"word":"w0099"},{"start":3,"end":4,"word":"w0091"},{"start":4,"end":6,"word":"w0102"}],"meaning":"Xiao Zhang is my friend."},"reply":{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Good!"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"你叫小马。","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"Your name is Xiao Ma."}]}}},{"id":"bye","slots":{},"expect":{"action":"bye"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"再见,小马!","tokens":[{"start":0,"end":2,"word":"w0034"},{"start":3,"end":5,"word":"x0003"}],"meaning":"Goodbye, Xiao Ma!"},"reply":{"text":"谢谢!再见!","tokens":[{"start":0,"end":2,"word":"w0141"},{"start":3,"end":5,"word":"w0034"}],"meaning":"Thank you! Goodbye!"},"alts":[{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"},{"text":"我叫小马。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0003"}],"meaning":"My name is Xiao Ma."}]}}}]},{"id":"street-practice","place":"street","npc":"wang","stage":1,"after":["street-hello"],"requires":{},"repeatable":true,"trustGain":1,"exchanges":[{"id":"hello","slots":{},"expect":{"action":"greet"},"hinges":["hello"],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}}}},{"id":"polite-1","slots":{"said":"courtesies"},"expect":{"action":"answer","said":"$said"},"hinges":["$said"],"pay":0,"missCost":0,"variants":{"said=hello":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}},"said=thanks":{"npc":{"text":"谢谢!","tokens":[{"start":0,"end":2,"word":"w0141"}],"meaning":"Thank you!"},"reply":{"text":"不客气!","tokens":[{"start":0,"end":3,"word":"w0010"}],"meaning":"You're welcome!"}},"said=sorry":{"npc":{"text":"对不起!","tokens":[{"start":0,"end":3,"word":"w0079"}],"meaning":"Sorry!"},"reply":{"text":"没关系!","tokens":[{"start":0,"end":3,"word":"w0112"}],"meaning":"That's all right!"}}}},{"id":"polite-2","slots":{"said":"courtesies"},"expect":{"action":"answer","said":"$said"},"hinges":["$said"],"pay":0,"missCost":0,"variants":{"said=hello":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}},"said=thanks":{"npc":{"text":"谢谢!","tokens":[{"start":0,"end":2,"word":"w0141"}],"meaning":"Thank you!"},"reply":{"text":"不客气!","tokens":[{"start":0,"end":3,"word":"w0010"}],"meaning":"You're welcome!"}},"said=sorry":{"npc":{"text":"对不起!","tokens":[{"start":0,"end":3,"word":"w0079"}],"meaning":"Sorry!"},"reply":{"text":"没关系!","tokens":[{"start":0,"end":3,"word":"w0112"}],"meaning":"That's all right!"}}}},{"id":"bye","slots":{},"expect":{"action":"farewell"},"hinges":["bye"],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},"reply":{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"}}}}]}],"reactions":{"wrong-generic":{"text":"不是。","tokens":[{"start":0,"end":1,"word":"w0009"},{"start":1,"end":2,"word":"w0099"}],"meaning":"No."},"wrong-count":{"text":"几杯?","tokens":[{"start":0,"end":1,"word":"w0037"},{"start":1,"end":2,"word":"x0001"}],"meaning":"How many cups?"}},"learnerFtl":"# Text-game UI. Every id here is required by packages/tui (UI_KEYS).\n\nhud = Day { $day } · slot { $slot }/{ $slots } · { $currency }{ $wallet } · { $rank }{ $rentLate ->\n [yes] { \" · rent due\" }\n *[no] {\"\"}\n}\n\nrank-0 = Pidgin\nrank-1 = Getting By\nrank-2 = Conversational\nrank-3 = Fluent\nrank-4 = Silver Tongue\n\nmenu-title = What now?\nmenu-talk = Talk to { $npc }: { $scene }\nmenu-go = Go to { $place }\nmenu-mentor = Ask { $npc } about the language\ncost-slot = { \" · 1 slot\" }\nmenu-sleep = Sleep (end the day)\nmenu-quit = Save and quit\n\nkeys-explore = [{ $keys }] choose · [n] notebook · [q] quit\nkeys-pick = [{ $keys }] reply · [w] word help · [n] notebook\nkeys-tiles = [{ $keys }] add · [⌫] undo · [enter] say · [w] help · [n] notebook\nkeys-help = [{ $keys }] look up · [esc] back\nkeys-help-sentence = [{ $keys }] look up · [s] whole sentence · [esc] back\n\nhelp-title = Which word?\nhelp-sentence = The whole sentence\nhelp-in-replies = In the replies:\nreply-title = Your reply:\ntiles-title = Your reply: tap the words in order, then press [enter].\ntiles-answer = You say:\nyou = You\n\nmismatch = That's not what they asked for.\nrephrased = (slower)\nwallet-change = { $sign }{ $currency }{ $amount } ({ $reason })\nreason-wages = wages\nreason-mixup = mix-up\nreason-food = food\nreason-rent = rent\ntrust-up = { $npc } trusts you a little more ({ $trust }).\nscene-done = { $earned ->\n [0] Done.\n *[other] Done. You earned { $currency }{ $earned }.\n}\nunlocked = New: { $scene }\nrank-up = You're now: { $rank }\nday-ended = Day { $day } is over. You sleep.\nreject-unknown-scene = There's nobody here for that.\nreject-in-scene = Finish the conversation first.\nreject-wrong-place = They're not here.\nreject-locked = They're not ready to talk about that yet.\nreject-no-slots = You're out of time today. Sleep first.\nreject-stale-run = That conversation can't continue. Start it again.\nreject-no-pick = Choose a reply with the number keys.\nreject-bad-choice = There's no reply with that number.\nreject-no-tiles = Build your reply from the tiles.\nreject-bad-tile = There's no tile with that number.\nreject-not-linked = You can't get there from here.\nreject-unknown-word = That word isn't in the dictionary.\nnotice-read-only = Your progress can't be saved on this computer, so this session won't be kept.\nnotice-bad-save = Your save couldn't be read. It was kept as a backup and a new game started.\n\nresume-title = Your games:\nresume-item = Day { $day } · { $place } · { $currency }{ $wallet } · { $done ->\n [one] 1 scene done\n *[other] { $done } scenes done\n} · last played { $date }\nresume-ask = Which one? (number, or enter to cancel)\nresume-none = No saved games yet, so here's a new one.\nreject-no-mentor = There's nobody here to explain things.\nnote-hint = { $npc } seems to have something to tell you.\nmentor-nothing = { $npc } has nothing new to explain today.\n\nkeys-notebook = [↑↓] scroll · [esc] back\nnotebook-progress = Stage { $stage }: { $known } of { $total } words known · { $heard } heard\nnotebook-empty = Nothing yet. Words you hear are written down here.\nnotebook-elsewhere = Heard elsewhere\nnotebook-notes = Notes\nexport-none = There's no saved game to export yet.\nimport-bad = That line isn't a saved game for this course ({ $reason }).\nimport-done = Added: { $game }. Run the game to continue it.\n\n# Browser page controls (packages/tui-web).\nweb-new = New game\nweb-games = Games\nweb-games-none = No saved games yet.\nweb-export = Export\nweb-export-hint = This line is your whole game. Paste it into Import on another device, or into the terminal game with: npx silver-tongue --import -\nweb-copy = Copy\nweb-copied = Copied\nweb-import = Import\nweb-import-hint = Paste a line from Export, here or from the terminal game. It is added as a new game; nothing is overwritten.\nweb-import-go = Add game\nweb-close = Close\nweb-saved = Your game is saved. You can close this tab, or keep playing.\n\n# The story. intro-1, intro-2, … open a new game ($currency, $wallet, $rent are available).\nintro-1 = Your phone is dead, your wallet is gone, and the bus that brought you here left an hour ago.\nintro-2 = You're standing on a street in a Chinese city with { $currency }{ $wallet } in your pocket. You know nobody, and nobody here speaks your language.\nintro-3 = Food costs money. Rent is { $currency }{ $rent }, due at the end of the week. To earn anything you'll need work, and for work you'll need words.\nintro-4 = On a bench by the road, an old man is watching you with open curiosity. Maybe start there.\n\nplace-street = Main Street\nplace-street-desc = Bikes, steam and shouting. An old man sits on a bench by the road. Across it, a noodle shop glows.\nplace-noodle_shop = Noodle Shop\nplace-noodle_shop-desc = Steam everywhere. The cook is shouting orders at nobody in particular.\n\nnpc-wang = Old Wang\nnpc-cook = Cook\n\n# Scene names for the menu; scene-<id>-start and scene-<id>-end are optional narration.\nscene-street-hello = Meet Old Wang\nscene-street-hello-start = The old man pats the bench beside him and points at himself. He seems to have decided you need lessons: he says something, you answer. Stuck? Press [w] to look words up, and [s] there to see what the whole sentence means.\nscene-street-hello-end = Old Wang looks delighted with his new student. You have a Chinese name now: 小马, Xiǎo Mǎ, \"little horse\". You didn't get a vote.\n\nscene-street-hungry = Talk about food\nscene-street-hungry-start = Your stomach growls, loudly. Old Wang raises an eyebrow.\nscene-street-hungry-end = Old Wang points at the noodle shop, then at you, then mimes rolling up his sleeves. Work first, noodles after.\n\nscene-street-practice = Practise greetings\nscene-street-practice-start = Old Wang shuffles over to make room. Another lesson, then.\nscene-street-practice-end = Old Wang nods, satisfied, and goes back to watching the street.\n\nscene-noodle-intro = Ask about work\nscene-noodle-intro-start = The cook looks you up and down, wiping her hands on her apron. So this is Old Wang's latest project.\nscene-noodle-intro-end = She throws you an apron. You have a job, sort of.\n\nscene-noodle-shift = Work a shift\nscene-noodle-shift-start = Orders fly across the counter. Keep up.\nscene-noodle-shift-end = The rush dies down. The cook counts coins into your hand.\n\n# What a reply does (action-<name>), and on a mix-up what was asked (asked-<name>).\n# Concept values arrive as learner names: $item = \"tea\", $count = \"three\".\naction-fetch = You bring { $item }.\nasked-fetch = They wanted { $item }.\naction-serve = You set down { $count } cups of { $item }.\nasked-serve = They wanted { $count } cups of { $item }.\n\n# Usage notes Old Wang explains (languages/zh/notes.json). note-<id>-title and note-<id>.\n\nnote-hao-ma-title = 好 and 吗\nnote-hao-ma = 好 (hǎo) means \"good\", and on its own it's how you agree: \"OK\". Put 吗 (ma) at the end of a sentence and it becomes a yes-or-no question: 你好吗? is \"How are you?\", literally \"You good?\" The usual answer is 很好 (hěn hǎo), \"very good\"; the 很 is there mostly for rhythm.\n\nnote-lao-xiao-title = 老王 and 小张\nnote-lao-xiao = Friends and neighbours your own age are often called by surname with 老 (lǎo, \"old\") or 小 (xiǎo, \"little\") in front: 老王 for someone a bit older, 小张 for someone younger. From a young stranger to an old man it would be too familiar; you'd say 王大爷, \"Grandpa Wang\". Old Wang told you to call him 老王, which is his way of saying you're friends now. Calling you 小马 says the same.\n\nnote-le-title = 了 for a change\nnote-le = 了 (le) after a word often marks a change: 我饿了 is \"I've got hungry\", \"I'm hungry now\". You'll also hear it in 太好了!, \"great!\", literally \"too good!\"\n\nnote-bukeqi-title = 谢谢 and 不客气\nnote-bukeqi = 谢谢 (xièxie) is \"thank you\". The usual answer is 不客气 (bùkèqi), \"you're welcome\"; it literally means \"don't be polite\": no need to stand on ceremony. Between close friends, people often skip 谢谢 altogether; thanking a friend too much can sound distant.\n\nnote-bei-title = 杯, a measure word\nnote-bei = Chinese doesn't say \"three teas\". A measure word goes between a number and a thing: 三杯茶 is \"three cups of tea\". 杯 (bēi) is the one for cups and glasses. There are many measure words; 个 (gè) is the everyday all-purpose one.\n","conceptNames":{"tea":"tea","water":"water","three":"three","four":"four","five":"five","hello":"Hello","thanks":"Thank you","sorry":"Sorry","bye":"Goodbye"},"stageWords":{"1":["w0001","w0002","w0003","w0004","w0005","w0006","w0007","w0008","w0009","w0010","w0011","w0012","w0013","w0014","w0015","w0016","w0017","w0018","w0019","w0020","w0021","w0022","w0023","w0024","w0025","w0026","w0027","w0028","w0029","w0030","w0031","w0032","w0033","w0034","w0035","w0036","w0037","w0038","w0039","w0040","w0041","w0042","w0043","w0044","w0045","w0046","w0047","w0048","w0049","w0050","w0051","w0052","w0053","w0054","w0055","w0056","w0057","w0058","w0059","w0060","w0061","w0062","w0063","w0064","w0065","w0066","w0067","w0068","w0069","w0070","w0071","w0072","w0073","w0074","w0075","w0076","w0077","w0078","w0079","w0080","w0081","w0082","w0083","w0084","w0085","w0086","w0087","w0088","w0089","w0090","w0091","w0092","w0093","w0094","w0095","w0096","w0097","w0098","w0099","w0100","w0101","w0102","w0103","w0104","w0105","w0106","w0107","w0108","w0109","w0110","w0111","w0112","w0113","w0114","w0115","w0116","w0117","w0118","w0119","w0120","w0121","w0122","w0123","w0124","w0125","w0126","w0127","w0128","w0129","w0130","w0131","w0132","w0133","w0134","w0135","w0136","w0137","w0138","w0139","w0140","w0141","w0142","w0143","w0144","w0145","w0146","w0147","w0148","w0149","w0150"],"2":["w0151","w0152","w0153","w0154","w0155","w0156","w0157","w0158","w0159","w0160","w0161","w0162","w0163","w0164","w0165","w0166","w0167","w0168","w0169","w0170","w0171","w0172","w0173","w0174","w0175","w0176","w0177","w0178","w0179","w0180","w0181","w0182","w0183","w0184","w0185","w0186","w0187","w0188","w0189","w0190","w0191","w0192","w0193","w0194","w0195","w0196","w0197","w0198","w0199","w0200","w0201","w0202","w0203","w0204","w0205","w0206","w0207","w0208","w0209","w0210","w0211","w0212","w0213","w0214","w0215","w0216","w0217","w0218","w0219","w0220","w0221","w0222","w0223","w0224","w0225","w0226","w0227","w0228","w0229","w0230","w0231","w0232","w0233","w0234","w0235","w0236","w0237","w0238","w0239","w0240","w0241","w0242","w0243","w0244","w0245","w0246","w0247","w0248","w0249","w0250","w0251","w0252","w0253","w0254","w0255","w0256","w0257","w0258","w0259","w0260","w0261","w0262","w0263","w0264","w0265","w0266","w0267","w0268","w0269","w0270","w0271","w0272","w0273","w0274","w0275","w0276","w0277","w0278","w0279","w0280","w0281","w0282","w0283","w0284","w0285","w0286","w0287","w0288","w0289","w0290","w0291","w0292","w0293","w0294","w0295","w0296","w0297"],"3":["w0298","w0299","w0300","w0301","w0302","w0303","w0304","w0305","w0306","w0307","w0308","w0309","w0310","w0311","w0312","w0313","w0314","w0315","w0316","w0317","w0318","w0319","w0320","w0321","w0322","w0323","w0324","w0325","w0326","w0327","w0328","w0329","w0330","w0331","w0332","w0333","w0334","w0335","w0336","w0337","w0338","w0339","w0340","w0341","w0342","w0343","w0344","w0345","w0346","w0347","w0348","w0349","w0350","w0351","w0352","w0353","w0354","w0355","w0356","w0357","w0358","w0359","w0360","w0361","w0362","w0363","w0364","w0365","w0366","w0367","w0368","w0369","w0370","w0371","w0372","w0373","w0374","w0375","w0376","w0377","w0378","w0379","w0380","w0381","w0382","w0383","w0384","w0385","w0386","w0387","w0388","w0389","w0390","w0391","w0392","w0393","w0394","w0395","w0396","w0397","w0398","w0399","w0400","w0401","w0402","w0403","w0404","w0405","w0406","w0407","w0408","w0409","w0410","w0411","w0412","w0413","w0414","w0415","w0416","w0417","w0418","w0419","w0420","w0421","w0422","w0423","w0424","w0425","w0426","w0427","w0428","w0429","w0430","w0431","w0432","w0433","w0434","w0435","w0436","w0437","w0438","w0439","w0440","w0441","w0442","w0443","w0444","w0445","w0446","w0447","w0448","w0449","w0450","w0451","w0452","w0453","w0454","w0455","w0456","w0457","w0458","w0459","w0460","w0461","w0462","w0463","w0464","w0465","w0466","w0467","w0468","w0469","w0470","w0471","w0472","w0473","w0474","w0475","w0476","w0477","w0478","w0479","w0480","w0481","w0482","w0483","w0484","w0485","w0486","w0487","w0488","w0489","w0490","w0491","w0492","w0493","w0494","w0495","w0496","w0497","w0498","w0499","w0500","w0501","w0502","w0503","w0504","w0505","w0506","w0507","w0508","w0509","w0510","w0511","w0512","w0513","w0514","w0515","w0516","w0517","w0518","w0519","w0520","w0521","w0522","w0523","w0524","w0525","w0526","w0527","w0528","w0529","w0530","w0531","w0532","w0533","w0534","w0535","w0536","w0537","w0538","w0539","w0540","w0541","w0542","w0543","w0544","w0545","w0546","w0547","w0548","w0549","w0550","w0551","w0552","w0553","w0554","w0555","w0556","w0557","w0558","w0559","w0560","w0561","w0562","w0563","w0564","w0565","w0566","w0567","w0568","w0569","w0570","w0571","w0572","w0573","w0574","w0575","w0576","w0577","w0578","w0579","w0580","w0581","w0582","w0584","w0585","w0586","w0588","w0589","w0590","w0591","w0592","w0593","w0594","w0595"],"4":["w0596","w0597","w0598","w0599","w0600","w0601","w0602","w0603","w0604","w0605","w0606","w0607","w0608","w0609","w0610","w0611","w0612","w0613","w0614","w0615","w0616","w0617","w0618","w0619","w0620","w0621","w0622","w0623","w0624","w0625","w0626","w0627","w0628","w0629","w0630","w0631","w0632","w0633","w0634","w0635","w0636","w0637","w0638","w0639","w0640","w0641","w0642","w0643","w0644","w0645","w0646","w0647","w0648","w0649","w0650","w0651","w0652","w0653","w0654","w0655","w0656","w0657","w0658","w0659","w0660","w0661","w0662","w0663","w0664","w0665","w0666","w0667","w0668","w0669","w0670","w0671","w0672","w0673","w0674","w0675","w0676","w0677","w0678","w0679","w0680","w0681","w0682","w0683","w0684","w0685","w0686","w0687","w0688","w0689","w0690","w0691","w0692","w0693","w0694","w0695","w0696","w0697","w0698","w0699","w0700","w0701","w0702","w0703","w0704","w0705","w0706","w0707","w0708","w0709","w0710","w0711","w0712","w0713","w0714","w0715","w0716","w0717","w0718","w0719","w0720","w0721","w0722","w0723","w0724","w0725","w0726","w0727","w0728","w0729","w0730","w0731","w0732","w0733","w0734","w0735","w0736","w0737","w0738","w0739","w0740","w0741","w0742","w0743","w0744","w0745","w0746","w0747","w0748","w0749","w0750","w0751","w0752","w0753","w0754","w0755","w0756","w0757","w0758","w0759","w0760","w0761","w0762","w0763","w0764","w0765","w0766","w0767","w0768","w0769","w0770","w0771","w0772","w0773","w0774","w0775","w0776","w0777","w0778","w0779","w0780","w0781","w0782","w0783","w0784","w0785","w0786","w0787","w0788","w0789","w0790","w0791","w0792","w0793","w0794","w0795","w0796","w0797","w0798","w0799","w0800","w0801","w0802","w0803","w0804","w0805","w0806","w0807","w0808","w0809","w0810","w0811","w0812","w0813","w0814","w0815","w0816","w0817","w0818","w0819","w0820","w0821","w0822","w0823","w0824","w0825","w0826","w0827","w0828","w0829","w0830","w0831","w0832","w0833","w0834","w0835","w0836","w0837","w0838","w0839","w0840","w0841","w0842","w0843","w0844","w0845","w0846","w0847","w0848","w0849","w0850","w0851","w0852","w0853","w0854","w0855","w0856","w0857","w0858","w0859","w0860","w0861","w0862","w0863","w0864","w0865","w0866","w0867","w0868","w0869","w0870","w0871","w0872","w0873","w0874","w0875","w0876","w0877","w0878","w0879","w0880","w0881","w0882","w0883","w0884","w0885","w0886","w0887","w0888","w0889","w0890","w0891","w0892","w0893","w0894","w0895","w0896","w0897","w0898","w0899","w0900","w0901","w0902","w0903","w0904","w0905","w0906","w0907","w0908","w0909","w0910","w0911","w0912","w0913","w0914","w0915","w0916","w0917","w0918","w0919","w0920","w0921","w0922","w0923","w0924","w0925","w0926","w0927","w0928","w0929","w0930","w0931","w0932","w0933","w0934","w0935","w0936","w0937","w0938","w0939","w0940","w0941","w0942","w0943","w0944","w0945","w0946","w0947","w0948","w0949","w0950","w0951","w0952","w0953","w0954","w0955","w0956","w0957","w0958","w0959","w0960","w0961","w0962","w0963","w0964","w0965","w0966","w0967","w0968","w0969","w0970","w0971","w0972","w0973","w0974","w0975","w0976","w0977","w0978","w0979","w0980","w0981","w0982","w0983","w0984","w0985","w0986","w0987","w0988","w0989","w0990","w0991","w0992","w0993","w0994","w0995","w0996","w0997","w0998","w0999","w1000","w1001","w1002","w1003","w1004","w1005","w1006","w1007","w1008","w1009","w1010","w1011","w1012","w1013","w1014","w1015","w1016","w1017","w1018","w1019","w1020","w1021","w1022","w1023","w1024","w1025","w1026","w1027","w1028","w1029","w1030","w1031","w1032","w1033","w1034","w1035","w1036","w1037","w1038","w1039","w1040","w1041","w1042","w1043","w1044","w1045","w1046","w1047","w1048","w1049","w1050","w1051","w1052","w1053","w1054","w1055","w1056","w1057","w1058","w1059","w1060","w1061","w1062","w1063","w1064","w1065","w1066","w1067","w1068","w1069","w1070","w1071","w1072","w1073","w1074","w1075","w1076","w1077","w1078","w1079","w1080","w1081","w1082","w1083","w1084","w1085","w1086","w1087","w1088","w1089","w1090","w1091","w1092","w1093","w1094","w1095","w1096","w1097","w1098","w1099","w1100","w1101","w1102","w1103","w1104","w1105","w1106","w1107","w1108","w1109","w1110","w1111","w1112","w1113","w1114","w1115","w1116","w1117","w1118","w1119","w1120","w1121","w1122","w1123","w1124","w1125","w1126","w1127","w1128","w1129","w1130","w1131","w1132","w1133","w1134","w1135","w1136","w1137","w1138","w1139","w1140","w1141","w1142","w1143","w1144","w1145","w1146","w1147","w1148","w1149","w1150","w1151","w1152","w1153","w1154","w1155","w1156","w1157","w1158","w1159","w1160","w1161","w1162","w1163","w1164","w1165","w1166","w1167","w1168","w1169","w1170","w1171","w1172","w1173","w1174","w1175","w1176","w1177","w1178","w1179","w1180","w1181","w1182","w1183","w1184","w1185","w1186","w1187","w1188","w1189","w1190","w1191","w1192","w1193"]},"notes":[{"id":"hao-ma","trigger":{"scene":"street-hello"}},{"id":"lao-xiao","trigger":{"word":"x0004"}},{"id":"le","trigger":{"scene":"street-hungry"}},{"id":"bukeqi","trigger":{"word":"w0141"}},{"id":"bei","trigger":{"word":"x0001"}}]}
1
+ {"id":"zh-china-en","typing":false,"words":{"w0003":{"id":"w0003","w":"三","lv":"1","gloss":"three; 3","pron":"sān"},"w0009":{"id":"w0009","w":"不","lv":"1","gloss":"no; not","pron":"bù"},"w0010":{"id":"w0010","w":"不客气","lv":"1","gloss":"you're welcome; don't mention it","pron":"bùkèqi"},"w0018":{"id":"w0018","w":"了","lv":"1","gloss":"(completed action marker)","pron":"le"},"w0020":{"id":"w0020","w":"五","lv":"1","gloss":"five; 5","pron":"wǔ"},"w0023":{"id":"w0023","w":"什么","lv":"1","gloss":"what?; something","pron":"shénme"},"w0028":{"id":"w0028","w":"你","lv":"1","gloss":"you (informal)","pron":"nǐ"},"w0034":{"id":"w0034","w":"再见","lv":"1","gloss":"goodbye","pron":"zàijiàn"},"w0037":{"id":"w0037","w":"几","lv":"1","gloss":"how much; how many","pron":"jǐ"},"w0046":{"id":"w0046","w":"叫","lv":"1","gloss":"to shout; to call","pron":"jiào"},"w0047":{"id":"w0047","w":"吃","lv":"1","gloss":"to eat; to consume; to eat at (a cafeteria etc)","pron":"chī"},"w0049":{"id":"w0049","w":"名字","lv":"1","gloss":"name (of a person or thing)","pron":"míngzi"},"w0051":{"id":"w0051","w":"吗","lv":"1","gloss":"(question particle for \"yes-no\" questions)","pron":"ma"},"w0053":{"id":"w0053","w":"呢","lv":"1","gloss":"particle indicating that a previously asked question is…","pron":"ne"},"w0058":{"id":"w0058","w":"喜欢","lv":"1","gloss":"to like; to be fond of","pron":"xǐhuan"},"w0060":{"id":"w0060","w":"四","lv":"1","gloss":"four; 4","pron":"sì"},"w0072":{"id":"w0072","w":"好","lv":"1","gloss":"good; appropriate; proper","pron":"hǎo"},"w0079":{"id":"w0079","w":"对不起","lv":"1","gloss":"I'm sorry; excuse me; I beg your pardon","pron":"duìbuqǐ"},"w0084":{"id":"w0084","w":"工作","lv":"1","gloss":"to work; (of a machine) to operate","pron":"gōngzuò"},"w0087":{"id":"w0087","w":"很","lv":"1","gloss":"(adverb of degree); quite","pron":"hěn"},"w0091":{"id":"w0091","w":"我","lv":"1","gloss":"I; me; my","pron":"wǒ"},"w0099":{"id":"w0099","w":"是","lv":"1","gloss":"to be (followed by substantives only); correct; right; true","pron":"shì"},"w0101":{"id":"w0101","w":"有","lv":"1","gloss":"to have; there is","pron":"yǒu"},"w0102":{"id":"w0102","w":"朋友","lv":"1","gloss":"friend","pron":"péngyou"},"w0108":{"id":"w0108","w":"水","lv":"1","gloss":"water; river","pron":"shuǐ"},"w0112":{"id":"w0112","w":"没关系","lv":"1","gloss":"it doesn't matter","pron":"méiguānxi"},"w0133":{"id":"w0133","w":"茶","lv":"1","gloss":"tea; tea plant","pron":"chá"},"w0141":{"id":"w0141","w":"谢谢","lv":"1","gloss":"to thank; thanks","pron":"xièxie"},"w0143":{"id":"w0143","w":"那","lv":"1","gloss":"(specifier) that; the; those (colloquial pr. [nèi])","pron":"nà"},"w0145":{"id":"w0145","w":"里","lv":"1","gloss":"lining; interior","pron":"lǐ"},"w0149":{"id":"w0149","w":"饭馆","lv":"1","gloss":"restaurant","pron":"fànguǎn"},"w0583":{"id":"w0583","w":"面条","lv":"3","gloss":"noodles","pron":"miàntiáo","bonus":true},"w0587":{"id":"w0587","w":"饿","lv":"3","gloss":"to be hungry; hungry","pron":"è","bonus":true},"x0001":{"id":"x0001","w":"杯","lv":"1","gloss":"cup; glass (measure word for drinks)","pron":"bēi","bonus":true},"x0002":{"id":"x0002","w":"老王","lv":"1","gloss":"Old Wang (a name: 老 \"old\" + the surname Wang)","pron":"Lǎo Wáng","bonus":true},"x0004":{"id":"x0004","w":"小张","lv":"1","gloss":"Xiao Zhang, the cook (小 \"little\" + the surname Zhang)","pron":"Xiǎo Zhāng","bonus":true}},"concepts":{"tea":["w0133"],"water":["w0108"],"three":["w0003"],"four":["w0060"],"five":["w0020"],"hello":["w0028","w0072"],"thanks":["w0141"],"sorry":["w0079"],"bye":["w0034"]},"groups":{"courtesies":["hello","thanks","sorry"],"drinks":["tea","water"],"numbers_3_5":["three","four","five"]},"world":{"start":"street","currency":"¥","slotsPerDay":4,"startWallet":20,"foodPerDay":5,"rentPerWeek":50,"places":{"street":{"links":["noodle_shop"]},"noodle_shop":{"links":["street"]}},"npcs":{"wang":{"place":"street"},"cook":{"place":"noodle_shop"}},"mentor":{"npc":"wang","after":"street-hello"}},"scenes":[{"id":"noodle-intro","place":"noodle_shop","npc":"cook","stage":1,"after":["street-hungry"],"requires":{},"repeatable":false,"trustGain":1,"exchanges":[{"id":"greet","slots":{},"expect":{"action":"greet"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!你叫什么名字?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":4,"word":"w0028"},{"start":4,"end":5,"word":"w0046"},{"start":5,"end":7,"word":"w0023"},{"start":7,"end":9,"word":"w0049"}],"meaning":"Hello! What's your name?"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"你好吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":2,"end":3,"word":"w0051"}],"meaning":"How are you?"}]}}},{"id":"names","slots":{},"expect":{"action":"names"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"我叫小张。你呢?","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0004"},{"start":5,"end":6,"word":"w0028"},{"start":6,"end":7,"word":"w0053"}],"meaning":"My name is Xiao Zhang. And you?"},"reply":{"text":"我叫。老王是我朋友。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":4,"end":6,"word":"x0002"},{"start":6,"end":7,"word":"w0099"},{"start":7,"end":8,"word":"w0091"},{"start":8,"end":10,"word":"w0102"}],"meaning":"My name is . Old Wang is my friend."},"alts":[{"text":"我叫小张。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0004"}],"meaning":"My name is Xiao Zhang."},{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}]}}},{"id":"job","slots":{},"expect":{"action":"job"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"工作,好吗?","tokens":[{"start":0,"end":2,"word":"w0084"},{"start":3,"end":4,"word":"w0072"},{"start":4,"end":5,"word":"w0051"}],"meaning":"Want to work here?"},"reply":{"text":"好。","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"OK."},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."}]}}}]},{"id":"noodle-shift","place":"noodle_shop","npc":"cook","stage":1,"after":["noodle-intro"],"requires":{"trust":{"cook":1}},"repeatable":true,"trustGain":1,"exchanges":[{"id":"drink","slots":{"item":"drinks"},"expect":{"action":"fetch","item":"$item"},"hinges":["$item"],"pay":1,"missCost":1,"variants":{"item=tea":{"npc":{"text":"茶。","tokens":[{"start":0,"end":1,"word":"w0133"}],"meaning":"Tea."},"reply":{"text":"好,茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0133"}],"meaning":"OK, tea."}},"item=water":{"npc":{"text":"水。","tokens":[{"start":0,"end":1,"word":"w0108"}],"meaning":"Water."},"reply":{"text":"好,水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0108"}],"meaning":"OK, water."}}}},{"id":"order","slots":{"item":"drinks","count":"numbers_3_5"},"expect":{"action":"serve","item":"$item","count":"$count"},"hinges":["$item","$count"],"pay":3,"missCost":2,"variants":{"count=three|item=tea":{"npc":{"text":"三杯茶。","tokens":[{"start":0,"end":1,"word":"w0003"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0133"}],"meaning":"Three cups of tea."},"reply":{"text":"好,三杯茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0133"}],"meaning":"OK, three cups of tea."},"rephrase":{"text":"茶。三杯。","tokens":[{"start":0,"end":1,"word":"w0133"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Tea. Three cups."}},"count=three|item=water":{"npc":{"text":"三杯水。","tokens":[{"start":0,"end":1,"word":"w0003"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0108"}],"meaning":"Three cups of water."},"reply":{"text":"好,三杯水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0108"}],"meaning":"OK, three cups of water."},"rephrase":{"text":"水。三杯。","tokens":[{"start":0,"end":1,"word":"w0108"},{"start":2,"end":3,"word":"w0003"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Water. Three cups."}},"count=four|item=tea":{"npc":{"text":"四杯茶。","tokens":[{"start":0,"end":1,"word":"w0060"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0133"}],"meaning":"Four cups of tea."},"reply":{"text":"好,四杯茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0133"}],"meaning":"OK, four cups of tea."},"rephrase":{"text":"茶。四杯。","tokens":[{"start":0,"end":1,"word":"w0133"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Tea. Four cups."}},"count=four|item=water":{"npc":{"text":"四杯水。","tokens":[{"start":0,"end":1,"word":"w0060"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0108"}],"meaning":"Four cups of water."},"reply":{"text":"好,四杯水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0108"}],"meaning":"OK, four cups of water."},"rephrase":{"text":"水。四杯。","tokens":[{"start":0,"end":1,"word":"w0108"},{"start":2,"end":3,"word":"w0060"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Water. Four cups."}},"count=five|item=tea":{"npc":{"text":"五杯茶。","tokens":[{"start":0,"end":1,"word":"w0020"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0133"}],"meaning":"Five cups of tea."},"reply":{"text":"好,五杯茶。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0133"}],"meaning":"OK, five cups of tea."},"rephrase":{"text":"茶。五杯。","tokens":[{"start":0,"end":1,"word":"w0133"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Tea. Five cups."}},"count=five|item=water":{"npc":{"text":"五杯水。","tokens":[{"start":0,"end":1,"word":"w0020"},{"start":1,"end":2,"word":"x0001"},{"start":2,"end":3,"word":"w0108"}],"meaning":"Five cups of water."},"reply":{"text":"好,五杯水。","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"},{"start":4,"end":5,"word":"w0108"}],"meaning":"OK, five cups of water."},"rephrase":{"text":"水。五杯。","tokens":[{"start":0,"end":1,"word":"w0108"},{"start":2,"end":3,"word":"w0020"},{"start":3,"end":4,"word":"x0001"}],"meaning":"Water. Five cups."}}}}]},{"id":"street-hello","place":"street","npc":"wang","stage":1,"after":[],"requires":{},"repeatable":false,"trustGain":1,"exchanges":[{"id":"hello","slots":{},"expect":{"action":"hello"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"alts":[{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Good!"}]}}},{"id":"wang","slots":{},"expect":{"action":"wang"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"老王!","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang!"},"reply":{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"},"alts":[{"text":"老王!","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang!"},{"text":"好,老王!","tokens":[{"start":0,"end":1,"word":"w0072"},{"start":2,"end":4,"word":"x0002"}],"meaning":"OK, Old Wang!"}]}}},{"id":"how","slots":{},"expect":{"action":"how"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":2,"end":3,"word":"w0051"}],"meaning":"How are you?"},"reply":{"text":"很好!你好吗?","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":4,"word":"w0028"},{"start":4,"end":5,"word":"w0072"},{"start":5,"end":6,"word":"w0051"}],"meaning":"Very well! How are you?"},"alts":[{"text":"老王!","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang!"},{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"}]}}},{"id":"name","slots":{},"expect":{"action":"name"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"很好!叫我老王。","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":4,"word":"w0046"},{"start":4,"end":5,"word":"w0091"},{"start":5,"end":7,"word":"x0002"}],"meaning":"Very well! Call me Old Wang."},"reply":{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"},"alts":[{"text":"我叫老王。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0002"}],"meaning":"My name is Old Wang."},{"text":"很好!","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Very well!"}]}}},{"id":"ask","slots":{},"expect":{"action":"ask"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你叫什么名字?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"w0023"},{"start":4,"end":6,"word":"w0049"}],"meaning":"What's your name?"},"reply":{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."},"alts":[{"text":"我叫老王。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"},{"start":2,"end":4,"word":"x0002"}],"meaning":"My name is Old Wang."},{"text":"你好吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":2,"end":3,"word":"w0051"}],"meaning":"How are you?"},{"text":"很好!","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Very well!"}]}}},{"id":"bye","slots":{},"expect":{"action":"bye"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"再见,!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye, !"},"reply":{"text":"再见,老王!","tokens":[{"start":0,"end":2,"word":"w0034"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Goodbye, Old Wang!"},"alts":[{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},{"text":"很好!","tokens":[{"start":0,"end":1,"word":"w0087"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Very well!"}]}}}]},{"id":"street-hungry","place":"street","npc":"wang","stage":1,"after":["street-hello"],"requires":{},"repeatable":false,"trustGain":1,"exchanges":[{"id":"hungry","slots":{},"expect":{"action":"hungry"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":",你好吗?","tokens":[{"start":2,"end":3,"word":"w0028"},{"start":3,"end":4,"word":"w0072"},{"start":4,"end":5,"word":"w0051"}],"meaning":", how are you?"},"reply":{"text":"我饿了。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0587"},{"start":2,"end":3,"word":"w0018"}],"meaning":"I'm hungry."},"alts":[{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."},{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"}]}}},{"id":"noodles","slots":{},"expect":{"action":"noodles"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"吃面条吗?","tokens":[{"start":0,"end":1,"word":"w0047"},{"start":1,"end":3,"word":"w0583"},{"start":3,"end":4,"word":"w0051"}],"meaning":"Want some noodles?"},"reply":{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Yes, please!"},"alts":[{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."},{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"}]}}},{"id":"like","slots":{},"expect":{"action":"like"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你喜欢面条吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":3,"word":"w0058"},{"start":3,"end":5,"word":"w0583"},{"start":5,"end":6,"word":"w0051"}],"meaning":"Do you like noodles?"},"reply":{"text":"喜欢!我喜欢面条。","tokens":[{"start":0,"end":2,"word":"w0058"},{"start":3,"end":4,"word":"w0091"},{"start":4,"end":6,"word":"w0058"},{"start":6,"end":8,"word":"w0583"}],"meaning":"I do! I like noodles."},"alts":[{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."},{"text":"再见,老王!","tokens":[{"start":0,"end":2,"word":"w0034"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Goodbye, Old Wang!"}]}}},{"id":"there","slots":{},"expect":{"action":"there"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"那里!","tokens":[{"start":0,"end":1,"word":"w0143"},{"start":1,"end":2,"word":"w0145"}],"meaning":"There!"},"reply":{"text":"那里?","tokens":[{"start":0,"end":1,"word":"w0143"},{"start":1,"end":2,"word":"w0145"}],"meaning":"There?"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."}]}}},{"id":"shop","slots":{},"expect":{"action":"shop"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"那里有饭馆。","tokens":[{"start":0,"end":1,"word":"w0143"},{"start":1,"end":2,"word":"w0145"},{"start":2,"end":3,"word":"w0101"},{"start":3,"end":5,"word":"w0149"}],"meaning":"There's a restaurant there."},"reply":{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Good!"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"你好吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":2,"end":3,"word":"w0051"}],"meaning":"How are you?"}]}}},{"id":"zhang","slots":{},"expect":{"action":"zhang"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"小张!","tokens":[{"start":0,"end":2,"word":"x0004"}],"meaning":"Xiao Zhang!"},"reply":{"text":"小张?","tokens":[{"start":0,"end":2,"word":"x0004"}],"meaning":"Xiao Zhang?"},"alts":[{"text":"老王?","tokens":[{"start":0,"end":2,"word":"x0002"}],"meaning":"Old Wang?"},{"text":"?","tokens":[],"meaning":"?"}]}}},{"id":"friend","slots":{},"expect":{"action":"friend"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"小张是我朋友。","tokens":[{"start":0,"end":2,"word":"x0004"},{"start":2,"end":3,"word":"w0099"},{"start":3,"end":4,"word":"w0091"},{"start":4,"end":6,"word":"w0102"}],"meaning":"Xiao Zhang is my friend."},"reply":{"text":"好!","tokens":[{"start":0,"end":1,"word":"w0072"}],"meaning":"Good!"},"alts":[{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},{"text":"你好吗?","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":2,"end":3,"word":"w0051"}],"meaning":"How are you?"}]}}},{"id":"bye","slots":{},"expect":{"action":"bye"},"hinges":[],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"再见,!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye, !"},"reply":{"text":"谢谢!再见!","tokens":[{"start":0,"end":2,"word":"w0141"},{"start":3,"end":5,"word":"w0034"}],"meaning":"Thank you! Goodbye!"},"alts":[{"text":"你好,老王!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"},{"start":3,"end":5,"word":"x0002"}],"meaning":"Hello, Old Wang!"},{"text":"我叫。","tokens":[{"start":0,"end":1,"word":"w0091"},{"start":1,"end":2,"word":"w0046"}],"meaning":"My name is ."}]}}}]},{"id":"street-practice","place":"street","npc":"wang","stage":1,"after":["street-hello"],"requires":{},"repeatable":true,"trustGain":1,"exchanges":[{"id":"hello","slots":{},"expect":{"action":"greet"},"hinges":["hello"],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}}}},{"id":"polite-1","slots":{"said":"courtesies"},"expect":{"action":"answer","said":"$said"},"hinges":["$said"],"pay":0,"missCost":0,"variants":{"said=hello":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}},"said=thanks":{"npc":{"text":"谢谢!","tokens":[{"start":0,"end":2,"word":"w0141"}],"meaning":"Thank you!"},"reply":{"text":"不客气!","tokens":[{"start":0,"end":3,"word":"w0010"}],"meaning":"You're welcome!"}},"said=sorry":{"npc":{"text":"对不起!","tokens":[{"start":0,"end":3,"word":"w0079"}],"meaning":"Sorry!"},"reply":{"text":"没关系!","tokens":[{"start":0,"end":3,"word":"w0112"}],"meaning":"That's all right!"}}}},{"id":"polite-2","slots":{"said":"courtesies"},"expect":{"action":"answer","said":"$said"},"hinges":["$said"],"pay":0,"missCost":0,"variants":{"said=hello":{"npc":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"},"reply":{"text":"你好!","tokens":[{"start":0,"end":1,"word":"w0028"},{"start":1,"end":2,"word":"w0072"}],"meaning":"Hello!"}},"said=thanks":{"npc":{"text":"谢谢!","tokens":[{"start":0,"end":2,"word":"w0141"}],"meaning":"Thank you!"},"reply":{"text":"不客气!","tokens":[{"start":0,"end":3,"word":"w0010"}],"meaning":"You're welcome!"}},"said=sorry":{"npc":{"text":"对不起!","tokens":[{"start":0,"end":3,"word":"w0079"}],"meaning":"Sorry!"},"reply":{"text":"没关系!","tokens":[{"start":0,"end":3,"word":"w0112"}],"meaning":"That's all right!"}}}},{"id":"bye","slots":{},"expect":{"action":"farewell"},"hinges":["bye"],"pay":0,"missCost":0,"variants":{"":{"npc":{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"},"reply":{"text":"再见!","tokens":[{"start":0,"end":2,"word":"w0034"}],"meaning":"Goodbye!"}}}}]}],"reactions":{"wrong-generic":{"text":"不是。","tokens":[{"start":0,"end":1,"word":"w0009"},{"start":1,"end":2,"word":"w0099"}],"meaning":"No."},"wrong-count":{"text":"几杯?","tokens":[{"start":0,"end":1,"word":"w0037"},{"start":1,"end":2,"word":"x0001"}],"meaning":"How many cups?"}},"learnerFtl":"# Text-game UI. Every id here is required by packages/tui (UI_KEYS).\n\nhud = Day { $day } · slot { $slot }/{ $slots } · { $currency }{ $wallet } · { $rank }{ $rentLate ->\n [yes] { \" · rent due\" }\n *[no] {\"\"}\n}\n\nrank-0 = Pidgin\nrank-1 = Getting By\nrank-2 = Conversational\nrank-3 = Fluent\nrank-4 = Silver Tongue\n\nmenu-title = What now?\nmenu-talk = Talk to { $npc }: { $scene }\nmenu-go = Go to { $place }\nmenu-mentor = Ask { $npc } about the language\ncost-slot = { \" · 1 slot\" }\nmenu-sleep = Sleep (end the day)\nmenu-quit = Save and quit\n\nkeys-explore = [{ $keys }] choose · [n] notebook · [q] quit\nkeys-pick = [{ $keys }] reply · [w] word help · [n] notebook\nkeys-tiles = [{ $keys }] add · [⌫] undo · [enter] say · [w] help · [n] notebook\nkeys-help = [{ $keys }] look up · [esc] back\nkeys-help-sentence = [{ $keys }] look up · [s] whole sentence · [esc] back\n\nhelp-title = Which word?\nhelp-sentence = The whole sentence\nhelp-in-replies = In the replies:\nreply-title = Your reply:\ntiles-title = Your reply: tap the words in order, then press [enter].\ntiles-answer = You say:\nyou = You\n\nmismatch = That's not what they asked for.\nrephrased = (slower)\nwallet-change = { $sign }{ $currency }{ $amount } ({ $reason })\nreason-wages = wages\nreason-mixup = mix-up\nreason-food = food\nreason-rent = rent\ntrust-up = { $npc } trusts you a little more ({ $trust }).\nscene-done = { $earned ->\n [0] Done.\n *[other] Done. You earned { $currency }{ $earned }.\n}\nunlocked = New: { $scene }\nrank-up = You're now: { $rank }\nday-ended = Day { $day } is over. You sleep.\nreject-unknown-scene = There's nobody here for that.\nreject-in-scene = Finish the conversation first.\nreject-wrong-place = They're not here.\nreject-locked = They're not ready to talk about that yet.\nreject-no-slots = You're out of time today. Sleep first.\nreject-stale-run = That conversation can't continue. Start it again.\nreject-no-pick = Choose a reply with the number keys.\nreject-bad-choice = There's no reply with that number.\nreject-no-tiles = Build your reply from the tiles.\nreject-bad-tile = There's no tile with that number.\nreject-not-linked = You can't get there from here.\nreject-unknown-word = That word isn't in the dictionary.\nnotice-read-only = Your progress can't be saved on this computer, so this session won't be kept.\nnotice-bad-save = Your save couldn't be read. It was kept as a backup and a new game started.\n\nresume-title = Your games:\nresume-item = { $name }Day { $day } · { $place } · { $currency }{ $wallet } · { $done ->\n [one] 1 scene done\n *[other] { $done } scenes done\n} · last played { $date }\nresume-ask = Which one? (number, or enter to cancel)\nresume-none = No saved games yet, so here's a new one.\nreject-no-mentor = There's nobody here to explain things.\nnote-hint = { $npc } seems to have something to tell you.\nmentor-nothing = { $npc } has nothing new to explain today.\n\nkeys-notebook = [↑↓] scroll · [esc] back\nnotebook-progress = Stage { $stage }: { $known } of { $total } words known · { $heard } heard\nnotebook-empty = Nothing yet. Words you hear are written down here.\nnotebook-elsewhere = Heard elsewhere\nnotebook-notes = Notes\nexport-none = There's no saved game to export yet.\nimport-bad = That line isn't a saved game for this course ({ $reason }).\nimport-done = Added: { $game }. Run the game to continue it.\n\n# Browser page controls (packages/tui-web).\nweb-new = New game\nweb-games = Games\nweb-games-none = No saved games yet.\nweb-export = Export\nweb-export-hint = This line is your whole game. Paste it into Import on another device, or into the terminal game with: npx silver-tongue --import -\nweb-copy = Copy\nweb-copied = Copied\nweb-import = Import\nweb-import-hint = Paste a line from Export, here or from the terminal game. It is added as a new game; nothing is overwritten.\nweb-import-go = Add game\nweb-close = Close\nweb-saved = Your game is saved. You can close this tab, or keep playing.\nreject-bad-name = That name won't work. Use 1 to 20 letters.\nreject-no-name = Tell us your name first.\nname-prompt = Before anything else: what's your name?\nkeys-name = type your name · [enter] done · [⌫] delete\n\n# The story. intro-1, intro-2, … open a new game ($currency, $wallet, $rent are available).\nintro-1 = Your phone is dead, your wallet is gone, and the bus that brought you here left an hour ago.\nintro-2 = You're standing on a street in a Chinese city with { $currency }{ $wallet } in your pocket. You know nobody, and nobody here speaks your language.\nintro-3 = Food costs money. Rent is { $currency }{ $rent }, due at the end of the week. To earn anything you'll need work, and for work you'll need words.\nintro-4 = On a bench by the road, an old man is watching you with open curiosity. Maybe start there.\n\nplace-street = Main Street\nplace-street-desc = Bikes, steam and shouting. An old man sits on a bench by the road. Across it, a noodle shop glows.\nplace-noodle_shop = Noodle Shop\nplace-noodle_shop-desc = Steam everywhere. The cook is shouting orders at nobody in particular.\n\nnpc-wang = Old Wang\nnpc-cook = Cook\n\n# Scene names for the menu; scene-<id>-start and scene-<id>-end are optional narration.\nscene-street-hello = Meet Old Wang\nscene-street-hello-start = The old man pats the bench beside him and points at himself. He seems to have decided you need lessons: he says something, you answer. Stuck? Press [w] to look words up, and [s] there to see what the whole sentence means.\nscene-street-hello-end = Old Wang looks delighted with his new student. He repeats your name a few times, getting it a little wrong each time, and seems very pleased about it.\n\nscene-street-hungry = Talk about food\nscene-street-hungry-start = Your stomach growls, loudly. Old Wang raises an eyebrow.\nscene-street-hungry-end = Old Wang points at the noodle shop, then at you, then mimes rolling up his sleeves. Work first, noodles after.\n\nscene-street-practice = Practise greetings\nscene-street-practice-start = Old Wang shuffles over to make room. Another lesson, then.\nscene-street-practice-end = Old Wang nods, satisfied, and goes back to watching the street.\n\nscene-noodle-intro = Ask about work\nscene-noodle-intro-start = The cook looks you up and down, wiping her hands on her apron. So this is Old Wang's latest project.\nscene-noodle-intro-end = She throws you an apron. You have a job, sort of.\n\nscene-noodle-shift = Work a shift\nscene-noodle-shift-start = Orders fly across the counter. Keep up.\nscene-noodle-shift-end = The rush dies down. The cook counts coins into your hand.\n\n# What a reply does (action-<name>), and on a mix-up what was asked (asked-<name>).\n# Concept values arrive as learner names: $item = \"tea\", $count = \"three\".\naction-fetch = You bring { $item }.\nasked-fetch = They wanted { $item }.\naction-serve = You set down { $count } cups of { $item }.\nasked-serve = They wanted { $count } cups of { $item }.\n\n# Usage notes Old Wang explains (languages/zh/notes.json). note-<id>-title and note-<id>.\n\nnote-hao-ma-title = 好 and 吗\nnote-hao-ma = 好 (hǎo) means \"good\", and on its own it's how you agree: \"OK\". Put 吗 (ma) at the end of a sentence and it becomes a yes-or-no question: 你好吗? is \"How are you?\", literally \"You good?\" The usual answer is 很好 (hěn hǎo), \"very good\"; the 很 is there mostly for rhythm.\n\nnote-lao-xiao-title = 老王 and 小张\nnote-lao-xiao = Friends and neighbours your own age are often called by surname with 老 (lǎo, \"old\") or 小 (xiǎo, \"little\") in front: 老王 for someone a bit older, 小张 for someone younger. From a young stranger to an old man it would be too familiar; you'd say 王大爷, \"Grandpa Wang\". Old Wang told you to call him 老王, which is his way of saying you're friends now.\n\nnote-le-title = 了 for a change\nnote-le = 了 (le) after a word often marks a change: 我饿了 is \"I've got hungry\", \"I'm hungry now\". You'll also hear it in 太好了!, \"great!\", literally \"too good!\"\n\nnote-bukeqi-title = 谢谢 and 不客气\nnote-bukeqi = 谢谢 (xièxie) is \"thank you\". The usual answer is 不客气 (bùkèqi), \"you're welcome\"; it literally means \"don't be polite\": no need to stand on ceremony. Between close friends, people often skip 谢谢 altogether; thanking a friend too much can sound distant.\n\nnote-bei-title = 杯, a measure word\nnote-bei = Chinese doesn't say \"three teas\". A measure word goes between a number and a thing: 三杯茶 is \"three cups of tea\". 杯 (bēi) is the one for cups and glasses. There are many measure words; 个 (gè) is the everyday all-purpose one.\n","conceptNames":{"tea":"tea","water":"water","three":"three","four":"four","five":"five","hello":"Hello","thanks":"Thank you","sorry":"Sorry","bye":"Goodbye"},"stageWords":{"1":["w0001","w0002","w0003","w0004","w0005","w0006","w0007","w0008","w0009","w0010","w0011","w0012","w0013","w0014","w0015","w0016","w0017","w0018","w0019","w0020","w0021","w0022","w0023","w0024","w0025","w0026","w0027","w0028","w0029","w0030","w0031","w0032","w0033","w0034","w0035","w0036","w0037","w0038","w0039","w0040","w0041","w0042","w0043","w0044","w0045","w0046","w0047","w0048","w0049","w0050","w0051","w0052","w0053","w0054","w0055","w0056","w0057","w0058","w0059","w0060","w0061","w0062","w0063","w0064","w0065","w0066","w0067","w0068","w0069","w0070","w0071","w0072","w0073","w0074","w0075","w0076","w0077","w0078","w0079","w0080","w0081","w0082","w0083","w0084","w0085","w0086","w0087","w0088","w0089","w0090","w0091","w0092","w0093","w0094","w0095","w0096","w0097","w0098","w0099","w0100","w0101","w0102","w0103","w0104","w0105","w0106","w0107","w0108","w0109","w0110","w0111","w0112","w0113","w0114","w0115","w0116","w0117","w0118","w0119","w0120","w0121","w0122","w0123","w0124","w0125","w0126","w0127","w0128","w0129","w0130","w0131","w0132","w0133","w0134","w0135","w0136","w0137","w0138","w0139","w0140","w0141","w0142","w0143","w0144","w0145","w0146","w0147","w0148","w0149","w0150"],"2":["w0151","w0152","w0153","w0154","w0155","w0156","w0157","w0158","w0159","w0160","w0161","w0162","w0163","w0164","w0165","w0166","w0167","w0168","w0169","w0170","w0171","w0172","w0173","w0174","w0175","w0176","w0177","w0178","w0179","w0180","w0181","w0182","w0183","w0184","w0185","w0186","w0187","w0188","w0189","w0190","w0191","w0192","w0193","w0194","w0195","w0196","w0197","w0198","w0199","w0200","w0201","w0202","w0203","w0204","w0205","w0206","w0207","w0208","w0209","w0210","w0211","w0212","w0213","w0214","w0215","w0216","w0217","w0218","w0219","w0220","w0221","w0222","w0223","w0224","w0225","w0226","w0227","w0228","w0229","w0230","w0231","w0232","w0233","w0234","w0235","w0236","w0237","w0238","w0239","w0240","w0241","w0242","w0243","w0244","w0245","w0246","w0247","w0248","w0249","w0250","w0251","w0252","w0253","w0254","w0255","w0256","w0257","w0258","w0259","w0260","w0261","w0262","w0263","w0264","w0265","w0266","w0267","w0268","w0269","w0270","w0271","w0272","w0273","w0274","w0275","w0276","w0277","w0278","w0279","w0280","w0281","w0282","w0283","w0284","w0285","w0286","w0287","w0288","w0289","w0290","w0291","w0292","w0293","w0294","w0295","w0296","w0297"],"3":["w0298","w0299","w0300","w0301","w0302","w0303","w0304","w0305","w0306","w0307","w0308","w0309","w0310","w0311","w0312","w0313","w0314","w0315","w0316","w0317","w0318","w0319","w0320","w0321","w0322","w0323","w0324","w0325","w0326","w0327","w0328","w0329","w0330","w0331","w0332","w0333","w0334","w0335","w0336","w0337","w0338","w0339","w0340","w0341","w0342","w0343","w0344","w0345","w0346","w0347","w0348","w0349","w0350","w0351","w0352","w0353","w0354","w0355","w0356","w0357","w0358","w0359","w0360","w0361","w0362","w0363","w0364","w0365","w0366","w0367","w0368","w0369","w0370","w0371","w0372","w0373","w0374","w0375","w0376","w0377","w0378","w0379","w0380","w0381","w0382","w0383","w0384","w0385","w0386","w0387","w0388","w0389","w0390","w0391","w0392","w0393","w0394","w0395","w0396","w0397","w0398","w0399","w0400","w0401","w0402","w0403","w0404","w0405","w0406","w0407","w0408","w0409","w0410","w0411","w0412","w0413","w0414","w0415","w0416","w0417","w0418","w0419","w0420","w0421","w0422","w0423","w0424","w0425","w0426","w0427","w0428","w0429","w0430","w0431","w0432","w0433","w0434","w0435","w0436","w0437","w0438","w0439","w0440","w0441","w0442","w0443","w0444","w0445","w0446","w0447","w0448","w0449","w0450","w0451","w0452","w0453","w0454","w0455","w0456","w0457","w0458","w0459","w0460","w0461","w0462","w0463","w0464","w0465","w0466","w0467","w0468","w0469","w0470","w0471","w0472","w0473","w0474","w0475","w0476","w0477","w0478","w0479","w0480","w0481","w0482","w0483","w0484","w0485","w0486","w0487","w0488","w0489","w0490","w0491","w0492","w0493","w0494","w0495","w0496","w0497","w0498","w0499","w0500","w0501","w0502","w0503","w0504","w0505","w0506","w0507","w0508","w0509","w0510","w0511","w0512","w0513","w0514","w0515","w0516","w0517","w0518","w0519","w0520","w0521","w0522","w0523","w0524","w0525","w0526","w0527","w0528","w0529","w0530","w0531","w0532","w0533","w0534","w0535","w0536","w0537","w0538","w0539","w0540","w0541","w0542","w0543","w0544","w0545","w0546","w0547","w0548","w0549","w0550","w0551","w0552","w0553","w0554","w0555","w0556","w0557","w0558","w0559","w0560","w0561","w0562","w0563","w0564","w0565","w0566","w0567","w0568","w0569","w0570","w0571","w0572","w0573","w0574","w0575","w0576","w0577","w0578","w0579","w0580","w0581","w0582","w0584","w0585","w0586","w0588","w0589","w0590","w0591","w0592","w0593","w0594","w0595"],"4":["w0596","w0597","w0598","w0599","w0600","w0601","w0602","w0603","w0604","w0605","w0606","w0607","w0608","w0609","w0610","w0611","w0612","w0613","w0614","w0615","w0616","w0617","w0618","w0619","w0620","w0621","w0622","w0623","w0624","w0625","w0626","w0627","w0628","w0629","w0630","w0631","w0632","w0633","w0634","w0635","w0636","w0637","w0638","w0639","w0640","w0641","w0642","w0643","w0644","w0645","w0646","w0647","w0648","w0649","w0650","w0651","w0652","w0653","w0654","w0655","w0656","w0657","w0658","w0659","w0660","w0661","w0662","w0663","w0664","w0665","w0666","w0667","w0668","w0669","w0670","w0671","w0672","w0673","w0674","w0675","w0676","w0677","w0678","w0679","w0680","w0681","w0682","w0683","w0684","w0685","w0686","w0687","w0688","w0689","w0690","w0691","w0692","w0693","w0694","w0695","w0696","w0697","w0698","w0699","w0700","w0701","w0702","w0703","w0704","w0705","w0706","w0707","w0708","w0709","w0710","w0711","w0712","w0713","w0714","w0715","w0716","w0717","w0718","w0719","w0720","w0721","w0722","w0723","w0724","w0725","w0726","w0727","w0728","w0729","w0730","w0731","w0732","w0733","w0734","w0735","w0736","w0737","w0738","w0739","w0740","w0741","w0742","w0743","w0744","w0745","w0746","w0747","w0748","w0749","w0750","w0751","w0752","w0753","w0754","w0755","w0756","w0757","w0758","w0759","w0760","w0761","w0762","w0763","w0764","w0765","w0766","w0767","w0768","w0769","w0770","w0771","w0772","w0773","w0774","w0775","w0776","w0777","w0778","w0779","w0780","w0781","w0782","w0783","w0784","w0785","w0786","w0787","w0788","w0789","w0790","w0791","w0792","w0793","w0794","w0795","w0796","w0797","w0798","w0799","w0800","w0801","w0802","w0803","w0804","w0805","w0806","w0807","w0808","w0809","w0810","w0811","w0812","w0813","w0814","w0815","w0816","w0817","w0818","w0819","w0820","w0821","w0822","w0823","w0824","w0825","w0826","w0827","w0828","w0829","w0830","w0831","w0832","w0833","w0834","w0835","w0836","w0837","w0838","w0839","w0840","w0841","w0842","w0843","w0844","w0845","w0846","w0847","w0848","w0849","w0850","w0851","w0852","w0853","w0854","w0855","w0856","w0857","w0858","w0859","w0860","w0861","w0862","w0863","w0864","w0865","w0866","w0867","w0868","w0869","w0870","w0871","w0872","w0873","w0874","w0875","w0876","w0877","w0878","w0879","w0880","w0881","w0882","w0883","w0884","w0885","w0886","w0887","w0888","w0889","w0890","w0891","w0892","w0893","w0894","w0895","w0896","w0897","w0898","w0899","w0900","w0901","w0902","w0903","w0904","w0905","w0906","w0907","w0908","w0909","w0910","w0911","w0912","w0913","w0914","w0915","w0916","w0917","w0918","w0919","w0920","w0921","w0922","w0923","w0924","w0925","w0926","w0927","w0928","w0929","w0930","w0931","w0932","w0933","w0934","w0935","w0936","w0937","w0938","w0939","w0940","w0941","w0942","w0943","w0944","w0945","w0946","w0947","w0948","w0949","w0950","w0951","w0952","w0953","w0954","w0955","w0956","w0957","w0958","w0959","w0960","w0961","w0962","w0963","w0964","w0965","w0966","w0967","w0968","w0969","w0970","w0971","w0972","w0973","w0974","w0975","w0976","w0977","w0978","w0979","w0980","w0981","w0982","w0983","w0984","w0985","w0986","w0987","w0988","w0989","w0990","w0991","w0992","w0993","w0994","w0995","w0996","w0997","w0998","w0999","w1000","w1001","w1002","w1003","w1004","w1005","w1006","w1007","w1008","w1009","w1010","w1011","w1012","w1013","w1014","w1015","w1016","w1017","w1018","w1019","w1020","w1021","w1022","w1023","w1024","w1025","w1026","w1027","w1028","w1029","w1030","w1031","w1032","w1033","w1034","w1035","w1036","w1037","w1038","w1039","w1040","w1041","w1042","w1043","w1044","w1045","w1046","w1047","w1048","w1049","w1050","w1051","w1052","w1053","w1054","w1055","w1056","w1057","w1058","w1059","w1060","w1061","w1062","w1063","w1064","w1065","w1066","w1067","w1068","w1069","w1070","w1071","w1072","w1073","w1074","w1075","w1076","w1077","w1078","w1079","w1080","w1081","w1082","w1083","w1084","w1085","w1086","w1087","w1088","w1089","w1090","w1091","w1092","w1093","w1094","w1095","w1096","w1097","w1098","w1099","w1100","w1101","w1102","w1103","w1104","w1105","w1106","w1107","w1108","w1109","w1110","w1111","w1112","w1113","w1114","w1115","w1116","w1117","w1118","w1119","w1120","w1121","w1122","w1123","w1124","w1125","w1126","w1127","w1128","w1129","w1130","w1131","w1132","w1133","w1134","w1135","w1136","w1137","w1138","w1139","w1140","w1141","w1142","w1143","w1144","w1145","w1146","w1147","w1148","w1149","w1150","w1151","w1152","w1153","w1154","w1155","w1156","w1157","w1158","w1159","w1160","w1161","w1162","w1163","w1164","w1165","w1166","w1167","w1168","w1169","w1170","w1171","w1172","w1173","w1174","w1175","w1176","w1177","w1178","w1179","w1180","w1181","w1182","w1183","w1184","w1185","w1186","w1187","w1188","w1189","w1190","w1191","w1192","w1193"]},"notes":[{"id":"hao-ma","trigger":{"scene":"street-hello"}},{"id":"lao-xiao","trigger":{"word":"x0004"}},{"id":"le","trigger":{"scene":"street-hungry"}},{"id":"bukeqi","trigger":{"word":"w0141"}},{"id":"bei","trigger":{"word":"x0001"}}],"needsName":true}
@@ -933,6 +933,7 @@ import { createInterface } from "node:readline/promises";
933
933
  import { fileURLToPath } from "node:url";
934
934
 
935
935
  // ../core/src/types.ts
936
+ var PLAYER_MARK = "\uE000";
936
937
  var REJECT_REASONS = [
937
938
  "unknown-scene",
938
939
  "in-scene",
@@ -946,7 +947,9 @@ var REJECT_REASONS = [
946
947
  "bad-tile",
947
948
  "not-linked",
948
949
  "unknown-word",
949
- "no-mentor"
950
+ "no-mentor",
951
+ "bad-name",
952
+ "no-name"
950
953
  ];
951
954
  var WALLET_REASONS = ["wages", "mixup", "food", "rent"];
952
955
 
@@ -1120,6 +1123,25 @@ function shuffle(xs, rng) {
1120
1123
  return a;
1121
1124
  }
1122
1125
 
1126
+ // ../core/src/player.ts
1127
+ var MAX_NAME_LENGTH = 20;
1128
+ function cleanName(name) {
1129
+ const n = name.trim();
1130
+ if (!n || [...n].length > MAX_NAME_LENGTH || /[\p{Cc}\p{Cf}]/u.test(n) || n.includes(PLAYER_MARK)) return void 0;
1131
+ return n;
1132
+ }
1133
+ function personalize(line, name) {
1134
+ if (!line.text.includes(PLAYER_MARK) && !line.meaning?.includes(PLAYER_MARK)) return line;
1135
+ const grow = name.length - PLAYER_MARK.length;
1136
+ const shiftAt = (pos) => pos + grow * [...line.text.slice(0, pos).matchAll(new RegExp(PLAYER_MARK, "g"))].length;
1137
+ return {
1138
+ ...line,
1139
+ text: line.text.split(PLAYER_MARK).join(name),
1140
+ tokens: line.tokens.map((t) => ({ ...t, start: shiftAt(t.start), end: shiftAt(t.end) })),
1141
+ ...line.meaning !== void 0 ? { meaning: line.meaning.split(PLAYER_MARK).join(name) } : {}
1142
+ };
1143
+ }
1144
+
1123
1145
  // ../core/src/dialogue.ts
1124
1146
  function reject(ctx, reason) {
1125
1147
  ctx.ev.push({ type: "inputRejected", reason });
@@ -1155,9 +1177,11 @@ function hear(ctx, line) {
1155
1177
  if (!rec.first) rec.first = { line: line.text, place: ctx.state.place };
1156
1178
  }
1157
1179
  }
1180
+ var nameOf = (state2) => state2.player ?? "?";
1158
1181
  function speak(ctx, npc, line) {
1159
- ctx.ev.push({ type: "lineSpoken", npc, line });
1160
- hear(ctx, line);
1182
+ const said = personalize(line, nameOf(ctx.state));
1183
+ ctx.ev.push({ type: "lineSpoken", npc, line: said });
1184
+ hear(ctx, said);
1161
1185
  }
1162
1186
  var altKey = (n) => `alt:${n}`;
1163
1187
  var altIndex = (key) => /^alt:\d+$/.test(key) ? Number(key.slice(4)) : void 0;
@@ -1200,11 +1224,11 @@ function optionLine(ex, run, key) {
1200
1224
  const n = altIndex(key);
1201
1225
  return n === void 0 ? ex.variants[key].reply : ex.variants[comboKey(run.combo)].alts[n];
1202
1226
  }
1203
- function optionsEvent(ex, run) {
1204
- return run.mode === "pick" ? { type: "replyOptions", mode: "pick", options: run.options.map((k) => optionLine(ex, run, k)) } : { type: "replyOptions", mode: "tiles", tiles: run.tiles };
1227
+ function optionsEvent(ex, run, name) {
1228
+ return run.mode === "pick" ? { type: "replyOptions", mode: "pick", options: run.options.map((k) => personalize(optionLine(ex, run, k), name)) } : { type: "replyOptions", mode: "tiles", tiles: run.tiles };
1205
1229
  }
1206
1230
  function emitOptions(ctx, ex) {
1207
- ctx.ev.push(optionsEvent(ex, ctx.state.run));
1231
+ ctx.ev.push(optionsEvent(ex, ctx.state.run, nameOf(ctx.state)));
1208
1232
  }
1209
1233
  function describeRun(course2, state2) {
1210
1234
  const run = state2.run;
@@ -1214,8 +1238,8 @@ function describeRun(course2, state2) {
1214
1238
  if (!run || !scene || !ex || !v) return [];
1215
1239
  return [
1216
1240
  { type: "sceneStarted", scene: scene.id, npc: scene.npc },
1217
- { type: "lineSpoken", npc: scene.npc, line: v.npc },
1218
- optionsEvent(ex, run)
1241
+ { type: "lineSpoken", npc: scene.npc, line: personalize(v.npc, nameOf(state2)) },
1242
+ optionsEvent(ex, run, nameOf(state2))
1219
1243
  ];
1220
1244
  }
1221
1245
  function beginExchange(ctx, scene, index) {
@@ -1287,7 +1311,7 @@ function resolve(ctx, scene, ex, chosen, diff, tilesWrong = false, other = false
1287
1311
  }
1288
1312
  if (run.misses >= 2) {
1289
1313
  const v = ex.variants[comboKey(run.combo)];
1290
- const line = v.rephrase ?? v.npc;
1314
+ const line = personalize(v.rephrase ?? v.npc, nameOf(ctx.state));
1291
1315
  ctx.ev.push({ type: "lineRephrased", npc: scene.npc, line, slow: !v.rephrase });
1292
1316
  hear(ctx, line);
1293
1317
  }
@@ -1300,6 +1324,7 @@ function startScene(ctx, id) {
1300
1324
  const scene = sceneById(ctx, id);
1301
1325
  if (!scene) return reject(ctx, "unknown-scene");
1302
1326
  if (ctx.state.run) return reject(ctx, "in-scene");
1327
+ if (ctx.course.needsName && !ctx.state.player) return reject(ctx, "no-name");
1303
1328
  if (scene.place !== ctx.state.place) return reject(ctx, "wrong-place");
1304
1329
  if (!isAvailable(scene, ctx.state)) return reject(ctx, "locked");
1305
1330
  if (ctx.state.slot >= ctx.course.world.slotsPerDay) return reject(ctx, "no-slots");
@@ -1376,7 +1401,7 @@ function isRunShape(x) {
1376
1401
  if (!["pick", "tiles", "type"].includes(x.mode) || !isStrings(x.options) || !isStrings(x.tiles)) return false;
1377
1402
  return ["exchange", "misses", "earned", "mixups"].every((k) => isCount(x[k]));
1378
1403
  }
1379
- var INPUT_TYPES = /* @__PURE__ */ new Set(["goTo", "startScene", "reply", "replyTiles", "helpWord", "visitMentor", "sleep"]);
1404
+ var INPUT_TYPES = /* @__PURE__ */ new Set(["goTo", "startScene", "reply", "replyTiles", "helpWord", "visitMentor", "setName", "sleep"]);
1380
1405
  function isLogEntry(x) {
1381
1406
  return isObj(x) && isCount(x.t) && isCount(x.day) && isCount(x.slot) && isObj(x.input) && INPUT_TYPES.has(x.input.type);
1382
1407
  }
@@ -1419,6 +1444,9 @@ function parseSave(raw, course2) {
1419
1444
  if (!isObj(data.scenesDone) || !allValues(data.scenesDone, isCount)) return { ok: false, reason: "bad-scenesDone" };
1420
1445
  if (!isObj(data.words) || !allValues(data.words, isWordRecord)) return { ok: false, reason: "bad-words" };
1421
1446
  if (data.run !== null && !isRunShape(data.run)) return { ok: false, reason: "bad-run" };
1447
+ if (data.player !== void 0 && (typeof data.player !== "string" || cleanName(data.player) !== data.player)) {
1448
+ return { ok: false, reason: "bad-player" };
1449
+ }
1422
1450
  if (!("notes" in data)) data.notes = { ready: [], read: [] };
1423
1451
  if (!("log" in data)) data.log = [];
1424
1452
  if (!isObj(data.notes) || !isStrings(data.notes.ready) || !isStrings(data.notes.read)) return { ok: false, reason: "bad-notes" };
@@ -1476,6 +1504,13 @@ function handle(ctx, input) {
1476
1504
  case "helpWord":
1477
1505
  if (!course2.words[input.word]) return reject(ctx, "unknown-word");
1478
1506
  return setWord(ctx, input.word, recordHelp);
1507
+ case "setName": {
1508
+ const name = cleanName(input.name);
1509
+ if (!name) return reject(ctx, "bad-name");
1510
+ state2.player = name;
1511
+ ctx.ev.push({ type: "playerNamed", name });
1512
+ return;
1513
+ }
1479
1514
  case "visitMentor":
1480
1515
  return visitMentor(ctx);
1481
1516
  case "sleep":
@@ -1643,6 +1678,8 @@ var UI_KEYS = {
1643
1678
  "keys-tiles": ["keys"],
1644
1679
  "keys-help": ["keys"],
1645
1680
  "keys-notebook": [],
1681
+ "keys-name": [],
1682
+ "name-prompt": [],
1646
1683
  "notebook-progress": ["stage", "known", "total", "heard"],
1647
1684
  "notebook-empty": [],
1648
1685
  "notebook-elsewhere": [],
@@ -1667,7 +1704,7 @@ var UI_KEYS = {
1667
1704
  "notice-bad-save": [],
1668
1705
  "notice-read-only": [],
1669
1706
  "resume-title": [],
1670
- "resume-item": ["day", "place", "currency", "wallet", "done", "date"],
1707
+ "resume-item": ["name", "day", "place", "currency", "wallet", "done", "date"],
1671
1708
  "resume-ask": [],
1672
1709
  "resume-none": [],
1673
1710
  "export-none": [],
@@ -1732,7 +1769,7 @@ function renderScreen(m, cols, rows) {
1732
1769
  return [
1733
1770
  border("\u250C", m.title, "\u2510", "\u2500", cols, m.hud),
1734
1771
  ...body.map((l) => [{ text: "\u2502 ", dim: true }, ...fitLine(l, inner), { text: " \u2502", dim: true }]),
1735
- border("\u2514", m.footer, "\u2518", "\u2500", cols)
1772
+ border("\u2514", m.footer, "\u2518", "\u2500", cols, m.footerRight)
1736
1773
  ];
1737
1774
  }
1738
1775
 
@@ -1798,6 +1835,7 @@ function startApp(opts) {
1798
1835
  let notebookFrom = "explore";
1799
1836
  let notebookTop = 0;
1800
1837
  let resuming = false;
1838
+ let nameInput = "";
1801
1839
  const push = (...lines) => {
1802
1840
  log = [...log, ...lines].slice(-LOG_LIMIT2);
1803
1841
  };
@@ -1951,6 +1989,9 @@ function startApp(opts) {
1951
1989
  return [...said, ...extra].slice(0, 9);
1952
1990
  }
1953
1991
  function prompt(width) {
1992
+ if (mode === "name") {
1993
+ return [[{ text: t("name-prompt"), bold: true }], [{ text: "> " }, { text: nameInput, bold: true }, { text: "_", dim: true }]];
1994
+ }
1954
1995
  if (mode === "explore") {
1955
1996
  return [[{ text: t("menu-title"), dim: true }], ...menu().map((m, i) => [{ text: `${i + 1}) ${m.label}` }])];
1956
1997
  }
@@ -1978,6 +2019,7 @@ function startApp(opts) {
1978
2019
  [{ text: `${t("tiles-answer")} `, dim: true }, { text: tileInput.map((i) => tiles[i]).join(""), bold: true }]
1979
2020
  ];
1980
2021
  }
2022
+ const footerRight = opts.version ? `Silver Tongue v${opts.version}` : void 0;
1981
2023
  function render() {
1982
2024
  const s = core2.state;
1983
2025
  const { cols, rows } = term2.size();
@@ -1996,15 +2038,26 @@ function startApp(opts) {
1996
2038
  notebookTop = Math.max(0, Math.min(notebookTop, lines.length - bodyRows));
1997
2039
  const page = lines.slice(notebookTop, notebookTop + bodyRows);
1998
2040
  const prompt2 = [...page, ...Array(bodyRows - page.length).fill([])];
1999
- term2.write(renderScreen({ title: t(`place-${s.place}`), hud, log: [], prompt: prompt2, footer: t("keys-notebook") }, cols, rows));
2041
+ term2.write(renderScreen({ title: t(`place-${s.place}`), hud, log: [], prompt: prompt2, footer: t("keys-notebook"), footerRight }, cols, rows));
2000
2042
  return;
2001
2043
  }
2002
- const [footerId, count] = mode === "explore" ? ["keys-explore", menu().length] : mode === "help" ? [lastLine?.meaning ? "keys-help-sentence" : "keys-help", helpWords().length] : replyMode === "pick" ? ["keys-pick", pickOptions2.length] : ["keys-tiles", tiles.length];
2044
+ const [footerId, count] = mode === "name" ? ["keys-name", 0] : mode === "explore" ? ["keys-explore", menu().length] : mode === "help" ? [lastLine?.meaning ? "keys-help-sentence" : "keys-help", helpWords().length] : replyMode === "pick" ? ["keys-pick", pickOptions2.length] : ["keys-tiles", tiles.length];
2003
2045
  const footer = t(footerId, { keys: keyRange(count) });
2004
- term2.write(renderScreen({ title: t(`place-${s.place}`), hud, log, prompt: prompt(cols - 4), footer }, cols, rows));
2046
+ term2.write(renderScreen({ title: t(`place-${s.place}`), hud, log, prompt: prompt(cols - 4), footer, footerRight }, cols, rows));
2005
2047
  }
2006
2048
  function press(key) {
2007
2049
  if (key.name === "ctrl-c") return opts.quit();
2050
+ if (mode === "name") {
2051
+ const ch = key.text ?? ([...key.name].length === 1 ? key.name : void 0);
2052
+ if (key.name === "return") {
2053
+ if (!core2.send({ type: "setName", name: nameInput }).some((e) => e.type === "inputRejected")) {
2054
+ persist();
2055
+ mode = core2.state.run ? "scene" : "explore";
2056
+ } else push([{ text: t("reject-bad-name"), color: "red" }]);
2057
+ } else if (key.name === "backspace") nameInput = [...nameInput].slice(0, -1).join("");
2058
+ else if (ch && ch >= " " && [...nameInput].length < MAX_NAME_LENGTH) nameInput += ch;
2059
+ return render();
2060
+ }
2008
2061
  if (mode === "notebook") {
2009
2062
  if (key.name === "escape" || key.name === "n") mode = notebookFrom;
2010
2063
  else if (key.name === "down") notebookTop += 1;
@@ -2065,6 +2118,7 @@ function startApp(opts) {
2065
2118
  resuming = true;
2066
2119
  apply(describeRun(course2, core2.state));
2067
2120
  resuming = false;
2121
+ if (course2.needsName && !core2.state.player) mode = "name";
2068
2122
  term2.onKey(press);
2069
2123
  term2.onResize(render);
2070
2124
  render();
@@ -2104,6 +2158,7 @@ async function decodeSave(line, course2) {
2104
2158
  function sessionLines(sessions, course2, t, date) {
2105
2159
  return sessions.map((s, i) => {
2106
2160
  const text = t("resume-item", {
2161
+ name: s.state.player ? `${s.state.player} \xB7 ` : "",
2107
2162
  day: s.state.day,
2108
2163
  place: t(`place-${s.state.place}`),
2109
2164
  currency: course2.world.currency,
@@ -2125,6 +2180,7 @@ var USAGE = `Usage: silver-tongue [--new | --resume | --export | --import <line>
2125
2180
  --export print the game you played last as one line of text
2126
2181
  --import <line> add a game exported with --export (nothing is overwritten);
2127
2182
  use --import - to paste the line on standard input
2183
+ --version print the version
2128
2184
  --help show this help`;
2129
2185
  function parseFlags(args) {
2130
2186
  let parsed;
@@ -2137,7 +2193,8 @@ function parseFlags(args) {
2137
2193
  resume: { type: "boolean" },
2138
2194
  export: { type: "boolean" },
2139
2195
  import: { type: "string" },
2140
- help: { type: "boolean", short: "h" }
2196
+ help: { type: "boolean", short: "h" },
2197
+ version: { type: "boolean", short: "v" }
2141
2198
  }
2142
2199
  });
2143
2200
  } catch (e) {
@@ -2146,6 +2203,7 @@ function parseFlags(args) {
2146
2203
  }
2147
2204
  const { values, positionals } = parsed;
2148
2205
  if (values.help) return { mode: "help" };
2206
+ if (values.version) return { mode: "version" };
2149
2207
  const chosen = ["new", "resume", "export", "import"].filter((k) => values[k] !== void 0 && values[k] !== false);
2150
2208
  if (chosen.length > 1) return { mode: "error", message: `use one of ${chosen.map((k) => `--${k}`).join(", ")}, not several` };
2151
2209
  const course2 = positionals[0] ? { coursePath: positionals[0] } : {};
@@ -2174,7 +2232,8 @@ function createNodeTerminal(input = process.stdin, output = process.stdout) {
2174
2232
  const handlers = [];
2175
2233
  input.on("keypress", (str, key) => {
2176
2234
  const name = keyName(str, key);
2177
- if (name) for (const h of handlers) h({ name });
2235
+ const text = str && [...str].length === 1 && str >= " " && !key?.ctrl && !key?.meta ? str : void 0;
2236
+ if (name) for (const h of handlers) h(text ? { name, text } : { name });
2178
2237
  });
2179
2238
  input.on("end", () => {
2180
2239
  for (const h of handlers) h({ name: "ctrl-c" });
@@ -2206,6 +2265,27 @@ function createNodeTerminal(input = process.stdin, output = process.stdout) {
2206
2265
  };
2207
2266
  }
2208
2267
 
2268
+ // package.json
2269
+ var package_default = {
2270
+ name: "silver-tongue",
2271
+ version: "0.6.0",
2272
+ description: "Learn a language by living in it: a text game for the terminal.",
2273
+ type: "module",
2274
+ repository: { type: "git", url: "git+https://github.com/jamil314/silver-tongue.git", directory: "packages/tui-node" },
2275
+ license: "MIT",
2276
+ engines: { node: ">=22" },
2277
+ bin: { "silver-tongue": "dist/silver-tongue.mjs" },
2278
+ files: ["dist"],
2279
+ scripts: {
2280
+ bundle: 'esbuild src/main.ts --bundle --platform=node --format=esm --outfile=dist/silver-tongue.mjs --banner:js="#!/usr/bin/env node" && mkdir -p dist/courses/zh-china-en && cp ../../dist/courses/zh-china-en/course.json dist/courses/zh-china-en/'
2281
+ },
2282
+ devDependencies: {
2283
+ "@silver-tongue/core": "*",
2284
+ "@silver-tongue/tui": "*",
2285
+ esbuild: "^0.28.2"
2286
+ }
2287
+ };
2288
+
2209
2289
  // src/sessions.ts
2210
2290
  import { existsSync, mkdirSync, readdirSync, readFileSync, renameSync, statSync } from "node:fs";
2211
2291
  import { join } from "node:path";
@@ -2307,6 +2387,10 @@ if (major < 22) {
2307
2387
  process.exit(1);
2308
2388
  }
2309
2389
  var flags = parseFlags(process.argv.slice(2));
2390
+ if (flags.mode === "version") {
2391
+ console.log(package_default.version);
2392
+ process.exit(0);
2393
+ }
2310
2394
  if (flags.mode === "help") {
2311
2395
  console.log(USAGE);
2312
2396
  process.exit(0);
@@ -2399,6 +2483,7 @@ startApp({
2399
2483
  term,
2400
2484
  now: Date.now,
2401
2485
  notice,
2486
+ version: package_default.version,
2402
2487
  save: readOnly ? void 0 : (s) => writeSave(savePath, s),
2403
2488
  quit: () => bail(0)
2404
2489
  });
package/package.json CHANGED
@@ -1,6 +1,6 @@
1
1
  {
2
2
  "name": "silver-tongue",
3
- "version": "0.5.0",
3
+ "version": "0.6.0",
4
4
  "description": "Learn a language by living in it: a text game for the terminal.",
5
5
  "type": "module",
6
6
  "repository": { "type": "git", "url": "git+https://github.com/jamil314/silver-tongue.git", "directory": "packages/tui-node" },