15 Commits

Author SHA1 Message Date
c0da615a93 Centralise initial clearing of the puzzle window.
I don't know how I've never thought of this before! Pretty much every
game in this collection has to have a mechanism for noticing when
game_redraw is called for the first time on a new drawstate, and if
so, start by covering the whole window with a filled rectangle of the
background colour. This is a pain for implementers, and also awkward
because the drawstate often has to _work out_ its own pixel size (or
else remember it from when its size method was called).

The backends all do that so that the frontends don't have to guarantee
anything about the initial window contents. But that's a silly
tradeoff to begin with (there are way more backends than frontends, so
this _adds_ work rather than saving it), and also, in this code base
there's a standard way to handle things you don't want to have to do
in every backend _or_ every frontend: do them just once in the midend!

So now that rectangle-drawing operation happens in midend_redraw, and
I've been able to remove it from almost every puzzle. (A couple of
puzzles have other approaches: Slant didn't have a rectangle-draw
because it handles even the game borders using its per-tile redraw
function, and Untangle clears the whole window on every redraw
_anyway_ because it would just be too confusing not to.)

In some cases I've also been able to remove the 'started' flag from
the drawstate. But in many cases that has to stay because it also
triggers drawing of static display furniture other than the
background.
2021-04-25 13:07:59 +01:00
78bc9ea7f7 Add method for frontends to query the backend's cursor location.
The Rockbox frontend allows games to be displayed in a "zoomed-in"
state targets with small displays. Currently we use a modal interface
-- a "viewing" mode in which the cursor keys are used to pan around
the rendered bitmap; and an "interaction" mode that actually sends
keys to the game.

This commit adds a midend_get_cursor_location() function to allow the
frontend to retrieve the backend's cursor location or other "region of
interest" -- such as the player location in Cube or Inertia.

With this information, the Rockbox frontend can now intelligently
follow the cursor around in the zoomed-in state, eliminating the need
for a modal interface.
2020-12-07 19:40:06 +00:00
5f5b284c0b Use C99 bool within source modules.
This is the main bulk of this boolification work, but although it's
making the largest actual change, it should also be the least
disruptive to anyone interacting with this code base downstream of me,
because it doesn't modify any interface between modules: all the
inter-module APIs were updated one by one in the previous commits.
This just cleans up the code within each individual source file to use
bool in place of int where I think that makes things clearer.
2018-11-13 21:48:24 +00:00
a550ea0a47 Replace TRUE/FALSE with C99 true/false throughout.
This commit removes the old #defines of TRUE and FALSE from puzzles.h,
and does a mechanical search-and-replace throughout the code to
replace them with the C99 standard lowercase spellings.
2018-11-13 21:48:24 +00:00
a76d269cf2 Adopt C99 bool in the game backend API.
encode_params, validate_params and new_desc now take a bool parameter;
fetch_preset, can_format_as_text_now and timing_state all return bool;
and the data fields is_timed, wants_statusbar and can_* are all bool.
All of those were previously typed as int, but semantically boolean.

This commit changes the API declarations in puzzles.h, updates all the
games to match (including the unfinisheds), and updates the developer
docs as well.
2018-11-13 21:34:42 +00:00
60a929a250 Add a request_keys() function with a midend wrapper.
This function gives the front end a way to find out what keys the back
end requires; and as such it is mostly useful for ports without a
keyboard. It is based on changes originally found in Chris Boyle's
Android port, though some modifications were needed to make it more
flexible.
2018-04-22 17:04:50 +01:00
b3243d7504 Return error messages as 'const char *', not 'char *'.
They're never dynamically allocated, and are almost always string
literals, so const is more appropriate.
2017-10-01 16:34:41 +01:00
de67801b0f Use a proper union in struct config_item.
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.
2017-10-01 16:34:41 +01:00
eeb2db283d New name UI_UPDATE for interpret_move's return "".
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.
2017-10-01 15:18:14 +01:00
a7dc17c425 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.
2017-04-26 21:51:23 +01:00
d295a8a93c 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.
2015-12-24 22:05:48 +00:00
195217a480 Fix a compile warning on ARM.
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.
2015-03-24 19:20:03 +00:00
cca302c01b Improve the Flood solver.
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.
2015-01-15 20:36:19 +00:00
f39681ab41 Revise the Flood preset list.
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.
2015-01-13 19:31:29 +00:00
201b32983b New puzzle: 'Flood'.
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.
2015-01-12 19:51:19 +00:00