5.1 KiB
Sigmar's Garden
This project implements the Sigmar's Garden mini-game from Zachronics' Opus Magnum in HTML5, JavaScript, and SVG.
Play on-line at https://bits.ondrovo.com/sigmar.
The game is fully client-side and static, you can simply download it and open locally as well.
Game rules
There are 55 marbles on the board, composed as follows:
- 8 pieces of the four Elements: Air, Water, Fire, and Earth (total of 32)
- 4 pieces of Salt
- 5 metals and 1 Gold
- 5 pieces of Mercury
- 4 pairs of Vitae and Mors
Your goal is to clear the board.
- Vitae reacts only with Mors
- Elements react with the same element kind, or with Salt
- Salt reacts with Elements or with itself
- Metals react with Mercury, but they unlock one by one, from the most common Lead to Gold.
- Gold is removed by itself as the last metal
The metals sequence is as follows:
- Lead + Mercury
- Tin + Mercury
- Iron + Mercury
- Copper + Mercury
- Silver + Mercury
- Gold
Here is a diagram from the original game (hosted on Steam Community)
User Interface Explanation
The user interface contains a few buttons and toggles:
- Randomize - start a new game with a random shape and marble placement
- Try Again - reset the current game to its initial arrangement
- Undo - reverts one game action (reaction of two marbles). There is no limit on how many steps you can undo.
The bottom left corner contains settings:
- Effects - enable graphic effects that look pretty but perform poorly on mobile phones or browsers without hardware acceleration.
- Dim Blocked - highlight marbles that can be played by dimming the others. This makes the game much harder, but is more realistic.
- Sloppy Gen - allow sloppy board filling. Use if building the board takes too long on your computer. May result in uglier and/or easier boards.
Settings
The game saves its persistent settings in your browser's localStorage.
Settings can be manipulated through the GUI, through some GET parameters, and via JavaScript API
in dev tools. The function of interest is called game.setCfg({key: value, ...})
.
Here's the settings object. Please refer to the source code, as this is internal API and may be extended
or changed without updating this reference. Search for SettingsStorage
.
{
log: 'info', // default log level
allowTemplateAugmenting: false, // sloppy mode
retryTemplate: 30, // retry attempts within one template
attemptTemplates: 50, // number of templates to try on failure
svgEffects: false, // fancy mode
dimBlocked: true, // highlight active marbles
}
GET Arguments
The game can be parametrised by GET arguments you add to the URL. This can be used for bookmarks or to share a particular board.
-
debug=1/0
- enable debug, or disable debug and trace logging levels -
trace=1/0
- toggle trace logging level -
log=level
- select logging level: trace, debug, info, warn, error -
seed=123
- set random seed, must be numeric. Share the current board by copying the URL -
rnd=1
- don't put the seed in URL, so you can randomize by pressing Refresh (F5) -
template=star
- set board template (shape in which the marbles are arranged). See the source code for a list of templates. The currently used template is also printed to the debug console for convenience. Can be combined with 'rnd' or 'seed'.Note that some templates are hard to fill, so the engine can give up and switch to a different random template.
Algorithm Quirks
Every board must be solvable, otherwise it wouldn't be much of a game. Generating a valid board turned out quite a bit more challenging than I thought. My algorithm is based in some heuristics and good deal of luck.
To make things more fun, besides the marble matching rules, the board must be laid out in one of several pre-defined shapes of exactly 55 tiles. The algorithm can sometimes get itself into a dead end while placing marbles on the board. I experimented with backtracking, but the current version simply retries the whole thing with a different random seed. There are configurable retry limits as a failsafe. If the given template fails many consecutive times, the algorithm opts to switch to a different template. Some templates are harder than others, and some random seeds just seem to have a problem.
A workaround I added is called Sloppy Mode. When the algorithm can't place an marble, it may choose to add a new tile to the template, trying to keep the overall shape as tidy as possible. This may hurt game difficulty, but is generally much faster than retrying over and over.
If you're curious about the inner workings, open dev tools and enable debug logging with the debug=1
GET parameter.