aboutsummaryrefslogtreecommitdiff
path: root/pattern.c (unfollow)
Commit message (Collapse)Author
2024-07-31Add more configuration parameter lower-bound checks.Franklin Wei
2024-07-31Refactor `button & ~MOD_MASK' as `STRIP_BUTTON_MODIFIERS(button)'.Franklin Wei
This refactors all instances of bitwise-ANDs with `~MOD_MASK'. There is a handful of more complex instances I left unchanged (in cube.c, midend.c, and twiddle.c), since those AND with `~MOD_MASK | MOD_NUM_KEYPAD' or similar. I don't think it's worth writing a macro for those cases. Also document this new macro's usage in devel.but.
2023-08-13Pattern: use new move_cursor() featuresBen Harris
2023-08-09move_cursor(): handle visible flag; return useful valueBen Harris
This adds an extra parameter to move_cursor() that's an optional pointer to a bool indicating whether the cursor is visible. This allows for centralising the common idiom of having the keyboard cursor become visible when a cursor key is pressed. Consistently with the vast majority of existing puzzles, the cursor moves even if it was invisible before, and becomes visible even if it can't move. The function now also returns one of the special constants that can be returned by interpret_move(), so that the caller can correctly return MOVE_UI_UPDATE or MOVE_NO_EFFECT without needing to carefully check for changes itself. Callers are updated only to the extent that they all pass NULL as the new argument. Most of them could now be substantially simplified.
2023-06-16Fix some unused-variable warnings.Simon Tatham
A test-build with a modern clang points out a number of 'set but not used' variables, which clang seems to have got better at recently. In cases where there's conditioned-out or commented-out code using the variable, I've left it in and added a warning-suppressing cast to void. Otherwise I've just deleted the variables.
2023-06-11Rename UI_UPDATE as MOVE_UI_UPDATEBen Harris
All the other constants named UI_* are special key names that can be passed to midend_process_key(), but UI_UPDATE is a special return value from the back-end interpret_move() function instead. This renaming makes the distinction clear and provides a naming convention for future special return values from interpret_move().
2023-04-24Pattern: Reduce row clue spacing if there are lots of themBen Harris
Normally, we put two spaces between row clues, but if there are a lot then even with a smaller font size they might overflow the left edge of the window. To compensate, go down to one space between clues instead of two if there are a lot of them. On my laptop the GTK build demonstrates overflow with "13x1:1//1//1//1//1//1//1/1.1.1.1.1.1.1".
2023-04-24Pattern: switch to small font when there are many row cluesBen Harris
If you have a particularly large number of clues in a row, they can end up falling off the left edge of the window. This used not to be a problem because the rendering code would squash them closer together if necessary. But then I switched to drawing them all as a single string (so that two-digit row clues would get enough space with a large font) and that broke the old mechanism. Now we detect if there are enough clues that our conservative guess at the string length looks like overflowing in the big font, and switch to the small one if necessary. If we had a drawing call to measure a string then we could be cleverer about this, but we don't. This problem can be demonstrated with "7x1:1//1//1//1/1.1.1.1" in the GTK port with the fonts my laptop has. I think overflow can still occur even with a small font, so once I've demonstrated that I'll try to fix it.
2023-04-24Correct a comment in Pattern's clue-drawing codeBen Harris
2023-04-23New backend functions: get_prefs and set_prefs.Simon Tatham
These are similar to the existing pair configure() and custom_params() in that get_prefs() returns an array of config_item describing a set of dialog-box controls to present to the user, and set_prefs() receives the same array with answers filled in and implements the answers. But where configure() and custom_params() operate on a game_params structure, the new pair operate on a game_ui, and are intended to permit GUI configuration of all the settings I just moved into that structure. However, nothing actually _calls_ these routines yet. All I've done in this commit is to add them to 'struct game' and implement them for the functions that need them. Also, config_item has new fields, permitting each config option to define a machine-readable identifying keyword as well as the user-facing description. For options of type C_CHOICES, each choice also has a keyword. These keyword fields are only defined at all by the new get_prefs() function - they're left uninitialised in existing uses of the dialog system. The idea is to use them when writing out the user's preferences into a configuration file on disk, although I haven't actually done any of that work in this commit.
2023-04-21Pass a game_ui to compute_size, print_size and print.Simon Tatham
I'm about to move some of the bodgy getenv-based options so that they become fields in game_ui. So these functions, which could previously access those options directly via getenv, will now need to be given a game_ui where they can look them up.
2023-04-08Don't allow zero clues in PatternBen Harris
Some nonogram implementations allow zero clues so that a row or column with a single zero clue is equivalent to one with no clues, that is it has no black squares in it. Pattern, however, doesn't interpret them like this and treats a puzzle with a zero clue as insoluble, so it's not helpful to permit them. Permitting zero clues also confuses Pattern's memory allocation so that it can suffer a buffer overrun. As an example, before this commit a build with AddressSanitizer would report a buffer overrun with the description "1:0/0.0" because it tries to put two clues in a row that can have a maximum of one.
2023-04-08Make encode_ui() and decode_ui() optional in back-endsBen Harris
The majority of back-ends define encode_ui() to return NULL and decode_ui() to do nothing. This commit allows them to instead specify the relevant function pointers as NULL, in which case the mid-end won't try to call them. I'm planning to add a parameter to decode_ui(), and if I'm going to have to touch every back-end's version of decode_ui(), I may as well ensure that most of them never need to be touched again. And obviously encode_ui() should go the same way for symmetry.
2023-04-06Fall back to <math.h> if <tgmath.h> doesn't work.Simon Tatham
This fixes a build failure introduced by commit 2e48ce132e011e8 yesterday. When I saw that commit I expected the most likely problem would be in the NestedVM build, which is currently the thing with the most most out-of-date C implementation. And indeed the NestedVM toolchain doesn't have <tgmath.h> - but much more surprisingly, our _Windows_ builds failed too, with a compile error inside <tgmath.h> itself! I haven't looked closely into the problem yet. Our Windows builds are done with clang, which comes with its own <tgmath.h> superseding the standard Windows one. So you'd _hope_ that clang could make sense of its own header! But perhaps the problem is that this is an unusual compile mode and hasn't been tested. My fix is to simply add a cmake check for <tgmath.h> - which doesn't just check the file's existence, it actually tries compiling a file that #includes it, so it will detect 'file exists but is mysteriously broken' just as easily as 'not there at all'. So this makes the builds start working again, precisely on Ben's theory of opportunistically using <tgmath.h> where possible and falling back to <math.h> otherwise. It looks ugly, though! I'm half tempted to make a new header file whose job is to include a standard set of system headers, just so that that nasty #ifdef doesn't have to sit at the top of almost all the source files. But for the moment this at least gets the build working again.
2023-04-04Replace <math.h> with <tgmath.h> throughoutBen Harris
C89 provided only double-precision mathematical functions (sin() etc), and so despite using single-precision elsewhere, those are what Puzzles has traditionally used. C99 introduced single-precision equivalents (sinf() etc), and I hope it's been long enough that we can safely use them. Maybe they'll even be faster. Rather than directly use the single-precision functions, though, we use the magic macros from <tgmath.h> that automatically choose the precision of mathematical functions based on their arguments. This has the advantage that we only need to change which header we include, and thus that we can switch back again if some platform has trouble with the new header.
2023-03-22Add an environment variable to control initial cursor visibilityBen Harris
If you define PUZZLES_INITIAL_CURSOR=y, puzzles that have a keyboard cursor will default to making it visible rather than invisible at the start of a new game. Behaviour is otherwise the same, so mouse actions will cause the cursor to vanish and keyboard actions will cause it to appear. It's just the default that has changed. The purpose of this is for use on devices and platforms where the primary or only means of interaction is keyboard-based. In those cases, starting with the keyboard cursor invisible is weird and a bit confusing.
2023-02-18Fix missing statics and #includes on variables.Simon Tatham
After Ben fixed all the unwanted global functions by using gcc's -Wmissing-declarations to spot any that were not predeclared, I remembered that clang has -Wmissing-variable-declarations, which does the same job for global objects. Enabled it in -DSTRICT=ON, and made the code clean under it. Mostly this was just a matter of sticking 'static' on the front of things. One variable was outright removed ('verbose' in signpost.c) because after I made it static clang was then able to spot that it was also unused. The more interesting cases were the ones where declarations had to be _added_ to header files. In particular, in COMBINED builds, puzzles.h now arranges to have predeclared each 'game' structure defined by a puzzle backend. Also there's a new tiny header file gtk.h, containing the declarations of xpm_icons and n_xpm_icons which are exported by each puzzle's autogenerated icon source file and by no-icon.c. Happily even the real XPM icon files were generated by our own Perl script rather than being raw xpm output from ImageMagick, so there was no difficulty adding the corresponding #include in there.
2023-02-13Remember to free the numcolours array from Pattern's drawstateBen Harris
2023-01-31Remove various unused game functionsBen Harris
If can_configure is false, then the game's configure() and custom_params() functions will never be called. If can_solve is false, solve() will never be called. If can_format_as_text_ever is false, can_format_as_text_now() and text_format() will never be called. If can_print is false, print_size() and print() will never be called. If is_timed is false, timing_state() will never be called. In each case, almost all puzzles provided a function nonetheless. I think this is because in Puzzles' early history there was no "game" structure, so the functions had to be present for linking to work. But now that everything indirects through the "game" structure, unused functions can be left unimplemented and the corresponding pointers set to NULL. So now where the flags mentioned above are false, the corresponding functions are omitted and the function pointers in the "game" structures are NULL.
2023-01-15Don't allow negative clues in PatternBen Harris
2023-01-15Integer overflow protection in PatternBen Harris
Both for grid sizes and for clue values.
2023-01-09Fix Pattern row clues when a row has no black inBen Harris
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-02Use a dynamically-sized buffer for Pattern row cluesBen Harris
2023-01-02Adjust font size of Pattern clues based on the numbersBen Harris
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-01Pattern: Pack clues for each row more closely togetherBen Harris
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-01Pattern: Clip clues to their proper rectanglesBen Harris
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().
2022-12-09New backend function: current_key_label()Ben Harris
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.
2021-12-11Pattern: fix a compile warning about memset bounds.Simon Tatham
The argument to memset was being taken from an int variable that not all compilers are able to prove is non-negative. Adding an assert convinces them.
2021-04-25Centralise initial clearing of the puzzle window.Simon Tatham
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.
2020-12-07Add method for frontends to query the backend's cursor location.Franklin Wei
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-05-11Provide visual guide to the cursor location across the rows and columns.Robert Konigsberg
2018-11-13Use C99 bool within source modules.Simon Tatham
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-13Replace TRUE/FALSE with C99 true/false throughout.Simon Tatham
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-13Adopt C99 bool in the game backend API.Simon Tatham
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-04-22Add a request_keys() function with a midend wrapper.Franklin Wei
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.
2017-10-01Return error messages as 'const char *', not 'char *'.Simon Tatham
They're never dynamically allocated, and are almost always string literals, so const is more appropriate.
2017-10-01Use a proper union in struct config_item.Simon Tatham
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-01New name UI_UPDATE for interpret_move's return "".Simon Tatham
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-09-23Pattern: randomise rounding bias in generate().Simon Tatham
Now, with an odd grid size, we choose the posterisation threshold so that half the time it delivers ceil(n/2) black squares and half the time it delivers floor(n/2). Previously it only did the former, which meant that asking Pattern to generate a 1x1 puzzle (with the bug in the previous commit fixed) would always generate the one with a single black square, and never the one with a single white square. Both are trivial to solve, of course, but it seemed inelegant! No change to the number of black squares in the puzzle solution can constitute a spoiler for the player, of course, because that number is trivial to determine without doing any difficult reasoning, just by adding up all the clues in one dimension.
2017-09-23Pattern: missing special case in the solver.Simon Tatham
We were filling in a row immediately as all-white if it had no clues at all, but weren't filling in a row as all-black if it had a single clue covering the entire row. Now we do both. In particular, this caused the Pattern solver to be unable to take advantage of one of the two kinds of totally obvious clue across the _easy_ dimension of a trivial 1xN puzzle - and a special case of _that_, as a user pointed out, is that the game generator hangs trying to create a 1x1 puzzle, which ought to be the easiest thing in the world!
2017-04-26Rework the preset menu system to permit submenus.Simon Tatham
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.
2015-12-12New utility 'patternpicture', to build a Pattern from an xbm.Simon Tatham
This utility works basically the same as galaxiespicture: you feed it a .xbm bitmap on standard input, and it constructs a game ID which solves to exactly that image. It will pre-fill some squares if that's necessary to resolve ambiguity, or leave the grid completely blank if it can.
2015-12-12Pattern: add a system of immutable pre-filled grid squares.Simon Tatham
The game previously only supported numeric clues round the edge; but if for some reason you really want a puzzle with a specific solution bitmap and that bitmap doesn't happen to be uniquely soluble from only its row and column counts, then this gives you a fallback approach of pre-filling a few grid squares to resolve the ambiguities. (This also applies if the puzzle is uniquely soluble *in principle* but not by Pattern's limited solver - for example, Pattern has never been able to solve 4x4:2/1/2/1/1.1/2/1/1 and still can't, but now it can solve 4x4:2/1/2/1/1.1/2/1/1,Ap which has the hard part done for it.) Immutable squares are protected from modification during play, and used as initial information by the solver.
2015-12-12Pattern: fix solver's handling of empty rows.Simon Tatham
The algorithm for deducing how many squares in a row could be filled in just from the initial clue set was focusing solely on _black_ squares, and forgot that if a row has a totally empty clue square then everything in it can be filled in as white! Now the solver can cope with puzzles such as 3x3:/1///1/ , where it would previously have spuriously considered that it had no idea where to start.
2015-12-12Pattern: make part of the game_state shared.Simon Tatham
The game_state now includes a pointer to a game_state_common containing all the row and column clues, which is reference-counted and therefore doesn't have to be physically copied in every dup_game.
2015-10-03Pattern: color multiple squares with Ctrl- or Shift-cursor keys.Jonas Kölker
2015-10-03Add game_text_format to Pattern.Jonas Kölker
2013-04-13Giant const patch of doom: add a 'const' to every parameter in everySimon Tatham
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-12Add 'const' to the game_params arguments in validate_desc andSimon Tatham
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-12Patch from Rogier Goossens to speed up the Pattern solver.Simon Tatham
do_recurse() now prunes early whenever it encounters a branch of the search tree inconsistent with existing grid data (rather than the previous naive approach of proceeding to enumerate all possibilities anyway and then ruling them out one by one); do_recurse also tries to split the row up into independent sections where possible; finally the main solver loop (all three copies of which have now been factored out into a new solve_puzzle function), instead of simply looping round and round over all the rows and columns, heuristically looks at the ones most changed since the last time deduction was attempted on them, on the basis that that will probably yield the most information the fastest. [originally from svn r9828]