Files
bitburner-src/src/Go/boardState/offlineNodes.ts

162 lines
4.5 KiB
TypeScript

import type { Board, BoardState, PointState } from "../Types";
import { Player } from "@player";
import { boardSizes } from "../Constants";
import { WHRNG } from "../../Casino/RNG";
import { getAllChains } from "../boardAnalysis/boardAnalysis";
import { updateChains } from "./boardState";
import { GoColor } from "@enums";
type rand = (n1: number, n2: number) => number;
export function addObstacles(boardState: BoardState) {
const rng = new WHRNG(Player.totalPlaytime ?? new Date().getTime());
const random = (n1: number, n2: number) => n1 + Math.floor((n2 - n1 + 1) * rng.random());
const shouldRemoveCorner = !random(0, 4);
const shouldRemoveRows = !shouldRemoveCorner && !random(0, 4);
const shouldAddCenterBreak = !shouldRemoveCorner && !shouldRemoveRows && random(0, 3);
const obstacleTypeCount = +shouldRemoveCorner + +shouldRemoveRows + +shouldAddCenterBreak;
const edgeDeadCount = random(1, (getScale(boardState.board) + 2 - obstacleTypeCount) * 1.5);
if (shouldRemoveCorner) {
boardState.board = addDeadCorners(boardState.board, random);
}
if (shouldAddCenterBreak) {
boardState.board = addCenterBreak(boardState.board, random);
}
boardState.board = randomizeRotation(boardState.board, random);
if (shouldRemoveRows) {
boardState.board = removeRows(boardState.board, random);
}
boardState.board = addDeadNodesToEdge(boardState.board, random, edgeDeadCount);
boardState.board = ensureOfflineNodes(boardState.board);
boardState.board = resetCoordinates(boardState.board);
boardState.board = removeIslands(boardState.board);
}
export function resetCoordinates(board: Board) {
const size = board[0].length;
for (let x = 0; x < size; x++) {
for (let y = 0; y < size; y++) {
const point = board[x]?.[y];
if (point) {
point.x = x;
point.y = y;
}
}
}
return board;
}
/**
* Removes all tiny islands of empty points (2 or fewer) from the board
* @param board
*/
export function removeIslands(board: Board) {
updateChains(board, true);
const chains = getAllChains(board);
for (const chain of chains) {
if (chain.length <= 2 && chain[0]?.color === GoColor.empty) {
for (const point of chain) {
board[point.x][point.y] = null;
}
}
}
return board;
}
function getScale(board: Board) {
return boardSizes.indexOf(board[0].length);
}
function removeRows(board: Board, random: rand) {
const rowsToRemove = Math.max(random(-2, getScale(board)), 1);
for (let i = 0; i < rowsToRemove; i++) {
board[i] = board[i].map(() => null);
}
board = rotateNTimes(board, 3);
return board;
}
function addDeadNodesToEdge(board: Board, random: rand, maxPerEdge: number) {
const size = board[0].length;
for (let i = 0; i < 4; i++) {
const count = random(0, maxPerEdge);
for (let j = 0; j < count; j++) {
const yIndex = Math.max(random(-2, size - 1), 0);
board[0][yIndex] = null;
}
board = rotate90Degrees(board);
}
return board;
}
function addDeadCorners(board: Board, random: rand) {
const scale = getScale(board) + 1;
addDeadCorner(board, random, scale);
if (!random(0, 3)) {
board = rotate90Degrees(board);
board = rotate90Degrees(board);
addDeadCorner(board, random, scale - 2);
}
return randomizeRotation(board, random);
}
function addDeadCorner(board: Board, random: rand, size: number) {
let currentSize = size;
for (let i = 0; i < size && i < currentSize; i++) {
random(0, 1) && currentSize--;
board[i].forEach((point, index) => index < currentSize && point && (board[point.x][point.y] = null));
}
return board;
}
function addCenterBreak(board: Board, random: rand) {
const size = board[0].length;
const maxOffset = getScale(board);
const xIndex = random(0, maxOffset * 2) - maxOffset + Math.floor(size / 2);
const length = random(1, Math.floor(size / 2 - 1));
board[xIndex] = board[xIndex].map((point, index) => (index < length ? null : point));
return randomizeRotation(board, random);
}
function ensureOfflineNodes(board: Board) {
if (board.flat().some((point) => !point)) {
return board;
}
board[0][0] = null;
return board;
}
function randomizeRotation(board: Board, random: rand) {
return rotateNTimes(board, random(0, 3));
}
function rotateNTimes(board: Board, rotations: number) {
for (let i = 0; i < rotations; i++) {
board = rotate90Degrees(board);
}
return board;
}
export function rotate90Degrees(board: Board): Board {
return board[0].map((_, index: number) => board.map((row: (PointState | null)[]) => row[index]).reverse());
}