simon-git: puzzles (master): Simon Tatham
Commits to Tartarus CVS repository.
tartarus-commits at lists.tartarus.org
Wed Feb 24 20:05:28 GMT 2016
TL;DR:
1add03f New centralised loop-finder, using Tarjan's algorithm.
deff331 Bridges: use the new findloop for loop detection.
e862d4a Net: use the new findloop for loop detection.
a2380d2 Slant: use the new findloop for loop detection.
01844d3 Tracks: use the new findloop for loop detection.
755c3d5 Tracks: tighten up a small loophole in completion checking.
2484870 Loopy: revamp loop detection, but not using findloop.
32643fa Loopy: be friendlier to right-click-less playing style.
c550092 Pearl: reinstate a conditioned-out assertion.
adc5474 Pearl: revise loop detection similarly to Loopy.
Repository: git://git.tartarus.org/simon/puzzles.git
On the web: http://tartarus.org/~simon-git/gitweb/?p=puzzles.git
Branch updated: master
Committer: Simon Tatham <anakin at pobox.com>
Date: 2016-02-24 20:05:28
commit 1add03f7b8a502d4453f53f4ea6930d0e71a6bb0
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=1add03f7b8a502d4453f53f4ea6930d0e71a6bb0;hp=4a0d9ad39b1fc5e42fea6fb595ca480db0727bcd
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 18:57:03 2016 +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.
findloop.c | 500 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
puzzles.h | 35 +++++
2 files changed, 535 insertions(+)
commit deff331e5f8d46215b967b7eaa7f64b13878785a
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=deff331e5f8d46215b967b7eaa7f64b13878785a;hp=1add03f7b8a502d4453f53f4ea6930d0e71a6bb0
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:01:42 2016 +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.
bridges.R | 2 +-
bridges.c | 147 +++++++++++++++++++++++++++----------------------------------
2 files changed, 66 insertions(+), 83 deletions(-)
commit e862d4a79b934a20d8c4cd283ff8292681b63314
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=e862d4a79b934a20d8c4cd283ff8292681b63314;hp=deff331e5f8d46215b967b7eaa7f64b13878785a
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:05:43 2016 +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.
net.R | 2 +-
net.c | 235 ++++++++++++++---------------------------------------------------
2 files changed, 52 insertions(+), 185 deletions(-)
commit a2380d277a50b02d9575017559d95d562986488a
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=a2380d277a50b02d9575017559d95d562986488a;hp=e862d4a79b934a20d8c4cd283ff8292681b63314
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:10:16 2016 +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...
slant.R | 2 +-
slant.c | 132 +++++++++++++++++++++++++--------------------------------------
2 files changed, 54 insertions(+), 80 deletions(-)
commit 01844d39c6c92d5ce417519ef2bdced6346f2549
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=01844d39c6c92d5ce417519ef2bdced6346f2549;hp=a2380d277a50b02d9575017559d95d562986488a
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:14:31 2016 +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.
tracks.R | 2 +-
tracks.c | 71 ++++++++++++++++++++++++++++++++++++++++++++------------------
2 files changed, 52 insertions(+), 21 deletions(-)
commit 755c3d5277262739e8beb03da3649e7f4d53e915
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=755c3d5277262739e8beb03da3649e7f4d53e915;hp=01844d39c6c92d5ce417519ef2bdced6346f2549
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:18:30 2016 +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.
tracks.c | 4 +++-
1 file changed, 3 insertions(+), 1 deletion(-)
commit 24848706edfdd1db1f97e3681d7ff52bec2fa575
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=24848706edfdd1db1f97e3681d7ff52bec2fa575;hp=755c3d5277262739e8beb03da3649e7f4d53e915
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:22:57 2016 +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.
loopy.c | 296 ++++++++++++++++++++++++++++++++++++++-------------------------
1 file changed, 177 insertions(+), 119 deletions(-)
commit 32643fab5583c6a0af6fd8373b226198d59d8b99
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=32643fab5583c6a0af6fd8373b226198d59d8b99;hp=24848706edfdd1db1f97e3681d7ff52bec2fa575
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:27:10 2016 +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.)
loopy.c | 58 ++++++++++++++++++++++++++++++++++++++++++++++++++++++----
1 file changed, 54 insertions(+), 4 deletions(-)
commit c5500926bf7458aabb0e11945bfd24038bfeedee
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=c5500926bf7458aabb0e11945bfd24038bfeedee;hp=32643fab5583c6a0af6fd8373b226198d59d8b99
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:31:54 2016 +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!
pearl.c | 4 ----
1 file changed, 4 deletions(-)
commit adc54741f03cf0cc5c639e917afd2442da9e3422
web diff http://tartarus.org/~simon-git/gitweb/?p=puzzles.git;a=commitdiff;h=adc54741f03cf0cc5c639e917afd2442da9e3422;hp=c5500926bf7458aabb0e11945bfd24038bfeedee
Author: Simon Tatham <anakin at pobox.com>
Date: Wed Feb 24 19:36:41 2016 +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.)
pearl.c | 176 ++++++++++++++++++++++++++++++++++++++++-----------------------
1 file changed, 112 insertions(+), 64 deletions(-)
More information about the tartarus-commits
mailing list