// 4桁7セグメントスロットマシン
// ピン定義
const int LATCH_PIN = 4;  // 74HC595 STCP
const int CLOCK_PIN = 3;  // 74HC595 SHCP  
const int DATA_PIN = 2;   // 74HC595 DS

const int DIGIT_PINS[] = {5, 6, 7, 8};  // 桁選択ピン

const int START_BTN = A0;   // スタートボタン(緑)
const int STOP_BTN1 = A1;   // ストップボタン1(赤)
const int STOP_BTN2 = A2;   // ストップボタン2(赤)
const int STOP_BTN3 = A3;   // ストップボタン3(赤)

const int LED_PINS[] = {9, 10, 11};  // 演出用LED

// 7セグメント数字パターン
const byte DIGIT_PATTERNS[] = {
  0b11111100,  // 0
  0b01100000,  // 1
  0b11011010,  // 2
  0b11110010,  // 3
  0b01100110,  // 4
  0b10110110,  // 5
  0b10111110,  // 6
  0b11100000,  // 7
  0b11111110,  // 8
  0b11110110   // 9
};

// ゲーム状態
enum GameState {
  IDLE,
  SPINNING,
  STOPPING1,
  STOPPING2,
  STOPPING3,
  JACKPOT
};

GameState gameState = IDLE;
int reels[4] = {0, 0, 0, 0};  // 各リールの値
bool reelStopped[] = {false, false, false, false};
unsigned long lastUpdate = 0;
unsigned long jackpotStart = 0;
bool jackpotLedState = false;

void setup() {
  // ピン初期化
  pinMode(LATCH_PIN, OUTPUT);
  pinMode(CLOCK_PIN, OUTPUT);
  pinMode(DATA_PIN, OUTPUT);
  
  for (int i = 0; i < 4; i++) {
    pinMode(DIGIT_PINS[i], OUTPUT);
    digitalWrite(DIGIT_PINS[i], HIGH);  // 共通カソードなのでHIGHで消灯
  }
  
  for (int i = 0; i < 3; i++) {
    pinMode(LED_PINS[i], OUTPUT);
    digitalWrite(LED_PINS[i], LOW);
  }
  
  pinMode(START_BTN, INPUT_PULLUP);
  pinMode(STOP_BTN1, INPUT_PULLUP);
  pinMode(STOP_BTN2, INPUT_PULLUP);
  pinMode(STOP_BTN3, INPUT_PULLUP);
  
  Serial.begin(9600);
  Serial.println("🎰 スロットマシン開始!");
  
  // 初期表示
  reels[0] = 0; reels[1] = 0; reels[2] = 0; reels[3] = 0;
}

void loop() {
  handleButtons();
  updateGame();
  updateDisplay();
  delay(1);
}

void handleButtons() {
  static bool startPressed = false;
  static bool stop1Pressed = false;
  static bool stop2Pressed = false;
  static bool stop3Pressed = false;
  
  // スタートボタン
  if (!digitalRead(START_BTN) && !startPressed) {
    startPressed = true;
    if (gameState == IDLE || gameState == JACKPOT) {
      startGame();
    }
  } else if (digitalRead(START_BTN)) {
    startPressed = false;
  }
  
  // ストップボタン1
  if (!digitalRead(STOP_BTN1) && !stop1Pressed) {
    stop1Pressed = true;
    if (gameState == SPINNING || gameState == STOPPING1) {
      stopReel(1);
    }
  } else if (digitalRead(STOP_BTN1)) {
    stop1Pressed = false;
  }
  
  // ストップボタン2
  if (!digitalRead(STOP_BTN2) && !stop2Pressed) {
    stop2Pressed = true;
    if (gameState == SPINNING || gameState == STOPPING1 || gameState == STOPPING2) {
      stopReel(2);
    }
  } else if (digitalRead(STOP_BTN2)) {
    stop2Pressed = false;
  }
  
  // ストップボタン3
  if (!digitalRead(STOP_BTN3) && !stop3Pressed) {
    stop3Pressed = true;
    if (gameState == SPINNING || gameState == STOPPING1 || 
        gameState == STOPPING2 || gameState == STOPPING3) {
      stopReel(3);
    }
  } else if (digitalRead(STOP_BTN3)) {
    stop3Pressed = false;
  }
}

void startGame() {
  Serial.println("🎰 ゲーム開始!");
  gameState = SPINNING;
  
  // リール初期化
  for (int i = 0; i < 4; i++) {
    reelStopped[i] = false;
  }
  
  // LED消灯
  for (int i = 0; i < 3; i++) {
    digitalWrite(LED_PINS[i], LOW);
  }
}

void stopReel(int reelNum) {
  if (reelNum >= 1 && reelNum <= 3 && !reelStopped[reelNum]) {
    reelStopped[reelNum] = true;
    Serial.print("リール"); Serial.print(reelNum); Serial.println("停止!");
    
    // ゲーム状態更新
    if (reelNum == 1) gameState = STOPPING1;
    else if (reelNum == 2) gameState = STOPPING2;
    else if (reelNum == 3) gameState = STOPPING3;
    
    // 全リール停止チェック
    if (reelStopped[1] && reelStopped[2] && reelStopped[3]) {
      checkJackpot();
    }
  }
}

void updateGame() {
  if (millis() - lastUpdate < 100) return;  // 100ms間隔で更新
  lastUpdate = millis();
  
  if (gameState == SPINNING || gameState == STOPPING1 || 
      gameState == STOPPING2 || gameState == STOPPING3) {
    
    // 回転中のリール更新
    for (int i = 1; i <= 3; i++) {
      if (!reelStopped[i]) {
        reels[i] = random(0, 10);
      }
    }
  }
  
  // ジャックポット演出
  if (gameState == JACKPOT) {
    if (millis() - jackpotStart > 500) {  // 500ms間隔で点滅
      jackpotStart = millis();
      jackpotLedState = !jackpotLedState;
      
      // LED点滅
      for (int i = 0; i < 3; i++) {
        digitalWrite(LED_PINS[i], jackpotLedState ? HIGH : LOW);
      }
    }
  }
}

void checkJackpot() {
  Serial.print("結果: ");
  for (int i = 1; i <= 3; i++) {
    Serial.print(reels[i]);
  }
  Serial.println();
  
  // 777チェック
  if (reels[1] == 7 && reels[2] == 7 && reels[3] == 7) {
    Serial.println("🎉 ジャックポット!!! 🎉");
    gameState = JACKPOT;
    jackpotStart = millis();
    jackpotLedState = true;
    
    // 即座にLED点灯
    for (int i = 0; i < 3; i++) {
      digitalWrite(LED_PINS[i], HIGH);
    }
  } else {
    Serial.println("残念... もう一度挑戦!");
    gameState = IDLE;
  }
}

void updateDisplay() {
  static int currentDigit = 0;
  static unsigned long lastDisplayUpdate = 0;
  
  if (millis() - lastDisplayUpdate < 2) return;  // 2ms間隔で桁切り替え
  lastDisplayUpdate = millis();
  
  // 全桁消灯
  for (int i = 0; i < 4; i++) {
    digitalWrite(DIGIT_PINS[i], HIGH);
  }
  
  // ジャックポット時の点滅効果
  if (gameState == JACKPOT && !jackpotLedState) {
    return;  // 点滅のため表示しない
  }
  
  // 現在の桁を表示
  shiftOut(DATA_PIN, CLOCK_PIN, MSBFIRST, DIGIT_PATTERNS[reels[currentDigit]]);
  digitalWrite(LATCH_PIN, HIGH);
  digitalWrite(LATCH_PIN, LOW);
  
  digitalWrite(DIGIT_PINS[currentDigit], LOW);  // 現在の桁を点灯
  
  currentDigit = (currentDigit + 1) % 4;
}
$abcdeabcde151015202530354045505560fghijfghij
74HC595