1764 Commits

Author SHA1 Message Date
9478efe32e Remove some midend functions from nullfe.c
As far as I can tell, nothing that uses nullfe.c depends on these
functions.  On the other hand, they do make it impossible to include
nullfe.c and midend.c in the same program.  If anything does turn out to
need them, they can be spun off into nullme.c or something.
2023-01-12 21:44:06 +00:00
332873db83 Add more functions to nullfe.c
The null get_random_seed required a little care.  It's not OK for it to
return NULL and zero because NULL isn't a valid argument to memcpy()
even with a length of zero (thank you UBSan).  So we return a single
zero byte instead.
2023-01-12 21:43:09 +00:00
e66d027a81 Fix Pattern row clues when a row has no black in
I'd failed to initialise the row clue string to empty so it got the
contents of the previous row to be displayed.  This could only happen
for imported descriptions, or for puzzles with one or two columns.

Thanks to Glen Sawyer for spotting and reporting the bug.
2023-01-09 21:26:35 +00:00
171e7a76ed Correct credits information 2023-01-08 13:53:28 +00:00
2537961b6f Update devel.but commit ID 2023-01-02 18:28:39 +00:00
a2212e82aa Use a dynamically-sized buffer for Pattern row clues 2023-01-02 18:11:45 +00:00
d246077e78 Add a macro of an upper bound on the formatted length of an integer
There are lots of places where Puzzles formats integers into
fixed-length buffers using sprintf() with a "%d" format.  This isn't
very safe, since C doesn't guarantee any particular maximum size for an
"int".  However, the restrictions on representations of integers means
we can infer an upper bound using sizeof(), CHAR_BIT, and an
approximation to the binary log of 10.
2023-01-02 18:09:27 +00:00
44b5291b48 Adjust font size of Pattern clues based on the numbers
If all the column clues are single digits, then the font can be larger
without adjacent clues getting too close to each other.  I've also
slightly increased the font size even with two-digit clues, from
TILE_SIZE/2 to TILE_SIZE/1.8.
2023-01-02 18:09:20 +00:00
1ef9aa4cc2 Pattern: Pack clues for each row more closely together
Rather than centring each clue in an imaginary box, put equal amounts of
space between them (using space characters) and then right-align the
whole string.  This makes for more efficient use of space, and I think
it also looks better when there are two-digit clues.

This does introduce a rather grotty (if large) fixed-size buffer for row
clues.  Probably the row clues should be pre-formatted into a string
when the puzzle is set up.
2023-01-01 16:09:19 +00:00
23c9e0a8b2 Pattern: Clip clues to their proper rectangles
Since the drawing API offers no guarantees about where text drawing
might have effects, it's unsafe to erase text other than by wiping the
clipping rectangle that was in effect when it was drawn.  In practice,
this means that all variable (including colour) text should be drawn
with a narrow clipping rectangle.

It wasn't actually a practical problem that Pattern didn't clip its
clues, but I'll like to make its fonts less tiny, which will make it
more likely to need clipping in odd cases.

This also factors out some repeated computations in draw_numbers().
2023-01-01 16:09:19 +00:00
14c025d192 Create an icon for the Null Game
This might be useful for creating a KaiOS app of it.  It also
conveniently ensures that Null Game doesn't just build but also runs
correctly.
2022-12-31 16:18:53 +00:00
b403f8f97a Support the generation of icons from uniformly-coloured screenshots
The square.pl script removed all pixels that were the same colour as the
edge ones, even if that meant removing all of the pixels.  Now it stops
removing pixels at 1x1 so that there will be something left for
ImageMagick to work on.
2022-12-31 16:18:53 +00:00
f63810fbc8 Don't use Null Game's extra source files for all GUI programs
All the not-quite-puzzle GUI programs (only galaxieseditor at this
point) were using the extra source files from Null Game, presumably as a
convenient way of asking not to have an icon on platforms where icons
are provided as extra source files.  Unfortunately, this all went wrong
if Null Game did have a save file for an icon, causing CMake to complain
about multiple definitions of a target.

Now these programs look for extra files under their own names, which
will work just as well since those have no save files to generate icons
from either.
2022-12-31 16:18:53 +00:00
0363e9e7fd devel.but: fix markup error causing build failure. 2022-12-31 08:39:46 +00:00
cc36e47807 Slightly better macro usage for Tracks completion flash 2022-12-30 00:06:27 +00:00
7249530429 Clear any existing Tracks flash data when generating it
Simon points out that if you have an ambiguous puzzle then it might
need different flash data for different solutions, so if you solve it
one way, than manually unsolve it and solve it another way, the old
flash data in the game state need to be cleared out when the new flash
data are written.

Tested by solving the hugely ambiguous "5x5:CwC,5,5,5,5,S5,S5,5,5,5,5".
2022-12-30 00:01:02 +00:00
3cb919f4f7 Tracks: Set the grid colour based on others
COL_GRID used to be mid-way between the usual COL_BACKGROUND and
COL_TRACK_BACKGROUND.  But then I changed mkhighlight() so that it
didn't make COL_BACKGROUND so dark and that made the grid lines
indistinguishable from the track background.

Now COL_GRID is generated from COL_BACKGROUND and COL_TRACK_BACKGROUND
so as long as those are sufficiently distinct from each other, COL_GRID
will be distinct from both of them.
2022-12-29 22:28:03 +00:00
cdd24fd459 Expose colour_mix() to backends (and others)
Quite a few backends currently generate colours by multiplying the
foreground colour by a fraction, effectively mixing it with black.  On a
black background, this might be reasonably replaced by mixing the
background colour with white, but that's rather arithmetically fiddly.
Happily, I already have a function for that and just need to expose it.
2022-12-29 21:19:55 +00:00
425942c852 Fancier completion flash for Tracks
It now runs along the track from A to B, spending the first half of
FLASH_TIME lighting all the segments and the second half extinguishing
them.
2022-12-27 19:27:38 +00:00
99d3c31e12 Tracks: Highlight more counting errors if track looks good
Normally, Tracks puts error marks on row and column clues only when one
of the existing track or no-track marks will have to be removed to
satisfy the clue.  This could lead to a situation where the player had
built a track from A to B and got neither a win nor a highlighted error
because the only error was in a row or column having too few track
segments.

This commit re-arranges the completion checking so that if there's a
complete track from A to B and no spurious track then the game will
highlight any clue that isn't matched by the actually laid track.  This
should mean that any solution with a track from A to B will either be a
win or have a highlighted error.

This should fix Android issue #266.
2022-12-27 16:34:37 +00:00
4ec2c58045 When filling in or blanking a square, don't generate null moves
This applies to various square-filling games: Keen, Solo, Towers,
Undead, and Unequal.  In all cases, selecting a square and pressing the
number that was already in it, or selecting an empty square and pressing
Backspace, would add a move to the undo chain that did nothing.  This
also meant that the convention where Backspace from the top level of an
application in KaiOS leaves the application didn't work.

Now the various interpret_move() functions check the current state of
the grid, and return NULL or UI_UPDATE where a move wouldn't change the
board.  UI_UPDATE is returned in the case where the cursor was put in
place using the mouse, because in those cases I think the cursor should
still be hidden again.  NULL is returned when the cursor was put in
place by keyboard, because then there's really nothing to do.
2022-12-27 15:18:42 +00:00
d332973438 Guess: Make 'H' key work properly with "Allow duplicates" off
Before it would not only generate an invalid guess, but also override
the usual rules to allow you to submit it.  Now guesses are only
provided if they're valid, and I've adjusted the maximum-colour finder
so that the code can actually find the correct guess.  This should have
no effect on the behaviour with "Allow duplicates" turned on.
2022-12-23 22:59:23 +00:00
11c1447eac Solo: Set max difficulty for small jigsaw puzzles
(cherry picked from Android port, commit
5c9a7b64a06d07f97a41622c4b91d81f3419a51b)
2022-12-17 11:44:42 +00:00
f967bfa87b Prevent starting in a solved state in Fifteen & Flood
(cherry picked from Android port, commit
cb38abdc71780bd9b393b90514396c338306fa69)
2022-12-16 23:55:15 +00:00
0d43753ff2 Remove _() introduced from Android port.
Introduced in cbf2ede64a. It's used there for marking up text for i18n
in a gettext stylee, but is not available here.
2022-12-16 11:17:29 +00:00
cbf2ede64a lightup: Ban 2x2 with either 4-way type
(2x2 with four-way symmetry must be either all-black (trivial) or
all-white (ambiguous). --bjh21)

(cherry picked from Android port, commit
27ae898e118b0a31a98d393bf56aa138845123e6)
2022-12-16 02:09:44 +00:00
a46bbae7c1 guess: Remove an obsolete workaround
dup_params() has taken a const argument for some time.
2022-12-16 00:28:09 +00:00
b780b073da magnetssolver: Add a missing newline to a message 2022-12-15 23:55:32 +00:00
69e63a810e magnets: Area constraints; fix message.
(The restriction on 2x2 puzzles is because the board layer-out doesn't
use neutral pieces on such small boards, and the only soluble 2x2 boards
have neutral pieces.  I haven't investigated the Tricky size limit, but
it seems entirely reasonable that all the smaller boards are too easy.
--bjh21)

(cherry picked from Android port, commit
133794977a13767e0c1596be6a5b26f2cf2d1fd1)
2022-12-15 23:51:59 +00:00
af2d992af0 Tweak Filling greys to better distinguish selected and completed
If you accidentally selected a cell that was part of a completed area,
it was hard to notice that you'd done so.

(cherry picked from Android port, commit
ca08cd832952cefd9a3b545f13785d7054a3e1f6)
2022-12-15 20:04:59 +00:00
f1756279d2 Update developer docs for mkhighlight changes
Specifically for passing -1 as a colour number, and for proper handling
of dark backgrounds.
2022-12-15 13:53:29 +00:00
8acb84ea7f Rewrite mkhighlight to handle a wider range of colours
Before, it worked by scaling all the colour components, which worked
reasonably for colours in the vicinity of white, but failed badly on a
black background.  Now it generates the highlight and lowlight colours
by mixing the background colour with white and black respectively.
Where there isn't enough headroom, it adjusts the background by mixing
in a negative amount of white or black, which makes sense geometrically
if not in paint.

There is still a problem that green and yellow colours don't end up with
bright enough highlights.  I think this is because the code doesn't
understand that green is brighter than red or blue.
2022-12-14 00:34:41 +00:00
562b29e102 Don't request a highlight colour in games that don't need one
This means that Range, Singles, and Tracks can now use the default
background colour even if it's close to white.  In the case of Singles
I've left a dummy entry in the colour list so as not to renumber the
rest and break everyone's environment variables.  If Singles ever needs
a new colour it can re-use that slot.
2022-12-14 00:34:36 +00:00
712abb7719 Add an assertion that all colours are within range
Because I know I'm going to mess this up at some point.
2022-12-14 00:34:31 +00:00
43bea5f6f2 mkhighlight: Don't darken the base colour if we don't need a highlight
The "mkhighlight" functions can now take -1 as the requested highlight
or lowlight colour as an indication that no such colour should be
returned.  If the caller doesn't want a highlight colour, there's not
much point in darkening the base colour to make it distinct from the
highlight, so don't do that.

This means that the background colours in Palisade and Untangle are no
longer unnecessarily darkened.
2022-12-12 20:17:30 +00:00
676ec87b6d Pearl: make PEARL_GUI_LOOPY affect printed output.
This display style is perfectly playable on paper (proof: it works for
Loopy), so there's no reason not to support both modes in both output
routines.
2022-12-11 18:52:06 +00:00
3150d72800 js: When opening a dialogue box, try to focus it
This will make using menus from the keyboard more convenient.
2022-12-10 21:54:11 +00:00
ebb7b4277e js: Don't treat SoftRight as CURSOR_SELECT2
I was hoping that I could treat SoftLeft and SoftRight the same in C and
arrange to filter one of them out in JavaScript, but that turned out to
be impractical.
2022-12-10 19:07:47 +00:00
9bcb06ee30 js: Add a mode where the puzzle tries to fill the viewport
This is activated by putting the puzzle in an element with id
"puzzlecanvascontain".  In that case, the puzzle's default size is as
close to filling that element as is achievable.  Unlike in the normal
mode, this sets the CSS size of the canvas directly.

Because it might take a little while for the page to settle down after
loading, and because the size of the viewport might change, this listens
for "resize" and "load" events, and only bothers changing anything when
the page is fully loaded.

Waiting for the document to be complete might be a problem if we had
images and so forth that we could plausibly be waiting for, but we
don't.
2022-12-10 18:33:00 +00:00
33b5c48429 js: Add a new function whereby C can ask JS for a preferred board size
Currently JS has no opinion.
2022-12-10 18:33:00 +00:00
14eb35da4a js: Set the default colour from the CSS background of the canvas
This allows the HTML/CSS to decide that it would like a different
background colour without the need to recompile.  The default if the CSS
specifies no colour (and hence the canvas is transparent) is the same
grey as before.
2022-12-10 17:58:41 +00:00
02f1d55a02 js: Allow CSS to set the font used by the puzzle
This means that the calculated font properties of the HTML canvas now
control what font is used.  The size is overridden, and for monospaced
text so is the family.

I'd like to be able to also specify the monospaced font, maybe using a
CSS variable, but that looks like being quite a lot of extra complexity.

My experience when testing this was that constructing a valid "font"
string for a canvas context is prone to breakage, but broke in a way
that left the font unchanged, so we always set a simple specification
first before trying to construct one from CSS.
2022-12-10 15:30:49 +00:00
a3310ab857 New backend function: current_key_label()
This provides a way for the front end to ask how a particular key should
be labelled right now (specifically, for a given game_state and
game_ui).  This is useful on feature phones where it's conventional to
put a small caption above each soft key indicating what it currently
does.

The function currently provides labels only for CURSOR_SELECT and
CURSOR_SELECT2.  This is because these are the only keys that need
labelling on KaiOS.

The concept of labelling keys also turns up in the request_keys() call,
but there are quite a few differences.  The labels returned by
current_key_label() are dynamic and likely to vary with each move, while
the labels provided by request_keys() are constant for a given
game_params.  Also, the keys returned by request_keys() don't generally
include CURSOR_SELECT and CURSOR_SELECT2, because those aren't necessary
on platforms with pointing devices.  It might be possible to provide a
unified API covering both of this, but I think it would be quite
difficult to work with.

Where a key is to be unlabelled, current_key_label() is expected to
return an empty string.  This leaves open the possibility of NULL
indicating a fallback to button2label or the label specified by
request_keys() in the future.

It's tempting to try to implement current_key_label() by calling
interpret_move() and parsing its output.  This doesn't work for two
reasons.  One is that interpret_move() is entitled to modify the
game_ui, and there isn't really a practical way to back those changes
out.  The other is that the information returned by interpret_move()
isn't sufficient to generate a label.  For instance, in many puzzles it
generates moves that toggle the state of a square, but we want the label
to reflect which state the square will be toggled to.  The result is
that I've generally ended up pulling bits of code from interpret_move()
and execute_move() together to implement current_key_label().

Alongside the back-end function, there's a midend_current_key_label()
that's a thin wrapper around the back-end function.  It just adds an
assertion about which key's being requested and a default null
implementation so that back-ends can avoid defining the function if it
will do nothing useful.
2022-12-09 20:48:30 +00:00
1d91522bab tracks: Allow a smaller or non-existent border at small tile sizes
The basic tile size in Tracks is required to be a multiple of 6, which
means that for small tile sizes the steps are rather large.  With the
standard border widths, this means that the default 8-by-8 puzzle can be
246 pixels wide (tilesize == 24) or 184 pixels wide (tilesize == 18).
This is particularly annoying if you happen to have a 240-pixel-wide
screen.

This commit allows the puzzle to reduce or remove the borders at small
tile sizes, on the grounds that a slightly narrower border is acceptable
if it avoids needing to use a smaller tile size.  It encodes the border
width in (tilesize % 6), and is thus enabled when the default border
width is 5 or less.  Above that size (which is a tilesize of 48), I
assume the steps in tile size aren't big enough to be a serious problem.
2022-12-08 13:42:31 +00:00
0d36b471d8 tracks: Make the keyboard cursor more visible
The former grey was almost indistinguishable from its background colours
even on a good screen.  I've separated the cursor colour from the grid
colour and made it a lot darker. This gives a contrast ratio over 3.0
even against a darkened tile.

The cursor is still hard to see against trackwork, so maybe something
that isn't grey would be even better.
2022-12-08 11:54:23 +00:00
0b036c9e79 galaxies: Use the same code for handling all dropped arrows
The keyboard code was prone to adding null items to the undo history,
and was also unreadable.  Rather than fix it, I've replaced it with a
jump to the mouse drop handling, lightly enhanced to reject drops on
things that aren't tiles.
2022-12-07 20:41:49 +00:00
09f2052fbf guess: Much more efficient keyboard interface
Now rather than mucking around with the cursor keys, you can just type a
four-digit number and press Enter.  Of course, if you still want to muck
around with the cursor keys they work the same as before.

Since Backspace was already assigned to clear the peg under the cursor,
I haven't co-opted it for the obvious action of clearing the peg to the
left of the cursor and moving the cursor left.  The left arrow key is a
reasonable alternative anyway.

For consistency, 'L' now labels the pegs with numbers rather than
letters, and is documented.
2022-12-07 00:43:45 +00:00
14b434cb88 guess: Move the cursor to the first peg position after a guess
It's annoying having to move it to the left each time.  I suppose I
could enter the second guess in reverse order, but then I'd need to move
the cursor all the way to the right to submit it, which is just as bad.
2022-12-07 00:38:23 +00:00
a8df0189ff guess: Correct documentation to not say Space places a peg
It sets a hold now, as is mentioned in the next sentence.
2022-12-07 00:38:17 +00:00
7d61c4cee4 js: Explicitly set the height of the status bar
Otherwise it varies depending on whether it has any text in it, which
is distracting.
2022-12-06 21:48:44 +00:00