import 'package:block_seasons/game/engine/line_clear.dart'; import 'package:block_seasons/game/models/cell.dart'; import 'package:block_seasons/game/models/grid.dart'; import 'package:flutter_test/flutter_test.dart'; GridState _fillRow(GridState grid, int y, {Set? skip}) { for (var x = 0; x < GridState.size; x++) { if (skip?.contains(x) ?? false) continue; grid = grid.withCell(x, y, const Cell(CellType.filled, colorId: 0)); } return grid; } GridState _fillCol(GridState grid, int x, {Set? skip}) { for (var y = 0; y < GridState.size; y++) { if (skip?.contains(y) ?? false) continue; grid = grid.withCell(x, y, const Cell(CellType.filled, colorId: 0)); } return grid; } void main() { group('detectAndClear', () { test('no full lines leaves the grid untouched', () { final grid = _fillRow(GridState.empty(), 3, skip: {5}); final result = detectAndClear(grid); expect(result.clearedRows, isEmpty); expect(result.clearedCols, isEmpty); expect(result.linesCleared, 0); expect(result.gemsCleared, 0); expect(result.grid.occupiedCount, grid.occupiedCount); }); test('clears a single full row', () { final grid = _fillRow(GridState.empty(), 2); final result = detectAndClear(grid); expect(result.clearedRows, [2]); expect(result.clearedCols, isEmpty); expect(result.linesCleared, 1); expect(result.grid.occupiedCount, 0); }); test('clears a single full column', () { final grid = _fillCol(GridState.empty(), 6); final result = detectAndClear(grid); expect(result.clearedRows, isEmpty); expect(result.clearedCols, [6]); expect(result.grid.occupiedCount, 0); }); test('clears two rows at once', () { var grid = _fillRow(GridState.empty(), 0); grid = _fillRow(grid, 7); final result = detectAndClear(grid); expect(result.clearedRows, [0, 7]); expect(result.linesCleared, 2); expect(result.grid.occupiedCount, 0); }); test('row and column sharing a corner clear together', () { var grid = _fillRow(GridState.empty(), 4); grid = _fillCol(grid, 4); final result = detectAndClear(grid); expect(result.clearedRows, [4]); expect(result.clearedCols, [4]); expect(result.linesCleared, 2); // 8 + 8 - 1 shared cell were occupied; all gone now. expect(result.grid.occupiedCount, 0); }); test('counts gems in cleared lines, intersection gem only once', () { var grid = GridState.empty(); grid = grid.withCell(4, 4, const Cell(CellType.gem)); grid = grid.withCell(0, 4, const Cell(CellType.gem)); grid = grid.withCell(4, 0, const Cell(CellType.gem)); grid = _fillRow(grid, 4, skip: {0, 4}); grid = _fillCol(grid, 4, skip: {0, 4}); final result = detectAndClear(grid); expect(result.clearedRows, [4]); expect(result.clearedCols, [4]); // Gems at (0,4), (4,0), and the shared (4,4) -> exactly 3. expect(result.gemsCleared, 3); }); test('cells outside cleared lines survive', () { var grid = _fillRow(GridState.empty(), 1); grid = grid.withCell(3, 5, const Cell(CellType.filled, colorId: 2)); final result = detectAndClear(grid); expect(result.grid.occupiedCount, 1); expect(result.grid.cellAt(3, 5).colorId, 2); }); }); }