Skip to content

Commit f4bc335

Browse files
authored
Merge pull request adafruit#1531 from caternuson/add_cpx_simon
add CPX Simple Simon
2 parents 7b0930c + f5ad424 commit f4bc335

File tree

1 file changed

+184
-0
lines changed

1 file changed

+184
-0
lines changed

CPX_Simple_Simon/code.py

+184
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,184 @@
1+
# Circuit Playground Express Simple Simon
2+
#
3+
# Game play based on information provided here:
4+
# http://www.waitingforfriday.com/?p=586
5+
#
6+
# Author: Carter Nelson
7+
# MIT License (https://opensource.org/licenses/MIT)
8+
import time
9+
import random
10+
import math
11+
import board
12+
from analogio import AnalogIn
13+
from adafruit_circuitplayground.express import cpx
14+
15+
FAILURE_TONE = 100
16+
SEQUENCE_DELAY = 0.8
17+
GUESS_TIMEOUT = 3.0
18+
DEBOUNCE = 0.250
19+
SEQUENCE_LENGTH = {
20+
1 : 8,
21+
2 : 14,
22+
3 : 20,
23+
4 : 31
24+
}
25+
SIMON_BUTTONS = {
26+
1 : { 'pads':(4,5), 'pixels':(0,1,2), 'color':0x00FF00, 'freq':415 },
27+
2 : { 'pads':(6,7), 'pixels':(2,3,4), 'color':0xFFFF00, 'freq':252 },
28+
3 : { 'pads':(1, ), 'pixels':(5,6,7), 'color':0x0000FF, 'freq':209 },
29+
4 : { 'pads':(2,3), 'pixels':(7,8,9), 'color':0xFF0000, 'freq':310 },
30+
}
31+
32+
def choose_skill_level():
33+
# Default
34+
skill_level = 1
35+
# Loop until button B is pressed
36+
while not cpx.button_b:
37+
# Button A increases skill level setting
38+
if cpx.button_a:
39+
skill_level += 1
40+
skill_level = skill_level if skill_level < 5 else 1
41+
# Indicate current skill level
42+
cpx.pixels.fill(0)
43+
for p in range(skill_level):
44+
cpx.pixels[p] = 0xFFFFFF
45+
time.sleep(DEBOUNCE)
46+
return skill_level
47+
48+
def new_game(skill_level):
49+
# Seed the random function with noise
50+
a4 = AnalogIn(board.A4)
51+
a5 = AnalogIn(board.A5)
52+
a6 = AnalogIn(board.A6)
53+
a7 = AnalogIn(board.A7)
54+
55+
seed = a4.value
56+
seed += a5.value
57+
seed += a6.value
58+
seed += a7.value
59+
60+
random.seed(seed)
61+
62+
# Populate the game sequence
63+
return [random.randint(1,4) for i in range(SEQUENCE_LENGTH[skill_level])]
64+
65+
def indicate_button(button, duration):
66+
# Turn them all off
67+
cpx.pixels.fill(0)
68+
# Turn on the ones for the given button
69+
for p in button['pixels']:
70+
cpx.pixels[p] = button['color']
71+
# Play button tone
72+
if button['freq'] == None:
73+
time.sleep(duration)
74+
else:
75+
cpx.play_tone(button['freq'], duration)
76+
# Turn them all off again
77+
cpx.pixels.fill(0)
78+
79+
def show_sequence(sequence, step):
80+
# Set tone playback duration based on current location
81+
if step <= 5:
82+
duration = 0.420
83+
elif step <= 13:
84+
duration = 0.320
85+
else:
86+
duration = 0.220
87+
88+
# Play back sequence up to current step
89+
for b in range(step):
90+
time.sleep(0.05)
91+
indicate_button(SIMON_BUTTONS[sequence[b]], duration)
92+
93+
def cap_map(b):
94+
if b == 1: return cpx.touch_A1
95+
if b == 2: return cpx.touch_A2
96+
if b == 3: return cpx.touch_A3
97+
if b == 4: return cpx.touch_A4
98+
if b == 5: return cpx.touch_A5
99+
if b == 6: return cpx.touch_A6
100+
if b == 7: return cpx.touch_A7
101+
102+
def get_button_press():
103+
# Loop over all the buttons
104+
for button in SIMON_BUTTONS.values():
105+
# Loop over each pad
106+
for pad in button['pads']:
107+
if cap_map(pad):
108+
indicate_button(button, DEBOUNCE)
109+
return button
110+
return None
111+
112+
def game_lost(step):
113+
# Show button that should have been pressed
114+
cpx.pixels.fill(0)
115+
for p in SIMON_BUTTONS[sequence[step]]['pixels']:
116+
cpx.pixels[p] = SIMON_BUTTONS[sequence[step]]['color']
117+
118+
# Play sad sound :(
119+
cpx.play_tone(FAILURE_TONE, 1.5)
120+
121+
# And just sit here until reset
122+
while True:
123+
pass
124+
125+
def game_won():
126+
# Play 'razz' special victory signal
127+
for i in range(3):
128+
indicate_button(SIMON_BUTTONS[4], 0.1)
129+
indicate_button(SIMON_BUTTONS[2], 0.1)
130+
indicate_button(SIMON_BUTTONS[3], 0.1)
131+
indicate_button(SIMON_BUTTONS[1], 0.1)
132+
indicate_button(SIMON_BUTTONS[4], 0.1)
133+
indicate_button(SIMON_BUTTONS[2], 0.1)
134+
135+
# Change tones to failure tone
136+
for button in SIMON_BUTTONS.values():
137+
button['freq'] = FAILURE_TONE
138+
139+
# Continue for another 0.8 seconds
140+
for i in range(2):
141+
indicate_button(SIMON_BUTTONS[3], 0.1)
142+
indicate_button(SIMON_BUTTONS[1], 0.1)
143+
indicate_button(SIMON_BUTTONS[4], 0.1)
144+
indicate_button(SIMON_BUTTONS[2], 0.1)
145+
146+
# Change tones to silence
147+
for button in SIMON_BUTTONS.values():
148+
button['freq'] = None
149+
150+
# Loop lights forever
151+
while True:
152+
indicate_button(SIMON_BUTTONS[3], 0.1)
153+
indicate_button(SIMON_BUTTONS[1], 0.1)
154+
indicate_button(SIMON_BUTTONS[4], 0.1)
155+
indicate_button(SIMON_BUTTONS[2], 0.1)
156+
157+
# Initialize setup
158+
cpx.pixels.fill(0)
159+
cpx.pixels[0] = 0xFFFFFF
160+
skill_level = choose_skill_level()
161+
sequence = new_game(skill_level)
162+
current_step = 1
163+
164+
#Loop forever
165+
while True:
166+
# Show sequence up to current step
167+
show_sequence(sequence, current_step)
168+
169+
# Read player button presses
170+
for step in range(current_step):
171+
start_guess_time = time.monotonic()
172+
guess = None
173+
while (time.monotonic() - start_guess_time < GUESS_TIMEOUT) and (guess == None):
174+
guess = get_button_press()
175+
if not guess == SIMON_BUTTONS[sequence[step]]:
176+
game_lost(sequence[step])
177+
178+
# Advance the game forward
179+
current_step += 1
180+
if current_step > len(sequence):
181+
game_won()
182+
183+
# Small delay before continuing
184+
time.sleep(SEQUENCE_DELAY)

0 commit comments

Comments
 (0)