// Arduino double dice roller with gimmick 
// A project for @klup77 by @TDvenlo
// https://www.youtube.com/watch?v=lC-AQQbGjd8

#define BUTTON_PIN A0

int sensorValue = 0;
unsigned long time_now = 0;
int period = 20000; 
bool randomReady = 0;

const byte die1Pins[] = { 2, 3, 4, 5};
const byte die2Pins[] = { 9, 10, 11, 12};

void setup() {
  pinMode (A0, INPUT);  // initialize pin A0 for analogue sensing
  //next loop initializes all output pins
  for (byte i = 0; i < 4; i++) {
    pinMode(die1Pins[i], OUTPUT);
    pinMode(die2Pins[i], OUTPUT);
  }
  Serial.begin(9600); //start serial monitor for debug output
}

void turnOff(const byte pins[]) {
  //this should turn off the LEDS instantaneously
  for (byte i=0; i < 4; i++) {
    digitalWrite(pins[i], LOW);
  }  
}

void displayNumber(const byte pins[], byte number) {
  //display a number between 1 ... 7 on the dice.
  //7???? YES, 7! our dice can show the number 7
  for (byte i = 0; i < 4; i++) {  //this loop clears previous display
    digitalWrite(pins[i], LOW);
    delay(25);
  }
  switch (number) {
  case 1:
    digitalWrite(pins[3], HIGH);
    break;
  case 2:
    digitalWrite(pins[0], HIGH);
    break;
  case 3:
    digitalWrite(pins[0], HIGH);
    digitalWrite(pins[3], HIGH);
    break;
  case 4:
    digitalWrite(pins[0], HIGH);
    digitalWrite(pins[1], HIGH);
    break;
  case 5:
    digitalWrite(pins[0], HIGH);
    digitalWrite(pins[1], HIGH);
    digitalWrite(pins[3], HIGH);
    break;
  case 6:
    digitalWrite(pins[0], HIGH);
    digitalWrite(pins[1], HIGH);
    digitalWrite(pins[2], HIGH);
    break;
  case 7:
    digitalWrite(pins[0], HIGH);
    digitalWrite(pins[1], HIGH);
    digitalWrite(pins[2], HIGH);
    digitalWrite(pins[3], HIGH);
  }
}

void loop() {
  bool diceRolled = 0;
  sensorValue = analogRead(BUTTON_PIN);         //for analog sensor (piezo)
  //Serial.println(sensorValue); //uncomment this line to activate debugging console
  if(sensorValue > 50){
    diceRolled = 1;
  }

  if (!randomReady && diceRolled) {
    // Use the time until the first button press
    // to initialize the random number generator
    randomSeed(micros());
    randomReady = 1;
  }

  if (diceRolled) {
    //if the dice is 'rolled', execute the roll
    int seventyseven = random(78); //initialize gimmick
    if(seventyseven==77){ 
      //with the odds of 77 to 1 the gimmick is activated, diceroll 77!
      //first blink all LEDS 6 times
      for (int i = 0; i < 6; i++) {
        displayNumber(die1Pins, 7);
        displayNumber(die2Pins, 7);
        delay(200 + i * 30);
        turnOff(die1Pins);
        turnOff(die2Pins);
        delay(200 + i * 30);
      }
      //then display number 77!
      displayNumber(die1Pins, 7);
      displayNumber(die2Pins, 7);
    }
    else{
      //if the gimmick is not activated, perform a normal dice roll
      //generate 15 random combinations and keep the last one
      //show each iteration a little longer, aka slow the roll down
      for (byte i = 0; i < 15; i++) {
        int num1 = random(1, 7);
        int num2 = random(1, 7);
        displayNumber(die1Pins, num1);
        displayNumber(die2Pins, num2);
        delay(50 + i * 10);
      }
    }
    time_now = millis();  //store timestamp of last roll
  }
  
  if (millis() >= time_now + period) {
    //after certain time of inactivity (period) LEDs should turn off. (actual timestamp greater or equal to last roll + period)
    turnOff(die1Pins);
    turnOff(die2Pins);
  }
}