Connexion
FR
games/sorcery / src / Data / RoomText.php · commit 613f5fb
<?phpnamespace App\Data;/** The parser of the room text files (a port of common/roomtext.cpp, parse only). */final class RoomText{    /**     * @param string[] $error error message out-param (single element)     */    public static function parse(string $text, ?array &$error = null): ?RoomDef    {        $out = new RoomDef();        $nmap = 0;        $nrec = 0;        $haveRoom = false;        $section = '';        $lineNo = 0;        foreach (preg_split('/\r?\n/', $text) as $line) {            $lineNo++;            $cut = strpos($line, ';');            if ($cut !== false) {                $line = substr($line, 0, $cut);            }            $toks = preg_split('/\s+/', trim($line), -1, PREG_SPLIT_NO_EMPTY);            if ($toks === false || $toks === []) {                continue;            }            if (count($toks) === 2 && $toks[0] === 'room') {                $out->number = (int)$toks[1];                $haveRoom = true;                continue;            }            if (count($toks) === 1 && ($toks[0] === 'map' || $toks[0] === 'record')) {                $section = $toks[0];                continue;            }            if (count($toks) === 1 && $toks[0] === 'end') {                $section = '';                continue;            }            if ($section === '') {                $error = ["line $lineNo: unexpected text outside map/record"];                return null;            }            foreach ($toks as $t) {                if ($section === 'record' && substr($t, -1) === ':') {                    continue;                }                if ($section === 'map') {                    if ($t === '..' || $t === '--') {                        $v = 0;                    } elseif (strlen($t) === 2 && ctype_xdigit($t)) {                        $v = (int)hexdec($t);                    } else {                        $error = ["line $lineNo: bad tile '$t' (use two hex digits or '..')"];                        return null;                    }                    if ($nmap >= 720) {                        $error = ['map has more than 720 tiles'];                        return null;                    }                    if ($v === 0xFF) {                        $error = ['tile id FF is reserved (end marker of the original format)'];                        return null;                    }                    $out->map[$nmap++] = $v;                } else {                    if (strlen($t) !== 2 || !ctype_xdigit($t)) {                        $error = ["line $lineNo: bad byte '$t'"];                        return null;                    }                    if ($nrec >= 64) {                        $error = ['record has more than 64 bytes'];                        return null;                    }                    $out->rec[$nrec++] = (int)hexdec($t);                }            }        }        if (!$haveRoom) {            $error = ["missing 'room N' line"];            return null;        }        if ($nmap !== 720) {            $error = ["map must have 40 x 18 = 720 tiles, found $nmap"];            return null;        }        if ($nrec !== 64) {            $error = ["record must have 64 bytes, found $nrec"];            return null;        }        return $out;    }}