All files utils.planning.js

82.66% Statements 62/75
73.52% Branches 25/34
69.23% Functions 9/13
81.42% Lines 57/70

Press n or j to go to the next uncovered block, b, p or k for the previous block.

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 66 67 68 69 70 71 72 73 74 75 76 77 78 79 80 81 82 83 84 85 86 87 88 89 90 91 92 93 94 95 96 97 98 99 100 101 102 103 104 105 106 107 108 109 110 111 112 113 114 115 116 117 118 119 120 121 122 123 124 125 126 127 128 129 130 131 132 133 134 135 136 137 138 139 140 141 142 143 144 145 146 147 148 149 150 151 152 153 154 155 156 157 158 159 160      1x     3x 3x     3x 134x 5988x 5988x         3x         5990x   5990x 37690x 242654x 242654x   242654x     242654x 1x         5989x         3x 3x   3x 2x     1x 1x 1x   1x 2116x     2116x 2116x 2116x   2116x 1x 1x       1x         1x 1x   1x 1x       7x 7x       49x 12x 12x           1x         1x 1x                           1x 1x 1x   1x 1x                                                   1x 1x   1x 1x   1x 1x     1x      
// Room Planning Utilities
// Basic implementations inspired by Distance Transform and Floodfill concepts
 
module.exports = {
    // Find open spaces in a room (simplified Distance Transform concept)
    findOpenSpaces: function (room, minSize = 3) {
        const terrain = room.getTerrain();
        const openSpaces = [];
 
        // Scan room for open areas
        for (let x = minSize; x < 50 - minSize; x++) {
            for (let y = minSize; y < 50 - minSize; y++) {
                Eif (this.isOpenArea(room, x, y, minSize, terrain)) {
                    openSpaces.push({ x, y, size: minSize });
                }
            }
        }
 
        return openSpaces;
    },
 
    // Check if an area is open (no walls/terrain)
    isOpenArea: function (room, centerX, centerY, size, terrain) {
        terrain = terrain || room.getTerrain();
 
        for (let dx = -size; dx <= size; dx++) {
            for (let dy = -size; dy <= size; dy++) {
                const x = centerX + dx;
                const y = centerY + dy;
 
                Iif (x < 0 || x >= 50 || y < 0 || y >= 50) {
                    return false;
                }
                if (terrain.get(x, y) === TERRAIN_MASK_WALL) {
                    return false;
                }
            }
        }
 
        return true;
    },
 
    // Find best position for spawn near controller and sources
    findBestSpawnPosition: function (room) {
        const controller = room.controller;
        const sources = room.find(FIND_SOURCES);
 
        if (!controller || sources.length === 0) {
            return null;
        }
 
        const openSpaces = this.findOpenSpaces(room, 2);
        let bestPos = null;
        let bestScore = Infinity;
 
        openSpaces.forEach((space) => {
            const pos = new RoomPosition(space.x, space.y, room.name);
 
            // Calculate distance score (lower is better)
            const controllerDist = pos.getRangeTo(controller);
            const sourceDist = Math.min(...sources.map((s) => pos.getRangeTo(s)));
            const score = controllerDist * 2 + sourceDist;
 
            if (score < bestScore) {
                bestScore = score;
                bestPos = pos;
            }
        });
 
        return bestPos;
    },
 
    // Get tiles at a certain distance from a position (Floodfill concept)
    getTilesAtDistance: function (room, centerPos, distance) {
        const tiles = [];
        const terrain = room.getTerrain();
 
        for (
            let x = Math.max(0, centerPos.x - distance);
            x <= Math.min(49, centerPos.x + distance);
            x++
        ) {
            for (
                let y = Math.max(0, centerPos.y - distance);
                y <= Math.min(49, centerPos.y + distance);
                y++
            ) {
                if (Math.abs(x - centerPos.x) + Math.abs(y - centerPos.y) === distance) {
                    Eif (terrain.get(x, y) !== TERRAIN_MASK_WALL) {
                        tiles.push(new RoomPosition(x, y, room.name));
                    }
                }
            }
        }
 
        return tiles;
    },
 
    // Visualize room planning
    visualizePlanning: function (room, positions, color = '#00ff00') {
        Eif (!positions || positions.length === 0) {
            return;
        }
 
        positions.forEach((pos) => {
            room.visual.circle(pos.x, pos.y, {
                radius: 0.4,
                fill: color,
                opacity: 0.5,
            });
        });
    },
 
    // Find positions for road network between key structures
    planRoadNetwork: function (room) {
        const spawn = room.find(FIND_MY_SPAWNS)[0];
        const sources = room.find(FIND_SOURCES);
        const controller = room.controller;
 
        Eif (!spawn) {
            return [];
        }
 
        const roadPositions = [];
 
        // Roads to sources
        sources.forEach((source) => {
            const path = spawn.pos.findPathTo(source, { ignoreCreeps: true });
            path.forEach((step) => {
                roadPositions.push(new RoomPosition(step.x, step.y, room.name));
            });
        });
 
        // Road to controller
        if (controller) {
            const path = spawn.pos.findPathTo(controller, { ignoreCreeps: true });
            path.forEach((step) => {
                roadPositions.push(new RoomPosition(step.x, step.y, room.name));
            });
        }
 
        return roadPositions;
    },
 
    // Display planning info
    displayPlanningInfo: function (room) {
        const openSpaces = this.findOpenSpaces(room, 3);
        const bestSpawnPos = this.findBestSpawnPosition(room);
 
        console.log(`\n🏗️ Room Planning [${room.name}]:`);
        console.log(`   Open spaces (5x5+): ${openSpaces.length}`);
 
        Eif (bestSpawnPos) {
            console.log(`   Best spawn position: ${bestSpawnPos}`);
        }
 
        return { openSpaces, bestSpawnPos };
    },
};