puyogg / puyogg

1 stars 0 forks source link

Support for Fumen-like chainsim replay #17

Open dec32nd opened 7 months ago

dec32nd commented 7 months ago

Holding issue to define the serialization format to allow a chain simulator to replay a Puyo chain build.

The format is defined through a series of layer features. Many chain simulators already implement one or more of these features; layering them allows chain simulators to implement only the features they support without needing to support the full specification. Furthermore, rich applications can fall back to lower layers in contexts with less support (example: a full featured playable chain simulator can fall back to a static image of the initial board state on a website that doesn't support rich embeds).

Layer 0: Puyo board

Defines the puyos currently placed on the puyo board. Should support the standard 6x12+1 puyo board at minimum, but should allow arbitrary board shapes to be specified.

Example: Puyo Nexus Chain Simulator 706000666470745470774547445547 Example: puyo.tw Chain Simulator 00HtnDw2Tjc9IsHFZ7iHQYPnBDq~Sa

Layer 1: Upcoming piece queue

A list of upcoming puyos to be displayed in the next piece queue.

Layer 2: Board evolution through play actions

Represents changes to the Layer 0 Puyo board as a result of play decisions. At minimum, this can just be represented as multiply defined "keyframe" Puyo boards in a list; alternatively, each "frame" can be defined as additional puyos placed since the last keyframe. The most advanced variation could also use gamepad inputs to represent interstitial piece movements and rotations before the piece is placed.

Example: Puyop Chain Simulator _980C9g4c9o5geE2Q1GoC4ybQ7w28cgm8ag90o0

Layer 3: Annotations

Adds annotations such as text, highlights, and ghost puyo on the board.

Example: puyo.gg Simulator supports several additional annotations on top of the default puyos.

dec32nd commented 7 months ago

Here is a really hacky example of what I'd like to be able to embed using available tools: https://jsfiddle.net/4L6ctowj/ Source video: https://youtu.be/BpiLPr36Euw?t=593

The two main issues are how verbose I need to be - setting up all 20 piece placements (40 total frames with the backwards equivalents) took me about two hours to generate, and I'm sure I still have miscopied pieces in there - as well as how all generated frames use PN chainsim shortlinks, meaning anybody who wanted to play out the replay themselves can't do so on a different site.

In fact I think the lowest tech equivalent would be to punch into a discord bot and using the rich embed + reactions to parse through the chain -- see attached for a Puzzle & Dragons monster book bot that is along the lines of what I am thinking of. image

dec32nd commented 7 months ago

Here's an attempt at trying to serialize the above example into a data format, and some JS code to parse it into a replay. https://jsfiddle.net/3hwpvtdg/1/

The data format is JSON based on how the Puyo Nexus chainsim stores chains.

var replay = {
  "0": ["646000548000558086885856548885858556655", null, null, null, null, "8000008008004008086885856548885858556655",null,null,null,null,null,null,null,null,"8000005880008558008858004448086885856548885858556655",null,"6000008000008004448086885856548885858556655","6000008000008000008400005",null],
  "1": ["640", "60000050", "8000004000", "6000008000", "8000004","60000040","800000400","560","64","54","54","8000005000","80000040","800000600","580","8000006","400000800000","60000040","600000600"],
  "2": ["64","56","84","68","48","64","84","65","64","64","45","54","58","48","86","85","86","48","46","66","68","65"]
};

Similar to what I described above, layer 0 is a series of chainsim inputs describing keyframed board states, where null indicates that the piece placements in layer 1 should be used to determine the next board state.

Layer 1 is just a small chainsim board indicating what to drop on the board next frame. Useful if you want to include garbage being dumped on the opponent and is future compatible with like big Fever pieces for example, but for simpler cases like next piece placement it can be extremely inefficient.

For example 400000800000 uses 12 characters to describe "drop straight down in column 1", not to mention the redundancy with the piece queue in layer 2. Not sure what the best implementation here is?

Then there's the matter of encoding the JSON blob; using something like Base64URL results in

eyIwIjpbIjY0NjAwMDU0ODAwMDU1ODA4Njg4NTg1NjU0ODg4NTg1ODU1NjY1NSIsbnVsbCxudWxsLG51bGwsbnVsbCwiODAwMDAwODAwODAwNDAwODA4Njg4NTg1NjU0ODg4NTg1ODU1NjY1NSIsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLG51bGwsbnVsbCxudWxsLCI4MDAwMDA1ODgwMDA4NTU4MDA4ODU4MDA0NDQ4MDg2ODg1ODU2NTQ4ODg1ODU4NTU2NjU1IixudWxsLCI2MDAwMDA4MDAwMDA4MDA0NDQ4MDg2ODg1ODU2NTQ4ODg1ODU4NTU2NjU1IiwiNjAwMDAwODAwMDAwODAwMDAwODQwMDAwNSIsbnVsbF0sIjEiOlsiNjQwIiwiNjAwMDAwNTAiLCI4MDAwMDA0MDAwIiwiNjAwMDAwODAwMCIsIjgwMDAwMDQiLCI2MDAwMDA0MCIsIjgwMDAwMDQwMCIsIjU2MCIsIjY0IiwiNTQiLCI1NCIsIjgwMDAwMDUwMDAiLCI4MDAwMDA0MCIsIjgwMDAwMDYwMCIsIjU4MCIsIjgwMDAwMDYiLCI0MDAwMDA4MDAwMDAiLCI2MDAwMDA0MCIsIjYwMDAwMDYwMCJdLCIyIjpbIjY0IiwiNTYiLCI4NCIsIjY4IiwiNDgiLCI2NCIsIjg0IiwiNjUiLCI2NCIsIjY0IiwiNDUiLCI1NCIsIjU4IiwiNDgiLCI4NiIsIjg1IiwiODYiLCI0OCIsIjQ2IiwiNjYiLCI2OCIsIjY1Il19

which is heinously large. There's opportunities for compression since the possible character set is so limited. Not sure if there's encoding/compression schemes in use already?