diff --git a/src/main.ts b/src/main.ts index 69366d0..6ee323c 100644 --- a/src/main.ts +++ b/src/main.ts @@ -15,11 +15,11 @@ declare global { id: string; spots: SourcePositionMatrix; pos: RoomPosition; - currentHarvesters: number; } interface GameState { sourcesStates: { [sourceId: string]: SourceState }; + maxHarvesters: number; // Maximum number of harvesters allowed in the game } // Memory extension samples @@ -35,6 +35,7 @@ declare global { spawnId: string; working: boolean; destination?: CreepDestination; + previousDestination?: CreepDestination; } // Syntax for adding proprties to `global` (ex "global.log") diff --git a/src/roleHandlers/harvesterHandler.ts b/src/roleHandlers/harvesterHandler.ts index b9505ee..e6343e9 100644 --- a/src/roleHandlers/harvesterHandler.ts +++ b/src/roleHandlers/harvesterHandler.ts @@ -33,7 +33,7 @@ class HarvesterHandler extends RoleHandler { const sourceState = state.sourcesStates[source.id]; const emptySpot = getNextEmptySpot(sourceState.spots); - if (!emptySpot) { + if (emptySpot === null) { continue; // No empty spots available, skip to next source } @@ -47,7 +47,6 @@ class HarvesterHandler extends RoleHandler { type: "source", sourceSpot: emptySpot }; - console.log(`Source ${creep.memory.destination.id} - `, state.sourcesStates[creep.memory.destination.id].spots) return } @@ -62,12 +61,7 @@ class HarvesterHandler extends RoleHandler { } if (creep.store.getFreeCapacity(RESOURCE_ENERGY) === 0) { - setSpotStatus( - state.sourcesStates[creep.memory.destination.id].spots, - creep.memory.destination.sourceSpot, - SourceSpotStatus.EMPTY - ); - console.log(`Source ${creep.memory.destination.id} - `, state.sourcesStates[creep.memory.destination.id].spots) + creep.memory.previousDestination = creep.memory.destination; creep.memory.destination = { id: creep.memory.spawnId, type: "spawn" @@ -76,7 +70,7 @@ class HarvesterHandler extends RoleHandler { } const source = getSourceById(creep.memory.destination.id); - if (!source) { + if (source === null) { console.log(`Source not found for creep: ${creep.name}`); return; } @@ -85,12 +79,20 @@ class HarvesterHandler extends RoleHandler { const sourceSpotPosition = getPositionWithDelta( source.pos, creep.memory.destination.sourceSpot ) - creep.moveTo(sourceSpotPosition, { reusePath: true, ignoreCreeps: true }); + creep.moveTo(sourceSpotPosition, { reusePath: 0, visualizePathStyle: { stroke: '#ffffff', lineStyle: 'dashed', strokeWidth: 0.1 } }); } } private static onSpawnDestination(creep: Creep, state: GameState) { - if (!creep.memory.destination) { + if (!!creep.memory.previousDestination && creep.memory.previousDestination.type === "source") { + setSpotStatus( + state.sourcesStates[creep.memory.previousDestination.id].spots, + creep.memory.previousDestination.sourceSpot, + SourceSpotStatus.EMPTY + ); + delete creep.memory.previousDestination; // Clear previous destination if it exists + } + if (creep.memory.destination === undefined) { creep.memory.destination = { id: creep.memory.spawnId, type: "spawn" @@ -109,7 +111,7 @@ class HarvesterHandler extends RoleHandler { } if (creep.transfer(spawn, RESOURCE_ENERGY) === ERR_NOT_IN_RANGE) { - creep.moveTo(spawn, { reusePath: true, ignoreCreeps: true }); + creep.moveTo(spawn, { reusePath: 0, visualizePathStyle: { stroke: '#ffffff', lineStyle: 'dashed', strokeWidth: 0.1 } }); } } @@ -119,11 +121,9 @@ class HarvesterHandler extends RoleHandler { const sources = Object.keys(state.sourcesStates) .map(sourceId => getSourceById(sourceId)) .filter(source => source !== null) - .sort((a, b) => Math.abs(creep.pos.getRangeTo(a) - creep.pos.getRangeTo(b))) + .sort((a, b) => creep.pos.getRangeTo(a) - creep.pos.getRangeTo(b)); - // console.log(`Creep ${creep.name} found ${sources.length} sources.`); - - return sources; + return sources as Source[]; } } diff --git a/src/spawnHandler.ts b/src/spawnHandler.ts index a51b755..cf431ac 100644 --- a/src/spawnHandler.ts +++ b/src/spawnHandler.ts @@ -33,17 +33,18 @@ class SpawnHandler { private updateSpawnState(state: GameState) { const sources = this.spawn.room.find(FIND_SOURCES); + if (!state.sourcesStates) { + state.sourcesStates = {}; + state.maxHarvesters = 0 + } for (const source of sources) { - if (!state.sourcesStates) { - state.sourcesStates = {}; - } const sourceId = source.id.toString(); + if (!state.sourcesStates[sourceId]) { state.sourcesStates[sourceId] = { "id": sourceId, "pos": source.pos, "spots": createSourcePositionMatrix(), - "currentHarvesters": 0 }; forEachMatrixSpot(state.sourcesStates[sourceId].spots, (delta, status) => { if (status !== SourceSpotStatus.UNKNOWN) { @@ -52,11 +53,11 @@ class SpawnHandler { const pos = getPositionWithDelta(source.pos, delta); if (checkPositionWalkable(pos)) { setSpotStatus(state.sourcesStates[sourceId].spots, delta, SourceSpotStatus.EMPTY); + state.maxHarvesters = state.maxHarvesters + 1; } else { setSpotStatus(state.sourcesStates[sourceId].spots, delta, SourceSpotStatus.INVALID); } }) - } } } diff --git a/src/types/gameConfig.ts b/src/types/gameConfig.ts index b649019..d36ebef 100644 --- a/src/types/gameConfig.ts +++ b/src/types/gameConfig.ts @@ -22,9 +22,9 @@ export type GameConfig = { * @type {GameConfig} */ export const DEFAULT_GAME_CONFIG: GameConfig = { - maxCreeps: 7, + maxCreeps: 5, minCreepsPerRole: { - harvester: 7, + harvester: 5, upgrader: 0, builder: 0 } diff --git a/src/types/source.ts b/src/types/source.ts index 42b801c..3bd5016 100644 --- a/src/types/source.ts +++ b/src/types/source.ts @@ -12,68 +12,70 @@ export type SourceSpotStatus = (typeof SourceSpotStatus)[keyof typeof SourceSpot export type PositionDeltaValue = -1 | 0 | 1; -export type PositionDelta = { - x: PositionDeltaValue; - y: PositionDeltaValue; -} +export type PositionDelta = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9; -export type SourcePositionMatrix = [ - SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, - SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, - SourceSpotStatus, SourceSpotStatus, SourceSpotStatus -] - - -export const createSourcePositionMatrix = () : SourcePositionMatrix => { - return [ - SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN, - SourceSpotStatus.UNKNOWN, SourceSpotStatus.CENTER, SourceSpotStatus.UNKNOWN, - SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN +export type SourcePositionMatrix = { + locked: boolean; + data: [ + SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, + SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, + SourceSpotStatus, SourceSpotStatus, SourceSpotStatus ]; } +type MatrixPoint = { + x: PositionDeltaValue; + y: PositionDeltaValue; +} + + +const indexToMatrixPoint = (index: number): MatrixPoint => { + // where the 0,0 point is the center of the matrix and -1, -1 is the top-left corner + const x = ((index % 3) - 1) as PositionDeltaValue; // Convert index to x coordinate (-1, 0, 1) + const y = (Math.floor(index / 3) - 1) as PositionDeltaValue; // Convert index to y coordinate (-1, 0, 1) + return { x, y }; +} + +export const createSourcePositionMatrix = () : SourcePositionMatrix => { + return { + locked: false, + data: [ + SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN, + SourceSpotStatus.UNKNOWN, SourceSpotStatus.CENTER, SourceSpotStatus.UNKNOWN, + SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN, SourceSpotStatus.UNKNOWN + ] + }; +} + + export const getNextEmptySpot = (matrix: SourcePositionMatrix): PositionDelta | null => { - const index = matrix.findIndex( status => status === SourceSpotStatus.EMPTY); + const index = matrix.data.findIndex( status => status === SourceSpotStatus.EMPTY); if (index === -1) { return null; // No empty spot found } - return { - x: (index % 3 - 1) as PositionDeltaValue, // Convert index to x delta (-1, 0, 1) - y: (Math.floor(index / 3) - 1) as PositionDeltaValue // Convert index to y delta (-1, 0, 1) - }; + return index as PositionDelta; // Convert index to PositionDelta }; export const setSpotStatus = (matrix: SourcePositionMatrix, delta: PositionDelta, status: SourceSpotStatus): void => { - const x = delta.x + 1; // Convert to index (0, 1, 2) - const y = delta.y + 1; // Convert to index (0, 1, 2) - - if (x < 0 || x > 2 || y < 0 || y > 2) { - throw new Error("Invalid position delta for source position matrix."); - } - - const index = y * 3 + x; // Calculate the index in the flat array - matrix[index] = status; + matrix.data[delta as number] = status; } export const getPositionWithDelta = (pos: RoomPosition, delta: PositionDelta): RoomPosition => { + const matrixPoint = indexToMatrixPoint(delta as number); return new RoomPosition( - pos.x + delta.x, - pos.y + delta.y, + pos.x + matrixPoint.x, + pos.y + matrixPoint.y, pos.roomName ); } export const forEachMatrixSpot = (matrix: SourcePositionMatrix, callback: (delta: PositionDelta, status: SourceSpotStatus) => void): void => { - for (let y = -1; y <= 1; y++) { - for (let x = -1; x <= 1; x++) { - const delta: PositionDelta = { x: x as PositionDeltaValue, y: y as PositionDeltaValue }; - const index = (y + 1) * 3 + (x + 1); // Convert delta to index - callback(delta, matrix[index]); - } + for (const index in matrix.data) { + callback(index as PositionDelta, matrix.data[index]); } };