MACROPAD 2+ Player "Chess" clock

Moderators: adafruit_support_bill, adafruit

Please be positive and constructive with your questions and comments.
Locked
User avatar
macewmi
 
Posts: 69
Joined: Sat Feb 08, 2020 10:26 am

MACROPAD 2+ Player "Chess" clock

Post by macewmi »

If you've seen a video where people are playing chess, you've probably noticed a chess clock.
clockLoRes.jpg
clockLoRes.jpg (188.51 KiB) Viewed 183 times
It's a way to ensure that games that involve a lot of "pondering" will end after a reasonable amount of time. During a player's turn, their clock is running. When they finish their move, they push a button which stops their clock and starts their opponent's clock. Play continues in this way. At the start of the game, each player is given a specific amount of time to beat their opponent. If they haven't beaten their opponent by within that time -- they lose.

My friends and family play games that require "pondering" but the games aren't limited to two players. To keep these games moving along, I used the MacroPad to build a "chess" clock for between 2 and 12 players.

Here's the flow:
  • Display a bitmap for a few seconds
    Prompt for the number of players. Use the encoder to dial-in the number
    Light that many pixels with a rainbow palette
    rainboxLoRes.jpg
    rainboxLoRes.jpg (258.32 KiB) Viewed 183 times
    Prompt for the player who will make the first move. Again, use the encoder
    Push the encoder to begin play
    Repeat until the current player's time expires or someone wins
    • Turn off all keys and Illuminate the key of the current player only
      Display the current player's time remaining
      When the current player presses their key, move on to the next player
    ELSE
    • Display a humiliating "You lost"
    timeoutLoRes.jpg
    timeoutLoRes.jpg (336.95 KiB) Viewed 183 times

Code: Select all

from adafruit_macropad import MacroPad
import time
import colorLib  # Array of 12 colors
import toneLib  # Array of 12 tones


def clearDisplay(display):
    for line in range(10):
        display[line].text = " "
    display.show()


def lightNextPlayer():
    #OLED[0].text = "Player {}".format(currentPlayer + 1)
    macropad.pixels[currentPlayer] = colorLib.PALETTE[currentPlayer]
    # macropad.play_tone(toneLib.TONES[currentPlayer], 0.25)
    # macropad.play_tone(toneLib.TONES[5], 0.25)
    return time.time()


def showAllPlayers():
    for player in range(numberOfPlayers):
        macropad.pixels[player] = colorLib.PALETTE[player]


def splashScreen():
    macropad.display_image("mace.bmp")
    time.sleep(1)


def getNumberOfPlayers():
    while not macropad.encoder_switch:
        players = macropad.encoder + 2
        if players < 2:
            players = 2
        if players > 12:
            players = 12
        OLED[0].text = "Players? {}".format(players)
        OLED.show()
    else:
        # numberOfPlayers = macropad.encoder + 2
        time.sleep(0.4)  # crappy debouce
        return players


macropad = MacroPad()

# Initialze the display
splashScreen()
OLED = macropad.display_text("Chess Clock")
macropad.pixels.fill((0, 0, 0))

numberOfPlayers = getNumberOfPlayers()

while True:
    showAllPlayers()
    # get first player
    firstPlayer = 1
    while not macropad.encoder_switch:
        firstPlayer = macropad.encoder + 2 - numberOfPlayers + 1
        if firstPlayer < 1:
            firstPlayer = 1
        if firstPlayer > numberOfPlayers:
            firstPlayer = numberOfPlayers
        OLED[1].text = "First player? {}".format(firstPlayer)
        OLED.show()
    else:
        time.sleep(0.4)  # crappy debouce

    OLED[0].text = "Press encoder"
    OLED[1].text = "to begin!"

    while not macropad.encoder_switch:
        continue
    else:
        clearDisplay(OLED)
        time.sleep(0.2)
    
    # Artificially low 10-second game for testing
    countdown = [10] * numberOfPlayers 

    currentPlayer = firstPlayer - 1  # switch to zero-relative

    for key in range(numberOfPlayers):
        macropad.pixels[key] = (0, 0, 0)
        time.sleep(0.2)

    startTime = lightNextPlayer()

    timeRemaining = countdown[currentPlayer]
    while timeRemaining > 0:
        minutes = timeRemaining // 60
        seconds = timeRemaining % 60
        if timeRemaining < 0:
            break
        OLED[0].text = "Player {} {}:{:02d}".format(currentPlayer + 1, minutes, seconds)
        key_event = macropad.keys.events.get()
        if key_event and key_event.pressed:
            if key_event.key_number == currentPlayer:
                macropad.pixels[currentPlayer] = 0x000000
                countdown[currentPlayer] = timeRemaining
                currentPlayer = (currentPlayer + 1) % numberOfPlayers
                startTime = lightNextPlayer()
        time.sleep(0.2) # crappy debouce
        timeRemaining = countdown[currentPlayer] - (time.time() - startTime)
    else:
        OLED[0].text = "Player {}".format(currentPlayer + 1)
        OLED[1].text = "Time's up!"
        macropad.pixels.fill(colorLib.INDIGO)
        macropad.pixels[currentPlayer] = colorLib.RED
        time.sleep(5) # Let the agony of defeat soak in a bit.
        clearDisplay(OLED)
        macropad.pixels.fill(0x000000)

User avatar
johnpark
 
Posts: 985
Joined: Wed Mar 25, 2009 2:15 pm

Re: MACROPAD 2+ Player "Chess" clock

Post by johnpark »

Nicely done, this is a great project!

Locked
Please be positive and constructive with your questions and comments.

Return to “AdaBox! Show us what you made!”