more work on bn13

This commit is contained in:
Olivier Gagnon 2021-11-13 23:45:26 -05:00
parent 56ddcd9a45
commit 43a6521403
11 changed files with 213 additions and 182 deletions

103
dist/vendor.bundle.js vendored

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

File diff suppressed because one or more lines are too long

@ -67,7 +67,6 @@ export class ActiveFragment {
}
cool(): void {
console.log(Math.log(this.numCharge + 1) / (Math.log(50) * 10));
this.numCharge = this.numCharge - Math.log(this.numCharge + 1) / (Math.log(50) * 10);
if (this.numCharge < 0) {
this.numCharge = 0;

@ -7,14 +7,14 @@ export interface IStaneksGift {
fragments: ActiveFragment[];
width(): number;
height(): number;
charge(rootX: number, rootY: number, ram: number): number;
charge(fragment: ActiveFragment, threads: number): void;
process(p: IPlayer, n: number): void;
effect(fragment: ActiveFragment): number;
canPlace(x: number, y: number, rotation: number, fragment: Fragment): boolean;
place(x: number, y: number, rotation: number, fragment: Fragment): boolean;
findFragment(rootX: number, rootY: number): ActiveFragment | undefined;
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined;
deleteAt(worldX: number, worldY: number): boolean;
fragmentAt(rootX: number, rootY: number): ActiveFragment | undefined;
delete(rootX: number, rootY: number): boolean;
clear(): void;
count(fragment: Fragment): number;
inBonus(): boolean;

@ -29,16 +29,11 @@ export class StaneksGift implements IStaneksGift {
return Math.floor(this.baseSize() / 2 + 0.6);
}
charge(rootX: number, rootY: number, threads: number): number {
const af = this.findFragment(rootX, rootY);
if (af === undefined) return 0;
charge(af: ActiveFragment, threads: number): void {
af.avgCharge = (af.numCharge * af.avgCharge + threads) / (af.numCharge + 1);
af.numCharge++;
Factions["Church of the Machine God"].playerReputation += Math.log(threads) / Math.log(2);
return threads;
}
inBonus(): boolean {
@ -74,21 +69,21 @@ export class StaneksGift implements IStaneksGift {
return CalculateEffect(fragment.avgCharge, fragment.numCharge, fragment.fragment().power, boost);
}
canPlace(worldX: number, worldY: number, rotation: number, fragment: Fragment): boolean {
if (worldX < 0 || worldY < 0) return false;
if (worldX + fragment.width(rotation) > this.width()) return false;
if (worldY + fragment.height(rotation) > this.height()) return false;
canPlace(rootX: number, rootY: number, rotation: number, fragment: Fragment): boolean {
if (rootX < 0 || rootY < 0) return false;
if (rootX + fragment.width(rotation) > this.width()) return false;
if (rootY + fragment.height(rotation) > this.height()) return false;
if (this.count(fragment) >= fragment.limit) return false;
const newFrag = new ActiveFragment({ x: worldX, y: worldY, rotation: rotation, fragment: fragment });
const newFrag = new ActiveFragment({ x: rootX, y: rootY, rotation: rotation, fragment: fragment });
for (const aFrag of this.fragments) {
if (aFrag.collide(newFrag)) return false;
}
return true;
}
place(worldX: number, worldY: number, rotation: number, fragment: Fragment): boolean {
if (!this.canPlace(worldX, worldY, rotation, fragment)) return false;
this.fragments.push(new ActiveFragment({ x: worldX, y: worldY, rotation: rotation, fragment: fragment }));
place(rootX: number, rootY: number, rotation: number, fragment: Fragment): boolean {
if (!this.canPlace(rootX, rootY, rotation, fragment)) return false;
this.fragments.push(new ActiveFragment({ x: rootX, y: rootY, rotation: rotation, fragment: fragment }));
return true;
}
@ -114,9 +109,9 @@ export class StaneksGift implements IStaneksGift {
return amt;
}
deleteAt(worldX: number, worldY: number): boolean {
delete(rootX: number, rootY: number): boolean {
for (let i = 0; i < this.fragments.length; i++) {
if (this.fragments[i].fullAt(worldX, worldY)) {
if (this.fragments[i].x === rootX && this.fragments[i].y === rootY) {
this.fragments.splice(i, 1);
return true;
}

@ -80,7 +80,9 @@ export function MainBoard(props: IProps): React.ReactElement {
}
function deleteAt(worldX: number, worldY: number): boolean {
return props.gift.deleteAt(worldX, worldY);
const f = props.gift.fragmentAt(worldX, worldY);
if (f === undefined) return false;
return props.gift.delete(f.x, f.y);
}
function clickAt(worldX: number, worldY: number): void {

@ -336,12 +336,12 @@ export const RamCosts: IMap<any> = {
stanek: {
charge: RamCostConstants.ScriptStanekCharge,
fragmentDefinitions: RamCostConstants.ScriptStanekFragmentDefinitions,
placedFragments: RamCostConstants.ScriptStanekPlacedFragments,
activeFragments: RamCostConstants.ScriptStanekPlacedFragments,
clear: RamCostConstants.ScriptStanekClear,
canPlace: RamCostConstants.ScriptStanekCanPlace,
place: RamCostConstants.ScriptStanekPlace,
fragmentAt: RamCostConstants.ScriptStanekFragmentAt,
deleteAt: RamCostConstants.ScriptStanekDeleteAt,
get: RamCostConstants.ScriptStanekFragmentAt,
remove: RamCostConstants.ScriptStanekDeleteAt,
},
heart: {

@ -70,7 +70,13 @@ import { NetscriptCorporation } from "./NetscriptFunctions/Corporation";
import { NetscriptFormulas } from "./NetscriptFunctions/Formulas";
import { NetscriptStockMarket } from "./NetscriptFunctions/StockMarket";
import { NS as INS, Player as INetscriptPlayer } from "./ScriptEditor/NetscriptDefinitions";
import {
NS as INS,
Player as INetscriptPlayer,
Gang as IGang,
Bladeburner as IBladeburner,
Stanek as IStanek,
} from "./ScriptEditor/NetscriptDefinitions";
import { NetscriptSingularity } from "./NetscriptFunctions/Singularity";
import { toNative } from "./NetscriptFunctions/toNative";
@ -82,6 +88,9 @@ import { Flags } from "./NetscriptFunctions/Flags";
interface NS extends INS {
[key: string]: any;
gang: IGang;
bladeburner: IBladeburner;
stanek: IStanek;
}
export function NetscriptFunctions(workerScript: WorkerScript): NS {

@ -7,25 +7,20 @@ import { getRamCost } from "../Netscript/RamCostGenerator";
import { staneksGift } from "../CotMG/Helper";
import { Fragments, FragmentById } from "../CotMG/Fragment";
export interface INetscriptStanek {
width(): number;
height(): number;
charge(rootX: number, rootY: number): any;
fragmentDefinitions(): any;
placedFragments(): any;
clear(): void;
canPlace(worldX: number, worldY: number, rotation: number, fragmentId: number): boolean;
place(worldX: number, worldY: number, rotation: number, fragmentId: number): boolean;
findFragment(rootX: any, rootY: any): any;
fragmentAt(worldX: number, worldY: number): any;
deleteAt(worldX: number, worldY: number): boolean;
}
import {
Stanek as IStanek,
Fragment as IFragment,
ActiveFragment as IActiveFragment,
} from "../ScriptEditor/NetscriptDefinitions";
import { AugmentationNames } from "../Augmentation/data/AugmentationNames";
export function NetscriptStanek(player: IPlayer, workerScript: WorkerScript, helper: INetscriptHelper): IStanek {
function checkStanekAPIAccess(func: string): void {
if (!player.hasAugmentation(AugmentationNames.StaneksGift1, true)) {
helper.makeRuntimeErrorMsg(func, "Requires Stanek's Gift installed.");
}
}
export function NetscriptStanek(
player: IPlayer,
workerScript: WorkerScript,
helper: INetscriptHelper,
): INetscriptStanek {
return {
width: function (): number {
return staneksGift.width();
@ -33,9 +28,12 @@ export function NetscriptStanek(
height: function (): number {
return staneksGift.height();
},
charge: function (rootX: any, rootY: any): any {
charge: function (arootX: any, arootY: any): Promise<void> {
const rootX = helper.number("stanek.charge", "rootX", arootX);
const rootY = helper.number("stanek.charge", "rootY", arootY);
helper.updateDynamicRam("charge", getRamCost("stanek", "charge"));
//checkStanekAPIAccess("charge");
checkStanekAPIAccess("charge");
const fragment = staneksGift.findFragment(rootX, rootY);
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.charge", `No fragment with root (${rootX}, ${rootY}).`);
const time = staneksGift.inBonus() ? 200 : 1000;
@ -43,65 +41,69 @@ export function NetscriptStanek(
if (workerScript.env.stopFlag) {
return Promise.reject(workerScript);
}
const ram = workerScript.scriptRef.ramUsage * workerScript.scriptRef.threads;
const charge = staneksGift.charge(rootX, rootY, workerScript.scriptRef.threads);
const charge = staneksGift.charge(fragment, workerScript.scriptRef.threads);
workerScript.log("stanek.charge", `Charged fragment for ${charge} charge.`);
return Promise.resolve(charge);
return Promise.resolve();
});
},
fragmentDefinitions: function () {
fragmentDefinitions: function (): IFragment[] {
helper.updateDynamicRam("fragmentDefinitions", getRamCost("stanek", "fragmentDefinitions"));
//checkStanekAPIAccess("fragmentDefinitions");
checkStanekAPIAccess("fragmentDefinitions");
workerScript.log("stanek.fragmentDefinitions", `Returned ${Fragments.length} fragments`);
return Fragments.map((f) => f.copy());
},
placedFragments: function () {
helper.updateDynamicRam("placedFragments", getRamCost("stanek", "placedFragments"));
//checkStanekAPIAccess("placedFragments");
workerScript.log("stanek.placedFragments", `Returned ${staneksGift.fragments.length} fragments`);
activeFragments: function (): IActiveFragment[] {
helper.updateDynamicRam("activeFragments", getRamCost("stanek", "activeFragments"));
checkStanekAPIAccess("activeFragments");
workerScript.log("stanek.activeFragments", `Returned ${staneksGift.fragments.length} fragments`);
return staneksGift.fragments.map((af) => {
return { ...af.copy(), ...af.fragment().copy() };
});
},
clear: function () {
clear: function (): void {
helper.updateDynamicRam("clear", getRamCost("stanek", "clear"));
//checkStanekAPIAccess("clear");
checkStanekAPIAccess("clear");
workerScript.log("stanek.clear", `Cleared Stanek's Gift.`);
staneksGift.clear();
},
canPlace: function (worldX: any, worldY: any, rotation: any, fragmentId: any): any {
canPlace: function (arootX: any, arootY: any, arotation: any, afragmentId: any): boolean {
const rootX = helper.number("stanek.canPlace", "rootX", arootX);
const rootY = helper.number("stanek.canPlace", "rootY", arootY);
const rotation = helper.number("stanek.canPlace", "rotation", arotation);
const fragmentId = helper.number("stanek.canPlace", "fragmentId", afragmentId);
helper.updateDynamicRam("canPlace", getRamCost("stanek", "canPlace"));
//checkStanekAPIAccess("canPlace");
checkStanekAPIAccess("canPlace");
const fragment = FragmentById(fragmentId);
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.canPlace", `Invalid fragment id: ${fragmentId}`);
const can = staneksGift.canPlace(worldX, worldY, rotation, fragment);
const can = staneksGift.canPlace(rootX, rootY, rotation, fragment);
return can;
},
place: function (worldX: any, worldY: any, rotation: any, fragmentId: any): any {
place: function (arootX: any, arootY: any, arotation: any, afragmentId: any): boolean {
const rootX = helper.number("stanek.place", "rootX", arootX);
const rootY = helper.number("stanek.place", "rootY", arootY);
const rotation = helper.number("stanek.place", "rotation", arotation);
const fragmentId = helper.number("stanek.place", "fragmentId", afragmentId);
helper.updateDynamicRam("place", getRamCost("stanek", "place"));
//checkStanekAPIAccess("place");
checkStanekAPIAccess("place");
const fragment = FragmentById(fragmentId);
if (!fragment) throw helper.makeRuntimeErrorMsg("stanek.place", `Invalid fragment id: ${fragmentId}`);
return staneksGift.place(worldX, worldY, rotation, fragment);
return staneksGift.place(rootX, rootY, rotation, fragment);
},
findFragment: function (rootX: any, rootY: any): any {
helper.updateDynamicRam("findFragment", getRamCost("stanek", "findFragment"));
//checkStanekAPIAccess("fragmentAt");
get: function (arootX: any, arootY: any): IActiveFragment | undefined {
const rootX = helper.number("stanek.get", "rootX", arootX);
const rootY = helper.number("stanek.get", "rootY", arootY);
helper.updateDynamicRam("get", getRamCost("stanek", "get"));
checkStanekAPIAccess("get");
const fragment = staneksGift.findFragment(rootX, rootY);
if (fragment !== undefined) return fragment.copy();
return undefined;
},
fragmentAt: function (worldX: any, worldY: any): any {
helper.updateDynamicRam("fragmentAt", getRamCost("stanek", "fragmentAt"));
//checkStanekAPIAccess("fragmentAt");
const fragment = staneksGift.fragmentAt(worldX, worldY);
if (fragment !== undefined) return fragment.copy();
return undefined;
},
deleteAt: function (worldX: any, worldY: any): any {
helper.updateDynamicRam("deleteAt", getRamCost("stanek", "deleteAt"));
//checkStanekAPIAccess("deleteAt");
return staneksGift.deleteAt(worldX, worldY);
remove: function (arootX: any, arootY: any): boolean {
const rootX = helper.number("stanek.remove", "rootX", arootX);
const rootY = helper.number("stanek.remove", "rootY", arootY);
helper.updateDynamicRam("remove", getRamCost("stanek", "remove"));
checkStanekAPIAccess("remove");
return staneksGift.delete(rootX, rootY);
},
};
}

@ -3360,20 +3360,123 @@ export interface Formulas {
hacknetServers: HacknetServersFormulas;
}
export interface Fragment {
id: number;
shape: boolean[][];
type: number;
power: number;
limit: number;
}
export interface ActiveFragment {
id: number;
avgCharge: number;
numCharge: number;
rotation: number;
x: number;
y: number;
}
/**
* Stanek's Gift API.
* @public
*/
interface Stanek {
/**
* @ramCost cost: 0.5 GB
* @param {number} rootX Root X against which to align the top left of the fragment.
* @param {number} rootY Root Y against which to align the top left of the fragment.
* @param {number} rotation A number from 0 to 3, the mount of 90 degree turn to take.
* @param {number} fragmentId ID of the fragment to place.
* @returns {boolean} true if the fragment can be placed at that position. false otherwise.
* Stanek's Gift width.
* @remarks
* RAM cost: 0.4 GB
* @returns The width of the gift.
*/
width(): number;
/**
* Stanek's Gift height.
* @remarks
* RAM cost: 0.4 GB
* @returns The height of the gift.
*/
height(): number;
/**
* Charge a fragment, increasing it's power.
* @remarks
* RAM cost: 0.4 GB
* @param rootX - rootX Root X against which to align the top left of the fragment.
* @param rootY - rootY Root Y against which to align the top left of the fragment.
* @returns Promise that lasts until the charge action is over.
*/
charge(rootX: number, rootY: number): Promise<void>;
/**
* List possible fragments.
* @remarks
* RAM cost: cost: 0 GB
*
* @returns List of possible fragments.
*/
fragmentDefinitions(): Fragment[];
/**
* List of fragments in Stanek's Gift.
* @remarks
* RAM cost: cost: 5 GB
*
* @returns List of active fragments placed on Stanek's Gift.
*/
activeFragments(): ActiveFragment[];
/**
* Clear the board of all fragments.
* @remarks
* RAM cost: cost: 0 GB
*/
clear(): void;
/**
* Check if fragment can be placed at specified location.
* @remarks
* RAM cost: cost: 0.5 GB
*
* @param rootX - rootX Root X against which to align the top left of the fragment.
* @param rootY - rootY Root Y against which to align the top left of the fragment.
* @param rotation - rotation A number from 0 to 3, the mount of 90 degree turn to take.
* @param fragmentId - fragmentId ID of the fragment to place.
* @returns true if the fragment can be placed at that position. false otherwise.
*/
canPlace(rootX: number, rootY: number, rotation: number, fragmentId: number): boolean;
/**
* Place fragment on Stanek's Gift.
* @remarks
* RAM cost: cost: 5 GB
*
* @param rootX - X against which to align the top left of the fragment.
* @param rootY - Y against which to align the top left of the fragment.
* @param rotation - A number from 0 to 3, the mount of 90 degree turn to take.
* @param fragmentId - ID of the fragment to place.
* @returns true if the fragment can be placed at that position. false otherwise.
*/
place(rootX: number, rootY: number, rotation: number, fragmentId: number): boolean;
/**
* Get placed fragment at location.
* @remarks
* RAM cost: cost: 5 GB
*
* @param rootX - X against which to align the top left of the fragment.
* @param rootY - Y against which to align the top left of the fragment.
* @returns The fragment at [rootX, rootY], if any.
*/
get(rootX: number, rootY: number): ActiveFragment | undefined;
/**
* Remove fragment at location.
* @remarks
* RAM cost: cost: 0.15 GB
*
* @param rootX - X against which to align the top left of the fragment.
* @param rootY - Y against which to align the top left of the fragment.
* @returns The fragment at [rootX, rootY], if any.
*/
remove(rootX: number, rootY: number): boolean;
}
/**