First git commit
This commit is contained in:
116
public_html/games/ttt.php
Normal file
116
public_html/games/ttt.php
Normal file
@ -0,0 +1,116 @@
|
||||
<?php
|
||||
// Multiplayer noughts & crosses.
|
||||
require_once __DIR__ . '/mplib.php';
|
||||
$me = require_login();
|
||||
$uid = (int)$me['id'];
|
||||
$SELF = '/games/ttt.php';
|
||||
|
||||
function ttt_win(array $b): ?string {
|
||||
$lines = [[0,1,2],[3,4,5],[6,7,8],[0,3,6],[1,4,7],[2,5,8],[0,4,8],[2,4,6]];
|
||||
foreach ($lines as $l) {
|
||||
if ($b[$l[0]] !== '' && $b[$l[0]] === $b[$l[1]] && $b[$l[1]] === $b[$l[2]]) return $b[$l[0]];
|
||||
}
|
||||
return null;
|
||||
}
|
||||
|
||||
$msg = '';
|
||||
$mid = (int)($_GET['g'] ?? 0);
|
||||
|
||||
if ($_SERVER['REQUEST_METHOD'] === 'POST') {
|
||||
require_csrf();
|
||||
$act = $_POST['act'] ?? '';
|
||||
if ($act === 'create') {
|
||||
$mid = mp_create('ttt', $uid, json_encode(['b' => array_fill(0, 9, '')]));
|
||||
redirect($SELF, ['g' => $mid]);
|
||||
}
|
||||
if ($act === 'move') {
|
||||
$mid = (int)($_POST['mid'] ?? 0);
|
||||
$m = mp_get('ttt', $mid);
|
||||
$seat = $m ? mp_seat($m, $uid) : 0;
|
||||
if (!$m || $m['status'] !== 'playing') $msg = 'Game is not in play.';
|
||||
elseif ($seat === 0) $msg = 'You are not in this game.';
|
||||
elseif ($seat !== (int)$m['turn']) $msg = 'Not your turn.';
|
||||
else {
|
||||
$st = json_decode($m['state'], true);
|
||||
$cell = (int)($_POST['cell'] ?? 0) - 1; // players type 1-9
|
||||
if ($cell < 0 || $cell > 8 || $st['b'][$cell] !== '') {
|
||||
$msg = 'That square is not free (pick 1-9).';
|
||||
} else {
|
||||
$mark = $seat === 1 ? 'X' : 'O';
|
||||
$st['b'][$cell] = $mark;
|
||||
$w = ttt_win($st['b']);
|
||||
$full = !in_array('', $st['b'], true);
|
||||
if ($w !== null) {
|
||||
mp_save($mid, json_encode($st), $seat, 'done', $uid);
|
||||
db()->prepare("INSERT INTO scores (game,user_id,score,detail,created_at)
|
||||
VALUES ('ttt',?,?,?,?)")->execute([$uid, 50, 'win', time()]);
|
||||
$msg = 'You win!';
|
||||
} elseif ($full) {
|
||||
mp_save($mid, json_encode($st), $seat, 'done', null);
|
||||
$msg = 'Draw!';
|
||||
} else {
|
||||
mp_save($mid, json_encode($st), $seat === 1 ? 2 : 1);
|
||||
$msg = 'Move played. Waiting for your opponent.';
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if ($mid && !empty($_GET['join'])) {
|
||||
if (mp_join('ttt', $mid, $uid)) $msg = 'You joined the game. Player 2 is O.';
|
||||
else $msg = 'Could not join that game.';
|
||||
}
|
||||
|
||||
page_start('Noughts & Crosses', ['back' => '/games.php']);
|
||||
if ($msg) p_para($msg);
|
||||
|
||||
if (!$mid) {
|
||||
mp_lobby('ttt', $SELF, $uid, json_encode(['b' => array_fill(0, 9, '')]));
|
||||
p_links([['/games.php', 'Games']]);
|
||||
page_end();
|
||||
exit;
|
||||
}
|
||||
|
||||
$m = mp_get('ttt', $mid);
|
||||
if (!$m) bail('Game', 'No such game.', $SELF);
|
||||
$st = json_decode($m['state'], true);
|
||||
$b = $st['b'];
|
||||
$seat = mp_seat($m, $uid);
|
||||
|
||||
p_para('#' . $m['id'] . ': X=' . ($m['n1'] ?? '?') . ' vs O=' . ($m['n2'] ?? 'waiting'));
|
||||
|
||||
// board: 3 rows, free cells show their number so WAP users know what to type
|
||||
for ($r = 0; $r < 3; $r++) {
|
||||
$cells = [];
|
||||
for ($c = 0; $c < 3; $c++) {
|
||||
$i = $r * 3 + $c;
|
||||
$cells[] = $b[$i] === '' ? (string)($i + 1) : $b[$i];
|
||||
}
|
||||
p_para(implode(' | ', $cells));
|
||||
}
|
||||
p_rule();
|
||||
|
||||
if ($m['status'] === 'open') {
|
||||
p_para('Waiting for an opponent to join. Tell a friend to open Games > Noughts & Crosses.');
|
||||
} elseif ($m['status'] === 'done') {
|
||||
if ($m['winner'] === null) p_para('Result: draw.');
|
||||
else {
|
||||
$wn = ((int)$m['winner'] === (int)$m['p1']) ? $m['n1'] : $m['n2'];
|
||||
p_para('Winner: ' . $wn);
|
||||
}
|
||||
} elseif ($seat === 0) {
|
||||
p_para('You are watching. Turn: player ' . $m['turn']);
|
||||
} elseif ($seat === (int)$m['turn']) {
|
||||
p_para('Your turn (' . ($seat === 1 ? 'X' : 'O') . '). Enter a free square number.');
|
||||
p_form($SELF . '?g=' . $mid, [
|
||||
['name' => 'act', 'type' => 'hidden', 'value' => 'move'],
|
||||
['name' => 'mid', 'type' => 'hidden', 'value' => (string)$mid],
|
||||
['name' => 'cell', 'label' => 'Square (1-9)', 'maxlength' => 1, 'format' => 'N'],
|
||||
], 'Play');
|
||||
} else {
|
||||
p_para('Opponent to move. Check back shortly.');
|
||||
}
|
||||
|
||||
p_links([[$SELF, 'Refresh', ['g' => $mid]], [$SELF, 'Lobby'], ['/games.php', 'Games']]);
|
||||
page_end();
|
||||
Reference in New Issue
Block a user