<?phpnamespace App\Data;use App\Game\Values;/** Column/row of each room in the map panel (a port of modern/src/maplayout.cpp). */final class MapLayout{ /** @var array<int, array{col: int, row: int}> per room; col -1 = not reachable */ public array $pos = []; public int $cols = 0; public int $rows = 0; public static function build(Level $level): self { $m = new self(); $n = count($level->rooms); $m->pos = array_fill(0, $n, ['col' => -1, 'row' => -1]); $unseen = 1 << 20; $col = array_fill(0, $n, $unseen); $order = []; $start = $level->original ? 0 : 0; if ($start < 0 || $start >= $n) { $start = 0; } $order[] = $start; $col[$start] = 0; for ($q = 0; $q < count($order); $q++) { $r = $order[$q]; $rec = $level->rooms[$r]->rec; for ($d = 0; $d < 4; $d++) { $dest = $rec[0x16 + 4 * $d + 2]; if ($rec[0x16 + 4 * $d] === Values::NONE || $dest >= $n || $col[$dest] !== $unseen) { continue; } $col[$dest] = $col[$r] + ($d < 2 ? -1 : 1); $order[] = $dest; } foreach ($level->extras as $e) { if ($e->type === Extra::TELEPORTER && $e->room === $r && $e->toRoom < $n && $col[$e->toRoom] === $unseen) { $col[$e->toRoom] = $col[$r]; $order[] = $e->toRoom; } } } $minc = 0; $maxc = 0; foreach ($order as $r) { $minc = min($minc, $col[$r]); $maxc = max($maxc, $col[$r]); } $fill = array_fill(0, $maxc - $minc + 1, 0); foreach ($order as $r) { $c = $col[$r] - $minc; $m->pos[$r] = ['col' => $c, 'row' => $fill[$c]++]; $m->rows = max($m->rows, $fill[$c]); } $m->cols = $maxc - $minc + 1; return $m; }}