import 'package:block_seasons/game/engine/placement.dart'; import 'package:block_seasons/game/models/cell.dart'; import 'package:block_seasons/game/models/grid.dart'; import 'package:block_seasons/game/models/piece.dart'; import 'package:flutter_test/flutter_test.dart'; const mono = Piece(id: 'mono', colorId: 0, offsets: [(0, 0)]); const dominoH = Piece(id: 'domino_h', colorId: 1, offsets: [(0, 0), (1, 0)]); const square2 = Piece( id: 'square2', colorId: 2, offsets: [(0, 0), (1, 0), (0, 1), (1, 1)], ); void main() { group('canPlace', () { test('any piece fits anywhere legal on an empty grid', () { final grid = GridState.empty(); expect(canPlace(grid, mono, 0, 0), isTrue); expect(canPlace(grid, mono, 7, 7), isTrue); expect(canPlace(grid, square2, 6, 6), isTrue); }); test('rejects out-of-bounds placements', () { final grid = GridState.empty(); expect(canPlace(grid, square2, 7, 7), isFalse); expect(canPlace(grid, dominoH, 7, 0), isFalse); expect(canPlace(grid, mono, -1, 0), isFalse); expect(canPlace(grid, mono, 0, 8), isFalse); }); test('rejects overlap with occupied cells', () { final grid = GridState.empty() .withCell(1, 0, const Cell(CellType.filled, colorId: 0)); expect(canPlace(grid, dominoH, 0, 0), isFalse); expect(canPlace(grid, dominoH, 2, 0), isTrue); }); }); group('place', () { test('fills cells with the piece color and keeps original grid', () { final grid = GridState.empty(); final next = place(grid, square2, 3, 3); expect(grid.occupiedCount, 0); expect(next.occupiedCount, 4); for (final (dx, dy) in square2.offsets) { expect(next.cellAt(3 + dx, 3 + dy).type, CellType.filled); expect(next.cellAt(3 + dx, 3 + dy).colorId, square2.colorId); } }); }); group('anyPlacementExists', () { test('true on an empty grid', () { expect(anyPlacementExists(GridState.empty(), [square2]), isTrue); }); test('detects when only a small piece fits', () { // Fill everything except (7, 7). var grid = GridState.empty(); for (var y = 0; y < GridState.size; y++) { for (var x = 0; x < GridState.size; x++) { if (x == 7 && y == 7) continue; grid = grid.withCell(x, y, const Cell(CellType.filled, colorId: 0)); } } expect(anyPlacementExists(grid, [mono]), isTrue); expect(anyPlacementExists(grid, [dominoH]), isFalse); expect(anyPlacementExists(grid, [dominoH, mono]), isTrue); }); test('false when the grid is completely full', () { var grid = GridState.empty(); for (var y = 0; y < GridState.size; y++) { for (var x = 0; x < GridState.size; x++) { grid = grid.withCell(x, y, const Cell(CellType.filled, colorId: 0)); } } expect(anyPlacementExists(grid, [mono]), isFalse); }); }); }