mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2024-12-20 21:25:47 +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();
|
||||
}
|
||||
}
|
||||
|
||||
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 { Fragment, NoneFragment } from "../Fragment";
|
||||
import { ActiveFragment } from "../ActiveFragment";
|
||||
import { FragmentType } from "../FragmentType";
|
||||
import { IStaneksGift } from "../IStaneksGift";
|
||||
import { Cell } from "./Cell";
|
||||
import { FragmentInspector } from "./FragmentInspector";
|
||||
import { FragmentSelector } from "./FragmentSelector";
|
||||
import Box from "@mui/material/Box";
|
||||
import Button from "@mui/material/Button";
|
||||
import TableRow from "@mui/material/TableRow";
|
||||
import TableBody from "@mui/material/TableBody";
|
||||
import { Table } from "../../ui/React/Table";
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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})`;
|
||||
}
|
||||
import { Grid } from "./Grid";
|
||||
import { zeros, calculateGrid } from "../Helper";
|
||||
|
||||
interface IProps {
|
||||
gift: IStaneksGift;
|
||||
}
|
||||
|
||||
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 [ghostGrid, setGhostGrid] = React.useState(zeros([props.gift.width(), props.gift.height()]));
|
||||
const [pos, setPos] = React.useState([0, 0]);
|
||||
@ -96,44 +54,11 @@ export function MainBoard(props: IProps): React.ReactElement {
|
||||
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 {
|
||||
props.gift.clear();
|
||||
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 {
|
||||
setSelectedFragment(fragment);
|
||||
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>
|
||||
<Box display="flex">
|
||||
<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>
|
||||
<FragmentInspector gift={props.gift} x={pos[0]} y={pos[1]} fragment={props.gift.fragmentAt(pos[0], pos[1])} />
|
||||
</Box>
|
||||
|
@ -7,6 +7,13 @@ import { IStaneksGift } from "../IStaneksGift";
|
||||
import { Info } from "@mui/icons-material";
|
||||
import { dialogBoxCreate } from "../../ui/React/DialogBox";
|
||||
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 = {
|
||||
staneksGift: IStaneksGift;
|
||||
@ -64,13 +71,99 @@ export function StaneksGiftRoot({ staneksGift }: IProps): React.ReactElement {
|
||||
charged.
|
||||
</Typography>
|
||||
|
||||
{/*
|
||||
TODO:
|
||||
Board showing a booster fragment touching a single stat fragment on one edge, labeled as providing a 10% bonus to the stat fragment.
|
||||
Board showing a booster fragment touching a single stat fragment on many edges, labeled as providing a 10% bonus to the stat fragment.
|
||||
Board showing a booster fragment diagonal from a single stat fragment along multiple corners, labeled as providing no bonus to the stat fragment.
|
||||
Board showing a booster fragment touching multiple stat fragments, labeled as providing a 10% bonus to each stat fragment.
|
||||
*/}
|
||||
<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: 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 />
|
||||
<Typography>
|
||||
|
Loading…
Reference in New Issue
Block a user