#include <LiquidCrystal.h>

// Initialize the LCD with the pin numbers
LiquidCrystal lcd(8, 9, 4, 5, 6, 7);

// Define button pins
const int btnRIGHT = 0;
const int btnUP = 1;
const int btnDOWN = 2;
const int btnLEFT = 3;    // Using LEFT button for buying
const int btnSELECT = 4;
const int btnNONE = 5;

// Number of players and current player
int numPlayers = 2;
int currentPlayer = 1;

// Player positions
int playerPositions[4] = {0, 0, 0, 0}; // Assuming a maximum of 4 players

// Names of the places on the Monopoly board
const char* places[] = {
  "GO", "Old Kent Road", "Community Chest", "Whitechapel Road", "Income Tax", "Kings Cross Station",
  "The Angel Islington", "Chance", "Euston Road", "Pentonville Road", "Just Visiting Jail",
  "Pall Mall", "Electric Company", "Whitehall", "Northumberland Ave", "Marylebone Station",
  "Bow Street", "Community Chest", "Marlborough Street", "Vine Street", "Free Parking",
  "Strand", "Chance", "Fleet Street", "Trafalgar Square", "Fenchurch St Station", "Leicester Square",
  "Coventry Street", "Water Works", "Piccadilly", "Go to Jail", "Regent Street", "Oxford Street",
  "Community Chest", "Bond Street", "Liverpool St Station", "Chance", "Park Lane", "Super Tax",
  "Mayfair"
};

// Track ownership of the places
int ownership[40]; // -1 means no owner, 0-3 corresponds to player indices

// Indices of properties that can be bought
const int buyableProperties[] = {
  1, 3, 5, 6, 8, 9, 11, 13, 14, 15, 16, 18, 19, 21, 23, 24, 25, 26, 27, 29, 31, 32, 34, 37, 39
};

void setup() {
  lcd.begin(16, 2); // Set up the LCD's number of columns and rows
  lcd.print("Monopoly Game");
  delay(2000);
  selectNumPlayers();
  // Initialize ownership array to -1 (no owner)
  for (int i = 0; i < 40; i++) {
    ownership[i] = -1;
  }
}

void loop() {
  playTurn();
}

void selectNumPlayers() {
  lcd.clear();
  lcd.print("Players: ");
  lcd.print(numPlayers);
  delay(500);

  while (true) {
    int btn = read_LCD_buttons();
    if (btn == btnUP) {
      if (numPlayers < 4) numPlayers++;
    } else if (btn == btnDOWN) {
      if (numPlayers > 2) numPlayers--;
    } else if (btn == btnSELECT) {
      break;
    }
    lcd.setCursor(9, 0);
    lcd.print(numPlayers);
    delay(200);
  }
}

void playTurn() {
  lcd.clear();
  lcd.print("Player ");
  lcd.print(currentPlayer);
  lcd.setCursor(0, 1);
  lcd.print("Click SELECT");

  // Wait for SELECT button press to roll dice
  while (true) {
    int btn = read_LCD_buttons();
    if (btn == btnSELECT) {
      break;
    }
  }

  int diceRoll = random(1, 13); // Random number between 1 and 12
  lcd.clear();
  lcd.print("Player ");
  lcd.print(currentPlayer);
  lcd.setCursor(0, 1);
  lcd.print("Roll: ");
  lcd.print(diceRoll);

  delay(3000); // Display the rolled number for 3 seconds

  // Update player position
  playerPositions[currentPlayer - 1] = (playerPositions[currentPlayer - 1] + diceRoll) % 40;

  // Display the place name
  int position = playerPositions[currentPlayer - 1];
  lcd.clear();
  lcd.print(places[position]);

  // Check if the place is buyable
  bool isBuyable = false;
  for (int i = 0; i < sizeof(buyableProperties) / sizeof(buyableProperties[0]); i++) {
    if (position == buyableProperties[i]) {
      isBuyable = true;
      break;
    }
  }

  // Check if the place is owned by another player
  if (ownership[position] != -1 && ownership[position] != currentPlayer - 1) {
    lcd.setCursor(0, 1);
    lcd.print("Pay rent to P");
    lcd.print(ownership[position] + 1);
    delay(3000); // Display the rent message for 3 seconds
  }

  if (isBuyable && ownership[position] == -1) {
    // Wait for LEFT button press to buy the place or RIGHT to skip buying
    while (true) {
      int btn = read_LCD_buttons();
      if (btn == btnLEFT) {
        ownership[position] = currentPlayer - 1; // Mark the place as owned by the current player

        // Display "Bought by" message
        lcd.clear();
        lcd.print("Bought by");
        lcd.setCursor(0, 1);
        lcd.print("Player ");
        lcd.print(currentPlayer);

        delay(3000); // Display the "Bought by" message for 3 seconds
        break;
      } else if (btn == btnRIGHT) {
        break;
      }
    }
  } else {
    delay(3000); // Display the place name for 3 seconds if not buyable
  }

  // Switch to next player
  currentPlayer++;
  if (currentPlayer > numPlayers) {
    currentPlayer = 1;
  }

  lcd.clear();
  lcd.print("Next Player ");
  lcd.print(currentPlayer);
  lcd.setCursor(0, 1);
  lcd.print("Click SELECT");

  // Wait for the next player to press SELECT
  while (true) {
    int btn = read_LCD_buttons();
    if (btn == btnSELECT) {
      break;
    }
  }
}

int read_LCD_buttons() {
  int adc_key_in = analogRead(0); // Read the value from the keypad shield

  if (adc_key_in > 1000) return btnNONE;
  if (adc_key_in < 50)   return btnRIGHT;
  if (adc_key_in < 195)  return btnUP;
  if (adc_key_in < 380)  return btnDOWN;
  if (adc_key_in < 555)  return btnLEFT;
  if (adc_key_in < 790)  return btnSELECT;
  
  return btnNONE;
}
