Commit f9dcacf7 authored by Mahmoud Aglan's avatar Mahmoud Aglan

fix: multiplayer Ludo respects player count (2p = diagonal, same as single player)

- mountGame reads playerCount from params (queue passes it from room)
- Server accepts player_count in queue request, creates matching positions
- Queue response includes player_count for both players
- onMatchFound propagates playerCount to game scene
- 2-player live matches now create only 2 positions (not 4 with bots)
Co-Authored-By: 's avatarClaude Opus 4.6 <noreply@anthropic.com>
parent 95029f8f
...@@ -28,16 +28,20 @@ switch ($action) { ...@@ -28,16 +28,20 @@ switch ($action) {
function handleLudoQueue(string $userId, array $input): void { function handleLudoQueue(string $userId, array $input): void {
$sdb = supabaseService(); $sdb = supabaseService();
$requestedPlayers = intval($input['player_count'] ?? 4);
if ($requestedPlayers < 2) $requestedPlayers = 2;
if ($requestedPlayers > 4) $requestedPlayers = 4;
// Clean old waiting entries for this player // Clean old waiting entries for this player
$sdb->delete('ludo_queue', ['user_id' => 'eq.' . $userId]); $sdb->delete('ludo_queue', ['user_id' => 'eq.' . $userId]);
// Check for ALL waiting opponents (up to 3 — we need at least 1 to start) // Check for waiting opponents (need at least 1 to start)
$maxOpponents = $requestedPlayers - 1;
$searchUrl = SUPABASE_REST . '/ludo_queue' $searchUrl = SUPABASE_REST . '/ludo_queue'
. '?user_id=neq.' . $userId . '?user_id=neq.' . $userId
. '&match_id=is.null' . '&match_id=is.null'
. '&select=id,user_id' . '&select=id,user_id'
. '&limit=3'; . '&limit=' . $maxOpponents;
$ch = curl_init($searchUrl); $ch = curl_init($searchUrl);
curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
...@@ -52,28 +56,29 @@ function handleLudoQueue(string $userId, array $input): void { ...@@ -52,28 +56,29 @@ function handleLudoQueue(string $userId, array $input): void {
$opponents = json_decode($result, true); $opponents = json_decode($result, true);
if (!empty($opponents) && isset($opponents[0])) { if (!empty($opponents) && isset($opponents[0])) {
// Found opponents — build player list (up to 4 humans, fill rest with bots) // Found opponents — build player list, fill remaining with bots
$humanPlayers = [$opponents[0]['user_id'], $userId]; $humanPlayers = [$opponents[0]['user_id'], $userId];
if (isset($opponents[1])) $humanPlayers[] = $opponents[1]['user_id']; if (isset($opponents[1]) && $requestedPlayers >= 3) $humanPlayers[] = $opponents[1]['user_id'];
if (isset($opponents[2])) $humanPlayers[] = $opponents[2]['user_id']; if (isset($opponents[2]) && $requestedPlayers >= 4) $humanPlayers[] = $opponents[2]['user_id'];
$players = $humanPlayers; $players = $humanPlayers;
$botCount = 4 - count($players); $botCount = $requestedPlayers - count($players);
for ($i = 1; $i <= $botCount; $i++) { $players[] = 'bot_' . $i; } for ($i = 1; $i <= $botCount; $i++) { $players[] = 'bot_' . $i; }
// Build positions array matching player count
$positions = [];
for ($i = 0; $i < $requestedPlayers; $i++) {
$positions[] = ['pos' => [-1,-1,-1,-1]];
}
$matchData = [ $matchData = [
'room_code' => strtoupper(substr(bin2hex(random_bytes(3)), 0, 6)), 'room_code' => strtoupper(substr(bin2hex(random_bytes(3)), 0, 6)),
'status' => 'in_progress', 'status' => 'in_progress',
'player_count' => 4, 'player_count' => $requestedPlayers,
'players' => json_encode($players), 'players' => json_encode($players),
'current_turn' => 0, 'current_turn' => 0,
'dice_value' => null, 'dice_value' => null,
'positions' => json_encode([ 'positions' => json_encode($positions),
['pos' => [-1,-1,-1,-1]],
['pos' => [-1,-1,-1,-1]],
['pos' => [-1,-1,-1,-1]],
['pos' => [-1,-1,-1,-1]]
]),
'moves' => '[]', 'moves' => '[]',
'winners' => '[]', 'winners' => '[]',
'game_state' => json_encode(['turn_count' => 0]), 'game_state' => json_encode(['turn_count' => 0]),
...@@ -92,6 +97,7 @@ function handleLudoQueue(string $userId, array $input): void { ...@@ -92,6 +97,7 @@ function handleLudoQueue(string $userId, array $input): void {
jsonResponse([ jsonResponse([
'match_id' => $matchId, 'match_id' => $matchId,
'player_index' => 1, 'player_index' => 1,
'player_count' => $requestedPlayers,
'players' => $players 'players' => $players
]); ]);
} }
...@@ -116,17 +122,20 @@ function handleLudoStatus(string $userId): void { ...@@ -116,17 +122,20 @@ function handleLudoStatus(string $userId): void {
// Clean queue // Clean queue
$sdb->delete('ludo_queue', ['user_id' => 'eq.' . $userId]); $sdb->delete('ludo_queue', ['user_id' => 'eq.' . $userId]);
// Get match to find player index // Get match to find player index and count
$matches = $sdb->get('ludo_matches', ['id' => 'eq.' . $matchId, 'select' => 'players', 'limit' => 1]); $matches = $sdb->get('ludo_matches', ['id' => 'eq.' . $matchId, 'select' => 'players,player_count', 'limit' => 1]);
$players = []; $players = [];
$playerCount = 4;
if (!empty($matches) && !isset($matches['error'])) { if (!empty($matches) && !isset($matches['error'])) {
$players = json_decode($matches[0]['players'] ?? '[]', true); $players = json_decode($matches[0]['players'] ?? '[]', true);
$playerCount = intval($matches[0]['player_count'] ?? 4);
} }
$playerIndex = array_search($userId, $players); $playerIndex = array_search($userId, $players);
jsonResponse([ jsonResponse([
'match_id' => $matchId, 'match_id' => $matchId,
'player_index' => $playerIndex !== false ? $playerIndex : 0, 'player_index' => $playerIndex !== false ? $playerIndex : 0,
'player_count' => $playerCount,
'players' => $players 'players' => $players
]); ]);
} }
......
...@@ -64,7 +64,8 @@ function renderPanel(p) { ...@@ -64,7 +64,8 @@ function renderPanel(p) {
} }
export function mountGame(el, params) { export function mountGame(el, params) {
const { mode = 'bot', numPlayers = 4, seats, humanCount = 1, difficulty = 'medium' } = params; const { mode = 'bot', seats, humanCount = 1, difficulty = 'medium' } = params;
const numPlayers = params.numPlayers || params.playerCount || 4;
scene.enterGameMode(); scene.enterGameMode();
myPlayerIndex = params.playerIndex || 0; myPlayerIndex = params.playerIndex || 0;
......
...@@ -52,7 +52,8 @@ async function joinQueue(params) { ...@@ -52,7 +52,8 @@ async function joinQueue(params) {
game_key: params.game, game_key: params.game,
time_control: params.timeControl || 'standard', time_control: params.timeControl || 'standard',
variant: params.variant, variant: params.variant,
match_length: params.matchLength match_length: params.matchLength,
player_count: params.playerCount || 4
}); });
if (data.match_id) { if (data.match_id) {
...@@ -87,6 +88,7 @@ function onMatchFound(data, params) { ...@@ -87,6 +88,7 @@ function onMatchFound(data, params) {
mode: 'live', mode: 'live',
color: data.color, color: data.color,
playerIndex: data.player_index, playerIndex: data.player_index,
playerCount: data.player_count || params.playerCount || 4,
players: data.players players: data.players
}); });
} }
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment