Skip to content

Commit

Permalink
refactor: Refactor some things for better typing or decreased complex…
Browse files Browse the repository at this point in the history
…ity.
  • Loading branch information
Mirroar committed May 3, 2024
1 parent b608052 commit 2fd463b
Show file tree
Hide file tree
Showing 6 changed files with 256 additions and 212 deletions.
3 changes: 2 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -99,7 +99,8 @@
],
"ignores": [
"snippets.js",
"mock/constants.ts"
"mock/constants.ts",
"src/utils/Profiler"
],
"settings": {
"import/resolver": {
Expand Down
90 changes: 49 additions & 41 deletions src/main.ts
Original file line number Diff line number Diff line change
Expand Up @@ -10,8 +10,7 @@ import './prototype/room';
import './prototype/structure';

// Create kernel object.
import {PROCESS_PRIORITY_ALWAYS, PROCESS_PRIORITY_LOW, PROCESS_PRIORITY_HIGH} from 'hivemind';
import hivemind from 'hivemind';
import hivemind, {PROCESS_PRIORITY_ALWAYS, PROCESS_PRIORITY_LOW, PROCESS_PRIORITY_HIGH} from 'hivemind';
import SegmentedMemory from 'utils/segmented-memory';

import container from 'utils/container';
Expand Down Expand Up @@ -58,7 +57,7 @@ import * as Profiler from 'utils/Profiler';

declare global {
interface RawMemory {
_parsed: boolean;
_parsed: Memory;
}

namespace NodeJS {
Expand Down Expand Up @@ -98,12 +97,14 @@ balancer.init();

// @todo make unarmed creeps run from hostiles.

const main = {
class BotKernel {
lastTime: number = 0;
lastMemory: Memory = null;

/**
* Runs main game loop.
*/
loop() {
runTick() {
this.useMemoryFromHeap();

hivemind.segmentMemory.manage();
Expand Down Expand Up @@ -213,10 +214,8 @@ const main = {

this.showDebug();
this.recordStats();
},
}

lastTime: 0,
lastMemory: null,
useMemoryFromHeap() {
if (this.lastTime && this.lastMemory && Game.time === this.lastTime + 1) {
delete global.Memory;
Expand All @@ -233,7 +232,7 @@ const main = {
}

this.lastTime = Game.time;
},
}

/**
* Saves CPU stats for the current tick to memory.
Expand All @@ -252,7 +251,7 @@ const main = {
stats.recordStat('cpu_total', time);
stats.recordStat('bucket', Game.cpu.bucket);
stats.recordStat('creeps', _.size(Game.creeps));
},
}

/**
* Periodically deletes unused data from memory.
Expand Down Expand Up @@ -296,37 +295,12 @@ const main = {

// Periodically clean old room memory.
if (Game.time % 3738 === 2100 && hivemind.segmentMemory.isReady()) {
let count = 0;
_.each(Memory.rooms, (memory, roomName) => {
if (getRoomIntel(roomName).getAge() > 100_000) {
delete Memory.rooms[roomName];
count++;
}

if (memory.observeTargets && !Game.rooms[roomName]?.observer) {
delete memory.observeTargets;
}
});

if (count > 0) {
hivemind.log('main').debug('Pruned old memory for', count, 'rooms.');
}
this.cleanupRoomMemory();
}

// Periodically clean old squad memory.
if (Game.time % 548 === 3) {
_.each(Memory.squads, (memory, squadName) => {
// Only delete if squad can't be spawned.
if (memory.spawnRoom && Game.rooms[memory.spawnRoom]) return;

// Don't delete inter-shard squad that can't have a spawn room.
if (squadName === 'interShardExpansion') return;

// Only delete if there are no creeps belonging to this squad.
if (_.size(_.filter(Game.creeps, creep => creep.memory.squadName === squadName)) > 0) return;

delete Memory.squads[squadName];
});
this.cleanupSquadMemory();
}

// Periodically garbage collect in caches.
Expand All @@ -352,7 +326,40 @@ const main = {
if (Game.time % 3625 == 0 && hivemind.segmentMemory.isReady()) {
this.cleanupSegmentMemory();
}
},
}

cleanupRoomMemory() {
let count = 0;
_.each(Memory.rooms, (memory, roomName) => {
if (getRoomIntel(roomName).getAge() > 100_000) {
delete Memory.rooms[roomName];
count++;
}

if (memory.observeTargets && !Game.rooms[roomName]?.observer) {
delete memory.observeTargets;
}
});

if (count > 0) {
hivemind.log('main').debug('Pruned old memory for', count, 'rooms.');
}
}

cleanupSquadMemory() {
_.each(Memory.squads, (memory, squadName) => {
// Only delete if squad can't be spawned.
if (memory.spawnRoom && Game.rooms[memory.spawnRoom]) return;

// Don't delete inter-shard squad that can't have a spawn room.
if (squadName === 'interShardExpansion') return;

// Only delete if there are no creeps belonging to this squad.
if (_.size(_.filter(Game.creeps, creep => creep.memory.squadName === squadName)) > 0) return;

delete Memory.squads[squadName];
});
}

cleanupSegmentMemory() {
// Clean old entries from remote path manager from segment memory.
Expand Down Expand Up @@ -383,7 +390,7 @@ const main = {
const isMyRoom = Game.rooms[roomName] && Game.rooms[roomName].isMine();
if (!isMyRoom) hivemind.segmentMemory.delete(key);
});
},
}

/**
*
Expand All @@ -396,10 +403,11 @@ const main = {
Memory.hivemind.showProcessDebug--;
hivemind.drawProcessDebug();
}
},
}

};

const kernel = new BotKernel();
export const loop = ErrorMapper.wrapLoop(() => {
main.loop();
kernel.runTick();
});
2 changes: 2 additions & 0 deletions src/prototype/room.structures.ts
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,8 @@ declare global {
[STRUCTURE_LINK]: StructureLink[];
[STRUCTURE_NUKER]: StructureNuker[];
[STRUCTURE_OBSERVER]: StructureObserver[];
[STRUCTURE_PORTAL]: StructurePortal[];
[STRUCTURE_POWER_BANK]: StructurePowerBank[];
[STRUCTURE_POWER_SPAWN]: StructurePowerSpawn[];
[STRUCTURE_RAMPART]: StructureRampart[];
[STRUCTURE_SPAWN]: StructureSpawn[];
Expand Down
2 changes: 1 addition & 1 deletion src/role/hauler.relay.ts
Original file line number Diff line number Diff line change
Expand Up @@ -463,7 +463,7 @@ export default class RelayHaulerRole extends Role {
filter: structure => structure.structureType === STRUCTURE_CONTAINER
&& structure.store.getFreeCapacity() < structure.store.getCapacity() * 0.1
&& structure.store.getUsedCapacity(RESOURCE_ENERGY) > 100,
});
}) as StructureContainer[];
if (container.length > 0) creep.heapMemory.energyPickupTarget = container[0].id;
return container[0];
}
Expand Down
50 changes: 28 additions & 22 deletions src/room-intel.ts
Original file line number Diff line number Diff line change
@@ -1,5 +1,5 @@
/* global PathFinder Room RoomPosition
STRUCTURE_KEEPER_LAIR STRUCTURE_CONTROLLER CONTROLLER_DOWNGRADE FIND_SOURCES
STRUCTURE_KEEPER_LAIR STRUCTURE_CONTROLLER FIND_SOURCES
TERRAIN_MASK_WALL TERRAIN_MASK_SWAMP POWER_BANK_DECAY STRUCTURE_PORTAL
STRUCTURE_POWER_BANK FIND_MY_CONSTRUCTION_SITES STRUCTURE_STORAGE
STRUCTURE_TERMINAL FIND_RUINS STRUCTURE_INVADER_CORE EFFECT_COLLAPSE_TIMER */
Expand Down Expand Up @@ -36,6 +36,12 @@ declare global {
}
}

type AdjacentRoomEntry = {
range: number;
origin: string;
room: string;
};

export interface RoomIntelMemory {
lastScan: number;
exits: Partial<Record<ExitKey, string>>;
Expand Down Expand Up @@ -104,7 +110,7 @@ export default class RoomIntel {
otherUnsafeRooms: string[];
joinedDirs: Record<string, Record<string, boolean>>;

constructor(roomName) {
constructor(roomName: string) {
this.roomName = roomName;

const key = 'intel:' + roomName;
Expand Down Expand Up @@ -139,9 +145,9 @@ export default class RoomIntel {
this.gatherResourceIntel(room);

const structures = room.structuresByType;
this.gatherPowerIntel(structures[STRUCTURE_POWER_BANK] as StructurePowerBank[]);
this.gatherPowerIntel(structures[STRUCTURE_POWER_BANK]);
this.gatherDepositIntel();
this.gatherPortalIntel(structures[STRUCTURE_PORTAL] as StructurePortal[]);
this.gatherPortalIntel(structures[STRUCTURE_PORTAL]);
this.gatherInvaderIntel(structures);
this.gatherExitIntel(room.name);

Expand Down Expand Up @@ -180,7 +186,7 @@ export default class RoomIntel {
this.memory.rcl = 0;
this.memory.ticksToDowngrade = 0;
this.memory.hasController = typeof room.controller !== 'undefined';
if (room.controller && room.controller.owner) {
if (room.controller?.owner) {
this.memory.owner = room.controller.owner.username;
this.memory.rcl = room.controller.level;
this.memory.ticksToDowngrade = room.controller.ticksToDowngrade;
Expand Down Expand Up @@ -386,7 +392,7 @@ export default class RoomIntel {
gatherPortalIntel(portals: StructurePortal[]) {
delete this.memory.portals;

const targetRooms = [];
const targetRooms: string[] = [];
for (const portal of portals || []) {
// Ignore same-shard portals for now.
if ('shard' in portal.destination) {
Expand Down Expand Up @@ -456,13 +462,13 @@ export default class RoomIntel {
if (this.memory.owner) return;
if (!structures[STRUCTURE_STORAGE] && !structures[STRUCTURE_TERMINAL] && ruins.length === 0) return;

const resources = {};
const resources: Partial<Record<ResourceConstant, number>> = {};
const collections = [structures[STRUCTURE_STORAGE], structures[STRUCTURE_TERMINAL], ruins];
_.each(collections, objects => {
_.each(objects, object => {
if (!object.store) return;

_.each(object.store, (amount, resourceType) => {
_.each(object.store, (amount: number, resourceType: ResourceConstant) => {
resources[resourceType] = (resources[resourceType] || 0) + amount;
});
});
Expand Down Expand Up @@ -497,10 +503,10 @@ export default class RoomIntel {
* @param {object} structures
* An object containing Arrays of structures, keyed by structure type.
*/
gatherInvaderIntel(structures) {
gatherInvaderIntel(structures: Record<string, Structure[]>) {
delete this.memory.invaderInfo;

const core: StructureInvaderCore = _.first(structures[STRUCTURE_INVADER_CORE]);
const core = _.first(structures[STRUCTURE_INVADER_CORE]) as StructureInvaderCore;
if (!core) return;

// Commit basic invader core info.
Expand Down Expand Up @@ -619,7 +625,7 @@ export default class RoomIntel {
*/
isClaimed(): boolean {
if (this.isOwned()) return true;
if (this.memory.reservation && this.memory.reservation.username && this.memory.reservation.username !== getUsername()) return true;
if (this.memory.reservation?.username && this.memory.reservation.username !== getUsername()) return true;

return false;
}
Expand Down Expand Up @@ -675,7 +681,7 @@ export default class RoomIntel {
* Type of this room's mineral source.
*/
getMineralTypes(): string[] {
const result = [];
const result: string[] = [];

for (const mineral of this.memory.minerals || []) {
result.push(mineral.type);
Expand Down Expand Up @@ -716,7 +722,7 @@ export default class RoomIntel {
*/
getCostMatrix(): CostMatrix {
// @todo For some reason, calling this in console gives a different version of the cost matrix. Verify!
let obstaclePositions;
let obstaclePositions: {obstacles: RoomPosition[]; roads: RoomPosition[]};
if (this.memory.costPositions) {
obstaclePositions = {
obstacles: unpackCoordListAsPosList(this.memory.costPositions[0], this.roomName),
Expand Down Expand Up @@ -817,7 +823,7 @@ export default class RoomIntel {
* @return {number}
* Number of tiles of the given type in this room.
*/
countTiles(type: string) {
countTiles(type: 'plain' | 'swamp' | 'wall' | 'exit') {
if (!this.memory.terrain) return 0;

return this.memory.terrain[type] || 0;
Expand Down Expand Up @@ -871,7 +877,7 @@ export default class RoomIntel {
[RIGHT]: 'E',
[BOTTOM]: 'S',
[LEFT]: 'W',
};
} as const;

this.newStatus = {
N: true,
Expand All @@ -880,22 +886,22 @@ export default class RoomIntel {
W: true,
};

const openList = {};
const closedList = {};
const openList: Record<string, AdjacentRoomEntry> = {};
const closedList: Record<string, AdjacentRoomEntry> = {};
this.joinedDirs = {};
this.otherSafeRooms = options ? (options.safe || []) : [];
this.otherUnsafeRooms = options ? (options.unsafe || []) : [];
// Add initial directions to open list.
for (const moveDir of _.keys(this.memory.exits)) {
const dir = dirMap[moveDir];
for (const moveDir in this.memory.exits) {
const dir: string = dirMap[moveDir];
const roomName = this.memory.exits[moveDir];

this.addAdjacentRoomToCheck(roomName, openList, {dir, range: 0});
}

// Process adjacent rooms until range has been reached.
while (_.size(openList) > 0) {
let minRange = null;
let minRange: AdjacentRoomEntry = null;
for (const roomName in openList) {
if (!minRange || minRange.range > openList[roomName].range) {
minRange = openList[roomName];
Expand Down Expand Up @@ -942,7 +948,7 @@ export default class RoomIntel {
* @param {object} base
* Information about the room this operation is base on.
*/
addAdjacentRoomToCheck(roomName: string, openList: Record<string, {range: number; origin: string; room: string}>, base: {range: number; dir: string}) {
addAdjacentRoomToCheck(roomName: string, openList: Record<string, AdjacentRoomEntry>, base: {range: number; dir: string}) {
if (!this.isPotentiallyUnsafeRoom(roomName)) return;

openList[roomName] = {
Expand Down Expand Up @@ -975,7 +981,7 @@ export default class RoomIntel {
* @param {object} closedList
* List of rooms that have been checked.
*/
handleAdjacentRoom(roomData: {range: number; origin: string; room: string}, openList: Record<string, {range: number; origin: string; room: string}>, closedList: Record<string, {range: number; origin: string; room: string}>) {
handleAdjacentRoom(roomData: AdjacentRoomEntry, openList: Record<string, AdjacentRoomEntry>, closedList: Record<string, AdjacentRoomEntry>) {
const roomIntel = getRoomIntel(roomData.room);
if (roomIntel.getAge() > 100_000) {
// Room has no intel, declare it as unsafe.
Expand Down
Loading

0 comments on commit 2fd463b

Please sign in to comment.