<feed xmlns='http://www.w3.org/2005/Atom'>
<title>puzzles/loopy.c, branch master</title>
<subtitle>My sgt-puzzles tree</subtitle>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/'/>
<entry>
<title>Refactor `button &amp; ~MOD_MASK' as `STRIP_BUTTON_MODIFIERS(button)'.</title>
<updated>2024-07-31T22:29:00+00:00</updated>
<author>
<name>Franklin Wei</name>
<email>franklin@rockbox.org</email>
</author>
<published>2024-07-21T22:06:37+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=5de69c22b0ff037f648a740a7c01869e78587df2'/>
<id>5de69c22b0ff037f648a740a7c01869e78587df2</id>
<content type='text'>
This refactors all instances of bitwise-ANDs with `~MOD_MASK'. There is
a handful of more complex instances I left unchanged (in cube.c, midend.c,
and twiddle.c), since those AND with `~MOD_MASK | MOD_NUM_KEYPAD' or
similar. I don't think it's worth writing a macro for those cases.

Also document this new macro's usage in devel.but.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This refactors all instances of bitwise-ANDs with `~MOD_MASK'. There is
a handful of more complex instances I left unchanged (in cube.c, midend.c,
and twiddle.c), since those AND with `~MOD_MASK | MOD_NUM_KEYPAD' or
similar. I don't think it's worth writing a macro for those cases.

Also document this new macro's usage in devel.but.
</pre>
</div>
</content>
</entry>
<entry>
<title>grid.c: allocate face/edge/dot arrays incrementally.</title>
<updated>2023-07-07T17:17:02+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-07-06T11:50:49+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=e6cdd70df867f064b0358dc3dba56d2667ab80a5'/>
<id>e6cdd70df867f064b0358dc3dba56d2667ab80a5</id>
<content type='text'>
Previously, the 'faces', 'edges' and 'dots' arrays in a grid structure
were arrays of actual grid_face, grid_edge and grid_dot structures,
physically containing all the data about the grid. But they also
referred to each other by pointers, which meant that they were hard to
realloc larger (you'd have to go through and rewrite all the pointers
whenever the base of an array moved). And _that_ meant that every grid
type had to figure out a reasonably good upper bound on the number of
all those things it was going to need, so that it could allocate those
arrays the right size to begin with, and not have to grow them
painfully later.

For some grid types - particularly the new aperiodic ones - that was
actually a painful part of the job. So I think enough is enough:
counting up how much memory you're going to need before using it is a
mug's game, and we should instead realloc on the fly.

So now g-&gt;faces, g-&gt;edges and g-&gt;dots have an extra level of
indirection. Instead of being arrays of actual structs, they're arrays
of pointers, and each struct in them is individually allocated. Once a
grid_face has been allocated, it never moves again, even if the array
of pointers changes size.

The old code had a common idiom of recovering the array index of a
particular element by subtracting it from the array base, e.g. writing
'f - g-&gt;faces' or 'e - g-&gt;edges'. To make that lookup remain possible,
I've added an 'index' field to each sub-structure, which is
initialised at the point where we decide what array index it will live
at.

This should involve no functional change, but the code that previously
had to figure out max_faces and max_dots up front for each grid type
is now completely gone, and nobody has to solve those problems in
advance any more.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Previously, the 'faces', 'edges' and 'dots' arrays in a grid structure
were arrays of actual grid_face, grid_edge and grid_dot structures,
physically containing all the data about the grid. But they also
referred to each other by pointers, which meant that they were hard to
realloc larger (you'd have to go through and rewrite all the pointers
whenever the base of an array moved). And _that_ meant that every grid
type had to figure out a reasonably good upper bound on the number of
all those things it was going to need, so that it could allocate those
arrays the right size to begin with, and not have to grow them
painfully later.

For some grid types - particularly the new aperiodic ones - that was
actually a painful part of the job. So I think enough is enough:
counting up how much memory you're going to need before using it is a
mug's game, and we should instead realloc on the fly.

So now g-&gt;faces, g-&gt;edges and g-&gt;dots have an extra level of
indirection. Instead of being arrays of actual structs, they're arrays
of pointers, and each struct in them is individually allocated. Once a
grid_face has been allocated, it never moves again, even if the array
of pointers changes size.

The old code had a common idiom of recovering the array index of a
particular element by subtracting it from the array base, e.g. writing
'f - g-&gt;faces' or 'e - g-&gt;edges'. To make that lookup remain possible,
I've added an 'index' field to each sub-structure, which is
initialised at the point where we decide what array index it will live
at.

This should involve no functional change, but the code that previously
had to figure out max_faces and max_dots up front for each grid type
is now completely gone, and nobody has to solve those problems in
advance any more.
</pre>
</div>
</content>
</entry>
<entry>
<title>Loopy / grid.c: support the new Spectre monotiling.</title>
<updated>2023-06-16T18:15:47+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-06-16T17:30:53+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=a33d9fad02d6319cb9061119a6165ed5493a3ba5'/>
<id>a33d9fad02d6319cb9061119a6165ed5493a3ba5</id>
<content type='text'>
This uses a tile shape very similar to the hat, but the tiling
_structure_ is totally changed so that there aren't any reflected
copies of the tile.

I'm not sure how much difference this makes to gameplay: the two
tilings are very similar for Loopy purposes. But the code was fun to
write, and I think the Spectre shape is noticeably prettier, so I'm
adding this to the collection anyway.

The test programs also generate a pile of SVG images used in the
companion article on my website.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This uses a tile shape very similar to the hat, but the tiling
_structure_ is totally changed so that there aren't any reflected
copies of the tile.

I'm not sure how much difference this makes to gameplay: the two
tilings are very similar for Loopy purposes. But the code was fun to
write, and I think the Spectre shape is noticeably prettier, so I'm
adding this to the collection anyway.

The test programs also generate a pile of SVG images used in the
companion article on my website.
</pre>
</div>
</content>
</entry>
<entry>
<title>Loopy: fix redraw issue due to enlarged dots.</title>
<updated>2023-05-07T20:41:50+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-05-07T20:41:50+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=8237b02be4e6f92a9e1aebbed23d7b5de0e3543c'/>
<id>8237b02be4e6f92a9e1aebbed23d7b5de0e3543c</id>
<content type='text'>
dot_bbox() wasn't taking into account the new size of the dots, so
sometimes a rectangle of the grid would be redrawn without a partial
dot it should have contained, because nothing had noticed that that
dot overlapped that rectangle.

Actually I'm not sure why this bug wasn't happening _before_ I
enlarged the dots, because the previous code seemed to think dots had
a fixed size in pixels regardless of tile size, which wasn't even
true _before_ my recent commit 4de9836bc8c36cd. Perhaps it did occur,
just never while I was watching.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
dot_bbox() wasn't taking into account the new size of the dots, so
sometimes a rectangle of the grid would be redrawn without a partial
dot it should have contained, because nothing had noticed that that
dot overlapped that rectangle.

Actually I'm not sure why this bug wasn't happening _before_ I
enlarged the dots, because the previous code seemed to think dots had
a fixed size in pixels regardless of tile size, which wasn't even
true _before_ my recent commit 4de9836bc8c36cd. Perhaps it did occur,
just never while I was watching.
</pre>
</div>
</content>
</entry>
<entry>
<title>Loopy: slightly increase the size of dots.</title>
<updated>2023-04-29T13:10:40+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-04-29T13:10:40+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=4de9836bc8c36cddead5e9efc6beff0692118b1e'/>
<id>4de9836bc8c36cddead5e9efc6beff0692118b1e</id>
<content type='text'>
In the Hats tiling, each tile has two consecutive edges collinear.
When both edges are turned on, i.e. drawn in black just like the dot,
it becomes _just slightly_ tricky to spot the dot in the middle of
that straight line, which is important if you're counting edges around
the face to check a clue.

Increasing the radius from 2/32 to 3/32 of tile size is far too big.
2.5/32 seems reasonable, though.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
In the Hats tiling, each tile has two consecutive edges collinear.
When both edges are turned on, i.e. drawn in black just like the dot,
it becomes _just slightly_ tricky to spot the dot in the middle of
that straight line, which is important if you're counting edges around
the face to check a clue.

Increasing the radius from 2/32 to 3/32 of tile size is far too big.
2.5/32 seems reasonable, though.
</pre>
</div>
</content>
</entry>
<entry>
<title>New backend functions: get_prefs and set_prefs.</title>
<updated>2023-04-23T12:25:06+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-04-21T14:50:05+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=0058331aeb027f7441a04d99cc7c1e445bd896d9'/>
<id>0058331aeb027f7441a04d99cc7c1e445bd896d9</id>
<content type='text'>
These are similar to the existing pair configure() and custom_params()
in that get_prefs() returns an array of config_item describing a set
of dialog-box controls to present to the user, and set_prefs()
receives the same array with answers filled in and implements the
answers. But where configure() and custom_params() operate on a
game_params structure, the new pair operate on a game_ui, and are
intended to permit GUI configuration of all the settings I just moved
into that structure.

However, nothing actually _calls_ these routines yet. All I've done in
this commit is to add them to 'struct game' and implement them for the
functions that need them.

Also, config_item has new fields, permitting each config option to
define a machine-readable identifying keyword as well as the
user-facing description. For options of type C_CHOICES, each choice
also has a keyword. These keyword fields are only defined at all by
the new get_prefs() function - they're left uninitialised in existing
uses of the dialog system. The idea is to use them when writing out
the user's preferences into a configuration file on disk, although I
haven't actually done any of that work in this commit.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
These are similar to the existing pair configure() and custom_params()
in that get_prefs() returns an array of config_item describing a set
of dialog-box controls to present to the user, and set_prefs()
receives the same array with answers filled in and implements the
answers. But where configure() and custom_params() operate on a
game_params structure, the new pair operate on a game_ui, and are
intended to permit GUI configuration of all the settings I just moved
into that structure.

However, nothing actually _calls_ these routines yet. All I've done in
this commit is to add them to 'struct game' and implement them for the
functions that need them.

Also, config_item has new fields, permitting each config option to
define a machine-readable identifying keyword as well as the
user-facing description. For options of type C_CHOICES, each choice
also has a keyword. These keyword fields are only defined at all by
the new get_prefs() function - they're left uninitialised in existing
uses of the dialog system. The idea is to use them when writing out
the user's preferences into a configuration file on disk, although I
haven't actually done any of that work in this commit.
</pre>
</div>
</content>
</entry>
<entry>
<title>Move per-puzzle ad-hoc getenv preferences into game_ui.</title>
<updated>2023-04-23T12:25:06+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-04-21T14:41:18+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=0d1a1f08bac25a4641c38a8e42dfa6e2bb9981d7'/>
<id>0d1a1f08bac25a4641c38a8e42dfa6e2bb9981d7</id>
<content type='text'>
Environment variables that set specific settings of particular
puzzles, such as SLANT_SWAP_BUTTONS, LIGHTUP_LIT_BLOBS and
LOOPY_AUTOFOLLOW, now all affect the game behaviour via fields in
game_ui instead of being looked up by getenv in the individual
functions that need to know them.

The purpose of this refactoring is to put those config fields in a
place where other more user-friendly configuration systems will also
be able to access them, once I introduce one. However, for the moment,
there's no functional change: I haven't _yet_ changed how the user
sets those options. They're still set by environment variables alone.
All I'm changing here is where the settings are stored inside the
code, and exactly when they're read out of the environment to put into
the game_ui.

Specifically, the getenvs now happen during new_ui(). Or rather, in
all the puzzles I've changed here, they happen in a subroutine
legacy_prefs_override() called from within new_ui(), after it's set up
the default values for the settings, and then gives the environment a
chance to override them. Or rather, legacy_prefs_override() only
actually calls getenv the first time, and after that, it's cached the
answers it got.

In order to make the override functions less wordy, I've altered the
prototype of getenv_bool so that it returns an int rather than a bool,
and takes its default return value in the same form. That way you can
set the default to something other than 0 or 1, and find out whether a
value was present at all.

This commit only touches environment configuration specific to an
individual puzzle. The midend also has some standard environment-based
config options that apply to all puzzles, such as colour scheme and
default presets and preset-menu extension. I haven't handled those
yet.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
Environment variables that set specific settings of particular
puzzles, such as SLANT_SWAP_BUTTONS, LIGHTUP_LIT_BLOBS and
LOOPY_AUTOFOLLOW, now all affect the game behaviour via fields in
game_ui instead of being looked up by getenv in the individual
functions that need to know them.

The purpose of this refactoring is to put those config fields in a
place where other more user-friendly configuration systems will also
be able to access them, once I introduce one. However, for the moment,
there's no functional change: I haven't _yet_ changed how the user
sets those options. They're still set by environment variables alone.
All I'm changing here is where the settings are stored inside the
code, and exactly when they're read out of the environment to put into
the game_ui.

Specifically, the getenvs now happen during new_ui(). Or rather, in
all the puzzles I've changed here, they happen in a subroutine
legacy_prefs_override() called from within new_ui(), after it's set up
the default values for the settings, and then gives the environment a
chance to override them. Or rather, legacy_prefs_override() only
actually calls getenv the first time, and after that, it's cached the
answers it got.

In order to make the override functions less wordy, I've altered the
prototype of getenv_bool so that it returns an int rather than a bool,
and takes its default return value in the same form. That way you can
set the default to something other than 0 or 1, and find out whether a
value was present at all.

This commit only touches environment configuration specific to an
individual puzzle. The midend also has some standard environment-based
config options that apply to all puzzles, such as colour scheme and
default presets and preset-menu extension. I haven't handled those
yet.
</pre>
</div>
</content>
</entry>
<entry>
<title>Pass a game_ui to compute_size, print_size and print.</title>
<updated>2023-04-21T15:18:04+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-04-21T14:30:41+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=a4fca3286f3aa630a3641e50a8e1f44ab1504a29'/>
<id>a4fca3286f3aa630a3641e50a8e1f44ab1504a29</id>
<content type='text'>
I'm about to move some of the bodgy getenv-based options so that they
become fields in game_ui. So these functions, which could previously
access those options directly via getenv, will now need to be given a
game_ui where they can look them up.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
I'm about to move some of the bodgy getenv-based options so that they
become fields in game_ui. So these functions, which could previously
access those options directly via getenv, will now need to be given a
game_ui where they can look them up.
</pre>
</div>
</content>
</entry>
<entry>
<title>Loopy: draw even faint lines using draw_thick_line.</title>
<updated>2023-04-20T18:41:46+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-04-20T18:41:46+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=ce203c12efe0e10445a3be56c4308db42d9086c8'/>
<id>ce203c12efe0e10445a3be56c4308db42d9086c8</id>
<content type='text'>
When playing on a high-DPI screen and running Loopy at a large tile
size to compensate, the faint lines along grid edges in LINE_NO state
are exceptionally hard to see, because they're still only one pixel
wide even when everything else has been expanded.

This has been true for ages, but it's more significant now, because
the new Hats tiling mode needs a lot of counting of edges in all
states (since the hats have 14 edges in total!), and it's awkward not
to be able to see exactly where the LINE_NO edges are, or where an
edge between two other tiles meets this hat's outline.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
When playing on a high-DPI screen and running Loopy at a large tile
size to compensate, the faint lines along grid edges in LINE_NO state
are exceptionally hard to see, because they're still only one pixel
wide even when everything else has been expanded.

This has been true for ages, but it's more significant now, because
the new Hats tiling mode needs a lot of counting of edges in all
states (since the hats have 14 edges in total!), and it's awkward not
to be able to see exactly where the LINE_NO edges are, or where an
edge between two other tiles meets this hat's outline.
</pre>
</div>
</content>
</entry>
<entry>
<title>Reorganise the dsf API into three kinds of dsf.</title>
<updated>2023-04-20T17:39:41+00:00</updated>
<author>
<name>Simon Tatham</name>
<email>anakin@pobox.com</email>
</author>
<published>2023-04-20T16:27:21+00:00</published>
<link rel='alternate' type='text/html' href='https://www.franklinwei.com/cgit/puzzles/commit/?id=c5e253a9f9d3d651227ccad56e2c7526ee1f3eba'/>
<id>c5e253a9f9d3d651227ccad56e2c7526ee1f3eba</id>
<content type='text'>
This is preparing to separate out the auxiliary functionality, and
perhaps leave space for making more of it in future.

The previous name 'edsf' was too vague: the 'e' stood for 'extended',
and didn't say anything about _how_ it was extended. It's now called a
'flip dsf', since it tracks whether elements in the same class are
flipped relative to each other. More importantly, clients that are
going to use the flip tracking must say so when they allocate the dsf.

And Keen's need to track the minimal element of an equivalence class
is going to become a non-default feature, so there needs to be a new
kind of dsf that specially tracks those, and Keen will have to call it.

While I'm here, I've renamed the three dsf creation functions so that
they start with 'dsf_' like all the rest of the dsf API.
</content>
<content type='xhtml'>
<div xmlns='http://www.w3.org/1999/xhtml'>
<pre>
This is preparing to separate out the auxiliary functionality, and
perhaps leave space for making more of it in future.

The previous name 'edsf' was too vague: the 'e' stood for 'extended',
and didn't say anything about _how_ it was extended. It's now called a
'flip dsf', since it tracks whether elements in the same class are
flipped relative to each other. More importantly, clients that are
going to use the flip tracking must say so when they allocate the dsf.

And Keen's need to track the minimal element of an equivalence class
is going to become a non-default feature, so there needs to be a new
kind of dsf that specially tracks those, and Keen will have to call it.

While I'm here, I've renamed the three dsf creation functions so that
they start with 'dsf_' like all the rest of the dsf API.
</pre>
</div>
</content>
</entry>
</feed>
