グリッドサイズ
8×8(64マス、GridPosition で管理)
配置ルール
- BlockShape.cells(at: anchor) で配置先セル群取得
- すべてのセルが
.empty かつグリッド範囲内なら有効
- 配置時に grid[row][col] = .filled(blockColor)
- 1マス = 1点(配置スコア)
ライン消去
| 条件 | 判定 |
| 横ライン | 行の8マス全部 filled |
| 縦ライン | 列の8マス全部 filled |
| クロス | 行+列同時 → 交差点を crossPositions Setに記録 |
スコア計算
| 項目 | 得点 |
| 配置(1マス) | +1 |
| ライン消去(基本) | 20 × ライン数 × max(1, comboCount) |
| Double(2ライン) | +30 |
| Triple(3ライン) | +80 |
| Quad(4+ライン) | +200 |
| Cross(行+列同時) | +150 |
| Perfect Clear(全消し) | +500 |
コンボシステム
- 消去直後に新ブロック配置で再消去 → comboCount++
- コンボ2以上で「Nice!」「Great!」「Amazing!」演出
- 各コンボでハプティクス+サウンド段階化
ゲームオーバー判定
トレイ内の全ブロックが「どの回転状態でも」配置不可なら gameOver。
GameEngine.canPlace(block:) が4回転すべてを試す(フェアネス設計)。
トレイ補充
- 3ブロック全消費で
refillTray() → BlockShape.generateTray()
- フェアネス: 1トレイに5マス以上ブロックは最大1個
アンドゥ
- UndoSnapshot で grid/blocks/score/comboCount をキャプチャ
- 最大3回(2回目以降はリワード広告必須)
- 新手を配置すると snapshot が上書き → 1手のみ復元可
変更履歴
| バージョン | 日付 | 変更内容 |
|---|
| 1.0 | 2026-05-09 | 初版作成 |