#include <LiquidCrystal.h>
#include <EEPROM.h>

// initialize the library with the numbers of the interface pins
LiquidCrystal lcd(7, 8, 9, 10, 11, 12);

String strGameName[3] = {"button 3 = enter", "Rock Paper Scissors", "Reaction"};    //an array of strings to hold the two games
int selection = 0;    //holds the selection for the game to play
int one = 3;          //the first button
int two = 4;          //the second button
int three = 5;        //the third button
int four = 6;         //the fourth button
int location = 15;    //the current location for the * in the reaction game
double tim = 1000;    //the time before the next * in the reaction game
int btnState = 0;     //the button state for button 1
int btnState2 = 0;    //the button state for button 2
int btnState3 = 0;    //the button state for button 3
int btnState4 = 0;    //the button state for button 4
int points = 0;       //the player's points
int points2 = 0;      //also the player's points. Used to determine if the player failed the reaction game
int highScore = 0;    //the high score for the current game

void setup() {
  lcd.begin(16, 2);         //initializes the lcd screen 
  pinMode(one, INPUT);      //make all button pins to input
  pinMode(three, INPUT);
  pinMode(four, INPUT);
  pinMode(two, INPUT);
  welcome();                //display the welcome screen
}

void loop() {
  while(selection == 1 && btnState4 == LOW){    //plays rock paper scissors as selected by the user
    delay(500);
    resetBtnState();              //resets the button states                            
    rps();                        //runs the rock paper scissors method
    resetBtnState();              //resets the button states again
    lcd.clear();
    lcd.setCursor(0,0);
    lcd.print("Play again?");     //prompt user to play again
    lcd.setCursor(0,1);
    lcd.print("1 = yes, 4 = no");
    while(btnState == LOW && btnState4 == LOW){
      btnState = digitalRead(one);    //pressing 1 goes back into the loop
      btnState4 = digitalRead(four);  //pressing 4 exits the loop
    }
    if(btnState4 == HIGH){            //this is just to check if the user has scored a new high score
      highScore == EEPROM.read(0);   //grab the high score from location 0 in eeprom
      if(points > highScore){         //if the current points are higher than what's recorded
        EEPROM.write(0, points);     //record the new high score 
        lcd.print("New high score!"); //notify the user
        lcd.setCursor(0,1);
        lcd.print(points);
        delay(500);
        lcd.clear();                  //clear out the screen
        lcd.setCursor(0,0);
      }
      points = 0;                     //reset the points
    }
  }
  if(selection == 2)
  {
    tim = 1000;                       //defaults the delay
  }
  while(selection == 2 && btnState4 == LOW){
    reaction();                       //starts the reaction game
    if(points > points2)              //if the points have changed, update the old points
    {
      points2 = points;
      tim/=1.5;                       //reduce the delay
    }
    else
    {
      lcd.clear();                    
      lcd.setCursor(0,0);
      if(points > EEPROM.read(1))   //check for a new high score
      {
        EEPROM.write(1, points);    //write to the high score if it is higher
        lcd.print("New high score!");
        lcd.setCursor(0,1);
        lcd.print(points);
        delay(500);
        lcd.clear();
        lcd.setCursor(0,0);
      }
      lcd.print("Try again?");      //asks the user if he/she wants to try again
      lcd.setCursor(0,1);
      lcd.print("1 = yes, 4 = no");
      while(btnState == LOW && btnState4 == LOW)
      {
        btnState = digitalRead(one);    //returns to the loop if the first button is pressed
        btnState4 = digitalRead(four);  //exits the loop otherwise
      }
      points = 0;                   //resets the score
    }
  }
  welcome();                        //puts the welcome message up
  attachInterrupt(digitalPinToInterrupt(2), doNothing, FALLING);    //set the interrupt pin to do nothing when pressed so the user cannot just gain points 
}

void doNothing(){       //does nothing
  
}

void reaction(){       //a game to test the user's reaction 
  location = 15;      //sets the location to 15, the char limit on the lcd screen for display
  attachInterrupt(digitalPinToInterrupt(2), reactionScore, FALLING);    //set the interrupt pin to add to the score
  lcd.clear();
  lcd.print("press 1 to stop");
  while(location > 0){  //if the location reaches 0, the user failed
    if(points2 < points)//check if the score has been updated
    {
      lcd.clear();
      lcd.setCursor(0,0);
      lcd.print("Nice!"); //let the user know he/she succeeded
      delay(500);
      break;
    }
    lcd.setCursor(location,1);//start printing * until it reaches location 0
    lcd.print("*");
    location--;
    delay(tim);
  }
}

void reactionScore()      //checks for the current location and adds 50 to the score if location is > 0
{
  if(location > 0){
    points += 50;
  }
}

void rps(){               //plays rock paper scissors
  randomSeed(millis());   //uses the time passed as a random number generator seed
  resetBtnState();        //resets all button states
  lcd.clear();
  lcd.setCursor(0,0);
  lcd.print("1=r, 2=p, 3=s");//1 for rock, 2 for paper, 3 for scissors for the corresponding buttons
  int randNum = random(3);  //generate a random number
  while(btnState == LOW && btnState2 == LOW && btnState3 == LOW)  //get the user input
  {
    btnState = digitalRead(one);
    if(btnState == HIGH){     //don't want the user to press multiple buttons.
      break;
    }
    btnState2 = digitalRead(two);
    if(btnState2 == HIGH){
      break;
    }
    btnState3 = digitalRead(three);
    if(btnState3 == HIGH){
      break;
    }
  }
  lcd.clear();              
  lcd.setCursor(0,0);
  if(randNum == 0)          //prints the randomly generated rock, paper, or scissors
  {
    lcd.print("Rock");    
  }
  else if(randNum == 1)
  {
    lcd.print("Paper");
  }
  else
  {
    lcd.print("Scissors");
  }
  if(btnState == HIGH && randNum == 2){       //compares what the user pressed to what the arduino generated
    points++;                                 //rock beats scissors
    lcd.setCursor(0,1);
    lcd.print("You Win!");
  }
  else if(btnState2 == HIGH && randNum == 0){//paper beats rock
    points++;
    lcd.setCursor(0,1);
    lcd.print("You Win!");
  }
  else if(btnState3 == HIGH && randNum == 1){//scissors beats paper
    points++;
    lcd.setCursor(0,1);
    lcd.print("You Win!");
  }
  else{                                       //in all other cases, the player loses and loses points.
    if(points > 0){
      points--;
    }
    lcd.setCursor(0,1);
    lcd.print("You Lose!");
  }
  delay(1000); 
}

void welcome(){                                 //a welcome message to the user
  resetBtnState();                              //resets all button states just in case
  selection = 0;                                //resets the selection for when this method gets recalled again
  lcd.setCursor(0,0);
  lcd.print(strGameName[0]);                    //prints the instructions for the user
  lcd.setCursor(0,1);
  lcd.print("1 = <-||2 = ->");
  //wait for the user to select a game    
  while(selection == 0){
    while(btnState3 == 0){
      btnState = digitalRead(one);
      btnState2 = digitalRead(four);
      if(btnState == HIGH && selection > 0){    //to ensure an out of bounds does not occur    
        lcd.clear();
        lcd.setCursor(0,0);
        selection--;
        lcd.print(strGameName[selection]);      //update the game name with the previous one
        lcd.setCursor(0,1);
        lcd.print("1 = <-, 2 = ->");
      }
      else if(btnState2 == HIGH && selection < 2){//ensure out of bounds does not occur
        lcd.clear();
        lcd.setCursor(0,0);
        selection++;
        lcd.print(strGameName[selection]);      //update the game name with the next one
        lcd.setCursor(0,1);
        lcd.print("1 = <-||2 = ->");
      }
      btnState3 = digitalRead(three);           //checks if the user has selected a game
      delay(100);
    }
    resetBtnState();                            //reset the button states again before moving on.
  }
}

void resetBtnState()      //resets the button states to 0
{
  btnState = 0;
  btnState2 = 0;
  btnState3 = 0;
  btnState4 = 0;
}



