Zillions is a player of board games according to rules specified in a ZRF rules file. Mostly games are for two players, human against computer, although single player games (puzzles) are possible too. The Zillions rules file is highly flxeible, convering games from simple tic-tac-toe (or noughts and crosses) through to chess, go and anywhere in between. Games must be of perfect information, so games with hidden cards like poker or bridge are not possible.
Zillions includes a powerful artificial intelligence, which provides a strong opponent across a wide range of games. AmzPlayer provides a modern player that can be published to just about any platform.
Zillions was released as a Windows program around 20 years ago. AmzPlayer is a re-release of the original Zillions with a modern player built on the Unity platform. It comes with the same standard library of 48 games and many variations.
This is an alpha release, with some changes and limitations.
there is no move animation or sound (to be done)
no developer features (authoring mode, etc)
music files are in OGG format (MIDI not supported)
image files are in either BMP or PNG
some upgrades to the ZRF format, which may introduce breaking changes (go-moku.zrf fails)
support for user-defined games and saved games is not yet implemented.
This is free software. You are free to download it, free to use it and free to create games with it, at no charge. In return, you are expected to provide feedback and report bugs either as issues on Github or by email to firstname.lastname@example.org.
Go to the Engine folder and run the AmzEngine.exe. It will start the player.
User created games
For now, you can load your own games by editing or replacing the select.zrf file.
This is the original Zillions program heavily modified to run as a server engine, with an all-new Unity player. The original MFC user interface has been removed and replaced by an API and it should play exactly the same as the v3.0 version from which it was derived. The essential features of the user interface have been re-created in Unity, but this has been a complex process, and there will be omissions and differences. This alpha release is intended to identify what still needs to be done. A later release will add core features and platforms.
Puzzlang is a pattern language for abstract single-player games and puzzles, with a Unity player. This version targets PC desktop and Web browser, but can be built to play on a phone just as easily. You can play it here or download it here.
The release includes the Puzzlang games engine, Unity player and a selection of games written by others. The Puzzlang engine compiles and executes games scripts. It is nearly feature complete with PuzzleScript, and has a few extensions. The Unity player is quite basic, compared to what Unity can achieve, but it can play games and it too has a few enhancements. The games are selected from the PuzzleScript demos plus a few extras, and show the range of what now works.
Puzzlang and its player can play most PuzzleScript games with 100% compatibility. The following enhancements are implemented so far.
Mouse input events Fire1, Fire2, Fire3 and Hover, applied to any object defined as ‘clickable‘.
Objects can have text sprites, either a single character or a string.
Setting pause_at_end_level makes the engine wait for an extra input at the end of each level. The player implements this.
Setting pause_on_again makes the engine wait for an extra input when processing an again loop. The player implements this.
Object sprites can be any pixel size, not just 5×5. The minimum is 2×2. Support for named images is planned.
Commands for undo and reset (start over, discarding any checkpoint).
There is an input for reset, not bound to any key but used in testing.
The player allows Pause, Reset, Quit, Restart from a chosen level and Select a game from multiple pages including gists.
Additional input event Reaction, similar to Action but not bound to a key.
Commands level, status, text, call (see sample programs).
So feel free to try it online, download it, play it, give it away. Let me know about any problems you find.
So after much experimentation I found a way to make it work. In Inkscape it looks like this.
Each of the hexagons is exactly 256 pixels high, and spaced 224 pixels apart. That means they can be imported into Unity and sliced accordingly.
Each arc is drawn as a Bezier curve with a stroke width of 24 pixels, which is about 1/5th of the hexagon side. One end is positioned against a vertical edge using the pixel grid for alignment. The hexagon and arc are rotated multiples of 60 degrees so that each end can be successively positioned in the same way. The yellow dots and vertical guides help with positioning.
Then each curve is converted to a path, with a white fill colour and no stroke. The shapes are tweaked and the final alignment corrected by editing the nodes. The circle and other shapes are created directly using circles and polygons.
Finally, all the guide components are in one layer and the arcs and other drawings in another, as only the drawings are to be exported into the PNG, not the templates. The page size is an exact multiple: 1330×768 pixels.
The first major algorithm problem is how to generate loops. Here is what I came up with.
The algorithm in summary is as follows.
Choose a starting point, giving preference to hexes with fewer free edges. Initially this will pick the rim corners.
Make an outward leg, again selecting hexes with fewer free edges. This will tend to hug the rim.
At each step use A* search to make sure there is a way back home.
After reaching the desired path length, use the A* search to head for home and close the loop.
The final result looks like this.
At this point I found a major bug. Occasionally it looks like this.
Why? It turns out that this implementation of the A* algorithm has no protection against paths that cross themselves.
Think about the Fedex algorithm: assuming trucks that drive on the right, Fedex found that it is cheaper to make three right turns rather than one left. If you set up a movement cost based on that rule it will generate paths that cross and break this implementation of the algorithm. Back to the drawing board!
I want to explore two things about this fascinating game: how it generates loops and how the game might be made even better. To do that, first I need a basic clone of the game.
The platform I know best is Unity, with code in C#. Earlier games such as Polygamo and Puzzlang provide a solid foundation, but they are based on a rectangular grid. Hexagonal grids are obviously quite different. You can fake a hex grid by pretending it’s rectangular and offsetting every alternate row, but the code gets messy fast. I know, I tried!
Unity provides an excellent platform for writing simple puzzle games. It’s really easy to attach bits of code to game objects and the code is simple and straightforward. Even better, the compiler code has been updated to the latest version so all the cute features of C# 4.x now work.
Hex Grid Library
The definitive reference for using hex grids in games is this article on Red Blob Games. It provides code in C#, which can be used as a starting point. First I tried each of the hex grid libraries referenced in the article, but I found that variously that they were:
very basic, lacking key features and particularly any kind of search algorithm
tightly coupled to Unity in ways that ruled out my kind of model-view
broken, just did not work at all.
So I decided it was time to just take the Red Blob code and get it working. I added a number of utility routines and two major pieces of functionality.
Path searching based on red-blob again. This includes A* search, which requires a Priority Queue: there is a nice one open-sourced by Microsoft.
Generic grid generation: hexagon, rectangle, parallelogram, triangle, etc. instead of the hard-coded loops provided by Red Blob.
It seems simple enough, but writing any kind of game requires attention to lots of detail. I decided to go with a 2D game using UI components like panels and sprites. So I need:
Assets: sprites for the grid, loops and buttons
Palette: to make nice colours
Font: the game is minimalist, but it still has some text
Animations: stuff needs to move!
Sound and Music can come later.
After wrestling too long with the Unity Animation system, I gave up and decided to go with a Tween library. I chose LeanTween, but there are others. And this is what it looks like, running in the Unity editor.
Creating the loops, now that’s the subject of another post!
LOOP is an elegant puzzle game based on paths through a hex grid. You start with a scrambled grid, swap pairs of hexes and when you finish all the loops link up in perfect harmony (see image).
No tutorial, but 100 individual puzzles introduce the key mechanic and the two special devices. Clicking on a hex highlights its border; clicking on another then gracefully swaps them over. One device is a simple arc inside a circle, which is fixed in location but changes colour when clicked. The other has three arcs inside a circle of arrows and is also fixed in location but rotates when clicked.
The maximum size of grid is a hexagon with four hexes to a side, sometimes a bit moth-eaten (see picture). The earlier puzzles often have a smaller grid, and some have holes in them. There are puzzles wth paths of just one colour, while others may use six or more. Sometimes the paths are tightly packed, using all sides of the hexes, sometimes they are quite sparse.
Finally there is a puzzle generator. The puzzles are less varied than the individual levels, but the supply appears unlimited. It’s a lovely puzzle with hours of enjoyment, and I highly recommend it to any puzzle aficionado. You can get it on Steam or direct from http://loopthegame.com/.
But of course the question I want to address here is: how does that generator work? And could it be even better? We might have to build a clone to do that.
Update release 18d17 of Puzzlang is now available on Github. This release fixes a few bugs and implements support for cursor games and text objects. The release is here. See the release notes for more information. Screenshot here: