chiark / gitweb /
Simon Tatham [Mon, 24 Apr 2017 15:00:24 +0000 (16:00 +0100)]
Rework the preset menu system to permit submenus.
To do this, I've completely replaced the API between mid-end and front
end, so any downstream front end maintainers will have to do some
rewriting of their own (sorry). I've done the necessary work in all
five of the front ends I keep in-tree here - Windows, GTK, OS X,
Javascript/Emscripten, and Java/NestedVM - and I've done it in various
different styles (as each front end found most convenient), so that
should provide a variety of sample code to show downstreams how, if
they should need it.
I've left in the old puzzle back-end API function to return a flat
list of presets, so for the moment, all the puzzle backends are
unchanged apart from an extra null pointer appearing in their
top-level game structure. In a future commit I'll actually use the new
feature in a puzzle; perhaps in the further future it might make sense
to migrate all the puzzles to the new API and stop providing back ends
with two alternative ways of doing things, but this seemed like enough
upheaval for one day.
Simon Tatham [Wed, 26 Apr 2017 13:39:45 +0000 (14:39 +0100)]
Javascript puzzles: switch to a CSS-based drop-down system.
The previous control buttons and dropdowns based on form elements were
always a bit ugly: partly in a purely visual sense, and partly because
of the nasty bodge I had to do with splitting the usual 'Custom' game
type menu item into two (to get round the fact that if an element of a
<select> is already selected, browsers won't send an event when it's
re-selected). Also, I'm about to want to introduce hierarchical
submenus in the Type menu, and <select> doesn't support that at all.
So here's a replacement system which does everything by CSS
properties, including the popping-up of menus when the mouse moves
over their parent menu item. (Thanks to the Internet in general for
showing me how that trick is done.)
Simon Tatham [Mon, 24 Apr 2017 16:09:30 +0000 (17:09 +0100)]
Use symbolic enum values in the Loopy presets array.
The use of plain numbers was needlessly confusing, and in particular
made it too easy to make unintended changes to the existing Loopy
presets when inserting a new grid enum value anywhere other than at
the end of the list.
But in the course of doing this I realised that, against all
sensibleness, the numeric indices for grid types in grid.h and in
Loopy itself don't match up! Right now I don't want to get sidetracked
into fixing the structural confusion that made that happen in the
first place, but I've at least materialised Loopy's version of the
enum with clearly identifiable LOOPY_GRID_* names.
Simon Tatham [Sun, 23 Apr 2017 06:41:46 +0000 (07:41 +0100)]
New Loopy tiling: 'Great Great Dodecagonal'.
Officially known as the '3-4-6-12 tiling', according to, e.g.,
https://en.wikipedia.org/wiki/3-4-6-12_tiling .
Thanks to Michael Quevillon for contributing this patch (and for
choosing a less hard-to-remember name for the tiling :-).
Simon Tatham [Mon, 13 Mar 2017 19:58:22 +0000 (19:58 +0000)]
Net: rework status line to cope with empty squares.
Another oddity involving an empty square is that if it coincides with
the source square for highlights (either by original design of the
game id, or because the player Ctrl-moves the source square into an
empty grid cell during play), then everything stops being lit up as
active. That's fine - you can still play the game using other
indications of error, such as the loop detection highlight - but it
looks silly for the status line to say 'Active: 1/lots'. So in that
situation I suppress the 'active' counter completely; it comes back
when you move the source square to somewhere it's _possible_ to
highlight more than one square.
While I'm at it, I've also removed the active counter in the case
where the game is completely solved, because in that situation it's
more or less unnecessary anyway, and that way the normal course of
play on the default small grid size doesn't overflow the available
status line space.
Simon Tatham [Sun, 12 Mar 2017 09:11:43 +0000 (09:11 +0000)]
Net: fix completion check if top left square is empty.
A hand-typed grid is permitted to use the square type '0' (never
generated by Net's own grid generator), which is a completely empty
square. This requires an adjustment to the completion checker, so that
such squares aren't required to be connected; otherwise, a grid
containing one would be permanently uncompletable.
However, the completion checker missed one case - it was
unconditionally checking that all squares are connected to the _top
left corner_, on the basis that (before I thought of the zero square)
any source square is as good as any other if what you really want to
know is whether they're all connected to each other. But that means
that if the top left square _is_ the empty one, things to wrong - e.g.
5x5:
02c328ade11adb129d7c3e524 would fail to give a completion flash.
Fixed by starting the completion-checking search from the first
non-empty square we find.
Simon Tatham [Mon, 27 Feb 2017 19:26:06 +0000 (19:26 +0000)]
GTK API deprecation: in GTK 3.22, stop using gdk_cairo_create.
This is another annoyingly removed function, replaced by a tower of
about four assorted objects you have to create in succession.
Simon Tatham [Mon, 27 Feb 2017 19:11:02 +0000 (19:11 +0000)]
GTK API deprecation: use GtkCssProvider for window background.
gdk_window_set_background_rgba is deprecated as of GTK 3.22, because
apparently you can't just _say_ any more 'here is what I want my
window's background colour to be in places where a widget isn't'.
Instead you have to provide a GtkStyleProvider which can be slotted
into a wobbly tower of other providers with associated priorities, so
that the user can override your choices if they really want to.
And the easiest way to constructc a GtkStyleProvider in turn is to
write *actual CSS* and get GTK to parse it, so I end up converting my
nice numeric RGB values into a complicated text format for another
part of _the same process_ to parse back into numbers. Sigh.
Simon Tatham [Tue, 27 Dec 2016 16:13:01 +0000 (16:13 +0000)]
Add some missing calls to midend_redraw().
I've just noticed that the GTK game window was not being redrawn when
changing between puzzle modes that don't involve a window resize - by
selecting a preset from the Type menu (e.g. changing between different
12x12 settings in Flood) or via the Custom menu.
It looks as if the bug was introduced in commit
8dfe5cec3, which
suggests that it was a side effect of the switch from
gtk_window_resize_to_geometry to plain gtk_window_resize. My guess is
that the implementation of the former function inside GTK might have
happened to trigger an unconditional window resize, while the latter
took the shortcut of doing nothing if the window was already the right
size; hence, resize_fe() would have been reliably generating a redraw
event without me having to ask for one, but now it doesn't, so I have
to trigger one myself any time I've just called resize_fe.
Simon Tatham [Fri, 16 Dec 2016 18:33:10 +0000 (18:33 +0000)]
Fix missing error highlights (+ array underrun!) in Pearl.
I was accidentally re-checking the value of component_state[comp]
after resetting comp to the special value -1, which caused a failure
to highlight stray path-shaped components if they existed in addition
to a large loop component. (Plus, of course, it's just illegal no
matter what visible behaviour it does or doesn't cause in practice.)
Fixed by adjusting the code to more closely match the version in Loopy
(I wonder how I managed to add two pieces of code in commit
b31155b73
without noticing this difference between them).
Simon Tatham [Sun, 11 Dec 2016 09:19:30 +0000 (09:19 +0000)]
Correct a logic error in Unequal game desc validation.
A user points out that the error check that should have detected a
non-digit where a digit should have been was never firing, due to an
&& that should have been ||.
I don't think it was a harmful error - the subsequent check that the
number was in range, plus the skipping past only digits to find the
next part of the string, combine to arrange that not many kinds of
invalid game id could actually get through.
But it did have the small effect that a 0 could be elided without
triggering an error, e.g. the game ids
4:0,0,0,0,0,0L,0,0,0R,0U,0,0L,0,0,,3,
4:0,0,0,0,0,0L,0,0,0R,0U,0,0L,0,0,0,3,
would both be accepted, and would be decoded into the same game, even
though the former should have failed syntax validation. Now it does.
Khem Raj [Tue, 6 Dec 2016 01:22:00 +0000 (01:22 +0000)]
Clarify conditions to avoid compiler errors
Fix errors pointed out by clang
error: logical not is only applied to the left hand side of this bitwise operator [-Werror,-Wlogical-not-parentheses]
| if (only_immutable && !copy->flags[i] & FLAG_IMMUTABLE) continue;
| ^
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Simon Tatham [Sat, 3 Dec 2016 08:49:29 +0000 (08:49 +0000)]
Stop using deprecated GTK 3 geometry-based functions.
Now we work out for ourselves how the drawing-area size relates to the
overall window size, by adding on the height of fe->menubar and/or
fe->statusbar.
Simon Tatham [Sun, 30 Oct 2016 17:59:13 +0000 (17:59 +0000)]
Clarify the Black Box rules slightly.
Chris Boyle points out that two of the rules are implicitly intended
to be read as only applying if a previous rule hadn't already decided
what would happen, and suggested that since not all readers infer that
priority order, it would be better to explicitly make them mutually
exclusive so that there can be no confusion about which one applies.
Simon Tatham [Fri, 28 Oct 2016 17:57:41 +0000 (18:57 +0100)]
Fix completion checking in Killer Solo.
The check_valid() function was not verifying that each Killer cage
summed to the right thing! Thanks to Chris Goodyer for spotting it. I
wonder how nobody else has, in 8 years.
Simon Tatham [Thu, 28 Apr 2016 19:42:23 +0000 (20:42 +0100)]
Account for disconnected paths in Loopy and Pearl error highlights.
In commits
24848706e and
adc54741f, I revamped the highlighting of
erroneous connected components of those two puzzles' solution graphs
in cases where a non-solution loop existed, so that the largest
component was considered correct and the smaller ones lit up in red.
I intended this to work in the cases where you have most of a correct
solution as one component and a small spurious loop as another (in
which case the latter lights up red), or conversely where your mostly
correct component was joined into a loop leaving a few edges out (in
which case the left-out edges again light up red). However, a user
points out that I overlooked the case where your mostly correct
solution is not all one component! If you've got lots of separate
pieces of path, and one tiny loop that's definitely wrong, it's silly
to light up all but the longest piece of path as if they're erroneous.
Fixed by treating all the non-loop components as one unit for these
purposes. So if there is at least one loop and it isn't the only thing
on the board, then we _either_ light up all loops (if they're all
smaller than the set of non-loop paths put together), _or_ light up
everything but the largest loop (if that loop is the biggest thing on
the board).
Simon Tatham [Thu, 28 Apr 2016 19:34:59 +0000 (20:34 +0100)]
Re-run mkauto.sh from within makedist.sh.
It isn't necessary to cause the right files to _exist_, because
makedist.sh is run from Buildscr which has already run mkauto. But it
turns out it _is_ important to get the relative timestamps of
Makefile.in and Makefile.am the right way round, otherwise somebody
who unpacks the tarball and runs 'configure' and 'make' will find make
tries to rebuild Makefile.in because it thinks Makefile.am is newer -
and if they don't have the right automake installed, or any automake,
that will fail.
Simon Tatham [Sun, 24 Apr 2016 06:30:20 +0000 (07:30 +0100)]
Explicitly set RGB colourspace in icon.pl's use of convert.
This is that annoying feature of up-to-date 'convert' in which
converting to or from a PNG file defaults to returning RGB values that
have been 'helpfully' gamma-corrected (or some such) from the exact
data stored in the source file to some nonsense you didn't want.
Usually the worst this causes is slightly washed-out looking graphics,
but in this case, since my entire aim was to squash the image into a
specific set of exact RGB values so as to turn it into a paletted
Windows icon file, it caused an actual build failure when the next
loop in icon.pl couldn't find the gamma-corrected values in its
expected palette map, and no wonder.
Simon Tatham [Sun, 24 Apr 2016 06:29:25 +0000 (07:29 +0100)]
Improve 'illegal colour' error message in icon.pl.
It actually went off this morning, after an upgrade of ImageMagick,
and I found that it contained both unprintable characters in the
colour description and the wrong variable in the coordinate display.
Simon Tatham [Sat, 9 Apr 2016 10:44:03 +0000 (11:44 +0100)]
Update build script for Inno Setup 5.5.9.
Between 5.5.6 and 5.5.9 the default output file name changed. To
defend against that potentially happening again, I'm now explicitly
specifying the output file name in the .iss source file (or rather, in
winiss.pl, which constructs it).
Simon Tatham [Mon, 14 Mar 2016 19:56:18 +0000 (19:56 +0000)]
s/Subversion/git/ in README.
Thanks to Kevin Buzzard for spotting that relic of an outmoded version
control system.
Simon Tatham [Fri, 11 Mar 2016 19:25:11 +0000 (19:25 +0000)]
Add a .htaccess redirection for the new .msi file.
Ahem. Left this out of yesterday's commit.
Simon Tatham [Thu, 10 Mar 2016 18:37:24 +0000 (18:37 +0000)]
Use WiX to generate an MSI-based Puzzles installer.
I've reused most of the install script I wrote for PuTTY recently,
minus the selectable-features dialog, and plus some preliminary Mason
templating to automatically build the right set of puzzle binaries
into the installer.
Stable GUIDs are autogenerated by the same technique I use in PuTTY's
Visual Studio project file generation: hash a fixed pile of randomly
generated bits (that is, randomly generated _once_ and used forever)
with each filename or other identifier and use those as your random
number source.
Simon Tatham [Tue, 1 Mar 2016 18:42:42 +0000 (18:42 +0000)]
Update Buildscr to use the new 'with' mechanism.
Simon Tatham [Fri, 26 Feb 2016 06:59:46 +0000 (06:59 +0000)]
Tracks: fix further completion-checking loopholes.
A user pointed out that Tracks could sometimes flash for completion
when there wasn't even a full path from A to B! And it looks as if
that wasn't even a mistake I introduced with the loop-checking revamp
this week.
Now I _think_ it's complete: we set ret=FALSE in check_completion
wherever we also produce an error highlight, and also whenever there
is no path connecting A with B. And if there is a path connecting A
with B, then any square not on the path becomes an error highlight.
Simon Tatham [Wed, 24 Feb 2016 19:36:41 +0000 (19:36 +0000)]
Pearl: revise loop detection similarly to Loopy.
Pearl has more or less the same attitude to loops as Loopy does, in
that a loop is required in the solution but some loops during play
want to be highlighted as errors. So it makes sense to use the same
strategy for loop highlighting.
I've cloned-and-hacked the code from Loopy rather than abstracting it
out, because there were some fiddly differences in application (like
checking of untouched clues in Pearl). Perhaps some day I can come
back and make it all neater.
Also, while I'm here, I've cleaned up the loop_length field in
game_state, which was carefully set up by check_completion() but never
actually used for anything. (If I remember rightly, it was going to be
used for a fancy victory flash which never saw the light of day.)
Simon Tatham [Wed, 24 Feb 2016 19:31:54 +0000 (19:31 +0000)]
Pearl: reinstate a conditioned-out assertion.
I think this assertion must have been put under '#if 0' during early
development, and accidentally never taken out once the game started
actually working. Putting it back in doesn't cause the self-tests to
fail, so I'm reinstating it - if it does fail, I'd like to know about
it!
Simon Tatham [Wed, 24 Feb 2016 19:27:10 +0000 (19:27 +0000)]
Loopy: be friendlier to right-click-less playing style.
Some people don't bother to use the right-click UI action that marks a
line as 'definitely not' rather than the initial default yellow
'unknown'. Previously, Loopy gave those people a UI annoyance for some
classes of mistake they made during solving: it would reliably
highlight a clue square with too _many_ edges around it, but not one
with too few - because in normal right-click-ful play, a clue with too
few LINE_YES only becomes an error when there aren't enough
LINE_UNKNOWN around it to potentially become the remaining YESes in
future.
This change arranges that once the player closes the loop, _then_ we
light up underfilled clues, on the basis that adding any further edge
would be an obvious error, so it's no longer sensible to assume that
the user might be planning to come back and do so.
(It's not a very timely notification of errors - it's easy to imagine
someone making a mistake like this very near the start of play and
only finding out about it when they close the loop at the very end. I
discuss possible improvements in a comment, but I don't think any
improvement avoids that problem completely, so I think it may just be
a form of annoyance that right-click-less players have to live with.)
Simon Tatham [Wed, 24 Feb 2016 19:22:57 +0000 (19:22 +0000)]
Loopy: revamp loop detection, but not using findloop.
Loopy differs from the other recently-reworked puzzles in that it
doesn't disallow loops completely in the solution - indeed, one is
actually required! But not all loops are what you wanted, so you have
to be a bit more subtle in what you highlight as an error. And the new
findloop system doesn't make that easy, because it only answers the
question 'is this edge part of a loop?' and doesn't talk about loops
as a whole, or enumerate them.
But since I was working in this area anyway, I thought I might as well
have a think about it; and I've come up with a strategy that seems
quite sensible to me, which I describe in a big comment added in
loopy.c. In particular, the new strategy should make a more sensible
decision about whether to highlight the loop or the non-loop edges, in
cases where the user has managed to enter a loop plus some extra
stuff.
Simon Tatham [Wed, 24 Feb 2016 19:18:30 +0000 (19:18 +0000)]
Tracks: tighten up a small loophole in completion checking.
If you had a single connected path linking the source to the
destination but _also_ had a spurious edge elsewhere in the grid, then
the spurious edge would be highlighted as an error, but it wouldn't
inhibit declaring the game complete and showing the victory flash.
Simon Tatham [Wed, 24 Feb 2016 19:14:31 +0000 (19:14 +0000)]
Tracks: use the new findloop for loop detection.
Tracks's previous loop detector was very basic, and only bothered to
highlight one loop, even if the player managed to create more than one
at a time. Now we highlight all of them.
Simon Tatham [Wed, 24 Feb 2016 19:10:16 +0000 (19:10 +0000)]
Slant: use the new findloop for loop detection.
The old face-dsf based loop detector is gone, and now we just call
findloop instead.
This is just a code cleanup: it doesn't fix any bugs that I know of.
In principle, it provides the same futureproofing we gained by making
the same change in Net, but Slant as a puzzle is less adaptable to
topologically interesting surfaces - in particular, you _can't_ play
it on any edgeless surface like a torus or Klein bottle, because no
filled grid can be loop-free in the first place. (The only way a
connected component can avoid having a loop surrounding it is if it
connects to the grid edge, so there has to _be_ a grid edge.) But you
could play Slant on a Mobius strip, I think, so perhaps one day...
Simon Tatham [Wed, 24 Feb 2016 19:05:43 +0000 (19:05 +0000)]
Net: use the new findloop for loop detection.
I've removed the old algorithm (the one described as 'footpath dsf' in
the findloop.c appendix comment, though I hadn't thought of that name
at the time), and replaced it with calls to the new API.
This should have no functional effect: there weren't any known bugs in
the previous loop-finder that affected currently supported play modes.
But this generality improvement means that non-orientable playing
surfaces could be supported in the future, which would have confused
the old algorithm. And Net, being the only puzzle as yet that's played
on a torus, is perhaps the one most likely to want to generalise
further at some point.
Simon Tatham [Wed, 24 Feb 2016 19:01:42 +0000 (19:01 +0000)]
Bridges: use the new findloop for loop detection.
Bridges only needs a loop detector for its non-default 'don't allow
loops' mode. But the one it had was using the graph-pruning strategy,
which means it had the dumb-bell bug - two loops joined by a path
would highlight the path as well as the loops. Switching to the new
findloop system fixes that bug.
A side effect is that I've been able to remove the 'scratch' array
from the game_state, which was only used by the old loop finder, so
that should save memory.
Simon Tatham [Wed, 24 Feb 2016 18:57:03 +0000 (18:57 +0000)]
New centralised loop-finder, using Tarjan's algorithm.
In the course of another recent project I had occasion to read up on
Tarjan's bridge-finding algorithm. This analyses an arbitrary graph
and finds 'bridges', i.e. edges whose removal would increase the
number of connected components. This is precisely the dual problem to
error-highlighting loops in games like Slant that don't permit them,
because an edge is part of some loop if and only if it is not a
bridge.
Having understood Tarjan's algorithm, it seemed like a good idea to
actually implement it for use in these puzzles, because we've got a
long and dishonourable history of messing up the loop detection in
assorted ways and I thought it would be nice to have an actually
reliable approach without any lurking time bombs. (That history is
chronicled in a long comment at the bottom of the new source file, if
anyone is interested.)
So, findloop.c is a new piece of reusable library code. You run it
over a graph, which you provide in the form of a vertex count and a
callback function to iterate over the neighbours of each vertex, and
it fills in a data structure which you can then query to find out
whether any given edge is part of a loop in the graph or not.
Phil Bordelon [Sun, 14 Feb 2016 01:53:30 +0000 (20:53 -0500)]
Add patternpicture to .gitignore.
Phil Bordelon [Sun, 14 Feb 2016 01:29:41 +0000 (20:29 -0500)]
Update documentation links.
Where possible (mostly with the Nikoli links), they've been updated to their
modern locations. At least one link had to become a Wayback Machine link;
I didn't bother making the floodit.appspot.com link a Wayback one because
there's no content there without the backing of Google App Engine. There
are other implementations online nowadays, of course, but I didn't want to
change the meaning of the text if at all possible. In addition, I added
Flash warnings for the Nikoli pages that now use Flash for instructions.
Simon Tatham [Mon, 1 Feb 2016 19:06:36 +0000 (19:06 +0000)]
Add missing casts to unsigned char inside ctype functions.
These are necessary because the argument to a ctype function cannot be
a negative value unless it's EOF. Thanks to Cygwin gcc for pointing
out the mistake, and to Patrick Shaughnessy for this patch.
Simon Tatham [Thu, 7 Jan 2016 19:33:34 +0000 (19:33 +0000)]
Rename the docs section for Rectangles.
The web page currently assumes it's called 'rect' rather than
'rectangles', because the web-page building script uses the first
field of each line of gamedesc.txt, same as the Unix binary name.
Rather than add another confusingly-almost-identical field to that
file, it's easier to just rename this one docs section to make the
assumption of equality hold.
Simon Tatham [Thu, 7 Jan 2016 19:30:56 +0000 (19:30 +0000)]
Fix a typo in the Black Box docs examples.
A letter offset by one from a ball on the edge should be an R, not an
H. Thanks to Kevin Buzzard for pointing out the error.
Simon Tatham [Sun, 3 Jan 2016 09:51:15 +0000 (09:51 +0000)]
Fix a valgrind warning in the Keen DIFF_HARD solver code.
The solver's array ctx->iscratch[] is used for a completely different
purpose in the DIFF_HARD code, compared to what it's used for in
DIFF_EASY and DIFF_NORMAL. In particular, a different number of
elements of the array are used - but the code which sets up the array
was not correctly initialising all of them.
I was also unable to find any clear comment that even explained _that_
the purpose of the array was entirely different between the two cases,
let alone explaining _what_ the two purposes were. So I've written
some comments as part of this commit, which should make things a bit
less confusing next time. (Though not much, I admit.)
Khem Raj [Wed, 30 Dec 2015 23:53:36 +0000 (23:53 +0000)]
rect: Fix compiler errors about uninitialized use of variables
error: 'r2.x' may be used uninitialized in this function
Its happening when using gcc 5.3 with musl C library. its considering
the case when case falls into default and immediately after exiting
this there is a check if (r1.h > 0 && r1.w > 0) where r1 element is
used but not assigned anything.
GCC is not noticing the control flow where the initilization will
always work due to assertion call can be a function call from libc
Signed-off-by: Khem Raj <raj.khem@gmail.com>
Simon Tatham [Thu, 24 Dec 2015 22:05:48 +0000 (22:05 +0000)]
Add a missing error message in Flood solve_game().
The only situation in which it actually can't find a solution is if
the puzzle is already solved, in which case it can at least fill in
*error to say so before it returns NULL.
Simon Tatham [Fri, 18 Dec 2015 14:50:44 +0000 (14:50 +0000)]
Clarify in README that Makefile.vc is for nmake.
A user pointed out today that I hadn't actually said that!
Simon Tatham [Fri, 11 Dec 2015 19:53:58 +0000 (19:53 +0000)]
New utility 'patternpicture', to build a Pattern from an xbm.
This utility works basically the same as galaxiespicture: you feed it
a .xbm bitmap on standard input, and it constructs a game ID which
solves to exactly that image. It will pre-fill some squares if that's
necessary to resolve ambiguity, or leave the grid completely blank if
it can.
Simon Tatham [Fri, 11 Dec 2015 18:09:41 +0000 (18:09 +0000)]
Pattern: add a system of immutable pre-filled grid squares.
The game previously only supported numeric clues round the edge; but
if for some reason you really want a puzzle with a specific solution
bitmap and that bitmap doesn't happen to be uniquely soluble from only
its row and column counts, then this gives you a fallback approach of
pre-filling a few grid squares to resolve the ambiguities.
(This also applies if the puzzle is uniquely soluble *in principle*
but not by Pattern's limited solver - for example, Pattern has never
been able to solve 4x4:2/1/2/1/1.1/2/1/1 and still can't, but now it
can solve 4x4:2/1/2/1/1.1/2/1/1,Ap which has the hard part done for
it.)
Immutable squares are protected from modification during play, and
used as initial information by the solver.
Simon Tatham [Fri, 11 Dec 2015 18:54:56 +0000 (18:54 +0000)]
Pattern: fix solver's handling of empty rows.
The algorithm for deducing how many squares in a row could be filled
in just from the initial clue set was focusing solely on _black_
squares, and forgot that if a row has a totally empty clue square then
everything in it can be filled in as white!
Now the solver can cope with puzzles such as 3x3:/1///1/ , where it
would previously have spuriously considered that it had no idea where
to start.
Simon Tatham [Thu, 10 Dec 2015 19:51:54 +0000 (19:51 +0000)]
Pattern: make part of the game_state shared.
The game_state now includes a pointer to a game_state_common
containing all the row and column clues, which is reference-counted
and therefore doesn't have to be physically copied in every dup_game.
Simon Tatham [Sat, 12 Dec 2015 09:17:33 +0000 (09:17 +0000)]
Code-sign the Windows puzzle binaries and installer.
Where facilities exist, that is. Like the approach I took with PuTTY
yesterday, Buildscr will now run a code-signing script over the binary
if you specify one in the bob config, and otherwise should fall back
to just leaving that step out.
Simon Tatham [Sun, 6 Dec 2015 16:00:10 +0000 (16:00 +0000)]
Implement align_label for GTK 3.[14,16).
gtk_misc_set_alignment was deprecated in GTK 3.14. But my replacement
code using gtk_label_set_{x,y}align doesn't work there, because that
function wasn't introduced until GTK 3.16, so there are two minor
versions in the middle where a third strategy is needed.
(That middle strategy doesn't permit arbitrary float alignments, but
that's OK, bceause we only actually use multiples of 0.5.)
Chris Boyle [Sat, 28 Nov 2015 13:56:39 +0000 (13:56 +0000)]
Allow unlocking an island despite moving slightly.
Previously moving 1 pixel would be treated as a failed drag and not an unlock.
Now you only have to release the button somewhere on the island you started on.
Simon Tatham [Tue, 17 Nov 2015 18:47:29 +0000 (18:47 +0000)]
Convert Buildscr to use the new "do/win" mechanism.
Simon Tatham [Tue, 3 Nov 2015 06:45:49 +0000 (06:45 +0000)]
Fix loophole in Palisade completion checker.
A user pointed out that if you construct a 'solution' in which no clue
square has too _many_ borders but at least one has too few, and then
bring those clues up to their count by adding extra stray border lines
_inside_ a connected component (avoiding actually dividing any
component completely into two), then the game checker treats that as
solved for victory-flash purposes, on the grounds that (a) the grid is
divided into components of the right size and (b) all clues are
satisfied.
A small example is 4x4n4:
22a2b2c33, with the non-solution of dividing
the grid into four 2x2 square blocks and then adding a spurious extra
edge between the two 3 clues. The old Palisade completion check would
flash for victory _at the same time_ as highlighting the spurious edge
in COL_ERROR.
Fixed by enforcing in is_solved() that every border line must separate
two distinct connected components.
Simon Tatham [Tue, 3 Nov 2015 06:56:47 +0000 (06:56 +0000)]
Format Palisade solve-type moves in sensible ASCII.
The solve move stored in 'aux' by new_game_desc consists of printable
characters in the range '@' to 'O', each representing a 4-bit bitmap
of edges around a cell. But the one generated on the fly by
solve_game() was missing out the 0x40 bit and just returning
characters in the range ^@ to ^O - which would not only have been
horrible if you found such a string in a save file, but also meant
that a game with any completely borderless square would have a
solution move string terminating early due to the ^@, causing
execute_move() to reject it.
Example: ./palisade --test-solve --generate 1 5x5n5#12345-37 now
succeeds, where previously it failed an assertion.
Simon Tatham [Fri, 23 Oct 2015 18:33:52 +0000 (19:33 +0100)]
Fix premature completion flash in Tracks.
Commit
44e2690ab loosened check_completion's idea of what made a
square count as 'having track in it' for purposes of checking
violations of the row/column counts. Unfortunately, that loosened
notion also applied to the check for the game being complete - so the
game would announce a win as soon as you had every square shaded, even
if you hadn't actually laid all the exact track positions down.
Now we separately count up the number of track-ish squares and the
number of fully completed ones, and use the former for error checking
and the latter for completion checking.
Jonas Kölker [Mon, 19 Oct 2015 00:48:39 +0000 (02:48 +0200)]
Tents: mark squares as non-tents with {Shift,Control}-cursor keys.
Jonas Kölker [Sun, 18 Oct 2015 19:05:11 +0000 (21:05 +0200)]
Fix a comment in Tents (it said 'tents' instead of 'trees').
Jonas Kölker [Tue, 13 Oct 2015 13:47:42 +0000 (15:47 +0200)]
Highlight clue errors in Tracks in some more situations.
- Count any square as having a track either if the square is marked
as such (rendered as a different background), or if at least one
adjacent edge is marked as containing a segment of train track
(rendered as train tracks if they're placed, else as an '=').
- Do the same counting in rows and columns.
Jonas Kölker [Mon, 12 Oct 2015 18:07:18 +0000 (20:07 +0200)]
In Undead, mark clues as errors in a few more situations.
- Mark a clue as an error if too many monsters are seen, even if
some squares are empty.
- Mark a clue as an error if too few monsters are seen, taking into
account how many more sightings are possible given the number of
empty squares and how many times each of them are visited.
Simon Tatham [Wed, 21 Oct 2015 17:32:15 +0000 (18:32 +0100)]
Fix array overruns in the new Filling solver pass.
Probably because I wrote a couple of loops up to the maximum cell
value using the non-idiomatic <= for their termination test, I also
managed to use <= inappropriately for iterating over every cell of the
grid, leading to a couple of references just off the end of arrays.
Amusingly, it was the Emscripten front end which pointed this out to
me by actually crashing as a result! Though valgrind found it just
fine too, once I thought to run that. But it comes to something when
running your C program in Javascript detects your memory errors :-)
Simon Tatham [Tue, 20 Oct 2015 19:33:53 +0000 (20:33 +0100)]
Enhance Filling's solver to handle large ghost regions.
The previous solver could cope with inferring a '1' in an empty
square, but had no deductions that would enable it to infer the
existence of a '4'-sized region in 5x3:
52d5b1a5b3. The new solver can
handle that, and I've made a companion change to the clue-stripping
code so that it aims to erase whole regions where possible so as to
actually present this situation to the player.
Current testing suggests that at the smallest preset a nontrivial
ghost region comes up in about 1/3 of games, and at the largest, more
like 1/2 of games. I may yet decide to introduce a difficulty level at
which it's skewed to happen more often still and one at which it
doesn't happen at all; but for the moment, this at least gets the
basic functionality into the code.
Simon Tatham [Sun, 18 Oct 2015 16:04:35 +0000 (17:04 +0100)]
Add the new 'fifteensolver' to .gitignore.
Simon Tatham [Sun, 18 Oct 2015 16:03:10 +0000 (17:03 +0100)]
Use \q{} in place of literal quote marks in puzzles.but.
While checking over the Palisade docs for this sort of error, I
happened to notice that a few were already in the existing games'
documentation.
Jonas Kölker [Fri, 2 Oct 2015 11:13:39 +0000 (13:13 +0200)]
Add a new puzzle: Palisade.
Simon Tatham [Sun, 18 Oct 2015 13:22:27 +0000 (14:22 +0100)]
Fix GTK puzzle resizing, *again*.
Jonas Kölker points out that commit
a800ff16b (which fixed a bug in
the previous attempt) left in another bug: if the puzzle size was
changed while the window was maximised, the system would fail to
recompute the tile size and would redraw completely wrongly.
So it's not optional after all to run midend_size(), even if the
drawing area size hasn't changed. I've reverted that code to be
unconditional, and now only the refresh of the Cairo-side backing
store system is conditionalised - and that's conditionalised on
changes to either the size of the actual window _or_ the size of the
contained pixmap. (The latter should defend against redraw failure in
the case where the puzzle aspect ratio changes, so that neither the
window size nor the tile size changes but a recentre is still needed.)
I _think_ this now fixes all the cases of resizing: this time I've
tested making an unmaximised puzzle window bigger or smaller, and
within a maximised window, forcing the puzzle to scale up, scale down,
or change its aspect ratio without changing its tile size. All work,
on GTK2 and GTK3, and yet we still don't get the visible flicker on
status line updates that was the reason I started fiddling with this
code in the first place.
(We _do_ still call configure_area on every update of the status line,
at least under GTK3; that's going to cause a forced full redraw on
every timer tick in Mines, which is wasteful of CPU, so it would still
be nice to find a better way of identifying the cases in which no
resizing at all was necessary and we could avoid renewing the game
drawstate. But the current code at least doesn't have any display
_errors_ that I know of, which is an improvement on its previous
state.)
Jonas Kölker [Wed, 7 Oct 2015 20:52:54 +0000 (22:52 +0200)]
Produce shorter Filling descriptions by run-length encoding 0s.
Jonas Kölker [Mon, 5 Oct 2015 15:59:39 +0000 (17:59 +0200)]
Expand keyboard input options in Bridges, for faster entry.
- Lay bridges (crosess) with Control-arrow (Shift-arrow)
- Jump (non-orthogonally) to nearby islands with number keys, a..f
- Mark islands as done with a single tap on the space bar
Jonas Kölker [Tue, 6 Oct 2015 23:08:11 +0000 (01:08 +0200)]
Fix two memory leaks in GTK frontend.
- The file selector for loading and saving gets a g_free().
- The handling of saving (menu_save_event) gets an sfree().
- It's also slightly restructured to prevent future errors.
- menu_load_event was already structured to prevent this error.
- The OLD_FILESEL code seems to not need a g_free().
Jonas Kölker [Mon, 5 Oct 2015 10:19:47 +0000 (12:19 +0200)]
Fix a typo in a Bridges error message.
'contain_ER_s' becomes 'contains'.
Jonas Kölker [Mon, 5 Oct 2015 08:03:57 +0000 (10:03 +0200)]
Fix Bridges keyboard cursor vertical out-of-bounds error.
Position the cursor in the top (bottom) row, press enter and press up
(down). The game acts as if you had pressed right, both with Enter-
and Space-based dragging.
Jonas Kölker [Thu, 1 Oct 2015 14:44:43 +0000 (16:44 +0200)]
Update Sixteen keyboard system for faster entry.
Pressing Ctrl-arrow or Shift-arrow on a tile now moves the row or
column under the tile. With Ctrl, the cursor moves as well so you can
keep making moves that affect the same tile; with Shift, the cursor
stays put so you can keep making moves that affect the same location.
Jonas Kölker [Fri, 2 Oct 2015 16:17:15 +0000 (18:17 +0200)]
In GTK frontend, bind mouse8/mouse9 to undo/redo.
These button codes are generated by the back/forward button pair on
the sides of some mice, and web browsers treat these as the back and
forward actions in the page history.
Jonas Kölker [Thu, 1 Oct 2015 20:53:53 +0000 (22:53 +0200)]
Add hinting feature to Guess.
Pressing H now suggests the lexicographically first row consistent
with all previous feedback.
The previous function of the H key to toggle a hold marker on the
current peg is now performed by Space / CURSOR_SELECT2, which is more
in line with other puzzles anyway.
Jonas Kölker [Thu, 8 Oct 2015 10:55:52 +0000 (12:55 +0200)]
Add standalone Fifteen solver, based on the hint feature.
Recall that the hint feature is really an incremental solver. Apply
it repeatedly until the board is solved. Grade puzzles as solvable
or unsolvable by checking their parity.
Jonas Kölker [Thu, 8 Oct 2015 10:20:15 +0000 (12:20 +0200)]
Add hinting feature to Fifteen (press 'h' for a hint).
This is really an incremental solver. It alternates between solving
rows and solving columns. Each row and column is solved one piece at
a time. Except for some temporary trickery with the last two pieces
in a row or column, once a piece is solved it is never moved again.
(On non-square grids it first solves some rows or some columns until
the unsolved part is a square, then starts alternating.)
Jonas Kölker [Thu, 8 Oct 2015 09:57:54 +0000 (11:57 +0200)]
Invert the Fifteen cursor if FIFTEEN_INVERT_CURSOR ~= ^[yY].*$
The introduction of flip_cursor allows us to replace some hairy
hand-rolled logic with the standardised and tested move_cursor.
Jonas Kölker [Thu, 8 Oct 2015 09:00:29 +0000 (11:00 +0200)]
End victory flash on new game and restart game.
Net provides the best demonstration of why. Complete a game of net,
then press N while the victory flash is playing: then the victory
flash keeps playing on the new game board. (Tip: save a game which
but for a redo is completed, then you can reproduce this repeatedly
without having to complete a new game each time.)
The flash timer reset code is placed together with the animation
timer reset code, because the two are conceptually related. Note
that midend_restart_game resets animations via midend_finish_move.
Jonas Kölker [Thu, 8 Oct 2015 08:54:47 +0000 (10:54 +0200)]
Reset midend animation counters on starting a new game.
This is already done in midend_restart_game via midend_finish_move.
If it's good enough for restarting a game, it ought to also be good
enough for starting new games.
Jonas Kölker [Thu, 8 Oct 2015 08:47:11 +0000 (10:47 +0200)]
Remove a redundant line of code.
Setting me->anim_time = 0.0 right before calling midend_finish_move is
redundant, since midend_finish_move itself sets me->anim_time = 0.
Jonas Kölker [Thu, 8 Oct 2015 08:43:51 +0000 (10:43 +0200)]
Don't stop animations when restarting an already restarted game.
Restarting a game that is already in the restarted state is meant to
be a no-op. It stopped animations. Don't do this.
Also, given that midmidend_restart_game called midend_stop_anim
twice, the invocation we remove was redundant.
Jonas Kölker [Wed, 7 Oct 2015 22:17:19 +0000 (00:17 +0200)]
Stop animations on a new game, no matter how it is started.
Animations were stopped if a new game was initiated with a keyboard
shortcut (n, N, Ctrl-N), but not via menu items such as presets or
custom configurations, nor (perhaps not a problem) on starting the
program. Fix this, so that animations are stopped on a new game no
matter how the new game is started.
Simon Tatham [Sun, 4 Oct 2015 19:03:50 +0000 (20:03 +0100)]
GTK 3 cleanup: stop using GtkDialog for config boxes.
It's becoming annoying to keep working within the increasing
restrictions on GtkDialog, in particular the fact that not only do we
have to let it have complete control of the button area, but also it's
not clear whether we can intercept a press of the 'OK' button and
display an error message rather than ending the dialog.
So, as I did in PuTTY, I'm resorting to using an ordinary GtkWindow
with controls I laid out myself.
Simon Tatham [Sun, 4 Oct 2015 18:57:25 +0000 (19:57 +0100)]
GTK 3 cleanup: use GtkAboutDialog for the About box.
This is again easier than faffing about doing it manually, and as an
added bonus, we get to put the largest of our icons in the box as a
logo :-)
Simon Tatham [Sun, 4 Oct 2015 18:56:39 +0000 (19:56 +0100)]
GTK 3 cleanup: use GtkMessageDialog for message_box().
This is a lot easier than faffing about setting up a dialog box
ourself, and also avoids direct access to GtkDialog's action area
(deprecated in GTK 3.16).
Simon Tatham [Sun, 4 Oct 2015 18:30:08 +0000 (19:30 +0100)]
GTK 3.16 deprecation: stop using gtk_misc_set_alignment.
The new equivalent is gtk_label_set_{x,y}align. But we can't use that
in all GTK 3 builds, because it's very new.
Jonas Kölker [Thu, 1 Oct 2015 16:47:55 +0000 (18:47 +0200)]
Improve Towers error highlighting.
Highlight clues of value n in Towers if its row/column contains an
increasing sequence of length n, the last number of which is not equal
to the number of rows/columns (i.e. such that the sequence will have
to be extended, in violation of the clue).
Jonas Kölker [Thu, 1 Oct 2015 15:35:40 +0000 (17:35 +0200)]
Dominosa: Highlight a number when pressed on the keyboard.
Simon Tatham [Sat, 3 Oct 2015 16:57:01 +0000 (17:57 +0100)]
Fix switching to a larger puzzle size under GTK 2.
Commit
8b491946e had a bug: configure_area stopped doing most of its
work if the new size already matched fe->w and fe->h, but in fact the
GTK2 resize_fe() _already_ set up fe->w and fe->h for the new size. I
managed not to notice, because I checked it all worked on GTK 3 but
only tested resizing to a _smaller_ puzzle on GTK 2. Ahem.
Now we don't change fe->w and fe->h at all until configure_area is
called. Also, we initialise them to dummy values at setup time, so
that configure_area won't compare the new size with uninitialised
data.
Simon Tatham [Sat, 3 Oct 2015 16:39:22 +0000 (17:39 +0100)]
build fix
Jonas Kölker [Sat, 3 Oct 2015 13:01:48 +0000 (15:01 +0200)]
Insert a manual reference in the default status bar text.
To guide developers to the resources they need.
[actual wording tweaked by SGT]
Jonas Kölker [Fri, 2 Oct 2015 16:23:44 +0000 (18:23 +0200)]
Render Filling presets as 'WxH', not 'HxW'.
Jonas Kölker [Thu, 1 Oct 2015 20:32:26 +0000 (22:32 +0200)]
Add 'Inshi No Heya' (multiplication only) variant to Keen.
Jonas Kölker [Thu, 1 Oct 2015 19:59:30 +0000 (21:59 +0200)]
Fix a display glitch in Keen's pencil-mode cursor.
Draw pencil-mode cursor before corners of thick lines in order to make
the thick lines appear on top of the north-west corner of the pencil
cursor, just like they do with the non-pencil cursor.
Jonas Kölker [Thu, 1 Oct 2015 19:29:42 +0000 (21:29 +0200)]
Recompute solutions in Inertia if the user strays from the path.
Jonas Kölker [Thu, 1 Oct 2015 19:22:24 +0000 (21:22 +0200)]
Fix an instance generation hang in Signpost.
Also expand the set of permissible parameters (add 1xN, Nx1 and 2x2).
Jonas Kölker [Thu, 1 Oct 2015 19:12:13 +0000 (21:12 +0200)]
Greatly improve and speed up the Filling instance generation.
Jonas Kölker [Thu, 1 Oct 2015 17:57:49 +0000 (19:57 +0200)]
Greatly increase the speed of the Filling solver.
Jonas Kölker [Thu, 1 Oct 2015 16:41:15 +0000 (18:41 +0200)]
Towers: allow marking of clues as done with the keyboard
Jonas Kölker [Thu, 1 Oct 2015 16:26:50 +0000 (18:26 +0200)]
Allow marking of clues as exhausted in Unequal.
Jonas Kölker [Thu, 1 Oct 2015 15:50:59 +0000 (17:50 +0200)]
Display improvements to Range.
Make the grid look a lot less heavy; enhance highlighting of error
clues; highlight enclosed small regions much more prettily.