Fixes Closest Source

This commit is contained in:
2025-07-12 00:00:14 -03:00
parent f9af46c501
commit c38ebe3721
5 changed files with 66 additions and 62 deletions

View File

@@ -15,11 +15,11 @@ declare global {
id: string; id: string;
spots: SourcePositionMatrix; spots: SourcePositionMatrix;
pos: RoomPosition; pos: RoomPosition;
currentHarvesters: number;
} }
interface GameState { interface GameState {
sourcesStates: { [sourceId: string]: SourceState }; sourcesStates: { [sourceId: string]: SourceState };
maxHarvesters: number; // Maximum number of harvesters allowed in the game
} }
// Memory extension samples // Memory extension samples
@@ -35,6 +35,7 @@ declare global {
spawnId: string; spawnId: string;
working: boolean; working: boolean;
destination?: CreepDestination; destination?: CreepDestination;
previousDestination?: CreepDestination;
} }
// Syntax for adding proprties to `global` (ex "global.log") // Syntax for adding proprties to `global` (ex "global.log")

View File

@@ -33,7 +33,7 @@ class HarvesterHandler extends RoleHandler {
const sourceState = state.sourcesStates[source.id]; const sourceState = state.sourcesStates[source.id];
const emptySpot = getNextEmptySpot(sourceState.spots); const emptySpot = getNextEmptySpot(sourceState.spots);
if (!emptySpot) { if (emptySpot === null) {
continue; // No empty spots available, skip to next source continue; // No empty spots available, skip to next source
} }
@@ -47,7 +47,6 @@ class HarvesterHandler extends RoleHandler {
type: "source", type: "source",
sourceSpot: emptySpot sourceSpot: emptySpot
}; };
console.log(`Source ${creep.memory.destination.id} - `, state.sourcesStates[creep.memory.destination.id].spots)
return return
} }
@@ -62,12 +61,7 @@ class HarvesterHandler extends RoleHandler {
} }
if (creep.store.getFreeCapacity(RESOURCE_ENERGY) === 0) { if (creep.store.getFreeCapacity(RESOURCE_ENERGY) === 0) {
setSpotStatus( creep.memory.previousDestination = creep.memory.destination;
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.destination = { creep.memory.destination = {
id: creep.memory.spawnId, id: creep.memory.spawnId,
type: "spawn" type: "spawn"
@@ -76,7 +70,7 @@ class HarvesterHandler extends RoleHandler {
} }
const source = getSourceById(creep.memory.destination.id); const source = getSourceById(creep.memory.destination.id);
if (!source) { if (source === null) {
console.log(`Source not found for creep: ${creep.name}`); console.log(`Source not found for creep: ${creep.name}`);
return; return;
} }
@@ -85,12 +79,20 @@ class HarvesterHandler extends RoleHandler {
const sourceSpotPosition = getPositionWithDelta( const sourceSpotPosition = getPositionWithDelta(
source.pos, creep.memory.destination.sourceSpot 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) { 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 = { creep.memory.destination = {
id: creep.memory.spawnId, id: creep.memory.spawnId,
type: "spawn" type: "spawn"
@@ -109,7 +111,7 @@ class HarvesterHandler extends RoleHandler {
} }
if (creep.transfer(spawn, RESOURCE_ENERGY) === ERR_NOT_IN_RANGE) { 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) const sources = Object.keys(state.sourcesStates)
.map(sourceId => getSourceById(sourceId)) .map(sourceId => getSourceById(sourceId))
.filter(source => source !== null) .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 as Source[];
return sources;
} }
} }

View File

@@ -33,17 +33,18 @@ class SpawnHandler {
private updateSpawnState(state: GameState) { private updateSpawnState(state: GameState) {
const sources = this.spawn.room.find(FIND_SOURCES); const sources = this.spawn.room.find(FIND_SOURCES);
for (const source of sources) {
if (!state.sourcesStates) { if (!state.sourcesStates) {
state.sourcesStates = {}; state.sourcesStates = {};
state.maxHarvesters = 0
} }
for (const source of sources) {
const sourceId = source.id.toString(); const sourceId = source.id.toString();
if (!state.sourcesStates[sourceId]) { if (!state.sourcesStates[sourceId]) {
state.sourcesStates[sourceId] = { state.sourcesStates[sourceId] = {
"id": sourceId, "id": sourceId,
"pos": source.pos, "pos": source.pos,
"spots": createSourcePositionMatrix(), "spots": createSourcePositionMatrix(),
"currentHarvesters": 0
}; };
forEachMatrixSpot(state.sourcesStates[sourceId].spots, (delta, status) => { forEachMatrixSpot(state.sourcesStates[sourceId].spots, (delta, status) => {
if (status !== SourceSpotStatus.UNKNOWN) { if (status !== SourceSpotStatus.UNKNOWN) {
@@ -52,11 +53,11 @@ class SpawnHandler {
const pos = getPositionWithDelta(source.pos, delta); const pos = getPositionWithDelta(source.pos, delta);
if (checkPositionWalkable(pos)) { if (checkPositionWalkable(pos)) {
setSpotStatus(state.sourcesStates[sourceId].spots, delta, SourceSpotStatus.EMPTY); setSpotStatus(state.sourcesStates[sourceId].spots, delta, SourceSpotStatus.EMPTY);
state.maxHarvesters = state.maxHarvesters + 1;
} else { } else {
setSpotStatus(state.sourcesStates[sourceId].spots, delta, SourceSpotStatus.INVALID); setSpotStatus(state.sourcesStates[sourceId].spots, delta, SourceSpotStatus.INVALID);
} }
}) })
} }
} }
} }

View File

@@ -22,9 +22,9 @@ export type GameConfig = {
* @type {GameConfig} * @type {GameConfig}
*/ */
export const DEFAULT_GAME_CONFIG: GameConfig = { export const DEFAULT_GAME_CONFIG: GameConfig = {
maxCreeps: 7, maxCreeps: 5,
minCreepsPerRole: { minCreepsPerRole: {
harvester: 7, harvester: 5,
upgrader: 0, upgrader: 0,
builder: 0 builder: 0
} }

View File

@@ -12,68 +12,70 @@ export type SourceSpotStatus = (typeof SourceSpotStatus)[keyof typeof SourceSpot
export type PositionDeltaValue = -1 | 0 | 1; export type PositionDeltaValue = -1 | 0 | 1;
export type PositionDelta = { export type PositionDelta = 0 | 1 | 2 | 3 | 4 | 5 | 6 | 7 | 8 | 9;
x: PositionDeltaValue;
y: PositionDeltaValue;
}
export type SourcePositionMatrix = [ export type SourcePositionMatrix = {
locked: boolean;
data: [
SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, SourceSpotStatus,
SourceSpotStatus, SourceSpotStatus, SourceSpotStatus, 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
]; ];
} }
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 => { 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) { if (index === -1) {
return null; // No empty spot found return null; // No empty spot found
} }
return { return index as PositionDelta; // Convert index to PositionDelta
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)
};
}; };
export const setSpotStatus = (matrix: SourcePositionMatrix, delta: PositionDelta, status: SourceSpotStatus): void => { export const setSpotStatus = (matrix: SourcePositionMatrix, delta: PositionDelta, status: SourceSpotStatus): void => {
const x = delta.x + 1; // Convert to index (0, 1, 2) matrix.data[delta as number] = status;
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;
} }
export const getPositionWithDelta = (pos: RoomPosition, delta: PositionDelta): RoomPosition => { export const getPositionWithDelta = (pos: RoomPosition, delta: PositionDelta): RoomPosition => {
const matrixPoint = indexToMatrixPoint(delta as number);
return new RoomPosition( return new RoomPosition(
pos.x + delta.x, pos.x + matrixPoint.x,
pos.y + delta.y, pos.y + matrixPoint.y,
pos.roomName pos.roomName
); );
} }
export const forEachMatrixSpot = (matrix: SourcePositionMatrix, callback: (delta: PositionDelta, status: SourceSpotStatus) => void): void => { export const forEachMatrixSpot = (matrix: SourcePositionMatrix, callback: (delta: PositionDelta, status: SourceSpotStatus) => void): void => {
for (let y = -1; y <= 1; y++) { for (const index in matrix.data) {
for (let x = -1; x <= 1; x++) { callback(index as PositionDelta, matrix.data[index]);
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]);
}
} }
}; };