aboutsummaryrefslogtreecommitdiff
path: root/hat.c (follow)
Commit message (Collapse)AuthorAge
* Reference my just-published article about aperiodic tilings.Simon Tatham2023-04-10
| | | | | | | | | | | | | | | | | | | In commit 8d6647548f7d005 I added the Hats grid type to Loopy, and mentioned in the commit message that I was very pleased with the algorithm I came up with. In fact, I was so pleased with it that I've decided it deserves a proper public writeup. So I've spent the Easter weekend producing one: https://www.chiark.greenend.org.uk/~sgtatham/quasiblog/aperiodic-tilings/ In this commit I adjust the header comments in both penrose.c and hat.c to refer to the article (replacing a previous comment in penrose.c to a much less polished page containing a copy of my jotting-grade personal notes that I sent James Harvey once). Also, added some code to hatgen.c to output Python hat descriptions in a similar style to hat-test, which I used to generate a couple of the more difficult diagrams in the new article, and didn't want to lose.
* Fall back to <math.h> if <tgmath.h> doesn't work.Simon Tatham2023-04-06
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This fixes a build failure introduced by commit 2e48ce132e011e8 yesterday. When I saw that commit I expected the most likely problem would be in the NestedVM build, which is currently the thing with the most most out-of-date C implementation. And indeed the NestedVM toolchain doesn't have <tgmath.h> - but much more surprisingly, our _Windows_ builds failed too, with a compile error inside <tgmath.h> itself! I haven't looked closely into the problem yet. Our Windows builds are done with clang, which comes with its own <tgmath.h> superseding the standard Windows one. So you'd _hope_ that clang could make sense of its own header! But perhaps the problem is that this is an unusual compile mode and hasn't been tested. My fix is to simply add a cmake check for <tgmath.h> - which doesn't just check the file's existence, it actually tries compiling a file that #includes it, so it will detect 'file exists but is mysteriously broken' just as easily as 'not there at all'. So this makes the builds start working again, precisely on Ben's theory of opportunistically using <tgmath.h> where possible and falling back to <math.h> otherwise. It looks ugly, though! I'm half tempted to make a new header file whose job is to include a standard set of system headers, just so that that nasty #ifdef doesn't have to sit at the top of almost all the source files. But for the moment this at least gets the build working again.
* Replace <math.h> with <tgmath.h> throughoutBen Harris2023-04-04
| | | | | | | | | | | | | | | C89 provided only double-precision mathematical functions (sin() etc), and so despite using single-precision elsewhere, those are what Puzzles has traditionally used. C99 introduced single-precision equivalents (sinf() etc), and I hope it's been long enough that we can safely use them. Maybe they'll even be faster. Rather than directly use the single-precision functions, though, we use the magic macros from <tgmath.h> that automatically choose the precision of mathematical functions based on their arguments. This has the advantage that we only need to change which header we include, and thus that we can switch back again if some platform has trouble with the new header.
* Move hat-test into its own source file.Simon Tatham2023-04-02
| | | | | | | | | | | | | | | I noticed while hacking on hat-test recently that it's quite awkward to be compiling a test main() program that lives in a source file also built into the Puzzles support library, because every modification to main() also triggers a rebuild of the library, and thence of all the actual puzzles. So it's better if such a test main() has its own source file. In order to make hat-test work standalone, I've had to move a lot of hat.c's internal declarations out into a second header file. This also means making a bunch of internal functions global, which means they're also in the namespace of programs other than hat-test, which means in turn that they should have names with less implicit context.
* hat-test: option to generate four-coloured hat tilings.Simon Tatham2023-03-31
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This commit is purely frivolous even by Puzzles standards, in that it's totally unrelated to any actual puzzle. But I know at least one person has already used the 'hat-test' tool in this code base to generate a patch of hat tiling for decorative purposes, so it's useful in its own right. Also, now that I've worked out _how_ to do this, it's a shame not to keep the code. Of course, any tiling of the plane _can_ be four-coloured, just by the Four Colour Theorem. But for a tiling with structure it's nicer if the colouring is related to the structure in some way. And there's a reasonably nice explicit construction that does just that: the paper introducing the tiling observes that if each reflected hat is fused with a particular one of its neighbours, the resulting tiling is graph-theoretically equivalent to a tiling of the plane by hexagons. And _that_ tiling can be three-coloured, in a unique way up to colour choices. This induces a four-colouring of the hat tiling in which the reflected hats have a colour to themselves, and everything else is coloured the same as its corresponding hexagon in the three-colouring. Actually implementing this turns out not to be too difficult using my coordinate system. I hand-wrote tables giving a patch of colouring for each of the four kitemaps; then, whenever two kitemaps meet, you can determine how the colours map to each other by looking at the overlapping tiles. So I can have hat-test work out the colour of each tile as it goes. So hat-test now supports a '--fourcolour' option to apply this colouring to the output tiling.
* hat-test: allow choosing a random number seed.Simon Tatham2023-03-30
| | | | | | | The default one is always the same, because the main purpose of this tool is debugging. But one person has already wanted to use it for actually generating a tiling patch for another use, so let's make it easier to vary the randomness!
* Hats: choose the tiling's starting hat more uniformly.Simon Tatham2023-03-30
| | | | | | | This fills in the missing piece of commit 6f75879e9fe7cb5, which was trying to make the output patches of tiling as uniformly random as possible across the whole space of possible ones. I fixed every _intermediate_ step in the algorithm, but forgot the starting one!
* Hats: factor out the parent-choosing system.Simon Tatham2023-03-30
| | | | NFC, but I'm about to want to use it again elsewhere.
* hat-test: alternative data output mode to write Python.Simon Tatham2023-03-28
| | | | | | This mode emits a sequence of calls to an imaginary Python function. Should be useful to anyone wanting to post-process the tiling in any way.
* hat-test: allow specifying tiling size on the command line.Simon Tatham2023-03-28
| | | | | I'm tired of recompiling every time I want a different size of test patch.
* Hats tiling: make hat-test draw each hat in one go.Simon Tatham2023-03-28
| | | | | | | | | | | | | By introducing a second callback between the client of hat.c and the maybe_report_hat function, I enable the test main() to provide a different version of that callback, so that instead of enumerating each kite, it can directly generate a Postscript path per actual hat. This should make it more useful to people wanting to generate hat patterns for any other purpose. The internal callback gets more details than the external one; in particular, it receives a HatCoords, so that it can colour hats based on their position in the hierarchical structure.
* Hats tiling: more uniform parent selection.Simon Tatham2023-03-28
| | | | | | | | | | | | | This tweak improves the uniformity of the generated patches of hat tiling, by selecting from (the closest 32-bit approximation I can get to) the limiting probability distribution of finite patches in the whole plane. This shouldn't invalidate any grid description that contains enough coordinates to uniquely specify a piece of tiling - in particular, any generated by the game itself. But if anyone's been brave enough to hand-type a grid description in the last two days and left off some of the coordinates, then those might be invalidated.
* Fix references to the renamed 'auxiliary' directory.Simon Tatham2023-03-27
| | | | | | I renamed it in a hurry this morning after the first report of a git error message on Windows. Now I realise that several source files referred to the old name, and also need fixing.
* Loopy / grid.c: new grid type, 'Hats'.Simon Tatham2023-03-26
The big mathematical news this month is that a polygon has been discovered that will tile the plane but only aperiodically. Penrose tiles achieve this with two tile types; it's been an open question for decades whether you could do it with only one tile. Now someone has announced the discovery of such a thing, so _obviously_ this mathematically exciting tiling ought to be one of the Loopy grid options! The polygon, named a 'hat' by its discoverers, consists of the union of eight cells of the 'Kites' periodic tiling that Loopy already implements. So all the vertex coordinates of the whole tiling are vertices of the Kites grid, which makes handling the coordinates in an exact manner a lot easier than Penrose tilings. What's _harder_ than Penrose tilings is that, although this tiling can be generated by a vaguely similar system of recursive expansion, the expansion is geometrically distorting, which means you can't easily figure out which tiles can be discarded early to save CPU. Instead I've come up with a completely different system for generating a patch of tiling, by using a hierarchical coordinate system to track a location within many levels of the expansion process without ever simulating the process as a whole. I'm really quite pleased with that technique, and am tempted to try switching the Penrose generator over to it too - except that we'd have to keep the old generator around to stop old game ids being invalidated, and also, I think it would be slightly trickier without an underlying fixed grid and without overlaps in the tile expansion system. However, before coming up with that, I got most of the way through implementing the more obvious system of actually doing the expansions. The result worked, but was very slow (because I changed approach rather than try to implement tree-pruning under distortion). But the code was reusable for two other useful purposes: it generated the lookup tables needed for the production code, and it also generated a lot of useful diagrams. So I've committed it anyway as a supporting program, in a new 'aux' source subdirectory, and in aux/doc is a writeup of the coordinate system's concepts, with all those diagrams. (That's the kind of thing I'd normally put in a huge comment at the top of the file, but doing all those diagrams in ASCII art would be beyond miserable.) From a gameplay perspective: the hat polygon has 13 edges, but one of them has a vertex of the Kites tiling in the middle, and sometimes two other tile boundaries meet at that vertex. I've chosen to represent every hat as having degree 14 for Loopy purposes, because if you only included that extra vertex when it was needed, then people would be forever having to check whether this was a 13-hat or a 14-hat and it would be nightmarish to play. Even so, there's a lot of clicking involved to turn all those fiddly individual edges on or off. This grid is noticeably nicer to play in 'autofollow' mode, by setting LOOPY_AUTOFOLLOW in the environment to either 'fixed' or 'adaptive'. I'm tempted to make 'fixed' the default, except that I think it would confuse players of ordinary square Loopy!