Download Game! Currently 79 players and visitors. Last logged in:GrizztSahadevCaitlineMarayana

Blitzer's Blog >> 72494

Back to blogs index
Posted: 15 Sep 2026 20:55 [ permalink ]
import fs from 'fs';

/ The logical opposing pairs for bidirectional routing
const COMPASS_PAIRS = [
    { fwd: 'NORTH', rev: 'SOUTH' },
    { fwd: 'EAST',  rev: 'WEST' },
    { fwd: 'UP',    rev: 'DOWN' },
    { fwd: 'IN',    rev: 'OUT' },
    // Backups if the room gets highly connected
    { fwd: 'NORTHEAST', rev: 'SOUTHWEST' },
    { fwd: 'NORTHWEST', rev: 'SOUTHEAST' }
];

function parseCartographer(input) {
    const rooms = {};
    const blocks = input.split('---').map(b => b.trim()).filter(Boolean);

    for (const block of blocks) {
        const lines = block.split('
');
        let id = '', desc = '', exits = [];
        
        for (const line of lines) {
            if (line.startsWith('ROOM:')) id = line.replace('ROOM:',
'').trim();
            if (line.startsWith('DESC:')) desc = line.replace('DESC:',
'').trim();
            if (line.startsWith('EXITS:')) {
                const exitsRaw = line.replace('EXITS:', '');
                exits = exitsRaw.split(',').map(e => e.trim()).filter(Boolean);
            }
        }
        
        if (id) {
            rooms[id] = { id, desc, exits, routes: {} };
        }
    }
    return rooms;
}

function assignCompassDirections(rooms) {
    // Keep track of assigned connections to enforce bidirectionality
    const assignedLinks = new Set();

    for (const [id, room] of Object.entries(rooms)) {
        for (const targetId of room.exits) {
            // Skip if the target room doesn't actually exist
            if (!rooms[targetId]) continue; 
            
            // Skip if we already mapped this connection from the other side
            const linkKey1 = `${id}->${targetId}`;
            const linkKey2 = `${targetId}->${id}`;
            if (assignedLinks.has(linkKey1)) continue;

            // Find an available compass pair
            const targetRoom = rooms[targetId];
            const usedInRoomA = Object.keys(room.routes);
            const usedInRoomB = Object.keys(targetRoom.routes);

            let chosenPair = COMPASS_PAIRS.find(pair => 
                !usedInRoomA.includes(pair.fwd) && !usedInRoomB.includes(pair.r
ev)
            );

            // Fallback just in case a room has crazy connectivity
            if (!chosenPair) chosenPair = { fwd: 'PATH', rev: 'PATH' }; 

            // Assign the forward route
            room.routes[chosenPair.fwd] = targetId;
            assignedLinks.add(linkKey1);

            // Enforce the reverse route automatically (no traps!)
            targetRoom.routes[chosenPair.rev] = id;
            assignedLinks.add(linkKey2);
        }
    }
}

function buildFSO(rooms) {
    let fsoCode = `LBL start_game
GLOBAL "HELP" handle_help
`;
    
    // Set the first room dynamically as the spawn point
    const firstRoomId = Object.keys(rooms)[0];
    if (firstRoomId) fsoCode += `JMP room_${firstRoomId.toLowerCase()}

`;

    for (const [id, room] of Object.entries(rooms)) {
        const lblName = `room_${id.toLowerCase()}`;
        fsoCode += `LBL ${lblName}
`;
        fsoCode += `ENV_FLUSH
`;
        
        // Escape quotes to prevent compilation crashes
        const safeDesc = room.desc.replace(/"/g, '\\"');
        fsoCode += `DESC "${safeDesc}"
`;

        for (const [direction, targetId] of Object.entries(room.routes)) {
            fsoCode += `EXIT "${direction}" room_${targetId.toLowerCase()}
`;
        }
        
        fsoCode += `AWAIT

`;
    }

    // Add the global help handler
    fsoCode += `LBL handle_help
`;
    fsoCode += `OUT "Type directions (like NORTH or EAST) to move around."
`;
    fsoCode += `AWAIT
`;

    return `\`\`\`fso-state
VAR INVENTORY ARR '[]'
\`\`\`

\`\`\`fso-code
${fsoCode.trim()}
\`\`\``;
}

/ CLI Execution
const inputFile = process.argv[2] || 'map.txt';
if (!fs.existsSync(inputFile)) {
    console.error(`[FAULT] Could not find ${inputFile}`);
    process.exit(1);
}

const rawText = fs.readFileSync(inputFile, 'utf-8');
const rooms = parseCartographer(rawText);
assignCompassDirections(rooms);
const outputMd = buildFSO(rooms);

fs.writeFileSync('game_idea.md', outputMd);
console.log(`[SYS] Topology successfully routed! Compiled to game_idea.md`);