DNET: Tweaks from player feedback (#2593)

This commit is contained in:
Michael Ficocelli
2026-03-26 18:38:45 -07:00
committed by GitHub
parent 38d5f3b364
commit fdd6d65c25
10 changed files with 96 additions and 54 deletions

View File

@@ -17,3 +17,7 @@ getCurrentPlayer(): "White" | "Black" | "None";
"White" \| "Black" \| "None" "White" \| "Black" \| "None"
## Remarks
RAM cost: 0 GB

View File

@@ -22,3 +22,7 @@ getGameState(): {
{ currentPlayer: "White" \| "Black" \| "None"; whiteScore: number; blackScore: number; previousMove: \[number, number\] \| null; komi: number; bonusCycles: number; } { currentPlayer: "White" \| "Black" \| "None"; whiteScore: number; blackScore: number; previousMove: \[number, number\] \| null; komi: number; bonusCycles: number; }
## Remarks
RAM cost: 0 GB

View File

@@ -31,3 +31,7 @@ getMoveHistory(): string[][];
string\[\]\[\] string\[\]\[\]
## Remarks
RAM cost: 0 GB

View File

@@ -15,3 +15,7 @@ getOpponent(): GoOpponent;
[GoOpponent](./bitburner.goopponent.md) [GoOpponent](./bitburner.goopponent.md)
## Remarks
RAM cost: 0 GB

View File

@@ -31,6 +31,7 @@ type LabDetails = {
mazeWidth: number; mazeWidth: number;
mazeHeight: number; mazeHeight: number;
manual: boolean; manual: boolean;
offsetStartAndEnd: boolean;
}; };
export const labData: Record<string, LabDetails> = { export const labData: Record<string, LabDetails> = {
@@ -41,6 +42,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 20, mazeWidth: 20,
mazeHeight: 14, mazeHeight: 14,
manual: true, manual: true,
offsetStartAndEnd: false,
}, },
[SpecialServers.CruelLab]: { [SpecialServers.CruelLab]: {
name: SpecialServers.CruelLab, name: SpecialServers.CruelLab,
@@ -49,6 +51,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 30, mazeWidth: 30,
mazeHeight: 20, mazeHeight: 20,
manual: true, manual: true,
offsetStartAndEnd: false,
}, },
[SpecialServers.MercilessLab]: { [SpecialServers.MercilessLab]: {
name: SpecialServers.MercilessLab, name: SpecialServers.MercilessLab,
@@ -57,6 +60,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 40, mazeWidth: 40,
mazeHeight: 26, mazeHeight: 26,
manual: false, manual: false,
offsetStartAndEnd: false,
}, },
[SpecialServers.UberLab]: { [SpecialServers.UberLab]: {
name: SpecialServers.UberLab, name: SpecialServers.UberLab,
@@ -65,6 +69,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 60, mazeWidth: 60,
mazeHeight: 40, mazeHeight: 40,
manual: false, manual: false,
offsetStartAndEnd: true,
}, },
[SpecialServers.EternalLab]: { [SpecialServers.EternalLab]: {
name: SpecialServers.EternalLab, name: SpecialServers.EternalLab,
@@ -73,6 +78,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 60, mazeWidth: 60,
mazeHeight: 40, mazeHeight: 40,
manual: false, manual: false,
offsetStartAndEnd: true,
}, },
[SpecialServers.EndlessLab]: { [SpecialServers.EndlessLab]: {
name: SpecialServers.EndlessLab, name: SpecialServers.EndlessLab,
@@ -81,6 +87,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 60, mazeWidth: 60,
mazeHeight: 40, mazeHeight: 40,
manual: false, manual: false,
offsetStartAndEnd: true,
}, },
[SpecialServers.FinalLab]: { [SpecialServers.FinalLab]: {
name: SpecialServers.FinalLab, name: SpecialServers.FinalLab,
@@ -89,6 +96,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 60, mazeWidth: 60,
mazeHeight: 40, mazeHeight: 40,
manual: false, manual: false,
offsetStartAndEnd: true,
}, },
[SpecialServers.BonusLab]: { [SpecialServers.BonusLab]: {
name: SpecialServers.BonusLab, name: SpecialServers.BonusLab,
@@ -97,6 +105,7 @@ export const labData: Record<string, LabDetails> = {
mazeWidth: 60, mazeWidth: 60,
mazeHeight: 40, mazeHeight: 40,
manual: false, manual: false,
offsetStartAndEnd: true,
}, },
} as const; } as const;
@@ -185,6 +194,7 @@ export const getSurroundingsVisualized = (
showEnd = false, showEnd = false,
): string => { ): string => {
const result: string[] = []; const result: string[] = [];
const [endpointY, endpointX] = DarknetState.labEndpoint ?? [maze[0].length - 2, maze.length - 2];
for (let i = y - range; i <= y + range; i++) { for (let i = y - range; i <= y + range; i++) {
let row = ""; let row = "";
for (let j = x - range; j <= x + range; j++) { for (let j = x - range; j <= x + range; j++) {
@@ -192,7 +202,7 @@ export const getSurroundingsVisualized = (
row += "@"; row += "@";
continue; continue;
} }
if (i === maze.length - 2 && j === maze[0].length - 2 && showEnd) { if (i === endpointX && j === endpointY && showEnd) {
row += "X"; row += "X";
continue; continue;
} }
@@ -205,7 +215,7 @@ export const getSurroundingsVisualized = (
}; };
const getLocationStatus = (pid: number): LocationStatus => { const getLocationStatus = (pid: number): LocationStatus => {
const [initialX, initialY] = DarknetState.labLocations[pid] ?? [1, 1]; const [initialX, initialY] = getPositionInLab(pid);
const surroundings = getSurroundingsVisualized(getLabMaze(), initialX, initialY).split("\n"); const surroundings = getSurroundingsVisualized(getLabMaze(), initialX, initialY).split("\n");
return { return {
coords: [initialX, initialY], coords: [initialX, initialY],
@@ -245,11 +255,8 @@ export const handleLabyrinthPassword = (
} }
const maze = getLabMaze(); const maze = getLabMaze();
if (!DarknetState.labLocations[pid]) { const [initialX, initialY] = getPositionInLab(pid);
DarknetState.labLocations[pid] = [1, 1]; const end = DarknetState.labEndpoint ?? [maze[0].length - 2, maze.length - 2];
}
const [initialX, initialY] = DarknetState.labLocations[pid];
const end = [maze[0].length - 2, maze.length - 2];
const [dx, dy] = getDirectionFromInput(attemptedPassword); const [dx, dy] = getDirectionFromInput(attemptedPassword);
const newLocation: [number, number] = [initialX + dx * 2, initialY + dy * 2]; const newLocation: [number, number] = [initialX + dx * 2, initialY + dy * 2];
@@ -324,6 +331,12 @@ export const handleLabyrinthPassword = (
}; };
}; };
export const getPositionInLab = (pid: number): [number, number] => {
const [offsetX, offsetY] = getRandomOffset();
DarknetState.labLocations[pid] ??= [1 + offsetX, 1 + offsetY];
return DarknetState.labLocations[pid];
};
const getDirectionFromInput = (input: string): number[] => { const getDirectionFromInput = (input: string): number[] => {
const direction = input const direction = input
.split(" ") .split(" ")
@@ -352,10 +365,22 @@ export const getLabMaze = (): string[] => {
if (!DarknetState.labyrinth) { if (!DarknetState.labyrinth) {
const { mazeWidth, mazeHeight } = getLabyrinthDetails(); const { mazeWidth, mazeHeight } = getLabyrinthDetails();
DarknetState.labyrinth = generateMaze(mazeWidth, mazeHeight); DarknetState.labyrinth = generateMaze(mazeWidth, mazeHeight);
const [offsetX, offsetY] = getRandomOffset();
DarknetState.labEndpoint = [
DarknetState.labyrinth[0].length - 2 - offsetX,
DarknetState.labyrinth.length - 2 - offsetY,
];
} }
return DarknetState.labyrinth; return DarknetState.labyrinth;
}; };
const getRandomOffset = () => {
const { offsetStartAndEnd } = getLabyrinthDetails();
const offsetX = offsetStartAndEnd ? Math.floor(Math.random() * 3) * 2 : 0;
const offsetY = offsetStartAndEnd ? Math.floor(Math.random() * 3) * 2 : 0;
return [offsetX, offsetY];
};
export const getLabyrinthServerNames = () => { export const getLabyrinthServerNames = () => {
const labHostnames: string[] = Object.keys(labData); const labHostnames: string[] = Object.keys(labData);
return labHostnames; return labHostnames;
@@ -455,6 +480,7 @@ export const getLabyrinthDetails = (): {
mazeHeight: number; mazeHeight: number;
cha: number; cha: number;
name: string; name: string;
offsetStartAndEnd: boolean;
} => { } => {
// Lab not unlocked yet // Lab not unlocked yet
if (!hasFullDarknetAccess()) { if (!hasFullDarknetAccess()) {
@@ -466,6 +492,7 @@ export const getLabyrinthDetails = (): {
lab: null, lab: null,
depth: 5, depth: 5,
manual: false, manual: false,
offsetStartAndEnd: false,
}; };
} }
@@ -480,6 +507,7 @@ export const getLabyrinthDetails = (): {
mazeHeight: labDetails.mazeHeight, mazeHeight: labDetails.mazeHeight,
cha: labDetails.cha, cha: labDetails.cha,
name: labDetails.name, name: labDetails.name,
offsetStartAndEnd: labDetails.offsetStartAndEnd,
}; };
}; };

View File

@@ -40,11 +40,12 @@ export const DarknetState = {
Network: new Array(MAX_NET_DEPTH).fill(null).map(() => new Array<DarknetServer | null>(NET_WIDTH).fill(null)), Network: new Array(MAX_NET_DEPTH).fill(null).map(() => new Array<DarknetServer | null>(NET_WIDTH).fill(null)),
labyrinth: null as string[] | null, labyrinth: null as string[] | null,
labEndpoint: null as [number, number] | null,
/** /**
* This property may contain data of dead PIDs. Call cleanUpLabyrinthLocations before using this property if you * This property may contain data of dead PIDs. Call cleanUpLabyrinthLocations before using this property if you
* want to get data of alive PIDs. * want to get data of alive PIDs.
*/ */
labLocations: { "-1": [1, 1] } as Record<number, [number, number] | undefined>, labLocations: {} as Record<number, [number, number] | undefined>,
lastPhishingCacheTime: new Date(), lastPhishingCacheTime: new Date(),
lastCctRewardTime: new Date(), lastCctRewardTime: new Date(),
@@ -90,7 +91,7 @@ export function prestigeDarknetState(prestigeSourceFile: boolean): void {
DarknetState.cyclesSinceLastMutation = 0; DarknetState.cyclesSinceLastMutation = 0;
DarknetState.Network = new Array(MAX_NET_DEPTH).fill(null).map(() => new Array<null>(NET_WIDTH).fill(null)); DarknetState.Network = new Array(MAX_NET_DEPTH).fill(null).map(() => new Array<null>(NET_WIDTH).fill(null));
DarknetState.labyrinth = null; DarknetState.labyrinth = null;
DarknetState.labLocations = { "-1": [1, 1] }; DarknetState.labLocations = {};
DarknetState.lastPhishingCacheTime = new Date(); DarknetState.lastPhishingCacheTime = new Date();
DarknetState.lastStormTime = new Date(); DarknetState.lastStormTime = new Date();
DarknetState.stockPromotions = {}; DarknetState.stockPromotions = {};

View File

@@ -144,7 +144,7 @@ export const LabyrinthSummary = ({ isAuthenticating }: LabyrinthSummaryProps): R
<> <>
<div className={classes.inlineFlexBox}> <div className={classes.inlineFlexBox}>
<div style={{ width: "50%" }}> <div style={{ width: "50%" }}>
{!lab.manual ? ( {!lab.manual && currentPerspective === -1 ? (
<Typography style={{ fontStyle: "italic", paddingRight: "10px" }}> <Typography style={{ fontStyle: "italic", paddingRight: "10px" }}>
This lab cannot be completed manually. Select a script PID that is attempting the labyrinth from the This lab cannot be completed manually. Select a script PID that is attempting the labyrinth from the
options below to view its progress. options below to view its progress.

View File

@@ -120,51 +120,35 @@ export function NetworkDisplayWrapper(): React.ReactElement {
} }
}; };
const zoomIn = useCallback(() => { const changeZoom = useCallback(
if (zoomIndex >= zoomOptions.length - 1) { (out = true, mouseX?: number, mouseY?: number) => {
return; if (out && zoomIndex <= 0) return;
} if (!out && zoomIndex >= zoomOptions.length - 1) return;
DarknetState.zoomIndex = Math.max(zoomIndex + 1, 0); const newZoomIndex = out ? zoomIndex - 1 : zoomIndex + 1;
setZoomIndex(DarknetState.zoomIndex); const oldZoom = zoomOptions[zoomIndex];
const zoom = zoomOptions[zoomIndex]; const newZoom = zoomOptions[newZoomIndex];
const background = draggableBackground.current; DarknetState.zoomIndex = newZoomIndex;
scrollTo( setZoomIndex(newZoomIndex);
(background?.scrollTop ?? 0) + ((background?.clientHeight ?? 0) / 4) * zoom, const background = draggableBackground.current;
(background?.scrollLeft ?? 0) + ((background?.clientWidth ?? 0) / 4) * zoom, const mx = mouseX ?? (background?.clientWidth ?? 0) / 2;
); const my = mouseY ?? (background?.clientHeight ?? 0) / 2;
}, [zoomIndex, setZoomIndex, zoomOptions, scrollTo]); scrollTo(
(((background?.scrollTop ?? 0) + my) / oldZoom) * newZoom - my,
const zoomOut = useCallback(() => { (((background?.scrollLeft ?? 0) + mx) / oldZoom) * newZoom - mx,
if (zoomIndex <= 0) { );
return; },
} [zoomIndex, setZoomIndex, zoomOptions, scrollTo],
DarknetState.zoomIndex = Math.min(zoomIndex - 1, zoomOptions.length - 1); );
setZoomIndex(DarknetState.zoomIndex);
const zoom = zoomOptions[zoomIndex];
const background = draggableBackground.current;
scrollTo(
(background?.scrollTop ?? 0) - ((background?.clientHeight ?? 0) / 4) * zoom,
(background?.scrollLeft ?? 0) - ((background?.clientWidth ?? 0) / 4) * zoom,
);
}, [zoomIndex, setZoomIndex, zoomOptions, scrollTo]);
const zoom = useCallback( const zoom = useCallback(
(wheelEvent: WheelEvent) => { (wheelEvent: WheelEvent) => {
const target = wheelEvent.target as HTMLDivElement; if (!draggableBackground.current || DarknetState.openServer) return;
if (!draggableBackground.current || DarknetState.openServer) { const rect = draggableBackground.current.getBoundingClientRect();
return; const mouseX = wheelEvent.clientX - rect.left;
} const mouseY = wheelEvent.clientY - rect.top;
if (wheelEvent.deltaY < 0) { changeZoom(wheelEvent.deltaY > 0, mouseX, mouseY);
zoomIn();
} else {
zoomOut();
}
if (!target?.parentElement?.getBoundingClientRect()) {
return;
}
}, },
[draggableBackground, zoomOut, zoomIn], [draggableBackground, changeZoom],
); );
const zoomRef = useRef(zoom); const zoomRef = useRef(zoom);
@@ -311,10 +295,10 @@ export function NetworkDisplayWrapper(): React.ReactElement {
</div> </div>
</div> </div>
<div className={classes.zoomContainer}> <div className={classes.zoomContainer}>
<Button className={classes.button} onClick={() => zoomIn()}> <Button className={classes.button} onClick={() => changeZoom(false)}>
<ZoomIn /> <ZoomIn />
</Button> </Button>
<Button className={classes.button} onClick={() => zoomOut()}> <Button className={classes.button} onClick={() => changeZoom()}>
<ZoomOut /> <ZoomOut />
</Button> </Button>
</div> </div>

View File

@@ -21,6 +21,7 @@ import { getPasswordType } from "../DarkNet/controllers/ServerGenerator";
import { checkPassword, getAuthResult, isAuthenticated } from "../DarkNet/effects/authentication"; import { checkPassword, getAuthResult, isAuthenticated } from "../DarkNet/effects/authentication";
import { import {
getLabMaze, getLabMaze,
getPositionInLab,
getLabyrinthDetails, getLabyrinthDetails,
getLabyrinthLocationReport, getLabyrinthLocationReport,
getSurroundingsVisualized, getSurroundingsVisualized,
@@ -695,7 +696,7 @@ export function NetscriptDarknet(): InternalAPI<DarknetAPI> {
const authenticationTime = calculateAuthenticationTime(lab, Player, ctx.workerScript.scriptRef.threads); const authenticationTime = calculateAuthenticationTime(lab, Player, ctx.workerScript.scriptRef.threads);
await helpers.netscriptDelay(ctx, authenticationTime); await helpers.netscriptDelay(ctx, authenticationTime);
const [x, y] = DarknetState.labLocations[pid] ?? [1, 1]; const [x, y] = getPositionInLab(pid);
return { return {
success: true, success: true,
message: getSurroundingsVisualized(getLabMaze(), x, y, 3, true, true), message: getSurroundingsVisualized(getLabMaze(), x, y, 3, true, true),

View File

@@ -5646,12 +5646,18 @@ export interface Go {
* ".XO.#", * ".XO.#",
* *
*] *]
*
* @remarks
* RAM cost: 0 GB
*/ */
getMoveHistory(): string[][]; getMoveHistory(): string[][];
/** /**
* Returns the color of the current player, or 'None' if the game is over. * Returns the color of the current player, or 'None' if the game is over.
* @returns "White" | "Black" | "None" * @returns "White" | "Black" | "None"
*
* @remarks
* RAM cost: 0 GB
*/ */
getCurrentPlayer(): "White" | "Black" | "None"; getCurrentPlayer(): "White" | "Black" | "None";
@@ -5659,6 +5665,9 @@ export interface Go {
* Gets the status of the current game. * Gets the status of the current game.
* Shows the current player, current score, and the previous move coordinates. * Shows the current player, current score, and the previous move coordinates.
* Previous move will be null for a pass, or if there are no prior moves. * Previous move will be null for a pass, or if there are no prior moves.
*
* @remarks
* RAM cost: 0 GB
*/ */
getGameState(): { getGameState(): {
currentPlayer: "White" | "Black" | "None"; currentPlayer: "White" | "Black" | "None";
@@ -5671,6 +5680,9 @@ export interface Go {
/** /**
* Returns the name of the opponent faction in the current subnet. * Returns the name of the opponent faction in the current subnet.
*
* @remarks
* RAM cost: 0 GB
*/ */
getOpponent(): GoOpponent; getOpponent(): GoOpponent;