Merge branch 'dev' of github.com:danielyxie/bitburner into dev

This commit is contained in:
Olivier Gagnon 2022-05-04 11:57:44 -04:00
commit 5e9b3b0c4f
26 changed files with 468 additions and 377 deletions

@ -336,12 +336,12 @@ The list contains the name of (i.e. the value returned by
| | | |
| | | You are given an LZ-encoded string. Decode it and output the original string. |
| | | |
| | | Example: decoding '5aaabc340533bca' chunk-by-chunk |
| | | 5aaabc -> aaabc |
| | | 5aaabc34 -> aaabcaab |
| | | 5aaabc340 -> aaabcaab |
| | | 5aaabc34053 -> aaabcaabaabaa |
| | | 5aaabc340533bca -> aaabcaabaabaabca |
| | | Example: decoding '5aaabb450723abb' chunk-by-chunk |
| | | 5aaabb -> aaabb |
| | | 5aaabb45 -> aaabbaaab |
| | | 5aaabb450 -> aaabbaaab |
| | | 5aaabb45072 -> aaabbaaababababa |
| | | 5aaabb450723abb -> aaabbaaababababaabb |
+-----------------------------------------+------------------------------------------------------------------------------------------+
| Compression III: LZ Compression | | Lempel-Ziv (LZ) compression is a data compression technique which encodes data using |
| | | references to earlier parts of the data. In this variant of LZ, data is encoded in two |
@ -366,7 +366,7 @@ The list contains the name of (i.e. the value returned by
| | | aAAaAAaAaAA -> 3aAA53035 |
| | | 2718281828 -> 627182844 |
| | | abcdefghijk -> 9abcdefghi02jk |
| | | aaaaaaaaaaa -> 1a911a |
| | | aaaaaaaaaaaa -> 1a912aa |
| | | aaaaaaaaaaaa -> 3aaa91 |
| | | aaaaaaaaaaaaa -> 1a91031 |
| | | aaaaaaaaaaaaaa -> 1a91041 |
+-----------------------------------------+------------------------------------------------------------------------------------------+

@ -189,9 +189,9 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
title={
<Typography>
Forcefully kill all active running scripts, in case there is a bug or some unexpected issue with the game.
After using this, save the game and then reload the page. This is different then normal kill in that
After using this, save the game and then reload the page. This is different than normal kill in that
normal kill will tell the script to shut down while force kill just removes the references to it (and it
should crash on it's own). This will not remove the files on your computer. Just forcefully kill all
should crash on its own). This will not remove the files on your computer, just forcefully kill all
running instances of all scripts.
</Typography>
}
@ -210,7 +210,7 @@ export const GameOptionsSidebar = (props: IProps): React.ReactElement => {
title={
<Typography>
If your save file is extremely big you can use this button to view a map of all the files on every server.
Be careful there might be spoilers.
Be careful: there might be spoilers.
</Typography>
}
>

@ -1,15 +1,14 @@
import { Paper, Typography } from "@mui/material";
import React, { useState } from "react";
import Grid from "@mui/material/Grid";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { KEY } from "../../utils/helpers/keyCodes";
import { random } from "../utils";
import { BlinkingCursor } from "./BlinkingCursor";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { random } from "../utils";
import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { Player } from "../../Player";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
interface Difficulty {
[key: string]: number;
@ -48,24 +47,18 @@ export function BackwardGame(props: IMinigameProps): React.ReactElement {
}
return (
<Grid container spacing={3}>
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Paper sx={{ display: "grid", justifyItems: "center", pb: 1 }}>
<Typography variant="h4">Type it{!hasAugment ? " backward" : ""}</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
<Grid item xs={6}>
<Typography style={{ transform: hasAugment ? "none" : "scaleX(-1)", marginLeft: hasAugment ? "50%" : "none" }}>
{answer}
</Typography>
</Grid>
<Grid item xs={6}>
<Typography style={{ transform: hasAugment ? "none" : "scaleX(-1)" }}>{answer}</Typography>
<Typography>
{guess}
<BlinkingCursor />
</Typography>
</Grid>
</Grid>
</Paper>
</>
);
}

@ -1,4 +1,4 @@
import React, { useState, useEffect } from "react";
import React, { useEffect, useState } from "react";
export function BlinkingCursor(): React.ReactElement {
const [on, setOn] = useState(true);
@ -6,5 +6,5 @@ export function BlinkingCursor(): React.ReactElement {
const i = setInterval(() => setOn((old) => !old), 1000);
return () => clearInterval(i);
});
return <>{on ? "|" : ""}</>;
return <>{on ? "|" : <>&nbsp;</>}</>;
}

@ -1,15 +1,14 @@
import { Paper, Typography } from "@mui/material";
import React, { useState } from "react";
import Grid from "@mui/material/Grid";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { KEY } from "../../utils/helpers/keyCodes";
import { random } from "../utils";
import { BlinkingCursor } from "./BlinkingCursor";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { random } from "../utils";
import { interpolate } from "./Difficulty";
import { BlinkingCursor } from "./BlinkingCursor";
import Typography from "@mui/material/Typography";
import { Player } from "../../Player";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { KEY } from "../../utils/helpers/keyCodes";
interface Difficulty {
[key: string]: number;
@ -84,16 +83,16 @@ export function BracketGame(props: IMinigameProps): React.ReactElement {
}
return (
<Grid container spacing={3}>
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Paper sx={{ display: "grid", justifyItems: "center" }}>
<Typography variant="h4">Close the brackets</Typography>
<Typography style={{ fontSize: "5em" }}>
{`${left}${right}`}
<BlinkingCursor />
</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
</Grid>
</Paper>
</>
);
}

@ -1,15 +1,14 @@
import { Paper, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import Grid from "@mui/material/Grid";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { KEY } from "../../utils/helpers/keyCodes";
import { downArrowSymbol, upArrowSymbol } from "../utils";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
interface Difficulty {
[key: string]: number;
@ -88,13 +87,11 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
}
return (
<Grid container spacing={3}>
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Typography variant="h4">Say something nice about the guard.</Typography>
<Paper sx={{ display: "grid", justifyItems: "center" }}>
<Typography variant="h4">Say something nice about the guard</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
<Grid item xs={6}>
<Typography variant="h5" color={upColor}>
{upArrowSymbol}
</Typography>
@ -104,8 +101,8 @@ export function BribeGame(props: IMinigameProps): React.ReactElement {
<Typography variant="h5" color={downColor}>
{downArrowSymbol}
</Typography>
</Grid>
</Grid>
</Paper>
</>
);
}
@ -154,6 +151,7 @@ const positive = [
"patient",
"dynamic",
"loyal",
"based",
];
const negative = [
@ -177,4 +175,5 @@ const negative = [
"picky",
"tactless",
"thoughtless",
"cringe",
];

@ -1,21 +1,20 @@
import { Paper, Typography } from "@mui/material";
import React, { useState } from "react";
import Grid from "@mui/material/Grid";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import {
random,
downArrowSymbol,
getArrow,
getInverseArrow,
leftArrowSymbol,
random,
rightArrowSymbol,
upArrowSymbol,
downArrowSymbol,
} from "../utils";
import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
interface Difficulty {
[key: string]: number;
@ -55,14 +54,14 @@ export function CheatCodeGame(props: IMinigameProps): React.ReactElement {
}
return (
<Grid container spacing={3}>
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Paper sx={{ display: "grid", justifyItems: "center" }}>
<Typography variant="h4">Enter the Code!</Typography>
<Typography variant="h4">{code[index]}</Typography>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
</Grid>
</Paper>
</>
);
}

@ -1,7 +1,6 @@
import React, { useState, useEffect } from "react";
import Grid from "@mui/material/Grid";
import { Paper, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import Typography from "@mui/material/Typography";
interface IProps {
onFinish: () => void;
}
@ -13,17 +12,13 @@ export function Countdown(props: IProps): React.ReactElement {
props.onFinish();
return;
}
setTimeout(() => setX(x - 1), 200);
setTimeout(() => setX(x - 1), 300);
});
return (
<>
<Grid container spacing={3}>
<Grid item xs={12}>
<Paper sx={{ p: 1, textAlign: "center" }}>
<Typography variant="h4">Get Ready!</Typography>
<Typography variant="h4">{x}</Typography>
</Grid>
</Grid>
</>
</Paper>
);
}

@ -1,15 +1,14 @@
import { Paper, Typography, Box } from "@mui/material";
import React, { useState } from "react";
import Grid from "@mui/material/Grid";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty";
import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { Settings } from "../../Settings/Settings";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { KEY } from "../../utils/helpers/keyCodes";
import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
interface Difficulty {
[key: string]: number;
@ -19,6 +18,12 @@ interface Difficulty {
symbols: number;
}
interface GridItem {
content: string;
color: string;
selected?: boolean;
}
const difficulties: {
Trivial: Difficulty;
Normal: Difficulty;
@ -76,18 +81,33 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
}
}
const flatGrid: GridItem[] = [];
grid.map((line, y) =>
line.map((cell, x) => {
const isCorrectAnswer = cell === answers[currentAnswerIndex];
const optionColor = hasAugment && !isCorrectAnswer ? Settings.theme.disabled : Settings.theme.primary;
if (x === pos[0] && y === pos[1]) {
flatGrid.push({ color: optionColor, content: cell, selected: true });
return;
}
flatGrid.push({ color: optionColor, content: cell });
}),
);
const fontSize = "2em";
return (
<Grid container spacing={3}>
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Paper sx={{ display: "grid", justifyItems: "center", pb: 1 }}>
<Typography variant="h4">Match the symbols!</Typography>
<Typography variant="h5" color={Settings.theme.primary}>
Targets:{" "}
{answers.map((a, i) => {
if (i == currentAnswerIndex)
return (
<span key={`${i}`} style={{ fontSize: "1em", color: "blue" }}>
<span key={`${i}`} style={{ fontSize: "1em", color: Settings.theme.infolight }}>
{a}&nbsp;
</span>
);
@ -99,34 +119,30 @@ export function Cyberpunk2077Game(props: IMinigameProps): React.ReactElement {
})}
</Typography>
<br />
{grid.map((line, y) => (
<div key={y}>
<Typography>
{line.map((cell, x) => {
const isCorrectAnswer = cell === answers[currentAnswerIndex];
if (x == pos[0] && y == pos[1]) {
return (
<span key={`${x}${y}`} style={{ fontSize: fontSize, color: "blue" }}>
{cell}&nbsp;
</span>
);
}
const optionColor = hasAugment && !isCorrectAnswer ? Settings.theme.disabled : Settings.theme.primary;
return (
<span key={`${x}${y}`} style={{ fontSize: fontSize, color: optionColor }}>
{cell}&nbsp;
</span>
);
})}
<Box
sx={{
display: "grid",
gridTemplateColumns: `repeat(${Math.round(difficulty.width)}, 1fr)`,
gap: 1,
}}
>
{flatGrid.map((item) => (
<Typography
sx={{
fontSize: fontSize,
color: item.color,
border: item.selected ? `2px solid ${Settings.theme.infolight}` : "unset",
lineHeight: "unset",
p: item.selected ? "2px" : "4px",
}}
>
{item.content}
</Typography>
<br />
</div>
))}
</Box>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
</Grid>
</Paper>
</>
);
}

@ -1,19 +1,17 @@
import { use } from "../../ui/Context";
import { Button, Container, Paper, Typography } from "@mui/material";
import React, { useState } from "react";
import Grid from "@mui/material/Grid";
import Button from "@mui/material/Button";
import { Countdown } from "./Countdown";
import { BracketGame } from "./BracketGame";
import { SlashGame } from "./SlashGame";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { use } from "../../ui/Context";
import { BackwardGame } from "./BackwardGame";
import { BracketGame } from "./BracketGame";
import { BribeGame } from "./BribeGame";
import { CheatCodeGame } from "./CheatCodeGame";
import { Countdown } from "./Countdown";
import { Cyberpunk2077Game } from "./Cyberpunk2077Game";
import { MinesweeperGame } from "./MinesweeperGame";
import { WireCuttingGame } from "./WireCuttingGame";
import { SlashGame } from "./SlashGame";
import { Victory } from "./Victory";
import Typography from "@mui/material/Typography";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { WireCuttingGame } from "./WireCuttingGame";
interface IProps {
StartingDifficulty: number;
@ -139,22 +137,20 @@ export function Game(props: IProps): React.ReactElement {
}
return (
<>
<Grid container spacing={3}>
<Grid item xs={3}>
<Button onClick={cancel}>Cancel</Button>
</Grid>
<Grid item xs={3}>
<Typography>
Level: {level}&nbsp;/&nbsp;{props.MaxLevel}
<Container>
<Paper sx={{ p: 1, mb: 1, display: "grid", justifyItems: "center", gap: 1 }}>
{stage !== Stage.Sell && (
<Button sx={{ width: "100%" }} onClick={cancel}>
Cancel Infiltration
</Button>
)}
<Typography variant="h5">
Level {level} / {props.MaxLevel}
</Typography>
<Progress />
</Grid>
</Paper>
<Grid item xs={12}>
{stageComponent}
</Grid>
</Grid>
</>
</Container>
);
}

@ -1,10 +1,9 @@
import LinearProgress from "@mui/material/LinearProgress";
import React, { useState, useEffect } from "react";
import withStyles from "@mui/styles/withStyles";
import { LinearProgress, Paper } from "@mui/material";
import { Theme } from "@mui/material/styles";
import Grid from "@mui/material/Grid";
import { use } from "../../ui/Context";
import withStyles from "@mui/styles/withStyles";
import React, { useEffect, useState } from "react";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { use } from "../../ui/Context";
const TimerProgress = withStyles((theme: Theme) => ({
root: {
@ -19,6 +18,7 @@ const TimerProgress = withStyles((theme: Theme) => ({
interface IProps {
millis: number;
onExpire: () => void;
noPaper?: boolean;
}
export function GameTimer(props: IProps): React.ReactElement {
@ -42,9 +42,11 @@ export function GameTimer(props: IProps): React.ReactElement {
// https://stackoverflow.com/questions/55593367/disable-material-uis-linearprogress-animation
// TODO(hydroflame): there's like a bug where it triggers the end before the
// bar physically reaches the end
return (
<Grid item xs={12}>
return props.noPaper ? (
<TimerProgress variant="determinate" value={v} color="primary" />
</Grid>
) : (
<Paper sx={{ p: 1, mb: 1 }}>
<TimerProgress variant="determinate" value={v} color="primary" />
</Paper>
);
}

@ -1,9 +1,9 @@
import React, { useState } from "react";
import { Intro } from "./Intro";
import { Game } from "./Game";
import { Location } from "../../Locations/Location";
import { use } from "../../ui/Context";
import { calculateDifficulty, calculateReward } from "../formulas/game";
import { Game } from "./Game";
import { Intro } from "./Intro";
interface IProps {
location: Location;
}
@ -22,8 +22,16 @@ export function InfiltrationRoot(props: IProps): React.ReactElement {
router.toCity();
}
if (!start) {
return (
<div style={{ display: "flex", alignItems: "center", height: "calc(100vh - 16px)" }}>
{start ? (
<Game
StartingDifficulty={startingSecurityLevel}
Difficulty={difficulty}
Reward={reward}
MaxLevel={props.location.infiltrationData.maxClearanceLevel}
/>
) : (
<Intro
Location={props.location}
Difficulty={difficulty}
@ -31,15 +39,7 @@ export function InfiltrationRoot(props: IProps): React.ReactElement {
start={() => setStart(true)}
cancel={cancel}
/>
);
}
return (
<Game
StartingDifficulty={startingSecurityLevel}
Difficulty={difficulty}
Reward={reward}
MaxLevel={props.location.infiltrationData.maxClearanceLevel}
/>
)}
</div>
);
}

@ -1,8 +1,8 @@
import { Report } from "@mui/icons-material";
import { Box, Button, Container, Paper, Tooltip, Typography } from "@mui/material";
import React from "react";
import { Location } from "../../Locations/Location";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import { Settings } from "../../Settings/Settings";
import { numeralWrapper } from "../../ui/numeralFormat";
interface IProps {
@ -41,9 +41,9 @@ function coloredArrow(difficulty: number): JSX.Element {
} else {
return (
<>
{arrowPart("white", difficulty * 13)}
{arrowPart("orange", (difficulty - 1) * 13)}
{arrowPart("red", (difficulty - 2) * 13)}
{arrowPart(Settings.theme.primary, difficulty * 13)}
{arrowPart(Settings.theme.warning, (difficulty - 1) * 13)}
{arrowPart(Settings.theme.error, (difficulty - 2) * 13)}
</>
);
}
@ -51,65 +51,84 @@ function coloredArrow(difficulty: number): JSX.Element {
export function Intro(props: IProps): React.ReactElement {
return (
<>
<Grid container spacing={3}>
<Grid item xs={10}>
<Typography variant="h4">Infiltrating {props.Location.name}</Typography>
</Grid>
<Grid item xs={10}>
<Typography variant="h5" color="primary">
Maximum level: {props.MaxLevel}
<Container sx={{ alignItems: "center" }}>
<Paper sx={{ p: 1, mb: 1, display: "grid", justifyItems: "center" }}>
<Typography variant="h4">
Infiltrating <b>{props.Location.name}</b>
</Typography>
</Grid>
<Grid item xs={10}>
<Typography variant="h5" color="primary">
Difficulty: {numeralWrapper.format(props.Difficulty * 33.3333, "0")} / 100
<Typography variant="h6">
<b>Maximum Level: </b>
{props.MaxLevel}
</Typography>
</Grid>
<Typography
variant="h6"
sx={{
color:
props.Difficulty > 2
? Settings.theme.error
: props.Difficulty > 1
? Settings.theme.warning
: Settings.theme.primary,
display: "flex",
alignItems: "center",
}}
>
<b>Difficulty:&nbsp;</b>
{numeralWrapper.format(props.Difficulty * 33.3333, "0")} / 100
{props.Difficulty > 1.5 && (
<Grid item xs={10}>
<Typography variant="h5" color="primary">
Warning: This location is too heavily guarded for your current stats, try training or finding an easier
location.
<Tooltip
title={
<Typography color="error">
This location is too heavily guarded for your current stats. It is recommended that you try training,
or finding an easier location.
</Typography>
</Grid>
}
>
<Report sx={{ ml: 1 }} />
</Tooltip>
)}
</Typography>
<Grid item xs={10}>
<Typography sx={{ lineHeight: "1em", whiteSpace: "pre" }}>[{coloredArrow(props.Difficulty)}]</Typography>
<Typography
sx={{ lineHeight: "1em", whiteSpace: "pre" }}
>{` ^ ^ ^ ^`}</Typography>
>{`▲ ▲ ▲ ▲`}</Typography>
<Typography
sx={{ lineHeight: "1em", whiteSpace: "pre" }}
>{` Trivial Normal Hard Impossible`}</Typography>
</Grid>
<Grid item xs={10}>
<Typography>
Infiltration is a series of short minigames that get progressively harder. You take damage for failing them.
Reaching the maximum level rewards you with intel you can trade for money or reputation.
</Paper>
<Paper sx={{ p: 1, display: "grid", justifyItems: "center" }}>
<Typography sx={{ width: "75%", textAlign: "center" }}>
<b>Infiltration</b> is a series of short minigames that get progressively harder. You take damage for failing
them. Reaching the maximum level rewards you with intel that you can trade for money or reputation.
<br />
<br />
<b>Gameplay:</b>
</Typography>
<br />
<ul>
<Typography>
The minigames you play are randomly selected. It might take you few tries to get used to them.
<li>
The minigames you play are randomly selected.
<br />
It might take you a few tries to get used to them.
</li>
<li>No game requires use of the mouse.</li>
<li>
<b>Spacebar</b> is the default action/confirm button.
</li>
<li>
The <b>arrow keys</b> and <b>WASD</b> can be used interchangeably.
</li>
<li>Sometimes the rest of the keyboard is used.</li>
</Typography>
<br />
<Typography>No game require use of the mouse.</Typography>
<br />
<Typography>Spacebar is the default action/confirm button.</Typography>
<br />
<Typography>Everything that uses arrow can also use WASD</Typography>
<br />
<Typography>Sometimes the rest of the keyboard is used.</Typography>
</Grid>
<Grid item xs={3}>
</ul>
<Box sx={{ display: "grid", gridTemplateColumns: "1fr 1fr", width: "100%" }}>
<Button onClick={props.start}>Start</Button>
</Grid>
<Grid item xs={3}>
<Button onClick={props.cancel}>Cancel</Button>
</Grid>
</Grid>
</>
</Box>
</Paper>
</Container>
);
}

@ -1,14 +1,16 @@
import React, { useState, useEffect } from "react";
import Grid from "@mui/material/Grid";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty";
import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { Close, Flag, Report } from "@mui/icons-material";
import { Box, Paper, Typography } from "@mui/material";
import { uniqueId } from "lodash";
import React, { useEffect, useState } from "react";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { KEY } from "../../utils/helpers/keyCodes";
import { downArrowSymbol, getArrow, leftArrowSymbol, rightArrowSymbol, upArrowSymbol } from "../utils";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
interface Difficulty {
[key: string]: number;
@ -81,32 +83,77 @@ export function MinesweeperGame(props: IMinigameProps): React.ReactElement {
return () => clearInterval(id);
}, []);
return (
<Grid container spacing={3}>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Typography variant="h4">{memoryPhase ? "Remember all the mines!" : "Mark all the mines!"}</Typography>
{minefield.map((line, y) => (
<div key={y}>
<Typography>
{line.map((cell, x) => {
const flatGrid: { flagged?: boolean; current?: boolean; marked?: boolean }[] = [];
minefield.map((line, y) =>
line.map((cell, x) => {
if (memoryPhase) {
if (minefield[y][x]) return <span key={x}>[?]&nbsp;</span>;
return <span key={x}>[&nbsp;]&nbsp;</span>;
flatGrid.push({ flagged: Boolean(minefield[y][x]) });
return;
} else if (x === pos[0] && y === pos[1]) {
flatGrid.push({ current: true });
} else if (answer[y][x]) {
flatGrid.push({ marked: true });
} else if (hasAugment && minefield[y][x]) {
flatGrid.push({ flagged: true });
} else {
if (x == pos[0] && y == pos[1]) return <span key={x}>[X]&nbsp;</span>;
if (answer[y][x]) return <span key={x}>[.]&nbsp;</span>;
if (hasAugment && minefield[y][x]) return <span key={x}>[?]&nbsp;</span>;
return <span key={x}>[&nbsp;]&nbsp;</span>;
flatGrid.push({});
}
})}
}),
);
return (
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Paper sx={{ display: "grid", justifyItems: "center", pb: 1 }}>
<Typography variant="h4">{memoryPhase ? "Remember all the mines!" : "Mark all the mines!"}</Typography>
<Box
sx={{
display: "grid",
gridTemplateColumns: `repeat(${Math.round(difficulty.width)}, 1fr)`,
gridTemplateRows: `repeat(${Math.round(difficulty.height)}, 1fr)`,
gap: 1,
}}
>
{flatGrid.map((item) => {
let color: string;
let icon: React.ReactElement;
if (item.marked) {
color = Settings.theme.warning;
icon = <Flag />;
} else if (item.current) {
color = Settings.theme.infolight;
icon = <Close />;
} else if (item.flagged) {
color = Settings.theme.error;
icon = <Report />;
} else {
color = Settings.theme.primary;
icon = <></>;
}
return (
<Typography
key={`${item}${uniqueId()}`}
sx={{
color: color,
border: `2px solid ${item.current ? Settings.theme.infolight : Settings.theme.primary}`,
height: "32px",
width: "32px",
display: "flex",
alignItems: "center",
justifyContent: "center",
}}
>
{icon}
</Typography>
<br />
</div>
))}
);
})}
</Box>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
</Grid>
</Paper>
</>
);
}

@ -1,13 +1,12 @@
import React, { useState, useEffect } from "react";
import Grid from "@mui/material/Grid";
import { Box, Paper, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { KEY } from "../../utils/helpers/keyCodes";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { interpolate } from "./Difficulty";
import Typography from "@mui/material/Typography";
import { KEY } from "../../utils/helpers/keyCodes";
import { Player } from "../../Player";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
interface Difficulty {
[key: string]: number;
@ -59,23 +58,25 @@ export function SlashGame(props: IMinigameProps): React.ReactElement {
}, []);
return (
<Grid container spacing={3}>
<GameTimer millis={5000} onExpire={props.onFailure} />
<Grid item xs={12}>
<Typography variant="h4">Slash when his guard is down!</Typography>
{hasAugment ? (
<>
<Typography variant="h4">Guard will drop in...</Typography>
<GameTimer millis={timeUntilAttacking} onExpire={props.onFailure} />
</>
<GameTimer millis={5000} onExpire={props.onFailure} />
<Paper sx={{ display: "grid", justifyItems: "center" }}>
<Typography variant="h4">Slash when his guard is down!</Typography>
{hasAugment ? (
<Box sx={{ my: 1 }}>
<Typography variant="h5">Guard will drop in...</Typography>
<GameTimer millis={timeUntilAttacking} onExpire={() => null} noPaper />
</Box>
) : (
<></>
)}
{phase === 0 && <Typography variant="h4">Guarding ...</Typography>}
{phase === 1 && <Typography variant="h4">Preparing?</Typography>}
{phase === 2 && <Typography variant="h4">ATTACKING!</Typography>}
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
</Grid>
</Paper>
</>
);
}

@ -1,21 +1,17 @@
import { Factions } from "../../Faction/Factions";
import { Box, Button, MenuItem, Paper, Select, SelectChangeEvent, Typography } from "@mui/material";
import React, { useState } from "react";
import Grid from "@mui/material/Grid";
import { FactionNames } from "../../Faction/data/FactionNames";
import { inviteToFaction } from "../../Faction/FactionHelpers";
import { Factions } from "../../Faction/Factions";
import { use } from "../../ui/Context";
import { Money } from "../../ui/React/Money";
import { Reputation } from "../../ui/React/Reputation";
import { use } from "../../ui/Context";
import Typography from "@mui/material/Typography";
import Button from "@mui/material/Button";
import MenuItem from "@mui/material/MenuItem";
import Select, { SelectChangeEvent } from "@mui/material/Select";
import { FactionNames } from "../../Faction/data/FactionNames";
import { formatNumber } from "../../utils/StringHelperFunctions";
import {
calculateInfiltratorsRepReward,
calculateSellInformationCashReward,
calculateTradeInformationRepReward,
} from "../formulas/victory";
import { inviteToFaction } from "../../Faction/FactionHelpers";
interface IProps {
StartingDifficulty: number;
@ -66,13 +62,9 @@ export function Victory(props: IProps): React.ReactElement {
}
return (
<>
<Grid container spacing={3}>
<Grid item xs={10}>
<Paper sx={{ p: 1, textAlign: "center", display: "flex", alignItems: "center", flexDirection: "column" }}>
<Typography variant="h4">Infiltration successful!</Typography>
</Grid>
<Grid item xs={10}>
<Typography variant="h5" color="primary">
<Typography variant="h5" color="primary" width="75%">
You{" "}
{isMemberOfInfiltrators ? (
<>
@ -83,7 +75,9 @@ export function Victory(props: IProps): React.ReactElement {
)}
can trade the confidential information you found for money or reputation.
</Typography>
<Select value={faction} onChange={changeDropdown}>
<Box sx={{ width: "fit-content" }}>
<Box sx={{ width: "100%" }}>
<Select value={faction} onChange={changeDropdown} sx={{ mr: 1 }}>
<MenuItem key={"none"} value={"none"}>
{"none"}
</MenuItem>
@ -98,17 +92,15 @@ export function Victory(props: IProps): React.ReactElement {
<Button onClick={trade}>
Trade for <Reputation reputation={repGain} /> reputation
</Button>
</Grid>
<Grid item xs={3}>
<Button onClick={sell}>
</Box>
<Button onClick={sell} sx={{ width: "100%" }}>
Sell for&nbsp;
<Money money={moneyGain} />
</Button>
</Grid>
<Grid item xs={3}>
<Button onClick={quitInfiltration}>Quit</Button>
</Grid>
</Grid>
</>
</Box>
<Button onClick={quitInfiltration} sx={{ width: "100%", mt: 1 }}>
Quit
</Button>
</Paper>
);
}

@ -1,15 +1,14 @@
import { Box, Paper, Typography } from "@mui/material";
import React, { useEffect, useState } from "react";
import Grid from "@mui/material/Grid";
import Typography from "@mui/material/Typography";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
import { GameTimer } from "./GameTimer";
import { random } from "../utils";
import { interpolate } from "./Difficulty";
import { KEY } from "../../utils/helpers/keyCodes";
import { AugmentationNames } from "../../Augmentation/data/AugmentationNames";
import { Player } from "../../Player";
import { Settings } from "../../Settings/Settings";
import { KEY } from "../../utils/helpers/keyCodes";
import { random } from "../utils";
import { interpolate } from "./Difficulty";
import { GameTimer } from "./GameTimer";
import { IMinigameProps } from "./IMinigameProps";
import { KeyHandler } from "./KeyHandler";
interface Difficulty {
[key: string]: number;
@ -102,46 +101,53 @@ export function WireCuttingGame(props: IMinigameProps): React.ReactElement {
}
return (
<Grid container spacing={3}>
<>
<GameTimer millis={timer} onExpire={props.onFailure} />
<Grid item xs={12}>
<Typography variant="h4">Cut the wires with the following properties! (keyboard 1 to 9)</Typography>
<Paper sx={{ display: "grid", justifyItems: "center", pb: 1 }}>
<Typography variant="h4" sx={{ width: "75%", textAlign: "center" }}>
Cut the wires with the following properties! (keyboard 1 to 9)
</Typography>
{questions.map((question, i) => (
<Typography key={i}>{question.toString()}</Typography>
))}
<Typography>
<Box
sx={{
display: "grid",
gridTemplateColumns: `repeat(${wires.length}, 1fr)`,
columnGap: 3,
justifyItems: "center",
}}
>
{new Array(wires.length).fill(0).map((_, i) => {
const isCorrectWire = checkWire(i + 1);
const color = hasAugment && !isCorrectWire ? Settings.theme.disabled : Settings.theme.primary;
return (
<span key={i} style={{ color: color }}>
&nbsp;{i + 1}&nbsp;&nbsp;&nbsp;&nbsp;
</span>
<Typography key={i} style={{ color: color }}>
{i + 1}
</Typography>
);
})}
</Typography>
{new Array(8).fill(0).map((_, i) => (
<div key={i}>
<Typography>
<React.Fragment key={i}>
{wires.map((wire, j) => {
if ((i === 3 || i === 4) && cutWires[j]) {
return <span key={j}>&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;&nbsp;</span>;
return <Typography key={j}></Typography>;
}
const isCorrectWire = checkWire(j + 1);
const wireColor =
hasAugment && !isCorrectWire ? Settings.theme.disabled : wire.colors[i % wire.colors.length];
return (
<span key={j} style={{ color: wireColor }}>
|{wire.tpe}|&nbsp;&nbsp;&nbsp;
</span>
<Typography key={j} style={{ color: wireColor }}>
|{wire.tpe}|
</Typography>
);
})}
</Typography>
</div>
</React.Fragment>
))}
</Box>
<KeyHandler onKeyDown={press} onFailure={props.onFailure} />
</Grid>
</Grid>
</Paper>
</>
);
}

@ -156,6 +156,7 @@ const singularity: IMap<any> = {
getUpgradeHomeCoresCost: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 2),
workForCompany: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
applyToCompany: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
quitJob: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost),
getCompanyRep: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 3),
getCompanyFavor: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 3),
getCompanyFavorGain: SF4Cost(RamCostConstants.ScriptSingularityFn2RamCost / 4),

@ -342,7 +342,7 @@ export function NetscriptGang(player: IPlayer, workerScript: WorkerScript, helpe
checkGangApiAccess("getBonusTime");
const gang = player.gang;
if (gang === null) throw new Error("Should not be called without Gang");
return Math.round(gang.storedCycles / 5);
return Math.round(gang.storedCycles / 5) * 1000;
},
};
}

@ -947,6 +947,12 @@ export function NetscriptSingularity(player: IPlayer, workerScript: WorkerScript
}
return res;
},
quitJob: (_ctx: NetscriptContext) =>
function (_companyName: unknown): void {
_ctx.helper.checkSingularityAccess();
const companyName = _ctx.helper.string("companyName", _companyName);
player.quitJob(companyName);
},
getCompanyRep: (_ctx: NetscriptContext) =>
function (_companyName: unknown): number {
_ctx.helper.checkSingularityAccess();

@ -248,7 +248,7 @@ export interface IPlayer {
queryStatFromString(str: string): number;
getIntelligenceBonus(weight: number): number;
getCasinoWinnings(): number;
quitJob(company: string): void;
quitJob(company: string, sing?: boolean): void;
hasJob(): boolean;
createHacknetServer(): HacknetServer;
startCreateProgramWork(programName: string, time: number, reqLevel: number): void;

@ -258,7 +258,7 @@ export class PlayerObject implements IPlayer {
queryStatFromString: (str: string) => number;
getIntelligenceBonus: (weight: number) => number;
getCasinoWinnings: () => number;
quitJob: (company: string) => void;
quitJob: (company: string, sing?: boolean) => void;
hasJob: () => boolean;
process: (router: IRouter, numCycles?: number) => void;
createHacknetServer: () => HacknetServer;

@ -1869,7 +1869,7 @@ export function getNextCompanyPosition(
return entryPosType;
}
export function quitJob(this: IPlayer, company: string): void {
export function quitJob(this: IPlayer, company: string, _sing = false): void {
if (this.isWorking == true && this.workType.includes("Working for Company") && this.companyName == company) {
this.finishWork(true);
}

@ -1800,6 +1800,18 @@ export interface Singularity {
*/
workForCompany(companyName?: string, focus?: boolean): boolean;
/**
* Quit jobs by company.
* @remarks
* RAM cost: 3 GB * 16/4/1
*
*
* This function will finish work with the company provided and quit any jobs.
*
* @param companyName - Name of the company.
*/
quitJob(companyName?: string): void;
/**
* Apply for a job at a company.
* @remarks
@ -6127,7 +6139,7 @@ export interface NS {
* Returns 0 if the script does not exist.
*
* @param script - Filename of script. This is case-sensitive.
* @param host - Host of target server the script is located on. This is optional, If it is not specified then the function will se the current server as the target server.
* @param host - Host of target server the script is located on. This is optional, if it is not specified then the function will use the current server as the target server.
* @returns Amount of RAM (in GB) required to run the specified script on the target server, and 0 if the script does not exist.
*/
getScriptRam(script: string, host?: string): number;

@ -1532,7 +1532,8 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
length += 2;
}
}
return ans.length === length;
return ans.length <= length;
},
},
{
@ -1555,12 +1556,12 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
"You are given the following LZ-encoded string:\n",
`&nbsp; &nbsp; ${compressed}\n`,
"Decode it and output the original string.\n\n",
"Example: decoding '5aaabc340533bca' chunk-by-chunk\n",
"&nbsp; &nbsp; 5aaabc &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -> &nbsp;aaabc\n",
"&nbsp; &nbsp; 5aaabc34 &nbsp; &nbsp; &nbsp; &nbsp; -> &nbsp;aaabcaab\n",
"&nbsp; &nbsp; 5aaabc340 &nbsp; &nbsp; &nbsp; &nbsp;-> &nbsp;aaabcaab\n",
"&nbsp; &nbsp; 5aaabc34053 &nbsp; &nbsp; &nbsp;-> &nbsp;aaabcaabaabaa\n",
"&nbsp; &nbsp; 5aaabc340533bca &nbsp;-> &nbsp;aaabcaabaabaabca",
"Example: decoding '5aaabb450723abb' chunk-by-chunk\n",
"&nbsp; &nbsp; 5aaabb &nbsp; &nbsp; &nbsp; &nbsp; &nbsp; -> &nbsp;aaabb\n",
"&nbsp; &nbsp; 5aaabb45 &nbsp; &nbsp; &nbsp; &nbsp; -> &nbsp;aaabbaaab\n",
"&nbsp; &nbsp; 5aaabb450 &nbsp; &nbsp; &nbsp; &nbsp;-> &nbsp;aaabbaaab\n",
"&nbsp; &nbsp; 5aaabb45072 &nbsp; &nbsp; &nbsp;-> &nbsp;aaabbaaababababa\n",
"&nbsp; &nbsp; 5aaabb450723abb &nbsp;-> &nbsp;aaabbaaababababaabb",
].join(" ");
},
gen: (): string => {
@ -1591,21 +1592,21 @@ export const codingContractTypesMetadata: ICodingContractTypeMetadata[] = [
`&nbsp; &nbsp; ${plaintext}\n`,
"Encode it using Lempel-Ziv encoding with the minimum possible output length.\n\n",
"Examples (some have other possible encodings of minimal length):\n",
"&nbsp; &nbsp; abracadabra &nbsp; &nbsp;-> &nbsp;7abracad47\n",
"&nbsp; &nbsp; mississippi &nbsp; &nbsp;-> &nbsp;4miss433ppi\n",
"&nbsp; &nbsp; aAAaAAaAaAA &nbsp; &nbsp;-> &nbsp;3aAA53035\n",
"&nbsp; &nbsp; 2718281828 &nbsp; &nbsp; -> &nbsp;627182844\n",
"&nbsp; &nbsp; abcdefghijk &nbsp; &nbsp;-> &nbsp;9abcdefghi02jk\n",
"&nbsp; &nbsp; aaaaaaaaaaa &nbsp; &nbsp;-> &nbsp;1a911a\n",
"&nbsp; &nbsp; aaaaaaaaaaaa &nbsp; -> &nbsp;1a912aa\n",
"&nbsp; &nbsp; aaaaaaaaaaaaa &nbsp;-> &nbsp;1a91031",
"&nbsp; &nbsp; abracadabra &nbsp; &nbsp; -> &nbsp;7abracad47\n",
"&nbsp; &nbsp; mississippi &nbsp; &nbsp; -> &nbsp;4miss433ppi\n",
"&nbsp; &nbsp; aAAaAAaAaAA &nbsp; &nbsp; -> &nbsp;3aAA53035\n",
"&nbsp; &nbsp; 2718281828 &nbsp; &nbsp; &nbsp;-> &nbsp;627182844\n",
"&nbsp; &nbsp; abcdefghijk &nbsp; &nbsp; -> &nbsp;9abcdefghi02jk\n",
"&nbsp; &nbsp; aaaaaaaaaaaa &nbsp; &nbsp;-> &nbsp;3aaa91\n",
"&nbsp; &nbsp; aaaaaaaaaaaaa &nbsp; -> &nbsp;1a91031\n",
"&nbsp; &nbsp; aaaaaaaaaaaaaa &nbsp;-> &nbsp;1a91041",
].join(" ");
},
gen: (): string => {
return comprLZGenerate();
},
solver: (plain: string, ans: string): boolean => {
return comprLZDecode(ans) === plain && ans.length === comprLZEncode(plain).length;
return comprLZDecode(ans) === plain && ans.length <= comprLZEncode(plain).length;
},
},
];

@ -105,6 +105,13 @@ export function comprLZEncode(plain: string): string {
// start new literal
set(new_state, 0, 1, string + length + offset);
// end current backreference and start new backreference
for (let new_offset = 1; new_offset <= Math.min(9, i); ++new_offset) {
if (plain[i - new_offset] === c) {
set(new_state, new_offset, 1, string + length + offset + "0");
}
}
}
}