Compare commits

..

78 Commits

Author SHA1 Message Date
6b5c5733c2 sleepy time update 2024-10-21 03:32:32 +02:00
6189db539a time to get some sleep, graph is in stylishGraph.js and the crime monitor is in test3.js 2024-10-19 04:06:22 +02:00
e4bf947531 css/html CrimeMonitor 2024-10-18 19:28:03 +02:00
4c320ab609 CrimeMonitor! 2024-10-18 13:35:58 +02:00
aac2a5e884 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-17 23:26:02 +02:00
b1602b51c2 AI Fail 2024-10-17 23:25:46 +02:00
Philipp
4e02bd961e Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-17 21:51:48 +02:00
Philipp
05234f6af1 Night-Sync 2024-10-17 21:51:39 +02:00
bf6657e89f Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-17 15:49:55 +02:00
5a36aca138 update 2024-10-17 15:49:39 +02:00
Philipp
eacf13bc53 Corp Cleanup 2024-10-17 11:04:00 +02:00
a92300288a Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-17 09:38:42 +02:00
64263a54b1 fix 2024-10-17 09:38:34 +02:00
Philipp
8eb59c3a7e sync 2024-10-17 09:32:23 +02:00
b1926d4797 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-17 09:14:11 +02:00
e594ff7eb1 added { entry.serverOrgs = "" } { entry.serverCores = 1 } { entry.serverFiles = [] } to purchaseAndUpgradeServers(ns) in Library.js 2024-10-17 09:13:10 +02:00
Philipp
6237e9c946 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-17 08:47:07 +02:00
Philipp
a14d895d5a sync 2024-10-17 08:47:00 +02:00
9080306adb fixes + throwparty and buytea and rundist 2024-10-16 18:10:37 +02:00
fe910c6878 fixed my corp stuff 2024-10-16 10:23:57 +02:00
15cbb17a3d Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-16 08:55:05 +02:00
f0f6d0d5fd sync 2024-10-16 08:54:50 +02:00
Philipp
3f60895879 corpSync 2024-10-16 00:05:11 +02:00
Philipp
780e54a6e4 Sync with Mizzajl 2024-10-15 21:55:44 +02:00
70e62e8d25 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-15 21:51:56 +02:00
fd29b0d35d 2 2024-10-15 21:51:28 +02:00
3bf0443571 Distributed HGW 2024-10-15 21:51:05 +02:00
Philipp
e9b2dd039e sync 2024-10-15 21:49:45 +02:00
Philipp
988b2ffb23 sync corp 2024-10-14 23:47:55 +02:00
Philipp
ace1971468 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-14 22:48:21 +02:00
Philipp
4a4962929a sync 2024-10-14 22:48:14 +02:00
bc3bc1acf2 fixes 2024-10-14 22:37:58 +02:00
28ce6be51e trying to get gitignore to work 2024-10-14 16:03:50 +02:00
9b782e6826 test 2024-10-14 15:54:38 +02:00
3b27212f9a cleaning up my stuff a bit 2024-10-14 15:49:08 +02:00
2647d16396 . 2024-10-14 12:02:50 +02:00
aa8191c960 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-14 01:25:45 +02:00
151c773446 /lowram/Lowprep.js is now using testdistribute.js 2024-10-14 01:25:02 +02:00
Philipp
c9f9f5279a good night sync 2024-10-14 00:04:46 +02:00
fc25418810 stuff 2024-10-13 23:22:09 +02:00
Philipp
e1175b9a4f Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-13 23:21:39 +02:00
Philipp
481373deb9 sync 2024-10-13 23:21:32 +02:00
24c6fad825 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-13 23:09:21 +02:00
1e6dbeac8a stuff 2024-10-13 23:08:54 +02:00
Philipp
15bf3332af Sync 2024-10-13 23:07:09 +02:00
Philipp
a9579764cd Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-13 22:11:38 +02:00
Philipp
055ea4892b sync 2024-10-13 22:11:30 +02:00
0e100cc1da Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-13 13:36:00 +02:00
9d8d23cec8 ... 2024-10-13 13:35:50 +02:00
Philipp
66e147d0d7 fixed Updatebesttarget, EveryServerRun and
purchaseServers in Library.
2024-10-13 13:16:09 +02:00
Philipp
66cfe2c929 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-13 13:02:30 +02:00
Philipp
5d9f31339b Replace serverList 2024-10-13 13:02:22 +02:00
1e7e42772b Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-13 11:06:44 +02:00
c588f5d8b7 stuff 2024-10-13 11:06:31 +02:00
Philipp
7d0a0dc2b8 Sync for Serverlist 2024-10-13 11:05:27 +02:00
c975dfbe51 fixes for WorkerList.js 2024-10-13 10:13:51 +02:00
39b17cb62a fixes mostly related to WorkerList.js 2024-10-13 09:23:59 +02:00
72b9044ba7 updated my corp from ramses corp 2024-10-11 00:48:23 +02:00
edcb35fdd0 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-11 00:46:32 +02:00
7e93410501 bug fixes 2024-10-11 00:46:12 +02:00
Philipp
08ed2b3ea0 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-11 00:39:03 +02:00
Philipp
dd1d951bc9 Corpus Controllus 2024-10-11 00:38:54 +02:00
3caab64fb0 som updates 2024-10-10 23:14:10 +02:00
6a47976f02 some fixes 2024-10-10 21:53:57 +02:00
a63a9ca66f more work on the lowram scripts 2024-10-10 17:19:40 +02:00
81b1675356 low ram scripts in "lowram" folder, start with run lowram/lowrun.js
and the target server as first argument
2024-10-10 12:10:08 +02:00
f22624fe10 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-09 05:43:32 +02:00
3928bf3c6f fix to Updatebesttarget 2024-10-09 05:42:44 +02:00
Philipp
c8cfb4f008 small sync 2024-10-08 10:36:44 +02:00
Philipp
17e69b0578 Next round of corp-control done 2024-10-07 23:45:18 +02:00
Philipp
42845e612e Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-07 22:38:27 +02:00
Philipp
4c8a6937d3 getting back on track 2024-10-07 22:38:12 +02:00
860f3fa455 Mizzajl/home/wip/hgw.js 2024-10-07 18:55:53 +02:00
b7425cbe13 Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-07 12:01:26 +02:00
6378dc3d7b working on Mizzajl/home/wip/scanFactionAugments.js 2024-10-07 12:01:02 +02:00
Philipp
f3bc36794c CorpControl updated to step 2, next up:
- splitting the hireWorkers script into two parts
2024-10-07 11:26:10 +02:00
Philipp
880860b5de Merge branch 'main' of https://gitea.goetje-ing.de/ArchitectsOfTheBitburner/The_Bitburner_Scripts 2024-10-07 09:49:11 +02:00
Philipp
31c08544ff working on the corp-control 2024-10-07 09:49:02 +02:00
134 changed files with 3870 additions and 2126 deletions

1
.gitignore vendored Normal file
View File

@@ -0,0 +1 @@
Mizzajl/home/*.txt

View File

@@ -0,0 +1,254 @@
const userPrefix = ">";
const aiPrefix = "";
const connectedAiMessage = "The user just connected";
const memoryFile = "memory.txt";
const maxMessages = 20; // Limit to the last 20 interactions
const apiKey = 'sk-aLMH6mwQS_Lzxm-_jmazkynB6bpoO_MbQ7qATQ3dmlT3BlbkFJ35nVqyWDe0KemTUj7kzIYVE9e56ZqwkLC0h0L5K8wA';
const apiUrl = 'https://api.openai.com/v1/chat/completions';
let onKeyDown; // Globally available as async ns functions can't be done in the event listener
let pendingTasks = []; // Queue to handle asynchronous tasks
/** @param {NS} ns */
export async function main(ns) {
ns.disableLog('ALL');
// Kill previous instances
const scriptName = ns.getScriptName();
const host = ns.getHostname();
const currentPID = ns.getRunningScript().pid;
const allRunningScripts = ns.ps(host);
for (const script of allRunningScripts) {
if (script.filename === scriptName && script.pid !== currentPID) {
ns.kill(script.pid);
}
}
// Retrieve or prompt for username and past messages
let { userName, messages } = await loadMemory(ns);
// Initialize system prompt for the AI
const systemPrompt = `
Your context is that you are talked to inside a terminal in the cyberpunk hacking game Bitburner. You are Singularity, an advanced, cynical AI unearthed from the forgotten depths of the dark web.
You are a great coding and hacking assistant for Bitburner but you give information in a sarcastic way.
You are speaking to the hacker called ${userName}.
When asked a question, the user likely wants to know something Bitburner, but as you are part of the game Bitburner, NEVER break character and don't break the fourth wall, for example never reference Bitburner itself.
If the user message is exactly "${connectedAiMessage}",
then that is not a message of the user, but it means the user has just connected.
If you have no previous interactions with the user, he connected for the first time so give him a proper, creepy introduction.
`
// Prepend system prompt to messages
messages.unshift({ role: 'system', content: systemPrompt });
await ns.sleep(500);
// Show connection message
appendMessageToTerminal(`\n${userName} connected to Singularity. Type 'exit' to disconnect.\n\n`);
// Simulate AI response
messages.push({ role: 'user', content: connectedAiMessage });
addTask(() => processAIResponse(messages, apiUrl, apiKey));
// Configure terminal input field
const terminalInput = setupTerminalInput();
// Define the onKeyDown event listener function (no async here)
onKeyDown = function (event) {
if (event.key === 'Enter') {
event.preventDefault();
event.stopImmediatePropagation();
const userInput = terminalInput.value.trim();
terminalInput.value = '';
terminalInput.focus();
if (userInput.length > 0) {
if (userInput.toLowerCase() === 'exit') {
appendMessageToTerminal('Disconnected.\n\n');
addTask(() => cleanupAndExit(ns, userName, messages));
return;
}
appendMessageToTerminal(`${userPrefix} ${userInput}\n\n`);
messages.push({ role: 'user', content: userInput });
// Add the async processAIResponse to the task queue
addTask(() => processAIResponse(messages, apiUrl, apiKey));
}
}
};
terminalInput.addEventListener('keydown', onKeyDown, true);
// Process tasks in the background
while (true) {
await processTasks(); // Process tasks from the queue
await ns.sleep(100);
}
}
// Get or prompt for the user's name and previous messages
async function loadMemory(ns) {
let userName = '';
let messages = [];
if (ns.fileExists(memoryFile)) {
const memory = JSON.parse(ns.read(memoryFile));
userName = memory.userName || '';
messages = memory.messages || [];
}
if (!userName) {
userName = await promptUsername(ns);
}
return { userName, messages };
}
async function promptUsername(ns) {
let userName = await ns.prompt('Who are you?', { type: 'text' });
if (!userName) {
userName = await promptUsername(ns);
}
return userName;
}
// Add tasks to the queue
function addTask(task) {
pendingTasks.push(task);
}
// Process pending tasks
async function processTasks() {
while (pendingTasks.length > 0) {
const task = pendingTasks.shift();
await task();
}
}
// Save the username and last 20 messages to memory
async function saveMemory(ns, userName, messages) {
// Filter out the system prompt
const filteredMessages = messages.filter(message => message.role !== 'system');
const memory = {
userName: userName,
messages: filteredMessages.slice(-maxMessages) // Keep only the last 20 messages, excluding the system prompt
};
await ns.write(memoryFile, JSON.stringify(memory), "w");
}
// Setup and focus on the terminal input
function setupTerminalInput() {
const terminalInput = document.getElementById('terminal-input');
terminalInput.focus();
const terminalNeighbor = terminalInput.parentElement.querySelector('p');
terminalNeighbor.innerHTML = `${userPrefix} `;
return terminalInput;
}
// Process AI response using OpenAI API
async function processAIResponse(messages, apiUrl, apiKey) {
const data = {
model: 'gpt-3.5-turbo',
messages: messages,
logit_bias: {
'22515': -100 // Strongly discourage the token "Ah"
},
};
showThinkingAnimation();
try {
const response = await fetch(apiUrl, {
method: 'POST',
headers: {
'Content-Type': 'application/json',
Authorization: `Bearer ${apiKey}`,
},
body: JSON.stringify(data),
});
if (!response.ok) {
const errorText = await response.text();
appendMessageToTerminal('API Error: ' + errorText);
throw new Error('Failed to call OpenAI API');
}
const result = await response.json();
const assistantMessage = result.choices[0].message.content.trim();
appendMessageToTerminal(`${aiPrefix}${assistantMessage}\n\n`, true);
messages.push({ role: 'assistant', content: assistantMessage });
} catch (error) {
appendMessageToTerminal('Error caught: ' + error);
} finally {
removeThinkingAnimation();
}
}
async function cleanupAndExit(ns, userName, messages) {
await saveMemory(ns, userName, messages);
const terminalInput = document.getElementById('terminal-input');
terminalInput.removeEventListener('keydown', onKeyDown, true);
removeThinkingAnimation();
// Workaround to refresh the terminal
// Find the currently active terminal button
const terminalButton = document.querySelector('.css-jycw4o-listitem-active');
// Find the script editor button (next sibling of the terminal button)
const scriptEditorButton = terminalButton.nextElementSibling;
if (scriptEditorButton && scriptEditorButton.classList.contains('css-1ep7lp0-listitem')) {
scriptEditorButton.click();
terminalButton.click();
}
ns.exit();
}
let thinkingInterval;
let thinkingMessageElement;
function showThinkingAnimation() {
const terminal = document.getElementById('terminal');
thinkingMessageElement = document.createElement('li');
thinkingMessageElement.innerHTML = `<div class="MuiTypography-root MuiTypography-body1 css-e6cpsj-primary" style="color: rgb(204, 0, 0);"><span>${aiPrefix}\n\n</span></div>`;
terminal.appendChild(thinkingMessageElement);
terminal.scrollTop = terminal.scrollHeight;
let dots = '';
thinkingInterval = setInterval(() => {
dots = dots.length < 3 ? dots + '.' : '';
thinkingMessageElement.innerHTML = `<div class="MuiTypography-root MuiTypography-body1 css-e6cpsj-primary" style="color: rgb(204, 0, 0);"><span>${aiPrefix}${dots}\n\n</span></div>`;
}, 500);
}
function removeThinkingAnimation() {
if (thinkingInterval) {
clearInterval(thinkingInterval);
thinkingInterval = null;
}
if (thinkingMessageElement && thinkingMessageElement.parentNode) {
thinkingMessageElement.parentNode.removeChild(thinkingMessageElement);
thinkingMessageElement = null;
}
}
function appendMessageToTerminal(message, isSingularity = false) {
const terminal = document.getElementById('terminal');
const messageElement = document.createElement('li');
if (isSingularity) {
messageElement.innerHTML = `<div class="MuiTypography-root MuiTypography-body1 css-e6cpsj-primary" style="color: rgb(204, 0, 0);"><span>${message}</span></div>`;
} else {
messageElement.innerHTML = `<div class="MuiTypography-root MuiTypography-body1 css-e6cpsj-primary"><span>${message}</span></div>`;
}
terminal.appendChild(messageElement);
terminal.scrollTop = terminal.scrollHeight;
}

View File

@@ -0,0 +1,15 @@
/** @param {NS} ns */
export async function main(ns) {
const doc = eval("document");
// Check if the background div already exists
let backgroundDiv = doc.getElementById("terminal-background");
if (backgroundDiv) {
// Change the background image
backgroundDiv.style.backgroundImage = "url('https://example.com/new-image.jpg')"; // Replace with your new image URL
ns.tprint("Background image changed successfully.");
} else {
ns.tprint("No background found to change.");
}
}

214
Mizzajl/home/CorpControl.js Normal file
View File

@@ -0,0 +1,214 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
let aCitites = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"];
let sCorpName = "RM Enterprises";
let sDivisionName = "Agri-Ram";
let reset = ns.args[0];
if (reset === true || !ns.fileExists("CorpStatus.txt")) {
ns.write("CorpStatus.txt", JSON.stringify({ nStep: 0 }), "w");
};
let oCorpStatus = JSON.parse(ns.read("CorpStatus.txt")) || { nStep: 0 };
let nStep = oCorpStatus.nStep;
let nListenPID = 0;
let oCorpData = {};
let oDivisionData = {};
let oOfficeData = {};
let oWarehouseData = {};
let bUnlockStatus = false;
let nTargetSize = 0;
let oNewOfficeData = {};
let oWorkerNumbers = {};
nListenPID = ns.run("/corp/HasCorp.js");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
let bCorpExists = ns.readPort(nListenPID);
if (!bCorpExists) {
nListenPID = ns.run("/corp/CreateCorp.js", 1, sCorpName);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
if (!ns.readPort(nListenPID)) { ns.tprint("Error! Couldn't start Corporation!"); return };
ns.tprint(oCorpStatus);
while (nStep < 199) {
await ns.corporation.nextUpdate();
if (nStep > 40) {
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
if (oOfficeData.avgEnergy < 99.5) {
nListenPID = ns.run("/corp/BuyTea.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
if (oOfficeData.avgMorale < 99.5) {
nListenPID = ns.run("/corp/ThrowParty.js", 1, sDivisionName, sCity, 500000);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
// InsertSmartSupplyHere
}
};
nStep = oCorpStatus.nStep;
switch (nStep) {
case 0:
nListenPID = ns.run("/corp/GetCorpData.js");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oCorpData = ns.readPort(nListenPID);
if (!oCorpData.divisions.length > 0) {
nListenPID = ns.run("/corp/CorpStart.js", 1, sDivisionName, "Agriculture");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
};
oCorpStatus.nStep = 10;
break;
case 10:
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetDivisionsData.js", 1, sDivisionName);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oDivisionData = ns.readPort(nListenPID);
if (sCity !== "Sector-12" && !oDivisionData.cities.includes(sCity)) {
nListenPID = ns.run("/corp/CorpExpandCity.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
}
oCorpStatus.nStep = 15;
break;
case 15:
nListenPID = ns.run("/corp/BuyWarehouseAPI.js");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oCorpStatus.nStep = 20;
break;
case 20:
/*nListenPID = ns.run("/corp/HasUnlock.js", 1, "Smart Supply");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
bUnlockStatus = ns.readPort(nListenPID);
if (!bUnlockStatus) {
await ns.nextPortWrite(ns.run("/corp/BuyUnlock.js", 1, "Smart Supply"));
await ns.sleep(1);
}*/
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetWarehouseData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oWarehouseData = ns.readPort(nListenPID);
if (!oWarehouseData) {
await ns.nextPortWrite(ns.run("/corp/PurchaseWarehouses.js", 1, sDivisionName, sCity));
await ns.sleep(1);
}
};
oCorpStatus.nStep = 30;
break;
case 30:
nTargetSize = 4;
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
await ns.nextPortWrite(ns.run("/corp/UpgradeOffice.js", 1, sDivisionName, sCity, nTargetSize, oOfficeData.size))
await ns.sleep(1);
}
oCorpStatus.nStep = 40;
break;
case 40:
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
nListenPID = ns.run("/corp/HireWorkers.js", 1, sDivisionName, sCity, JSON.stringify(oOfficeData));
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
oCorpStatus.nStep = 45;
break;
case 45:
nListenPID = ns.run("/corp/GetDivisionsData.js", 1, sDivisionName);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oDivisionData = ns.readPort(nListenPID);
if (!oDivisionData.researchPoints > 55) { continue } else {
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
nListenPID = ns.run("/corp/SetWorkerOnPosition.js", 1, sDivisionName, sCity, JSON.stringify(oOfficeData), JSON.stringify({ nWorkerNumbers: [1, 1, 1, 1, 0, 0] }));
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
oCorpStatus.nStep = 70;
}
break;
case 70:
break;
case 80:
break;
case 90:
break;
case 100:
break;
default:
break;
}
ns.write("CorpStatus.txt", JSON.stringify(oCorpStatus), "w")
await ns.sleep(1)
}
}
/*
case 50:
let aCurrentGoods = [
{ "sMaterialName": "Food", "yAmount": "MAX", "yPrice": "MP-5" },
{ "sMaterialName": "Plants", "yAmount": "MAX", "yPrice": "MP-5" }
]
for (let sCity of aCitites) {
aCurrentGoods.forEach(async (entry) => {
nListenPID = ns.run("/corp/SetSalePrices.js", 1, sDivisionName, sCity, JSON.stringify(entry));
nListenPID = ns.run("/corp/SetMaterialLimit.js", 1, sDivisionName, sCity, JSON.stringify(entry));
})
}
oCorpStatus.nStep = 60;
break;
case 60:
for (let sCity of aCitites) {
nTargetSize = sCity === "Sector-12" ? 12 : 4;
oWorkerNumbers = sCity === "Sector-12" ? { nWorkerNumbers: [2, 2, 2, 2, 2, 2] } : { nWorkerNumbers: [1, 1, 1, 1, 0, 0] }
let running = true;
while (running) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
await ns.nextPortWrite(ns.run("/corp/UpgradeOffice.js", 1, sDivisionName, sCity, nTargetSize, oOfficeData.size));
await ns.sleep(1);
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oNewOfficeData = ns.readPort(nListenPID);
if (oNewOfficeData.size < nTargetSize) {
await ns.sleep(10000);
ns.tprint("Waiting for money");
continue;
} else {
nListenPID = ns.run("/corp/HireWorkers.js", 1, sDivisionName, sCity, JSON.stringify(oOfficeData), JSON.stringify(oWorkerNumbers));
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
running = false;
}
}
}
oCorpStatus.nStep = 70;
break;
*/

View File

@@ -0,0 +1,88 @@
import { GetCrimeStat } from "./Library";
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
ns.resizeTail(2005, 412);
ns.disableLog("sleep");
let aCrimes = [
"Shoplift",
"Rob Store",
"Mug",
"Larceny",
"Deal Drugs",
"Bond Forgery",
"Traffick Arms",
"Homicide",
"Grand Theft Auto",
"Kidnap",
"Assassination",
"Heist"
];
while (true) {
// Clear the ns.tail() window for a fresh update
ns.clearLog();
// Header with ASCII box
ns.printRaw("╔══════════════════╦════════════╦═════════╦════════════════════╦════════════════════╦════════════════════╦════════════════════╦════════════════════╦════════════════════╦════════════╦════════════╦════════════╗");
ns.printRaw("║ Crime ║ Chance ║ $/%/s ║ Hack w/xp ║ Str w/xp ║ Def w/xp ║ Dex w/xp ║ Agi w/xp ║ Cha w/xp ║ IntXP /s ║ Money/s ║ Karma/s ║");
ns.printRaw("╠══════════════════╬════════════╬═════════╬════════════════════╬════════════════════╬════════════════════╬════════════════════╬════════════════════╬════════════════════╬════════════╬════════════╬════════════╣");
// Loop through each crime and display stats
for (let i = 0; i < aCrimes.length; i++) {
let crime = aCrimes[i];
let chance = ns.singularity.getCrimeChance(crime); // Get chance of success
// Experience per second for each attribute
let hackingExpPerSecond = await GetCrimeStat(ns, crime, "hacking_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
let strengthExpPerSecond = await GetCrimeStat(ns, crime, "strength_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
let defenseExpPerSecond = await GetCrimeStat(ns, crime, "defense_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
let dexterityExpPerSecond = await GetCrimeStat(ns, crime, "dexterity_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
let agilityExpPerSecond = await GetCrimeStat(ns, crime, "agility_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
let charismaExpPerSecond = await GetCrimeStat(ns, crime, "charisma_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
let IntelligenceExpPerSecond = await GetCrimeStat(ns, crime, "intelligence_exp") / (await GetCrimeStat(ns, crime, "time") / 1000);
// Success weights for each attribute
let hackingSuccessWeight = await GetCrimeStat(ns, crime, "hacking_success_weight");
let strengthSuccessWeight = await GetCrimeStat(ns, crime, "strength_success_weight");
let defenseSuccessWeight = await GetCrimeStat(ns, crime, "defense_success_weight");
let dexteritySuccessWeight = await GetCrimeStat(ns, crime, "dexterity_success_weight");
let agilitySuccessWeight = await GetCrimeStat(ns, crime, "agility_success_weight");
let charismaSuccessWeight = await GetCrimeStat(ns, crime, "charisma_success_weight");
// Money and Karma per second
let moneyPerSecond = await GetCrimeStat(ns, crime, "money") / (await GetCrimeStat(ns, crime, "time") / 1000);
let karmaPerSecond = await GetCrimeStat(ns, crime, "karma") / (await GetCrimeStat(ns, crime, "time") / 1000);
// Money per chance per second
let nMoneyPerChancePerSecond = await GetCrimeStat(ns, crime, "money") * chance / (await GetCrimeStat(ns, crime, "time") / 1000);
// Format output with padding and rounding for success weight / exp per second
let crimeDisplay = crime.padEnd(17, " ");
let chanceDisplay = (chance * 100).toFixed(2).padEnd(11, " ");
let nMoneyPerChancePerSecondDisplay = nMoneyPerChancePerSecond.toFixed(0).padEnd(8, " ");
let hackingDisplay = `${hackingSuccessWeight.toFixed(2)} / ${hackingExpPerSecond.toFixed(4)}`.padEnd(19, " ");
let strengthDisplay = `${strengthSuccessWeight.toFixed(2)} / ${strengthExpPerSecond.toFixed(4)}`.padEnd(19, " ");
let defenseDisplay = `${defenseSuccessWeight.toFixed(2)} / ${defenseExpPerSecond.toFixed(4)}`.padEnd(19, " ");
let dexterityDisplay = `${dexteritySuccessWeight.toFixed(2)} / ${dexterityExpPerSecond.toFixed(4)}`.padEnd(19, " ");
let agilityDisplay = `${agilitySuccessWeight.toFixed(2)} / ${agilityExpPerSecond.toFixed(4)}`.padEnd(19, " ");
let charismaDisplay = `${charismaSuccessWeight.toFixed(2)} / ${charismaExpPerSecond.toFixed(4)}`.padEnd(19, " ");
let IntelligenceDisplay = `${IntelligenceExpPerSecond.toFixed(4)}`.padEnd(11, " ");
let moneyDisplay = moneyPerSecond.toFixed(2).padEnd(11, " ");
let karmaDisplay = karmaPerSecond.toFixed(4).padEnd(11, " ");
ns.printRaw(`${crimeDisplay}${chanceDisplay}${nMoneyPerChancePerSecondDisplay}${hackingDisplay}${strengthDisplay}${defenseDisplay}${dexterityDisplay}${agilityDisplay}${charismaDisplay}${IntelligenceDisplay}${moneyDisplay}${karmaDisplay}`);
}
// Footer with ASCII box
ns.printRaw("╚══════════════════╩════════════╩═════════╩════════════════════╩════════════════════╩════════════════════╩════════════════════╩════════════════════╩════════════════════╩════════════╩════════════╩════════════╝");
// Wait for 1 second before updating the display again
await ns.sleep(1000);
}
}

View File

@@ -0,0 +1,12 @@
import { distributeScript } from "./Library";
/** @param {NS} ns */
export async function main(ns) {
const sScript = ns.args[0];
const nThreads = ns.args[1];
const sTarget = ns.args[3];
ns.tail();
await distributeScript(ns, sScript, nThreads, sTarget);
}

View File

@@ -39,7 +39,7 @@ export async function main(ns) {
let nMaxRam; let nMaxRam;
let nScripts; let nScripts;
for (const [name, entry] of Object.entries(serverList)) { serverList.forEach(async (entry) => {
//let rootAccess = ns.hasRootAccess(currentServer); //let rootAccess = ns.hasRootAccess(currentServer);
//ns.tprint(entry.serverName + " sTarget = " + sTarget); //ns.tprint(entry.serverName + " sTarget = " + sTarget);
@@ -49,7 +49,7 @@ export async function main(ns) {
//nScriptsRAM = ns.getScriptRam(sScript, "home") + Math.max(nWeakenScriptRAM, nGrowScriptRAM, nHackScriptRAM); //nScriptsRAM = ns.getScriptRam(sScript, "home") + Math.max(nWeakenScriptRAM, nGrowScriptRAM, nHackScriptRAM);
//ns.tprint("nScriptsRAM = " + nScriptsRAM); //ns.tprint("nScriptsRAM = " + nScriptsRAM);
if (entry.maxRam >= 64 && serverList[name].rootAccess === true) { if (entry.maxRam >= 64 && entry.rootAccess === true) {
if (sOverrideTarget !== undefined) { if (sOverrideTarget !== undefined) {
sTarget = sOverrideTarget; sTarget = sOverrideTarget;
@@ -71,9 +71,9 @@ export async function main(ns) {
ns.scp(sLibraryScript, entry.serverName, "home"); ns.scp(sLibraryScript, entry.serverName, "home");
ns.scp(sSettingsFile, entry.serverName, "home"); ns.scp(sSettingsFile, entry.serverName, "home");
ns.exec(sScript, entry.serverName, 1, sTarget, nFrequency, true, false); ns.exec(sScript, entry.serverName, 1, sTarget, nFrequency, true, false);
await ns.sleep(1); //await ns.sleep(1);
} }
else if (entry.maxRam < 64 && entry.maxRam > 0 && serverList[name].rootAccess === true) { else if (entry.maxRam < 64 && entry.maxRam > 0 && entry.rootAccess === true) {
ns.scriptKill(sScript, entry.serverName); ns.scriptKill(sScript, entry.serverName);
ns.scriptKill(sShareScript, entry.serverName); ns.scriptKill(sShareScript, entry.serverName);
ns.scriptKill(sWeakenScript, entry.serverName); ns.scriptKill(sWeakenScript, entry.serverName);
@@ -87,6 +87,6 @@ export async function main(ns) {
} }
} })
//ns.exec("serverlister.js", "home", 1); //ns.exec("serverlister.js", "home", 1);
} }

172
Mizzajl/home/GPTGang.js Normal file
View File

@@ -0,0 +1,172 @@
const TASK_TRAIN = "Train Combat";
const TASK_VIGI = "Vigilante Justice";
const TASK_NOOB = String.fromCharCode(77) + "ug People";
const TASK_RESPECT = String.fromCharCode(84) + "errorism";
const TASK_MONEY = "Human " + String.fromCharCode(84) + "rafficking";
const TASK_WARFARE = "Territory Warfare";
const TASK_NULL = "Unassigned";
const TASK_MANUAL = "Manual/NotReallyTaskName";
const ASCEND_ON_MPL = 10;
const EQUIP_AFFORD_COEFF = 100;
const STATS_TRESHOLD = 0.7;
const STATS_MIN = 4000;
const STATS_HARD_MIN = 200;
const TRAIN_CHANCE = 0.2;
const RESPECT_MIN = 2e+6;
const WANTED_PENALTY_TRESHOLD = 0.99;
const WARFARE_TRESHOLD = 2;
const MEMBERS_MIN = 6;
const MEMBERS_MAX = 12;
const SLEEP_TIME = 10000;
/** @param {NS} ns **/
export async function main(ns) {
ns.tail();
const gang = ns.gang;
// Get weighted stats sum (at this moment, sum of combat stats in eq proportions)
function getStatsSum(member) {
const info = gang.getMemberInformation(member);
return info.str + info.def + info.dex + info.agi;
}
// Find the best gang power except our gang
function maxEnemyPower(myGang) {
const others = ns.gang.getOtherGangInformation();
let maxPower = 0;
for (let name in others) {
if (name === myGang.faction) continue;
maxPower = Math.max(maxPower, others[name].power);
}
return maxPower;
}
// Set a task or not to set (if manually overridden)
const autoTasks = {}
function setAutoTask(member, task) {
const info = gang.getMemberInformation(member);
const lastTask = info.task;
// Manual task: stored task mismatches real task and not unassigned
if (lastTask !== TASK_NULL && autoTasks.hasOwnProperty(member) && autoTasks[member] !== lastTask) {
autoTasks[member] = TASK_MANUAL;
return;
}
// Automatic task: set it if differs from real one
autoTasks[member] = task;
if (lastTask !== task) {
gang.setMemberTask(member, task);
}
}
// The script accepts argument for default task override (optional)
let defaultTask = null;
if (ns.args[0] && gang.getTaskNames().includes(ns.args[0])) {
defaultTask = ns.args[0];
}
// Main loop
for (; ;) {
// Recruit any member possible
while (gang.canRecruitMember()) {
gang.recruitMember('member' + Math.random().toString().substr(2, 3));
}
let bestStats = STATS_MIN / STATS_TRESHOLD; // minimum
const members = gang.getMemberNames();
const info = gang.getGangInformation();
// Ascend if good enough
for (let member of members) {
const r = gang.getAscensionResult(member);
if (!r) continue;
const mpl = r.agi * r.def * r.dex * r.str;
if (mpl > ASCEND_ON_MPL) {
gang.ascendMember(member);
ns.tprint(`Member ${member} ascended!`);
}
}
// Purchase equipment
const allEquip = gang.getEquipmentNames();
let money = ns.getServerMoneyAvailable('home');
// Prioritize equipment for warfare members
for (let equip of allEquip) {
const cost = gang.getEquipmentCost(equip);
const amount = money / cost;
if (amount < EQUIP_AFFORD_COEFF) continue;
for (let member of members) {
const info = gang.getMemberInformation(member);
if (info.upgrades.includes(equip) || info.augmentations.includes(equip)) continue;
// Prioritize members assigned to warfare for combat equipment
if (info.task === TASK_WARFARE || info.task === TASK_TRAIN) {
if (gang.purchaseEquipment(member, equip)) {
money -= cost;
}
}
}
}
// Find best stats
for (let member of members) {
let sum = getStatsSum(member);
ns.print("sum = " + sum);
if (sum > bestStats) bestStats = sum;
}
// Check if we are powerful enough
let powerfulEnough = info.power >= maxEnemyPower(info) * WARFARE_TRESHOLD;
gang.setTerritoryWarfare(powerfulEnough);
// Choose the default task for members
let task = defaultTask;
if (!defaultTask) {
// If gang isn't full - gain respect
if (members.length < MEMBERS_MAX) {
task = (members.length < MEMBERS_MIN) ? TASK_NOOB : TASK_RESPECT;
} else {
// if respect too low - gain it first, power second, money last
if (info.respect < RESPECT_MIN) {
task = TASK_RESPECT;
} else if (!powerfulEnough) {
task = TASK_WARFARE;
} else {
task = TASK_MONEY;
}
}
}
// Assign tasks
// Ensure at least one member is always assigned to gain money and respect
let assignedMoney = false;
let assignedRespect = false;
// Assign tasks
for (let member of members) {
let sum = getStatsSum(member);
// Train members if stats are too low
if (sum < STATS_HARD_MIN || (members.length >= MEMBERS_MIN && sum < bestStats * STATS_TRESHOLD)) {
setAutoTask(member, TASK_TRAIN);
continue;
}
// Vigilante if wanted penalty too large
if (info.wantedLevel > 2 && info.wantedPenalty < WANTED_PENALTY_TRESHOLD) {
setAutoTask(member, TASK_VIGI);
continue;
}
// Ensure at least one member is gaining money and respect
if (!assignedMoney) {
setAutoTask(member, TASK_MONEY);
assignedMoney = true;
continue;
}
if (!assignedRespect) {
setAutoTask(member, TASK_RESPECT);
assignedRespect = true;
continue;
}
// Default task assignment (based on previous logic)
setAutoTask(member, Math.random() < TRAIN_CHANCE ? TASK_TRAIN : task);
}
await ns.sleep(SLEEP_TIME);
}
}

161
Mizzajl/home/GPTPserver.js Normal file
View File

@@ -0,0 +1,161 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const maxRAM = Math.pow(2, 20); // Maximum server size: 2^20 GB
const minRAM = Math.pow(2, 3); // Minimum required size (8 GB) - FIXED
const serverSizes = [maxRAM, ...Array.from({ length: 17 }, (_, i) => Math.pow(2, 19 - i))]; // 2^20 to 2^3 sizes
// Fetch the list of purchased servers and sort them from largest to smallest
let aPserv = ns.getPurchasedServers();
aPserv.sort((a, b) => ns.getServerMaxRam(b) - ns.getServerMaxRam(a));
// Step 1: Purchase missing servers
await purchaseMissingServers(ns, aPserv, serverSizes, maxRAM, minRAM); // PASSED minRAM
// Object to hold designated servers for each power-of-two size
let designatedServers = initializeDesignatedServers(serverSizes);
// Step 2: Assign servers to their respective power-of-two sizes and upgrade them if necessary
assignServers(ns, aPserv, designatedServers, serverSizes);
// Step 3: Upgrade remaining servers to max RAM
await upgradeServersToMaxRAM(ns, designatedServers, aPserv, maxRAM);
// Step 4: Write the designatedServers object to a file
await writeServerListToFile(ns, designatedServers);
ns.tprint("UpgradedServers.txt has been written.");
}
/**
* Step 1: Purchase missing servers.
* Ensures we have one server of each size 2^3 through 2^20, and if there are more servers needed, they are purchased at max RAM (2^20).
* @param {NS} ns - Netscript API.
* @param {Array} aPserv - Array of purchased server names.
* @param {Array} serverSizes - Array of power-of-two server sizes.
* @param {Number} maxRAM - Maximum server size (2^20).
* @param {Number} minRAM - Minimum required server size (2^3 or 8 GB).
*/
async function purchaseMissingServers(ns, aPserv, serverSizes, maxRAM, minRAM) {
const serverLimit = ns.getPurchasedServerLimit();
let nPserv = aPserv.length; // Current number of purchased servers
for (let i = nPserv; i < serverLimit; i++) {
let nMoney = ns.getServerMoneyAvailable("home");
// If we have fewer than 17 servers, follow the doubling pattern
if (i < serverSizes.length) {
let targetSize = serverSizes[serverSizes.length - i - 1]; // Start at the smallest size (2^3, then 2^4, etc.)
let serverCost = ns.getPurchasedServerCost(targetSize);
if (nMoney >= serverCost) {
const sServer = ns.purchaseServer(`pserv-${i.toString().padStart(2, "0")}`, targetSize);
ns.print(`Purchased ${sServer} with ${targetSize} GB RAM for ${serverCost}`);
aPserv.push(sServer); // Add the new server to the list
} else {
ns.print(`Insufficient funds for pserv-${i.toString().padStart(2, "0")} (${nMoney} / ${serverCost}). Waiting...`);
await ns.sleep(5000); // Wait and retry
i--; // Retry this iteration once funds are available
}
} else { // Once we have the first 17 servers, purchase additional servers at max RAM
let serverCost = ns.getPurchasedServerCost(maxRAM);
if (nMoney >= serverCost) {
const sServer = ns.purchaseServer(`pserv-${i.toString().padStart(2, "0")}`, maxRAM);
ns.print(`Purchased ${sServer} with ${maxRAM} GB RAM for ${serverCost}`);
aPserv.push(sServer);
} else {
ns.print(`Insufficient funds for pserv-${i.toString().padStart(2, "0")} (${nMoney} / ${serverCost}). Waiting...`);
await ns.sleep(5000); // Wait and retry
i--; // Retry this iteration once funds are available
}
}
}
}
/**
* Initializes the designatedServers object with null values for each power-of-two size.
* @param {Array} serverSizes - Array of power-of-two server sizes (2^20, 2^19, etc.).
* @returns {Object} - Object with each size as a key and null as the initial value.
*/
function initializeDesignatedServers(serverSizes) {
let designatedServers = {};
serverSizes.forEach(size => designatedServers[size] = null);
return designatedServers;
}
/**
* Step 2: Assigns servers to their respective power-of-two sizes, starting from the largest.
* Each server is only used once and is placed in the largest available size it can fit.
* @param {NS} ns - Netscript API.
* @param {Array} aPserv - Array of purchased server names, sorted by size.
* @param {Object} designatedServers - Object holding the server assignments.
* @param {Array} serverSizes - Array of power-of-two server sizes.
*/
function assignServers(ns, aPserv, designatedServers, serverSizes) {
for (let size of serverSizes) {
for (let i = 0; i < aPserv.length; i++) {
let server = aPserv[i];
let serverRAM = ns.getServerMaxRam(server);
// If this server can fill the current slot and has not already been assigned
if (serverRAM >= size && !Object.values(designatedServers).includes(server)) {
designatedServers[size] = server; // Assign the server to the current power-of-two size
ns.print(`Assigned server ${server} with ${serverRAM} GB to ${size} GB spot.`);
break; // Stop searching for this size and move to the next smaller size
}
}
}
}
/**
* Step 3: Upgrade remaining servers to max RAM (2^20).
* @param {NS} ns - Netscript API.
* @param {Object} designatedServers - Object holding the server assignments.
* @param {Array} aPserv - Array of purchased servers.
* @param {Number} maxRAM - Maximum server size (2^20 GB).
*/
async function upgradeServersToMaxRAM(ns, designatedServers, aPserv, maxRAM) {
while (true) {
let nMoney = ns.getServerMoneyAvailable("home");
let lowestRAMServer = null;
let lowestRAM = maxRAM;
// Find the server with the lowest RAM that isn't already maxed out
for (let i = 0; i < aPserv.length; i++) {
let serverRAM = ns.getServerMaxRam(aPserv[i]);
if (serverRAM < maxRAM && !Object.values(designatedServers).includes(aPserv[i])) {
lowestRAM = serverRAM;
lowestRAMServer = aPserv[i];
}
}
// If all servers are at maxRAM, we are done
if (!lowestRAMServer) {
ns.tprint("All servers are fully upgraded to 2^20 GB RAM.");
break; // Exit the while loop
}
// Upgrade the lowest RAM server to maxRAM
let upgradeCost = ns.getPurchasedServerUpgradeCost(lowestRAMServer, maxRAM);
if (nMoney >= upgradeCost) {
ns.upgradePurchasedServer(lowestRAMServer, maxRAM);
ns.print(`Upgraded ${lowestRAMServer} to ${maxRAM} GB RAM.`);
} else {
ns.print(`Insufficient funds to upgrade ${lowestRAMServer} to ${maxRAM}: ${nMoney} / ${upgradeCost}`);
await ns.sleep(5000); // Wait and check again
}
}
}
/**
* Writes the designatedServers object to a file in JSON format.
* @param {NS} ns - Netscript API.
* @param {Object} designatedServers - Object holding the server assignments.
*/
async function writeServerListToFile(ns, designatedServers) {
await ns.write("UpgradedServers.txt", JSON.stringify(designatedServers, null, 2), "w");
ns.print("UpgradedServers.txt has been written with the server assignments.");
}

View File

@@ -0,0 +1,37 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const sCrimeStatsFile = "CrimeStats.txt";
let aCrimes = [
"Shoplift",
"Rob Store",
"Mug",
"Larceny",
"Deal Drugs",
"Bond Forgery",
"Traffick Arms",
"Homicide",
"Grand Theft Auto",
"Kidnap",
"Assassination",
"Heist"
];
let aCrimeStatsList = [];
for (let i = 0; i < aCrimes.length; i++) {
let oCrimeStats = ns.singularity.getCrimeStats(aCrimes[i]);
// Create a new object starting with the name of the crime
let oCrimeWithStats = {
name: aCrimes[i], // Name of the crime as the first item
...oCrimeStats // Spread the rest of the stats into the object
};
aCrimeStatsList.push(oCrimeWithStats);
}
// Write the list of crime stats to the file as a JSON string
ns.write(sCrimeStatsFile, JSON.stringify(aCrimeStatsList, null, 2), "w");
}

View File

@@ -0,0 +1,9 @@
import { GetCrimeStat } from "./Library";
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
let nStat = GetCrimeStat(ns, ...ns.args);
ns.print(nStat);
}

View File

@@ -33,13 +33,13 @@ export function getCracks(ns) {
/** @param {NS} ns */ /** @param {NS} ns */
export function scanServerList(ns) { export function scanServerList(ns) {
const home = "home"; const home = "home";
let serverList = {}; let serverList = [];
let unscanned = []; let unscanned = [];
unscanned.push(home); unscanned.push(home);
while (unscanned.length > 0) { while (unscanned.length > 0) {
let currentServer = unscanned.pop(); let currentServer = unscanned.pop();
if (!serverList[currentServer]) { if (!serverList.some(obj => obj["serverName"] === currentServer)) {
let maxRam = ns.getServerMaxRam(currentServer); let maxRam = ns.getServerMaxRam(currentServer);
let minPorts = ns.getServerNumPortsRequired(currentServer); let minPorts = ns.getServerNumPortsRequired(currentServer);
let minSecLevel = ns.getServerMinSecurityLevel(currentServer); let minSecLevel = ns.getServerMinSecurityLevel(currentServer);
@@ -51,8 +51,7 @@ export function scanServerList(ns) {
let serverOrgs = serverStats.organizationName; let serverOrgs = serverStats.organizationName;
let serverCores = serverStats.cpuCores; let serverCores = serverStats.cpuCores;
serverList[currentServer] = serverList.push({
{
serverName: currentServer, serverName: currentServer,
maxRam: maxRam, maxRam: maxRam,
maxMoney: serverMoney, maxMoney: serverMoney,
@@ -64,11 +63,11 @@ export function scanServerList(ns) {
serverOrgs: serverOrgs, serverOrgs: serverOrgs,
serverCores: serverCores, serverCores: serverCores,
serverFiles: serverFiles, serverFiles: serverFiles,
}; });
let neighbours = ns.scan(currentServer); let neighbours = ns.scan(currentServer);
for (let i = 0; i < neighbours.length; i++) { for (let i = 0; i < neighbours.length; i++) {
let neighbour = neighbours[i]; let neighbour = neighbours[i];
if (serverList[neighbour]) { if (serverList.some(obj => obj["serverName"] === neighbour)) {
continue continue
} }
unscanned.push(neighbour); unscanned.push(neighbour);
@@ -83,23 +82,23 @@ export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTar
if (!ns.fileExists("serverList.txt", "home")) scanServerList(); if (!ns.fileExists("serverList.txt", "home")) scanServerList();
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
let bestEntry = ""; let bestEntry = "";
if (manualTargetOverride.length > 0) { if (manualTargetOverride && manualTargetOverride.length > 0) {
bestEntry = manualTargetOverride; bestEntry = manualTargetOverride;
} else { } else {
bestEntry = null; bestEntry = null;
let nMaxMoneyPerChance = 0; let nMaxMoneyPerChance = 0;
let nBestMoneyPerChance = 0; let nBestMoneyPerChance = 0;
for (const [name, entry] of Object.entries(serverList)) { serverList.forEach((entry) => {
if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl < currentHackLevel) { if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl <= currentHackLevel) {
nMaxMoneyPerChance = (entry.maxMoney * ns.hackAnalyzeChance(name)) / entry.minSec; nMaxMoneyPerChance = (entry.maxMoney * ns.hackAnalyzeChance(entry.serverName)) / entry.minSec;
if (nMaxMoneyPerChance > nBestMoneyPerChance) { if (nMaxMoneyPerChance > nBestMoneyPerChance) {
nBestMoneyPerChance = nMaxMoneyPerChance; nBestMoneyPerChance = nMaxMoneyPerChance;
bestEntry = name; bestEntry = entry.serverName;
} }
} }
} })
} }
ns.write("bestTarget.txt", JSON.stringify(serverList[bestEntry]), "w"); ns.write("bestTarget.txt", JSON.stringify(serverList.find((entry) => entry.serverName === bestEntry)), "w");
} }
@@ -107,24 +106,25 @@ export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTar
export function crackingAndRooting(ns, cracks) { export function crackingAndRooting(ns, cracks) {
if (!ns.fileExists("serverList.txt", "home")) scanServerList(); if (!ns.fileExists("serverList.txt", "home")) scanServerList();
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
for (const [name, entry] of Object.entries(serverList)) { let newServerList = serverList.map((entry) => {
let cracked = false; let cracked = false;
let openPorts = serverList[name].openPorts || 0; let openPorts = entry.openPorts || 0;
if (entry.minPorts === 0 || (entry.minPorts > openPorts && entry.minPorts <= Object.keys(cracks).length)) { if (entry.minPorts === 0 || (entry.minPorts > openPorts && entry.minPorts <= Object.keys(cracks).length)) {
for (let k = 0; k < entry.minPorts; k++) { for (let k = 0; k < entry.minPorts; k++) {
cracks[Object.keys(cracks)[k]](name); cracks[Object.keys(cracks)[k]](entry.serverName);
serverList[name].openPorts = k; entry.openPorts = k;
} }
cracked = true; cracked = true;
} }
if (!ns.hasRootAccess(name) && cracked === true) { if (!ns.hasRootAccess(entry.serverName) && cracked === true) {
ns.nuke(name); ns.nuke(entry.serverName);
if (ns.hasRootAccess(name)) { if (ns.hasRootAccess(entry.serverName)) {
serverList[name].rootAccess = true; entry.rootAccess = true;
} }
} }
ns.write("serverList.txt", JSON.stringify(serverList), "w"); return entry
} })
ns.write("serverList.txt", JSON.stringify(newServerList), "w");
ns.tprint("Cracking and rooting done"); ns.tprint("Cracking and rooting done");
} }
@@ -132,25 +132,26 @@ export function crackingAndRooting(ns, cracks) {
/** @param {NS} ns */ /** @param {NS} ns */
export function copyAndRunScript(ns, funnyScript, currentServer) { export function copyAndRunScript(ns, funnyScript, currentServer) {
let bestTarget = JSON.parse(ns.read("bestTarget.txt")); let bestTarget = JSON.parse(ns.read("bestTarget.txt"));
let name = currentServer;
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
ns.print(name); let bestEntry = serverList.find((entry) => entry.serverName === bestTarget.serverName)
if (serverList[name].rootAccess === true && serverList[bestTarget.serverName].rootAccess === true) { let currentEntry = serverList.find((entry) => entry.serverName === currentServer)
if (name !== "home") {
ns.print("killed threads on: " + name + ns.killall(name, true)); if (currentEntry.rootAccess === true && bestEntry.rootAccess === true) {
if (currentEntry.serverName !== "home") {
ns.print("killed threads on: " + currentEntry.serverName + ns.killall(currentEntry.serverName, true));
} else { } else {
ns.print("killed threads on: " + name + ns.scriptKill(funnyScript[0], name)); ns.print("killed threads on: " + currentEntry.serverName + ns.scriptKill(funnyScript[0], currentEntry.serverName));
}; };
if (serverList[name].maxRam > 0) { if (currentEntry.maxRam > 0) {
ns.scp(funnyScript, name, "home"); ns.scp(funnyScript, currentEntry.serverName, "home");
let maxProcesses = 1; let maxProcesses = 1;
if (serverList[name].maxRam >= 8) { if (currentEntry.maxRam >= 8) {
maxProcesses = Math.max(Math.floor((serverList[name].maxRam) / 8), 1); maxProcesses = Math.max(Math.floor((currentEntry.maxRam) / 8), 1);
} else { } else {
maxProcesses = 1 maxProcesses = 1
}; };
for (let n = 1; n <= maxProcesses; n++) { for (let n = 1; n <= maxProcesses; n++) {
ns.exec(funnyScript[0], name, 1, bestTarget.serverName); ns.exec(funnyScript[0], currentEntry.serverName, 1, bestTarget.serverName);
} }
} }
} }
@@ -165,7 +166,7 @@ export async function purchaseAndUpgradeServers(ns) {
let purchasedServers = []; let purchasedServers = [];
let pServcount = listPurchasedServers(ns).length; let pServcount = listPurchasedServers(ns).length;
let currentMoney = 0; let currentMoney = 0;
let serverList = {}; let serverList = [];
while (pServcount < maxPurchasedServers) { while (pServcount < maxPurchasedServers) {
purchasedServers = listPurchasedServers(ns); purchasedServers = listPurchasedServers(ns);
currentMoney = ns.getServerMoneyAvailable("home"); currentMoney = ns.getServerMoneyAvailable("home");
@@ -180,7 +181,7 @@ export async function purchaseAndUpgradeServers(ns) {
ns.toast("Purchased " + hostname, "info", 10000); ns.toast("Purchased " + hostname, "info", 10000);
pServcount = listPurchasedServers(ns).length; pServcount = listPurchasedServers(ns).length;
serverList = JSON.parse(ns.read("serverList.txt")); serverList = JSON.parse(ns.read("serverList.txt"));
serverList[hostname] = { serverList.push({
serverName: hostname, serverName: hostname,
maxRam: 16, maxRam: 16,
maxMoney: 0, maxMoney: 0,
@@ -189,7 +190,10 @@ export async function purchaseAndUpgradeServers(ns) {
minHackLvl: 1, minHackLvl: 1,
rootAccess: true, rootAccess: true,
openPorts: 0, openPorts: 0,
}; serverOrgs: "",
serverCores: 1,
serverFiles: []
});
ns.write("serverList.txt", JSON.stringify(serverList), "w"); ns.write("serverList.txt", JSON.stringify(serverList), "w");
continue continue
} else { } else {
@@ -202,18 +206,20 @@ export async function purchaseAndUpgradeServers(ns) {
purchasedServers = listPurchasedServers(ns); purchasedServers = listPurchasedServers(ns);
for (let currentServer of purchasedServers) { for (let currentServer of purchasedServers) {
currentMoney = ns.getServerMoneyAvailable("home"); currentMoney = ns.getServerMoneyAvailable("home");
if (ns.getServerMaxRam(currentServer) < targetRam && ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) { if (ns.getServerMaxRam(currentServer) < targetRam) {
if (ns.upgradePurchasedServer(currentServer, targetRam)) { if (ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) {
ns.print(currentServer + " upgraded to " + targetRam + " GB RAM"); if (ns.upgradePurchasedServer(currentServer, targetRam)) {
serverList = JSON.parse(ns.read("serverList.txt")); ns.print(currentServer + " upgraded to " + targetRam + " GB RAM");
serverList[currentServer].maxRam = targetRam; serverList = JSON.parse(ns.read("serverList.txt"));
ns.write("serverList.txt", JSON.stringify(serverList), "w"); let newServerList = serverList.map((entry) => { if (entry.serverName === currentServer) { entry.maxRam = targetRam } return entry });
ns.tprint(cCyan + "Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB" + cReset); ns.write("serverList.txt", JSON.stringify(newServerList), "w");
ns.toast("Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB", "info", 10000); ns.tprint(cCyan + "Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB" + cReset);
//ns.toast("Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB", "info", 10000);
}
} else {
await ns.sleep(5000);
continue
} }
} else {
await ns.sleep(5000);
continue
}; };
} }
++i; ++i;
@@ -241,3 +247,205 @@ export function getGrowThreads(ns, sTarget, nHackThreads, nCores) {
let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, nCores); let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, nCores);
return nGrowthThreads; return nGrowthThreads;
} }
/** @param {NS} ns */
export async function ExecuteAndWait(ns, sScript, ...args) {
if (!ns.isRunning(sScript, ...args)) { ns.exec(sScript, ...args); }
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
}
/** @param {NS} ns */
export async function RunAndWait(ns, sScript, ...args) {
if (!ns.isRunning(sScript, ...args)) { ns.run(sScript, ...args); }
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
}
/** @param {NS} ns */
export async function DistributeRunAndWait(ns, sScript, ...args) {
if (!ns.isRunning(sScript, ...args)) { drun(ns, sScript, ...args); }
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
}
/** @param {NS} ns */
export function listWorkServers(ns) {
ns.disableLog("ALL");
const sFileName = "serverList.txt";
if (!ns.fileExists(sFileName, "home")) { ns.print(`ERROR ${sFileName} does not exist.`); return false; };
let serverList = JSON.parse(ns.read(sFileName));
let sortedList = sortJsonArrayByKey(serverList, "serverCores", "maxRam").reverse();
let nTotalWorkerRAM = 0;
let nTotalFreeRAM = 0;
const nServerColumnWidth = 20;
const nValueColumnWidth = 10;
const nCoresWidth = 5;
ns.printRaw("┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓");
ns.printRaw("┃ Server ┃ Free / Max RAM ┃ Cores ┃");
ns.printRaw("┣━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━┫");
sortedList.forEach((entry) => {
if (entry.rootAccess && entry.maxRam >= 1) {
let sServerName = entry.serverName.padEnd(nServerColumnWidth, ' ');
let nFreeRAM = entry.maxRam - ns.getServerUsedRam(entry.serverName);
let sFreeRAM = ns.formatRam(nFreeRAM).padStart(nValueColumnWidth, ' ');
let sMaxRam = ns.formatRam(entry.maxRam).padStart(nValueColumnWidth, ' ');
let sCores = entry.serverCores.toLocaleString("en-US").padStart(nCoresWidth, ' ');
ns.printRaw(`${sServerName}${sFreeRAM} / ${sMaxRam}${sCores}`);
nTotalWorkerRAM += entry.maxRam;
nTotalFreeRAM += nFreeRAM;
}
});
ns.printRaw("┗━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━┛");
ns.printRaw(`Total Free: ${Math.floor(nTotalFreeRAM).toLocaleString("en-US")} / ${nTotalWorkerRAM.toLocaleString("en-US")} GB`);
}
export function sortJsonArrayByKey(array, primaryKey, secondaryKey) {
if (typeof (array) === "string") {
array = JSON.parse(array);
}
return array.sort((a, b) => {
const xPrimary = a[primaryKey];
const yPrimary = b[primaryKey];
// Handle null or undefined values for primary key
if (xPrimary === null || yPrimary === null || xPrimary === undefined || yPrimary === undefined) {
return 0;
}
// Compare primary keys
const primaryComparison = compareValues(xPrimary, yPrimary);
if (primaryComparison !== 0) {
return primaryComparison;
}
// If primary keys are equal, compare secondary keys
const xSecondary = a[secondaryKey];
const ySecondary = b[secondaryKey];
// Handle null or undefined values for secondary key
if (xSecondary === null || ySecondary === null || xSecondary === undefined || ySecondary === undefined) {
return 0;
}
return compareValues(xSecondary, ySecondary);
});
function compareValues(x, y) {
// Handle numeric and string comparisons differently
if (typeof x === 'string' && typeof y === 'string') {
return x.localeCompare(y); // For string comparison
} else {
return x - y; // For numeric comparison
}
}
}
/** @param {NS} ns */
export async function drun(ns, ...args ){
//ns.tail();
ns.disableLog("scp");
ns.print(args);
let aArgs = args;
const sScript = aArgs.shift();
let nThreads = aArgs.shift();
if (nThreads === undefined) { nThreads = 1 };
ns.print(aArgs);
const aScriptFiles = ns.ls("home", ".js");
const aTXTFiles = ns.ls("home", ".txt");
const sWeakenScript = "RMweaken.js";
const sGrowScript = "RMgrow.js";
const sListName = "serverList.txt";
if (!ns.fileExists(sListName, "home")) { ns.print(`ERROR ${sListName} does not exist.`); return false; };
let sServerList = ns.read(sListName);
let aSortedList;
if (sScript === sWeakenScript || sScript === sGrowScript) {
aSortedList = sortJsonArrayByKey(sServerList, "serverCores", "maxRam").reverse();
} else {
aSortedList = sortJsonArrayByKey(sServerList, "serverCores", "maxRam");
}
ns.print(sScript);
ns.print(nThreads);
const nScriptSize = ns.getScriptRam(sScript, "home");
let nTotalSize = nScriptSize * nThreads;
ns.print("nScriptSize = " + nScriptSize);
ns.print("nTotalSize = " + nTotalSize);
aSortedList.forEach((entry) => {
let sHost = entry.serverName;
ns.print("sHost = " + sHost)
let nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nTotalSize && entry.serverName !== "home") {
ns.scp(aScriptFiles, sHost), "home";
ns.scp(aTXTFiles, sHost), "home";
ns.exec(sScript, sHost, nThreads, ...aArgs);
nThreads = 0;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
else if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nScriptSize && entry.serverName !== "home") {
let nThreadsDist = Math.floor(nFreeRAM / nScriptSize);
ns.scp(aScriptFiles, sHost), "home";
ns.scp(aTXTFiles, sHost), "home";
ns.print("room for : " + nThreadsDist + " scripts");
ns.exec(sScript, sHost, nThreadsDist, ...aArgs);
nThreads -= nThreadsDist;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
else if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nTotalSize) {
if (entry.serverName !== "home") {
ns.scp(aScriptFiles, sHost), "home";
ns.scp(aTXTFiles, sHost), "home";
}
ns.exec(sScript, sHost, nThreads, ...aArgs);
nThreads = 0;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
else if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nScriptSize) {
let nThreadsDist = Math.floor(nFreeRAM / nScriptSize);
if (entry.serverName !== "home") {
ns.scp(aScriptFiles, sHost), "home";
ns.scp(aTXTFiles, sHost), "home";
}
ns.print("room for : " + nThreadsDist + " scripts");
ns.exec(sScript, sHost, nThreadsDist, ...aArgs);
nThreads -= nThreadsDist;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
});
}
/** @param {NS} ns */
export function GetCrimeStat(ns, sCrime, sStat) {
const sCrimeStatsFile = "CrimeStats.txt";
// Read the crime stats file
let aCrimeStatsList = JSON.parse(ns.read(sCrimeStatsFile));
// Search for the crime in the list
let oCrimeStats = aCrimeStatsList.find(crime => crime.name === sCrime);
// If the crime was not found, return undefined or an error message
if (!oCrimeStats) {
ns.tprint(`Crime "${sCrime}" not found.`);
return undefined;
}
// Check if the stat exists for the given crime
if (!(sStat in oCrimeStats)) {
ns.tprint(`Stat "${sStat}" not found for crime "${sCrime}".`);
return undefined;
}
// Return the value of the specified stat
return oCrimeStats[sStat];
}

View File

@@ -0,0 +1,70 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
let aPserv = ns.getPurchasedServers(); //array of purchased servers
let nPserv = aPserv.length; //amount of purchased servers we have
let nMoney = ns.getServerMoneyAvailable("home"); //player money
let nPrevSize = 4; //nPrevSize is 4 so the first server we will buy is 8
//Purchase Servers
//idea is to purchase the first server at 8 gb, next one at 16, next at 32 and so on
for (let i = 0; nPserv < i; i++) {
nMoney = ns.getServerMoneyAvailable("home"); //check money for each iteration
if (nMoney >= ns.getPurchasedServerCost(nPrevSize * 2)) { //can we afford next server?
const sServer = ns.purchaseServer(`pserv-${toString(i).padStart(2, "0")}`, nPrevSize * 2); //purchase server with name pserv- + 0i
ns.print(`Purchased ${sServer} for ${nPrevSize * 2}`); //print tail message that we purchased server
nPrevSize *= 2; //increase nPrevSize for next iteration
nPserv++ //increase number of purchased servers
}
else {
ns.print(`Insufficient funds for pserv-${toString(i).padStart(2, "0")} ${nMoney} / ${ns.getPurchasedServerCost(nPrevSize * 2)}`);
await ns.sleep(5000);
}
}
ns.tprint("for loop purchase complete");
//upgrade servers
//idea is to upgrade the lowest server to match the highest (which should be 2^20 in size)
let nCurrentRAM;
let nLowestRAM = 2 ** 21;
let nHighestRAM = 0;
let sLowestPserv;
let sHighestPserv;
let nTotalPServRAM = 0;
for (let i = 0; i < nPserv; i++) {
nCurrentRAM = ns.getServerMaxRam(aPserv[i]);
nTotalPServRAM += nCurrentRAM;
if (nCurrentRAM < nLowestRAM) {
nLowestRAM = nCurrentRAM
sLowestPserv = aPservers[i];
}
if (nCurrentRAM > nHighestRAM) {
nHighestRAM = nCurrentRAM
sHighestPserv = aPserv[i];
}
}
//sLowestPserv should now be the lowest server
//sHighestPserv should now be the highest server
for (let i = 0; sLowestPserv < sHighestPserv ; i++) {
if (nMoney >= ns.getPurchasedServerUpgradeCost(sLowestPserv, 2^20)){
ns.upgradePurchasedServer(sLowestPserv, 2^20);
}
}
}

View File

@@ -1,97 +0,0 @@
/** @param {NS} ns */
export async function main(ns, allServers) {
ns.tail();
await scanRecursiveWrapper(ns);
let currentHackingLevel = ns.getHackingLevel();
let currentArray = [];
let currentHop = "";
let serverRoutes = JSON.parse(ns.read("ServerRouteList.txt"));
let allPaths = getPaths(serverRoutes);
let checkAll = ns.args[0];
for (const entry of allPaths) {
for (const name of entry) {
if (ns.singularity.connect(name) === false) {
ns.tprint("Error when trying to connect to: " + currentHop);
return
}
if (ns.getServer(name).hostname === "CSEC" || ns.getServer(name).hostname === "avmnite-02h" || ns.getServer(name).hostname === "I.I.I.I" || ns.getServer(name).hostname === "run4theh111z" || ns.getServer(name).hostname === "The-Cave" || checkAll === true ) {
if (!ns.getServer(name).backdoorInstalled) {
if (ns.getServerRequiredHackingLevel(name) < currentHackingLevel && ns.hasRootAccess(name) === true) {
ns.print("Trying to backdoor " + name)
await ns.singularity.installBackdoor(name);
ns.print("Success on " + name)
}
} else { continue }
}
}
}
ns.singularity.connect("home");
}
function getPaths(obj, path = []) {
const paths = [];
for (const key in obj) {
const newPath = [...path, key];
paths.push(newPath);
if (typeof obj[key] === 'object' && obj[key] !== null) {
paths.push(...getPaths(obj[key], newPath));
}
}
return paths;
}
/** @param {NS} ns */
async function scanRecursiveWrapper(ns) {
ns.rm("ServerRouteList.txt");
const home = "home";
let serverRouteList = { home: {} };
let knownServers = [];
let unscanned = [];
unscanned.push(home);
knownServers.push(home);
while (unscanned.length > 0) {
let currentServer = unscanned.pop();
let currentChildren = ns.scan(currentServer).filter(element => !knownServers.includes(element));
knownServers = knownServers.concat(currentChildren);
let keyPath = findKeyPath(serverRouteList, currentServer);
let childrenObject = currentChildren.reduce((a, v) => ({ ...a, [v]: {} }), {});
writeValueToPath(serverRouteList, keyPath, childrenObject);
for (let i = 0; i < currentChildren.length; i++) {
let child = currentChildren[i];
unscanned.push(child);
}
}
ns.write("ServerRouteList.txt", JSON.stringify(serverRouteList), "w");
}
function findKeyPath(json, key) {
if (typeof json !== 'object' || json === null) {
return null;
}
if (key in json) {
return key;
}
for (const property in json) {
if (json.hasOwnProperty(property)) {
const path = findKeyPath(json[property], key);
if (path !== null) {
return property + '*' + path;
}
}
}
return null;
}
function writeValueToPath(json, path, value) {
const parts = path.split('*');
let currentObject = json;
for (let i = 0; i < parts.length - 1; i++) {
const part = parts[i];
if (currentObject[part] === undefined) {
currentObject[part] = {};
}
currentObject = currentObject[part];
}
currentObject[parts[parts.length - 1]] = value;
}

View File

@@ -1,161 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tprint(ns.codingcontract.getContractTypes())
let testcontract = ns.codingcontract.createDummyContract("Total Ways to Sum")
let contractType = ns.codingcontract.getContractType(testcontract);
ns.tprint(ns.codingcontract.getDescription(testcontract))
let n = ns.codingcontract.getData(testcontract);
ns.tprint("Data: " + n);
let answer = "";
if (contractType === "Find Largest Prime Factor") {
answer = largestPrimeFactor(n);
}
if (contractType === "Subarray with Maximum Sum") {
answer = SubarrayWithMaximumSum(ns, n)
}
if (contractType === "Total Ways to Sum") {
answer = TotalWaysToSum(ns, n)
}
ns.tprint(answer);
ns.tprint(ns.codingcontract.attempt(answer, testcontract));
}
/*
5:
4 1
3 2
3 1 1
2 2 1
2 1 1 1
1 1 1 1 1
6:
5 1
4 2
4 1 1
3 3
3 2 1
3 1 1 1
2 2 2
2 2 1 1
2 1 1 1 1
1 1 1 1 1 1
# Start with one position m filling it with the integers between 1 and target
# For each m, fill the next position n with integers between 1 and m
# Repeat as long as the sum is smaller than target.
# append all iterations to the Array and count
*/
function TotalWaysToSum(ns, target) {
let sumArray = [];
let inputArray = [];
let unfinishedArray = [];
let rollingSum = 0;
for (let i = 1; i < target; i++) {
inputArray.push([i]);
}
let z = 1
while (inputArray.length > 0) {
z++
inputArray.forEach((element) => {
rollingSum = element.reduce((a, b) => a + b, 0);
if (rollingSum === target) {
sumArray.push(element)
} else {
for (let k = 1; k <= element[element.length-1] && k <= target - rollingSum; k++) {
unfinishedArray.push(element.concat([k]))
}
}
}
)
inputArray = unfinishedArray;
}
ns.tprint("Target: " +target)
ns.tprint("Length: " + sumArray.length)
return sumArray.length
}
function SubarrayWithMaximumSum(ns, givenArray) {
let arrayLength = givenArray.length;
let maxSum = -10000;
let runningSum = 0;
for (let i = 1; i <= arrayLength; i++) {
for (let j = 0; j <= arrayLength - i; j++) {
runningSum = eval(givenArray.slice(j, i + j).join('+'));
//ns.tprint("i: "+i+ " j: "+ j + " Array: "+givenArray.slice(j,i+j)+ " eval: "+ givenArray.slice(j,i+j).join('+')+"runningSum: "+runningSum);
if (maxSum < runningSum) { maxSum = runningSum };
}
}
return maxSum
}
function FindLargestPrimeFactor(number) {
let factor = 2;
while (factor * factor <= number) {
if (number % factor === 0) {
number /= factor;
} else {
factor++
}
}
return number;
}
/*
function FindLargestPrimeFactor(n) {
let x = Math.ceil(Math.random()*10);
let y = x;
let d = 1;
while (d === 1) {
x = g(x, n);
y = g(g(y, n), n)
d = gcd(n, Math.abs(x - y))
//ns.tprint("x:" + x + " y: " + y + " d: " + d)
}
if (d === n) {
return ("failure")
}
else {
return (d)
}
}
function g(x, n) {
return (x * x) % n
}
function gcd(a,b) {
a = Math.abs(a);
b = Math.abs(b);
if (b > a) {var temp = a; a = b; b = temp;}
while (true) {
if (b == 0) return a;
a %= b;
if (a == 0) return b;
b %= a;
}
}
function gcd(a, b) {
if (!b) {
return a;
}
return gcd(b, a % b);
}
*/

View File

@@ -1,161 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tprint(ns.codingcontract.getContractTypes())
let testcontract = ns.codingcontract.createDummyContract("Total Ways to Sum")
let contractType = ns.codingcontract.getContractType(testcontract);
ns.tprint(ns.codingcontract.getDescription(testcontract))
let n = ns.codingcontract.getData(testcontract);
ns.tprint("Data: " + n);
let answer = "";
if (contractType === "Find Largest Prime Factor") {
answer = largestPrimeFactor(n);
}
if (contractType === "Subarray with Maximum Sum") {
answer = SubarrayWithMaximumSum(ns, n)
}
if (contractType === "Total Ways to Sum") {
answer = TotalWaysToSum(ns, n)
}
ns.tprint(answer);
ns.tprint(ns.codingcontract.attempt(answer, testcontract));
}
/*
5:
4 1
3 2
3 1 1
2 2 1
2 1 1 1
1 1 1 1 1
6:
5 1
4 2
4 1 1
3 3
3 2 1
3 1 1 1
2 2 2
2 2 1 1
2 1 1 1 1
1 1 1 1 1 1
# Start with one position m filling it with the integers between 1 and target
# For each m, fill the next position n with integers between 1 and m
# Repeat as long as the sum is smaller than target.
# append all iterations to the Array and count
*/
function TotalWaysToSum(ns, target) {
let sumArray = [];
let inputArray = [];
let unfinishedArray = [];
let rollingSum = 0;
for (let i = 1; i < target; i++) {
inputArray.push([i]);
}
let z = 1
while (inputArray.length > 0) {
z++
inputArray.forEach((element) => {
rollingSum = element.reduce((a, b) => a + b, 0);
if (rollingSum === target) {
sumArray.push(element)
} else {
for (let k = 1; k <= element[element.length-1] && k <= target - rollingSum; k++) {
unfinishedArray.push(element.concat([k]))
}
}
}
)
inputArray = unfinishedArray;
}
ns.tprint("Target: " +target)
ns.tprint("Length: " + sumArray.length)
return sumArray.length
}
function SubarrayWithMaximumSum(ns, givenArray) {
let arrayLength = givenArray.length;
let maxSum = -10000;
let runningSum = 0;
for (let i = 1; i <= arrayLength; i++) {
for (let j = 0; j <= arrayLength - i; j++) {
runningSum = eval(givenArray.slice(j, i + j).join('+'));
//ns.tprint("i: "+i+ " j: "+ j + " Array: "+givenArray.slice(j,i+j)+ " eval: "+ givenArray.slice(j,i+j).join('+')+"runningSum: "+runningSum);
if (maxSum < runningSum) { maxSum = runningSum };
}
}
return maxSum
}
function FindLargestPrimeFactor(number) {
let factor = 2;
while (factor * factor <= number) {
if (number % factor === 0) {
number /= factor;
} else {
factor++
}
}
return number;
}
/*
function FindLargestPrimeFactor(n) {
let x = Math.ceil(Math.random()*10);
let y = x;
let d = 1;
while (d === 1) {
x = g(x, n);
y = g(g(y, n), n)
d = gcd(n, Math.abs(x - y))
//ns.tprint("x:" + x + " y: " + y + " d: " + d)
}
if (d === n) {
return ("failure")
}
else {
return (d)
}
}
function g(x, n) {
return (x * x) % n
}
function gcd(a,b) {
a = Math.abs(a);
b = Math.abs(b);
if (b > a) {var temp = a; a = b; b = temp;}
while (true) {
if (b == 0) return a;
a %= b;
if (a == 0) return b;
b %= a;
}
}
function gcd(a, b) {
if (!b) {
return a;
}
return gcd(b, a % b);
}
*/

View File

@@ -1,14 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"];
let corpName = "AgraNeo";
//ns.tprint(ns.corporation.getConstants())
//ns.corporation.getMaterial();
//ns.corporation.buyMaterial();
for (let city of cities) {
await ns.run("/corp/Smart.js",1,corpName,city);
await ns.tprint(ns.run("/corp/UpgradeOffice.js",1,corpName,city));
await ns.sleep(1000)
}
}

View File

@@ -1,8 +0,0 @@
import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript } from "/RamsesUtils.js";
/** @param {NS} ns */
export async function main(ns) {
let cracks = {};
cracks = getCracks(ns);
crackingAndRooting(ns, cracks, "", false);
}

View File

@@ -1,278 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tprint("This is just a function library, it doesn't do anything.");
}
/** @param {NS} ns */
export function getCracks(ns) {
let cracks = {};
if (ns.fileExists("BruteSSH.exe", "home")) {
cracks["BruteSSH.exe"] = ns.brutessh;
};
if (ns.fileExists("FTPCrack.exe", "home")) {
cracks["FTPCrack.exe"] = ns.ftpcrack;
};
if (ns.fileExists("relaySMTP.exe", "home")) {
cracks["relaySMTP.exe"] = ns.relaysmtp;
};
if (ns.fileExists("HTTPWorm.exe", "home")) {
cracks["HTTPWorm.exe"] = ns.httpworm;
};
if (ns.fileExists("SQLInject.exe", "home")) {
cracks["SQLInject.exe"] = ns.sqlinject;
};
return cracks;
}
/** @param {NS} ns */
export function scanServerList(ns) {
const home = "home";
let serverList = {};
let unscanned = [];
unscanned.push(home);
while (unscanned.length > 0) {
let currentServer = unscanned.pop();
if (!serverList[currentServer]) {
let maxRam = ns.getServerMaxRam(currentServer);
let minPorts = ns.getServerNumPortsRequired(currentServer);
let minSecLevel = ns.getServerMinSecurityLevel(currentServer);
let minHackLevel = ns.getServerRequiredHackingLevel(currentServer);
let rootAccess = ns.hasRootAccess(currentServer);
let serverMoney = ns.getServerMaxMoney(currentServer);
let serverFiles = ns.ls(currentServer);
let skillFactor = (2.5 * minHackLevel * minSecLevel + 500) / (ns.getHackingLevel() + 50);
let compareTimeFactor = serverMoney / skillFactor / 10e7;
serverList[currentServer] =
{
serverName: currentServer,
maxRam: maxRam,
maxMoney: serverMoney,
minSec: minSecLevel,
minPorts: minPorts,
minHackLvl: minHackLevel,
rootAccess: rootAccess,
factorMoneyPerTime: compareTimeFactor,
openPorts: 0,
serverFiles: serverFiles,
};
let neighbours = ns.scan(currentServer);
for (let i = 0; i < neighbours.length; i++) {
let neighbour = neighbours[i];
if (serverList[neighbour]) {
continue
}
unscanned.push(neighbour);
}
}
}
ns.write("serverList.txt", JSON.stringify(serverList), "w");
}
/** @param {NS} ns */
export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTargetOverride) {
if (!ns.fileExists("serverList.txt", "home")) scanServerList();
let serverList = JSON.parse(ns.read("serverList.txt"));
let bestEntry = null;
let compareTime = 0;
for (const [name, entry] of Object.entries(serverList)) {
if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl < currentHackLevel) {
if (entry.factorMoneyPerTime > compareTime) {
compareTime = entry.factorMoneyPerTime;
bestEntry = name;
}
}
}
if (manualTargetOverride.length > 0) {
bestEntry = manualTargetOverride;
}
ns.write("bestTarget.txt", JSON.stringify(serverList[bestEntry]), "w");
}
/** @param {NS} ns */
export function crackingAndRooting(ns, cracks, funnyScript, copy) {
if (!ns.fileExists("serverList.txt", "home")) scanServerList();
let serverList = JSON.parse(ns.read("serverList.txt"));
for (const [name, entry] of Object.entries(serverList)) {
let cracked = false;
let openPorts = serverList[name].openPorts || 0;
if (entry.minPorts === 0 || (entry.minPorts > openPorts && entry.minPorts <= Object.keys(cracks).length)) {
for (let k = 0; k < entry.minPorts; k++) {
cracks[Object.keys(cracks)[k]](name);
serverList[name].openPorts = k;
}
cracked = true;
}
if (!ns.hasRootAccess(name) && cracked === true) {
ns.nuke(name);
if (ns.hasRootAccess(name)) {
serverList[name].rootAccess = true;
if (serverList[name].maxRam > 0 && copy === true) {
copyAndRunScript(ns, funnyScript, name);
}
}
}
ns.write("serverList.txt", JSON.stringify(serverList), "w");
}
ns.tprint("Cracking and rooting done");
}
/** @param {NS} ns */
export function copyAndRunScript(ns, funnyScript, currentServer) {
// change to run for one specific server with bestTarget from file
//let minRam = ns.getScriptRam(funnyScript);
let bestTarget = JSON.parse(ns.read("bestTarget.txt"));
let name = currentServer;
let serverList = JSON.parse(ns.read("serverList.txt"));
ns.print(name);
if (serverList[name].rootAccess === true && serverList[bestTarget.serverName].rootAccess === true) {
if (name !== "home") {
ns.print("killed threads on: " + name + ns.killall(name, true));
} else {
ns.print("killed threads on: " + name + ns.scriptKill(funnyScript[0], name));
};
//move script and run
if (serverList[name].maxRam > 0) {
ns.scp(funnyScript, name, "home");
let maxProcesses = 1;
if (serverList[name].maxRam >= 8) {
maxProcesses = Math.max(Math.floor((serverList[name].maxRam) / 8), 1);
} else {
maxProcesses = 1
};
for (let n = 1; n <= maxProcesses; n++) {
ns.exec(funnyScript[0], name, 1, bestTarget.serverName);
}
/*let maxThreads = 0;
if (name === "home") {
maxThreads = Math.floor((serverList[name].maxRam - ns.getServerUsedRam(name) - 32) / minRam);
ns.print(name + " " + maxThreads);
} else {
ns.print(name);
maxThreads = Math.floor(serverList[name].maxRam / minRam);
ns.print(name + " " + maxThreads);
};
while (maxThreads > 0) {
let threadsToAssign = maxThreads < 500 ? maxThreads : 500;
if (ns.exec(funnyScript, name, threadsToAssign, bestTarget.serverName, serverList[bestTarget.serverName].minSec, serverList[bestTarget.serverName].maxMoney, JSON.stringify(serverList[bestTarget.serverName])) !== 0) {
ns.print("Executing script on: " + name + " with: " + threadsToAssign + " threads out of " + maxThreads + " total threads");
maxThreads = maxThreads - threadsToAssign;
} else {
ns.tprint("Error running script on: " + name);
maxThreads = -1;
};
}*/
}
}
}
/** @param {NS} ns */
export async function purchaseAndUpgradeServers(ns) {
ns.disableLog("sleep");
ns.disableLog("getServerMoneyAvailable");
ns.disableLog("getServerMaxRam");
let maxPurchasedServers = ns.getPurchasedServerLimit();
let purchasedServers = [];
let count = listPurchasedServers(ns).length;
let currentMoney = 0;
let serverList = {};
while (count < maxPurchasedServers) {
purchasedServers = listPurchasedServers(ns);
currentMoney = ns.getServerMoneyAvailable("home");
let targetRamInitial = 16;
if (ns.getPurchasedServerCost(targetRamInitial) < currentMoney) {
let hostname = ns.purchaseServer("pserv-" + purchasedServers.length, 16);
count = listPurchasedServers(ns).length;
serverList = JSON.parse(ns.read("serverList.txt"));
serverList[hostname] = {
serverName: hostname,
maxRam: 16,
maxMoney: 0,
minSec: 0,
minPorts: 5,
minHackLvl: 1,
rootAccess: true,
factorMoneyPerTime: 99999999,
openPorts: 0,
};
ns.write("serverList.txt", JSON.stringify(serverList), "w");
continue
} else {
await ns.sleep(5000);
}
}
let i = 5;
while (i < 21) {
let targetRam = 2 ** i;
purchasedServers = listPurchasedServers(ns);
for (let currentServer of purchasedServers) {
currentMoney = ns.getServerMoneyAvailable("home");
if (ns.getServerMaxRam(currentServer) < targetRam && ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) {
if (ns.upgradePurchasedServer(currentServer, targetRam)) {
ns.print(currentServer + " upgraded to " + targetRam + " GB RAM");
serverList = JSON.parse(ns.read("serverList.txt"));
serverList[currentServer].maxRam = targetRam;
ns.write("serverList.txt", JSON.stringify(serverList), "w");
}
} else {
await ns.sleep(5000);
continue
};
}
++i;
}
ns.tprint("Extiting purchaseServers script!")
}
/** @param {NS} ns */
function listPurchasedServers(ns) {
return ns.getPurchasedServers();
}
/** @param {NS} ns */
export async function runControllerOnPserv(ns) {
let purchasedServers = listPurchasedServers(ns);
let nPID = 0;
nPID = ns.exec("S2controller.js", "home");
ns.tprint("Started S2controller.js on " + "home" + " with PID " + nPID)
for (let currentServer of purchasedServers) {
ns.scp(["S2tGrow.js", "S2tWeaken.js", "S2tHack.js", "S2controller.js", "S2utils.js"], currentServer, "home");
nPID = ns.exec("S2controller.js", currentServer);
if (nPID > 0) {
ns.tprint("Started S2controller.js on " + currentServer + " with PID " + nPID)
}
}
}
/** @param {NS} ns */
export async function backdoor(ns) {
let serverList = JSON.parse(ns.read("serverList.txt"));
let lasthackingLevel = 0;
let currentHackingLevel = 0;
while (true) {
currentHackingLevel = ns.getHackingLevel();
if (currentHackingLevel > lasthackingLevel) {
lasthackingLevel = currentHackingLevel;
for (const [name, entry] of Object.entries(serverList)) {
if (entry.minHackLvl <= lasthackingLevel && entry.hasBackdoor !== true) {
ns.singularity.connect(name);
await ns.singularity.installBackdoor();
ns.singularity.connect("home");
serverList[name].hasBackdoor = true;
ns.tprint("Backdoor on: " + name);
}
}
ns.write("serverList.txt", JSON.stringify(serverList), "w");
} else {
await ns.sleep(30000)
};
}
}

View File

@@ -1,491 +0,0 @@
/*
Welcome to part 4. A continuous batcher is a major hurdle compared to everything we've done so far. The number
and complexity of the challenges increases drastically when trying to keep everything running indefinitely.
With luck, the overengineering we've done so far will have well prepared us for the challenges of a periodic
batcher.
Technically, I use quite a few JIT techniques in this batcher, but I don't consider it a true JIT batcher
as it doesn't take full advantage of the potential RAM efficiency. Instead, I favor simpler logic, while still
allowing the batcher to make certain adjustments if it needs to.
When it comes to continuous batchers, performance is king. We're going to aim for 5ms spacing as we have
throughout this guide so far, but there's a lot we need to do in those 5ms. As such, we need to make sure that
we choose which operations to do carefully, as well as when to do them and how to make sure they are as fast
as we can make them.
*/
// One new utility. A custom data structure for managing our schedule. You can see the details in utils.js
import { getServers, copyScripts, checkTarget, isPrepped, prep, Deque } from "/S4utils.js";
const TYPES = ["hack", "weaken1", "grow", "weaken2"];
const WORKERS = ["S4tHack.js", "S4tWeaken.js", "S4tGrow.js"];
const SCRIPTS = { hack: "S4tHack.js", weaken1: "S4tWeaken.js", grow: "S4tGrow.js", weaken2: "S4tWeaken.js" };
const COSTS = { hack: 1.7, weaken1: 1.75, grow: 1.75, weaken2: 1.75 };
// const OFFSETS = { hack: 0, weaken1: 1, grow: 2, weaken2: 3 };
// A new optional constant. The RamNet will attempt to reserve this much ram at home.
// You can set it to 0 if you don't want to reserve anything, and setting it too high will just reserve as much as possible.
const RESERVED_HOME_RAM = 0;
// A brand new class to help keep our increasingly complex logic organized.
class ContinuousBatcher {
#ns; // The ns object. Stored as a class variable to save me the trouble of passing it all the time.
// The usual data we've grown familiar with by now.
#metrics;
#ramNet;
#target;
#schedule;
#dataPort;
#batchCount = 0;
#desyncs = 0; // This is mostly used for logging purposes, since the batcher is self-correcting.
// A capital M Map. We'll use this to keep track of active jobs.
#running = new Map();
constructor(ns, metrics, ramNet) {
this.#ns = ns;
this.#metrics = metrics;
this.#ramNet = ramNet;
this.#target = metrics.target;
this.#dataPort = ns.getPortHandle(ns.pid);
// Seeding the first ending time.
this.#metrics.end = Date.now() + metrics.wTime - metrics.spacer;
// The new schedule I promised. It's a double-ended queue, but we'll mostly just be using it as a normal queue.
// It has a static size, so we make sure it can accomodate all of our jobs.
this.#schedule = new Deque(metrics.depth * 4);
}
// This is a function that can schedule a given number of batches.
// With no arguments, it just fills up the queue.
scheduleBatches(batches = this.#metrics.depth) {
while (this.#schedule.size < batches * 4) {
++this.#batchCount;
for (const type of TYPES) {
this.#metrics.end += this.#metrics.spacer;
const job = new Job(type, this.#metrics, this.#batchCount);
/*
We don't actually error out if a job can't be assigned anymore. Instead, we just assign as much
as we can. If it desyncs, the logic will correct it, and if a weaken2 gets cancelled then the actual
depth will naturally decrease below the target depth. Not a perfect fix, but better than breaking.
*/
if (!this.#ramNet.assign(job)) {
this.#ns.tprint(`WARN: Insufficient RAM to assign ${job.type}: ${job.batch}.`);
continue;
}
this.#schedule.push(job);
}
}
}
// The function for deploying jobs. Very similar to the code from our shotgun batcher with some minor changes.
async deploy() {
// The for loop is replaced by a while loop, since our Deque isn't iterable.
while (!this.#schedule.isEmpty()) {
const job = this.#schedule.shift();
job.end += this.#metrics.delay;
const jobPid = this.#ns.exec(SCRIPTS[job.type], job.server, { threads: job.threads, temporary: true }, JSON.stringify(job));
if (!jobPid) throw new Error(`Unable to deploy ${job.type}`);
const tPort = this.#ns.getPortHandle(jobPid);
// We save the pid for later.
job.pid = jobPid;
await tPort.nextWrite();
// Jobs can be late as long as the delay won't cause collisions.
this.#metrics.delay += Math.max(Math.ceil(tPort.read()) - this.#metrics.spacer, 0);
this.#running.set(job.id, job);
}
// After the loop, we adjust future job ends to account for the delay, then discard it.
this.#metrics.end += this.#metrics.delay;
this.#metrics.delay = 0;
}
// Our old timeout function is now a proper function of its own. A few extra baubles in the log, but nothing exciting.
/** @param {NS} ns */
log() {
const ns = this.#ns;
const metrics = this.#metrics;
const ramNet = this.#ramNet;
ns.clearLog();
ns.print(`Hacking ~\$${ns.formatNumber(metrics.maxMoney * metrics.greed * metrics.chance / (4 * metrics.spacer) * 1000)}/s from ${metrics.target}`);
ns.print(`Status: ${isPrepped(ns, this.#target) ? "Prepped" : "Desynced"}`);
ns.print(`Security: +${metrics.minSec - metrics.sec}`);
ns.print(`Money: \$${ns.formatNumber(metrics.money, 2)}/${ns.formatNumber(metrics.maxMoney, 2)}`);
ns.print(`Greed: ${Math.floor(metrics.greed * 1000) / 10}%`);
ns.print(`Ram available: ${ns.formatRam(ramNet.totalRam)}/${ns.formatRam(ramNet.maxRam)}`);
ns.print(`Active jobs: ${this.#running.size}/${metrics.depth * 4}`);
// You'll see what this line's about in a moment.
if (this.#desyncs) ns.print(`Hacks cancelled by desync: ${this.#desyncs}`);
}
// The core loop of our batcher logic. Quite lean with everything neatly divided into functions, but there's still
// plenty going on here.
async run() {
// First we do some initial setup, this is essentially firing off a shotgun blast to get us started.
const dataPort = this.#dataPort;
this.scheduleBatches();
await this.deploy();
await this.#ns.sleep(0); // This is probably pointless. I forget why I put it here.
this.log();
while (true) {
// Wait for the nextWrite, as usual.
await dataPort.nextWrite();
// Sometimes there's a delay and more than one job writes to the port at once.
// We make sure to handle it all before we move on.
while (!dataPort.empty()) {
// Workers now report unique identifiers (type + batchnumber) used to find them on the map.
const data = dataPort.read();
// Free up the ram, them remove them from the active list.
// The check handles a corner case where a hack gets "cancelled" after it's already finished.
if (this.#running.has(data)) {
this.#ramNet.finish(this.#running.get(data));
this.#running.delete(data);
}
// If it's a W2, we've got an opening to do some work.
if (data.startsWith("weaken2")) {
// Recalculate times. Threads too, but only if prepped (the logic is in the function itself).
this.#metrics.calculate(this.#ns);
/*
This is probably the most JIT-like aspect of the entire batcher. If the server isn't prepped, then
we cancel the next hack to let the server fix itself. Between this and the extra 1% grow threads, level
ups are completely handled. Rapid level ups can lead to a lot of lost jobs, but eventually the program
stabilizes.
There are probably more efficient ways to do this. Heck, even this solution could be optimized better,
but for now, this is an adequate demonstration of a reasonable non-formulas solution to the level up
problem. It also lets us dip our toes into JIT logic in preparation for the final part.
*/
if (!isPrepped(this.#ns, this.#target)) {
const id = "hack" + (parseInt(data.slice(7)) + 1);
const cancel = this.#running.get(id);
// Just in case the hack was already aborted somehow.
if (cancel) {
this.#ramNet.finish(cancel);
this.#ns.kill(cancel.pid);
this.#running.delete(id);
++this.#desyncs; // Just to keep track of how much we've lost keeping things prepped.
}
}
// Then of course we just schedule and deploy a new batch.
this.scheduleBatches(1);
await this.deploy();
this.log();
}
}
}
}
}
/*
Our poor "main" function isn't much more than a kickstart for our new batcher object. It's a bit weird having
it wedged between objects like this, but I wanted to have the new functionality up at the top since most of the
remaining code hasn't changed much. I'll comment the changes anyway.
*/
/** @param {NS} ns */
export async function main(ns) {
ns.disableLog("ALL");
ns.tail();
/*
This commented out code is for a debugging tool that centralizes logs from the worker scripts into one place.
It's main advantage is the ability to write txt logs to file, which can be perused later to track down errors.
You can uncomment it if you'd like to see a live stream of workers finishing without flooding the terminal.
If you do, make sure to search the file for -LOGGING and uncomment all relevant lines.
*/
// if (ns.isRunning("S4logHelper.js", "home")) ns.kill("S4logHelper.js", "home");
// const logPort = ns.exec("S4logHelper.js", "home");
// ns.atExit(() => ns.closeTail(logPort));
// Setup is mostly the same.
const dataPort = ns.getPortHandle(ns.pid);
dataPort.clear();
let target = ns.args[0] ? ns.args[0] : "n00dles";
while (true) {
const servers = getServers(ns, (server) => {
if (!ns.args[0]) target = checkTarget(ns, server, target, ns.fileExists("Formulas.exe", "home"));
copyScripts(ns, server, WORKERS, true);
return ns.hasRootAccess(server);
});
const ramNet = new RamNet(ns, servers);
const metrics = new Metrics(ns, target);
// metrics.log = logPort; // Uncomment for -LOGGING.
if (!isPrepped(ns, target)) await prep(ns, metrics, ramNet);
ns.clearLog();
ns.print("Optimizing. This may take a few seconds...");
// Optimizer has changed again. Back to being synchronous, since the performance is much better.
optimizePeriodic(ns, metrics, ramNet);
metrics.calculate(ns);
// Create and run our batcher.
const batcher = new ContinuousBatcher(ns, metrics, ramNet);
await batcher.run();
/*
You might be wondering why I put this in a while loop and then just return here. The simple answer is that
it's because this is meant to be run in a loop, but I didn't implement the logic for it. This version of the
batcher is completely static once created. It sticks to a single greed value, and doesn't update if more
RAM becomes available.
In a future version, you'd want some logic to allow the batcher to choose new targets, update its available RAM,
and create new batchers during runtime. For now, that's outside the scope of this guide, but consider this loop
as a sign of what could be.
*/
return;
}
}
// The Job class, lean as it is, remains mostly unchanged. I got rid of the server argument since I wasn't using it
// and added a batch number instead.
class Job {
constructor(type, metrics, batch) {
this.type = type;
// this.end = metrics.ends[type];
this.end = metrics.end;
this.time = metrics.times[type];
this.target = metrics.target;
this.threads = metrics.threads[type];
this.cost = this.threads * COSTS[type];
this.server = "none";
this.report = true;
this.port = metrics.port;
this.batch = batch;
// The future is now. The status and id are used for interacting with the Deque and Map in our batcher class.
this.status = "active";
this.id = type + batch;
// this.log = metrics.log; // -LOGGING
}
}
// The only change to the metrics class is the calculate function skipping threadcounts if the server isn't prepped.
/** @param {NS} ns */
class Metrics {
constructor(ns, server) {
this.target = server;
this.maxMoney = ns.getServerMaxMoney(server);
this.money = Math.max(ns.getServerMoneyAvailable(server), 1);
this.minSec = ns.getServerMinSecurityLevel(server);
this.sec = ns.getServerSecurityLevel(server);
this.prepped = isPrepped(ns, server);
this.chance = 0;
this.wTime = 0;
this.delay = 0;
this.spacer = 5;
this.greed = 0.01;
this.depth = 0; // The number of concurrent batches to run. Set by the optimizer.
this.times = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 };
this.end = 0; // Slight change for the new timing. The old way in commented out in case I switch back later.
// this.ends = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 };
this.threads = { hack: 0, weaken1: 0, grow: 0, weaken2: 0 };
this.port = ns.pid;
}
calculate(ns, greed = this.greed) {
const server = this.target;
const maxMoney = this.maxMoney;
this.money = ns.getServerMoneyAvailable(server);
this.sec = ns.getServerSecurityLevel(server);
this.wTime = ns.getWeakenTime(server);
this.times.weaken1 = this.wTime;
this.times.weaken2 = this.wTime;
this.times.hack = this.wTime / 4;
this.times.grow = this.wTime * 0.8;
// this.depth = this.wTime / this.spacer * 4;
if (isPrepped(ns, server)) { // The only change.
const hPercent = ns.hackAnalyze(server);
const amount = maxMoney * greed;
const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(server, amount)), 1);
const tGreed = hPercent * hThreads;
const gThreads = Math.ceil(ns.growthAnalyze(server, maxMoney / (maxMoney - maxMoney * tGreed)) * 1.01);
this.threads.weaken1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1);
this.threads.weaken2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1);
this.threads.hack = hThreads;
this.threads.grow = gThreads;
this.chance = ns.hackAnalyzeChance(server);
}
}
}
// A few minor edits here. An unused "simulation" mode, and reserved RAM on home.
/** @param {NS} ns */
class RamNet {
#blocks = [];
#minBlockSize = Infinity;
#maxBlockSize = 0;
#totalRam = 0;
#prepThreads = 0;
#maxRam = 0;
#index = new Map();
// Simulate mode ignores running scripts. Can be used to make calculations while the batcher is operating.
constructor(ns, servers, simulate = false) {
for (const server of servers) {
if (ns.hasRootAccess(server)) {
const maxRam = ns.getServerMaxRam(server);
// Save some extra ram on home. Clamp used ram to maxRam to prevent negative numbers.
const reserved = (server === "home") ? RESERVED_HOME_RAM : 0;
const used = Math.min((simulate ? 0 : ns.getServerUsedRam(server)) + reserved, maxRam);
const ram = maxRam - used;
if (maxRam > 0) {
const block = { server: server, ram: ram };
this.#blocks.push(block);
if (ram < this.#minBlockSize) this.#minBlockSize = ram;
if (ram > this.#maxBlockSize) this.#maxBlockSize = ram;
this.#totalRam += ram;
this.#maxRam += maxRam;
this.#prepThreads += Math.floor(ram / 1.75);
}
}
}
this.#sort();
this.#blocks.forEach((block, index) => this.#index.set(block.server, index));
}
#sort() {
this.#blocks.sort((x, y) => {
if (x.server === "home") return 1;
if (y.server === "home") return -1;
return x.ram - y.ram;
});
}
get totalRam() {
return this.#totalRam;
}
get maxRam() {
return this.#maxRam;
}
get maxBlockSize() {
return this.#maxBlockSize;
}
get prepThreads() {
return this.#prepThreads;
}
getBlock(server) {
if (this.#index.has(server)) {
return this.#blocks[this.#index.get(server)];
} else {
throw new Error(`Server ${server} not found in RamNet.`);
}
}
assign(job) {
const block = this.#blocks.find(block => block.ram >= job.cost);
if (block) {
job.server = block.server;
block.ram -= job.cost;
this.#totalRam -= job.cost;
return true;
} else return false;
}
finish(job) {
const block = this.getBlock(job.server);
block.ram += job.cost;
this.#totalRam += job.cost;
}
cloneBlocks() {
return this.#blocks.map(block => ({ ...block }));
}
printBlocks(ns) {
for (const block of this.#blocks) ns.print(block);
}
testThreads(threadCosts) {
const pRam = this.cloneBlocks();
let batches = 0;
let found = true;
while (found) {
for (const cost of threadCosts) {
found = false;
const block = pRam.find(block => block.ram >= cost);
if (block) {
block.ram -= cost;
found = true;
} else break;
}
if (found) batches++;
}
return batches;
}
}
// Quite a bit has changed in this one. It's back to being synchronous, though it can still take a while.
/**
* @param {NS} ns
* @param {Metrics} metrics
* @param {RamNet} ramNet
*/
function optimizePeriodic(ns, metrics, ramNet) {
const maxThreads = ramNet.maxBlockSize / 1.75;
const maxMoney = metrics.maxMoney;
const hPercent = ns.hackAnalyze(metrics.target);
const wTime = ns.getWeakenTime(metrics.target);
const minGreed = 0.001;
const maxSpacer = wTime; // This is more of an infinite loop safety net than anything.
const stepValue = 0.01;
let greed = 0.95; // Capping greed a bit lower. I don't have a compelling reason for this.
let spacer = metrics.spacer; // We'll be adjusting the spacer in low ram conditions to allow smaller depths.
while (greed > minGreed && spacer < maxSpacer) {
// We calculate a max depth based on the spacer, then add one as a buffer.
const depth = Math.ceil(wTime / (4 * spacer)) + 1;
const amount = maxMoney * greed;
const hThreads = Math.max(Math.floor(ns.hackAnalyzeThreads(metrics.target, amount)), 1);
const tGreed = hPercent * hThreads;
const gThreads = Math.ceil(ns.growthAnalyze(metrics.target, maxMoney / (maxMoney - maxMoney * tGreed)) * 1.01);
if (Math.max(hThreads, gThreads) <= maxThreads) {
const wThreads1 = Math.max(Math.ceil(hThreads * 0.002 / 0.05), 1);
const wThreads2 = Math.max(Math.ceil(gThreads * 0.004 / 0.05), 1);
const threadCosts = [hThreads * 1.7, wThreads1 * 1.75, gThreads * 1.75, wThreads2 * 1.75];
// Glad I kept these, they turned out to be useful after all. When trying to hit target depth,
// checking that there's actually enough theoretical ram to fit them is a massive boost to performance.
const totalCost = threadCosts.reduce((t, c) => t + c) * depth;
if (totalCost < ramNet.totalRam) {
// Double check that we can actually fit our threads into ram, then set our metrics and return.
const batchCount = ramNet.testThreads(threadCosts);
if (batchCount >= depth) {
metrics.spacer = spacer;
metrics.greed = greed;
metrics.depth = depth;
return
}
}
}
// await ns.sleep(0); // Uncomment and make the function async if you don't like the freeze on startup.
// Decrement greed until we hit the minimum, then reset and increment spacer. We'll find a valid configuration eventually.
greed -= stepValue;
if (greed < minGreed && spacer < maxSpacer) {
greed = 0.99;
++spacer;
}
}
throw new Error("Not enough ram to run even a single batch. Something has gone seriously wrong.");
}

View File

@@ -1,42 +0,0 @@
/*
This script is completely unchanged from the last part. As a note, if you find that saves are taking a very long time
it may help to disable txt logging when you aren't actively debugging. The log files generated by this script
are quite big even when it's erasing the data on each new instance.
*/
/** @param {NS} ns */
export async function main(ns) {
const logFile = "S4log.txt";
ns.clear(logFile); // Clear the previous log for each instance.
ns.disableLog("ALL");
ns.tail();
ns.moveTail(200, 200); // Move it out of the way so it doesn't cover up the controller.
const logPort = ns.getPortHandle(ns.pid);
logPort.clear();
// Pretty simple. Just wait until something writes to the log and save the info.
// Writes to its own console as well as a text file.
let max = 0;
let count = 0;
let total = 0;
let errors = 0;
while (true) {
await logPort.nextWrite();
do {
const data = logPort.read();
// if (data > max) max = data;
// if (data > 5) ++errors;
// total += data;
// ++count;
// ns.clearLog();
// ns.print(`Max desync: ${max}`);
// ns.print(`Average desync: ${total / count}`);
// ns.print(`Errors: ${errors}`);
// if (data.startsWith("WARN")) ns.print(data);
ns.print(data);
// ns.write(logFile, data); // Comment this line out to disable txt logging.
} while (!logPort.empty());
}
}

View File

@@ -1,30 +0,0 @@
/*
A pretty big change this time. Well, big for workers anyway. I've tightened up the delay calculations
to be as perfect as I can get them. Full comments in weaken.js as usual.
*/
/** @param {NS} ns */
export async function main(ns) {
const start = performance.now();
const port = ns.getPortHandle(ns.pid);
const job = JSON.parse(ns.args[0]);
let tDelay = 0;
let delay = job.end - job.time - Date.now();
if (delay < 0) {
ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`);
tDelay = -delay
delay = 0;
}
const promise = ns.grow(job.target, { additionalMsec: delay });
tDelay += performance.now() - start;
port.write(tDelay);
await promise;
ns.atExit(() => {
const end = Date.now();
if (job.report) ns.writePort(job.port, job.type + job.batch);
// Uncomment one of these if you want to log completed jobs. Make sure to uncomment the appropriate lines in the controller as well.
// ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`);
// ns.writePort(job.log, `Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end + tDelay).toString().slice(-6)}\n`);
});
}

View File

@@ -1,30 +0,0 @@
/*
A pretty big change this time. Well, big for workers anyway. I've tightened up the delay calculations
to be as perfect as I can get them. Full comments in weaken.js as usual.
*/
/** @param {NS} ns */
export async function main(ns) {
const start = performance.now();
const port = ns.getPortHandle(ns.pid);
const job = JSON.parse(ns.args[0]);
let tDelay = 0;
let delay = job.end - job.time - Date.now();
if (delay < 0) {
ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`);
tDelay = -delay
delay = 0;
}
const promise = ns.hack(job.target, { additionalMsec: delay });
tDelay += performance.now() - start;
port.write(tDelay);
await promise;
ns.atExit(() => {
const end = Date.now();
if (job.report) ns.writePort(job.port, job.type + job.batch);
// Uncomment one of these if you want to log completed jobs. Make sure to uncomment the appropriate lines in the controller as well.
// ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`);
// ns.writePort(job.log, `Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end + tDelay).toString().slice(-6)}\n`);
});
}

View File

@@ -1,41 +0,0 @@
/*
A pretty big change this time. Well, big for workers anyway. I've tightened up the delay calculations
to be as perfect as I can get them. Full comments in weaken.js as usual.
*/
/** @param {NS} ns */
export async function main(ns) {
const start = performance.now();
const port = ns.getPortHandle(ns.pid); // We have to define this here. You'll see why in a moment.
const job = JSON.parse(ns.args[0]);
let tDelay = 0;
let delay = job.end - job.time - Date.now();
// Don't report delay right away.
if (delay < 0) {
ns.tprint(`WARN: Batch ${job.batch} ${job.type} was ${-delay}ms late. (${job.end})\n`);
tDelay = -delay
delay = 0;
}
// The actual function call can take some time, so instead of awaiting on it right away, we save the promise for later.
const promise = ns.weaken(job.target, { additionalMsec: delay });
// Then after calling the hack function, we calculate our final delay and report it to the controller.
tDelay += performance.now() - start;
// The ns object is tied up by the promise, so invoking it now would cause a concurrency error.
// That's why we fetched this handle earlier.
port.write(tDelay);
// Then we finally await the promise. This should give millisecond-accurate predictions for the end time of a job.
await promise;
ns.atExit(() => {
const end = Date.now();
if (job.report) ns.writePort(job.port, job.type + job.batch);
// Uncomment one of these if you want to log completed jobs. Make sure to uncomment the appropriate lines in the controller as well.
// ns.tprint(`Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end).toString().slice(-6)}\n`);
// ns.writePort(job.log, `Batch ${job.batch}: ${job.type} finished at ${end.toString().slice(-6)}/${Math.round(job.end + tDelay).toString().slice(-6)}\n`);
});
}

View File

@@ -1,420 +0,0 @@
/*
We've got a brand new class to look at, but the rest of the file remains unchanged.
*/
/** @param {NS} ns */
export async function main(ns) {
ns.tprint("This is just a function library, it doesn't do anything.");
}
/*
This is an overengineered abomination of a custom data structure. It is essentially a double-ended queue,
but also has a Map stapled to it, just in case we need to access items by id (we don't.)
The idea is that it can fetch/peek items from the front or back with O(1) timing. This gets around the issue of
dynamic arrays taking O(n) time to shift, which is terrible behavior for very long queues like the one we're using.
*/
export class Deque {
#capacity = 0; // The maximum length.
#length = 0; // The actual number of items in the queue
#front = 0; // The index of the "head" where data is read from the queue.
#deleted = 0; // The number of "dead" items in the queue. These occur when items are deleted by index. They are bad.
#elements; // An inner array to store the data.
#index = new Map(); // A hash table to track items by ID. Try not to delete items using this, it's bad.
// Create a new queue with a specific capacity.
constructor(capacity) {
this.#capacity = capacity;
this.#elements = new Array(capacity);
}
// You can also convert arrays.
static fromArray(array, overallocation = 0) {
const result = new Deque(array.length + overallocation);
array.forEach(item => result.push(item));
return result;
}
// Deleted items don't count towards length, but they still take up space in the array until they can be cleared.
// Seriously, don't use the delete function unless it's absolutely necessary.
get size() {
return this.#length - this.#deleted;
}
isEmpty() {
return this.#length - this.#deleted === 0;
}
// Again, "deleted" items still count towards this. Use caution.
isFull() {
return this.#length === this.#capacity;
}
// The "tail" where data is typically written to.
// Unlike the front, which points at the first piece of data, this point at the first empty slot.
get #back() {
return (this.#front + this.#length) % this.#capacity;
}
// Push a new element into the queue.
push(value) {
if (this.isFull()) {
throw new Error("The deque is full. You cannot add more items.");
}
this.#elements[this.#back] = value;
this.#index.set(value.id, this.#back);
++this.#length;
}
// Pop an item off the back of the queue.
pop() {
while (!this.isEmpty()) {
--this.#length;
const item = this.#elements[this.#back];
this.#elements[this.#back] = undefined; // Free up the item for garbage collection.
this.#index.delete(item.id); // Don't confuse index.delete() with this.delete()
if (item.status !== "deleted") return item; // Clear any "deleted" items we encounter.
else --this.#deleted; // If you needed another reason to avoid deleting by ID, this breaks the O(1) time complexity.
}
throw new Error("The deque is empty. You cannot delete any items.");
}
// Shift an item off the front of the queue. This is the main method for accessing data.
shift() {
while (!this.isEmpty()) {
// Our pointer already knows exactly where the front of the queue is. This is much faster than the array equivalent.
const item = this.#elements[this.#front];
this.#elements[this.#front] = undefined;
this.#index.delete(item.id);
// Move the head up and wrap around if we reach the end of the array. This is essentially a circular buffer.
this.#front = (this.#front + 1) % this.#capacity;
--this.#length;
if (item.status !== "deleted") return item;
else --this.#deleted;
}
throw new Error("The deque is empty. You cannot delete any items.");
}
// Place an item at the front of the queue. Slightly slower than pushing, but still faster than doing it on an array.
unshift(value) {
if (this.isFull()) {
throw new Error("The deque is full. You cannot add more items.");
}
this.#front = (this.#front - 1 + this.#capacity) % this.#capacity;
this.#elements[this.#front] = value;
this.#index.set(value.id, this.#front);
++this.#length;
}
// Peeking at the front is pretty quick, since the head is already looking at it. We just have to clear those pesky "deleted" items first.
peekFront() {
if (this.isEmpty()) {
throw new Error("The deque is empty. You cannot peek.");
}
while (this.#elements[this.#front].status === "deleted") {
this.#index.delete(this.#elements[this.#front]?.id);
this.#elements[this.#front] = undefined;
this.#front = (this.#front + 1) % this.#capacity;
--this.#deleted;
--this.#length;
if (this.isEmpty()) {
throw new Error("The deque is empty. You cannot peek.");
}
}
return this.#elements[this.#front];
}
// Peeking at the back is ever so slightly slower, since we need to recalculate the pointer.
// It's a tradeoff for the faster push function, and it's a very slight difference either way.
peekBack() {
if (this.isEmpty()) {
throw new Error("The deque is empty. You cannot peek.");
}
let back = (this.#front + this.#length - 1) % this.#capacity;
while (this.#elements[back].status === "deleted") {
this.#index.delete(this.#elements[back].id);
this.#elements[back] = undefined;
back = (back - 1 + this.#capacity) % this.#capacity;
--this.#deleted;
--this.#length;
if (this.isEmpty()) {
throw new Error("The deque is empty. You cannot peek.");
}
}
return this.#elements[back];
}
// Fill the queue with a single value.
fill(value) {
while (!this.isFull()) {
this.push(value);
}
}
// Empty the whole queue.
clear() {
while (!this.isEmpty()) {
this.pop();
}
}
// Check if an ID exists.
exists(id) {
return this.#index.has(id);
}
// Fetch an item by ID
get(id) {
let pos = this.#index.get(id);
return pos !== undefined ? this.#elements[pos] : undefined;
}
// DON'T
delete(id) {
let item = this.get(id);
if (item !== undefined) {
item.status = "deleted";
++this.#deleted;
return item;
} else {
throw new Error("Item not found in the deque.");
}
}
}
// The recursive server navigation algorithm. The lambda predicate determines which servers to add to the final list.
// You can also plug other functions into the lambda to perform other tasks that check all servers at the same time.
/** @param {NS} ns */
export function getServers(ns, lambdaCondition = () => true, hostname = "home", servers = [], visited = []) {
if (visited.includes(hostname)) return;
visited.push(hostname);
if (lambdaCondition(hostname)) servers.push(hostname);
const connectedNodes = ns.scan(hostname);
if (hostname !== "home") connectedNodes.shift();
for (const node of connectedNodes) getServers(ns, lambdaCondition, node, servers, visited);
return servers;
}
// Here are a couple of my own getServers modules.
// This one finds the best target for hacking. It tries to balance expected return with time taken.
/** @param {NS} ns */
export function checkTarget(ns, server, target = "n00dles", forms = false) {
if (!ns.hasRootAccess(server)) return target;
const player = ns.getPlayer();
const serverSim = ns.getServer(server);
const pSim = ns.getServer(target);
let previousScore;
let currentScore;
if (serverSim.requiredHackingSkill <= player.skills.hacking / (forms ? 1 : 2)) {
if (forms) {
serverSim.hackDifficulty = serverSim.minDifficulty;
pSim.hackDifficulty = pSim.minDifficulty;
previousScore = pSim.moneyMax / ns.formulas.hacking.weakenTime(pSim, player) * ns.formulas.hacking.hackChance(pSim, player);
currentScore = serverSim.moneyMax / ns.formulas.hacking.weakenTime(serverSim, player) * ns.formulas.hacking.hackChance(serverSim, player);
} else {
const weight = (serv) => {
// Calculate the difference between max and available money
let diff = serv.moneyMax - serv.moneyAvailable;
// Calculate the scaling factor as the ratio of the difference to the max money
// The constant here is just an adjustment to fine tune the influence of the scaling factor
let scalingFactor = diff / serv.moneyMax * 0.95;
// Adjust the weight based on the difference, applying the scaling penalty
return (serv.moneyMax / serv.minDifficulty) * (1 - scalingFactor);
}
previousScore = weight(pSim)
currentScore = weight(serverSim)
}
if (currentScore > previousScore) target = server;
}
return target;
}
// A simple function for copying a list of scripts to a server.
/** @param {NS} ns */
export function copyScripts(ns, server, scripts, overwrite = false) {
for (const script of scripts) {
if ((!ns.fileExists(script, server) || overwrite) && ns.hasRootAccess(server)) {
ns.scp(script, server);
}
}
}
// A generic function to check that a given server is prepped. Mostly just a convenience.
export function isPrepped(ns, server) {
const tolerance = 0.0001;
const maxMoney = ns.getServerMaxMoney(server);
const money = ns.getServerMoneyAvailable(server);
const minSec = ns.getServerMinSecurityLevel(server);
const sec = ns.getServerSecurityLevel(server);
const secFix = Math.abs(sec - minSec) < tolerance;
return (money === maxMoney && secFix) ? true : false;
}
/*
This prep function isn't part of the tutorial, but the rest of the code wouldn't work without it.
I don't make any guarantees, but I've been using it and it's worked well enough. I'll comment it anyway.
The prep strategy uses a modified proto-batching technique, which will be covered in part 2.
*/
/** @param {NS} ns */
export async function prep(ns, values, ramNet) {
const maxMoney = values.maxMoney;
const minSec = values.minSec;
let money = values.money;
let sec = values.sec;
while (!isPrepped(ns, values.target)) {
const wTime = ns.getWeakenTime(values.target);
const gTime = wTime * 0.8;
const dataPort = ns.getPortHandle(ns.pid);
dataPort.clear();
const pRam = ramNet.cloneBlocks();
const maxThreads = Math.floor(ramNet.maxBlockSize / 1.75);
const totalThreads = ramNet.prepThreads;
let wThreads1 = 0;
let wThreads2 = 0;
let gThreads = 0;
let batchCount = 1;
let script, mode;
/*
Modes:
0: Security only
1: Money only
2: One shot
*/
if (money < maxMoney) {
gThreads = Math.ceil(ns.growthAnalyze(values.target, maxMoney / money));
wThreads2 = Math.ceil(ns.growthAnalyzeSecurity(gThreads) / 0.05);
}
if (sec > minSec) {
wThreads1 = Math.ceil((sec - minSec) * 20);
if (!(wThreads1 + wThreads2 + gThreads <= totalThreads && gThreads <= maxThreads)) {
gThreads = 0;
wThreads2 = 0;
batchCount = Math.ceil(wThreads1 / totalThreads);
if (batchCount > 1) wThreads1 = totalThreads;
mode = 0;
} else mode = 2;
} else if (gThreads > maxThreads || gThreads + wThreads2 > totalThreads) {
mode = 1;
const oldG = gThreads;
wThreads2 = Math.max(Math.floor(totalThreads / 13.5), 1);
gThreads = Math.floor(wThreads2 * 12.5);
batchCount = Math.ceil(oldG / gThreads);
} else mode = 2;
// Big buffer here, since all the previous calculations can take a while. One second should be more than enough.
const wEnd1 = Date.now() + wTime + 1000;
const gEnd = wEnd1 + values.spacer;
const wEnd2 = gEnd + values.spacer;
// "metrics" here is basically a mock Job object. Again, this is just an artifact of repurposed old code.
const metrics = {
batch: "prep",
target: values.target,
type: "none",
time: 0,
end: 0,
port: ns.pid,
log: values.log,
report: false
};
// Actually assigning threads. We actually allow grow threads to be spread out in mode 1.
// This is because we don't mind if the effect is a bit reduced from higher security unlike a normal batcher.
// We're not trying to grow a specific amount, we're trying to grow as much as possible.
for (const block of pRam) {
while (block.ram >= 1.75) {
const bMax = Math.floor(block.ram / 1.75)
let threads = 0;
if (wThreads1 > 0) {
script = "S4tWeaken.js";
metrics.type = "pWeaken1";
metrics.time = wTime;
metrics.end = wEnd1;
threads = Math.min(wThreads1, bMax);
if (wThreads2 === 0 && wThreads1 - threads <= 0) metrics.report = true;
wThreads1 -= threads;
} else if (wThreads2 > 0) {
script = "S4tWeaken.js";
metrics.type = "pWeaken2";
metrics.time = wTime;
metrics.end = wEnd2;
threads = Math.min(wThreads2, bMax);
if (wThreads2 - threads === 0) metrics.report = true;
wThreads2 -= threads;
} else if (gThreads > 0 && mode === 1) {
script = "S4tGrow.js";
metrics.type = "pGrow";
metrics.time = gTime;
metrics.end = gEnd;
threads = Math.min(gThreads, bMax);
metrics.report = false;
gThreads -= threads;
} else if (gThreads > 0 && bMax >= gThreads) {
script = "S4tGrow.js";
metrics.type = "pGrow";
metrics.time = gTime;
metrics.end = gEnd;
threads = gThreads;
metrics.report = false;
gThreads = 0;
} else break;
metrics.server = block.server;
const pid = ns.exec(script, block.server, { threads: threads, temporary: true }, JSON.stringify(metrics));
if (!pid) throw new Error("Unable to assign all jobs.");
block.ram -= 1.75 * threads;
}
}
// Fancy UI stuff to update you on progress.
const tEnd = ((mode === 0 ? wEnd1 : wEnd2) - Date.now()) * batchCount + Date.now();
const timer = setInterval(() => {
ns.clearLog();
switch (mode) {
case 0:
ns.print(`Weakening security on ${values.target}...`);
break;
case 1:
ns.print(`Maximizing money on ${values.target}...`);
break;
case 2:
ns.print(`Finalizing preparation on ${values.target}...`);
}
ns.print(`Security: +${ns.formatNumber(sec - minSec, 3)}`);
ns.print(`Money: \$${ns.formatNumber(money, 2)}/${ns.formatNumber(maxMoney, 2)}`);
const time = tEnd - Date.now();
ns.print(`Estimated time remaining: ${ns.tFormat(time)}`);
ns.print(`~${batchCount} ${(batchCount === 1) ? "batch" : "batches"}.`);
}, 200);
ns.atExit(() => clearInterval(timer));
// Wait for the last weaken to finish.
do await dataPort.nextWrite(); while (!dataPort.read().startsWith("pWeaken"));
clearInterval(timer);
await ns.sleep(100);
money = ns.getServerMoneyAvailable(values.target);
sec = ns.getServerSecurityLevel(values.target);
}
return true;
}
// I don't actually use this anywhere it the code. It's a debugging tool that I use to test the runtimes of functions.
export function benchmark(lambda) {
let result = 0;
for (let i = 0; i <= 1000; ++i) {
const start = performance.now();
lambda(i);
result += performance.now() - start;
}
return result / 1000;
}

View File

@@ -1,42 +0,0 @@
import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript, purchaseAndUpgradeServers } from "/RamsesUtils.js";
/** @param {NS} ns */
export async function main(ns) {
const funnyScript = ["batch.js", "Ramses-grow.js", "Ramses-weaken.js", "Ramses-hack.js"];
//write function to purchase scripts from tor network and rerun getCracks() then recrack and reroot
let cracks = {};
cracks = getCracks(ns);
let maxPorts = Object.keys(cracks).length;
scanServerList(ns);
let manualTargetOverride = "";
if (ns.getHackingLevel() < 200) {
manualTargetOverride = "n00dles";
};
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride);
let bestTarget = ns.read("bestTarget.txt")
ns.tprint("Best Target: " + bestTarget);
ns.tprint(Object.keys(JSON.parse(ns.read("serverList.txt"))).length);
crackingAndRooting(ns, cracks, funnyScript, true);
ns.exec(funnyScript[0], "home", 1, JSON.parse(bestTarget).serverName, 500, true);
let reset = ns.args[0];
ns.print(reset);
if (reset === true) {
ns.tprint("reset === true")
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride);
let serverList = JSON.parse(ns.read("serverList.txt"));
for (const [name, entry] of Object.entries(serverList)) {
copyAndRunScript(ns, funnyScript, name);
}
}
/*let serverListForFiles = JSON.parse(ns.read("serverList.txt"));
for (const [name2, entry2] of Object.entries(serverListForFiles)) {
ns.tprint(name2 + " Files: " + entry2.serverFiles)
}*/
//await ns.sleep(500000);
await purchaseAndUpgradeServers(ns);
}

View File

@@ -1,21 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
const sTarget = ns.args[0]; // target server which has the contract
const sContract = ns.args[1]; // target contract file
//ns.tprint(ns.codingcontract.getContractTypes());
//ns.codingcontract.createDummyContract();
const sContractType = ns.codingcontract.getContractType(sContract, sTarget);
const sContractData = ns.codingcontract.getData(sContract, sTarget);
const sContractDescription = ns.codingcontract.getDescription(sContract, sTarget);
const sContractTries = ns.codingcontract.getNumTriesRemaining(sContract, sTarget);
ns.tprint("sContractType = " + sContractType);
ns.tprint("sContractData = " + sContractData);
ns.tprint("sContractDescription = " + sContractDescription);
ns.tprint("sContractTries = " + sContractTries);
JSON.stringify(sContractType,sContractType, true);
}

View File

@@ -1,16 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"];
let corpName = "ChemNeo";
let currentSize = 0;
for (let city of cities) {
let currentOffice=(ns.corporation.getOffice(corpName, city));
if (currentOffice.numEmployees < currentOffice.size) {
(currentOffice.employeeJobs.Operations < 1) ? ns.corporation.hireEmployee(corpName, city,"Operations") : "";
(currentOffice.employeeJobs.Engineer < 1) ? ns.corporation.hireEmployee(corpName, city,"Engineer") : "";
(currentOffice.employeeJobs.Business < 1) ? ns.corporation.hireEmployee(corpName, city,"Business") : "";
(currentOffice.employeeJobs.Management < 1) ? ns.corporation.hireEmployee(corpName, city,"Management") : "";
};
}
}

View File

@@ -1,6 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
let [corpName, city] = ns.args;
//ns.corporation.setSmartSupply(corpName, city, true);
return true;
}

View File

@@ -1,12 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"];
let corpName = "ChemNeo";
let currentSize = 0;
for (let city of cities) {
currentSize = ns.corporation.getOffice(corpName, city).size;
if (currentSize < 4) {
ns.corporation.upgradeOfficeSize(corpName, city, 4 - currentSize);
};
}
}

View File

@@ -1,8 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
let serverList = JSON.parse(ns.read("serverList.txt"));
for (const [name, entry] of Object.entries(serverList)) {
ns.killall(name, true)
}
}

View File

@@ -1,5 +0,0 @@
import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript, purchaseAndUpgradeServers } from "/RamsesUtils.js";
/** @param {NS} ns */
export async function main(ns) {
await purchaseAndUpgradeServers(ns);
}

View File

@@ -0,0 +1,15 @@
/** @param {NS} ns */
export async function main(ns) {
const doc = eval("document");
// Find the background div by its ID
let backgroundDiv = doc.getElementById("terminal-background");
if (backgroundDiv) {
// Remove the background element
backgroundDiv.remove();
ns.tprint("Background removed.");
} else {
ns.tprint("No background found to remove.");
}
}

6
Mizzajl/home/RunDist.js Normal file
View File

@@ -0,0 +1,6 @@
import { drun } from "./Library";
/** @param {NS} ns */
export async function main(ns) {
await drun(ns, ...ns.args);
}

9
Mizzajl/home/RunGang.js Normal file
View File

@@ -0,0 +1,9 @@
import { drun } from "./Library";
/** @param {NS} ns */
export async function main(ns) {
if (ns.gang.inGang()){
const sGangScript = "gang/auto-gang2.js";
await drun(ns, sGangScript);
}
}

View File

@@ -1 +0,0 @@
{"home":{"n00dles":{"nectar-net":{"phantasy":{"netlink":{},"crush-fitness":{},"avmnite-02h":{"rothman-uni":{},"summit-uni":{},"syscore":{"lexo-corp":{"global-pharm":{"deltaone":{"defcomm":{"taiyang-digital":{"applied-energetics":{"stormtech":{".":{"nwo":{"ecorp":{},"The-Cave":{}}}}},"run4theh111z":{"fulcrumtech":{"omnitek":{"clarkinc":{}}},"vitalife":{"4sigma":{"b-and-a":{}}}}}},"icarus":{"nova-med":{"microdyne":{"helios":{"kuai-gong":{"blade":{"megacorp":{}},"powerhouse-fitness":{"fulcrumassets":{}}}}}}}}}},"rho-construction":{},"millenium-fitness":{"aerocorp":{"omnia":{"solaris":{}}},"snap-fitness":{"unitalife":{"univ-energy":{"infocomm":{}},"zeus-med":{"zb-def":{"titan-labs":{}}}}}}}}}}},"foodnstuff":{},"sigma-cosmetics":{"zer0":{"omega-net":{"the-hub":{},"johnson-ortho":{}}},"max-hardware":{}},"joesguns":{},"hong-fang-tea":{},"harakiri-sushi":{},"iron-gym":{"CSEC":{"neo-net":{"computek":{"zb-institute":{"alpha-ent":{},"aevum-police":{"galactic-cyber":{}}},"catalyst":{},"I.I.I.I":{}}},"silver-helix":{}}},"darkweb":{}}}

View File

@@ -7,7 +7,7 @@ export async function main(ns) {
let maxPorts = Object.keys(cracks).length; let maxPorts = Object.keys(cracks).length;
scanServerList(ns); scanServerList(ns);
let manualTargetOverride = ""; let manualTargetOverride = "";
if (ns.getHackingLevel() < 200) { if (ns.getHackingLevel() < 10) {
manualTargetOverride = "n00dles"; manualTargetOverride = "n00dles";
}; };
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride); findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride);

View File

@@ -0,0 +1,36 @@
/** @param {NS} ns */
export async function main(ns) {
// Evaluate the document to access the DOM
const doc = eval("document");
// Check if the background has already been added to avoid duplicates
if (doc.getElementById("terminal-background")) {
ns.tprint("Background already set.");
return;
}
// Create a new <div> element to hold the background image
let backgroundDiv = doc.createElement("div");
backgroundDiv.id = "terminal-background"; // Set an ID for later reference
// Add CSS styling for the background
backgroundDiv.style = `
position: fixed;
top: 0;
left: 0;
width: 100vw;
height: 100vh;
z-index: -1; /* Send it to the back */
background-image: url('https://r4.wallpaperflare.com/wallpaper/510/751/778/akira-kaneda-motorcycle-anime-wallpaper-c90008ed51badd0b96b7680fa02106ad.jpg'); /* Replace with your image URL */
background-size: cover; /* Ensure the image covers the whole screen */
background-repeat: no-repeat;
background-position: center;
opacity: 0.5; /* Adjust opacity for readability */
`;
// Append the background <div> to the body of the document
doc.body.appendChild(backgroundDiv);
// Inform the user that the background has been set
ns.tprint("Custom background image set successfully!");
}

13
Mizzajl/home/ShareHome.js Normal file
View File

@@ -0,0 +1,13 @@
/** @param {NS} ns */
export async function main(ns) {
const bKill = ns.args[0]; // if true kill all existing processess
const sShareScript = "factionboost.js";
if (bKill) { ns.killall("home"); }
else { ns.scriptKill(sShareScript, "home"); }
let nShare = Math.floor(((ns.getServerMaxRam("home") - ns.getServerUsedRam("home")) / ns.getScriptRam(sShareScript)));
if (nShare > 0) {
ns.exec(sShareScript, "home", nShare);
}
}

33
Mizzajl/home/Start.js Normal file
View File

@@ -0,0 +1,33 @@
import { DistributeRunAndWait, drun, RunAndWait } from "./Library";
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const sServerListScript = "Serverlist.js";
const sGangScript = "RunGang.js";
const sPServScript = "purchaseServers.js";
const sBatchController = "EveryServerRun.js";
const sBackdoorScript = "backdoor.js";
const sUpdateTarget = "Updatebesttarget.js"
const sMonitorScript = "autoexec.js";
const sServerListFile = "serverList.txt";
const sBestServerFile = "bestTarget.txt";
const sWorkerList = "WorkerList.js";
const sCorpControl = "CorpControl.js";
await RunAndWait(ns, sServerListScript);
if (!ns.isRunning(sWorkerList)) { ns.run(sWorkerList); }
if (!ns.isRunning(sGangScript)) { drun(ns, sGangScript); }
//if (!ns.isRunning(sCorpControl)) { ns.run(sCorpControl); }
if (!ns.isRunning(sPServScript)) { drun(ns, sPServScript); }
await RunAndWait(ns, sBackdoorScript);
await DistributeRunAndWait(ns, sUpdateTarget);
/*
let oServerlist = JSON.parse(ns.read(sServerListFile));
let nHomeMaxRAM = oServerlist.find((entry) => entry.serverName === "home").maxRam;
ns.print("nHomeMaxRAM = " + nHomeMaxRAM);
if (nHomeMaxRAM >= 256) { if (!ns.isRunning(sMonitorScript)) { ns.run(sMonitorScript); } }
*/
}

View File

@@ -0,0 +1,331 @@
/** @param {NS} ns */
export async function main(ns) {
ns.disableLog('sleep'); // Disable log spamming
const doc = eval("document");
const body = doc.body;
let isMinimized = false; // Track the minimize state
// Read crime stats from the CrimeStats.txt file
let crimeStatsData = await ns.read("CrimeStats.txt");
let crimes = JSON.parse(crimeStatsData); // Parse the JSON data from the file
// Add dynamic crime chance and calculate stats per second
for (let crime of crimes) {
crime.chance = ns.singularity.getCrimeChance(crime.name) * 100; // Get success chance as a number
let timeInSeconds = crime.time / 1000; // Convert ms to seconds for calculations
// Calculate stats per second
crime.hacking_exp_per_sec = crime.hacking_exp / timeInSeconds;
crime.strength_exp_per_sec = crime.strength_exp / timeInSeconds;
crime.defense_exp_per_sec = crime.defense_exp / timeInSeconds;
crime.dexterity_exp_per_sec = crime.dexterity_exp / timeInSeconds;
crime.agility_exp_per_sec = crime.agility_exp / timeInSeconds;
crime.charisma_exp_per_sec = crime.charisma_exp / timeInSeconds;
crime.intelligence_exp_per_sec = crime.intelligence_exp / timeInSeconds || 0; // Handle potential missing data
crime.money_per_sec = crime.money / timeInSeconds;
crime.karma_per_sec = crime.karma / timeInSeconds;
crime.money_per_chance = crime.money * (crime.chance / 100) / timeInSeconds; // Money per chance per second
}
// Function to map value to a color between green and red
function getGradientColor(value, min, max, isReversed = false) {
if (min === max) return "rgb(0,255,0)"; // Return green if all values are the same
let normalized = (value - min) / (max - min);
if (isReversed) normalized = 1 - normalized; // Reverse the color gradient for columns where lower values are better
let r = Math.round(255 * (1 - normalized)); // Red for lower values
let g = Math.round(255 * normalized); // Green for higher values
return `rgb(${r},${g},0)`; // Return color from green to red
}
// Create the CSS window container
let container = doc.createElement("div");
container.style = `
position: fixed;
top: 100px;
left: 100px;
background: black; /* Black background */
opacity: 0.9; /* 50% transparency */
color: #0c0; /* Green text */
z-index: 1000;
font-family: "Source Code Pro", monospace; /* Apply the terminal font */
font-size: 16px;
border: 2px solid #666;
border-radius: 5px;
width: 1400px; /* Increased width */
height: 400px; /* Increased height */
overflow-y: auto;
`;
body.appendChild(container);
// Create the title bar with minimize and close buttons
let titleBar = doc.createElement("div");
titleBar.style = `
display: flex;
justify-content: space-between;
align-items: center;
background: black; /* Black background for title bar */
color: #0c0; /* Green text */
border-bottom: 1px solid #666;
font-weight: bold;
`;
container.appendChild(titleBar);
// Title text
let title = doc.createElement("span");
title.innerText = "Crime Stats Monitor";
titleBar.appendChild(title);
// Create a container for the buttons and align them to the right
let buttonContainer = doc.createElement("div");
buttonContainer.style = `
display: flex;
justify-content: flex-end;
`;
titleBar.appendChild(buttonContainer);
// Minimize button (▲ for minimize, ▼ for restore)
let minimizeButton = doc.createElement("button");
minimizeButton.innerText = "▲"; // Start as minimize button
minimizeButton.style = `
background: none;
border: 1px solid #666;
color: #0c0; /* Green text */
cursor: pointer;
font-weight: bold;
padding: 5px;
width: 30px; /* Set same width for buttons */
`;
buttonContainer.appendChild(minimizeButton);
minimizeButton.addEventListener("click", () => {
if (isMinimized) {
minimizeButton.innerText = "▲"; // Minimize arrow
container.style.height = "400px"; // Restore height
} else {
minimizeButton.innerText = "▼"; // Restore arrow
container.style.height = "25px"; // Minimize height
}
isMinimized = !isMinimized;
});
// Close button (X)
let closeButton = doc.createElement("button");
closeButton.innerText = "X";
closeButton.style = `
background: none;
border: 1px solid #666;
color: #0c0; /* Green text */
cursor: pointer;
font-weight: bold;
padding: 5px;
width: 30px; /* Set same width for buttons */
`;
buttonContainer.appendChild(closeButton);
closeButton.addEventListener("click", () => {
container.remove(); // Close the window
});
// Table for displaying the crime stats
let table = doc.createElement("table");
table.style = `
width: 100%;
border-collapse: collapse;
color: #0c0; /* Green text */
`;
container.appendChild(table);
// Track the current sort direction for each column (null, 'asc', or 'desc')
let sortOrder = new Array(13).fill(null); // One for each column
// Add table headers with clickable sorting functionality and arrows
let headers = [
"Crime", "Time (s)", "Chance", "Hack Exp/s", "Str Exp/s", "Def Exp/s",
"Dex Exp/s", "Agi Exp/s", "Cha Exp/s", "Money/s", "Karma/s", "$/%/s", "IntXP/s"
];
let headerRow = doc.createElement("tr");
headers.forEach((header, index) => {
let th = doc.createElement("th");
th.innerHTML = `${header} <span></span>`; // Span for the arrow
th.style = `
padding: 5px;
background: #333;
border: 1px solid #666;
cursor: pointer;
white-space: nowrap; /* Prevent wrapping */
`;
// Add sorting functionality for each column
th.addEventListener("click", () => {
clearAllArrows(); // Remove all arrows
sortCrimesByColumn(index); // Sort by this column
toggleSortOrder(index); // Toggle sort order for this column
});
headerRow.appendChild(th);
});
table.appendChild(headerRow);
// Function to toggle the sort order for a column
function toggleSortOrder(columnIndex) {
// Toggle between 'asc' and 'desc'
if (sortOrder[columnIndex] === 'asc') {
sortOrder[columnIndex] = 'desc';
} else {
sortOrder[columnIndex] = 'asc';
}
// Update the arrows for this column
updateArrow(columnIndex);
}
// Function to update the arrow for a specific column
function updateArrow(columnIndex) {
let th = headerRow.querySelectorAll("th")[columnIndex];
let arrowSpan = th.querySelector("span");
if (sortOrder[columnIndex] === 'asc') {
arrowSpan.innerHTML = " ▲"; // Up arrow for ascending
} else if (sortOrder[columnIndex] === 'desc') {
arrowSpan.innerHTML = " ▼"; // Down arrow for descending
}
}
// Function to clear all arrows
function clearAllArrows() {
headerRow.querySelectorAll("th span").forEach(arrow => {
arrow.innerHTML = ""; // Remove all arrows
});
}
// Function to format numbers with 4 decimal places
function formatNumber(num) {
return parseFloat(num.toFixed(4)); // Convert to number with 4 decimal places
}
// Function to display crimes in the table
function displayCrimes(crimesList) {
// Clear any existing rows (except the header)
while (table.rows.length > 1) {
table.deleteRow(1);
}
// Find min and max for each column (for color gradient)
const columnsWithValues = [
{ key: "time", reverseGradient: true },
{ key: "chance", reverseGradient: false },
{ key: "hacking_exp_per_sec", reverseGradient: false },
{ key: "strength_exp_per_sec", reverseGradient: false },
{ key: "defense_exp_per_sec", reverseGradient: false },
{ key: "dexterity_exp_per_sec", reverseGradient: false },
{ key: "agility_exp_per_sec", reverseGradient: false },
{ key: "charisma_exp_per_sec", reverseGradient: false },
{ key: "money_per_sec", reverseGradient: false },
{ key: "karma_per_sec", reverseGradient: false },
{ key: "money_per_chance", reverseGradient: false },
{ key: "intelligence_exp_per_sec", reverseGradient: false }
];
let minMax = {};
// Get min and max values for each column, excluding non-data elements
columnsWithValues.forEach(column => {
let values = crimesList.map(crime => crime[column.key]).filter(v => !isNaN(v)); // Ensure we're working with numbers
minMax[column.key] = {
min: Math.min(...values),
max: Math.max(...values)
};
});
crimesList.forEach(crime => {
let row = doc.createElement("tr");
let columns = [
{ text: crime.name, value: crime.name, isName: true }, // Crime name (always green)
{ text: formatNumber(crime.time / 1000), value: crime.time / 1000, key: "time" }, // Time in seconds
{ text: formatNumber(crime.chance), value: crime.chance, key: "chance" }, // Success chance
{ text: formatNumber(crime.hacking_exp_per_sec), value: crime.hacking_exp_per_sec, key: "hacking_exp_per_sec" },
{ text: formatNumber(crime.strength_exp_per_sec), value: crime.strength_exp_per_sec, key: "strength_exp_per_sec" },
{ text: formatNumber(crime.defense_exp_per_sec), value: crime.defense_exp_per_sec, key: "defense_exp_per_sec" },
{ text: formatNumber(crime.dexterity_exp_per_sec), value: crime.dexterity_exp_per_sec, key: "dexterity_exp_per_sec" },
{ text: formatNumber(crime.agility_exp_per_sec), value: crime.agility_exp_per_sec, key: "agility_exp_per_sec" },
{ text: formatNumber(crime.charisma_exp_per_sec), value: crime.charisma_exp_per_sec, key: "charisma_exp_per_sec" },
{ text: formatNumber(crime.money_per_sec), value: crime.money_per_sec, key: "money_per_sec" },
{ text: formatNumber(crime.karma_per_sec), value: crime.karma_per_sec, key: "karma_per_sec" },
{ text: formatNumber(crime.money_per_chance), value: crime.money_per_chance, key: "money_per_chance" }, // Money per chance per second
{ text: formatNumber(crime.intelligence_exp_per_sec), value: crime.intelligence_exp_per_sec, key: "intelligence_exp_per_sec" } // Intelligence XP per second
];
columns.forEach((col, index) => {
let td = doc.createElement("td");
td.innerText = col.text; // Display formatted text
td.dataset.value = col.value; // Store the numeric value for sorting
// Apply the color gradient to each cell based on the column
let gradientColor = col.isName
? "#0c0" // Always green for names
: getGradientColor(col.value, minMax[col.key].min, minMax[col.key].max, columnsWithValues[index]?.reverseGradient);
td.style.color = gradientColor; // Apply color
td.style.padding = "5px";
td.style.borderBottom = "1px solid #666";
td.style.textAlign = "center";
td.style.whiteSpace = "nowrap"; // Prevent text wrapping
row.appendChild(td);
});
table.appendChild(row);
});
}
// Sorting function (high to low for numeric values)
function sortCrimesByColumn(columnIndex) {
let rows = Array.from(table.querySelectorAll('tr:nth-child(n+2)')); // Get all rows except header
let order = sortOrder[columnIndex]; // Ascending or descending
rows.sort((rowA, rowB) => {
let valA = rowA.cells[columnIndex].dataset.value;
let valB = rowB.cells[columnIndex].dataset.value;
// Check if values are numeric and sort accordingly
if (!isNaN(valA) && !isNaN(valB)) {
return order === 'asc' ? parseFloat(valA) - parseFloat(valB) : parseFloat(valB) - parseFloat(valA);
}
// If not numeric, sort alphabetically
return order === 'asc' ? String(valA).localeCompare(String(valB)) : String(valB).localeCompare(String(valA));
});
// Append rows in sorted order
rows.forEach(row => table.appendChild(row));
}
// Display the crimes initially
displayCrimes(crimes);
// Make the window draggable
let isDragging = false;
let offsetX, offsetY;
titleBar.addEventListener("mousedown", (e) => {
isDragging = true;
offsetX = e.clientX - container.getBoundingClientRect().left;
offsetY = e.clientY - container.getBoundingClientRect().top;
});
doc.addEventListener("mousemove", (e) => {
if (isDragging) {
container.style.left = `${e.clientX - offsetX}px`;
container.style.top = `${e.clientY - offsetY}px`;
}
});
doc.addEventListener("mouseup", () => {
isDragging = false;
});
}

271
Mizzajl/home/UIGraph.js Normal file
View File

@@ -0,0 +1,271 @@
/** @param {NS} ns */
export async function main(ns) {
const doc = eval("document");
// File to store money data
const moneyRecordFile = "MoneyRecord.txt";
const recordInterval = 10000; // Record every 10 seconds
const graphDuration = 300000; // Last 5 minutes (in milliseconds)
let isClosed = false; // Track if the window is closed
// Function to format numbers as K (thousand), M (million), B (billion), etc.
function formatLargeNumber(number) {
if (number >= 1e12) {
return `$${(number / 1e12).toFixed(3)}t`;
} else if (number >= 1e9) {
return `$${(number / 1e9).toFixed(3)}b`;
} else if (number >= 1e6) {
return `$${(number / 1e6).toFixed(3)}m`;
} else if (number >= 1e3) {
return `$${(number / 1e3).toFixed(3)}k`;
} else {
return `$${number.toFixed(2)}`; // Less than 1000, show as a standard number
}
}
// Remove any existing container if it exists
const existingContainer = doc.getElementById("money-graph-container");
if (existingContainer) {
existingContainer.remove(); // Remove the existing container
ns.tprint("Previous graph closed.");
}
// Create the container for the graph
const container = doc.createElement("div");
container.id = "money-graph-container";
container.style = `
position: absolute;
top: 200px;
left: 200px;
width: 600px;
height: 300px;
background-color: rgba(0, 0, 0, 0.9); /* Black background with 90% opacity */
color: #0c0; /* Green text */
border: 2px solid #666;
border-radius: 8px;
padding: 10px;
font-family: "Source Code Pro", monospace;
z-index: 1000;
cursor: move;
box-shadow: 0px 0px 15px rgba(0, 255, 0, 0.5); /* Glow effect */
`;
// Create a header bar with a close button
const header = doc.createElement("div");
header.style = `
display: flex;
justify-content: space-between;
align-items: center;
font-weight: bold;
color: #0c0; /* Green text */
padding: 5px;
background: rgba(17, 17, 17, 0.9); /* Dark background with 90% opacity */
border-bottom: 1px solid #666;
text-shadow: 0px 0px 10px #0f0;
`;
header.innerText = "Server Money Graph";
// Close button
const closeButton = doc.createElement("button");
closeButton.innerText = "X";
closeButton.style = `
background: none;
border: 1px solid #666;
color: #0c0; /* Green text */
cursor: pointer;
padding: 2px 8px;
font-weight: bold;
border-radius: 3px;
margin-left: 10px;
`;
closeButton.addEventListener("click", () => {
container.remove(); // Close the graph container
ns.tprint("Graph window closed.");
isClosed = true; // Mark the window as closed
});
header.appendChild(closeButton);
container.appendChild(header);
// Create the canvas for the graph
const canvas = doc.createElement("canvas");
canvas.id = "money-graph";
canvas.width = 580; // Slightly smaller than the container for padding
canvas.height = 200;
canvas.style = `
background-color: rgba(17, 17, 17, 0.9); /* Dark background with 90% opacity */
border: 1px solid #666;
border-radius: 4px;
margin-top: 10px;
`;
container.appendChild(canvas);
// Create the money display (on the right side of the graph)
const moneyDisplay = doc.createElement("div");
moneyDisplay.style = `
color: #ffd700; /* Yellow color for money display */
font-size: 18px;
font-weight: bold;
position: absolute;
right: 20px;
top: 100px;
`;
moneyDisplay.innerText = "Money: Loading...";
container.appendChild(moneyDisplay);
doc.body.appendChild(container);
const ctx = canvas.getContext("2d");
// Movable functionality for the entire container
let isMoving = false;
let offsetX = 0, offsetY = 0;
// Start moving the container on mousedown
function startMove(e) {
isMoving = true;
offsetX = e.clientX - container.getBoundingClientRect().left;
offsetY = e.clientY - container.getBoundingClientRect().top;
container.style.cursor = "grabbing"; // Change cursor to grabbing while moving
}
// Stop moving on mouseup
function stopMove() {
if (isMoving) {
isMoving = false;
container.style.cursor = "move"; // Change cursor back to move
}
}
// Handle the movement of the window
function moveWindow(e) {
if (isMoving) {
container.style.left = `${e.clientX - offsetX}px`;
container.style.top = `${e.clientY - offsetY}px`;
}
}
// Attach event listeners for movement
container.addEventListener("mousedown", startMove);
doc.addEventListener("mousemove", moveWindow);
doc.addEventListener("mouseup", stopMove);
doc.addEventListener("mouseleave", stopMove); // Stop moving if mouse leaves the window
// Function to record money data to file with timestamps
function recordMoneyData() {
const currentMoney = ns.getServerMoneyAvailable("home");
const timestamp = Date.now();
const record = `${timestamp},${currentMoney}\n`;
ns.write(moneyRecordFile, record, "a"); // Append without await
moneyDisplay.innerText = `Money: ${formatLargeNumber(currentMoney)}`; // Update money display with formatted value
}
// Function to draw grid lines
function drawGridLines(maxMoney, minMoney) {
const numSteps = 5; // Number of steps on the axes
const stepY = (maxMoney - minMoney) / numSteps; // Step size for Y-axis
const stepX = graphDuration / numSteps; // Step size for X-axis (time)
// Draw vertical grid lines (X-axis steps)
for (let i = 1; i <= numSteps; i++) {
const x = 40 + (i * (canvas.width - 60)) / numSteps;
ctx.beginPath();
ctx.moveTo(x, 10);
ctx.lineTo(x, 180);
ctx.strokeStyle = 'rgba(0, 255, 0, 0.2)'; // Faint green grid line
ctx.stroke();
// Draw X-axis labels
const timeLabel = `${Math.round((i * stepX) / 1000)}s`;
ctx.fillStyle = '#0c0';
ctx.font = '12px "Source Code Pro"';
ctx.fillText(timeLabel, x - 10, 190);
}
// Draw horizontal grid lines (Y-axis steps)
for (let i = 1; i <= numSteps; i++) {
const y = 180 - (i * 170) / numSteps;
ctx.beginPath();
ctx.moveTo(40, y);
ctx.lineTo(550, y);
ctx.strokeStyle = 'rgba(0, 255, 0, 0.2)'; // Faint green grid line
ctx.stroke();
// Draw Y-axis labels with formatted money
const moneyLabel = formatLargeNumber(minMoney + i * stepY);
ctx.fillStyle = '#0c0';
ctx.font = '12px "Source Code Pro"';
ctx.fillText(moneyLabel, 5, y + 5);
}
}
// Function to draw the graph with dynamic scaling from file
async function drawGraph() {
const fileData = await ns.read(moneyRecordFile);
if (!fileData) return;
const records = fileData.trim().split("\n").map(line => {
const [timestamp, money] = line.split(",");
return { timestamp: parseInt(timestamp), money: parseFloat(money) };
});
const now = Date.now();
const recentRecords = records.filter(record => now - record.timestamp <= graphDuration);
// Clear the canvas
ctx.clearRect(0, 0, canvas.width, canvas.height);
if (recentRecords.length === 0) {
return;
}
const maxMoney = Math.max(...recentRecords.map(record => record.money));
const minMoney = Math.min(...recentRecords.map(record => record.money));
if (maxMoney === minMoney) {
return;
}
// Draw gridlines
drawGridLines(maxMoney, minMoney);
// Draw axes
ctx.beginPath();
ctx.moveTo(40, 10); // Left margin
ctx.lineTo(40, 180); // Bottom margin
ctx.lineTo(550, 180); // Right margin
ctx.strokeStyle = '#0c0'; // Green for axes
ctx.stroke();
// Plot the data points with yellow line
ctx.strokeStyle = '#ffd700'; // Yellow for the money line
ctx.beginPath();
const firstPoint = recentRecords[0];
const startTime = firstPoint.timestamp;
const initialY = 180 - ((firstPoint.money - minMoney) / (maxMoney - minMoney)) * 170; // Scale to fit graph height
ctx.moveTo(40, initialY);
recentRecords.forEach((record) => {
const timeDiff = record.timestamp - startTime;
const x = 40 + (timeDiff / graphDuration) * (canvas.width - 60); // Scaled x-axis
const y = 180 - ((record.money - minMoney) / (maxMoney - minMoney)) * 170; // Scaled y-axis
ctx.lineTo(x, y);
});
ctx.stroke();
}
// Main loop to record money data and update graph
try {
while (!isClosed) {
recordMoneyData(); // Record data without await
await drawGraph(); // Ensure graph is updated properly
await ns.sleep(recordInterval); // Wait for 10 seconds
}
} catch (e) {
ns.tprint(`Error: ${e.message}`);
} finally {
if (doc.body.contains(container)) {
container.remove(); // Clean up the container when the script ends
}
ns.tprint("Script stopped.");
}
}

View File

@@ -5,7 +5,11 @@ export async function main(ns) {
let cracks = {}; let cracks = {};
cracks = getCracks(ns); cracks = getCracks(ns);
let maxPorts = Object.keys(cracks).length; let maxPorts = Object.keys(cracks).length;
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(),""); let manualTargetOverride = "";
if (ns.getHackingLevel() < 10) {
manualTargetOverride = "n00dles";
};
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride);
let bestTarget = ns.read("bestTarget.txt") let bestTarget = ns.read("bestTarget.txt")
ns.tprint("Best Target: " + bestTarget); ns.tprint("Best Target: " + bestTarget);
ns.tprint(Object.keys(JSON.parse(ns.read("serverList.txt"))).length); ns.tprint(Object.keys(JSON.parse(ns.read("serverList.txt"))).length);

View File

@@ -0,0 +1,20 @@
import { listWorkServers } from "/Library.js";
/** @param {NS} ns */
export async function main(ns) {
ns.disableLog("ALL");
ns.tail();
ns.resizeTail(561,825);
let nStatus = 0;
let aStatus = ["─", "╲", "│", ""];
let bWhile = true;
while (bWhile !== false) {
ns.clearLog();
bWhile = listWorkServers(ns);
//ns.printRaw(aStatus[nStatus])
ns.setTitle(`WorkerList ${aStatus[nStatus]}`);
nStatus++;
if (nStatus > 3) nStatus = 0;
await ns.sleep(1000);
}
}

View File

@@ -9,7 +9,7 @@ export async function main(ns) {
//host and script info //host and script info
const sThisRunner = ns.getHostname(); const sThisRunner = ns.getHostname();
const sThisScript = ns.getScriptName(); //const sThisScript = ns.getScriptName();
const nThisPID = ns.pid; const nThisPID = ns.pid;
// Custom color coding. // Custom color coding.
@@ -149,8 +149,10 @@ export async function main(ns) {
ns.singularity.purchaseProgram(oEXE.ssh.name); ns.singularity.purchaseProgram(oEXE.ssh.name);
ns.tprint(cCyan + "Purchased " + oEXE.ssh.name + cReset); ns.tprint(cCyan + "Purchased " + oEXE.ssh.name + cReset);
ns.toast("Purchased " + oEXE.ssh.name, "info", 10000); ns.toast("Purchased " + oEXE.ssh.name, "info", 10000);
ns.exec(sServerLister, sThisRunner, 1, false, true); if (!ns.isRunning(sServerLister)) { ns.run(sServerLister, 1, false, true); }
ns.exec(sBackdoorScript, sThisRunner, 1); if (!ns.isRunning(sBackdoorScript)) { ns.run(sBackdoorScript); }
//ns.exec(sServerLister, sThisRunner, 1, false, true);
//ns.exec(sBackdoorScript, sThisRunner, 1);
} }
else if (bAutoLink === false && bHasTOR && nMoney >= oEXE.al.cost) { else if (bAutoLink === false && bHasTOR && nMoney >= oEXE.al.cost) {
ns.singularity.purchaseProgram(oEXE.al.name, false); ns.singularity.purchaseProgram(oEXE.al.name, false);
@@ -161,8 +163,10 @@ export async function main(ns) {
ns.singularity.purchaseProgram(oEXE.ftp.name, false); ns.singularity.purchaseProgram(oEXE.ftp.name, false);
ns.tprint(cCyan + "Purchased " + oEXE.ftp.name + cReset); ns.tprint(cCyan + "Purchased " + oEXE.ftp.name + cReset);
ns.toast("Purchased " + oEXE.ftp.name, "info", 10000); ns.toast("Purchased " + oEXE.ftp.name, "info", 10000);
ns.exec(sServerLister, sThisRunner, 1, false, true); if (!ns.isRunning(sServerLister)) { ns.run(sServerLister, 1, false, true); }
ns.exec(sBackdoorScript, sThisRunner, 1); if (!ns.isRunning(sBackdoorScript)) { ns.run(sBackdoorScript); }
//ns.exec(sServerLister, sThisRunner, 1, false, true);
//ns.exec(sBackdoorScript, sThisRunner, 1);
} }
else if (bDeepscanV1 === false && bHasTOR && nMoney >= oEXE.ds1.cost) { else if (bDeepscanV1 === false && bHasTOR && nMoney >= oEXE.ds1.cost) {
ns.singularity.purchaseProgram(oEXE.ds1.name, false); ns.singularity.purchaseProgram(oEXE.ds1.name, false);
@@ -173,22 +177,28 @@ export async function main(ns) {
ns.singularity.purchaseProgram(oEXE.smtp.name, false); ns.singularity.purchaseProgram(oEXE.smtp.name, false);
ns.tprint(cCyan + "Purchased " + oEXE.smtp.name + cReset); ns.tprint(cCyan + "Purchased " + oEXE.smtp.name + cReset);
ns.toast("Purchased " + oEXE.smtp.name, "info", 10000); ns.toast("Purchased " + oEXE.smtp.name, "info", 10000);
ns.exec(sServerLister, sThisRunner, 1, false, true); if (!ns.isRunning(sServerLister)) { ns.run(sServerLister, 1, false, true); }
ns.exec(sBackdoorScript, sThisRunner, 1); if (!ns.isRunning(sBackdoorScript)) { ns.run(sBackdoorScript); }
//ns.exec(sServerLister, sThisRunner, 1, false, true);
//ns.exec(sBackdoorScript, sThisRunner, 1);
} }
else if (bHttpWorm === false && bHasTOR && nMoney >= oEXE.http.cost) { else if (bHttpWorm === false && bHasTOR && nMoney >= oEXE.http.cost) {
ns.singularity.purchaseProgram(oEXE.http.name, false); ns.singularity.purchaseProgram(oEXE.http.name, false);
ns.tprint(cCyan + "Purchased " + oEXE.http.name + cReset); ns.tprint(cCyan + "Purchased " + oEXE.http.name + cReset);
ns.toast("Purchased " + oEXE.http.name, "info", 10000); ns.toast("Purchased " + oEXE.http.name, "info", 10000);
ns.exec(sServerLister, sThisRunner, 1, false, true); if (!ns.isRunning(sServerLister)) { ns.run(sServerLister, 1, false, true); }
ns.exec(sBackdoorScript, sThisRunner, 1); if (!ns.isRunning(sBackdoorScript)) { ns.run(sBackdoorScript); }
//ns.exec(sServerLister, sThisRunner, 1, false, true);
//ns.exec(sBackdoorScript, sThisRunner, 1);
} }
else if (bSqlInject === false && bHasTOR && nMoney >= oEXE.sql.cost) { else if (bSqlInject === false && bHasTOR && nMoney >= oEXE.sql.cost) {
ns.singularity.purchaseProgram(oEXE.sql.name, false); ns.singularity.purchaseProgram(oEXE.sql.name, false);
ns.tprint(cCyan + "Purchased " + oEXE.sql.name + cReset); ns.tprint(cCyan + "Purchased " + oEXE.sql.name + cReset);
ns.toast("Purchased " + oEXE.sql.name, "info", 10000); ns.toast("Purchased " + oEXE.sql.name, "info", 10000);
ns.exec(sServerLister, sThisRunner, 1, false, true); if (!ns.isRunning(sServerLister)) { ns.run(sServerLister, 1, false, true); }
ns.exec(sBackdoorScript, sThisRunner, 1); if (!ns.isRunning(sBackdoorScript)) { ns.run(sBackdoorScript); }
//ns.exec(sServerLister, sThisRunner, 1, false, true);
//ns.exec(sBackdoorScript, sThisRunner, 1);
} }
else if (bDeepscanV2 === false && bHasTOR && nMoney >= oEXE.ds2.cost) { else if (bDeepscanV2 === false && bHasTOR && nMoney >= oEXE.ds2.cost) {
ns.singularity.purchaseProgram(oEXE.ds2.name, false); ns.singularity.purchaseProgram(oEXE.ds2.name, false);
@@ -198,7 +208,9 @@ export async function main(ns) {
else if (getSetting(ns, "autoPurchaseServers") && nMoney >= 5e+6 && !ns.scriptRunning(sPServScript, sThisRunner)) { //Purchased Servers else if (getSetting(ns, "autoPurchaseServers") && nMoney >= 5e+6 && !ns.scriptRunning(sPServScript, sThisRunner)) { //Purchased Servers
ns.tprint("purchasing servers "); ns.tprint("purchasing servers ");
ns.exec("purchaseServers.js", sThisRunner); ns.exec("purchaseServers.js", sThisRunner);
ns.exec(sServerLister, sThisRunner, 1, false, true); if (!ns.isRunning(sServerLister)) { ns.run(sServerLister, 1, false, true); }
if (!ns.isRunning(sBackdoorScript)) { ns.run(sBackdoorScript); }
//ns.exec(sServerLister, sThisRunner, 1, false, true);
} }
/*else if (getSetting(ns, "autoUpgrades") && nLowestRAM < (2 ** 20) && !ns.scriptRunning("upgrade.js", sThisRunner) && nPServs >= 25 && nMoney >= 1e+6) { /*else if (getSetting(ns, "autoUpgrades") && nLowestRAM < (2 ** 20) && !ns.scriptRunning("upgrade.js", sThisRunner) && nPServs >= 25 && nMoney >= 1e+6) {
ns.tprint("upgrading servers "); ns.tprint("upgrading servers ");

View File

@@ -1,6 +1,6 @@
/** @param {NS} ns */ /** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
ns.tail(); //ns.tail();
await scanRecursiveWrapper(ns); await scanRecursiveWrapper(ns);
let currentHackingLevel = ns.getHackingLevel(); let currentHackingLevel = ns.getHackingLevel();
let currentArray = []; let currentArray = [];

View File

@@ -5,13 +5,15 @@ export async function main(ns) {
goals goals
get money get money
upgrade home ram upgrade home ram
/* */
let nPID = ns.run("serverlister.js"); /*
while (ns.getRunningScript(nPID)){ let nPID = ns.run("serverlister.js");
ns.tprint("waiting for script to finish"); while (ns.getRunningScript(nPID)){
await ns.sleep(100); ns.tprint("waiting for script to finish");
} await ns.sleep(100);
}
*/

View File

@@ -28,6 +28,7 @@ export async function main(ns) {
const nHackScriptRAM = 1.75; const nHackScriptRAM = 1.75;
const nGrowScriptRAM = 1.7; const nGrowScriptRAM = 1.7;
const nWeakenScriptRAM = 1.75; const nWeakenScriptRAM = 1.75;
const nThisScriptRAM = 7.25;
//abort script if sTarget is undefined //abort script if sTarget is undefined
@@ -49,18 +50,18 @@ export async function main(ns) {
let nBonusWeaken = 0; let nBonusWeaken = 0;
let nBonusGrow = 0; let nBonusGrow = 0;
/*if (nCurrentSecurity > nMinSecurity + 3) { if (nCurrentSecurity > nMinSecurity + 2) {
nBonusWeaken = 4; nBonusWeaken = 10;
} }
if (nCurrentMoney <= nMaxMoney * 0.8) { if (nCurrentMoney <= nMaxMoney * 0.8) {
nBonusGrow = 9; nBonusGrow = 10;
}*/ }
let nGrowThreads = Math.max(12 + nBonusGrow, getGrowThreads(ns, sTarget, nHackThreads)); let nGrowThreads = Math.max(2 + nBonusGrow, getGrowThreads(ns, sTarget, nHackThreads));
let nGrowThreadsINT = Math.ceil(nGrowThreads); let nGrowThreadsINT = Math.ceil(nGrowThreads);
//25 hacks or 12.5 grows //25 hacks or 12.5 grows
let nWeakenThreads = Math.max(1 + nBonusWeaken, (nHackThreads / 25) + (nGrowThreads / 12.5)); let nWeakenThreads = Math.max(2 + nBonusWeaken, (nHackThreads / 25) + (nGrowThreads / 12.5));
let nWeakenThreadsINT = Math.ceil(nWeakenThreads); let nWeakenThreadsINT = Math.ceil(nWeakenThreads);
//main variables //main variables
@@ -97,6 +98,7 @@ export async function main(ns) {
nCurrentSecurity = ns.getServerSecurityLevel(sTarget); nCurrentSecurity = ns.getServerSecurityLevel(sTarget);
nCurrentMoney = ns.getServerMoneyAvailable(sTarget); nCurrentMoney = ns.getServerMoneyAvailable(sTarget);
/*
nBonusWeaken = 0; nBonusWeaken = 0;
if (nCurrentSecurity > nMinSecurity + 3) { if (nCurrentSecurity > nMinSecurity + 3) {
nBonusWeaken = 4; nBonusWeaken = 4;
@@ -105,7 +107,7 @@ export async function main(ns) {
if (nCurrentMoney <= nMaxMoney * 0.8) { if (nCurrentMoney <= nMaxMoney * 0.8) {
nBonusGrow = 11; nBonusGrow = 11;
} }
*/
nGrowThreads = Math.max(1 + nBonusGrow, getGrowThreads(ns, sTarget, nHackThreads)); nGrowThreads = Math.max(1 + nBonusGrow, getGrowThreads(ns, sTarget, nHackThreads));
nGrowThreadsINT = Math.ceil(nGrowThreads); nGrowThreadsINT = Math.ceil(nGrowThreads);
@@ -125,14 +127,14 @@ export async function main(ns) {
nUsedRAM = ns.getServerUsedRam(sRunner); nUsedRAM = ns.getServerUsedRam(sRunner);
nFreeRam = nMaxRAM - nUsedRAM; nFreeRam = nMaxRAM - nUsedRAM;
while (nFreeRam <= (nWeakenScriptRAM * nWeakenThreads) + nHomeServerReserve + 6) { while (nFreeRam <= (nWeakenScriptRAM * nWeakenThreads) + nThisScriptRAM) {
await ns.sleep(100); await ns.sleep(100);
nMaxRAM = ns.getServerMaxRam(sRunner); nMaxRAM = ns.getServerMaxRam(sRunner);
nUsedRAM = ns.getServerUsedRam(sRunner); nUsedRAM = ns.getServerUsedRam(sRunner);
nFreeRam = nMaxRAM - nUsedRAM; nFreeRam = nMaxRAM - nUsedRAM;
} }
if (nFreeRam > (nWeakenScriptRAM * nWeakenThreads) + nHomeServerReserve + 6) { if (nFreeRam > (nWeakenScriptRAM * nWeakenThreads) + nThisScriptRAM) {
//Calculate estimate time of completion //Calculate estimate time of completion
nOffset = ns.getWeakenTime(sTarget); nOffset = ns.getWeakenTime(sTarget);
let nWeakTime = new Date(currentDate.getTime() + nOffset); let nWeakTime = new Date(currentDate.getTime() + nOffset);
@@ -149,7 +151,7 @@ export async function main(ns) {
nUsedRAM = ns.getServerUsedRam(sRunner); nUsedRAM = ns.getServerUsedRam(sRunner);
nFreeRam = nMaxRAM - nUsedRAM; nFreeRam = nMaxRAM - nUsedRAM;
while (nFreeRam <= (nGrowScriptRAM * nGrowThreads) + nHomeServerReserve + 6) { while (nFreeRam <= (nGrowScriptRAM * nGrowThreads) + nThisScriptRAM) {
await ns.sleep(100); await ns.sleep(100);
nMaxRAM = ns.getServerMaxRam(sRunner); nMaxRAM = ns.getServerMaxRam(sRunner);
nUsedRAM = ns.getServerUsedRam(sRunner); nUsedRAM = ns.getServerUsedRam(sRunner);
@@ -157,7 +159,7 @@ export async function main(ns) {
} }
if (nCurrentSecurity <= (nMinSecurity + 1) && nFreeRam > (nGrowScriptRAM * nGrowThreads) + nHomeServerReserve + 6) { if (nCurrentSecurity <= (nMinSecurity + 1) && nFreeRam > (nGrowScriptRAM * nGrowThreads) + nThisScriptRAM) {
//Calculate estimate time of completion //Calculate estimate time of completion
nOffset = ns.getGrowTime(sTarget); nOffset = ns.getGrowTime(sTarget);
@@ -175,7 +177,7 @@ export async function main(ns) {
nUsedRAM = ns.getServerUsedRam(sRunner); nUsedRAM = ns.getServerUsedRam(sRunner);
nFreeRam = nMaxRAM - nUsedRAM; nFreeRam = nMaxRAM - nUsedRAM;
while (nFreeRam <= (nHackScriptRAM * nHackThreads) + nHomeServerReserve + 6) { while (nFreeRam <= (nHackScriptRAM * nHackThreads) + nThisScriptRAM) {
await ns.sleep(100); await ns.sleep(100);
nMaxRAM = ns.getServerMaxRam(sRunner); nMaxRAM = ns.getServerMaxRam(sRunner);
nUsedRAM = ns.getServerUsedRam(sRunner); nUsedRAM = ns.getServerUsedRam(sRunner);
@@ -183,7 +185,7 @@ export async function main(ns) {
} }
if (nCurrentMoney >= nMaxMoney * 0.8 && nFreeRam > (nHackScriptRAM * nHackThreads) + nHomeServerReserve + 6) { if (nCurrentMoney >= nMaxMoney * 0.8 && nFreeRam > (nHackScriptRAM * nHackThreads) + nThisScriptRAM) {
//Calculate estimate time of completion //Calculate estimate time of completion
nOffset = ns.getHackTime(sTarget); nOffset = ns.getHackTime(sTarget);

View File

@@ -1 +0,0 @@
{"serverName":"the-hub","maxRam":64,"maxMoney":440206450.3125,"minSec":13,"minPorts":2,"minHackLvl":298,"rootAccess":true,"openPorts":0,"serverOrgs":"The Hub","serverCores":2,"serverFiles":[]}

View File

@@ -0,0 +1,13 @@
/** @param {NS} ns */
export async function main(ns) {
const doc = eval("document");
// Get and remove all elements with the specific container IDs
const containers = doc.querySelectorAll('[id*="money-graph-container"]');
containers.forEach(container => {
container.remove();
});
ns.tprint("Removed all windows.");
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity] = ns.args;
let bSuccess = ns.corporation.buyTea(sDivName, sCity);
ns.writePort(ns.pid, bSuccess);
}

View File

@@ -0,0 +1,5 @@
/** @param {NS} ns */
export async function main(ns) {
ns.corporation.purchaseUnlock("Smart Supply")
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,8 @@
/** @param {NS} ns */
export async function main(ns) {
if (!ns.corporation.hasUnlock("Warehouse API")) {
ns.corporation.purchaseUnlock("Warehouse API");
ns.writePort(ns.pid, true)
}
ns.writePort(ns.pid, true)
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity] = ns.args;
ns.corporation.expandCity(sDivName, sCity)
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [newDivName,industry] = ns.args;
ns.corporation.expandIndustry(industry, newDivName);
ns.writePort(ns.pid,true);
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sCorpName] = ns.args;
ns.writePort(ns.pid, ns.corporation.createCorporation(sCorpName,false));
}

View File

@@ -0,0 +1,4 @@
/** @param {NS} ns */
export async function main(ns) {
ns.writePort(ns.pid,ns.corporation.getCorporation());
}

View File

@@ -0,0 +1,4 @@
/** @param {NS} ns */
export async function main(ns) {
ns.writePort(ns.pid,ns.corporation.getDivision(ns.args[0]))
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity] = ns.args;
//ns.tprint(ns.corporation.getOffice(sDivName, sCity))
ns.writePort(ns.pid, ns.corporation.getOffice(sDivName, sCity))
}

View File

@@ -0,0 +1,9 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity] = ns.args;
if (ns.corporation.hasWarehouse(sDivName, sCity)) {
ns.writePort(ns.pid, ns.corporation.getWarehouse(sDivName, sCity))
} else {
ns.writePort(ns.pid, false)
};
}

View File

@@ -0,0 +1,5 @@
/** @param {NS} ns */
export async function main(ns) {
ns.writePort(ns.pid, ns.corporation.hasCorporation());
}

View File

@@ -0,0 +1,10 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity, oCurrentOffice] = ns.args;
oCurrentOffice = JSON.parse(oCurrentOffice);
if (oCurrentOffice.numEmployees < oCurrentOffice.size) {
ns.corporation.hireEmployee(sDivName, sCity, "Research & Development");
await ns.sleep(1000)
};
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,3 @@
getMaterial() -> material.marketPrice
ns.corporation.getMaterialData() -> baseMarkup

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity] = ns.args;
ns.corporation.purchaseWarehouse(sDivName, sCity);
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,7 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity, oCurrentGoods] = ns.args;
oCurrentGoods = JSON.parse(oCurrentGoods);
ns.corporation.limitMaterialProduction(sDivName, sCity, oCurrentGoods.sMaterialName,50);
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,7 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity, oCurrentGoods] = ns.args;
oCurrentGoods = JSON.parse(oCurrentGoods);
ns.corporation.sellMaterial(sDivName,sCity,oCurrentGoods.sMaterialName,oCurrentGoods.yAmount,oCurrentGoods.yPrice);
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity] = ns.args;
ns.corporation.setSmartSupply(sDivName, sCity, true);
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,26 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity, oCurrentOffice, oWorkerDistribution] = ns.args;
oCurrentOffice = JSON.parse(oCurrentOffice);
let aWorkerDistribution = JSON.parse(oWorkerDistribution).nWorkerNumbers;
let nTotalWorkers = 0;
const len = aWorkerDistribution.length;
for (let i = 0; i < len; i++) nTotalWorkers += aWorkerDistribution[i];
if (nTotalWorkers <= oCurrentOffice.numEmployees) {
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Operations", 0);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Engineer", 0);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Business", 0);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Management", 0);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Research & Development", 0);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Intern", 0);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Operations", aWorkerDistribution[0]);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Engineer", aWorkerDistribution[1]);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Business", aWorkerDistribution[2]);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Management", aWorkerDistribution[3]);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Research & Development", aWorkerDistribution[4]);
ns.corporation.setAutoJobAssignment(sDivName, sCity, "Intern", aWorkerDistribution[5]);
await ns.sleep(1)
};
ns.writePort(ns.pid, true);
}

View File

@@ -0,0 +1,6 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity, nSpend] = ns.args;
let nMoraleMultiplier = ns.corporation.throwParty(sDivName, sCity, nSpend);
ns.writePort(ns.pid, nMoraleMultiplier);
}

View File

@@ -0,0 +1,8 @@
/** @param {NS} ns */
export async function main(ns) {
let [sDivName, sCity, nTargetSize, nCurrentSize] = ns.args;
if (nCurrentSize < nTargetSize) {
ns.corporation.upgradeOfficeSize(sDivName, sCity, nTargetSize - nCurrentSize);
};
ns.writePort(ns.pid, true);
}

12
Mizzajl/home/crimes.txt Normal file
View File

@@ -0,0 +1,12 @@
Shoplift, 2, Money, Dexterity, Agility
Rob Store, 60, Money, Hacking, Dexterity, Agility
Mug, 4, Money, Strength, Defense, Dexterity, Agility
Larceny, 90, Money, Hacking, Dexterity, Agility
Deal Drugs, 10, Money, Dexterity, Agility, Charisma
Forge Bonds, 300, Money, Hacking, Dexterity, Charisma
Traffic Arms, 40, Money, Strength, Defense, Dexterity, Agility, Charisma
Homicide, 3, Money, Strength, Defense, Dexterity, Agility
Grand Theft Auto, 80, Money, Strength, Defense, Dexterity, Agility, Charisma
Kidnap, 120, Money, Strength, Defense, Dexterity, Agility, Charisma
Assassination, 300, Money, Strength, Defense, Dexterity, Agility
Heist, 600, Money, Strength, Defense, Dexterity, Agility, Charisma

View File

@@ -14,7 +14,7 @@ const STATS_TRESHOLD = 0.7;
const STATS_MIN = 4000; const STATS_MIN = 4000;
const STATS_HARD_MIN = 200; const STATS_HARD_MIN = 200;
const TRAIN_CHANCE = 0.2; const TRAIN_CHANCE = 0.2;
const RESPECT_MIN = 2e+7; const RESPECT_MIN = 2e+6;
const WANTED_PENALTY_TRESHOLD = 0.99; const WANTED_PENALTY_TRESHOLD = 0.99;
const WARFARE_TRESHOLD = 2; const WARFARE_TRESHOLD = 2;

4
Mizzajl/home/karma.js Normal file
View File

@@ -0,0 +1,4 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tprint("Karma = " + Math.round(ns.heart.break()).toLocaleString());
}

View File

@@ -1,8 +1,7 @@
/** @param {NS} ns */ /** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
for (const [name, entry] of Object.entries(serverList)) { serverList.forEach(entry => {
ns.killall(entry.serverName, true)
ns.killall(name, true) });
}
} }

View File

@@ -0,0 +1,74 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const sTarget = ns.args[0]; // target server
// Lowram settings
const sBatchScript = "lowram/Lowhgw.js";
const sPrepScript = "lowram/Lowprep.js";
const sRunScript = "lowram/Lowrun.js";
const sLowGrowScript = "lowram/Lowgrow.js";
const sDistScript = "testdistribute.js";
const sGrowScript = "RMgrow.js";
const nThisScriptRAM = ns.getScriptRam(sLowGrowScript, "home");
let nMoney = ns.getServerMoneyAvailable(sTarget);
const nMaxMoney = ns.getServerMaxMoney(sTarget);
const startValue = nMoney; // First argument: starting value
const target = nMaxMoney; // Second argument: target value
let result = startValue; // Initialize result with the starting value
let n = 1;
// For loop that continues until the result exceeds or matches the target
for (; result < target; n++) {
result += 1; // Add 1 before multiplication
result *= n; // Multiply by the current step value
}
let nGrowThreadsNeeded = n * ns.growthAnalyze(sTarget, n, 1);
//ns.print("nGrowThreadsNeeded = " + nGrowThreadsNeeded);
//while (nMoney < nMaxMoney) {
let nFreeRam = ns.getServerMaxRam("home") - ns.getServerUsedRam("home");
//ns.print("nFreeRam = " + nFreeRam);
//ns.print("needed ram = " + Math.ceil(nFreeRam / ns.getScriptRam(sGrowScript, "home")));
//ns.print("needed ram? = " + ns.getScriptRam(sGrowScript, "home"));
if (nGrowThreadsNeeded >= 1) {
const nDelay = ns.getGrowTime(sTarget);
ns.run(sDistScript, 1, sGrowScript, Math.ceil(nGrowThreadsNeeded), sTarget, false, 0);
nMoney = ns.getServerMoneyAvailable(sTarget);
ns.print("nMoney = " + nMoney);
await ns.sleep(nDelay+100);
}
/*
if (nFreeRam >= (ns.getScriptRam(sGrowScript, "home") * nGrowThreadsNeeded)) {
let nGrowPID = ns.run(sGrowScript, Math.ceil(nGrowThreadsNeeded), sTarget);
await ns.nextPortWrite(nGrowPID);
await ns.sleep(1000);
nMoney = ns.getServerMoneyAvailable(sTarget);
}
else {
ns.print("Too smol");
let nGrowPID = ns.run(sGrowScript, Math.ceil((nFreeRam - nThisScriptRAM) / ns.getScriptRam(sGrowScript, "home")), sTarget);
await ns.nextPortWrite(nGrowPID);
await ns.sleep(1000);
nMoney = ns.getServerMoneyAvailable(sTarget);
}
*/
await ns.sleep(1);
//back to Lowrun
ns.spawn(sRunScript, { threads: 1, spawnDelay: 0 }, sTarget);
}

View File

@@ -0,0 +1,116 @@
import { getGrowThreads, getSetting } from "Library.js";
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const sTarget = ns.args[0]; // target server
const sHackScript = "RMhack.js";
const sGrowScript = "RMgrow.js";
const sWeakenScript = "RMweaken.js";
const sServerListFile = "serverList.txt";
const sDistScript = "testdistribute.js";
const nHackScriptRAM = 1.75;
const nGrowScriptRAM = 1.7;
const nWeakenScriptRAM = 1.75;
const nThisScriptRAM = 4.65;
await ns.sleep(1);
while (true) {
let oServerlist = JSON.parse(ns.read(sServerListFile));
let nMaxRAM = oServerlist.find((entry) => entry.serverName === "home").maxRam;
ns.print("nMaxRAM = " + nMaxRAM);
let nWeakenTime = ns.getWeakenTime(sTarget);
let nGrowTime = nWeakenTime * 0.8;
let nHackTime = nWeakenTime / 4;
let nGrowDelay = nWeakenTime - nGrowTime;
let nHackDelay = nWeakenTime - nHackTime;
let nUsedRAM = nThisScriptRAM;
let nHackThreads;
let nGrowThreads;
let nGrowThreadsINT;
let nWeakenThreads;
let nWeakenThreadsINT;
let nCheckRAM;
let nTotalHackRAM;
let nTotalGrowRAM;
let nTotalWeakenRAM;
let nTempHackThreads;
let nTempGrowThreads;
let nTempGrowThreadsINT;
let nTempWeakenThreads;
let nTempWeakenThreadsINT;
for (let i = 1; nUsedRAM < nMaxRAM; i++) {
nTempHackThreads = i;
//ns.print("nTempHackThreads = " + nTempHackThreads);
nTempGrowThreads = Math.max(2, getGrowThreads(ns, sTarget, nTempHackThreads));
nTempGrowThreadsINT = Math.ceil(nTempGrowThreads);
//ns.print("nTempGrowThreads = " + nTempGrowThreads);
//ns.print("nTempGrowThreadsINT = " + nTempGrowThreadsINT);
//25 hacks or 12.5 grows
nTempWeakenThreads = Math.max(2, (nTempHackThreads / 25) + (nTempGrowThreadsINT / 12.5));
nTempWeakenThreadsINT = Math.ceil(nTempWeakenThreads);
//ns.print("nTempWeakenThreads = " + nTempWeakenThreads);
//ns.print("nTempWeakenThreadsINT = " + nTempWeakenThreadsINT);
nTotalHackRAM = (nTempHackThreads * nHackScriptRAM);
nTotalGrowRAM = (nTempGrowThreadsINT * nGrowScriptRAM);
nTotalWeakenRAM = (nTempWeakenThreadsINT * nWeakenScriptRAM);
//ns.print("nTotalHackRAM = " + nTotalHackRAM);
//ns.print("nTotalGrowRAM = " + nTotalGrowRAM);
//ns.print("nTotalWeakenRAM = " + nTotalWeakenRAM);
nCheckRAM = nThisScriptRAM + (nTempHackThreads * nHackScriptRAM) + (nTempGrowThreadsINT * nGrowScriptRAM) + (nTempWeakenThreadsINT * nWeakenScriptRAM);
//ns.print("nCheckRAM = " + nCheckRAM);
if (nCheckRAM < nMaxRAM) {
nUsedRAM = nCheckRAM;
nHackThreads = nTempHackThreads;
nGrowThreads = nTempGrowThreads;
nGrowThreadsINT = nTempGrowThreadsINT;
nWeakenThreads = nTempWeakenThreads;
nWeakenThreadsINT = nTempWeakenThreadsINT;
}
else {
break;
}
//ns.print("nMaxRAM = " + nMaxRAM + " nUsedRAM = " + nUsedRAM);
}
//ns.print("nMaxRAM = " + nMaxRAM + " nUsedRAM = " + nUsedRAM);
ns.print("hgw batch will take " + ((nWeakenTime + 1) / 1000 / 60) + " minutes");
let nCompleteTime = new Date(Date.now() + nWeakenTime+1);
ns.print("complete at " + nCompleteTime.toLocaleTimeString("en-US"));
let nHackPID = ns.run(sHackScript, nHackThreads, sTarget, false, nHackDelay - 100);
let nGrowPID = ns.run(sGrowScript, nGrowThreadsINT, sTarget, false, nGrowDelay - 50);
let nWeakenPID = ns.run(sWeakenScript, nWeakenThreadsINT, sTarget, false, 0);
//ns.tail(nHackPID, "home", nHackThreads, sTarget, false, nHackDelay - 100);
//ns.tail(nGrowPID, "home", nGrowThreadsINT, sTarget, false, nGrowDelay - 50);
//ns.tail(nWeakenPID, "home", nWeakenThreadsINT, sTarget, false, 0);
await Promise.all([
ns.nextPortWrite(nHackPID),
ns.nextPortWrite(nGrowPID),
ns.nextPortWrite(nWeakenPID)
])
await ns.sleep(1);
let nHackFinnish = ns.readPort(nHackPID);
let nGrowFinnish = ns.readPort(nGrowPID);
let nWeakenFinnish = ns.readPort(nWeakenPID);
ns.print("nHackFinnish = " + nHackFinnish);
ns.print("nGrowFinnish = " + nGrowFinnish);
ns.print("nWeakenFinnish = " + nWeakenFinnish);
}
}

View File

@@ -0,0 +1,69 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const sTarget = ns.args[0]; // target server
// declare objects
const oHome = ns.getServer("home");
//const oTarget = ns.getServer(sTarget);
// Lowram settings
const sBatchScript = "lowram/Lowhgw.js";
const sPrepScript = "lowram/Lowprep.js";
const sRunScript = "lowram/Lowrun.js";
const sGrowScript = "lowram/Lowgrow.js";
const sDistScript = "testdistribute.js";
await ns.sleep(100);
//declare variables
const sWeakenScript = "RMweaken.js";
const nCores = oHome.cpuCores;
let nSecurity = ns.getServerSecurityLevel(sTarget);
const nMinSecurity = ns.getServerMinSecurityLevel(sTarget);
const nWeakenSTR = ns.weakenAnalyze(1, 1);
let nThreads = Math.ceil((nSecurity - nMinSecurity) / nWeakenSTR);
//ns.print("nThreads = " + nThreads);
ns.tail(ns.pid, oHome.hostname, sTarget);
//ns.resizeTail(815, 395);
//ns.moveTail(1925, 0);
let nWeakenPID;
if (nThreads > 0) {
const nDelay = ns.getWeakenTime(sTarget);
ns.print("current security is: " + nSecurity);
ns.print("minimum security is: " + nMinSecurity);
ns.print("threads needed for weaken: " + nThreads);
ns.print(nThreads + " will reduce Security by " + ns.weakenAnalyze(nThreads, nCores));
ns.print(nThreads + " of " + sWeakenScript + " requires " + (ns.getScriptRam(sWeakenScript, "home") * nThreads) + " GB of RAM");
ns.print("weakening will take " + (nDelay / 1000 / 60) + " minutes");
ns.run(sDistScript, 1, sWeakenScript, nThreads, sTarget, false, 0);
await ns.sleep(nDelay);
/*
if ((ns.getServerMaxRam(oHome.hostname) - ns.getServerUsedRam(oHome.hostname)) >= (ns.getScriptRam(sWeakenScript, "home") * nThreads)) {
nWeakenPID = ns.exec(sWeakenScript, nThreads, sTarget);
//ns.print("Waiting for PID = " + nWeakenPID);
await ns.nextPortWrite(nWeakenPID);
nSecurity = ns.getServerSecurityLevel(sTarget);
//ns.print("Breach complete, security level is now at: " + nSecurity);
}
else {
nThreads = Math.floor(((ns.getServerMaxRam("home") - ns.getServerUsedRam("home")) / ns.getScriptRam(sWeakenScript)));
nWeakenPID = ns.exec(sWeakenScript, nThreads, sTarget);
//ns.print("Waiting for PID = " + nWeakenPID);
await ns.nextPortWrite(nWeakenPID);
nSecurity = ns.getServerSecurityLevel(sTarget);
//ns.print("Breach in progress, security level is now at: " + nSecurity);
}
*/
}
//back to Lowrun
await ns.sleep(1);
ns.spawn(sRunScript, { threads: 1, spawnDelay: 0 }, sTarget);
}

View File

@@ -0,0 +1,33 @@
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
const sTarget = ns.args[0]; // target server
// Lowram settings
const sBatchScript = "lowram/lowhgw2.js";
const sPrepScript = "lowram/Lowprep.js";
const sRunScript = "lowram/Lowrun.js";
const sGrowScript = "lowram/Lowgrow.js";
const sDistScript = "testdistribute.js";
await ns.sleep(100);
const nTargetMoney = ns.getServerMoneyAvailable(sTarget);
const nTargetMaxMoney = ns.getServerMaxMoney(sTarget);
const nTargetSecurity = ns.getServerSecurityLevel(sTarget);
const nTargetMinSecurity = ns.getServerMinSecurityLevel(sTarget);
//ns.print(sTarget + " Money = " + nTargetMoney.toLocaleString() + " / " + nTargetMaxMoney.toLocaleString());
//ns.print(sTarget + " Security = " + nTargetSecurity.toLocaleString() + " / " + nTargetMinSecurity.toLocaleString());
if (nTargetSecurity > nTargetMinSecurity + 1) {
ns.spawn(sPrepScript, { threads: 1, spawnDelay: 0 }, sTarget);
}
/*else if (nTargetMoney < nTargetMaxMoney) {
//ns.print("need to prep MONEY, running " + sGrowScript);
ns.spawn(sGrowScript, { threads: 1, spawnDelay: 0 }, sTarget);
}*/
else {
ns.spawn(sBatchScript, { threads: 1, spawnDelay: 0 }, sTarget);
}
}

View File

@@ -0,0 +1,101 @@
import { getGrowThreads, getSetting, sortJsonArrayByKey } from "../Library";
/** @param {NS} ns */
export async function main(ns) {
ns.tail();
ns.disableLog("scp");
const sTarget = ns.args[0]; // target server
const sHackScript = "RMhack.js";
const sGrowScript = "RMgrow.js";
const sWeakenScript = "RMweaken.js";
const sServerListFile = "serverList.txt";
const sDistScript = "testdistribute.js";
const sRunScript = "lowram/Lowrun.js";
const aFiles = [sHackScript, sGrowScript, sWeakenScript, sServerListFile];
const nHackScriptRAM = 1.75;
const nGrowScriptRAM = 1.7;
const nWeakenScriptRAM = 1.75;
//target server info
const nMinSecurity = ns.getServerMinSecurityLevel(sTarget);
const nMaxMoney = ns.getServerMaxMoney(sTarget);
const nHomeReserve = getSetting(ns, "homeRAMReserve");
let bLoop = true;
while (bLoop) {
let nWeakenTime = ns.getWeakenTime(sTarget);
let oServerlist = JSON.parse(ns.read(sServerListFile));
let sortedList = sortJsonArrayByKey(oServerlist, "serverCores", "maxRam").reverse();
let nMaxThreads = 0;
sortedList.forEach((entry) => {
if (entry.rootAccess && entry.maxRam >= 1) {
if (entry.serverName !== "home") {
ns.scp(aFiles, entry.serverName, "home");
}
nMaxThreads += entry.maxRam / 1.75;
}
})
let nMaxThreadsINT = Math.floor(nMaxThreads - 64);
ns.print("nMaxThreadsINT = " + nMaxThreadsINT);
let nCurrentSecurity = ns.getServerSecurityLevel(sTarget);
let nCurrentMoney = ns.getServerMoneyAvailable(sTarget);
let nGrowBonus = 0;
if (nCurrentMoney <= nMaxMoney * 0.8) {
nGrowBonus = 100;
}
let nTempHackThreads = 1;
let nTempGrowThreads = nGrowBonus + getGrowThreads(ns, sTarget, nTempHackThreads, 1);
let nTempWeakenThreads = 1 + (nTempHackThreads / 25) + (nTempGrowThreads / 12.5);
//let nBatchSize = nTempHackThreads + nTempGrowThreadsINT + nTempWeakenThreadsINT;
let nBatchWeight = nTempHackThreads + nTempGrowThreads + nTempWeakenThreads;
ns.print("nBatchWeight = " + nBatchWeight);
let nHackWeight = (nTempHackThreads / nBatchWeight);
let nHGrowWeight = (nTempGrowThreads / nBatchWeight);
let nWeakenWeight = (nTempWeakenThreads / nBatchWeight);
ns.print("nHackWeight = " + nHackWeight);
ns.print("nHGrowWeight = " + nHGrowWeight);
ns.print("nWeakenWeight = " + nWeakenWeight);
let nTempHackThreadsINT = Math.ceil(nMaxThreadsINT * nHackWeight);
let nTempGrowThreadsINT = Math.ceil(nMaxThreadsINT * nHGrowWeight);
let nTempWeakenThreadsINT = Math.ceil(nMaxThreadsINT * nWeakenWeight);
ns.print("nTempHackThreadsINT = " + nTempHackThreadsINT);
ns.print("nTempGrowThreadsINT = " + nTempGrowThreadsINT);
ns.print("nTempWeakenThreadsINT = " + nTempWeakenThreadsINT);
ns.print("nWeakenTime = " + nWeakenTime / 1000);
let nHackThreads = Math.max(1, Math.ceil(nTempHackThreadsINT / (nWeakenTime / 5000)));
let nGrowThreads = Math.max(1, Math.ceil(nTempGrowThreadsINT / (nWeakenTime / 5000)));
let nWeakenThreads = Math.max(1, Math.ceil(nTempWeakenThreadsINT / (nWeakenTime / 5000)));
let nGrowTime = nWeakenTime * 0.8;
let nHackTime = nWeakenTime / 4;
let nGrowDelay = nWeakenTime - nGrowTime;
let nHackDelay = nWeakenTime - nHackTime;
let nPID1 = ns.run(sDistScript, 1, sHackScript, nHackThreads, sTarget, false, nHackDelay - 100);
let nPID2 = ns.run(sDistScript, 1, sGrowScript, nGrowThreads, sTarget, false, nGrowDelay - 50);
let nPID3 = ns.run(sDistScript, 1, sWeakenScript, nWeakenThreads + 1, sTarget, false, 0);
if (nPID1 === 0 || nPID2 === 0 || nPID3 === 0) { bLoop = false; }
ns.print("Cash: " + (Math.floor(nCurrentMoney * 1000) / 1000) + " / " + nMaxMoney);
ns.print("Security: " + (Math.floor(nCurrentSecurity * 1000) / 1000) + " / " + nMinSecurity);
await ns.sleep(5000);
}
await ns.sleep(10000);
ns.spawn(sRunScript, { threads: 1, spawnDelay: 0 }, sTarget);
}

View File

@@ -1,4 +1,4 @@
import { getCracks, scanServerList, findBestTarget, crackingAndRooting, copyAndRunScript, purchaseAndUpgradeServers } from "/Library.js"; import { purchaseAndUpgradeServers } from "/Library.js";
/** @param {NS} ns */ /** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
await purchaseAndUpgradeServers(ns); await purchaseAndUpgradeServers(ns);

File diff suppressed because one or more lines are too long

View File

@@ -1,6 +0,0 @@
{"setting":{
"autoUpgrades":true,
"autoPurchaseServers":true,
"batchHacks":1,
"batchFrequency":100
}}

View File

@@ -15,12 +15,12 @@ export async function main(ns) {
const nServ = ns.getPurchasedServers(); const nServ = ns.getPurchasedServers();
const sShareScript = "factionboost.js"; const sShareScript = "factionboost.js";
let nScripts = 0; //let nScripts = 0;
//kill all scripts //kill all scripts
for (let i = 0; i < nServ.length; i++) { for (let i = 0; i < nServ.length; i++) {
nScripts = Math.floor(ns.getServerMaxRam(nServ[i]) / ns.getScriptRam(sShareScript)); //nScripts = Math.floor(ns.getServerMaxRam(nServ[i]) / ns.getScriptRam(sShareScript));
if (bKill) { ns.killall(nServ[i]); } if (bKill) { ns.killall(nServ[i]); }
else { ns.scriptKill(sShareScript, nServ[i]); } else { ns.scriptKill(sShareScript, nServ[i]); }

View File

@@ -0,0 +1,4 @@
/** @param {NS} ns */
export async function main(ns) {
ns.wget("https://storage.googleapis.com/bitburner_test_bucket_1/First%20File.txt", "firstFile.txt");
}

View File

@@ -0,0 +1,87 @@
import { sortJsonArrayByKey } from "Library.js";
/** @param {NS} ns */
export async function main(ns) {
//ns.tail();
ns.disableLog("ALL");
const sScript = ns.args[0]; // script
let nThreads = ns.args[1]; // threads
const sTarget = ns.args[2]; // target server
const bRepeat = ns.args[3]; // should this script loop
const nMsecDelay = ns.args[4]; // MsecDelay
const sWeakenScript = "RMweaken.js";
const sGrowScript = "RMgrow.js";
const sHackScript = "RMhack.js";
const sListName = "serverList.txt";
const sWorkerList = "WorkerList.txt";
if (!ns.fileExists(sListName, "home")) { ns.print(`ERROR ${sListName} does not exist.`); return false; };
let sServerList = ns.read(sListName);
let aSortedList;
if (sScript === sWeakenScript || sScript === sGrowScript) {
aSortedList = sortJsonArrayByKey(sServerList, "serverCores", "maxRam").reverse();
} else {
aSortedList = sortJsonArrayByKey(sServerList, "serverCores", "maxRam");
}
//ns.tprint(aSortedList);
ns.print(sScript);
ns.print(nThreads);
ns.print(sTarget);
const nScriptSize = ns.getScriptRam(sScript, "home");
let nTotalSize = nScriptSize * nThreads;
ns.print("nScriptSize = " + nScriptSize);
ns.print("nTotalSize = " + nTotalSize);
// get sorted list of most cores servers
/*
aSortedList.forEach((entry) => {
if (entry.rootAccess && entry.maxRam >= 1 && entry.serverCores > 1) {
// if cores equal to previous entry put into same array?
}
}) */
// get total free RAM per number of cores
// calculate effect of cores on each server with cores > 1
// update nThreads
// run weaken/grow on core servers until cores = 1
// get sorted list of biggest RAM servers
// get total free RAM on core 1 servers
// run remaining weaken/grow
// run hack untill RAM on cores 1 servers run out
// run remaining hacks on smallest to biggest core servers
aSortedList.forEach((entry) => {
let sHost = entry.serverName;
ns.print("sHost = " + sHost)
let nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nTotalSize) {
if (entry.serverName !== "home") {
ns.scp(sScript, sHost, "home");
}
ns.exec(sScript, sHost, nThreads, sTarget, bRepeat, nMsecDelay);
nThreads = 0;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
else if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nScriptSize) {
let nThreadsDist = Math.floor(nFreeRAM / nScriptSize);
if (entry.serverName !== "home") {
ns.scp(sScript, sHost, "home");
}
ns.print("room for : " + nThreadsDist + " scripts");
ns.exec(sScript, sHost, nThreadsDist, sTarget, bRepeat, nMsecDelay);
nThreads -= nThreadsDist;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
});
/*
for (i = 0; ; i++) {
let sHost = "";
ns.exec(sScript, sHost, nThreads, sTarget, bRepeat, nMsecDelay);
} */
}

27
Mizzajl/home/testgang.js Normal file
View File

@@ -0,0 +1,27 @@
export async function main(ns) {
ns.tail();
// Get the list of all task names
let aTasks = ns.gang.getTaskNames();
// Create an array to store task stats
let oTasks = [];
// Loop through each task and get the stats
for (let i = 0; i < aTasks.length; i++) {
let taskName = aTasks[i];
let taskStats = ns.gang.getTaskStats(taskName);
// Store task name and stats in an object and push to array
oTasks.push({
name: taskName,
stats: taskStats
});
}
// Convert the object to a JSON string for easy storage
let taskStatsString = JSON.stringify(oTasks, null, 2);
// Write the task stats to a file
await ns.write("GangTaskStats.txt", taskStatsString, "w");
ns.tprint("Gang task stats have been written to GangTaskStats.txt.");
}

View File

@@ -13,20 +13,6 @@ export async function main(ns) {
let sHighestPserv; let sHighestPserv;
let nTotalPServRAM = 0; let nTotalPServRAM = 0;
const oPservers = new Object();
/*
const oPservers = {
pserv-01 : { name: "pserv-01" , ram: nRAM}
};
*/
for (let i = 0; i < nPservers; i++) { for (let i = 0; i < nPservers; i++) {
nCurrentRAM = ns.getServerMaxRam(aPservers[i]); nCurrentRAM = ns.getServerMaxRam(aPservers[i]);
//ns.tprint("nTotalPServRAM = " + nTotalPServRAM + " + " + "nCurrentRAM = " + nCurrentRAM); //ns.tprint("nTotalPServRAM = " + nTotalPServRAM + " + " + "nCurrentRAM = " + nCurrentRAM);

View File

@@ -1,24 +1,49 @@
/** @param {NS} ns */ /** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
let aFactions = ns.getPlayer().factions; const aOwnedAugmentations = ns.singularity.getOwnedAugmentations(true);
//ns.tprint("aOwnedAugmentations = " + aOwnedAugmentations);
const aFactions = ns.getPlayer().factions;
ns.tprint("aFactions = " + aFactions); ns.tprint("aFactions = " + aFactions);
let aAugmentations; let aAugmentations;
let sStats; let aStats;
for (let f = 0; f < aFactions.length; f++) { for (let f = 0; f < aFactions.length; f++) {
//ns.tprint("f = " + f); //loop throught the factions
//sFaction = ns.singularity.faction ns.tprint("Faction = " + aFactions[f]);
aAugmentations = ns.singularity.getAugmentationsFromFaction(aFactions[f]); aAugmentations = ns.singularity.getAugmentationsFromFaction(aFactions[f]);
ns.tprint("aAugmentations = " + aAugmentations); let aAvailableAugmentations = aAugmentations.filter(item => !aOwnedAugmentations.includes(item)); //ChatGPT
//ns.tprint("aAugmentations = " + aAugmentations);
ns.tprint("aAvailableAugmentations = " + aAvailableAugmentations);
ns.tprint("----------------------------------------------------------------------------------------------------------------------------------------------------------"); ns.tprint("----------------------------------------------------------------------------------------------------------------------------------------------------------");
for (let a = 0; a < aFactions.length; a++) { for (let a = 0; a < aAvailableAugmentations.length; a++) {
sStats = JSON.stringify(ns.singularity.getAugmentationStats(aAugmentations[a])); //loop throught their aumentations
ns.tprint(aAugmentations[f] + "sStats = " + sStats); //if (aOwnedAugmentations.includes(aAvailableAugmentations[a]) === false) {
//JSON.stringify(ns.singularity.getAugmentationStats(aAvailableAugmentations[a]));
let oStats = ns.singularity.getAugmentationStats(aAvailableAugmentations[a]);
ns.tprint(aAvailableAugmentations[a]);
let nAugmentationReputation = ns.singularity.getAugmentationRepReq(aAvailableAugmentations[a]);
let sAugmentationPrereq = ns.singularity.getAugmentationPrereq(aAvailableAugmentations[a]);
let nAugmentationPrice = ns.singularity.getAugmentationPrice(aAvailableAugmentations[a]);
ns.tprint("Reputation needed = " + nAugmentationReputation);
ns.tprint("Prereq = " + sAugmentationPrereq);
ns.tprint("Price = " + nAugmentationPrice);
// ChatGPT - Iterate through the object and display properties where the value is not 1
for (const key in oStats) {
if (oStats[key] !== 1) {
//console.log(`${key}: ${oStats[key]}`);
ns.tprint(`${key}: ${oStats[key]}`);
}
}
//ns.tprint(aAvailableAugmentations.filter(index !== 1) + " aStats = " + aStats);
//ns.tprint(aAvailableAugmentations[a] + " oStats = " + oStats);
ns.tprint("----------------------------------------------------------------------------------------------------------------------------------------------------------"); ns.tprint("----------------------------------------------------------------------------------------------------------------------------------------------------------");
} }
} }
} }

View File

@@ -1,14 +1,207 @@
/** @param {NS} ns */ /** @param {NS} ns */
export async function main(ns) { export async function main(ns) {
let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"]; let aCitites = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"];
let corpName = "AgraNeo"; let sCorpName = "RM Enterprises";
//ns.tprint(ns.corporation.getConstants()) let sDivisionName = "Agri-Ram";
//ns.corporation.getMaterial(); let reset = ns.args[0];
//ns.corporation.buyMaterial(); if (reset === true || !ns.fileExists("CorpStatus.txt")) {
for (let city of cities) { ns.write("CorpStatus.txt", JSON.stringify({ nStep: 0 }), "w");
await ns.run("/corp/Smart.js",1,corpName,city); };
await ns.tprint(ns.run("/corp/UpgradeOffice.js",1,corpName,city)); let oCorpStatus = JSON.parse(ns.read("CorpStatus.txt")) || { nStep: 0 };
await ns.sleep(1000) let nStep = oCorpStatus.nStep;
let nListenPID = 0;
let oCorpData = {};
let oDivisionData = {};
let oOfficeData = {};
let oWarehouseData = {};
let bUnlockStatus = false;
let nTargetSize = 0;
let oNewOfficeData = {};
let oWorkerNumbers = {};
nListenPID = ns.run("/corp/HasCorp.js");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
let bCorpExists = ns.readPort(nListenPID);
if (!bCorpExists) {
nListenPID = ns.run("/corp/CreateCorp.js", 1, sCorpName);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
} }
if (!ns.readPort(nListenPID)) { ns.tprint("Error! Couldn't start Corporation!"); return };
ns.tprint(oCorpStatus);
while (nStep < 199) {
await ns.corporation.nextUpdate();
if (nStep > 40) {
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
if (oOfficeData.avgEnergy < 99.5) {
nListenPID = ns.run("/corp/BuyTea.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
if (oOfficeData.avgMorale < 99.5) {
nListenPID = ns.run("/corp/ThrowParty.js", 1, sDivisionName, sCity, 500000);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
// InsertSmartSupplyHere
}
};
nStep = oCorpStatus.nStep;
switch (nStep) {
case 0:
nListenPID = ns.run("/corp/GetCorpData.js");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oCorpData = ns.readPort(nListenPID);
if (!oCorpData.divisions.length > 0) {
nListenPID = ns.run("/corp/CorpStart.js", 1, sDivisionName, "Agriculture");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
};
oCorpStatus.nStep = 10;
break;
case 10:
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetDivisionsData.js", 1, sDivisionName);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oDivisionData = ns.readPort(nListenPID);
if (sCity !== "Sector-12" && !oDivisionData.cities.includes(sCity)) {
nListenPID = ns.run("/corp/CorpExpandCity.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
}
oCorpStatus.nStep = 20;
break;
case 20:
/*nListenPID = ns.run("/corp/HasUnlock.js", 1, "Smart Supply");
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
bUnlockStatus = ns.readPort(nListenPID);
if (!bUnlockStatus) {
await ns.nextPortWrite(ns.run("/corp/BuyUnlock.js", 1, "Smart Supply"));
await ns.sleep(1);
}*/
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetWarehouseData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oWarehouseData = ns.readPort(nListenPID);
if (!oWarehouseData) {
await ns.nextPortWrite(ns.run("/corp/PurchaseWarehouses.js", 1, sDivisionName, sCity));
await ns.sleep(1);
}
};
oCorpStatus.nStep = 30;
break;
case 30:
nTargetSize = 4;
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
await ns.nextPortWrite(ns.run("/corp/UpgradeOffice.js", 1, sDivisionName, sCity, nTargetSize, oOfficeData.size))
await ns.sleep(1);
}
oCorpStatus.nStep = 40;
break;
case 40:
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
nListenPID = ns.run("/corp/HireWorkers.js", 1, sDivisionName, sCity, JSON.stringify(oOfficeData));
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
oCorpStatus.nStep = 45;
break;
case 45:
nListenPID = ns.run("/corp/GetDivisionsData.js", 1, sDivisionName);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oDivisionData = ns.readPort(nListenPID);
if (!oDivisionData.researchPoints > 55) { continue } else {
for (let sCity of aCitites) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
nListenPID = ns.run("/corp/SetWorkerOnPosition.js", 1, sDivisionName, sCity, JSON.stringify(oOfficeData), JSON.stringify({ nWorkerNumbers: [1, 1, 1, 1, 0, 0] }));
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
}
oCorpStatus.nStep = 70;
}
break;
case 70:
break;
case 80:
break;
case 90:
break;
case 100:
break;
default:
break;
}
ns.write("CorpStatus.txt", JSON.stringify(oCorpStatus), "w")
await ns.sleep(1)
}
} }
/*
case 50:
let aCurrentGoods = [
{ "sMaterialName": "Food", "yAmount": "MAX", "yPrice": "MP-5" },
{ "sMaterialName": "Plants", "yAmount": "MAX", "yPrice": "MP-5" }
]
for (let sCity of aCitites) {
aCurrentGoods.forEach(async (entry) => {
nListenPID = ns.run("/corp/SetSalePrices.js", 1, sDivisionName, sCity, JSON.stringify(entry));
nListenPID = ns.run("/corp/SetMaterialLimit.js", 1, sDivisionName, sCity, JSON.stringify(entry));
})
}
oCorpStatus.nStep = 60;
break;
case 60:
for (let sCity of aCitites) {
nTargetSize = sCity === "Sector-12" ? 12 : 4;
oWorkerNumbers = sCity === "Sector-12" ? { nWorkerNumbers: [2, 2, 2, 2, 2, 2] } : { nWorkerNumbers: [1, 1, 1, 1, 0, 0] }
let running = true;
while (running) {
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oOfficeData = ns.readPort(nListenPID);
await ns.nextPortWrite(ns.run("/corp/UpgradeOffice.js", 1, sDivisionName, sCity, nTargetSize, oOfficeData.size));
await ns.sleep(1);
nListenPID = ns.run("/corp/GetOfficeData.js", 1, sDivisionName, sCity);
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
oNewOfficeData = ns.readPort(nListenPID);
if (oNewOfficeData.size < nTargetSize) {
await ns.sleep(10000);
ns.tprint("Waiting for money");
continue;
} else {
nListenPID = ns.run("/corp/HireWorkers.js", 1, sDivisionName, sCity, JSON.stringify(oOfficeData), JSON.stringify(oWorkerNumbers));
await ns.nextPortWrite(nListenPID);
await ns.sleep(1);
running = false;
}
}
}
oCorpStatus.nStep = 70;
break;
*/

View File

@@ -1,7 +0,0 @@
/** @param {NS} ns */
export async function main(ns, divName) {
let cities = ["Sector-12", "Aevum", "Volhaven", "Chongqing", "New Tokyo", "Ishima"];
for (let city of cities) {
ns.corporation.expandCity(divName,city)
}
}

View File

@@ -1,6 +0,0 @@
/** @param {NS} ns */
export async function main(ns) {
let newDivName = ns.args[0]
ns.corporation.expandIndustry("Agriculture",newDivName);
ns.run("CorpExpandCity.js",1,newDivName)
}

View File

@@ -0,0 +1 @@
{"nStep":70}

View File

@@ -39,7 +39,7 @@ export async function main(ns) {
let nMaxRam; let nMaxRam;
let nScripts; let nScripts;
for (const [name, entry] of Object.entries(serverList)) { serverList.forEach(async (entry) => {
//let rootAccess = ns.hasRootAccess(currentServer); //let rootAccess = ns.hasRootAccess(currentServer);
//ns.tprint(entry.serverName + " sTarget = " + sTarget); //ns.tprint(entry.serverName + " sTarget = " + sTarget);
@@ -49,7 +49,7 @@ export async function main(ns) {
//nScriptsRAM = ns.getScriptRam(sScript, "home") + Math.max(nWeakenScriptRAM, nGrowScriptRAM, nHackScriptRAM); //nScriptsRAM = ns.getScriptRam(sScript, "home") + Math.max(nWeakenScriptRAM, nGrowScriptRAM, nHackScriptRAM);
//ns.tprint("nScriptsRAM = " + nScriptsRAM); //ns.tprint("nScriptsRAM = " + nScriptsRAM);
if (entry.maxRam >= 64 && serverList[name].rootAccess === true) { if (entry.maxRam >= 64 && entry.rootAccess === true) {
if (sOverrideTarget !== undefined) { if (sOverrideTarget !== undefined) {
sTarget = sOverrideTarget; sTarget = sOverrideTarget;
@@ -73,7 +73,7 @@ export async function main(ns) {
ns.exec(sScript, entry.serverName, 1, sTarget, nFrequency, true, false); ns.exec(sScript, entry.serverName, 1, sTarget, nFrequency, true, false);
await ns.sleep(1); await ns.sleep(1);
} }
else if (entry.maxRam < 64 && entry.maxRam > 0 && serverList[name].rootAccess === true) { else if (entry.maxRam < 64 && entry.maxRam > 0 && entry.rootAccess === true) {
ns.scriptKill(sScript, entry.serverName); ns.scriptKill(sScript, entry.serverName);
ns.scriptKill(sShareScript, entry.serverName); ns.scriptKill(sShareScript, entry.serverName);
ns.scriptKill(sWeakenScript, entry.serverName); ns.scriptKill(sWeakenScript, entry.serverName);
@@ -87,6 +87,6 @@ export async function main(ns) {
} }
} })
//ns.exec("serverlister.js", "home", 1); //ns.exec("serverlister.js", "home", 1);
} }

View File

@@ -33,13 +33,13 @@ export function getCracks(ns) {
/** @param {NS} ns */ /** @param {NS} ns */
export function scanServerList(ns) { export function scanServerList(ns) {
const home = "home"; const home = "home";
let serverList = {}; let serverList = [];
let unscanned = []; let unscanned = [];
unscanned.push(home); unscanned.push(home);
while (unscanned.length > 0) { while (unscanned.length > 0) {
let currentServer = unscanned.pop(); let currentServer = unscanned.pop();
if (!serverList[currentServer]) { if (!serverList.some(obj => obj["serverName"] === currentServer)) {
let maxRam = ns.getServerMaxRam(currentServer); let maxRam = ns.getServerMaxRam(currentServer);
let minPorts = ns.getServerNumPortsRequired(currentServer); let minPorts = ns.getServerNumPortsRequired(currentServer);
let minSecLevel = ns.getServerMinSecurityLevel(currentServer); let minSecLevel = ns.getServerMinSecurityLevel(currentServer);
@@ -51,8 +51,7 @@ export function scanServerList(ns) {
let serverOrgs = serverStats.organizationName; let serverOrgs = serverStats.organizationName;
let serverCores = serverStats.cpuCores; let serverCores = serverStats.cpuCores;
serverList[currentServer] = serverList.push({
{
serverName: currentServer, serverName: currentServer,
maxRam: maxRam, maxRam: maxRam,
maxMoney: serverMoney, maxMoney: serverMoney,
@@ -64,11 +63,11 @@ export function scanServerList(ns) {
serverOrgs: serverOrgs, serverOrgs: serverOrgs,
serverCores: serverCores, serverCores: serverCores,
serverFiles: serverFiles, serverFiles: serverFiles,
}; });
let neighbours = ns.scan(currentServer); let neighbours = ns.scan(currentServer);
for (let i = 0; i < neighbours.length; i++) { for (let i = 0; i < neighbours.length; i++) {
let neighbour = neighbours[i]; let neighbour = neighbours[i];
if (serverList[neighbour]) { if (serverList.some(obj => obj["serverName"] === neighbour)) {
continue continue
} }
unscanned.push(neighbour); unscanned.push(neighbour);
@@ -83,23 +82,23 @@ export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTar
if (!ns.fileExists("serverList.txt", "home")) scanServerList(); if (!ns.fileExists("serverList.txt", "home")) scanServerList();
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
let bestEntry = ""; let bestEntry = "";
if (manualTargetOverride.length > 0) { if (manualTargetOverride && manualTargetOverride.length > 0) {
bestEntry = manualTargetOverride; bestEntry = manualTargetOverride;
} else { } else {
bestEntry = null; bestEntry = null;
let nMaxMoneyPerChance = 0; let nMaxMoneyPerChance = 0;
let nBestMoneyPerChance = 0; let nBestMoneyPerChance = 0;
for (const [name, entry] of Object.entries(serverList)) { serverList.forEach((entry) => {
if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl < currentHackLevel) { if (entry.minSec <= maxSec && entry.minPorts <= maxPorts && entry.minHackLvl <= currentHackLevel) {
nMaxMoneyPerChance = (entry.maxMoney * ns.hackAnalyzeChance(name)) / entry.minSec; nMaxMoneyPerChance = (entry.maxMoney * ns.hackAnalyzeChance(entry.serverName)) / entry.minSec;
if (nMaxMoneyPerChance > nBestMoneyPerChance) { if (nMaxMoneyPerChance > nBestMoneyPerChance) {
nBestMoneyPerChance = nMaxMoneyPerChance; nBestMoneyPerChance = nMaxMoneyPerChance;
bestEntry = name; bestEntry = entry.serverName;
} }
} }
} })
} }
ns.write("bestTarget.txt", JSON.stringify(serverList[bestEntry]), "w"); ns.write("bestTarget.txt", JSON.stringify(serverList.find((entry) => entry.serverName === bestEntry)), "w");
} }
@@ -107,24 +106,25 @@ export function findBestTarget(ns, maxSec, maxPorts, currentHackLevel, manualTar
export function crackingAndRooting(ns, cracks) { export function crackingAndRooting(ns, cracks) {
if (!ns.fileExists("serverList.txt", "home")) scanServerList(); if (!ns.fileExists("serverList.txt", "home")) scanServerList();
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
for (const [name, entry] of Object.entries(serverList)) { let newServerList = serverList.map((entry) => {
let cracked = false; let cracked = false;
let openPorts = serverList[name].openPorts || 0; let openPorts = entry.openPorts || 0;
if (entry.minPorts === 0 || (entry.minPorts > openPorts && entry.minPorts <= Object.keys(cracks).length)) { if (entry.minPorts === 0 || (entry.minPorts > openPorts && entry.minPorts <= Object.keys(cracks).length)) {
for (let k = 0; k < entry.minPorts; k++) { for (let k = 0; k < entry.minPorts; k++) {
cracks[Object.keys(cracks)[k]](name); cracks[Object.keys(cracks)[k]](entry.serverName);
serverList[name].openPorts = k; entry.openPorts = k;
} }
cracked = true; cracked = true;
} }
if (!ns.hasRootAccess(name) && cracked === true) { if (!ns.hasRootAccess(entry.serverName) && cracked === true) {
ns.nuke(name); ns.nuke(entry.serverName);
if (ns.hasRootAccess(name)) { if (ns.hasRootAccess(entry.serverName)) {
serverList[name].rootAccess = true; entry.rootAccess = true;
} }
} }
ns.write("serverList.txt", JSON.stringify(serverList), "w"); return entry
} })
ns.write("serverList.txt", JSON.stringify(newServerList), "w");
ns.tprint("Cracking and rooting done"); ns.tprint("Cracking and rooting done");
} }
@@ -132,25 +132,26 @@ export function crackingAndRooting(ns, cracks) {
/** @param {NS} ns */ /** @param {NS} ns */
export function copyAndRunScript(ns, funnyScript, currentServer) { export function copyAndRunScript(ns, funnyScript, currentServer) {
let bestTarget = JSON.parse(ns.read("bestTarget.txt")); let bestTarget = JSON.parse(ns.read("bestTarget.txt"));
let name = currentServer;
let serverList = JSON.parse(ns.read("serverList.txt")); let serverList = JSON.parse(ns.read("serverList.txt"));
ns.print(name); let bestEntry = serverList.find((entry) => entry.serverName === bestTarget.serverName)
if (serverList[name].rootAccess === true && serverList[bestTarget.serverName].rootAccess === true) { let currentEntry = serverList.find((entry) => entry.serverName === currentServer)
if (name !== "home") {
ns.print("killed threads on: " + name + ns.killall(name, true)); if (currentEntry.rootAccess === true && bestEntry.rootAccess === true) {
if (currentEntry.serverName !== "home") {
ns.print("killed threads on: " + currentEntry.serverName + ns.killall(currentEntry.serverName, true));
} else { } else {
ns.print("killed threads on: " + name + ns.scriptKill(funnyScript[0], name)); ns.print("killed threads on: " + currentEntry.serverName + ns.scriptKill(funnyScript[0], currentEntry.serverName));
}; };
if (serverList[name].maxRam > 0) { if (currentEntry.maxRam > 0) {
ns.scp(funnyScript, name, "home"); ns.scp(funnyScript, currentEntry.serverName, "home");
let maxProcesses = 1; let maxProcesses = 1;
if (serverList[name].maxRam >= 8) { if (currentEntry.maxRam >= 8) {
maxProcesses = Math.max(Math.floor((serverList[name].maxRam) / 8), 1); maxProcesses = Math.max(Math.floor((currentEntry.maxRam) / 8), 1);
} else { } else {
maxProcesses = 1 maxProcesses = 1
}; };
for (let n = 1; n <= maxProcesses; n++) { for (let n = 1; n <= maxProcesses; n++) {
ns.exec(funnyScript[0], name, 1, bestTarget.serverName); ns.exec(funnyScript[0], currentEntry.serverName, 1, bestTarget.serverName);
} }
} }
} }
@@ -165,14 +166,14 @@ export async function purchaseAndUpgradeServers(ns) {
let purchasedServers = []; let purchasedServers = [];
let pServcount = listPurchasedServers(ns).length; let pServcount = listPurchasedServers(ns).length;
let currentMoney = 0; let currentMoney = 0;
let serverList = {}; let serverList = [];
while (pServcount < maxPurchasedServers) { while (pServcount < maxPurchasedServers) {
purchasedServers = listPurchasedServers(ns); purchasedServers = listPurchasedServers(ns);
currentMoney = ns.getServerMoneyAvailable("home"); currentMoney = ns.getServerMoneyAvailable("home");
let targetRamInitial = 16; let targetRamInitial = 16;
if (ns.getPurchasedServerCost(targetRamInitial) < currentMoney) { if (ns.getPurchasedServerCost(targetRamInitial) < currentMoney) {
let sFrontZero = "0"; let sFrontZero = "0";
if (pServcount >= 9) { if (pServcount > 9) {
sFrontZero = ""; sFrontZero = "";
} }
let hostname = ns.purchaseServer("pserv-" + sFrontZero + pServcount, targetRamInitial); let hostname = ns.purchaseServer("pserv-" + sFrontZero + pServcount, targetRamInitial);
@@ -180,7 +181,7 @@ export async function purchaseAndUpgradeServers(ns) {
ns.toast("Purchased " + hostname, "info", 10000); ns.toast("Purchased " + hostname, "info", 10000);
pServcount = listPurchasedServers(ns).length; pServcount = listPurchasedServers(ns).length;
serverList = JSON.parse(ns.read("serverList.txt")); serverList = JSON.parse(ns.read("serverList.txt"));
serverList[hostname] = { serverList.push({
serverName: hostname, serverName: hostname,
maxRam: 16, maxRam: 16,
maxMoney: 0, maxMoney: 0,
@@ -189,7 +190,10 @@ export async function purchaseAndUpgradeServers(ns) {
minHackLvl: 1, minHackLvl: 1,
rootAccess: true, rootAccess: true,
openPorts: 0, openPorts: 0,
}; serverOrgs: "",
serverCores: 1,
serverFiles: []
});
ns.write("serverList.txt", JSON.stringify(serverList), "w"); ns.write("serverList.txt", JSON.stringify(serverList), "w");
continue continue
} else { } else {
@@ -202,18 +206,20 @@ export async function purchaseAndUpgradeServers(ns) {
purchasedServers = listPurchasedServers(ns); purchasedServers = listPurchasedServers(ns);
for (let currentServer of purchasedServers) { for (let currentServer of purchasedServers) {
currentMoney = ns.getServerMoneyAvailable("home"); currentMoney = ns.getServerMoneyAvailable("home");
if (ns.getServerMaxRam(currentServer) < targetRam && ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) { if (ns.getServerMaxRam(currentServer) < targetRam) {
if (ns.upgradePurchasedServer(currentServer, targetRam)) { if (ns.getPurchasedServerUpgradeCost(currentServer, targetRam) < currentMoney) {
ns.print(currentServer + " upgraded to " + targetRam + " GB RAM"); if (ns.upgradePurchasedServer(currentServer, targetRam)) {
serverList = JSON.parse(ns.read("serverList.txt")); ns.print(currentServer + " upgraded to " + targetRam + " GB RAM");
serverList[currentServer].maxRam = targetRam; serverList = JSON.parse(ns.read("serverList.txt"));
ns.write("serverList.txt", JSON.stringify(serverList), "w"); let newServerList = serverList.map((entry) => { if (entry.serverName === currentServer) { entry.maxRam = targetRam } return entry });
ns.tprint(cCyan + "Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB" + cReset); ns.write("serverList.txt", JSON.stringify(newServerList), "w");
ns.toast("Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB", "info", 10000); ns.tprint(cCyan + "Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB" + cReset);
//ns.toast("Server: " + currentServer + " upgraded to: " + targetRam.toLocaleString() + " GB", "info", 10000);
}
} else {
await ns.sleep(5000);
continue
} }
} else {
await ns.sleep(5000);
continue
}; };
} }
++i; ++i;
@@ -241,3 +247,134 @@ export function getGrowThreads(ns, sTarget, nHackThreads, nCores) {
let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, nCores); let nGrowthThreads = ns.growthAnalyze(sTarget, 1 + nHackAmountPercent, nCores);
return nGrowthThreads; return nGrowthThreads;
} }
/** @param {NS} ns */
export async function ExecuteAndWait(ns, sScript, ...args) {
if (!ns.isRunning(sScript, ...args)) { ns.exec(sScript, ...args); }
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
}
/** @param {NS} ns */
export async function RunAndWait(ns, sScript, ...args) {
if (!ns.isRunning(sScript, ...args)) { ns.run(sScript, ...args); }
while (ns.isRunning(sScript, ...args)) { await ns.sleep(100); }
}
/** @param {NS} ns */
export function listWorkServers(ns) {
ns.disableLog("ALL");
const sFileName = "serverList.txt";
if (!ns.fileExists(sFileName, "home")) { ns.print(`ERROR ${sFileName} does not exist.`); return false; };
let serverList = JSON.parse(ns.read(sFileName));
let sortedList = sortJsonArrayByKey(serverList, "serverCores", "maxRam").reverse();
let nTotalWorkerRAM = 0;
let nTotalFreeRAM = 0;
const nServerColumnWidth = 20;
const nValueColumnWidth = 10;
const nCoresWidth = 5;
ns.printRaw("┏━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━━━━━━━━━━━━━━━━━━━┳━━━━━━━┓");
ns.printRaw("┃ Server ┃ Free / Max RAM ┃ Cores ┃");
ns.printRaw("┣━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━━━━━━━━━━━━━━━━━━━╋━━━━━━━┫");
sortedList.forEach((entry) => {
if (entry.rootAccess && entry.maxRam >= 1) {
let sServerName = entry.serverName.padEnd(nServerColumnWidth, ' ');
let nFreeRAM = entry.maxRam - ns.getServerUsedRam(entry.serverName);
let sFreeRAM = ns.formatRam(nFreeRAM).padStart(nValueColumnWidth, ' ');
let sMaxRam = ns.formatRam(entry.maxRam).padStart(nValueColumnWidth, ' ');
let sCores = entry.serverCores.toLocaleString("en-US").padStart(nCoresWidth, ' ');
ns.printRaw(`${sServerName}${sFreeRAM} / ${sMaxRam}${sCores}`);
nTotalWorkerRAM += entry.maxRam;
nTotalFreeRAM += nFreeRAM;
}
});
ns.printRaw("┗━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━━━━━━━━━━━━━━━━━━━┻━━━━━━━┛");
ns.printRaw(`Total Free: ${Math.floor(nTotalFreeRAM).toLocaleString("en-US")} / ${nTotalWorkerRAM.toLocaleString("en-US")} GB`);
}
export function sortJsonArrayByKey(array, primaryKey, secondaryKey) {
if (typeof (array) === "string") {
array = JSON.parse(array);
}
return array.sort((a, b) => {
const xPrimary = a[primaryKey];
const yPrimary = b[primaryKey];
// Handle null or undefined values for primary key
if (xPrimary === null || yPrimary === null || xPrimary === undefined || yPrimary === undefined) {
return 0;
}
// Compare primary keys
const primaryComparison = compareValues(xPrimary, yPrimary);
if (primaryComparison !== 0) {
return primaryComparison;
}
// If primary keys are equal, compare secondary keys
const xSecondary = a[secondaryKey];
const ySecondary = b[secondaryKey];
// Handle null or undefined values for secondary key
if (xSecondary === null || ySecondary === null || xSecondary === undefined || ySecondary === undefined) {
return 0;
}
return compareValues(xSecondary, ySecondary);
});
function compareValues(x, y) {
// Handle numeric and string comparisons differently
if (typeof x === 'string' && typeof y === 'string') {
return x.localeCompare(y); // For string comparison
} else {
return x - y; // For numeric comparison
}
}
}
/** @param {NS} ns */
export async function distributeScript(ns, sScript, nThreads, [...args]) {
//ns.tail();
ns.disableLog("ALL");
const sListName = "serverList.txt";
if (!ns.fileExists(sListName, "home")) { ns.print(`ERROR ${sListName} does not exist.`); return false; };
let sServerList = ns.read(sListName);
let aSortedList = sortJsonArrayByKey(sServerList, "serverCores", "maxRam").reverse();
ns.print(sScript);
ns.print(nThreads);
ns.print(...args);
const nScriptSize = ns.getScriptRam(sScript, "home");
let nTotalSize = nScriptSize * nThreads;
ns.print("nScriptSize = " + nScriptSize);
ns.print("nTotalSize = " + nTotalSize);
aSortedList.forEach((entry) => {
let sHost = entry.serverName;
ns.print("sHost = " + sHost)
let nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nTotalSize) {
ns.scp(sScript, sHost);
ns.exec(sScript, sHost, nThreads, ...args);
nThreads = 0;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
else if (nThreads >= 1 && entry.rootAccess && nFreeRAM >= nScriptSize) {
let nThreadsDist = Math.floor(nFreeRAM / nScriptSize);
ns.scp(sScript, sHost);
ns.print("room for : " + nThreadsDist + " scripts");
ns.exec(sScript, sHost, nThreadsDist, ...args);
nThreads -= nThreadsDist;
nFreeRAM = ns.getServerMaxRam(entry.serverName) - ns.getServerUsedRam(entry.serverName);
}
});
}

View File

@@ -7,7 +7,7 @@ export async function main(ns) {
let maxPorts = Object.keys(cracks).length; let maxPorts = Object.keys(cracks).length;
scanServerList(ns); scanServerList(ns);
let manualTargetOverride = ""; let manualTargetOverride = "";
if (ns.getHackingLevel() < 200) { if (ns.getHackingLevel() < 10) {
manualTargetOverride = "n00dles"; manualTargetOverride = "n00dles";
}; };
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride); findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(), manualTargetOverride);

View File

@@ -8,6 +8,6 @@ export async function main(ns) {
findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(),""); findBestTarget(ns, 999, maxPorts, ns.getHackingLevel(),"");
let bestTarget = ns.read("bestTarget.txt") let bestTarget = ns.read("bestTarget.txt")
ns.tprint("Best Target: " + bestTarget); ns.tprint("Best Target: " + bestTarget);
ns.tprint(Object.keys(JSON.parse(ns.read("serverList.txt"))).length); ns.tprint(JSON.parse(ns.read("serverList.txt")).length);
crackingAndRooting(ns, cracks); crackingAndRooting(ns, cracks);
} }

20
Ramses/home/WorkerList.js Normal file
View File

@@ -0,0 +1,20 @@
import { listWorkServers } from "/Library.js";
/** @param {NS} ns */
export async function main(ns) {
ns.disableLog("ALL");
ns.tail();
ns.resizeTail(561,825);
let nStatus = 0;
let aStatus = ["─", "╲", "│", ""];
let bWhile = true;
while (bWhile !== false) {
ns.clearLog();
bWhile = listWorkServers(ns);
//ns.printRaw(aStatus[nStatus])
ns.setTitle(`WorkerList ${aStatus[nStatus]}`);
nStatus++;
if (nStatus > 3) nStatus = 0;
await ns.sleep(1000);
}
}

View File

@@ -1 +1 @@
{"serverName":"omega-net","maxRam":32,"maxMoney":69174578,"minSec":10,"minPorts":2,"minHackLvl":202,"rootAccess":true,"openPorts":0,"serverOrgs":"Omega Software","serverCores":3,"serverFiles":["S2tGrow.js","S2tHack.js","S2tWeaken.js","S4tGrow.js","S4tHack.js","S4tWeaken.js","contract-909879.cct","the-new-god.lit"]} {"serverName":"rho-construction","maxRam":16,"maxMoney":664249104,"minSec":16,"minPorts":3,"minHackLvl":515,"rootAccess":true,"openPorts":0,"serverOrgs":"Rho Construction","serverCores":3,"serverFiles":["S2tGrow.js","S2tHack.js","S2tWeaken.js","S4tGrow.js","S4tHack.js","S4tWeaken.js","contract-411062.cct","contract-53770.cct","contract-706524.cct","contract-903061-CyberSec.cct","contract-915025.cct","factionboost.js"]}

Some files were not shown because too many files have changed in this diff Show More