#include <LiquidCrystal.h>

int click = 7;
int dinoPos = 2;
int state = 0;
int stepCount = 0;
int points = 0;
int record = 0;
int level = 1;
int speed = 150;
int upArr[16];
int downArr[16];
LiquidCrystal lcd(12, 11, 5, 4, 3, 2);

byte cactus[8] = {
	0b00100,
	0b10101,
	0b10101,
	0b11111,
	0b01110,
	0b01110,
	0b01110,
	0b00000
};

byte meteor[8] = {
	0b00000,
	0b01001,
	0b10010,
	0b00100,
	0b00001,
	0b11000,
	0b11100,
	0b11100
};

byte dino[8] = {
	0b01111,
	0b01111,
	0b11100,
	0b11100,
	0b11110,
	0b10010,
	0b11011,
	0b00000
};

void setup() {
  pinMode(click, INPUT_PULLUP);
  lcd.createChar(0, cactus);
  lcd.createChar(1, meteor);
  lcd.createChar(2, dino);
  lcd.begin(16, 2); 
 }

void loop() {
  lcd.setCursor(3,0);
  lcd.print("DINO RACE!");
  lcd.setCursor(1,2);
  lcd.print("Recorde = ");
  lcd.print(record);
  delay(50);
  if (!digitalRead(click)) state = 1;
  if (state == 1) levelStart();
  while (state == 1) {
    step();
    obstacle();
    printGame();
    printPoints();
    checkDeath();
    moveDino();
    delay(speed);
  }
}

void step() {
  for (int i = 0; i < 16; i++) {
    upArr[i] = upArr[i+1];
  }
  upArr[15] = 0;
  for (int i = 0; i < 16; i++) {
    downArr[i] = downArr[i+1];
  }
  downArr[15] = 0;
  if (upArr[0]||downArr[0]) {
    points++;
    if (points == 50 || points == 100 || points == 200 || points == 400) levelUp();
  }
  stepCount++;
}

void obstacle() {
  if (random(0,10) > 7) {
    if (!downArr[13] && !downArr[14] && !upArr[13] && !upArr[14]) {
      upArr[15] = 1;
    }
  }
  if (random(0,10) > 7) {
    if (!upArr[13] && !upArr[14] && !upArr[15]) {
      downArr[15] = 1;
    }
  }
}

void printGame() {
  lcd.clear();
  for (int i = 0; i < 16; i++) {
    if (upArr[i] == 1) {
        lcd.setCursor(i,0);
        lcd.write(byte(1));
    }
    if (downArr[i] == 1) {
      lcd.setCursor(i,2);
      lcd.write(byte(0));
    }
  }
  lcd.setCursor(1, dinoPos);
  lcd.write(byte(2));
}

void printPoints() {
  int column = 15;
  if (points >= 10) column = 14;
  if (points >= 100) column = 13;
  if (points >= 1000) column = 12;
  lcd.setCursor(column, 0);
  lcd.print(points);
}

void levelUp(){
  speed -= 50 / level;
  level++;
  for (int i = 0; i < 16; i++) upArr[i] = 0;
  for (int i = 0; i < 16; i++) downArr[i] = 0;
  levelStart();
}

void levelStart() {
  printGame();
  if (level < 5) {
    lcd.setCursor(5, 0);
    lcd.print("NIVEL ");
    lcd.print(level);
  } else {
    lcd.setCursor(1, 0);
    lcd.print("NIVEL MAXIMO!!");
  }
  delay(2000);
}

void moveDino() {
  if(!digitalRead(click)) {
    if (stepCount > 1) {
      dinoPos = (dinoPos == 0) ? 2 : 0;
      stepCount = 0;
    }
  }
}

void checkDeath() {
  if ((upArr[1] && dinoPos == 0) || (downArr[1] && dinoPos == 2)) death();
}

void death() {
  lcd.setCursor(5,0);
  lcd.print("PERDEU!");
  delay(2000);
  lcd.clear();
  lcd.setCursor(3,0);
  lcd.print("PONTOS: ");
  lcd.print(points);
  if (points > record) {
    lcd.setCursor(1,2);
    lcd.print("NOVO RECORDE!!");
    record = points;
  }
  while (digitalRead(click));
  resetGame();
  lcd.clear();
}

void resetGame() {
  for (int i = 0; i < 16; i++) upArr[i] = 0;
  for (int i = 0; i < 16; i++) downArr[i] = 0;
  dinoPos = 2;
  state = 0;
  points = 0;
  level = 1;
  speed = 150;
}