mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-05-08 00:27:47 +02:00
IPVGO: Add support for highlighting nodes and adding small text (#1996)
This commit is contained in:
committed by
GitHub
parent
5d486e3914
commit
f6e7ef082c
@@ -6,6 +6,10 @@ import { resetGoPromises } from "./boardAnalysis/goAI";
|
||||
import { getNewBoardState } from "./boardState/boardState";
|
||||
import { EventEmitter } from "../utils/EventEmitter";
|
||||
|
||||
export const getEmptyHighlightedPoints = (size: number = 7) => {
|
||||
return Array.from({ length: size }, () => Array.from({ length: size }, () => null));
|
||||
};
|
||||
|
||||
export class GoObject {
|
||||
// Todo: Make previous game a slimmer interface
|
||||
previousGame: BoardState | null = null;
|
||||
|
||||
@@ -55,6 +55,7 @@ export type BoardState = {
|
||||
cheatCount: number;
|
||||
cheatCountForWhite: number;
|
||||
komiOverride: number | null;
|
||||
highlightedPoints: (PointHighlight | null)[][];
|
||||
};
|
||||
|
||||
export type PointState = {
|
||||
@@ -109,3 +110,8 @@ export type SimpleOpponentStats = {
|
||||
bonusPercent: number;
|
||||
bonusDescription: string;
|
||||
};
|
||||
|
||||
export type PointHighlight = {
|
||||
color: string;
|
||||
text: string;
|
||||
};
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
import type { Board, BoardState, Neighbor, Play, PointState, SimpleBoard } from "../Types";
|
||||
|
||||
import { GoValidity, GoOpponent, GoColor, GoPlayType } from "@enums";
|
||||
import { Go } from "../Go";
|
||||
import { getEmptyHighlightedPoints, Go, GoEvents } from "../Go";
|
||||
import {
|
||||
findAdjacentPointsInChain,
|
||||
findNeighbors,
|
||||
@@ -730,3 +730,18 @@ export function getPreviousMoveDetails(): Play {
|
||||
y: null,
|
||||
};
|
||||
}
|
||||
|
||||
export function addPointHighlight(board: BoardState, x: number, y: number, color: string, text: string) {
|
||||
board.highlightedPoints[x][y] = { color, text };
|
||||
GoEvents.emit();
|
||||
}
|
||||
|
||||
export function clearPointHighlight(board: BoardState, x: number, y: number) {
|
||||
board.highlightedPoints[x][y] = null;
|
||||
GoEvents.emit();
|
||||
}
|
||||
|
||||
export function clearAllPointHighlights(board: BoardState) {
|
||||
board.highlightedPoints = getEmptyHighlightedPoints(Go.currentGame.board.length);
|
||||
GoEvents.emit();
|
||||
}
|
||||
|
||||
@@ -6,6 +6,7 @@ import { getExpansionMoveArray } from "../boardAnalysis/goAI";
|
||||
import {
|
||||
boardFromSimpleBoard,
|
||||
boardStringFromBoard,
|
||||
clearAllPointHighlights,
|
||||
evaluateIfMoveIsValid,
|
||||
findAllCapturedChains,
|
||||
findLibertiesForChain,
|
||||
@@ -36,6 +37,7 @@ export function getNewBoardState(
|
||||
cheatCount: 0,
|
||||
cheatCountForWhite: 0,
|
||||
komiOverride: null,
|
||||
highlightedPoints: Array.from({ length: boardSize }, () => Array.from({ length: boardSize }, () => null)),
|
||||
board: Array.from({ length: boardSize }, (_, x) =>
|
||||
Array.from({ length: boardSize }, (_, y) =>
|
||||
!boardToCopy || boardToCopy?.[x]?.[y]
|
||||
@@ -123,6 +125,7 @@ export function makeMove(boardState: BoardState, x: number, y: number, player: G
|
||||
|
||||
// Add move to board history
|
||||
boardState.previousBoards.unshift(boardStringFromBoard(boardState.board));
|
||||
clearAllPointHighlights(boardState);
|
||||
|
||||
point.color = player;
|
||||
boardState.previousPlayer = player;
|
||||
@@ -140,6 +143,8 @@ export function passTurn(boardState: BoardState, player: GoColor, allowEndGame =
|
||||
if (boardState.previousPlayer === null || boardState.previousPlayer === player) {
|
||||
return;
|
||||
}
|
||||
clearAllPointHighlights(boardState);
|
||||
|
||||
boardState.previousPlayer = boardState.previousPlayer === GoColor.black ? GoColor.white : GoColor.black;
|
||||
boardState.passCount++;
|
||||
|
||||
|
||||
@@ -10,10 +10,18 @@ type Point =
|
||||
| "filledPoint"
|
||||
| "emptyPoint"
|
||||
| "broken"
|
||||
| "cyberStyle"
|
||||
| "tradStone"
|
||||
| "priorStoneTrad";
|
||||
type Structure = "coordinates" | "liberty" | "northLiberty" | "eastLiberty" | "westLiberty" | "southLiberty";
|
||||
type Highlight = "hover" | "valid" | "priorPoint";
|
||||
type Structure =
|
||||
| "coordinates"
|
||||
| "highlightText"
|
||||
| "liberty"
|
||||
| "northLiberty"
|
||||
| "eastLiberty"
|
||||
| "westLiberty"
|
||||
| "southLiberty";
|
||||
type Highlight = "hover" | "valid" | "priorPoint" | "hack" | "hp" | "money" | "int" | "cha";
|
||||
|
||||
const fadeLoop = keyframes`
|
||||
0% {
|
||||
@@ -29,31 +37,56 @@ export const pointStyle = makeStyles<unknown, Size | Point | Structure | Highlig
|
||||
hover: {},
|
||||
valid: {},
|
||||
priorPoint: {},
|
||||
cyberStyle: {},
|
||||
highlightText: {},
|
||||
hack: {},
|
||||
hp: {},
|
||||
money: {},
|
||||
int: {},
|
||||
cha: {},
|
||||
point: {
|
||||
position: "relative",
|
||||
height: "100%",
|
||||
width: "100%",
|
||||
|
||||
[`&.${classes.hover}.${classes.valid}:hover .${classes.innerPoint}`]: {
|
||||
[`&.${classes.hover}.${classes.valid}.${classes.cyberStyle}:hover .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.white,
|
||||
},
|
||||
[`&.${classes.hover}.${classes.priorPoint} .${classes.innerPoint}`]: {
|
||||
[`&.${classes.hover}.${classes.cyberStyle}.${classes.priorPoint} .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.white,
|
||||
},
|
||||
[`&.${classes.hover}.${classes.priorPoint} .${classes.priorStoneTrad}.${classes.blackPoint}`]: {
|
||||
outlineColor: theme.colors.white,
|
||||
display: "block",
|
||||
},
|
||||
[`&.${classes.hover}.${classes.priorPoint} .${classes.priorStoneTrad}.${classes.whitePoint}`]: {
|
||||
outlineColor: theme.colors.black,
|
||||
display: "block",
|
||||
},
|
||||
[`&.${classes.hover}.${classes.cyberStyle}.${classes.priorPoint} .${classes.priorStoneTrad}.${classes.blackPoint}`]:
|
||||
{
|
||||
outlineColor: theme.colors.white,
|
||||
display: "block",
|
||||
},
|
||||
[`&.${classes.hover}.${classes.cyberStyle}.${classes.priorPoint} .${classes.priorStoneTrad}.${classes.whitePoint}`]:
|
||||
{
|
||||
outlineColor: theme.colors.black,
|
||||
display: "block",
|
||||
},
|
||||
[`&.${classes.hover}:hover .${classes.coordinates}`]: {
|
||||
display: "block",
|
||||
},
|
||||
[`&:hover .${classes.broken}`]: {
|
||||
opacity: "0.4",
|
||||
},
|
||||
|
||||
[`&.${classes.hack} .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.hack,
|
||||
},
|
||||
[`&.${classes.hp} .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.hp,
|
||||
},
|
||||
[`&.${classes.money} .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.money,
|
||||
},
|
||||
[`&.${classes.int} .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.int,
|
||||
},
|
||||
[`&.${classes.cha} .${classes.innerPoint}`]: {
|
||||
outlineColor: theme.colors.cha,
|
||||
},
|
||||
},
|
||||
broken: {
|
||||
backgroundImage: `repeating-radial-gradient(circle at 17% 32%, ${theme.colors.white}, black 0.00085px)`,
|
||||
@@ -82,7 +115,10 @@ export const pointStyle = makeStyles<unknown, Size | Point | Structure | Highlig
|
||||
},
|
||||
traditional: {
|
||||
[`& .${classes.innerPoint}`]: {
|
||||
display: "none",
|
||||
outlineColor: "transparent",
|
||||
[`& .${classes.emptyPoint}`]: {
|
||||
display: "none",
|
||||
},
|
||||
},
|
||||
[`& .${classes.broken}`]: {
|
||||
backgroundImage: "none",
|
||||
@@ -118,7 +154,7 @@ export const pointStyle = makeStyles<unknown, Size | Point | Structure | Highlig
|
||||
},
|
||||
},
|
||||
[`& .${classes.coordinates}`]: {
|
||||
fontSize: "0.9vw",
|
||||
fontSize: "0.7vw",
|
||||
},
|
||||
},
|
||||
[`&.${classes.thirteenByThirteen}`]: {
|
||||
@@ -133,7 +169,7 @@ export const pointStyle = makeStyles<unknown, Size | Point | Structure | Highlig
|
||||
},
|
||||
},
|
||||
[`& .${classes.coordinates}`]: {
|
||||
fontSize: "0.9vw",
|
||||
fontSize: "0.7vw",
|
||||
},
|
||||
},
|
||||
[`&.${classes.nineByNine}`]: {
|
||||
@@ -379,6 +415,9 @@ export const pointStyle = makeStyles<unknown, Size | Point | Structure | Highlig
|
||||
left: "8%",
|
||||
zIndex: "10",
|
||||
userSelect: "none",
|
||||
[`&.${classes.highlightText}`]: {
|
||||
display: "block",
|
||||
},
|
||||
},
|
||||
priorStoneTrad: {
|
||||
display: "none",
|
||||
|
||||
@@ -12,6 +12,7 @@ import {
|
||||
} from "../boardState/boardState";
|
||||
import { getNextTurn, handleNextTurn, resetGoPromises } from "../boardAnalysis/goAI";
|
||||
import {
|
||||
clearAllPointHighlights,
|
||||
evaluateIfMoveIsValid,
|
||||
getControlledSpace,
|
||||
getPreviousMove,
|
||||
@@ -357,6 +358,7 @@ export function resetBoardState(
|
||||
|
||||
Go.currentGame = getNewBoardState(boardSize, opponent, true);
|
||||
resetGoPromises();
|
||||
clearAllPointHighlights(Go.currentGame);
|
||||
logger(`New game started: ${opponent}, ${boardSize}x${boardSize}`);
|
||||
return simpleBoardFromBoard(Go.currentGame.board);
|
||||
}
|
||||
|
||||
@@ -52,6 +52,7 @@ export function GoGameboard({ boardState, traditional, clickHandler, hover }: Go
|
||||
hover={hover}
|
||||
valid={pointIsValid(xIndex, yIndex)}
|
||||
emptyPointOwner={ownedEmptyNodes[xIndex]?.[yIndex]}
|
||||
pointHighlight={boardState.highlightedPoints[xIndex][yIndex]}
|
||||
/>
|
||||
</Grid>
|
||||
);
|
||||
|
||||
@@ -9,7 +9,12 @@ import { SnackbarEvents } from "../../ui/React/Snackbar";
|
||||
import { getNewBoardState, getStateCopy, makeMove, passTurn, updateCaptures } from "../boardState/boardState";
|
||||
import { bitverseArt, weiArt } from "../boardState/asciiArt";
|
||||
import { getScore, resetWinstreak } from "../boardAnalysis/scoring";
|
||||
import { boardFromBoardString, evaluateIfMoveIsValid, getAllValidMoves } from "../boardAnalysis/boardAnalysis";
|
||||
import {
|
||||
boardFromBoardString,
|
||||
clearAllPointHighlights,
|
||||
evaluateIfMoveIsValid,
|
||||
getAllValidMoves,
|
||||
} from "../boardAnalysis/boardAnalysis";
|
||||
import { useRerender } from "../../ui/React/hooks";
|
||||
import { OptionSwitch } from "../../ui/React/OptionSwitch";
|
||||
import { boardStyles } from "../boardState/goStyles";
|
||||
@@ -135,6 +140,7 @@ export function GoGameboardWrapper({ showInstructions }: GoGameboardWrapperProps
|
||||
|
||||
Go.currentGame = getNewBoardState(newBoardSize, newOpponent, true);
|
||||
resetGoPromises();
|
||||
clearAllPointHighlights(Go.currentGame);
|
||||
}
|
||||
|
||||
function getPriorMove() {
|
||||
|
||||
+40
-10
@@ -7,6 +7,7 @@ import { columnIndexes } from "../Constants";
|
||||
import { findNeighbors } from "../boardState/boardState";
|
||||
import { boardStyles, pointStyle } from "../boardState/goStyles";
|
||||
import { findAdjacentLibertiesAndAlliesForPoint, getColorOnBoardString } from "../boardAnalysis/boardAnalysis";
|
||||
import { PointHighlight } from "../Types";
|
||||
|
||||
interface GoPointProps {
|
||||
state: BoardState;
|
||||
@@ -15,11 +16,29 @@ interface GoPointProps {
|
||||
traditional: boolean;
|
||||
hover: boolean;
|
||||
valid: boolean;
|
||||
emptyPointOwner: GoColor;
|
||||
emptyPointOwner: GoColor | undefined;
|
||||
pointHighlight: PointHighlight | null;
|
||||
}
|
||||
|
||||
export function GoPoint({ state, x, y, traditional, hover, valid, emptyPointOwner }: GoPointProps): React.ReactElement {
|
||||
export function GoPoint({
|
||||
state,
|
||||
x,
|
||||
y,
|
||||
traditional,
|
||||
hover,
|
||||
valid,
|
||||
emptyPointOwner,
|
||||
pointHighlight,
|
||||
}: GoPointProps): React.ReactElement {
|
||||
const { classes } = pointStyle({});
|
||||
const colorClasses = {
|
||||
hack: classes.hack,
|
||||
hp: classes.hp,
|
||||
money: classes.money,
|
||||
int: classes.int,
|
||||
cha: classes.cha,
|
||||
none: "none",
|
||||
};
|
||||
|
||||
const currentPoint = state.board[x]?.[y];
|
||||
const player = currentPoint?.color;
|
||||
@@ -51,9 +70,16 @@ export function GoPoint({ state, x, y, traditional, hover, valid, emptyPointOwne
|
||||
? classes.libertyBlack
|
||||
: "";
|
||||
|
||||
const mainClassName = `${classes.point} ${sizeClass} ${traditional ? classes.traditional : ""} ${
|
||||
const highlightClass: string = pointHighlight?.color
|
||||
? colorClasses[pointHighlight.color as keyof typeof colorClasses] ?? ""
|
||||
: "";
|
||||
const rawColorStyle = !highlightClass && pointHighlight?.color ? `${pointHighlight.color}` : "";
|
||||
const outlineWidth = rawColorStyle ? "2px" : "1px";
|
||||
const highlightText = pointHighlight?.text ?? "";
|
||||
|
||||
const mainClassName = `${classes.point} ${sizeClass} ${traditional ? classes.traditional : classes.cyberStyle} ${
|
||||
hover ? classes.hover : ""
|
||||
} ${valid ? classes.valid : ""} ${isPriorMove ? classes.priorPoint : ""}
|
||||
} ${valid ? classes.valid : ""} ${isPriorMove ? classes.priorPoint : ""} ${highlightClass}
|
||||
${isInAtari ? classes.fadeLoopAnimation : ""}`;
|
||||
|
||||
return (
|
||||
@@ -64,18 +90,22 @@ export function GoPoint({ state, x, y, traditional, hover, valid, emptyPointOwne
|
||||
<div className={hasEastLiberty ? `${classes.eastLiberty} ${colorLiberty}` : classes.liberty}></div>
|
||||
<div className={hasSouthLiberty ? `${classes.southLiberty} ${colorLiberty}` : classes.liberty}></div>
|
||||
<div className={hasWestLiberty ? `${classes.westLiberty} ${colorLiberty}` : classes.liberty}></div>
|
||||
<div className={`${classes.innerPoint} `}>
|
||||
<div className={`${classes.innerPoint} `} style={{ outlineColor: rawColorStyle, outlineWidth: outlineWidth }}>
|
||||
<div
|
||||
className={`${pointClass} ${player !== GoColor.empty ? classes.filledPoint : emptyPointColorClass}`}
|
||||
></div>
|
||||
</div>
|
||||
<div className={`${pointClass} ${classes.tradStone}`} />
|
||||
{traditional ? <div className={`${pointClass} ${classes.priorStoneTrad}`}></div> : ""}
|
||||
<div className={classes.coordinates}>
|
||||
{columnIndexes[x]}
|
||||
{traditional ? "" : "."}
|
||||
{y + 1}
|
||||
</div>
|
||||
{highlightText ? (
|
||||
<div className={`${classes.highlightText} ${classes.coordinates}`}>{highlightText}</div>
|
||||
) : (
|
||||
<div className={classes.coordinates}>
|
||||
{columnIndexes[x]}
|
||||
{traditional ? "" : "."}
|
||||
{y + 1}
|
||||
</div>
|
||||
)}
|
||||
</>
|
||||
) : (
|
||||
<>
|
||||
|
||||
Reference in New Issue
Block a user