Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
12 changes: 8 additions & 4 deletions src/role_mineral.js
Original file line number Diff line number Diff line change
Expand Up @@ -348,7 +348,7 @@ function setStatePrepareReactionLab1WithResource(creep) {
return false;
}
// Check if terminal actually has the required resource
if (!creep.room.terminal || !creep.room.terminal.store[reaction.result.first] || creep.room.terminal.store[reaction.result.first] === 0) {
if (!creep.room.terminal || !creep.room.terminal.store[reaction.result.first] || creep.room.terminal.store[reaction.result.first] < LAB_REACTION_AMOUNT) {
return false;
}
creep.data.state = {
Expand Down Expand Up @@ -378,7 +378,7 @@ function setStatePrepareReactionLab2WithResource(creep) {
return false;
}
// Check if terminal actually has the required resource
if (!creep.room.terminal || !creep.room.terminal.store[reaction.result.second] || creep.room.terminal.store[reaction.result.second] === 0) {
if (!creep.room.terminal || !creep.room.terminal.store[reaction.result.second] || creep.room.terminal.store[reaction.result.second] < LAB_REACTION_AMOUNT) {
return false;
}
creep.data.state = {
Expand Down Expand Up @@ -492,9 +492,13 @@ function handleWithdrawFromSource(creep) {
}
creep.moveToMy(source.pos);
const resource = creep.data.state.getResource(source);
if (!resource) {
creep.log(`No resource available from ${source}, clearing state`);
if (!resource || !source.store[resource] || source.store[resource] < LAB_REACTION_AMOUNT) {
creep.log(`No sufficient resource available from ${source}, clearing state and reaction`);
delete creep.data.state;
// Also clear the room's reaction to prevent immediate re-setting
if (creep.room.memory.reaction) {
delete creep.room.memory.reaction;
}
return true;
}
const response = creep.withdraw(source, resource);
Expand Down
7 changes: 3 additions & 4 deletions src/role_squadheal.js
Original file line number Diff line number Diff line change
Expand Up @@ -47,15 +47,14 @@ roles.squadheal.preMove = function(creep, directions) {
}
};

// TODO need to check if it works
roles.squadheal.action = function(creep) {
creep.selfHeal();
if (creep.room.name !== creep.memory.routing.targetRoom) {
// creep.log('Not in room');
// Not in target room yet - traveling
if (creep.hits < creep.hitsMax) {
creep.moveRandom();
} else {
// creep.log('delete?');
} else if (!creep.pos.isBorder(-1)) {
// Only reset routing if not at border to prevent bouncing
delete creep.memory.routing.reached;
}
return true;
Expand Down
9 changes: 7 additions & 2 deletions src/role_squadsiege.js
Original file line number Diff line number Diff line change
Expand Up @@ -76,15 +76,20 @@ roles.squadsiege.preMove = function(creep, directions) {
return false;
};

// TODO need to check if it works
roles.squadsiege.action = function(creep) {
creep.say('action');

if (creep.room.name !== creep.memory.routing.targetRoom) {
// Not in target room yet - traveling
if (creep.hits < creep.hitsMax) {
creep.moveRandom();
} else {
} else if (!creep.pos.isBorder(-1)) {
// Only reset routing if not at border to prevent bouncing
delete creep.memory.routing.reached;
}
return true; // Don't execute siege when traveling
}

// In target room - execute siege action
return creep.siege();
};
280 changes: 280 additions & 0 deletions test/test.js
Original file line number Diff line number Diff line change
Expand Up @@ -467,6 +467,74 @@ describe('Mineral System', () => {
// With the fix, state should be set because terminal has the resource
// (This test will pass after we implement the fix)
});

it('mineral creep does not set state when terminal has insufficient resources (1-4 units)', () => {
const room = new Room('W1N1', 5000);
room.terminal = {
id: 'terminal-id',
store: {
[RESOURCE_HYDROGEN]: 3, // Insufficient (< LAB_REACTION_AMOUNT of 5)
[RESOURCE_OXYGEN]: 100,
},
};
room.storage = {
id: 'storage-id',
store: {
energy: 10000,
},
};
room.memory.reaction = {
result: {
result: RESOURCE_HYDROXIDE,
first: RESOURCE_HYDROGEN,
second: RESOURCE_OXYGEN,
},
labs: ['lab0-id', 'lab1-id', 'lab2-id'],
};

const creep = {
name: 'mineral1',
role: 'mineral',
room: room,
data: {},
store: {
getUsedCapacity: () => 0,
getCapacity: () => 50,
},
carry: {},
say: () => {},
log: () => {},
moveRandom: () => {},
};

// Mock labs with lab1 needing hydrogen
global.Game.getObjectById = (id) => {
if (id === 'lab1-id') {
return {
id: 'lab1-id',
store: {
[RESOURCE_HYDROGEN]: 0, // Empty, needs refill
getCapacity: () => 3000,
},
};
}
if (id === 'lab2-id') {
return {
id: 'lab2-id',
store: {
[RESOURCE_OXYGEN]: 1500,
getCapacity: () => 3000,
},
};
}
return null;
};

roles.mineral.action(creep);

// State should NOT be set because terminal has insufficient resources (< LAB_REACTION_AMOUNT)
assert.equal(creep.data.state, undefined);
});
});

describe('Creep Spawning', () => {
Expand Down Expand Up @@ -680,3 +748,215 @@ describe('Trapped Detection', () => {
assert.equal(isTrapped, false, 'Should not count no-data as blocked when recently stagnant');
});
});

describe('Squad Roles', () => {
beforeEach(() => {
// Setup Memory.squads for tests
global.Memory.squads = {};
});

it('squadsiege does not delete routing.reached when at border position', () => {
const room = new Room('W1N1', 5000);

const creep = {
name: 'squadsiege-1',
memory: {
role: 'squadsiege',
routing: {
targetRoom: 'W1N2',
reached: true,
},
},
room: room,
pos: {
x: 0, // Border position
y: 25,
roomName: 'W1N1',
isBorder: () => true, // At border
},
hits: 1000,
hitsMax: 1000,
say: () => {},
moveRandom: () => {},
siege: () => true,
};

roles.squadsiege.action(creep);

// routing.reached should still be true because at border
assert.equal(creep.memory.routing.reached, true);
});

it('squadsiege deletes routing.reached when not in target room and not at border', () => {
const room = new Room('W1N1', 5000);

const creep = {
name: 'squadsiege-1',
memory: {
role: 'squadsiege',
routing: {
targetRoom: 'W1N2',
reached: true,
},
},
room: room,
pos: {
x: 25, // Not border position
y: 25,
roomName: 'W1N1',
isBorder: () => false, // Not at border
},
hits: 1000,
hitsMax: 1000,
say: () => {},
moveRandom: () => {},
siege: () => true,
};

roles.squadsiege.action(creep);

// routing.reached should be deleted because not at border and not in target room
assert.equal(creep.memory.routing.reached, undefined);
});

it('squadsiege does not call siege() when not in target room', () => {
const room = new Room('W1N1', 5000);
let siegeCalled = false;

const creep = {
name: 'squadsiege-1',
memory: {
role: 'squadsiege',
routing: {
targetRoom: 'W1N2',
},
},
room: room,
pos: {
x: 25,
y: 25,
roomName: 'W1N1',
isBorder: () => false,
},
hits: 1000,
hitsMax: 1000,
say: () => {},
moveRandom: () => {},
siege: () => {
siegeCalled = true;
return true;
},
};

roles.squadsiege.action(creep);

// siege() should NOT be called when traveling (not in target room)
assert.equal(siegeCalled, false);
});

it('squadsiege calls siege() when in target room', () => {
const room = new Room('W1N1', 5000);
let siegeCalled = false;

const creep = {
name: 'squadsiege-1',
memory: {
role: 'squadsiege',
routing: {
targetRoom: 'W1N1', // Same as current room
},
},
room: room,
pos: {
x: 25,
y: 25,
roomName: 'W1N1',
isBorder: () => false,
},
hits: 1000,
hitsMax: 1000,
say: () => {},
siege: () => {
siegeCalled = true;
return true;
},
};

roles.squadsiege.action(creep);

// siege() SHOULD be called when in target room
assert.equal(siegeCalled, true);
});

it('squadheal does not delete routing.reached when at border position', () => {
const room = new Room('W1N1', 5000);

const creep = {
name: 'squadheal-1',
memory: {
role: 'squadheal',
routing: {
targetRoom: 'W1N2',
reached: true,
},
},
room: room,
pos: {
x: 0, // Border position
y: 25,
roomName: 'W1N1',
isBorder: () => true, // At border
findClosestByRange: () => null,
},
hits: 1000,
hitsMax: 1000,
selfHeal: () => {},
say: () => {},
moveRandom: () => {},
moveTo: () => {},
squadHeal: () => {},
creepLog: () => {},
};

roles.squadheal.action(creep);

// routing.reached should still be true because at border
assert.equal(creep.memory.routing.reached, true);
});

it('squadheal deletes routing.reached when not in target room and not at border', () => {
const room = new Room('W1N1', 5000);

const creep = {
name: 'squadheal-1',
memory: {
role: 'squadheal',
routing: {
targetRoom: 'W1N2',
reached: true,
},
},
room: room,
pos: {
x: 25, // Not border position
y: 25,
roomName: 'W1N1',
isBorder: () => false, // Not at border
findClosestByRange: () => null,
},
hits: 1000,
hitsMax: 1000,
selfHeal: () => {},
say: () => {},
moveRandom: () => {},
moveTo: () => {},
squadHeal: () => {},
creepLog: () => {},
};

roles.squadheal.action(creep);

// routing.reached should be deleted because not at border and not in target room
assert.equal(creep.memory.routing.reached, undefined);
});
});