Skip to content

README media

Every file the README embeds, and how to make it again.

Everything here is generated. The generator is RoyaleGym/docs/media/make_media.py, which lives in RoyaleGym because it writes into all four repos and the four are cloned side by side. From the folder that holds the repos, in Windows PowerShell:

.venv\Scripts\python RoyaleGym\docs\media\make_media.py --list
.venv\Scripts\python RoyaleGym\docs\media\make_media.py battle-page determinism

It needs the engine built, royalegym and royaleviser installed, and Pillow. The videos also need RoyaleViser's media extra, which supplies ffmpeg; without it the videos are skipped and the stills are still written. Re-running it gives the same bytes: the battle is played on a fixed seed with a named deck, and the viewer's capture freezes the two numbers on screen that move with the wall clock.

Each video is a .gif and an .mp4 of the same thing. The README points at the gif, because GitHub plays a gif inside an <img> tag and will not play an mp4 there. The mp4 is the better copy for anyone who opens the file directly.

File How it is made What it shows
battle-page.gif / .mp4 make_media.py battle-page The busiest stretch of an engine battle in RoyaleViser, found by sweeping the trace for the tick with the most units alive. One frame per engine tick.
cards-and-spells.gif / .mp4 make_media.py cards-and-spells A spell landing on a crowd late in the same battle, found the same way: the tick with a spell in the air and the most units on the board.
deploy-legality.png make_media.py deploy-legality The arena coloured by what check_deploy answers for one card, before and after an enemy princess tower falls.
determinism.png make_media.py determinism One seed run more than once, with the per-tick state hashes side by side.
throughput.png make_media.py throughput A real transcript of tools/throughput.py, and what the rate means in whole battles an hour.
snapshots.png make_media.py snapshots One saved position loaded into several engines and stepped on differently.
ledger.png make_media.py ledger The spread of statuses across data/calibration.json: every entry counted, in four bands from measured to guess.
engine-battle-viewer.png a RoyaleViser screenshot final, not regenerated here
family.svg hand-drawn the Royale repos and how they depend on each other; final

Still placeholders, and why

A placeholder is a generated SVG whose alt text begins "Image placeholder:" or "Video placeholder:" and says what the real picture must show. Replace the file, keep the name.

File What it must show Why it is not made here
measured-routes.svg one deploy, two routes on one board: the recorded route and the engine's, node for node, plus the 743 of 744 score Nobody has made it yet. It CAN be made: crates/royalesim/tests/fixtures/oracle2026/client16402_first_paths.json carries 747 cases, each with the recorded route (oracle_cells_goal_first) and the request the engine needs to plan the same one, so both routes come from the repo.
contact-law.svg a real battle and the engine side by side over 20 ticks, a crowd dropped onto a defender spreading apart Nobody has made it yet. crates/royalesim/tests/fixtures/replay/sample.json carries 1,178 ticks of per-tick positions for 16 entities, so the picture's INPUT is committed; whether that particular battle contains a scene that shows the law is not checked. It holds Prince, Dark Prince, Skeletons, Battle Ram, Giant and Musketeer.

Those two tiles carry the project's strongest claims, so they are worth making properly rather than approximating. Both are drawn from committed fixtures plus a running engine, which is the rule for every public picture here: it comes from the engine or from data already in the repo, and a script anyone with a clone can run.