diff --git a/src/CotMG/DummyGift.ts b/src/CotMG/DummyGift.ts
new file mode 100644
index 000000000..79b541e72
--- /dev/null
+++ b/src/CotMG/DummyGift.ts
@@ -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");
+ }
+}
diff --git a/src/CotMG/Helper.tsx b/src/CotMG/Helper.tsx
index c8f07c388..26e686853 100644
--- a/src/CotMG/Helper.tsx
+++ b/src/CotMG/Helper.tsx
@@ -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;
+}
diff --git a/src/CotMG/ui/DummyGrid.tsx b/src/CotMG/ui/DummyGrid.tsx
new file mode 100644
index 000000000..a31646cc6
--- /dev/null
+++ b/src/CotMG/ui/DummyGrid.tsx
@@ -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 (
+
+
+ undefined}
+ click={() => undefined}
+ />
+
+
+ );
+}
diff --git a/src/CotMG/ui/Grid.tsx b/src/CotMG/ui/Grid.tsx
new file mode 100644
index 000000000..479681bc4
--- /dev/null
+++ b/src/CotMG/ui/Grid.tsx
@@ -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(
+ props.enter(i, j)} onClick={() => props.click(i, j)} color={color(i, j)} />,
+ );
+ }
+ elems.push({cells} );
+ }
+
+ return {elems} ;
+}
diff --git a/src/CotMG/ui/MainBoard.tsx b/src/CotMG/ui/MainBoard.tsx
index 3bbcfdfe4..873592b76 100644
--- a/src/CotMG/ui/MainBoard.tsx
+++ b/src/CotMG/ui/MainBoard.tsx
@@ -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(
- moveGhost(i, j, rotation)}
- onClick={() => clickAt(i, j)}
- color={color(i, j)}
- />,
- );
- }
- elems.push(
-
- {cells}
- ,
- );
- }
-
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 {
Clear
- {elems}
+ moveGhost(i, j, rotation)}
+ click={(i, j) => clickAt(i, j)}
+ />
diff --git a/src/CotMG/ui/StaneksGiftRoot.tsx b/src/CotMG/ui/StaneksGiftRoot.tsx
index a7a3b8bf2..72cc3b050 100644
--- a/src/CotMG/ui/StaneksGiftRoot.tsx
+++ b/src/CotMG/ui/StaneksGiftRoot.tsx
@@ -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.
- {/*
- 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.
- */}
+ f.id === 5) ?? Fragments[0],
+ }),
+ new ActiveFragment({
+ x: 0,
+ y: 2,
+ rotation: 0,
+ fragment: Fragments.find((f) => f.id === 101) ?? Fragments[0],
+ }),
+ ]}
+ />
+
+ This boost provides a bonus to the touching fragment
+
+
+ f.id === 100) ?? Fragments[0],
+ }),
+ new ActiveFragment({
+ x: 0,
+ y: 0,
+ rotation: 2,
+ fragment: Fragments.find((f) => f.id === 1) ?? Fragments[0],
+ }),
+ ]}
+ />
+
+ Even though the booster touches many tiles, the bonus is only applied once.
+
+
+ f.id === 5) ?? Fragments[0],
+ }),
+ new ActiveFragment({
+ x: 2,
+ y: 0,
+ rotation: 0,
+ fragment: Fragments.find((f) => f.id === 105) ?? Fragments[0],
+ }),
+ ]}
+ />
+
+ Even though the booster touches many tiles, the bonus is only applied once.
+
+
+ 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],
+ }),
+ ]}
+ />
+
+ This booster provides bonus to all fragment it touches.
+
| |