Micro:bit Multiplayer Reaction Timer Game
Python Code

from microbit import *
import random
import music

# High scores (lower is better). None means no score yet.
best_a = None
best_b = None

# --- Helper: vibration on pin0 ---
def vibrate(duration_ms):
    pin0.write_digital(1)
    sleep(duration_ms)
    pin0.write_digital(0)

# --- Helper: countdown animation ---
def countdown():
    for i in range(3):
        display.show(Image("00000:00000:00900:00000:00000"))
        sleep(200)
        display.clear()
        sleep(200)

# --- Helper: show high score for a player ---
def show_high_score(player, score):
    if score is None:
        display.scroll(player + " BEST: ---")
    else:
        display.scroll(player + " BEST: " + str(score) + "ms")

display.scroll("REACTION 2P")

while True:
    display.scroll("A/B=START")

    # Wait for either player to start the round
    while not (button_a.was_pressed() or button_b.was_pressed()):
        sleep(50)

    display.clear()
    display.scroll("GET READY")
    countdown()

    # Random delay between 1 and 4 seconds (1000–4000 ms)
    delay = random.randint(1000, 4000)

    # FALSE START CHECK DURING DELAY
    false_starter = None
    start_delay = running_time()
    while running_time() - start_delay < delay:
        if button_a.was_pressed():
            false_starter = "A"
            break
        if button_b.was_pressed():
            false_starter = "B"
            break
        sleep(10)

    if false_starter is not None:
        # False start detected
        display.show(Image.NO)
        music.play(music.WAWAWAWAA)
        vibrate(150)

        if false_starter == "A":
            display.scroll("A FALSE")
            display.scroll("B WINS!")
        else:
            display.scroll("B FALSE")
            display.scroll("A WINS!")

        # Show current best times
        show_high_score("A", best_a)
        show_high_score("B", best_b)
        display.scroll("B=RESET")

        # Wait for B to reset or auto-return after a bit
        reset_wait = running_time()
        while running_time() - reset_wait < 5000:
            if button_b.was_pressed():
                break
            sleep(50)
        display.clear()
        continue  # Next round

    # No false start – send GO signal
    display.show(Image.HAPPY)
    music.play("C4:4")
    vibrate(250)

    start_time = running_time()

    # Wait for first reaction (winner)
    winner = None
    while winner is None:
        if button_a.was_pressed():
            winner = "A"
        elif button_b.was_pressed():
            winner = "B"
        sleep(5)

    end_time = running_time()
    reaction_time = end_time - start_time

    # Announce winner and reaction time
    display.clear()
    if winner == "A":
        display.scroll("A WINS!")
        display.scroll(str(reaction_time) + "ms")
        vibrate(200)
        music.play(music.POWER_UP)

        # Update high score for A
        if best_a is None or reaction_time < best_a:
            best_a = reaction_time
            display.scroll("A NEW BEST!")
        show_high_score("A", best_a)
        show_high_score("B", best_b)

    else:
        display.scroll("B WINS!")
        display.scroll(str(reaction_time) + "ms")
        vibrate(200)
        music.play(music.POWER_UP)

        # Update high score for B
        if best_b is None or reaction_time < best_b:
            best_b = reaction_time
            display.scroll("B NEW BEST!")
        show_high_score("A", best_a)
        show_high_score("B", best_b)

    display.scroll("B=RESET")

    # Wait for B to reset or timeout
    reset_wait = running_time()
    while running_time() - reset_wait < 5000:
        if button_b.was_pressed():
            break
        sleep(50)

    display.clear()