'use strict';

/* ────────────────────────────────────────────────────────────────
   Phase 6 Sprint 6.3 — RPG & Adventure Templates
   
   Top-down RPG, Visual Novel, Point & Click, Roguelike, Dungeon Crawler
──────────────────────────────────────────────────────────────── */
const DEFAULT_RPG_CONFIG = {
    moveSpeed: 3,
    tileSize: 16,
    gridMovement: true,
    maxPartySize: 4,
    baseStats: { hp: 100, mp: 50, attack: 10, defense: 8, magic: 5, speed: 5, luck: 3 },
    xpCurve: 'quadratic',
    xpBase: 100,
    xpScale: 1.5,
    maxLevel: 99,
    battleSystem: 'turn-based',
    encounterRate: 0.05,
    inventorySlots: 40,
};
function xpForLevel(level, config) {
    switch (config.xpCurve) {
        case 'linear': return Math.floor(config.xpBase * level);
        case 'quadratic': return Math.floor(config.xpBase * Math.pow(level, config.xpScale));
        case 'cubic': return Math.floor(config.xpBase * Math.pow(level, 3) * 0.01);
    }
}
function createInventory(capacity) {
    return { slots: new Array(capacity).fill(null), gold: 0 };
}
function addItem(inv, itemId, count, itemDefs) {
    const def = itemDefs.get(itemId);
    if (!def)
        return false;
    if (def.stackable) {
        // Try to stack
        for (const slot of inv.slots) {
            if (slot && slot.itemId === itemId && slot.count < def.maxStack) {
                const toAdd = Math.min(count, def.maxStack - slot.count);
                slot.count += toAdd;
                count -= toAdd;
                if (count <= 0)
                    return true;
            }
        }
    }
    // Find empty slot
    while (count > 0) {
        const emptyIdx = inv.slots.indexOf(null);
        if (emptyIdx < 0)
            return false; // full
        const toAdd = def.stackable ? Math.min(count, def.maxStack) : 1;
        inv.slots[emptyIdx] = { itemId, count: toAdd };
        count -= toAdd;
    }
    return true;
}
const DEFAULT_VISUAL_NOVEL_CONFIG = {
    textSpeed: 30,
    autoAdvanceDelay: 2,
    skipSpeed: 10,
    historyLength: 100,
    saveSlots: 20,
    maxCharactersOnScreen: 4,
    transitionDuration: 0.5,
};
function parseVNLabels(commands) {
    const labels = {};
    for (let i = 0; i < commands.length; i++) {
        if (commands[i].label) {
            labels[commands[i].label] = i;
        }
    }
    return labels;
}
function createVNState(scriptId) {
    return {
        scriptId, commandIndex: 0,
        variables: {}, history: [],
        visibleCharacters: [],
        currentBackground: '',
        textProgress: 0,
        waitingForChoice: false,
    };
}
const DEFAULT_POINT_AND_CLICK_CONFIG = {
    walkSpeed: 3,
    doubleClickRun: true,
    runMultiplier: 2,
    interactionDistance: 1.5,
    inventoryPosition: 'bottom',
    cursorTypes: ['look', 'use', 'talk', 'pickup'],
    verbCoin: true,
    hotspotHighlight: true,
};
const DEFAULT_ROGUELIKE_CONFIG = {
    mapWidth: 80,
    mapHeight: 50,
    roomMinSize: 5,
    roomMaxSize: 12,
    maxRooms: 15,
    fovRadius: 8,
    turnBased: true,
    permadeath: true,
    metaProgression: false,
    floorCount: 10,
    itemDropRate: 0.15,
    eliteChance: 0.1,
    bossEveryNFloors: 5,
};
/** BSP dungeon generator. */
function generateDungeon(config) {
    const tiles = new Array(config.mapWidth * config.mapHeight).fill('wall');
    const rooms = [];
    for (let i = 0; i < config.maxRooms; i++) {
        const w = config.roomMinSize + Math.floor(Math.random() * (config.roomMaxSize - config.roomMinSize));
        const h = config.roomMinSize + Math.floor(Math.random() * (config.roomMaxSize - config.roomMinSize));
        const x = 1 + Math.floor(Math.random() * (config.mapWidth - w - 2));
        const y = 1 + Math.floor(Math.random() * (config.mapHeight - h - 2));
        // Check overlap
        let overlaps = false;
        for (const room of rooms) {
            if (x <= room.x + room.width + 1 && x + w + 1 >= room.x &&
                y <= room.y + room.height + 1 && y + h + 1 >= room.y) {
                overlaps = true;
                break;
            }
        }
        if (overlaps)
            continue;
        // Carve room
        for (let ry = y; ry < y + h; ry++) {
            for (let rx = x; rx < x + w; rx++) {
                tiles[ry * config.mapWidth + rx] = 'floor';
            }
        }
        // Connect to previous room
        if (rooms.length > 0) {
            const prev = rooms[rooms.length - 1];
            const cx1 = Math.floor(prev.x + prev.width / 2);
            const cy1 = Math.floor(prev.y + prev.height / 2);
            const cx2 = Math.floor(x + w / 2);
            const cy2 = Math.floor(y + h / 2);
            // Horizontal corridor
            const startX = Math.min(cx1, cx2);
            const endX = Math.max(cx1, cx2);
            for (let rx = startX; rx <= endX; rx++) {
                tiles[cy1 * config.mapWidth + rx] = 'floor';
            }
            // Vertical corridor
            const startY = Math.min(cy1, cy2);
            const endY = Math.max(cy1, cy2);
            for (let ry = startY; ry <= endY; ry++) {
                tiles[ry * config.mapWidth + cx2] = 'floor';
            }
        }
        rooms.push({ x, y, width: w, height: h, connected: rooms.length > 0 });
    }
    if (rooms.length > 0)
        rooms[0].connected = true;
    return { tiles, rooms };
}
/** Simple FOV (field of view) via raycasting. */
function computeFOV(tiles, mapWidth, cx, cy, radius) {
    const visible = new Set();
    const rays = Math.ceil(radius * 8);
    for (let i = 0; i < rays; i++) {
        const angle = (i / rays) * Math.PI * 2;
        const dx = Math.cos(angle);
        const dy = Math.sin(angle);
        for (let d = 0; d <= radius; d++) {
            const x = Math.round(cx + dx * d);
            const y = Math.round(cy + dy * d);
            const idx = y * mapWidth + x;
            if (x < 0 || y < 0 || x >= mapWidth)
                break;
            visible.add(idx);
            if (tiles[idx] === 'wall')
                break;
        }
    }
    return visible;
}
const DEFAULT_DUNGEON_CRAWLER_CONFIG = {
    perspective: 'first-person',
    gridSize: 1,
    partySize: 4,
    automap: true,
    trapChance: 0.1,
    secretWallChance: 0.05,
    encounterRate: 0.2,
    lootQualityScale: 1.2,
    puzzleFrequency: 0.15,
};

exports.DEFAULT_DUNGEON_CRAWLER_CONFIG = DEFAULT_DUNGEON_CRAWLER_CONFIG;
exports.DEFAULT_POINT_AND_CLICK_CONFIG = DEFAULT_POINT_AND_CLICK_CONFIG;
exports.DEFAULT_ROGUELIKE_CONFIG = DEFAULT_ROGUELIKE_CONFIG;
exports.DEFAULT_RPG_CONFIG = DEFAULT_RPG_CONFIG;
exports.DEFAULT_VISUAL_NOVEL_CONFIG = DEFAULT_VISUAL_NOVEL_CONFIG;
exports.addItem = addItem;
exports.computeFOV = computeFOV;
exports.createInventory = createInventory;
exports.createVNState = createVNState;
exports.generateDungeon = generateDungeon;
exports.parseVNLabels = parseVNLabels;
exports.xpForLevel = xpForLevel;
//# sourceMappingURL=RPGTemplates.js.map
