prepare("SELECT * FROM sp_games WHERE user_id=? AND game='hangman' AND status='active' ORDER BY id DESC LIMIT 1"); $s->execute([$uid]); return $s->fetch() ?: null; } function h_new(int $uid): array { $word = H_WORDS[array_rand(H_WORDS)]; $st = json_encode(['word' => $word, 'used' => [], 'lives' => H_MAX_LIVES]); $now = time(); db()->prepare("INSERT INTO sp_games (game,user_id,state,created_at,updated_at) VALUES ('hangman',?,?,?,?)")->execute([$uid, $st, $now, $now]); return h_load($uid); } $msg = ''; $done = false; $g = h_load((int)$me['id']); if ($_SERVER['REQUEST_METHOD'] === 'POST') { require_csrf(); $act = $_POST['act'] ?? ''; if ($act === 'new') { if ($g) db()->prepare("UPDATE sp_games SET status='abandoned' WHERE id=?")->execute([$g['id']]); $g = h_new((int)$me['id']); $msg = 'New game! I have chosen a word. Guess letters one at a time.'; } else { if (!$g) $g = h_new((int)$me['id']); $st = json_decode($g['state'], true); $letter = strtolower((string)($_POST['letter'] ?? '')); if (strlen($letter) !== 1 || !ctype_alpha($letter)) { $msg = 'Please enter a single letter a-z.'; } elseif (in_array($letter, $st['used'], true)) { $msg = 'You have already used that letter.'; } else { $st['used'][] = $letter; if (in_array($letter, str_split($st['word']), true)) { $msg = 'Good! ' . $letter . ' is in the word.'; } else { $st['lives']--; $msg = $letter . ' is not in the word.'; } // Check win/loss $word_letters = array_diff(str_split($st['word']), $st['used']); if (empty($word_letters)) { $score = max(1, 50 - (H_MAX_LIVES - $st['lives']) * 5); db()->prepare("UPDATE sp_games SET status='won', state=?, updated_at=? WHERE id=?") ->execute([json_encode($st), time(), $g['id']]); db()->prepare("INSERT INTO scores (game,user_id,score,detail,created_at) VALUES ('hangman',?,?,?,?)") ->execute([$me['id'], $score, $st['lives'] . ' lives left', time()]); $msg = "Yay! You guessed the word {$st['word']}! Score: $score"; $done = true; $g = null; } elseif ($st['lives'] <= 0) { db()->prepare("UPDATE sp_games SET status='lost', state=?, updated_at=? WHERE id=?") ->execute([json_encode($st), time(), $g['id']]); $msg = "You died! The word was {$st['word']}."; $done = true; $g = null; } else { db()->prepare("UPDATE sp_games SET state=?, updated_at=? WHERE id=?") ->execute([json_encode($st), time(), $g['id']]); $g['state'] = json_encode($st); } } } } page_start('Hangman', ['back' => '/games.php']); if ($msg) p_para($msg); if ($g) { $st = json_decode($g['state'], true); $display = ''; foreach (str_split($st['word']) as $ch) { $display .= (in_array($ch, $st['used'], true) ? $ch : '-') . ' '; } p_para('Word: ' . trim($display)); p_para('Lives left: ' . $st['lives']); if ($st['used']) p_para('Used: ' . implode(', ', $st['used'])); p_form('/games/hangman.php', [ ['name' => 'letter', 'label' => 'Guess a letter', 'maxlength' => 1, 'format' => '*A'], ], 'Guess'); } else { if (!$done) p_para('Guess the word one letter at a time. You have 6 lives.'); } p_form('/games/hangman.php', [ ['name' => 'act', 'type' => 'hidden', 'value' => 'new'], ], $g ? 'Restart' : 'New game'); p_links([['/games/scores.php', 'High scores', ['g' => 'hangman']], ['/games.php', 'Games']]); page_end();