mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-30 09:57:32 +01:00
Added demos in stanek
This commit is contained in:
parent
2b4b59b371
commit
3e357ab9a7
67
src/CotMG/DummyGift.ts
Normal file
67
src/CotMG/DummyGift.ts
Normal file
@ -0,0 +1,67 @@
|
|||||||
|
import { ActiveFragment } from "./ActiveFragment";
|
||||||
|
import { IStaneksGift } from "./IStaneksGift";
|
||||||
|
|
||||||
|
export class DummyGift implements IStaneksGift {
|
||||||
|
storedCycles = 0;
|
||||||
|
fragments: ActiveFragment[] = [];
|
||||||
|
_width: number;
|
||||||
|
_height: number;
|
||||||
|
|
||||||
|
constructor(width: number, height: number, fragments: ActiveFragment[]) {
|
||||||
|
this.fragments = fragments;
|
||||||
|
this._width = width;
|
||||||
|
this._height = height;
|
||||||
|
}
|
||||||
|
|
||||||
|
width(): number {
|
||||||
|
return this._width;
|
||||||
|
}
|
||||||
|
height(): number {
|
||||||
|
return this._height;
|
||||||
|
}
|
||||||
|
charge(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
process(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
effect(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
canPlace(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
place(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
findFragment(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
fragmentAt(worldX: number, worldY: number): ActiveFragment | undefined {
|
||||||
|
for (const aFrag of this.fragments) {
|
||||||
|
if (aFrag.fullAt(worldX, worldY)) {
|
||||||
|
return aFrag;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return undefined;
|
||||||
|
}
|
||||||
|
delete(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
clear(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
count(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
inBonus(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
prestigeAugmentation(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
prestigeSourceFile(): any {
|
||||||
|
throw new Error("unimplemented for dummy gift");
|
||||||
|
}
|
||||||
|
}
|
@ -12,3 +12,26 @@ export function loadStaneksGift(saveString: string): void {
|
|||||||
staneksGift = new StaneksGift();
|
staneksGift = new StaneksGift();
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export function zeros(dimensions: number[]): any {
|
||||||
|
const array = [];
|
||||||
|
|
||||||
|
for (let i = 0; i < dimensions[0]; ++i) {
|
||||||
|
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
|
||||||
|
}
|
||||||
|
|
||||||
|
return array;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function calculateGrid(gift: IStaneksGift): number[][] {
|
||||||
|
const newgrid = zeros([gift.width(), gift.height()]) as unknown as number[][];
|
||||||
|
for (let i = 0; i < gift.width(); i++) {
|
||||||
|
for (let j = 0; j < gift.height(); j++) {
|
||||||
|
const fragment = gift.fragmentAt(i, j);
|
||||||
|
if (!fragment) continue;
|
||||||
|
newgrid[i][j] = 1;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return newgrid;
|
||||||
|
}
|
||||||
|
33
src/CotMG/ui/DummyGrid.tsx
Normal file
33
src/CotMG/ui/DummyGrid.tsx
Normal file
@ -0,0 +1,33 @@
|
|||||||
|
import { Box, Table } from "@mui/material";
|
||||||
|
import * as React from "react";
|
||||||
|
import { ActiveFragment } from "../ActiveFragment";
|
||||||
|
import { DummyGift } from "../DummyGift";
|
||||||
|
import { Grid } from "./Grid";
|
||||||
|
import { calculateGrid, zeros } from "../Helper";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
fragments: ActiveFragment[];
|
||||||
|
}
|
||||||
|
|
||||||
|
export function DummyGrid(props: IProps): React.ReactElement {
|
||||||
|
const gift = new DummyGift(props.width, props.height, props.fragments);
|
||||||
|
const activeGrid = calculateGrid(gift);
|
||||||
|
const ghostGrid = zeros([props.width, props.height]);
|
||||||
|
return (
|
||||||
|
<Box>
|
||||||
|
<Table>
|
||||||
|
<Grid
|
||||||
|
width={props.width}
|
||||||
|
height={props.height}
|
||||||
|
activeGrid={activeGrid}
|
||||||
|
ghostGrid={ghostGrid}
|
||||||
|
gift={gift}
|
||||||
|
enter={() => undefined}
|
||||||
|
click={() => undefined}
|
||||||
|
/>
|
||||||
|
</Table>
|
||||||
|
</Box>
|
||||||
|
);
|
||||||
|
}
|
60
src/CotMG/ui/Grid.tsx
Normal file
60
src/CotMG/ui/Grid.tsx
Normal file
@ -0,0 +1,60 @@
|
|||||||
|
import { Table, TableBody, TableRow } from "@mui/material";
|
||||||
|
import * as React from "react";
|
||||||
|
import { ActiveFragment } from "../ActiveFragment";
|
||||||
|
import { IStaneksGift } from "../IStaneksGift";
|
||||||
|
import { Cell } from "./Cell";
|
||||||
|
|
||||||
|
interface IProps {
|
||||||
|
width: number;
|
||||||
|
height: number;
|
||||||
|
activeGrid: number[][];
|
||||||
|
ghostGrid: number[][];
|
||||||
|
gift: IStaneksGift;
|
||||||
|
enter(i: number, j: number): void;
|
||||||
|
click(i: number, j: number): void;
|
||||||
|
}
|
||||||
|
|
||||||
|
function randomColor(fragment: ActiveFragment): string {
|
||||||
|
// Can't set Math.random seed so copy casino. TODO refactor both RNG later.
|
||||||
|
let s1 = Math.pow((fragment.x + 1) * (fragment.y + 1), 10);
|
||||||
|
let s2 = s1;
|
||||||
|
let s3 = s1;
|
||||||
|
|
||||||
|
const colors = [];
|
||||||
|
for (let i = 0; i < 3; i++) {
|
||||||
|
s1 = (171 * s1) % 30269;
|
||||||
|
s2 = (172 * s2) % 30307;
|
||||||
|
s3 = (170 * s3) % 30323;
|
||||||
|
colors.push((s1 / 30269.0 + s2 / 30307.0 + s3 / 30323.0) % 1.0);
|
||||||
|
}
|
||||||
|
|
||||||
|
return `rgb(${colors[0] * 256}, ${colors[1] * 256}, ${colors[2] * 256})`;
|
||||||
|
}
|
||||||
|
|
||||||
|
export function Grid(props: IProps): React.ReactElement {
|
||||||
|
function color(worldX: number, worldY: number): string {
|
||||||
|
if (props.ghostGrid[worldX][worldY] && props.activeGrid[worldX][worldY]) return "red";
|
||||||
|
if (props.ghostGrid[worldX][worldY]) return "white";
|
||||||
|
|
||||||
|
if (props.activeGrid[worldX][worldY]) {
|
||||||
|
const fragment = props.gift.fragmentAt(worldX, worldY);
|
||||||
|
if (!fragment) throw new Error("ActiveFragment should not be null");
|
||||||
|
return randomColor(fragment);
|
||||||
|
}
|
||||||
|
return "";
|
||||||
|
}
|
||||||
|
|
||||||
|
// switch the width/length to make axis consistent.
|
||||||
|
const elems = [];
|
||||||
|
for (let j = 0; j < props.height; j++) {
|
||||||
|
const cells = [];
|
||||||
|
for (let i = 0; i < props.width; i++) {
|
||||||
|
cells.push(
|
||||||
|
<Cell key={i} onMouseEnter={() => props.enter(i, j)} onClick={() => props.click(i, j)} color={color(i, j)} />,
|
||||||
|
);
|
||||||
|
}
|
||||||
|
elems.push(<TableRow key={j}>{cells}</TableRow>);
|
||||||
|
}
|
||||||
|
|
||||||
|
return <TableBody>{elems}</TableBody>;
|
||||||
|
}
|
@ -1,62 +1,20 @@
|
|||||||
import * as React from "react";
|
import * as React from "react";
|
||||||
import { Fragment, NoneFragment } from "../Fragment";
|
import { Fragment, NoneFragment } from "../Fragment";
|
||||||
import { ActiveFragment } from "../ActiveFragment";
|
|
||||||
import { FragmentType } from "../FragmentType";
|
import { FragmentType } from "../FragmentType";
|
||||||
import { IStaneksGift } from "../IStaneksGift";
|
import { IStaneksGift } from "../IStaneksGift";
|
||||||
import { Cell } from "./Cell";
|
|
||||||
import { FragmentInspector } from "./FragmentInspector";
|
import { FragmentInspector } from "./FragmentInspector";
|
||||||
import { FragmentSelector } from "./FragmentSelector";
|
import { FragmentSelector } from "./FragmentSelector";
|
||||||
import Box from "@mui/material/Box";
|
import Box from "@mui/material/Box";
|
||||||
import Button from "@mui/material/Button";
|
import Button from "@mui/material/Button";
|
||||||
import TableRow from "@mui/material/TableRow";
|
|
||||||
import TableBody from "@mui/material/TableBody";
|
|
||||||
import { Table } from "../../ui/React/Table";
|
import { Table } from "../../ui/React/Table";
|
||||||
|
import { Grid } from "./Grid";
|
||||||
function zeros(dimensions: number[]): any {
|
import { zeros, calculateGrid } from "../Helper";
|
||||||
const array = [];
|
|
||||||
|
|
||||||
for (let i = 0; i < dimensions[0]; ++i) {
|
|
||||||
array.push(dimensions.length == 1 ? 0 : zeros(dimensions.slice(1)));
|
|
||||||
}
|
|
||||||
|
|
||||||
return array;
|
|
||||||
}
|
|
||||||
|
|
||||||
function randomColor(fragment: ActiveFragment): string {
|
|
||||||
// Can't set Math.random seed so copy casino. TODO refactor both RNG later.
|
|
||||||
let s1 = Math.pow((fragment.x + 1) * (fragment.y + 1), 10);
|
|
||||||
let s2 = s1;
|
|
||||||
let s3 = s1;
|
|
||||||
|
|
||||||
const colors = [];
|
|
||||||
for (let i = 0; i < 3; i++) {
|
|
||||||
s1 = (171 * s1) % 30269;
|
|
||||||
s2 = (172 * s2) % 30307;
|
|
||||||
s3 = (170 * s3) % 30323;
|
|
||||||
colors.push((s1 / 30269.0 + s2 / 30307.0 + s3 / 30323.0) % 1.0);
|
|
||||||
}
|
|
||||||
|
|
||||||
return `rgb(${colors[0] * 256}, ${colors[1] * 256}, ${colors[2] * 256})`;
|
|
||||||
}
|
|
||||||
|
|
||||||
interface IProps {
|
interface IProps {
|
||||||
gift: IStaneksGift;
|
gift: IStaneksGift;
|
||||||
}
|
}
|
||||||
|
|
||||||
export function MainBoard(props: IProps): React.ReactElement {
|
export function MainBoard(props: IProps): React.ReactElement {
|
||||||
function calculateGrid(gift: IStaneksGift): any {
|
|
||||||
const newgrid = zeros([gift.width(), gift.height()]);
|
|
||||||
for (let i = 0; i < gift.width(); i++) {
|
|
||||||
for (let j = 0; j < gift.height(); j++) {
|
|
||||||
const fragment = gift.fragmentAt(i, j);
|
|
||||||
if (!fragment) continue;
|
|
||||||
newgrid[i][j] = 1;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return newgrid;
|
|
||||||
}
|
|
||||||
|
|
||||||
const [grid, setGrid] = React.useState(calculateGrid(props.gift));
|
const [grid, setGrid] = React.useState(calculateGrid(props.gift));
|
||||||
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
const [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
||||||
const [pos, setPos] = React.useState([0, 0]);
|
const [pos, setPos] = React.useState([0, 0]);
|
||||||
@ -96,44 +54,11 @@ export function MainBoard(props: IProps): React.ReactElement {
|
|||||||
setGrid(calculateGrid(props.gift));
|
setGrid(calculateGrid(props.gift));
|
||||||
}
|
}
|
||||||
|
|
||||||
function color(worldX: number, worldY: number): string {
|
|
||||||
if (ghostGrid[worldX][worldY] && grid[worldX][worldY]) return "red";
|
|
||||||
if (ghostGrid[worldX][worldY]) return "white";
|
|
||||||
|
|
||||||
if (grid[worldX][worldY]) {
|
|
||||||
const fragment = props.gift.fragmentAt(worldX, worldY);
|
|
||||||
if (!fragment) throw new Error("ActiveFragment should not be null");
|
|
||||||
return randomColor(fragment);
|
|
||||||
}
|
|
||||||
return "";
|
|
||||||
}
|
|
||||||
|
|
||||||
function clear(): void {
|
function clear(): void {
|
||||||
props.gift.clear();
|
props.gift.clear();
|
||||||
setGrid(zeros([props.gift.width(), props.gift.height()]));
|
setGrid(zeros([props.gift.width(), props.gift.height()]));
|
||||||
}
|
}
|
||||||
|
|
||||||
// switch the width/length to make axis consistent.
|
|
||||||
const elems = [];
|
|
||||||
for (let j = 0; j < props.gift.height(); j++) {
|
|
||||||
const cells = [];
|
|
||||||
for (let i = 0; i < props.gift.width(); i++) {
|
|
||||||
cells.push(
|
|
||||||
<Cell
|
|
||||||
key={i}
|
|
||||||
onMouseEnter={() => moveGhost(i, j, rotation)}
|
|
||||||
onClick={() => clickAt(i, j)}
|
|
||||||
color={color(i, j)}
|
|
||||||
/>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
elems.push(
|
|
||||||
<TableRow key={j} className="staneksgift_row">
|
|
||||||
{cells}
|
|
||||||
</TableRow>,
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function updateSelectedFragment(fragment: Fragment): void {
|
function updateSelectedFragment(fragment: Fragment): void {
|
||||||
setSelectedFragment(fragment);
|
setSelectedFragment(fragment);
|
||||||
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
const newgrid = zeros([props.gift.width(), props.gift.height()]);
|
||||||
@ -162,7 +87,15 @@ export function MainBoard(props: IProps): React.ReactElement {
|
|||||||
<Button onClick={clear}>Clear</Button>
|
<Button onClick={clear}>Clear</Button>
|
||||||
<Box display="flex">
|
<Box display="flex">
|
||||||
<Table>
|
<Table>
|
||||||
<TableBody>{elems}</TableBody>
|
<Grid
|
||||||
|
width={props.gift.width()}
|
||||||
|
height={props.gift.height()}
|
||||||
|
activeGrid={grid}
|
||||||
|
ghostGrid={ghostGrid}
|
||||||
|
gift={props.gift}
|
||||||
|
enter={(i, j) => moveGhost(i, j, rotation)}
|
||||||
|
click={(i, j) => clickAt(i, j)}
|
||||||
|
/>
|
||||||
</Table>
|
</Table>
|
||||||
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
|
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
|
||||||
</Box>
|
</Box>
|
||||||
|
@ -7,6 +7,13 @@ import { IStaneksGift } from "../IStaneksGift";
|
|||||||
import { Info } from "@mui/icons-material";
|
import { Info } from "@mui/icons-material";
|
||||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||||
import Typography from "@mui/material/Typography";
|
import Typography from "@mui/material/Typography";
|
||||||
|
import Box from "@mui/material/Box";
|
||||||
|
import { Table } from "@mui/material";
|
||||||
|
import { Grid } from "./Grid";
|
||||||
|
import { DummyGift } from "../DummyGift";
|
||||||
|
import { ActiveFragment } from "../ActiveFragment";
|
||||||
|
import { Fragments } from "../Fragment";
|
||||||
|
import { DummyGrid } from "./DummyGrid";
|
||||||
|
|
||||||
type IProps = {
|
type IProps = {
|
||||||
staneksGift: IStaneksGift;
|
staneksGift: IStaneksGift;
|
||||||
@ -64,13 +71,99 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
|||||||
charged.
|
charged.
|
||||||
</Typography>
|
</Typography>
|
||||||
|
|
||||||
{/*
|
<DummyGrid
|
||||||
TODO:
|
width={4}
|
||||||
Board showing a booster fragment touching a single stat fragment on one edge, labeled as providing a 10% bonus to the stat fragment.
|
height={4}
|
||||||
Board showing a booster fragment touching a single stat fragment on many edges, labeled as providing a 10% bonus to the stat fragment.
|
fragments={[
|
||||||
Board showing a booster fragment diagonal from a single stat fragment along multiple corners, labeled as providing no bonus to the stat fragment.
|
new ActiveFragment({
|
||||||
Board showing a booster fragment touching multiple stat fragments, labeled as providing a 10% bonus to each stat fragment.
|
x: 0,
|
||||||
*/}
|
y: 0,
|
||||||
|
rotation: 0,
|
||||||
|
fragment: Fragments.find((f) => f.id === 5) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 0,
|
||||||
|
y: 2,
|
||||||
|
rotation: 0,
|
||||||
|
fragment: Fragments.find((f) => f.id === 101) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
|
This boost provides a bonus to the touching fragment
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<DummyGrid
|
||||||
|
width={4}
|
||||||
|
height={4}
|
||||||
|
fragments={[
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
rotation: 3,
|
||||||
|
fragment: Fragments.find((f) => f.id === 100) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
rotation: 2,
|
||||||
|
fragment: Fragments.find((f) => f.id === 1) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
|
Even though the booster touches many tiles, the bonus is only applied once.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<DummyGrid
|
||||||
|
width={4}
|
||||||
|
height={4}
|
||||||
|
fragments={[
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
rotation: 0,
|
||||||
|
fragment: Fragments.find((f) => f.id === 5) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 2,
|
||||||
|
y: 0,
|
||||||
|
rotation: 0,
|
||||||
|
fragment: Fragments.find((f) => f.id === 105) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
|
Even though the booster touches many tiles, the bonus is only applied once.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
|
<DummyGrid
|
||||||
|
width={4}
|
||||||
|
height={4}
|
||||||
|
fragments={[
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 0,
|
||||||
|
y: 0,
|
||||||
|
rotation: 1,
|
||||||
|
fragment: Fragments.find((f) => f.id === 27) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 0,
|
||||||
|
y: 1,
|
||||||
|
rotation: 2,
|
||||||
|
fragment: Fragments.find((f) => f.id === 100) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
new ActiveFragment({
|
||||||
|
x: 2,
|
||||||
|
y: 0,
|
||||||
|
rotation: 1,
|
||||||
|
fragment: Fragments.find((f) => f.id === 30) ?? Fragments[0],
|
||||||
|
}),
|
||||||
|
]}
|
||||||
|
/>
|
||||||
|
<Typography sx={{ fontStyle: "italic" }}>
|
||||||
|
This booster provides bonus to all fragment it touches.
|
||||||
|
</Typography>
|
||||||
|
|
||||||
<br />
|
<br />
|
||||||
<Typography>
|
<Typography>
|
||||||
|
Loading…
Reference in New Issue
Block a user