0210c14858
PCG32 seeded RNG; immutable 8x8 GridState with occupancy bitmask; placement legality + anyPlacementExists; simultaneous row/col clears with single-count gem credit; combo scoring with one-move grace; weighted-bag generator with pity bias and depth-3 solvability nudge. All TDD, 51 tests green. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
57 lines
1.4 KiB
Dart
57 lines
1.4 KiB
Dart
import '../models/cell.dart';
|
|
import '../models/grid.dart';
|
|
|
|
class ClearResult {
|
|
const ClearResult({
|
|
required this.grid,
|
|
required this.clearedRows,
|
|
required this.clearedCols,
|
|
required this.gemsCleared,
|
|
});
|
|
|
|
final GridState grid;
|
|
final List<int> clearedRows;
|
|
final List<int> clearedCols;
|
|
final int gemsCleared;
|
|
|
|
int get linesCleared => clearedRows.length + clearedCols.length;
|
|
}
|
|
|
|
/// Detects all simultaneously full rows/columns and clears them in one pass.
|
|
ClearResult detectAndClear(GridState grid) {
|
|
final rows = <int>[];
|
|
final cols = <int>[];
|
|
for (var y = 0; y < GridState.size; y++) {
|
|
if (grid.isRowFull(y)) rows.add(y);
|
|
}
|
|
for (var x = 0; x < GridState.size; x++) {
|
|
if (grid.isColFull(x)) cols.add(x);
|
|
}
|
|
if (rows.isEmpty && cols.isEmpty) {
|
|
return ClearResult(
|
|
grid: grid,
|
|
clearedRows: const [],
|
|
clearedCols: const [],
|
|
gemsCleared: 0,
|
|
);
|
|
}
|
|
|
|
final rowSet = rows.toSet();
|
|
final colSet = cols.toSet();
|
|
var gems = 0;
|
|
var next = grid;
|
|
for (var y = 0; y < GridState.size; y++) {
|
|
for (var x = 0; x < GridState.size; x++) {
|
|
if (!rowSet.contains(y) && !colSet.contains(x)) continue;
|
|
if (grid.cellAt(x, y).type == CellType.gem) gems++;
|
|
next = next.withCell(x, y, Cell.empty);
|
|
}
|
|
}
|
|
return ClearResult(
|
|
grid: next,
|
|
clearedRows: rows,
|
|
clearedCols: cols,
|
|
gemsCleared: gems,
|
|
);
|
|
}
|