bitburner-src/src/NetscriptFunctions/CodingContract.ts

93 lines
4.3 KiB
TypeScript
Raw Normal View History

import { Player } from "@player";
2021-10-14 09:22:02 +02:00
import { CodingContract } from "../CodingContracts";
import { CodingContract as ICodingContract } from "@nsdefs";
2022-08-08 19:43:41 +02:00
import { InternalAPI, NetscriptContext } from "../Netscript/APIWrapper";
import { helpers } from "../Netscript/NetscriptHelpers";
2022-10-09 08:56:11 +02:00
import { codingContractTypesMetadata } from "../data/codingcontracttypes";
import { generateDummyContract } from "../CodingContractGenerator";
2021-10-14 09:22:02 +02:00
2022-08-09 21:41:47 +02:00
export function NetscriptCodingContract(): InternalAPI<ICodingContract> {
const getCodingContract = function (ctx: NetscriptContext, hostname: string, filename: string): CodingContract {
2022-08-08 19:43:41 +02:00
const server = helpers.getServer(ctx, hostname);
2021-11-20 21:01:04 +01:00
const contract = server.getContract(filename);
2021-10-14 09:22:02 +02:00
if (contract == null) {
2022-08-08 19:43:41 +02:00
throw helpers.makeRuntimeErrorMsg(ctx, `Cannot find contract '${filename}' on server '${hostname}'`);
2021-10-14 09:22:02 +02:00
}
return contract;
};
return {
attempt: (ctx) => (answer, _filename, _hostname?) => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
2021-10-14 09:22:02 +02:00
if (typeof answer !== "number" && typeof answer !== "string" && !Array.isArray(answer))
throw new Error("The answer provided was not a number, string, or array");
// Convert answer to string.
// Todo: better typing for contracts, don't do this weird string conversion of the player answer
const answerStr = typeof answer === "string" ? answer : JSON.stringify(answer);
const creward = contract.reward;
2021-10-14 09:22:02 +02:00
const serv = helpers.getServer(ctx, hostname);
if (contract.isSolution(answerStr)) {
const reward = Player.gainCodingContractReward(creward, contract.getDifficulty());
helpers.log(ctx, () => `Successfully completed Coding Contract '${filename}'. Reward: ${reward}`);
serv.removeContract(filename);
return reward;
} else {
++contract.tries;
if (contract.tries >= contract.getMaxNumTries()) {
helpers.log(ctx, () => `Coding Contract attempt '${filename}' failed. Contract is now self-destructing`);
2021-11-20 21:01:04 +01:00
serv.removeContract(filename);
2021-10-14 09:22:02 +02:00
} else {
helpers.log(
ctx,
() =>
`Coding Contract attempt '${filename}' failed. ${
contract.getMaxNumTries() - contract.tries
} attempts remaining.`,
);
2021-10-14 09:22:02 +02:00
}
return "";
}
},
getContractType: (ctx) => (_filename, _hostname?) => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
return contract.getType();
},
getData: (ctx) => (_filename, _hostname?) => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
const data = contract.getData();
if (Array.isArray(data)) {
// For multi-dimensional arrays, we have to copy the internal arrays as well
return JSON.parse(JSON.stringify(data));
} else return data;
},
getDescription: (ctx) => (_filename, _hostname?) => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
return contract.getDescription();
},
getNumTriesRemaining: (ctx) => (_filename, _hostname?) => {
const filename = helpers.string(ctx, "filename", _filename);
const hostname = _hostname ? helpers.string(ctx, "hostname", _hostname) : ctx.workerScript.hostname;
const contract = getCodingContract(ctx, hostname, filename);
return contract.getMaxNumTries() - contract.tries;
},
createDummyContract: (ctx) => (_type) => {
const type = helpers.string(ctx, "type", _type);
generateDummyContract(type);
},
getContractTypes: () => () => codingContractTypesMetadata.map((c) => c.name),
2021-10-14 09:22:02 +02:00
};
}