byte randomNum[100];
byte currentRound = 0;
byte counting = 0;
byte userPress = 0;
bool lastbtnState[4];
const int RATE = 333;
const byte lamps[] = {7, 8, 9, 10};
const byte buttons[] = {2, 3, 4, 5};
# define BEEP 6
bool noisy = true;
const int notes[] = { 300, 500, 700, 900};
void setup()
{
for (byte ii = 0; ii < 4; ii++) {
pinMode(buttons[ii], INPUT_PULLUP);
pinMode(lamps[ii], OUTPUT);
}
pinMode(BEEP, OUTPUT);
Serial.begin(9600);
// randomSeed(analogRead(A0));
currentRound = 0;
randomNum[currentRound] = random(0, 4);
}
void count()
{
lamp(randomNum[counting]);
while (lampService());
counting++;
}
byte theCode;
enum lampStates {IDLE, START, ON, OFF};
byte lampState;
unsigned long dwell;
void lamp(byte nn)
{
// turn off old lamp? really should not call a busy lamping machine...
lampState = START;
dwell = 0;
theCode = nn;
}
// returns 0 when done or not busy
byte lampService()
{
static unsigned long lastTime;
static byte status;
static int lastCode = -1;
unsigned long now = millis();
static int lastState = -1;
if (0) if (lastState != lampState) {
Serial.print(lampState);
Serial.print(" (");
Serial.println(dwell);
lastState = lampState;
}
if (now - lastTime < dwell) return status;
lastTime = now;
switch (lampState) {
case IDLE :
break;
case START :
if (lastCode >= 0) {
digitalWrite(lastCode, LOW);
noTone(BEEP);
}
digitalWrite(lamps[theCode], HIGH);
if (noisy) tone(BEEP, notes[theCode]);
status = 1;
dwell = RATE;
lampState = ON;
lastCode = theCode;
break;
case ON :
digitalWrite(lamps[theCode], LOW);
noTone(BEEP);
dwell = RATE;
lampState = OFF;
break;
case OFF :
lastCode = 0;
status = 0;
dwell = 0;
lampState = IDLE;
break;
}
return status;
}
# define DOWN LOW
# define UP HIGH
void user()
{
delay(20);
for (byte ii = 0; ii < 4; ii++) {
bool btn = digitalRead(buttons[ii]) == DOWN;
if (btn && !lastbtnState[ii]) {
if (ii == randomNum[userPress]) {
lamp(randomNum[userPress]);
userPress++;
}
else { // Oops!
counting = 0;
userPress = 0;
currentRound = 0;
randomNum[currentRound] = random(0, 4);
Serial.println("game over");
delay(1000);
}
}
lastbtnState[ii] = btn;
}
}
enum phases {SHOW = 0, TEST};
void loop()
{
// grow it. this should come after she successfully completes the sequence to date.
// it should be initialised with sequence length of 1
if (userPress == currentRound) {
Serial.println("ok, extending sequence");
currentRound++;
userPress = 0;
randomNum[currentRound] = random(0, 4);
}
// show it. in this state just play the sequence
// it could be interruptable, I don't think Simon was.
Serial.println("count() current round");
delay(500); // pacing
while (counting < currentRound) {
count();
}
// make her repeat it. mistakes start a new game.
// the machine will just wait and validate the next input
if (counting == currentRound)
{
counting = 0;
Serial.println("user() current round");
while (userPress < currentRound) {
lampService();
user();
}
while (lampService()); // gack! finish last step
}
}
/*
playing sequence - next until transition listening
listening - next until transition reward or error
reward - acknowledge transition or just grow
grow - transition to playing
error - punish, reset transition to playing
lamp machine init call for which, service to advnace light + tone, no tone, no light phases
// test lamp FSM
lamp(7);
while (lampService());
Serial.println("thassit.");
for (; ; );
*/