骨までしゃぶりつくす「ぷよぷよプログラミング」(2/4)

この記事は未完成です@2022/02/15
大まかに使用の要点は記述できたのでfixとします。@2022/02/19

# この記事の目的
　この記事では[前回記事](https://qiita.com/KennyKTA/items/360aa62aa7f7ba084a2f)の

- 目的2.「ぷよぷよプログラミング」のソースコードを理解することで、その仕様や設計を推測してドキュメント化する

に沿ってソースコードを読み込んだ結果をできるだけ仕様、設計に復元しようと思います。

# 前置き
　「ぷよぷよ」は日本ではかなりの市民権を得ているゲームで、そのルールを知らない人はあまりいないと思います。ですので、ゲームとしてのルールはある程度知っている前提で、そのゲームをWebアプリとして動作させるために必要な仕様や設計をソースコードから書き起こします。下記を一読してからソースコードを読むと、何を実現しようとしているか理解しやすくなると思われます。以下は厳密な仕様を規定するわけではなく、ソースコードの理解を促す目的のドキュメントだと捉えてください。

# 仕様

## 状態遷移仕様
　game.js から抽出したゲームの状態遷移図が以下です。楕円が状態を表現します。ゲームは開始状態(Start）から始まり、終了状態（batankyu）へ移行するまでループします。この状態を約1/60秒毎（ディスプレイのリフレッシュレート）に更新することでゲームが動きます。状態遷移図をよく見てみると<font color="Red">newPuyo</font>が中心的な存在に見えます。名前からわかる通り、新しいぷよぷよを発生させる処理が紐づいているのですが、ぷよぷよが発生することで操作対象が生まれて playing できますし、詰みの状態であれば gameOver になりますし、連鎖後には新しいぷよぷよを発生させる必要があるので線が出入りしているわけです。大雑把にみると<font color="MediumSeaGreen">緑点線（プレイヤーが介入しない）</font>、黒点線（プレイヤーが介入する）、<font color="Red">赤点線（終了処理）</font>で系統をくくれるように見えます。ゲーム自体の挙動を体感したことがあっても、プログラミングする前にはこのような遷移図があると作製対象への理解が高まります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/0c9e43ab-740e-642c-a025-9504f7777f7f.png)

## 画面仕様
　このぷよぷよは、右方向を正としたX軸、下方向を正としたY軸でゲーム内の論理的な位置を表現します。デフォルトでは横６マス、縦１２マスのエリアでプレイが可能です。図にすると以下のようになります。薄く着色している部分でプレーすることになります。この範囲は、コンフィギュレーション可能です。また、デフォルトではぷよぷよは左から3列目（ソース内のコメントでは2列目とあるが、そのまま実装すると3列目になります）のマイナス位置で発生します。後述しますが、ぷよぷよは中心ぷよ（centralPuyo）と可動ぷよ（movablePuyo）で構成されます。可動ぷよは中心ぷよの論理的な位置を基準として回転します。ぷよぷよのデフォルト発生位置は<font color="DarkMagenta">図中紫が中心ぷよ</font>、<font color="MediumSeaGreen">黄緑が可動ぷよ</font>です。
　

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/b28d0635-4075-832a-23ee-9cf05ea5af87.png)

## 操作仕様
###プレイヤーの入力
　プレイヤーはぷよぷよを操作することができます。ゲームの状態に応じて可能な操作が変わります。

　batankyuの場合

- キーボードの上矢印でページをリロードして新しいゲームを再開する

　それ以外の場合

- キーボードの左矢印で中心ぷよの位置を１つ左に動かす
- キーボードの右矢印で中心ぷよの位置を１つ右に動かす
- キーボードの上矢印で可動ぷよの位置を反時計回りに９０度動かす
- キーボードの下矢印でぷよぷよの落下速度を上げる

です。

###可動ぷよの回転仕様
中心ぷよの位置に対して特定位置に床、壁、積まれたぷよぷよが存在すると可動ぷよの回転によって中心ぷよの位置に影響を及ぼします。可動ぷよの移動前の位置に応じて仕様を記述します。

- 可動ぷよが中心ぷよの右にある場合

この場合は何も注意することはなく、可動ぷよが中心ぷよの上に移動します。図にすると以下のようになります。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/c23b2d46-2f5b-b7f1-bf49-c2b3f5e2a238.png)

- 可動ぷよが中心ぷよの上にある場合

中心ぷよの左隣に壁もしくは積まれたぷよぷよが存在すると中心ぷよの位置が右に一つずれて回転します。図にすると以下のようになります。この挙動が実現できない場合、つまり中心ぷよの右隣に壁もしくは積まれたぷよが存在する場合は回転はできません。それ以外は可動ぷよが中心ぷよの左に移動します。
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/4813692f-c9b2-9a08-b69b-72ee01458f2d.png)


- 可動ぷよが中心ぷよの左にある場合
中心ぷよの真下もしくは左下に床もしくは積まれたぷよぷよが存在すると中心ぷよの位置が上に一つずれて回転します。図にすると以下のようになります。

真下の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/e32f6977-b353-3f59-b340-eebf7e8b7788.png)
左下の場合
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/84f2e1c2-d9d2-dd4b-8183-082f0821a653.png)



- 可動ぷよが中心ぷよの下にある場合

中心ぷよの右隣に壁もしくは積まれたぷよぷよが存在すると中心ぷよの位置が左に一つずれて回転します。図にすると以下のようになります。この挙動が実現できない場合、つまり中心ぷよの左隣に壁もしくは積まれたぷよが存在する場合は回転はできません。それ以外は可動ぷよが中心ぷよの右に移動します。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/626166/dfc419f4-bcf1-85b8-a6fb-b4537d174f44.png)


　パターンは上述の通りです。何気なく操作しているぷよぷよですが、その動きを文書化してみるとこういったケースに分類できるんですね。ぷよぷよプログラミングでは逆回りの回転は仕様に無いので追加で実装してみるのも面白いかもしれません。

## 落下の仕様
　ぷよぷよの自由落下はデフォルトでは1/60秒毎に16pxずつ落下していきます。また、設置の閾値は20フレーム（つまり1/3秒）です。

## 全消しに関して
　積まれたぷよぷよがある状態ですべてのぷよぷよが消された場合、全消しと判定します。全消しした場合は全消しのイラストが画面下から中央に登場します。登場したイラストは次回ぷよぷよを消すまで表示されます。

## バタンキューに関して
　ゲームオーバーになるとバタンキューのイラストが表示されます。ページがリロードされるまで左右に揺れながらページを上下します。

# 得点の仕様に関して

- 全消し:3600点
- 下キー入力による加速:1点/1論理位置
- ぷよぷを消したことによる得点

計算式
スコア= スケール×消したぷよの数×10
スケール = 連鎖ボーナス+ 消した数のボーナス + 消した色の数のボーナス
連鎖ボーナス=Score.rensaBonusに格納されている値から選ばれる。連鎖数が配列のインデックスとなる。
消した数のボーナス=Score.pieceBonusに格納されている値から選ばれる。連鎖の各回で消したぷよぷよの数が配列のインデックスとなる。 
消した色の数のボーナス=Score.colorBonusに格納されている値から選ばれる。連鎖の各回で消したぷよぷよの色の数が配列のインデックスとなる。

例として連鎖ごとに１色、４ぷよぷよを消して３連鎖した場合を考えると

1連鎖目：スケール = 8 + 2 + 0 = 10、スコア=10×4×10 = 400
2連鎖目：スケール = 16+ 2 + 0 = 10、スコア=18×4×10 = 720
3連鎖目：スケール = 32+ 2 + 0 = 10、スコア=34×4×10 = 1360

合計点=400+720+1360=2480

となる。

## 最後に
ＧＵＩ系統の仕様記述があまいが、このあたりで仕様の記述はとめる。

次回

https://qiita.com/KennyKTA/items/d9383cacb180096261ef