Claudeに、ブロック崩しを作ってもらいました。全6ステージ、ブロックの硬さが3種類あるやつです。
自分で遊んで一通り確かめたあと、念のため自動で遊ばせてみました。ブラウザを勝手に操作する仕組みを使って、パドルをボールの真下へ動かし続けるだけの、ごく単純な自動プレイです。人間より正確に追いかけます。
そうしたら、終わらない試合が出ました。
ボールが、真っすぐ上下に往復し続ける
画面の中では、こうなっていました。
ボールが真上へ飛び、真下へ戻ってくる。左右にまったく動きません。すでに崩れて空になった縦の列を、エレベーターみたいに行ったり来たりしています。
ブロックには当たらない。下にも落ちない。残機も減らない。ゲームが終わる条件に、ひとつも近づかない。
自動プレイのほうも律儀なもので、ボールの真下にパドルを置き続けます。永久に。
原因は、たった一か所の掛け算でした
このゲームは、パドルのどこで受けたかで跳ね返る角度を変えています。端で受ければ大きく横へ、真ん中で受ければ素直に上へ。ブロック崩しの基本です。
問題は「真ん中」でした。実際に同じ式で計算してみます。
受けた位置:ちょうど真ん中 パドル:止まっている 横の速度 → 0.0000000000000003 縦の速度 → −5.5
横がゼロです。ボールは完全に垂直に飛びます。
そして、ここが厄介なところでした。上で跳ね返るとき、変わるのは縦の符号だけです。横の速度には誰も触らない。ゼロはゼロのまま、次も、その次も、永遠に。
一度その状態に入ると、出口がありません。
パドルが上手いほど、ハマる
これに気づいたとき、少し笑ってしまいました。
ボールをど真ん中で受けるのは、下手な人には難しいことです。たいてい少しズレます。ズレれば横の速度がつくので、この状態には入りません。
ところが、ボールをぴったり追いかけると、パドルの中心はいつもボールの真下にあります。しかも追いつききっているので、パドルは動いていません。横の速度を足してくれるはずのパドル自身の動きも、ゼロ。
つまり、完璧に受け続ける人だけが、終わらない試合に入れる。そういうバグでした。
私が手で遊んでいるあいだ、一度も出なかったのも当然です。私はそんなに上手くありません。
直し方は、下限を決めること
いまのネオンブレイカーには、こういう決まりが入っています。
- 跳ね返ったあと、横の速度が小さすぎたら、垂直から9度以上は必ず傾ける
- 同じように、縦が小さすぎたら、水平から19度以上は必ず傾ける
2つめは逆のケースへの備えです。横に寝すぎると、今度はボールが画面を横に滑り続けます。上下どちらの「寝すぎ」も禁止、という形になりました。
ひとつ気をつけたのは、傾けるときにボールを速くしないことです。横を足したぶん縦を削って、速さの合計は変えていません。中学校で習う三平方の定理が、こんなところで出てきます。
なので、ど真ん中で受けても、ボールはほんの少しだけ斜めに飛びます。遊んでいて気づかない程度です。でも、ゼロではない。ゼロでなければ、いつかは横の壁に届きます。
打ち間違いと、同じことをしていた
三十五年前、ベーマガのプログラムを打ち込んでは、よく動かしていました。動かないときは誌面と画面を1文字ずつ照合するしかありません。カンマがピリオドになっている。0とOを間違えている。見つけると、動く。
あれは「動かない」バグでした。今回のは「動きすぎて終わらない」バグです。正反対のようですが、やったことは同じでした。おかしなところを目で見つけて、数字を一か所直す。
違うのは、探すのを機械にやらせたことだけです。人間が何十回遊んでも出ないものを、自動プレイは律儀に引き当ててくれました。しかも「上手いから引き当てた」というのが、いちばん面白いところでした。
ひとつ、書けなかったこと
この記事には、本当は「何回に1回起きるか」を載せるつもりでした。前の2本でも数字を測って書いたので。
修正前の状態に戻して、自動プレイを走らせて数えてみました。1回目は10回のうち1回、はまりました。もう一度やったら、10回やって0回でした。数え方そのものが怪しい。試合が途中で終わってしまっていて、そもそも最後まで走っていませんでした。
ちゃんと測れる形に直すには、もう少し手間がかかります。怪しい数字を載せるのはやめました。「起きる」ことと「なぜ起きるか」は計算で確かめられたので、今回はそこまでにしておきます。
いまは直っています。安心して崩してください。
遊んでみてください。→ ネオンブレイカー

コメント