01
BOARD DATA
岩とアイテムを別の16×16配列に記憶
rocks[y][x] は岩、items[y][x] は0=なし・1〜99=得点・255=★。プレイヤーは常にY=15です。
◆=岩 数字=得点 ★=面クリア ▲=プレイヤー
bool rocks[16][16];
uint8_t items[16][16];
uint8_t playerX; // Yは常に15Webからは毎ティック、新しい最上段の岩マスクと16列分のアイテム値が届きます。
02
ONE TICK
衝突と取得の判定は2回ある
①移動左・停止・右
判定①移動先の最下段
②落下全オブジェクト+1行
判定②頭上から落ちた物
移動した瞬間は安全でも、その直後にY=14の岩が落ちてくれば衝突します。
safeAt() は両方を確認します。03
CMD_TICK
Webと同じ順番で、盤面を1段ずらす
現在位置で取得処理をし、岩とアイテムを下へずらし、もう一度取得処理。その後、新しい最上段を登録します。
矢印の方向へ1行落下する
playerX = buf[1]; 判定①: items[15][playerX] shiftRocks(spawnMask); shiftItems(); 判定②: items[15][playerX] items[0][x] = buf[5+x];
Webと更新順がずれると、デバイスが予測した未来と実際の衝突が一致しなくなります。
04
SPACE × TIME
盤面を「列X × 未来時刻t」に変換する
横はプレイヤーの列、縦は未来のティック。緑のマスを左・停止・右でつないだ線が、生存できる経路です。
横=X 縦=t(下へ行くほど未来)
safeAt(x,t)
判定①: rocks[16-t][x] 判定②: rocks[15-t][x] どちらかに岩があれば危険;
今Y=15−tにある岩は、tティック後の落下直後にプレイヤーへ到達します。
05
MEMOIZED DFS
未来の各状態を一度だけ調べる
memo[t][x] は −1=未探索、0=死亡、1=生存可能。最大17×16=272状態なので軽量です。
canSurvive(x,t) {
左・停止・右の各 nx について
safeAt(nx,t+1) かつ canSurvive(nx,t+1)
なら memo[t][x]=1;
全部だめなら 0;
}目先の1マスだけでなく、現在見えている岩がすべて落ち切るまで逃げ道が続く候補だけを採用します。
06
RISK / REWARD
生存できる候補の中で、アイテムを狙う
近い得点±1列の寄り道ならセーフティラインへ戻りやすい。
高得点深く外れるほど得点は高いが、狙い岩で戻れなくなる。
★即クリア+ノルマ免除。高得点の後の脱出口にもなる。
候補を作る左・停止・右
生存確認canSurvive()
即時取得2回の判定を見る
DIR最良方向を返す
配布スケッチは近いアイテムまで。さらに勝つには「得点−ライン復帰コスト」と、その先に★があるかを評価します。
✓
SUMMARY
RockDodge.ino 全体を一言ずつ
shiftRocks/items()Webと同じ落下を配列で再現。safeAt(x,t)未来の移動直後と落下直後を判定。canSurvive(x,t)時空間上の生存経路をメモ化DFS。nearItemDir()安全に寄り道できる近い得点を探す。computeNextDir()生存を絶対条件に取得ボーナスを比較。