Add pure-Dart engine core: RNG, grid, placement, line clear, scoring, piece generator
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>
This commit is contained in:
@@ -0,0 +1,41 @@
|
||||
import '../models/cell.dart';
|
||||
import '../models/grid.dart';
|
||||
import '../models/piece.dart';
|
||||
|
||||
/// Whether [piece] fits with its anchor at ([x], [y]).
|
||||
bool canPlace(GridState grid, Piece piece, int x, int y) {
|
||||
for (final (dx, dy) in piece.offsets) {
|
||||
final px = x + dx;
|
||||
final py = y + dy;
|
||||
if (px < 0 || px >= GridState.size || py < 0 || py >= GridState.size) {
|
||||
return false;
|
||||
}
|
||||
if (grid.isOccupied(px, py)) return false;
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
/// Places [piece] at ([x], [y]); caller must check [canPlace] first.
|
||||
GridState place(GridState grid, Piece piece, int x, int y) {
|
||||
var next = grid;
|
||||
for (final (dx, dy) in piece.offsets) {
|
||||
next = next.withCell(
|
||||
x + dx,
|
||||
y + dy,
|
||||
Cell(CellType.filled, colorId: piece.colorId),
|
||||
);
|
||||
}
|
||||
return next;
|
||||
}
|
||||
|
||||
/// Whether at least one of [pieces] has at least one legal placement.
|
||||
bool anyPlacementExists(GridState grid, List<Piece> pieces) {
|
||||
for (final piece in pieces) {
|
||||
for (var y = 0; y < GridState.size; y++) {
|
||||
for (var x = 0; x < GridState.size; x++) {
|
||||
if (canPlace(grid, piece, x, y)) return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
return false;
|
||||
}
|
||||
Reference in New Issue
Block a user