code.py
  1  # SPDX-FileCopyrightText: 2020 Dave Astels for Adafruit Industries
  2  #
  3  # SPDX-License-Identifier: MIT
  4  
  5  """
  6  Dice roller for CLUE
  7  
  8  Set the number of dice with button A (1-2-3-4-5-6)
  9  and the type with button B (d4-d6-d8-d10-d12-d20-d100).
 10  Roll by shaking.
 11  Pressing either button returns to the dice selection mode.
 12  """
 13  
 14  import time
 15  from random import randint
 16  import board
 17  from adafruit_clue import clue
 18  from adafruit_debouncer import Debouncer
 19  import displayio
 20  from adafruit_bitmap_font import bitmap_font
 21  from adafruit_display_text import label
 22  
 23  
 24  # input constraints
 25  MAX_NUMBER_OF_DICE = 6
 26  SIDES = [4, 6, 8, 10, 12, 20, 100]
 27  
 28  # modes: selecting/result
 29  SELECTING = 0
 30  ROLL_RESULT = 1
 31  
 32  # 0-relative, gets adjusted to 1-relative before display/use
 33  number_of_dice = 0
 34  side_selection = 0
 35  
 36  button_a = Debouncer(lambda: clue.button_a)
 37  button_b = Debouncer(lambda: clue.button_b)
 38  
 39  # Set up display
 40  
 41  select_font = bitmap_font.load_font('/Helvetica-Bold-36.bdf')
 42  select_font.load_glyphs(b'0123456789XDd')
 43  select_color = 0xDB4379
 44  
 45  roll_font = bitmap_font.load_font('/Anton-Regular-104.bdf')
 46  roll_font.load_glyphs(b'0123456789X')
 47  roll_color = 0xFFFFFF
 48  
 49  select_label = label.Label(select_font, x=0, y=25, text='XdXXX', color=select_color)
 50  roll_label = label.Label(roll_font, x=0, y=150, text='XXX', color=roll_color)
 51  
 52  group = displayio.Group()
 53  group.append(select_label)
 54  group.append(roll_label)
 55  
 56  board.DISPLAY.show(group)
 57  
 58  # Helper functions
 59  
 60  def roll(count, sides):
 61      select_label.text = ''
 62      for i in range(15):
 63          roll_value = sum([randint(1, sides) for _ in range(count + 1)])
 64          roll_label.text = str(roll_value)
 65          roll_label.x = 120 - (roll_label.bounding_box[2] // 2)
 66          duration = (i * 0.05) / 2
 67          clue.play_tone(2000, duration)
 68          time.sleep(duration)
 69  
 70  
 71  def update_display(count, sides):
 72      select_label.text = '{0}d{1}'.format(count + 1, SIDES[sides])
 73      select_label.x = 120 - (select_label.bounding_box[2] // 2)
 74      roll_label.text = ''
 75  
 76  
 77  mode = SELECTING
 78  update_display(number_of_dice, side_selection)
 79  
 80  while True:
 81      button_a.update()
 82      button_b.update()
 83  
 84      if mode == SELECTING:
 85          if button_a.rose:
 86              number_of_dice = ((number_of_dice + 1) % MAX_NUMBER_OF_DICE)
 87              update_display(number_of_dice, side_selection)
 88          elif button_b.rose:
 89              side_selection = (side_selection + 1) % len(SIDES)
 90              update_display(number_of_dice, side_selection)
 91          elif clue.shake(shake_threshold=25):
 92              mode = ROLL_RESULT
 93              if SIDES[side_selection] == 100:   # only roll one percentile
 94                  number_of_dice = 0
 95                  update_display(number_of_dice, side_selection)
 96              roll(number_of_dice, SIDES[side_selection])
 97      else:
 98          if button_a.rose or button_b.rose:   # back to dice selection
 99              mode = SELECTING
100              update_display(number_of_dice, side_selection)
101          elif clue.shake(shake_threshold=25):   # reroll
102              roll(number_of_dice, SIDES[side_selection])