57 Commits

Author SHA1 Message Date
8f3413c31f galaxieseditor: make 'copy to clipboard' give the game id.
This seems like a generally helpful design for game editors in
general: if we're going to have a helper program that can construct an
instance of a game, then one obvious thing you'd want as output from
it would be the descriptive game id, suitable for pasting back into
the playing UI.

So, in the just-re-enabled helper program 'galaxieseditor', I've
rewritten game_text_format so that it generates exactly that. Now you
can place dots until you have a puzzle you like, then use the 'Copy'
menu item to make it into a game id usable in 'galaxies' proper.

This doesn't set a precedent that I'm planning to _write_ editors for
all the other games, or even any of them (right now). For some, it
wouldn't be too hard (especially games where the solution and clues
are the same kind of thing, like default-mode Solo); for others, it
would be a huge UI nightmare.
2021-05-25 10:59:11 +01:00
12b64a1db1 Build a lot of conditioned-out test and helper programs.
Most of these aren't especially useful, but if we're going to have
them in the code base at all, we should at least ensure they compile:
bit-rotted conditioned-out code is of no value.

One of the new programs is 'galaxieseditor', which borrows most of the
Galaxies code but changes the UI so that you can create and remove
_dots_ instead of edges, and then run the solver to see whether it can
solve the puzzle you've designed. Unlike the rest, this is a GUI
helper tool, using the 'guiprogram' cmake function introduced in the
previous commit.

The programs are:
 - 'combi', a test program for the utility module that generates all
   combinations of n things
 - 'divvy', a test program for the module that divides a rectangle at
   random into equally-sized polyominoes
 - 'penrose-test', a test program for the Penrose-tiling generator
   used in Loopy, which outputs an SVG of a piece of tiling
 - 'penrose-vector', a much smaller test program for the vector
   arithmetic subroutines in that code
 - 'sort-test', a test of this code base's local array sorting routine
 - 'tree234-test', the exhaustive test code that's been in tree234.c
   all along.

Not all of them compiled first time. Most of the fixes were the usual
kind of thing: fixing compiler warnings by removing unused
variables/functions, bringing uses of internal APIs up to date. A
notable one was that galaxieseditor's interpret_move() modified the
input game state, which was an error all along and is now detected by
me having made it a const pointer; I had to replace that with an extra
wrinkle in the move-string format, so that now execute_move() makes
the modification.

The one I'm _least_ proud of is squelching a huge number of
format-string warnings in tree234-test by interposing a variadic
function without __attribute__((printf)).
2021-05-25 10:52:25 +01:00
20a85890d7 Galaxies: clean up draw/undraw code for dragged arrows.
The previous code had multiple bugs. We had completely left out the
draw_update after drawing each arrow; we omitted the usual
precautionary clip() that constrains each arrow draw to the same
rectangle we just saved in the blitter; we re-computed the coordinates
of the opposite arrow at undraw time, instead of saving the
coordinates we _actually_ used after computing them the first time.
And we restored from the two blitters in the same order we saved them,
instead of reverse order, which was harmless at the time (the drawing
happened after both saves), but is generally bad practice, and needed
to be fixed when the code was rearranged to fix the rest of these
issues.

I noticed these issues in passing, while hunting the diagonal-line bug
fixed in the previous commit. These fixes by themselves would have
prevented any persistent drawing artefact as a result of that bug (the
clip() would have constrained the spurious diagonal line to the region
saved by the blitter, so it would have been undrawn again afterwards);
but it's better to have fixed the root cause as well!
2021-05-21 14:14:21 +01:00
985b538e53 Galaxies: avoid division by zero in draw_arrow().
During an interactive drag of an arrow, it's possible to put the mouse
pointer precisely on the pixel the arrow is pointing at. When that
happens, draw_arrow computes the zero-length vector from the pointer
to the target pixel, and tries to normalise it to unit length by
dividing by its length. Of course, this leads to computing 0/0 = NaN.

Depending on the platform, this can cause different effects.
Conversion of a floating-point NaN to an integer is not specified by
IEEE 754; on some platforms (e.g. Arm) it comes out as 0, and on
others (e.g. x86), INT_MIN.

If the conversion delivers INT_MIN, one possible effect is that the
arrow is drawn as an immensely long diagonal line, pointing upwards
and leftwards from the target point. To add to the confusion, that
line would not immediately appear on the display in full, because of
the draw_update system. But further dragging-around of arrows will
gradually reveal it as draw_update rectangles intersect the corrupted
display area.

However, that diagonal line need not show up at all, because once
draw_arrow has accidentally computed a lot of values in the region of
INT_MIN, it then adds them together, causing signed integer overflow
(i.e. undefined behaviour) to confuse matters further! In fact, this
diagonal-line drawing artefact has only been observed on the
WebAssembly front end. The x86 desktop platforms might very plausibly
have done it too, but in fact they didn't (I'm guessing because of
this UB issue, or else some kind of clipping inside the graphics
library), which is how we haven't found this bug until now.

Having found it, however, the fix is simple. If asked to draw an arrow
from a point to itself, take an early return from draw_arrow before
dividing by zero, and don't draw anything at all.
2021-05-21 14:01:47 +01:00
b7124dc05e Galaxies: disallow placing an edge touching a dot.
Trivially, no edge of this kind can be part of any legal solution, so
it's a minor UI affordance that doesn't spoil any of the puzzly
thinking to prevent the user accidentally placing them in the first
place.

Suggestion from Larry Hastings, although this is not his patch.
2021-05-20 15:17:36 +01:00
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
84cb4c6701 Galaxies: fix assertion failure when adding out-of-bounds association.
Adding an association with an out-of-bounds square (i.e. by pressing Return
with a dot selected, and then moving the cursor so the `opposite' arrow was
off the screen) would cause space_opposite_dot() to return NULL, in turn
causing ok_to_add_assoc_with_opposite_internal() to return false, failing
the assertion.

This assertion appears to have been introduced in 68363231.
2020-12-07 21:43:54 +00: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
68363231f0 Galaxies: prevent creation of empty undo-chain items.
If you drag an arrow on to a square which is already filled in as part
of a completed region, or whose counterpart is filled in, or whose
counterpart is actually a dot, then the game can't actually place a
double arrow. Previously, it didn't find that out until execute_move
time, at which point it was too late to prevent a no-op action from
being placed on the undo chain.

Now we do those checks in interpret_move, before generating the move
string that tries to place the double arrow in the first place. So
execute_move can now enforce by assertion that arrow-placement moves
it gets are valid.
2019-02-18 21:12:16 +00:00
db3b531e2c Add missing 'static' to game-internal declarations.
Another thing I spotted while trawling the whole source base was that
a couple of games had omitted 'static' on a lot of their internal
functions. Checking with nm, there turned out to be quite a few more
than I'd spotted by eye, so this should fix them all.

Also added one missing 'const', on the lookup table nbits[] in Tracks.
2018-11-13 22:06:19 +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
a58c1b216b Make the code base clean under -Wwrite-strings.
I've also added that warning option and -Werror to the build script,
so that I'll find out if I break this property in future.
2017-10-01 16:35:40 +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
f9027226a0 Enforce more than one dot in Galaxies puzzles.
At minimum size (3x3) Galaxies can generate a pre-solved single dot
game.

You have to add and remove a line to get the victory flash which is a
bit weird, so just prevent this.
2015-09-26 20:02:02 +01:00
f49c7f530c Handle replacing an existing arrow 2015-05-11 11:05:36 +01:00
3627111c52 Fix the extra arrow hanging around while moving the opposite existing arrow 2015-05-11 11:05:36 +01:00
bef1b2c59b Mark some arguments constant 2015-05-11 10:46:12 +01:00
3768ed65f2 Fix the issue with adding only one arrow when the other end was already white 2015-05-11 10:46:12 +01:00
83318d4218 Add/remove the opposite arrow when you let go 2015-05-11 10:46:12 +01:00
4fa5df1cba Draw the opposite arrow only while dragging 2015-05-11 10:15:02 +01:00
774395d373 Moved all function declarations to the top of the file 2015-05-11 10:14:57 +01:00
155607b768 Use the game_state and space typedefs 2015-05-11 10:14:53 +01:00
6684bec60c Always use ret instead of state in execute_move 2015-05-11 10:14:48 +01:00
7cf1e1f83e Fixed a typo in a comment 2015-05-11 10:14:44 +01:00
251b21c418 Giant const patch of doom: add a 'const' to every parameter in every
puzzle backend function which ought to have it, and propagate those
consts through to per-puzzle subroutines as needed.

I've recently had to do that to a few specific parameters which were
being misused by particular puzzles (r9657, r9830), which suggests
that it's probably a good idea to do the whole lot pre-emptively
before the next such problem shows up.

[originally from svn r9832]
[r9657 == 3b250baa02a7332510685948bf17576c397b8ceb]
[r9830 == 0b93de904a98f119b1a95d3a53029f1ed4bfb9b3]
2013-04-13 10:37:32 +00:00
0b93de904a Add 'const' to the game_params arguments in validate_desc and
new_desc. Oddities in the 'make test' output brought to my attention
that a few puzzles have been modifying their input game_params for
various reasons; they shouldn't do that, because that's the
game_params held permanently by the midend and it will affect
subsequent game generations if they modify it. So now those arguments
are const, and all the games which previously modified their
game_params now take a copy and modify that instead.

[originally from svn r9830]
2013-04-12 17:11:49 +00:00
3b250baa02 New rule: interpret_move() is passed a pointer to the game_drawstate
basically just so that it can divide mouse coordinates by the tile
size, but is definitely not expected to _write_ to it, and it hadn't
previously occurred to me that anyone might try. Therefore,
interpret_move() now gets a pointer to a _const_ game_drawstate
instead of a writable one.

All existing puzzles cope fine with this API change (as long as the
new const qualifier is also added to a couple of subfunctions to which
interpret_move delegates work), except for the just-committed Undead,
which somehow had ds->ascii and ui->ascii the wrong way round but is
otherwise unproblematic.

[originally from svn r9657]
2012-09-09 18:40:12 +00:00
b4f3b57aa1 Swap a 'max' for a 'min', fixing an out-of-range colour component
being passed to the front end.

[originally from svn r9451]
2012-04-08 13:06:46 +00:00
73daff3937 Changed my mind about midend_is_solved: I've now reprototyped it as
midend_status(), and given it three return codes for win, (permanent)
loss and game-still-in-play. Depending on what the front end wants to
use it for, it may find any or all of these three states worth
distinguishing from each other.

(I suppose a further enhancement might be to add _non_-permanent loss
as a fourth distinct status, to describe situations in which you can't
play further without pressing Undo but doing so is not completely
pointless. That might reasonably include dead-end situations in Same
Game and Pegs, and blown-self-up situations in Mines and Inertia.
However, I haven't done this at present.)

[originally from svn r9179]
2011-06-19 13:43:35 +00:00
980880be1f Add a function to every game backend which indicates whether a game
state is in a solved position, and a midend function wrapping it.

(Or, at least, a situation in which further play is pointless. The
point is, given that game state, would it be a good idea for a front
end that does that sort of thing to proactively provide the option to
start a fresh game?)

[originally from svn r9140]
2011-04-02 16:19:12 +00:00
0687980f0c Memory management and other fixes from James H.
[originally from svn r8596]
2009-06-17 20:01:45 +00:00
4850845205 Keyboard cursor support in Galaxies, by James H.
[originally from svn r8413]
2009-01-15 18:18:21 +00:00
a7431c0b7c New infrastructure feature. Games are now permitted to be
_conditionally_ able to format the current puzzle as text to be sent
to the clipboard. For instance, if a game were to support playing on
a square grid and on other kinds of grid such as hexagonal, then it
might reasonably feel that only the former could be sensibly
rendered in ASCII art; so it can now arrange for the "Copy" menu
item to be greyed out depending on the game_params.

To do this I've introduced a new backend function
(can_format_as_text_now()), and renamed the existing static backend
field "can_format_as_text" to "can_format_as_text_ever". The latter
will cause compile errors for anyone maintaining a third-party front
end; if any such person is reading this, I apologise to them for the
inconvenience, but I did do it deliberately so that they'd know to
update their front end.

As yet, no checked-in game actually uses this feature; all current
games can still either copy always or copy never.

[originally from svn r8161]
2008-09-06 09:27:56 +00:00
0564211167 Revise the printing colour framework so that we can explicitly
request either of hatching or halftoning, and also choose which to
supply as a fallback when printing in colour.

[originally from svn r7976]
2008-04-07 17:13:29 +00:00
5fb108db00 Kyle Brazell points out that the completion checker considers a
region valid if it has _a_ dot at its centre of symmetry, even if
that dot isn't actually within the region in question.

[originally from svn r7407]
2007-03-23 18:08:21 +00:00
587d105799 My favourite kind of patch, from James H: one which decreases the
amount of code. James has ripped out the solver's version of
check_complete(), in favour of using the one I wrote for the
game-playing UI. My one checks connectedness, which means that the
solver will now not believe non-solutions to puzzles where
connectedness becomes a difficult issue. Examples of game IDs which
are now solved correctly but were previously not are 5x3:ubb and
7x7:ajfzmfqgtdzgt.

[originally from svn r7362]
2007-03-03 17:15:25 +00:00
6713d21cd1 Fix problems with arrow UI with non-square grid.
[originally from svn r7355]
2007-03-02 20:14:15 +00:00
3584fc5a1b Silliness! Here's a somewhat hacky patch which builds an additional
binary from the Galaxies source file. The function of the new
`galaxiespicture' is to take a .xbm bitmap on standard input and
convert it into a Galaxies game ID using both black and white dots,
such that when solved the puzzle displays the input bitmap.

In the process of this I've implemented a post-processing pass after
the main game generation, to prevent clusters of adjacent
singletons. James H already solved that problem for unconstrained
game generation, but for some reason it came back when I did this.
However, the post-processing pass is still turned off for normal
usage, on the basis that (a) if it ain't broke don't fix it, and (b)
it's rather slow and best avoided if not necessary.

[originally from svn r7354]
2007-03-01 18:57:36 +00:00
db743e54e8 Cleanup patch from James H: disable the `s' key, which was only in
there by accident.

[originally from svn r7351]
2007-03-01 07:41:11 +00:00
cf0b0b747b Bound edge thicknesses below so that they're always thicker than the
grid lines.

[originally from svn r7349]
2007-03-01 07:32:35 +00:00
9287d95d08 General cleanups patch from James H:
- missing static in filling.c
 - better robustness in execute_move() in filling.c
 - remove side effects in assert statements
 - remove rogue diagnostic in galaxies.c
 - remove // comment in map.c
 - add more stylus-friendly UI to Pattern
 - bias Unequal towards generating inequality clues rather than numeric

[originally from svn r7344]
2007-02-28 21:19:15 +00:00
de5ccc9352 Gary Wong points out a couple of minor errors in the setting of
`used_solve'.

[originally from svn r7343]
2007-02-28 21:02:31 +00:00
15f70f527a Dariusz Olszewski's changes to support compiling for PocketPC. This
is mostly done with ifdefs in windows.c; so mkfiles.pl generates a
new makefile (Makefile.wce) and Recipe enables it, but it's hardly
any different from Makefile.vc apart from a few definitions at the
top of the files.

Currently the PocketPC build is not enabled in the build script, but
with any luck I'll be able to do so reasonably soon.

[originally from svn r7337]
2007-02-26 20:35:47 +00:00
bc64fc8481 Galaxies doesn't print in colour.
[originally from svn r7334]
2007-02-25 15:50:24 +00:00