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 browser environment (Pyodide)."""
28+ try :
29+ import js # Pyodide exposes this global
30+ return True
31+ except ImportError :
32+ return False
33+
2334
2435# Core, testable logic (no I/O, no global state)
2536
@@ -34,11 +45,7 @@ def get_input_limit(choice):
3445
3546
3647def 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- """
48+ """Generate a random emoji sequence for the given level."""
4249 if level < 1 :
4350 raise ValueError ("level must be >= 1" )
4451 return random .choices (emojis , k = level + 2 )
@@ -72,17 +79,12 @@ def format_countdown_message(remaining_seconds):
7279
7380
7481def 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- """
82+ """Calculate score for a correctly-answered round."""
8083 base = level * 10
8184 streak_bonus = streak * 2
8285 return base + streak_bonus
8386
8487
85-
8688# I/O helpers
8789
8890def load_high_score ():
@@ -110,34 +112,25 @@ def save_high_score(score):
110112
111113
112114def clear_screen ():
113- os .system ('cls' if os .name == 'nt' else 'clear' )
115+ """Safe clear screen that works in both terminal and browser."""
116+ if is_browser ():
117+ print ("\n " * 3 ) # Simple spacing for browser
118+ else :
119+ os .system ('cls' if os .name == 'nt' else 'clear' )
114120
115121
116122def 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- """
123+ """Original fancy countdown (terminal only)."""
131124 remaining = duration
132125 while remaining > 0 :
133126 if stop_event .wait (timeout = 1 ):
134- return # user already answered, stop counting
127+ return
135128 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
129+ sys .stdout .write ("\033 7" )
130+ sys .stdout .write ("\033 [2A" )
131+ sys .stdout .write ("\r \033 [2K" )
139132 sys .stdout .write (format_countdown_message (remaining ))
140- sys .stdout .write ("\033 8" ) # restore cursor -> back to input line
133+ sys .stdout .write ("\033 8" )
141134 sys .stdout .flush ()
142135
143136
@@ -184,26 +177,33 @@ def main():
184177 time .sleep (display_time )
185178 clear_screen ()
186179
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
180+ # Input Phase
190181 print (format_countdown_message (input_time ))
191182 print ("Type the emojis in order (separated by spaces):" )
192183 sys .stdout .write ("> " )
193184 sys .stdout .flush ()
194185
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 ()
186+ if is_browser ():
187+ # Simplified version for browser (no threads/ANSI)
188+ print ("\n ⚠️ Browser mode active - enter your answer below." )
189+ start_time = time .time ()
190+ user_input_raw = input ().strip ()
191+ elapsed = time .time () - start_time
192+ else :
193+ # Original fancy terminal version
194+ stop_event = threading .Event ()
195+ timer_thread = threading .Thread (
196+ target = run_countdown , args = (
197+ input_time , stop_event ), daemon = True
198+ )
199+ timer_thread .start ()
200200
201- start_time = time .time ()
202- user_input_raw = input ().strip ()
203- elapsed = time .time () - start_time
201+ start_time = time .time ()
202+ user_input_raw = input ().strip ()
203+ elapsed = time .time () - start_time
204204
205- stop_event .set ()
206- timer_thread .join (timeout = 0.2 )
205+ stop_event .set ()
206+ timer_thread .join (timeout = 0.2 )
207207
208208 user_input = parse_input (user_input_raw )
209209 timed_out = is_timeout (elapsed , input_time )
@@ -261,4 +261,4 @@ def main():
261261
262262
263263if __name__ == '__main__' :
264- main ()
264+ main ()
0 commit comments