// A game of Redlight, Greenlight against a dragon
// Made by Loonmos

#include <Servo.h>

// attach things to pins
Servo myservo;  // create servo object to control a servo
int buttonPin = 2;
int pirPin = 4; // motion sensor
int ledGPin = 8; //green led
int buzzer = 10;
int ledRPin = 12; //red led

// status
int pirStat = 0; 
int buttonStat = 0;

// variables
int pos = 0;    // variable to store the servo position
int GLCounter = 0; //counts the time in the greenlight round
int GLTime; //total time in the greenlight round
int RLCounter = 0; //counts the time in the redlight round
int RLTime; //total time in the redlight round

// bools
bool checkMove;
bool checkButton;
bool positivePosition; //changes depending on if the servo should go from 0 to 180 or 180 to 0

//states
enum {beforeGame, greenLight, redLight, caughtMove, winGame};
unsigned char gameState; //what the game is doing

void setup() {
  myservo.attach(13);  // attaches the servo on pin 13 to the servo object
  pinMode(buttonPin, INPUT);
  pinMode(pirPin, INPUT);
  pinMode(ledGPin, OUTPUT);
  pinMode(buzzer, OUTPUT); 
  pinMode(ledRPin, OUTPUT);

  positivePosition = true;
  Serial.begin(9600);
}

void loop() 
{
  switch (gameState)
  {
    case beforeGame:
      BeforeGame();
      break;

    case greenLight:
      GreenLight();
      break;

    case redLight:
      RedLight();
      break;

    case caughtMove:
      WhenCaught();
      break;
    
    case winGame:
      EndGame();
      break;

    default:
      gameState = beforeGame;
      break;
  }

  if (checkButton == true)
  {
    CheckButton();
  }

  if (checkMove == true)
  {
    CheckMove();
  }
}

// Game States
void BeforeGame()
{
  checkMove = false;
  checkButton = true;

  if (buttonStat == HIGH)
    {
      LedBlink(900, ledRPin);
      delay(300);
      SwitchSound();
      buttonStat = 0;
      checkButton = false;
      GreenLightPrep();
      gameState = greenLight;
    }
}

void GreenLight()
{
  digitalWrite(ledGPin, HIGH);
  digitalWrite(ledRPin, LOW);
  checkButton = true;

  if (buttonStat == HIGH)
    {
      buttonStat = 0;
      checkButton = false;
      gameState = winGame;
    }
  
  GLCounter++;
  Serial.println(GLCounter); // this needs to be here to slow down the arduino since I didn't make a proper timer

  if (GLCounter == GLTime) // if the round is over
  {
    SwitchSound();
    checkButton = false;
    RedLightPrep();
    gameState = redLight;
  }
}

void RedLight()
{
  digitalWrite(ledGPin, LOW);
  digitalWrite(ledRPin, HIGH);

  CheckMove();

  if (pirStat == HIGH)
  {
    CaughtSound();
    gameState = caughtMove;
  }
  else if (pirStat == LOW)
  {
    DragonMove();
  }
  
  RLCounter++;
  Serial.println(RLCounter); // this needs to be here to slow down the arduino since I didn't make a proper timer

  if (RLCounter == RLTime) // if the round is over
  {
    SwitchSound();
    GreenLightPrep();
    gameState = greenLight;
  }
}

void WhenCaught()
{
  LedBlink(30, ledRPin);
  LedBlink(30, ledRPin);

  delay(2000);

  SwitchSound();
  GreenLightPrep();
  gameState = greenLight;
}

void EndGame()
{
  LedBlink(50, ledGPin);
  LedBlink(50, ledGPin);

  gameState = beforeGame;
}

// State Preperations
void GreenLightPrep() //resets the countdown
{
  GLCounter = 0;
  GLTime = random(500, 1000);
}

void RedLightPrep() //resets the countdown
{
  RLCounter = 0;
  RLTime = random(500, 1000);
}

// Checks
void CheckButton() //check if button pressed
{
  buttonStat = digitalRead(buttonPin);
}

void CheckMove() // check if someone moved
{
  pirStat = digitalRead(pirPin);
}

// Servo
void DragonMove()
{
  if (pos == 0)
  {
    positivePosition = true;
  }
  else if (pos == 180)
  {
    positivePosition = false;
  }

  if (positivePosition == true)
  {
    pos++;
    myservo.write(pos); 
  }
  else
  {
    pos--;
    myservo.write(pos); 
  }
}

// Sounds
void SwitchSound()
{
  tone(buzzer, 500); 
  delay(500);   
  noTone(buzzer);     
}

void CaughtSound()
{
  tone(buzzer, 1000); 
  delay(500);
  noTone(buzzer);     
}

// Sounds + Lights
void LedBlink(int betweenBlinks, int led)
{
  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 100);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 200);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 300);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 400);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 500);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 600);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 700);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 800);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 900);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);

  delay(betweenBlinks);
  digitalWrite(led, HIGH);
  tone(buzzer, 1000);
  delay(100);
  digitalWrite(led, LOW);
  noTone(buzzer);
}