This allows me to use different types for the mutable, dynamically
allocated string value in a C_STRING control and the fixed constant
list of option names in a C_CHOICES.
Now midend.c directly tests the returned pointer for equality to this
value, instead of checking whether it's the empty string.
A minor effect of this is that games may now return a dynamically
allocated empty string from interpret_move() and treat it as just
another legal move description. But I don't expect anyone to be
perverse enough to actually do that! The main purpose is that it
avoids returning a string literal from a function whose return type is
a pointer to _non-const_ char, i.e. we are now one step closer to
being able to make this code base clean under -Wwrite-strings.
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.
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.
Aapo Rantalainen points out that comparing 'char c' against zero gives
rise to gcc's "comparison is always false" warning, which escalates to
an error under -Werror.
This is one of those situations where the warning is doing more harm
than good, but here's a rephrasing which casts to unsigned so that
both negative numbers and positive out-of-range ones can be caught by
the same comparison.
Previously it simply chose every move based on the static evaluation
function 'minimise the pair (longest shortest-path to any square,
number of squares at that distance)'. Now it looks three moves ahead
recursively, and I've also adjusted the evaluation function to tie-
break based on the number of squares brought to distance zero (i.e.
actually in control).
The result isn't an unconditional improvement on the old solver; in a
test run based on 'flood --generate 1000 12x12c6m0#12345' I found that
57 out of 1000 grids tested now had longer solutions. However, about
three quarters had shorter ones, and solutions are more than a move
shorter on average.
The ones I started with were a bit under-varied and over-orthogonal.
Get rid of some of the more pointless things like 16x16 with lots of
extra moves, and add some with different colour counts. While I'm
here, make the menu descriptions nicer.
Based on a web game I saw a few years ago, and dashed off this weekend
after I thought of a way to write a good (though not quite optimal)
heuristic solver, here's a random little thing not quite in the same
line as the most usual kind of Puzzles fare: instead of making you
scratch your head to find any move to make at all, it's easy to find
solutions in principle, and the challenge comes from having to do so
within a move limit.