Skip to content
Open
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
5 changes: 5 additions & 0 deletions Fork.url
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://github.com/CTH999/bitburner-solution
5 changes: 5 additions & 0 deletions Original.url
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
[{000214A0-0000-0000-C000-000000000046}]
Prop3=19,11
[InternetShortcut]
IDList=
URL=https://github.com/snchlsn/bitburner-solution
8 changes: 8 additions & 0 deletions To Sort/autoexec.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,8 @@
import {initEnums} from "lib/nsEnums";
import {main as genResetInfo} from "lib/genInfo/reset";

export async function main(ns: NS) {
// initEnums needs to be synchronous and called first to prevent errors
initEnums(ns);
await genResetInfo(ns);
}
57 changes: 57 additions & 0 deletions To Sort/bladeburner/chooseCity.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
import {Ports} from "lib/util";
import {ExecutorJob} from "daemons/executor";
import {BladeburnerChaosThreshold, BladeburnerPopThreshold} from "bladeburner/util";
import {bladeburnerPlayer} from "bladeburner/genInfo/player";
import {BladeburnerCity, bladeburnerCities} from "bladeburner/genInfo/cities";

type CityEntry = [CityName, BladeburnerCity];

function chaosLow(c: CityEntry) {
return c[1].chaos <= BladeburnerChaosThreshold * 1.1;
}

function popAboveThreshold(c: CityEntry) {
return c[1].estimatedPopulation >= BladeburnerPopThreshold;
}

function popComparator(a: CityEntry, b: CityEntry) {
return a[1].estimatedPopulation - b[1].estimatedPopulation
}

export async function main(ns: NS) {
var destination;

// First, prefer cities with at least one community
var candidates: Array<CityEntry> =
Object.entries(bladeburnerCities).filter(c => c[1].communities) as typeof candidates;
if (!candidates.length)
candidates = Object.entries(bladeburnerCities) as typeof candidates;

// Second, prefer cities with low chaos
// Is this actually a good idea? Liable to get stuck in one city if Incite Violence is ever used.
// Probably won't happen, but even so, maybe reconsider.
if (candidates.findIndex(chaosLow) >= 0)
candidates = candidates.filter(chaosLow);

// Third, find the city closest to the threshold at which population affects success (above it if possible)
if (candidates.findIndex(popAboveThreshold) >= 0) {
candidates = candidates.filter(popAboveThreshold);
destination = candidates.toSorted(popComparator)[0][0];
}
else
destination = candidates.toSorted(popComparator)[candidates.length - 1][0];

if (bladeburnerPlayer.bladeburner.city != destination) {
ns.print("INFO: Traveling to ", destination, " from ", bladeburnerPlayer.bladeburner.city, ".");
ns.writePort(Ports.Exec, {
"script": "/bladeburner/travel.ts",
"hostname": ns.self().server,
"args": [destination],
"threadOrOptions": {"temporary": true},
"retry": true
} as ExecutorJob);
bladeburnerPlayer.bladeburner.city = destination;
}
else
ns.print("INFO: Staying in ", destination, ".");
}
19 changes: 19 additions & 0 deletions To Sort/bladeburner/forge.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,19 @@
import {Ports} from "lib/util";
import {main as genBladeburnerPlayer} from "bladeburner/genInfo/player";
import {main as genBladeburnerActions} from "bladeburner/genInfo/actions";
import {main as genBladeburnerCities} from "bladeburner/genInfo/cities";
import {main as chooseCity} from "bladeburner/chooseCity";
import {main as manageSkills} from "bladeburner/manageSkills";

export async function main(ns: NS) {
ns.clearPort(Ports.Bladeburner);
while (true) {
ns.clearLog();
await genBladeburnerCities(ns);
await genBladeburnerPlayer(ns);
await chooseCity(ns);
await genBladeburnerActions(ns);
await manageSkills(ns);
await ns.bladeburner.nextUpdate();
}
}
100 changes: 100 additions & 0 deletions To Sort/bladeburner/genInfo/actions.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {Ports} from "lib/util";
import {ExecutorJob} from "daemons/executor";
import {
BladeburnerAutoLevelMap,
BladeburnerActionEstimatedChanceMap,
BladeburnerActionLevelMap,
BladeburnerActionRepMap,
BladeburnerActionSucessesMap,
BladeburnerActionTimeMap,
BladeburnerActionsRemainingMap,
BladeburnerGetDir,
mapBladeburnerActions
} from "bladeburner/util";

const GetDir = BladeburnerGetDir + "action/";

export interface BladeburnerActionInfo {
autoLevel?: boolean,
estimatedSuccessChance: [number, number],
level?: number,
maxLevel?: number,
repGain: number,
successes: number,
time: number,
countRemaining: number
}

export var bladeburnerActions: Record<BladeburnerActionName, BladeburnerActionInfo>;

/** Shim for ns.bladeburner.getNextBlackOp. Name changed to distinguish it. */
export function getNextBlackOpShim() {
// Assumes Black Ops are in order, which happens to be true, but that's still not ideal.
return Object.entries(bladeburnerActions).find(
action => action[1].countRemaining == 1 && action[0].startsWith("Operation")
) as [BladeburnerBlackOpName, BladeburnerActionInfo];
}

export async function main(ns: NS) {
const hostname = ns.self().server;

var executorJob: ExecutorJob = {
"script": GetDir + "autoLevel.ts",
"hostname": hostname,
"args": ["-a"],
"threadOrOptions": {"temporary": true},
"retry": true
};
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const autoLevelMap = ns.readPort(Ports.Bladeburner) as BladeburnerAutoLevelMap;

executorJob.script = GetDir + "countRemaining.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const countRemainingMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionsRemainingMap;

executorJob.script = GetDir + "currentLevel.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const levelMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionLevelMap;

executorJob.script = GetDir + "maxLevel.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const maxLevelMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionLevelMap;

executorJob.script = GetDir + "repGain.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const repGainMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionRepMap;

executorJob.script = GetDir + "estSuccessChance.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const estChanceMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionEstimatedChanceMap;

executorJob.script = GetDir + "successes.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const successesMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionSucessesMap;

executorJob.script = GetDir + "time.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const timeMap = ns.readPort(Ports.Bladeburner) as BladeburnerActionTimeMap;

bladeburnerActions = Object.freeze(mapBladeburnerActions(
ns,
(typ, name) => ({
"autoLevel": autoLevelMap[name],
"countRemaining": countRemainingMap[name],
"level": levelMap[name],
"maxLevel": maxLevelMap[name],
"repGain": repGainMap[name],
"estimatedSuccessChance": estChanceMap[name],
"successes": successesMap[name],
"time": timeMap[name]
} as BladeburnerActionInfo)
));
}
44 changes: 44 additions & 0 deletions To Sort/bladeburner/genInfo/cities.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,44 @@
import {Ports} from "lib/util";
import {ExecutorJob} from "daemons/executor";
import {BladeburnerGetDir} from "bladeburner/util";

const GetDir = BladeburnerGetDir + "city/";

export type BladeburnerCity = {
estimatedPopulation: ReturnType<NS["bladeburner"]["getCityEstimatedPopulation"]>
communities: ReturnType<NS["bladeburner"]["getCityCommunities"]>
chaos: ReturnType<NS["bladeburner"]["getCityChaos"]>
};

export var bladeburnerCities: Record<CityName, BladeburnerCity>;

export async function main(ns: NS) {
const hostname = ns.self().server;

var executorJob: ExecutorJob = {
"script": GetDir + "chaos.ts",
"hostname": hostname,
"args": ["-a"],
"threadOrOptions": {"temporary": true},
"retry": true
};
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const chaos = ns.readPort(Ports.Bladeburner) as Record<CityName, number>;

executorJob.script = GetDir + "communities.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const communities = ns.readPort(Ports.Bladeburner) as Record<CityName, number>;

executorJob.script = GetDir + "estPop.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const estPop = ns.readPort(Ports.Bladeburner) as Record<CityName, number>;

bladeburnerCities = Object.freeze(Object.fromEntries(Object.values(ns.enums.CityName).map(c => [c, {
"chaos": chaos[c],
"communities": communities[c],
"estimatedPopulation": estPop[c]
} as BladeburnerCity])) as typeof bladeburnerCities);
}
100 changes: 100 additions & 0 deletions To Sort/bladeburner/genInfo/player.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,100 @@
import {Ports} from "lib/util";
import {ExecutorJob} from "daemons/executor";
import {BladeburnerGetDir as GetDir} from "bladeburner/util";

/** Bladeburner skill info */
export interface BladeburnerSkill {
/** Current skill level */
level: ReturnType<NS["bladeburner"]["getSkillLevel"]>,

/** Point cost of upgrading */
cost: ReturnType<NS["bladeburner"]["getSkillUpgradeCost"]>
}

export type BladeburnerSkills = Record<BladeburnerSkillName, BladeburnerSkill>;

/** Extends the Player interface with player info for Bladeburner */
export interface BladeburnerPlayer extends Player {bladeburner: {
city: ReturnType<NS["bladeburner"]["getCity"]>,
rank: ReturnType<NS["bladeburner"]["getRank"]>,
skills: BladeburnerSkills,
skillPoints: ReturnType<NS["bladeburner"]["getSkillPoints"]>,

/** Current stamina, max stamina */
stamina: ReturnType<NS["bladeburner"]["getStamina"]>,
teamSize: ReturnType<NS["bladeburner"]["getTeamSize"]>
}}

export var bladeburnerPlayer: BladeburnerPlayer;

export function getBladeburnerEffectiveSkills(player: BladeburnerPlayer) {
var skills = structuredClone(player.skills);
const reaperMult = 1 + (0.02 * player.bladeburner.skills[BladeburnerSkillName.Reaper].level);
const evasiveSysMult = 1 + (0.04 * player.bladeburner.skills[BladeburnerSkillName.EvasiveSystem].level);

for (const s of ["dexterity", "agility"] as Array<keyof Skills>)
skills[s] *= evasiveSysMult;
for (const s of ["strength", "defense", "dexterity", "agility"] as Array<keyof Skills>) {
skills[s] *= reaperMult;
skills[s] = Math.floor(skills[s]);
}
return skills;
}

export async function main(ns: NS) {
const hostname = ns.self().server;
var player = ns.getPlayer() as BladeburnerPlayer;

var executorJob: ExecutorJob = {
"script": GetDir + "skill/points.ts",
"hostname": hostname,
"threadOrOptions": {"temporary": true},
"retry": true
};
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const points = ns.readPort(Ports.Bladeburner) as BladeburnerPlayer["bladeburner"]["skillPoints"];

executorJob.script = GetDir + "city/current.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const city = ns.readPort(Ports.Bladeburner) as BladeburnerPlayer["bladeburner"]["city"];

executorJob.script = GetDir + "rank.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const rank = ns.readPort(Ports.Bladeburner) as BladeburnerPlayer["bladeburner"]["rank"];

executorJob.script = GetDir + "teamSize.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const teamSize = ns.readPort(Ports.Bladeburner) as BladeburnerPlayer["bladeburner"]["teamSize"];

executorJob.script = GetDir + "stamina.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const stamina = ns.readPort(Ports.Bladeburner) as BladeburnerPlayer["bladeburner"]["stamina"];

executorJob.script = GetDir + "skill/level.ts";
executorJob.args = ["-a"];
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const levels = ns.readPort(Ports.Bladeburner) as Record<BladeburnerSkillName, BladeburnerSkill["level"]>;

executorJob.script = GetDir + "skill/upgradeCost.ts";
ns.writePort(Ports.Exec, executorJob);
await ns.nextPortWrite(Ports.Bladeburner);
const costs = ns.readPort(Ports.Bladeburner) as Record<BladeburnerSkillName, BladeburnerSkill["cost"]>;

const skills = Object.fromEntries(ns.bladeburner.getSkillNames().map(s => [s, ({"level": levels[s], "cost": costs[s]} as BladeburnerSkill)])) as BladeburnerSkills;

player.bladeburner = {
"city": city,
"rank": rank,
"skills": skills,
"skillPoints": points,
"stamina": stamina,
"teamSize": teamSize
};
bladeburnerPlayer = player;
}
11 changes: 11 additions & 0 deletions To Sort/bladeburner/get/action/autoLevel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {Ports} from "lib/util";
import {mapBladeburnerActions} from "bladeburner/util";

export async function main(ns: NS) {
const flags = ns.flags([["a", false]]);
const getAuto = ns.bladeburner.getActionAutolevel;
ns.writePort(Ports.Bladeburner, flags.a ?
mapBladeburnerActions(ns, getAuto):
getAuto(ns.args[0] as BladeburnerActionType, ns.args[1] as BladeburnerActionName)
);
}
11 changes: 11 additions & 0 deletions To Sort/bladeburner/get/action/countRemaining.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {Ports} from "lib/util";
import {mapBladeburnerActions} from "bladeburner/util";

export async function main(ns: NS) {
const flags = ns.flags([["a", false]]);
const getCountRemaining = ns.bladeburner.getActionCountRemaining;
ns.writePort(Ports.Bladeburner, flags.a ?
mapBladeburnerActions(ns, getCountRemaining) :
getCountRemaining(ns.args[0] as BladeburnerActionType, ns.args[1] as BladeburnerActionName)
);
}
11 changes: 11 additions & 0 deletions To Sort/bladeburner/get/action/currentLevel.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,11 @@
import {Ports} from "lib/util";
import {mapBladeburnerActions} from "bladeburner/util";

export async function main(ns: NS) {
const flags = ns.flags([["a", false]]);
const getLevel = ns.bladeburner.getActionCurrentLevel;
ns.writePort(Ports.Bladeburner, flags.a ?
mapBladeburnerActions(ns, getLevel):
getLevel(ns.args[0] as BladeburnerActionType, ns.args[1] as BladeburnerActionName)
);
}
5 changes: 5 additions & 0 deletions To Sort/bladeburner/get/action/currentTime.ts
Original file line number Diff line number Diff line change
@@ -0,0 +1,5 @@
import {Ports} from "lib/util";

export async function main(ns: NS) {
ns.writePort(Ports.Bladeburner, ns.bladeburner.getActionCurrentTime());
}
Loading