83 lines
3.4 KiB
PHP
83 lines
3.4 KiB
PHP
<?php
|
|
// Shared helpers for turn-based multiplayer games stored in `matches`.
|
|
require_once __DIR__ . '/../lib/bootstrap.php';
|
|
|
|
function mp_create(string $game, int $uid, string $state): int {
|
|
$now = time();
|
|
db()->prepare("INSERT INTO matches (game,p1,turn,state,status,created_at,updated_at)
|
|
VALUES (?,?,1,?, 'open',?,?)")
|
|
->execute([$game, $uid, $state, $now, $now]);
|
|
return (int)db()->lastInsertId();
|
|
}
|
|
|
|
function mp_join(string $game, int $mid, int $uid): bool {
|
|
$s = db()->prepare("SELECT * FROM matches WHERE id=? AND game=?");
|
|
$s->execute([$mid, $game]);
|
|
$m = $s->fetch();
|
|
if (!$m || $m['status'] !== 'open' || (int)$m['p1'] === $uid) return false;
|
|
db()->prepare("UPDATE matches SET p2=?, status='playing', updated_at=? WHERE id=?")
|
|
->execute([$uid, time(), $mid]);
|
|
return true;
|
|
}
|
|
|
|
function mp_get(string $game, int $mid): ?array {
|
|
$s = db()->prepare("SELECT m.*, a.username AS n1, b.username AS n2
|
|
FROM matches m
|
|
LEFT JOIN users a ON a.id=m.p1
|
|
LEFT JOIN users b ON b.id=m.p2
|
|
WHERE m.id=? AND m.game=?");
|
|
$s->execute([$mid, $game]);
|
|
return $s->fetch() ?: null;
|
|
}
|
|
|
|
function mp_save(int $mid, string $state, int $turn, string $status = 'playing', ?int $winner = null): void {
|
|
db()->prepare("UPDATE matches SET state=?, turn=?, status=?, winner=?, updated_at=? WHERE id=?")
|
|
->execute([$state, $turn, $status, $winner, time(), $mid]);
|
|
}
|
|
|
|
// Which seat is this user in? 1, 2, or 0 for spectator.
|
|
function mp_seat(array $m, int $uid): int {
|
|
if ((int)$m['p1'] === $uid) return 1;
|
|
if ((int)$m['p2'] === $uid) return 2;
|
|
return 0;
|
|
}
|
|
|
|
// Render the lobby: open games to join, your active games, and a create button.
|
|
function mp_lobby(string $game, string $self, int $uid, string $newState): void {
|
|
$d = db();
|
|
$s = $d->prepare("SELECT m.*, a.username AS n1 FROM matches m
|
|
LEFT JOIN users a ON a.id=m.p1
|
|
WHERE m.game=? AND m.status='open' AND m.p1<>?
|
|
ORDER BY m.id DESC LIMIT 10");
|
|
$s->execute([$game, $uid]);
|
|
$open = $s->fetchAll();
|
|
|
|
$s = $d->prepare("SELECT m.*, a.username AS n1, b.username AS n2 FROM matches m
|
|
LEFT JOIN users a ON a.id=m.p1
|
|
LEFT JOIN users b ON b.id=m.p2
|
|
WHERE m.game=? AND (m.p1=? OR m.p2=?) AND m.status IN ('open','playing')
|
|
ORDER BY m.updated_at DESC LIMIT 10");
|
|
$s->execute([$game, $uid, $uid]);
|
|
$mine = $s->fetchAll();
|
|
|
|
if ($mine) {
|
|
p_para('Your games:');
|
|
foreach ($mine as $m) {
|
|
$opp = ((int)$m['p1'] === $uid) ? ($m['n2'] ?? 'waiting...') : ($m['n1'] ?? '?');
|
|
$yourTurn = ($m['status'] === 'playing' && mp_seat($m, $uid) === (int)$m['turn']);
|
|
p_link($self, '#' . $m['id'] . ' vs ' . $opp . ($yourTurn ? ' - YOUR TURN' : ''),
|
|
['g' => $m['id']]);
|
|
}
|
|
}
|
|
if ($open) {
|
|
p_para('Open games to join:');
|
|
foreach ($open as $m) {
|
|
p_link($self, 'Join #' . $m['id'] . ' by ' . ($m['n1'] ?? '?'), ['g' => $m['id'], 'join' => 1]);
|
|
}
|
|
}
|
|
if (!$mine && !$open) p_para('No games yet - create one and wait for an opponent.');
|
|
p_form($self, [
|
|
['name' => 'act', 'type' => 'hidden', 'value' => 'create'],
|
|
], 'Create new game');
|
|
}
|