なぞぷよのAPIを考えてみた話

ぷよぷよのプログラムを作っていたら、なぞぷよで遊びたくなってくる。
好きななぞぷよが取得できるAPIがあったらゲーム制作が捗るだろうなと思ってまずは考えてみた。

# なぞぷよ
なぞぷよを検索すると色々ななぞぷよサイトが出てくる。
「なぞぷよシミュレータ」なるものがあり、自分で作ったなぞぷよや他の人が作ったなぞぷよを遊べる！　これは楽しい。


## なぞぷよサイト
https://ishikawapuyo.net/

## なぞぷよシミュレータ
なぞぷよシミュレータでは好きな配置にぷよを並べ、盤面に応じて以下のようなURLを生成してくれる。
https://ishikawapuyo.net/simu/pn.html?g00g00g00J0EHggloE_g1w1O1__u05
このURLをなぞぷよ投稿サイトで公開することで、みんなが作ったなぞぷよを遊べるという素晴らしいツール

ただ、この素晴らしいなぞぷよを自作のゲームと連携、
盤面情報をゲーム画面に打込む（例： g0_g1__u5）
みたいな作業が必須。
どうせならもう少し可読性の高いJSON APIにならないかな？と思って作ってみた。

## API案

#### メタ情報（あってもなくても）
- no: ただの項番
- level: 激辛とか
- move: なん手必要か
- creator: なぞぷよの作成者

#### 盤面情報

- conditions
    - クリア条件を表す。
    - なぞぷよシミュレータでは「cぷよn個消す」みたいなクリア条件が17通りあるので、それが全部網羅できれば良いかな。
- board
    - 初期配置を表す
- next
    - ネクぷよを表す

↓みたいなイメージになった。

```
{
  "no": "2",
  "level": "激辛",
  "move": "5手",
  "creator": "XXX",
  "conditions": {
    "condition": "n_chains",
    "c": null,
    "n": 8
  },
  "board": [
    {
      "color": "red",
      "cells": [
        76
      ]
    },
    {
      "color": "blue",
      "cells": [
        75,
        64,
        40
      ]
    }
  ],
  "next": [
    {
      "order": 1,
      "colors": [
        "blue",
        "red"
      ]
    },
    {
      "order": 3,
      "colors": [
        "blue",
        "red"
      ]
    }
  ]
}
```

## 実装

JSON全部手書きはしんどいので、既存のなぞぷよURLをjsonに変換するスクリプトを作った

盤面情報について、アンダーバーで区切った１つ目が初期配置を表しており、２つ目がネクぷよ、3つ目がクリア条件を表している。
`g00g00g00J0EHggloE_g1w1O1__u05`
このため、この文字列をパースしてぷよとマッピングしてあげれば良い。


```python
import sys

mapper = {
    "0": ["empty" , "empty" ],
    "1": ["empty" , "red"   ],
    "2": ["empty" , "green" ],
    "3": ["empty" , "blue"  ],
    "4": ["empty" , "yellow"],
    "5": ["empty" , "purple"],
    "6": ["empty" , "ojama" ],
    "7": ["empty" , "wall"  ],

    "8": ["red"   , "empty" ],
    "9": ["red"   , "red"   ],
    "a": ["red"   , "green" ],
    "b": ["red"   , "blue"  ],
    "c": ["red"   , "yellow"],
    "d": ["red"   , "purple"],
    "e": ["red"   , "ojama" ],
    "f": ["red"   , "wall"  ],

    "g": ["green" , "empty" ],
    "h": ["green" , "red"   ],
    "i": ["green" , "green" ],
    "j": ["green" , "blue"  ],
    "k": ["green" , "yellow"],
    "l": ["green" , "purple"],
    "m": ["green" , "ojama" ],
    "n": ["green" , "wall"  ],

    "o": ["blue"  , "empty" ],
    "p": ["blue"  , "red"   ],
    "q": ["blue"  , "green" ],
    "r": ["blue"  , "blue"  ],
    "s": ["blue"  , "yellow"],
    "t": ["blue"  , "purple"],
    "u": ["blue"  , "ojama" ],
    "v": ["blue"  , "wall"  ],

    "w": ["yellow", "empty" ],
    "x": ["yellow", "red"   ],
    "y": ["yellow", "green" ],
    "z": ["yellow", "blue"  ],
    "A": ["yellow", "yellow"],
    "B": ["yellow", "purple"],
    "C": ["yellow", "ojama" ],
    "D": ["yellow", "wall"  ],

    "E": ["purple", "empty" ],
    "F": ["purple", "red"   ],
    "G": ["purple", "green" ],
    "H": ["purple", "blue"  ],
    "I": ["purple", "yellow"],
    "J": ["purple", "purple"],
    "K": ["purple", "ojama" ],
    "L": ["purple", "wall"  ],

    "M": ["ojama" , "empty" ],
    "N": ["ojama" , "red"   ],
    "O": ["ojama" , "green" ],
    "P": ["ojama" , "blue"  ],
    "Q": ["ojama" , "yellow"],
    "R": ["ojama" , "purple"],
    "S": ["ojama" , "ojama" ],
    "T": ["ojama" , "wall"  ],

    "U": ["wall"  , "empty" ],
    "V": ["wall"  , "red"   ],
    "W": ["wall"  , "green" ],
    "X": ["wall"  , "blue"  ],
    "Y": ["wall"  , "yellow"],
    "Z": ["wall"  , "purple"],
    ".": ["wall"  , "ojama" ]
    }

next_mapper = {
    "0": ["red"   , "red"   ],
    "2": ["green" , "red"   ],
    "4": ["blue"  , "red"   ],
    "6": ["yellow", "red"   ],
    "8": ["purple", "red"   ],

    "c": ["red"   , "green" ],
    "e": ["green" , "green" ],
    "g": ["blue"  , "green" ],
    "i": ["yellow", "green" ],
    "k": ["purple", "green" ],

    "o": ["red"   , "blue"  ],
    "q": ["green" , "blue"  ],
    "s": ["blue"  , "blue"  ],
    "u": ["yellow", "blue"  ],
    "w": ["purple", "blue"  ],

    "A": ["red"   , "yellow"],
    "C": ["green" , "yellow"],
    "E": ["blue"  , "yellow"],
    "G": ["yellow", "yellow"],
    "I": ["purple", "yellow"],

    "M": ["red"   , "purple"],
    "O": ["green" , "purple"],
    "Q": ["blue"  , "purple"],
    "S": ["yellow", "purple"],
    "U": ["purple", "purple"],
}

conditions_1 = {
    "2": "clear_c",
    "3": "pops_n_colors",
    "b": "pops_n_or_more_colors",
    "c": "pops_n_of_c",
    "d": "erase_n_or_more_c",
    "u": "n_chains",
    "v": "n_chains_or_more",
    "w": "n_chains_and_clear_c",
    "x": "n_chains_or_more_and_clear_c",
    "E": "pops_n_colors_simul",
    "F": "pops_n_or_more_colors_simul",
    "G": "pops_n_of_c_puyo_simul",
    "H": "pops_n_or_more_c_puyo_simul",
    "l": "pops_n_places_of_c_puyo_simul",
    "J": "pops_n_places_or_more_c_puyo_simul",
    "Q": "pops_c_puyo_n_chains",
    "R": "pops_c_puyo_n_chains_or_more",
}

conditions_2 = {
    "1": "red",
    "2": "green",
    "3": "blue",
    "4": "yelloow",
    "5": "purple",
    "6": "ojama",
    "7": "any_color",
}

conditions_3 = {
    "1": 1,
    "2": 2,
    "3": 3,
    "4": 4,
    "5": 5,
    "6": 6,
    "7": 7,
    "8": 8,
    "9": 9,
    "a": 10,
    "b": 11,
}
print(sys.argv[1])
param = sys.argv[1].split("_")

''' create nazopuyo board
'''
counter = 78
puyolist = {}
for n in reversed(param[0]):
    puyos = mapper.get(n)
    if puyos[1] in puyolist:
        puyolist[puyos[1]].append(counter)
    else:
        puyolist[puyos[1]] = [counter]
    if puyos[0] in puyolist:
        puyolist[puyos[0]].append(counter - 1)
    else:
        puyolist[puyos[0]] = [counter - 1]
    counter = counter - 2
if "empty" in puyolist:
    puyolist.pop("empty")
board = []
for k, v in puyolist.items():
    board.append({ "color": k, "cells": v })

''' create next list
'''
counter = 1
nextlist = []
nextpuyo = param[1]
for n in nextpuyo:
    if counter % 2 == 1:
        puyos = next_mapper.get(n)
        nextlist.append({"order": counter, "colors": puyos})
    counter = counter + 1

param = sys.argv[1].split("__")
c_param = param[1]
conditions = {
    "condition" : conditions_1.get(c_param[0]),
    "c" : conditions_2.get(c_param[1]),
    "n" : conditions_3.get(c_param[2]),
}

result = {
    "conditions": conditions,
    "board": board,
    "next": nextlist,
}
print(result)
```

こんな感じで、なぞぷよの文字列を入れると、JSONを出力する。
`python3 t.py g00g00g00J0EHggloE_g1w1O1__u05`


## 自作ゲームとの連携
自分の作ったゲームでこのAPIを叩けば思い通りの盤面が作れる。
APIサーバも作らなきゃいけないけど、、、

![nazopuyo2.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/520924/3689a751-e4a2-7c14-c973-12e39e4912cb.gif)