@logic-pad/core
Version:
417 lines (416 loc) • 20.3 kB
TypeScript
import GridConnections from './gridConnections.js';
import { CachedAccess } from './dataHelper.js';
import { Color, Direction, Orientation, Position } from './primitives.js';
import Rule from './rules/rule.js';
import Symbol from './symbols/symbol.js';
import TileData from './tile.js';
import MusicGridRule from './rules/musicGridRule.js';
import CompletePatternRule from './rules/completePatternRule.js';
import UndercluedRule from './rules/undercluedRule.js';
import GridZones from './gridZones.js';
import WrapAroundRule from './rules/wrapAroundRule.js';
export declare const NEIGHBOR_OFFSETS: Position[];
export default class GridData {
readonly width: number;
readonly height: number;
readonly tiles: readonly (readonly TileData[])[];
readonly connections: GridConnections;
readonly zones: GridZones;
readonly symbols: ReadonlyMap<string, readonly Symbol[]>;
readonly rules: readonly Rule[];
readonly musicGrid: CachedAccess<MusicGridRule | undefined>;
readonly completePattern: CachedAccess<CompletePatternRule | undefined>;
readonly underclued: CachedAccess<UndercluedRule | undefined>;
readonly wrapAround: CachedAccess<WrapAroundRule | undefined>;
/**
* Create a new grid with tiles, connections, symbols and rules.
*
* @param width The width of the grid.
* @param height The height of the grid.
* @param tiles The tiles of the grid.
* @param connections The connections of the grid, which determines which tiles are merged.
* @param zones The zones of the grid.
* @param symbols The symbols in the grid.
* @param rules The rules of the grid.
*/
constructor(width: number, height: number, tiles?: readonly (readonly TileData[])[], connections?: GridConnections, zones?: GridZones, symbols?: ReadonlyMap<string, readonly Symbol[]>, rules?: readonly Rule[]);
/**
* Create a new GridData object from a string array.
*
* - Use `b` for dark cells, `w` for light cells, and `n` for gray cells.
* - Capitalize the letter to make the tile fixed.
* - Use `.` to represent empty space.
*
* @param array - The string array to create the grid from.
* @returns The created grid.
*/
static create(array: string[]): GridData;
/**
* Create a new grid with tiles, connections, symbols and rules. Sanitize the provided list of symbols and rules,
* and trigger grid change events.
*
* @param width The width of the grid.
* @param height The height of the grid.
* @param tiles The tiles of the grid.
* @param connections The connections of the grid, which determines which tiles are merged.
* @param zones The zones of the grid.
* @param symbols The symbols in the grid.
* @param rules The rules of the grid.
*/
static create(width: number, height: number, tiles?: readonly (readonly TileData[])[], connections?: GridConnections, zones?: GridZones, symbols?: ReadonlyMap<string, readonly Symbol[]>, rules?: readonly Rule[]): GridData;
/**
* Copy the current grid while modifying the provided properties.
* @param param0 The properties to modify.
* @returns The new grid with the modified properties.
*/
copyWith({ width, height, tiles, connections, zones, symbols, rules, }: {
width?: number;
height?: number;
tiles?: readonly (readonly TileData[])[];
connections?: GridConnections;
zones?: GridZones;
symbols?: ReadonlyMap<string, readonly Symbol[]>;
rules?: readonly Rule[];
}): GridData;
/**
* Copy the current grid while modifying the provided properties.
* Skip sanitization and event triggering for performance.
*
* @param param0 The properties to modify.
* @returns The new grid with the modified properties.
*/
fastCopyWith({ width, height, tiles, connections, zones, symbols, rules, }: {
width?: number;
height?: number;
tiles?: readonly (readonly TileData[])[];
connections?: GridConnections;
zones?: GridZones;
symbols?: ReadonlyMap<string, readonly Symbol[]>;
rules?: readonly Rule[];
}): GridData;
toArrayCoordinates(x: number, y: number): Position;
isPositionValid(x: number, y: number): boolean;
/**
* Safely get the tile at the given position.
* @param x The x-coordinate of the tile.
* @param y The y-coordinate of the tile.
* @returns The tile at the given position, or a non-existent tile if the position is invalid.
*/
getTile(x: number, y: number): TileData;
/**
* Safely set the tile at the given position.
* If the position is invalid, the tile array is returned unchanged.
* If the tile is merged with other tiles, the colors of all connected tiles are changed.
*
* @param x The x-coordinate of the tile.
* @param y The y-coordinate of the tile.
* @param tile The new tile to set.
* @returns The new tile array with updated tiles.
*/
setTile(x: number, y: number, tile: TileData | ((tile: TileData) => TileData)): readonly (readonly TileData[])[];
/**
* Replace or modify all tiles in the grid.
*
* @param tiles The new tile array or a function to mutate the existing tile array.
* @returns The new grid with the new tiles.
*/
withTiles(tiles: readonly (readonly TileData[])[] | ((value: TileData[][]) => readonly (readonly TileData[])[])): GridData;
/**
* Add or modify the connections in the grid.
* @param connections The new connections to add or modify.
* @returns The new grid with the new connections.
*/
withConnections(connections: GridConnections | ((value: GridConnections) => GridConnections)): GridData;
/**
* Add or modify the zones in the grid.
* @param zones The new zones to add or modify.
* @returns The new grid with the new zones.
*/
withZones(zones: GridZones | ((value: GridZones) => GridZones)): GridData;
/**
* Add or modify the symbols in the grid.
* @param symbols The new symbols to add or modify.
* @returns The new grid with the new symbols.
*/
withSymbols(symbols: readonly Symbol[] | ReadonlyMap<string, readonly Symbol[]> | ((value: Map<string, readonly Symbol[]>) => ReadonlyMap<string, readonly Symbol[]>)): GridData;
/**
* Add a new symbol to the grid.
* @param symbol The symbol to add.
* @returns The new grid with the new symbol.
*/
addSymbol(symbol: Symbol): GridData;
/**
* Remove an instance of the symbol from the grid.
* @param symbol The symbol to remove.
* @returns The new grid with the symbol removed.
*/
removeSymbol(symbol: Symbol): GridData;
/**
* Remove all symbols that satisfy the predicate.
* @param predicate The predicate to test each symbol with.
* @returns The new grid with the symbols removed.
*/
removeSymbolIf(predicate: (symbol: Symbol) => boolean): GridData;
/**
* Find the first symbol that satisfies the predicate.
* @param predicate The predicate to test each symbol with.
* @returns The first symbol that satisfies the predicate, or undefined if no symbol is found.
*/
findSymbol(predicate: (symbol: Symbol) => boolean): Symbol | undefined;
/**
* Replace an existing symbol with a new symbol.
* @param oldSymbol The symbol to replace.
* @param newSymbol The new symbol to replace with.
* @returns The new grid with the symbol replaced.
*/
replaceSymbol(oldSymbol: Symbol, newSymbol: Symbol): GridData;
/**
* Add or modify the rules in the grid.
* @param rules The new rules to add or modify.
* @returns The new grid with the new rules.
*/
withRules(rules: readonly Rule[] | ((value: readonly Rule[]) => readonly Rule[])): GridData;
/**
* Add a new rule to the grid.
* @param rule The rule to add.
* @returns The new grid with the new rule.
*/
addRule(rule: Rule): GridData;
/**
* Remove an instance of the rule from the grid.
* @param rule The rule to remove.
* @returns The new grid with the rule removed.
*/
removeRule(rule: Rule): GridData;
/**
* Remove all rules that satisfy the predicate.
* @param predicate The predicate to test each rule with.
* @returns The new grid with the rules removed.
*/
removeRuleIf(predicate: (rule: Rule) => boolean): GridData;
/**
* Find the first rule that satisfies the predicate.
* @param predicate The predicate to test each rule with.
* @returns The first rule that satisfies the predicate, or undefined if no rule is found.
*/
findRule(predicate: (rule: Rule) => boolean): Rule | undefined;
/**
* Replace an existing rule with a new rule.
* @param oldRule The rule to replace.
* @param newRule The new rule to replace with.
* @returns The new grid with the rule replaced.
*/
replaceRule(oldRule: Rule, newRule: Rule): GridData;
/**
* Insert a new column at the given index, shifting all components of the grid accordingly. Newly inserted tiles are gray.
* @param index The index to insert the column at.
* @returns The new grid with the new column inserted.
*/
insertColumn(index: number): GridData;
/**
* Insert a new row at the given index, shifting all components of the grid accordingly. Newly inserted tiles are gray.
* @param index The index to insert the row at.
* @returns The new grid with the new row inserted.
*/
insertRow(index: number): GridData;
/**
* Remove a column at the given index, shifting all components of the grid accordingly.
* @param index The index to remove the column at.
* @returns The new grid with the column removed.
*/
removeColumn(index: number): GridData;
/**
* Remove a row at the given index, shifting all components of the grid accordingly.
* @param index The index to remove the row at.
* @returns The new grid with the row removed.
*/
removeRow(index: number): GridData;
/**
* Resize the grid to the new width and height, shifting all components of the grid accordingly. Newly inserted tiles are gray.
* @param width The new width of the grid.
* @param height The new height of the grid.
* @returns The new grid with the new dimensions.
*/
resize(width: number, height: number): this;
/**
* Create a new mutable TileData array from a string array.
*
* - Use `b` for dark cells, `w` for light cells, and `n` for gray cells.
* - Capitalize the letter to make the tile fixed.
* - Use `.` to represent empty space.
*
* @param array - The string array to create the tiles from.
* @returns The created tile array.
*/
static createTiles(array: string[]): TileData[][];
/**
* Find a tile in the grid that satisfies the predicate.
*
* @param predicate The predicate to test each tile with.
* @returns The position of the first tile that satisfies the predicate, or undefined if no tile is found.
*/
find(predicate: (tile: TileData, x: number, y: number) => boolean): Position | undefined;
/**
* Iterate over all tiles in the same region as the given position that satisfy the predicate.
* The iteration stops when the callback returns a value that is not undefined.
* Non-existent tiles are not included in the iteration.
*
* @param position The position to start the iteration from. This position is included in the iteration.
* @param predicate The predicate to test each tile with. The callback is only called for tiles that satisfy this predicate.
* @param callback The callback to call for each tile that satisfies the predicate. The iteration stops when this callback returns a value that is not undefined.
* @param visited A 2D array to keep track of visited tiles. This array is modified by the function.
* @returns The value returned by the callback that stopped the iteration, or undefined if the iteration completed.
*/
iterateArea<T>(position: Position, predicate: (tile: TileData) => boolean, callback: (tile: TileData, x: number, y: number, logicalX: number, logicalY: number) => undefined | T, visited?: boolean[][]): T | undefined;
/**
* Iterate over all tiles in a straight line from the given position in the given direction that satisfy the predicate.
* The iteration stops when the callback returns a value that is not undefined.
* Non-existent tiles break the iteration.
*
* @param position The position to start the iteration from. This position is included in the iteration.
* @param direction The direction to iterate in.
* @param predicate The predicate to test each tile with. The callback is only called for tiles that satisfy this predicate.
* @param callback The callback to call for each tile that satisfies the predicate. The iteration stops when this callback returns a value that is not undefined.
* @param visited A 2D array to keep track of visited tiles. This array is modified by the function.
* @returns The value returned by the callback that stopped the iteration, or undefined if the iteration completed.
*/
iterateDirection<T>(position: Position, direction: Direction | Orientation, predicate: (tile: TileData) => boolean, callback: (tile: TileData, x: number, y: number, logicalX: number, logicalY: number) => T | undefined, visited?: boolean[][]): T | undefined;
/**
* Iterate over all tiles in a straight line from the given position in the given direction that satisfy the predicate.
* The iteration stops when the callback returns a value that is not undefined.
* Non-existent tiles are included in the iteration.
*
* @param position The position to start the iteration from. This position is included in the iteration.
* @param direction The direction to iterate in.
* @param predicate The predicate to test each tile with. The callback is only called for tiles that satisfy this predicate.
* @param callback The callback to call for each tile that satisfies the predicate. The iteration stops when this callback returns a value that is not undefined.
* @param visited A 2D array to keep track of visited tiles. This array is modified by the function.
* @returns The value returned by the callback that stopped the iteration, or undefined if the iteration completed.
*/
iterateDirectionAll<T>(position: Position, direction: Direction | Orientation, predicate: (tile: TileData) => boolean, callback: (tile: TileData, x: number, y: number, logicalX: number, logicalY: number) => T | undefined, visited?: boolean[][]): T | undefined;
/**
* Check if every tile in the grid is filled with a color other than gray.
*
* @returns True if every tile is filled with a color other than gray, false otherwise.
*/
isComplete(): boolean;
/**
* Iterate over all tiles in the grid.
* The iteration stops when the callback returns a value that is not undefined.
*
* @param callback The callback to call for each tile.
* @returns The value returned by the callback that stopped the iteration, or undefined if the iteration completed.
*/
forEach<T>(callback: (tile: TileData, x: number, y: number) => T | undefined): T | undefined;
/**
* Flood fill a continuous region starting from the given position with the given color.
*
* @param position The position to start the flood fill from.
* @param from The color of the tiles to fill.
* @param to The color to fill the tiles with.
* @param allowFixed Whether to fill fixed tiles.
* @returns The new grid with the region filled with the new color.
*/
floodFill(position: Position, from: Color, to: Color, allowFixed: boolean): GridData;
/**
* Flood fill all tiles with the given color to a new color, even if they are not connected.
*
* @param from The color of the tiles to fill.
* @param to The color to fill the tiles with.
* @param allowFixed Whether to fill fixed tiles.
* @returns The new grid with all tiles filled with the new color.
*/
floodFillAll(from: Color, to: Color, allowFixed: boolean): GridData;
/**
* Check if the grid has any instructions that require a custom solution.
* @returns True if the grid has any instructions that require a custom solution, false otherwise.
*/
requireSolution(): boolean;
/**
* Reset all non-fixed tiles to gray.
*
* @returns The new grid with all non-fixed tiles reset to gray.
*/
resetTiles(): this;
/**
* Copy the tiles in the given region to a new grid.
* All connections and symbols within the selected region are copied.
* All rules are included as well.
*
* @param origin The top-left corner of the region to copy.
* @param width The width of the region to copy.
* @param height The height of the region to copy.
* @returns The new grid with the copied tiles.
*/
copyTiles(origin: Position, width: number, height: number): GridData;
/**
* Paste the tiles from the given grid to the current grid at the given position.
* All connections, symbols, and rules are merged.
*
* @param origin The top-left corner of the region to paste the tiles to.
* @param grid The grid to paste the tiles from.
* @returns The new grid with the pasted tiles.
*/
pasteTiles(origin: Position, grid: GridData): GridData;
/**
* Paste the tiles from the given array to the current grid at the given position.
*
* @param origin The top-left corner of the region to paste the tiles to.
* @param tile The array of tiles to paste.
* @returns The new grid with the pasted tiles.
*/
pasteTiles(origin: Position, tile: readonly (readonly TileData[])[]): GridData;
/**
* Check if this grid is equal to another grid in terms of size and tile colors.
* Rules, symbols, and connections are not compared.
*
* @param grid The grid to compare with.
* @returns True if the grids are equal in size and tile colors, false otherwise.
*/
colorEquals(grid: GridData): boolean;
/**
* Check if this grid is equal to another grid in terms of size, tile colors, connections, symbols, and rules.
*
* @param other The grid to compare with.
* @returns True if the grids are equal, false otherwise.
*/
equals(other: GridData): boolean;
/**
* Get the count of tiles that satisfy the given conditions.
* @param exists Whether the tile exists or not.
* @param fixed Whether the tile is fixed or not. If undefined, the fixed state is ignored.
* @param color The color of the tile. If undefined, all colors are included.
* @returns The count of tiles that satisfy the given conditions.
*/
getTileCount(exists: boolean, fixed?: boolean | undefined, color?: Color | undefined): number;
/**
* Get the count of tiles that satisfy the given conditions for each color.
* @param color The color of the tiles.
* @returns The count of tiles that satisfy the given conditions for each color.
*/
getColorCount(color: Color): {
min: number;
max: number;
};
/**
* Deduplicate the rules in the given list.
*
* @param rules The list of rules to deduplicate.
* @returns The deduplicated list of rules.
*/
static deduplicateRules(rules: readonly Rule[]): Rule[];
/**
* Deduplicate the singleton rules in the given list.
*
* @param rules The list of rules to deduplicate.
* @returns The deduplicated list of rules.
*/
static deduplicateSingletonRules(rules: readonly Rule[]): Rule[];
/**
* Deduplicate the symbols in the given map.
*
* @param symbols The map of symbols to deduplicate.
* @returns The deduplicated map of symbols.
*/
static deduplicateSymbols(symbols: ReadonlyMap<string, readonly Symbol[]>): Map<string, Symbol[]>;
}