44import sys
55import threading
66
7+ # Note: Works best in a terminal. Browser version (Pyodide) uses simplified input.
8+
79EMOJIS = ["🍎" , "🚗" , "⚽" , "🐍" , "🎧" , "🔥" , "🌈" , "🚀" ]
810HIGH_SCORE_FILE = "highscore.txt"
911
2022}
2123
2224
25+ # Detect if running in browser (Pyodide)
26+ def is_browser ():
27+ """Return True if running in a browser environment (Pyodide)."""
28+ return sys .platform == "emscripten"
29+
2330
2431# Core, testable logic (no I/O, no global state)
2532
@@ -34,11 +41,7 @@ def get_input_limit(choice):
3441
3542
3643def generate_sequence (emojis , level ):
37- """Generate a random emoji sequence for the given level.
38-
39- Sequence length grows with level (level + 2), matching the
40- original game's difficulty curve.
41- """
44+ """Generate a random emoji sequence for the given level."""
4245 if level < 1 :
4346 raise ValueError ("level must be >= 1" )
4447 return random .choices (emojis , k = level + 2 )
@@ -72,17 +75,12 @@ def format_countdown_message(remaining_seconds):
7275
7376
7477def calculate_score (level , streak ):
75- """Calculate score for a correctly-answered round.
76-
77- Base score scales with level; a streak bonus rewards consecutive
78- correct answers.
79- """
78+ """Calculate score for a correctly-answered round."""
8079 base = level * 10
8180 streak_bonus = streak * 2
8281 return base + streak_bonus
8382
8483
85-
8684# I/O helpers
8785
8886def load_high_score ():
@@ -110,34 +108,25 @@ def save_high_score(score):
110108
111109
112110def clear_screen ():
113- os .system ('cls' if os .name == 'nt' else 'clear' )
111+ """Safe clear screen that works in both terminal and browser."""
112+ if is_browser ():
113+ print ("\n " * 3 ) # Simple spacing for browser
114+ else :
115+ os .system ('cls' if os .name == 'nt' else 'clear' )
114116
115117
116118def run_countdown (duration , stop_event ):
117- """Update a single countdown line once per second while waiting for input.
118-
119- Runs in a background thread. Instead of printing a new line each
120- tick, it:
121- 1. Saves the cursor's current position (which is on the input
122- line, wherever the user has typed so far).
123- 2. Moves the cursor up 2 lines to the dedicated countdown line.
124- 3. Clears that line and writes the new remaining-time message.
125- 4. Restores the cursor back to the input line, so the user's
126- typing is completely undisturbed.
127-
128- stop_event is set as soon as the user submits their answer, so the
129- countdown stops immediately rather than continuing to update.
130- """
119+ """Original fancy countdown (terminal only)."""
131120 remaining = duration
132121 while remaining > 0 :
133122 if stop_event .wait (timeout = 1 ):
134- return # user already answered, stop counting
123+ return
135124 remaining -= 1
136- sys .stdout .write ("\033 7" ) # save cursor position
137- sys .stdout .write ("\033 [2A" ) # move up 2 lines -> countdown line
138- sys .stdout .write ("\r \033 [2K" ) # jump to col 0 and clear the line
125+ sys .stdout .write ("\033 7" )
126+ sys .stdout .write ("\033 [2A" )
127+ sys .stdout .write ("\r \033 [2K" )
139128 sys .stdout .write (format_countdown_message (remaining ))
140- sys .stdout .write ("\033 8" ) # restore cursor -> back to input line
129+ sys .stdout .write ("\033 8" )
141130 sys .stdout .flush ()
142131
143132
@@ -184,26 +173,33 @@ def main():
184173 time .sleep (display_time )
185174 clear_screen ()
186175
187- # Line 1: countdown line (updated in place by run_countdown)
188- # Line 2: static prompt text
189- # Line 3: "> " where the user actually types
176+ # Input Phase
190177 print (format_countdown_message (input_time ))
191178 print ("Type the emojis in order (separated by spaces):" )
192179 sys .stdout .write ("> " )
193180 sys .stdout .flush ()
194181
195- stop_event = threading .Event ()
196- timer_thread = threading .Thread (
197- target = run_countdown , args = (input_time , stop_event ), daemon = True
198- )
199- timer_thread .start ()
182+ if is_browser ():
183+ # Simplified version for browser (no threads/ANSI)
184+ print ("\n ⚠️ Browser mode active - enter your answer below." )
185+ start_time = time .time ()
186+ user_input_raw = input ().strip ()
187+ elapsed = time .time () - start_time
188+ else :
189+ # Original fancy terminal version
190+ stop_event = threading .Event ()
191+ timer_thread = threading .Thread (
192+ target = run_countdown , args = (
193+ input_time , stop_event ), daemon = True
194+ )
195+ timer_thread .start ()
200196
201- start_time = time .time ()
202- user_input_raw = input ().strip ()
203- elapsed = time .time () - start_time
197+ start_time = time .time ()
198+ user_input_raw = input ().strip ()
199+ elapsed = time .time () - start_time
204200
205- stop_event .set ()
206- timer_thread .join (timeout = 0.2 )
201+ stop_event .set ()
202+ timer_thread .join (timeout = 0.2 )
207203
208204 user_input = parse_input (user_input_raw )
209205 timed_out = is_timeout (elapsed , input_time )
@@ -261,4 +257,4 @@ def main():
261257
262258
263259if __name__ == '__main__' :
264- main ()
260+ main ()
0 commit comments