mirror of
https://github.com/bitburner-official/bitburner-src.git
synced 2026-04-17 06:48:42 +02:00
162 lines
4.5 KiB
TypeScript
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());
|
|
}
|