-
1
-
2
-
3
-
4
-
5
-
6
-
7
-
8
-
9
-
10
-
11
-
12
-
13
-
14
-
15
-
16
-
17
-
18
-
19
-
20
-
21
-
22
-
23
-
24
-
25
-
26
-
27
-
28
-
29
-
30
-
31
-
32
-
33
-
34
-
35
-
36
-
37
-
38
-
39
-
40
-
41
-
42
-
43
-
44
-
45
-
46
-
47
-
48
-
49
-
50
-
51
-
52
-
53
-
54
-
55
-
56
-
57
-
58
-
59
-
60
-
61
-
62
-
63
-
64
-
65
-
66
-
67
-
68
-
69
-
70
-
71
-
72
-
73
-
74
-
75
-
76
-
77
-
78
-
79
-
80
-
81
-
82
-
83
-
84
-
85
-
86
-
87
-
88
-
89
-
90
-
91
-
92
-
93
-
94
-
95
-
96
-
97
-
98
-
99
-
100
-
101
-
102
-
103
-
104
-
105
-
106
-
107
-
108
-
109
-
110
-
111
-
112
-
113
-
114
-
115
-
116
-
117
-
118
-
119
-
120
-
121
-
122
-
123
-
124
-
125
-
126
-
127
-
128
-
129
-
130
-
131
-
132
-
133
-
134
-
135
-
136
-
137
-
138
-
139
-
140
-
141
-
142
-
143
-
144
-
145
-
146
-
147
-
148
-
149
-
150
-
151
-
152
-
153
-
154
-
155
-
156
-
157
-
158
-
159
-
160
-
161
-
162
-
163
-
164
-
165
-
166
-
167
-
168
-
169
-
170
-
171
-
172
-
173
-
174
-
175
-
176
-
177
-
178
-
179
-
180
-
181
-
182
-
183
-
184
-
185
-
186
-
187
-
188
-
189
-
190
-
191
-
192
-
193
-
194
-
195
-
196
-
197
-
198
-
199
-
200
-
201
-
202
-
203
-
204
-
205
-
206
-
207
-
208
-
209
-
210
-
211
-
212
-
213
-
214
-
215
-
216
-
217
-
218
-
219
-
220
-
221
-
222
-
223
-
224
-
225
-
226
-
227
-
228
-
229
-
230
-
231
-
232
-
233
-
234
-
235
-
236
-
237
-
238
-
239
-
240
-
241
-
242
-
243
-
244
-
245
-
246
-
247
-
248
-
249
-
250
-
251
-
252
-
253
-
254
-
255
-
256
-
257
-
258
-
259
-
260
-
261
-
262
-
263
-
264
-
265
-
266
-
267
-
268
-
269
-
270
-
271
-
272
-
273
-
274
init python:
from pingshui_rhyme import PingZeClassifier, RhymeChecker
classifier = PingZeClassifier()
rhyme_checker = RhymeChecker()
# https://en.wikipedia.org/wiki/Jueju#Structure
# https://pages.ucsd.edu/~dkjordan/chin/pinyin3.html
# 0 = ping
# 1 = ze
tones = [
[1, 1, 0, 0, 1, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 0, 1, 1, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0],
[1, 1, 1, 0, 0, 0, 0, 1, 1, 0, 0, 0, 0, 1, 1, 1, 1, 1, 0, 0],
[0, 0, 1, 1, 0, 1, 1, 1, 0, 0, 1, 1, 0, 0, 1, 0, 0, 1, 1, 0]
]
# 0 = no rhyme
# 1 = last character must rhyme
rhymes = [
[0, 1, 0, 1],
[0, 1, 0, 1],
[1, 1, 0, 1],
[1, 1, 0, 1]
]
def format_poem(poem, rubypoem):
pad = 20 - len(poem)
return rubypoem + "_" * pad
def format_tones(poem):
out = "Tones\n\n"
for i in range(4):
for j in range(20):
if j < len(poem):
if (classifier.classify(poem[j])[0] == 'ze') == tones[i][j]:
out += "{color=#0D0}"
else:
out += "{color=#F00}"
out += ("仄" if tones[i][j] else "平") + "{/color}"
else:
out += "仄" if tones[i][j] else "平"
if j % 5 == 4:
out += "\n"
out += "\n"
return out
def format_rhymes(poem):
out = "Rhymes\n\n"
for i in range(4):
used_rhymes = set()
for j in range(4):
if rhymes[i][j] and 5 * j + 4 < len(poem):
used_rhymes.add(rhyme_checker.get_rhyme_group(poem[5 * j + 4])[0][2])
for j in range(4):
if rhymes[i][j]:
if 5 * j + 4 < len(poem):
if len(used_rhymes) == 1:
out += "{color=#0D0}"
else:
out += "{color=#F00}"
out += "韻{/color}"
else:
out += "韻"
out += "\n"
out += "\n"
return out
def score(poem):
scores = []
for i in range(4):
points = [sum((classifier.classify(poem[j])[0] == 'ze') == tones[i][j] for j in range(20)), 0]
used_rhymes = set()
rhyme_count = 0
for j in range(4):
if rhymes[i][j]:
used_rhymes.add(rhyme_checker.get_rhyme_group(poem[5 * j + 4])[0][2])
rhyme_count += 1
if len(used_rhymes) == 1:
points[0] += 5 * rhyme_count
points[1] = 5 * rhyme_count
scores.append(points)
return max(scores)
def pick(words, poem, idx, i):
poem += words[idx][i][0]
idx += 1
transform farleft:
xalign -0.1
yalign 1.1
transform canvas:
xalign 0.95
yalign 0.1
# OK this is gonna be super gross
screen poetry(poem, rubypoem):
frame:
style_prefix "poem"
xalign 0.53
yalign 0.15
vbox:
xsize 1000
xalign 0.5
yalign 0.5
# Ren'Py 8.3.7 seems to have some bug related to ruby_style
# So let's downgrade to 8.3.6 for now
text "[format_poem(poem, rubypoem)]" text_align 0.5 color "#000" size 180 line_leading 25 ruby_style style.ruby_style
frame:
style_prefix "poem"
xalign 0.83
yalign 0.15
vbox:
xalign 0.5
yalign 0.5
text "[format_tones(poem)]" text_align 0.5 color "#000" size 38
frame:
style_prefix "poem"
xalign 0.95
yalign 0.15
vbox:
xalign 0.5
yalign 0.5
text "[format_rhymes(poem)]" text_align 0.5 color "#000" size 38
screen poetry_choices(word):
window:
fixed:
for i in range(4):
textbutton "[word[i][0]] [word[i][1]]" xalign (i + 1) / 5 yalign 0.5 action Return(word[i]):
xysize (400, 500)
style poem_frame:
padding (0, 0)
background None
style ruby_style is default:
size 36
yoffset -160
color "#000"
label run_poetry_game(do_tutorial):
scene bg garden
show canvas at canvas
show shl at farleft
show screen poetry(poem, rubypoem)
with fade
$ idx = 0
if do_tutorial:
s "I'd like you to help me write a {i}jueju{/i}, which a type of Tang poem with four lines of five characters."
s "There are four valid tone-rhyme patterns, listed on the right. In Middle Chinese, the literary language of the Tang dynasty, there are two types of tones, 平 {i}ping{/i} and 仄 {i}ze{/i}. They roughly correspond to tones 1 and 2 and tones 3 and 4 in modern standard Mandarin."
s "Likewise, most Middle Chinese rhymes correspond to Mandarin rhymes, but there have also been a lot of sound changes over 1300 years."
s "If a character in your poem has the correct tone and rhyme, the corresponding position in the pattern will light up green."
s "But don't worry too much about meeting the standards! This is a real Tang poem and it doesn't even fit the template exactly!"
s "Let's get started!"
$ poem = ""
$ rubypoem = ""
show screen poetry(poem, rubypoem)
label loop:
if idx < len(words):
# Apparently call screen is different than renpy.call_screen?
# Doing it in Python makes it act weirdly
# For instance, it breaks rollback
# For some reason the bottom box flashes here but whatever
call screen poetry_choices(words[idx])
$ poem += _return[0]
$ englishpoem.append(_return[1].split(" (")[0])
$ rubypoem += "{rb}" + _return[0] + "{/rb}{rt}" + englishpoem[-1] + "{/rt}"
$ idx += 1
show screen poetry(poem, rubypoem)
jump loop
label poetry_end:
$ poem_score = score(poem)
if poem_score[0] == 35:
s "What the... that's impossible! Your tone score is [poem_score[0] - poem_score[1]] and you get a rhyme bonus, for a total score of [poem_score[0]]! I've never seen someone get a perfect score!"
elif poem_score[1] > 0:
s "Wow nice poem! Your tone score is [poem_score[0] - poem_score[1]] and you get a rhyme bonus, for a total score of [poem_score[0]]! Very impressive!"
else:
s "Wow nice poem! Your tone score is [poem_score[0]]! Awesome!"
return
label minigame:
python:
words = [
[("春", "spring"), ("旱", "drought"), ("年", "year"), ("鯰", "catfish")],
[("來", "comes"), ("擊", "strikes"), ("飄", "floats"), ("蹦", "hops")],
[("無", "without"), ("歸", "to return to"), ("弱", "weak"), ("爛", "rotting")],
[("長安", "Chang'an"), ("口紅", "lipstick"), ("政變", "coup"), ("豐田", "Toyota")],
[("友", "friend"), ("貓", "cat"), ("人", "people"), ("佛", "Buddha")],
[("跨", "steps across"), ("飲", "drinks"), ("扔", "throws"), ("撈", "dredges up")],
[("乒乓球", "ping-pong"), ("毛澤東", "Mao Zedong"), ("動畫片", "anime"), ("大漢奸", "great traitor (to the Han ethnicity)")],
[("偶遇", "chance encounter"), ("搜索", "look up"), ("詐騙", "defraud"), ("撫摸", "caress")],
[("十字路", "crossroads"), ("喵喵叫", "make meowing sounds"), ("碰碰車", "bumper cars"), ("薩達姆", "Saddam Hussein")],
[("風", "wind"), ("雀", "sparrow"), ("汞", "mercury (immortality pill ingredient)"), ("校", "school")],
[("打", "attacks"), ("知", "knows"), ("爭", "competes"), ("難", "endures")],
[("且", "also"), ("非", "not"), ("故", "therefore"), ("勿", "do not")],
[("生鏽", "rust"), ("解凍", "defrost"), ("成仙", "become immortal"), ("吃麵", "eat noodles")]
]
poem = "打起黃鶯兒莫教枝上啼啼時驚"
# This was a huge PITA to type
rubypoem = "{rb}打起{/rb}{rt}hit{/rt}{rb}黃{/rb}{rt}yellow{/rt}{rb}鶯兒{/rb}{rt}oriole{/rt}{rb}莫{/rb}{rt}do not{/rt}{rb}教{/rb}{rt}teach{/rt}{rb}枝上{/rb}{rt}on branch{/rt}{rb}啼{/rb}{rt}sing{/rt}{rb}啼{/rb}{rt}sing{/rt}{rb}時{/rb}{rt}time{/rt}{rb}驚{/rb}{rt}startle{/rt}"
englishpoem = []
label poetry1:
call run_poetry_game(True) from _call_run_poetry_game
python:
words = [
[("超寬", "ultrawide"), ("變態", "perverted"), ("禁忌", "taboo"), ("傲嬌", "tsundere")],
[("獸醫", "veterinarian"), ("獨裁", "dictatorship"), ("原成", "Genghis Impact"), ("刺客", "assassin")],
[("好", "is good"), ("欠", "owes money"), ("酷", "is cool"), ("亂", "is chaotic")],
[("肆", "undisciplined"), ("狂", "crazy"), ("翠", "green (Xi Jinping dies twice)"), ("匪", "CCP bandit")],
[("川", "river"), ("聖", "sage"), ("狐", "fox"), ("敵", "enemy")],
[("摟", "hugs"), ("吻", "kisses"), ("顫", "quakes"), ("扶", "supports (by placing a hand on)")],
[("匝道", "highway ramp"), ("火箭", "rocket"), ("蠟燭", "candle"), ("鉛酸", "battery acid")],
[("刪除", "delete"), ("閹割", "castrate"), ("殘舔", "cruelly lick"), ("封鎖", "block (on social media)")],
[("喵星人", "invaders from Planet Meow"), ("啦啦隊", "cheerleaders"), ("連鎖店", "chain stores"), ("殺必死", "fan service")],
[("仁", "humane"), ("棒", "outstanding"), ("萌", "moe (cute)"), ("悶", "stuffy")],
[("室", "room"), ("猴", "Möngke"), ("皇", "emperor"), ("醬", "sauce")],
[("又", "again"), ("不", "does not"), ("偶", "occasionally"), ("愛", "loves")],
[("糟糕", "oops"), ("上線", "go online"), ("房主", "landlord"), ("搗蛋", "commit mischief")]
]
poem = ""
rubypoem = ""
englishpoem = []
label poetry2:
s "Let's do another one."
call run_poetry_game(False) from _call_run_poetry_game_1
python:
words = [
[("水母", "jellyfish"), ("圖釘", "thumb tack"), ("電鋸", "chainsaw"), ("鐵水", "molten iron")],
[("彈跳屋", "bouncy house"), ("三溫暖", "sauna"), ("波波池", "ball pit"), ("主機板", "motherboard")],
[("適合", "is suitable for"), ("吸引", "attracts"), ("懲罰", "punishes"), ("戀愛", "romantically loves")],
[("肥", "obese"), ("貪", "greedy"), ("愚", "foolish"), ("炎", "inflamed (medical)")],
[("老鼠", "rodent"), ("肉丸", "meatball"), ("白癡", "idiot"), ("雲盤", "cloud storage")],
[("砍", "chop"), ("噴", "eject"), ("毀", "destroy"), ("戳", "poke")],
[("偉大", "mighty"), ("折扣", "discounted (on sale)"), ("傲慢", "arrogant"), ("網紅", "viral on the internet")],
[("領袖", "leader"), ("車禍", "car accident"), ("地鼠", "gopher"), ("明月", "bright moon")],
[("友力", "power of friendship"), ("正義", "righteousness"), ("常識", "common sense"), ("松鼠", "squirrels")],
[("必", "must"), ("永", "always"), ("真", "really"), ("也", "also")],
[("超酷", "super cool"), ("極端", "extreme"), ("芝士", "cheese"), ("簡單", "easy")]
]
poem = ""
rubypoem = ""
englishpoem = []
label poetry3:
s "One last poem!"
call run_poetry_game(False) from _call_run_poetry_game_2
s "Hope you had fun!"
hide screen poetry
hide canvas
show rating at top
s "Oh and by the way I rated Kublai: Star Rail!"
stop music fadeout 2
scene black with fade
$ renpy.quit()