aboutsummaryrefslogtreecommitdiff
path: root/unfinished (follow)
Commit message (Collapse)AuthorAge
* Refactor `button & ~MOD_MASK' as `STRIP_BUTTON_MODIFIERS(button)'.Franklin Wei2024-07-31
| | | | | | | | | 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.
* Group: make keyboard play work again.Simon Tatham2023-08-13
| | | | | | | | | It looks as if it's been broken for about nine years, ever since commit 822243de1bc1fc6d introduced the system for drag-selecting a diagonal of squares. The effect of moving the keyboard cursor and then pressing a button was to cause crashes because the ui fields introduced for that system to use (ohx, ohy, odx, ody, odn) were all completely uninitialised.
* Keen, Solo, Towers, Undead, Unequal, Group: new UI preference.Simon Tatham2023-08-13
| | | | | | | | | | | | | | | | | | | | | | | If you're using the mouse to change pencil marks, you have to right-click to pencil-highlight a square, then press a number or letter key to add or remove a highlight. That causes the highlight to vanish again. So adding or removing multiple pencil marks requires a right-click + keypress per mark. Chris's Android port reversed that decision, making the pencil highlight persist so that you could 'click' just once and then press multiple pencil keys. That makes it easier to add lots of highlights, but harder to just remove a single one (click + press + click to remove the highlight), unless you don't mind keeping the highlight around afterwards cluttering up your view. In other words, this is just the sort of thing users might reasonably disagree on. So now we have an organised preferences system, we can let them disagree, and each configure it whichever way they like! This only affects mouse-based play. The keyboard cursor has _always_ worked this way, because it doesn't disappear at all; its behaviour is unchanged, and independent of the new preference.
* move_cursor(): handle visible flag; return useful valueBen Harris2023-08-09
| | | | | | | | | | | | | | | | | 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.
* Rename UI_UPDATE as MOVE_UI_UPDATEBen Harris2023-06-11
| | | | | | | | 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().
* New backend functions: get_prefs and set_prefs.Simon Tatham2023-04-23
| | | | | | | | | | | | | | | | | | | | | | | | 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.
* Pass a game_ui to compute_size, print_size and print.Simon Tatham2023-04-21
| | | | | | | 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.
* Reorganise the dsf API into three kinds of dsf.Simon Tatham2023-04-20
| | | | | | | | | | | | | | | | | | This is preparing to separate out the auxiliary functionality, and perhaps leave space for making more of it in future. The previous name 'edsf' was too vague: the 'e' stood for 'extended', and didn't say anything about _how_ it was extended. It's now called a 'flip dsf', since it tracks whether elements in the same class are flipped relative to each other. More importantly, clients that are going to use the flip tracking must say so when they allocate the dsf. And Keen's need to track the minimal element of an equivalence class is going to become a non-default feature, so there needs to be a new kind of dsf that specially tracks those, and Keen will have to call it. While I'm here, I've renamed the three dsf creation functions so that they start with 'dsf_' like all the rest of the dsf API.
* Remove size parameter from dsf init and copy functions.Simon Tatham2023-04-20
| | | | | | | | | Now that the dsf knows its own size internally, there's no need to tell it again when one is copied or reinitialised. This makes dsf_init much more about *re*initialising a dsf, since now dsfs are always allocated using a function that will initialise them anyway. So I think it deserves a rename.
* Declare all dsfs as a dedicated type name 'DSF'.Simon Tatham2023-04-20
| | | | | | | In this commit, 'DSF' is simply a typedef for 'int', so that the new declaration form 'DSF *' translates to the same type 'int *' that dsfs have always had. So all we're doing here is mechanically changing type declarations throughout the code.
* Use a dedicated free function to free dsfs.Simon Tatham2023-04-20
| | | | | No functional change: currently, this just wraps the previous sfree call.
* Remove an unnecessary extern function declaration.Simon Tatham2023-04-20
| | | | | | | unfinished/separate.c had its own declaration of divvy_rectangle(), duplicating the one in puzzles.h. Probably that was where the declaration originally lived, before I moved it out into the main header.
* Make encode_ui() and decode_ui() optional in back-endsBen Harris2023-04-08
| | | | | | | | | | | | 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.
* Fall back to <math.h> if <tgmath.h> doesn't work.Simon Tatham2023-04-06
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Replace <math.h> with <tgmath.h> throughoutBen Harris2023-04-04
| | | | | | | | | | | | | | | 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.
* Replace a buch of "const static" with "static const"Ben Harris2023-02-18
| | | | C18 section 6.11.5 says that "const static" is obsolescent.
* Mark many more function (and some objects) staticBen Harris2023-02-18
| | | | | | | | | | | | | I noticed commit db3b531e2cab765a00475054d2e9046c9d0437d3 in the history where Simon added a bunch of "static" qualifiers. That suggested that consistently marking internal functions "static" is desirable, so I tried a build using GCC's -Wmissing-declarations, which requires prior declaration (presumed to be in a header file) of all global functions. This commit makes the GTK build clean under GCC's -Wmissing-declarations. I've also adding "static" to a few obviously internal objects, but GCC doesn't complain about those so I certainly haven't got them all.
* latin_solver_alloc: handle clashing numbers in input grid.Simon Tatham2023-02-05
| | | | | | | | | | | | | | | | | | | | | In the setup phase of the centralised latin.c solver, we start by going over the input grid containing already-placed clue numbers, and calling latin_solver_place to enter each on into the solver's data structure. This has the side effect of ruling out each number from the rest of the row and column, and _also_ checking by assertion that the number being placed is not ruled out. Those are a bad combination, because it means that if you give an obviously inconsistent input grid to latin_solver_alloc (e.g. with two identical numbers in a row already), it will fail an assertion. In that situation, you want the solver run as a whole to return diff_impossible so that the error is reported cleanly. This assertion failure could be provoked by giving either Towers or Group a manually-constructed game description inconsistent in that way, and hitting Solve. Worse, it could be provoked during live play in Unequal, by filling in a number clashing with a clue and then pressing 'h' to get hints.
* New backend function: current_key_label()Ben Harris2022-12-09
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Centralise initial clearing of the puzzle window.Simon Tatham2021-04-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Migrate to a CMake-based build system.Simon Tatham2021-03-29
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | This completely removes the old system of mkfiles.pl + Recipe + .R files that I used to manage the various per-platform makefiles and other build scripts in this code base. In its place is a CMakeLists.txt setup, which is still able to compile for Linux, Windows, MacOS, NestedVM and Emscripten. The main reason for doing this is because mkfiles.pl was a horrible pile of unmaintainable cruft. It was hard to keep up to date (e.g. didn't reliably support the latest Visual Studio project files); it was so specific to me that nobody else could maintain it (or was even interested in trying, and who can blame them?), and it wasn't even easy to _use_ if you weren't me. And it didn't even produce very good makefiles. In fact I've been wanting to hurl mkfiles.pl in the bin for years, but was blocked by CMake not quite being able to support my clang-cl based system for cross-compiling for Windows on Linux. But CMake 3.20 was released this month and fixes the last bug in that area (it had to do with preprocessing of .rc files), so now I'm unblocked! CMake is not perfect, but it's better at mkfiles.pl's job than mkfiles.pl was, and it has the great advantage that lots of other people already know about it. Other advantages of the CMake system: - Easier to build with. At least for the big three platforms, it's possible to write down a list of build commands that's actually the same everywhere ("cmake ." followed by "cmake --build ."). There's endless scope for making your end-user cmake commands more fancy than that, for various advantages, but very few people _have_ to. - Less effort required to add a new puzzle. You just add a puzzle() statement to the top-level CMakeLists.txt, instead of needing to remember eight separate fiddly things to put in the .R file. (Look at the reduction in CHECKLST.txt!) - The 'unfinished' subdirectory is now _built_ unconditionally, even if the things in it don't go into the 'make install' target. So they won't bit-rot in future. - Unix build: unified the old icons makefile with the main build, so that each puzzle builds without an icon, runs to build its icon, then relinks with it. - Windows build: far easier to switch back and forth between debug and release than with the old makefiles. - MacOS build: CMake has its own .dmg generator, which is surely better thought out than my ten-line bodge. - net reduction in the number of lines of code in the code base. In fact, that's still true _even_ if you don't count the deletion of mkfiles.pl itself - that script didn't even have the virtue of allowing everything else to be done exceptionally concisely.
* Fix bit rot in the 'unfinished' subdir.Simon Tatham2021-03-29
| | | | | | | | | | | | Several of the source files here won't quite compile any more, because of minor things like const-correctness and the UI_UPDATE change. Now they should all build again (without prejudice to how useful they are once they have built). The biggest change was to remove the fatal() implementation from the standalone path.c, because my new plan is that basically everything that's not linked against a true puzzle frontend will be linked against nullfe.c, which provides that function anyway.
* Add method for frontends to query the backend's cursor location.Franklin Wei2020-12-07
| | | | | | | | | | | | | | | | 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.
* Group: fix assertion failure in Unreasonable generation.Simon Tatham2020-06-09
| | | | | | | Generating the game id 6dui#12345 would cause an assertion failure in a call to latin_solver_place that should never have happened in the first place, because the "return -1" that ought to have prevented it was accidentally inside #ifdef STANDALONE_SOLVER.
* Group: hard-mode identity deduction.Simon Tatham2020-05-23
| | | | | | | | | | | | | | | | | | | | | | | This fills in the deduction feature I mentioned in commit 7acc554805, of determining the identity by elimination, having ruled out all other candidates. In fact, it goes further: as soon as we know that an element can't be the group identity, we rule out every possible entry in its row and column which would involve it acting as a left- or right-identity for any individual element. This noticeably increases the number of puzzles that can be solved at Hard mode without resorting to Unreasonable-level recursion. In a test of 100 Hard puzzles generated with this change, 80 of them are reported as Unreasonable by the previous solver. (One of those puzzles is 12i:m12b9a1zd9i6d10c3y2l11q4r , the example case that exposed the latin.c validation bug described by the previous two commits. That was reported as ambiguous with the validation bug, as Unreasonable with the validation bug fixed, and now it's merely Hard, because this identity-based deduction eliminates the need for recursion.)
* Group: fill in the latin.c validator function.Simon Tatham2020-05-23
| | | | | | | | | This actually fixes the example game id mentioned in the previous commit. Now 12i:m12b9a1zd9i6d10c3y2l11q4r is reported as Unreasonable rather than ambiguous, on the basis that although the solver still recurses and finds two filled grids, the validator throws out the nonsense one at the last minute, leaving only one that's actually legal.
* latin.c: call a user-provided validator function. [NFC]Simon Tatham2020-05-23
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | I've only just realised that there's a false-positive bug in the latin.c solver framework. It's designed to solve puzzles in which the solution is a latin square but with some additional constraints provided by the individual puzzle, and so during solving, it runs a mixture of its own standard deduction functions that apply to any latin-square puzzle and extra functions provided by the client puzzle to do deductions based on the extra clues or constraints. But what happens if the _last_ move in the solving process is performed by one of the latin.c built-in methods, and it causes a violation of the client puzzle's extra constraints? Nothing will ever notice, and so the solver will report that the puzzle has a solution when it actually has none. An example is the Group game id 12i:m12b9a1zd9i6d10c3y2l11q4r . This was reported by 'groupsolver -g' as being ambiguous. But if you look at the two 'solutions' reported in the verbose diagnostics, one of them is arrant nonsense: it has no identity element at all, and therefore, it fails associativity all over the place. Actually that puzzle _does_ have a unique solution. This bug has been around for ages, and nobody has reported a problem. For recursive solving, that's not much of a surprise, because it would cause a spurious accusation of ambiguity, so that at generation time some valid puzzles would be wrongly discarded, and you'd never see them. But at non-recursive levels, I can't see a reason why this bug _couldn't_ have led one of the games to present an actually impossible puzzle believing it to be soluble. Possibly this never came up because the other clients of latin.c are more forgiving of this error in some way. For example, they might all be very likely to use their extra clues early in the solving process, so that the requirements are already baked in by the time the final grid square is filled. I don't know! Anyway. The fix is to introduce last-minute client-side validation: whenever the centralised latin_solver thinks it's come up with a filled grid, it should present it to a puzzle-specific validator function and check that it's _really_ a legal solution. This commit does the plumbing for all of that: it introduces the new validator function as one of the many parameters to latin_solver, and arranges to call it in an appropriate way during the solving process. But all the per-puzzle validation functions are empty, for the moment.
* groupsolver: show working when using -v on ambiguous puzzles.Simon Tatham2020-05-22
|
* Group: fix loop bounds in the solver.Simon Tatham2020-05-20
| | | | | | | | | | | | | | | | | | Applications of the associativity rule were iterating over only n-1 of the group elements, because I started the loops at 1 rather than 0. So the solver was a bit underpowered, and would have had trouble with some perfectly good unambiguous game ids such as 6i:2a5i4a6a1s . (The latin.c system is very confusing for this, because for historical reasons due to its ancestry in Solo, grid coordinates run from 0 to n-1 inclusive, but grid _contents_ run from 1 to n, using 0 as the 'unknown' value. So there's a constant risk of getting confused as to which kind of value you're dealing with.) This solver weakness only affects puzzles in 'identity hidden' mode, because in normal mode, the omitted row and column are those of the group identity, and applications of associativity involving the identity never generate anything interesting.
* Group: add a special deduction about the group identity.Simon Tatham2020-05-20
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | In identity-hidden mode, as soon as you find any table entry that matches the element indexing its row or column (i.e. a product of group elements of the form ab=a or ab=b), then you immediately know which element is the group identity, and you can fill in the rest of its row and column trivially. But the Group solver was not actually able to do this deduction. Proof: it couldn't solve the game id 4i:1d1d1d1, which is trivial if you take this into account. (a^2=a, so a is the identity, and once you fill in ax=xa=x for all x, the rest of the grid is forced.) So I've added dedicated piece of logic to spot the group identity as soon as anything in its row and column is filled in. Now that puzzle can be solved. (A thing that I _haven't_ done here is the higher-level deduction of determining the identity by elimination. Any table entry that _doesn't_ match either its row or column rules out both the row and the column from being the group identity - so as soon as you have enough table entries to rule out all but one element, you know the identity must be the remaining one. At the moment, this is just doing the simple version of the deduction where a single table entry tells you what _is_ the identity.) One slightly tricky part is that because this new identity inference deduction fills in multiple grid entries at a time, it has to be careful to avoid triggering an assertion failure if the puzzle is inconsistent - before filling in each entry, it has to make sure the value it wants to fill in has not been ruled out by something it filled in already. Without that care, an insoluble puzzle can cause the solver to crash - and worse, the same can happen on an insoluble _branch_ of the guesswork-and-backtracking tree in Unreasonable mode. In both cases, the answer is to make sure you detect the problem before hitting the assertion, and return -1 for 'inconsistent puzzle' if you spot it. Then any guesswork branch that ends up in this situation is cleanly abandoned, and we move on to another one.
* unfinished/path: some jottings towards a solver.Simon Tatham2020-05-12
| | | | | | I still don't actually have a solver design, but a recent conversation sent my brain in some more useful directions than I've come up with before, so I might as well at least note it all down.
* Unruly, Group: reference-count the 'immutable' array.Simon Tatham2018-11-13
| | | | | | | | | I noticed this during the bool trawl: both of these games have an array of flags indicating which grid squares are immutable starting clues, and copy it in every call to dup_game, which is completely unnecessary because it doesn't change during play. So now each one lives in a reference-counted structure, as per my usual practice in similar cases elsewhere.
* Add a missing const in unfinished/sokoban.c.Simon Tatham2018-11-13
| | | | | I noticed this when I temporarily enabled compilation of all the unfinished puzzles while doing the bool trawl.
* Use C99 bool within source modules.Simon Tatham2018-11-13
| | | | | | | | | | 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.
* Replace TRUE/FALSE with C99 true/false throughout.Simon Tatham2018-11-13
| | | | | | 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.
* Adopt C99 bool in the game backend API.Simon Tatham2018-11-13
| | | | | | | | | | | 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.
* Add request_keys() to the rest of the unfinished games.Franklin Wei2018-04-24
| | | | | I just realized that only "Group" received the request_keys() field in the game struct for some reason.
* Add a request_keys() function with a midend wrapper.Franklin Wei2018-04-22
| | | | | | | | 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.
* Recipe: centralise dependencies for latin.c.Simon Tatham2018-04-22
| | | | | | | | | | | | | | It's silly to have every puzzle using latin.c separately specify in its .R file the list of additional modules that latin.c depends on, or for that matter to have them all have to separately know how to adjust that for the STANDALONE_SOLVER mode of latin.c. So I've centralised a new pair of definitions into the core Recipe file, called LATIN and LATIN_SOLVER, and now a client of latin.c need only ask for that to get all the necessary dependencies too. Also, while I'm here, I've moved the non-puzzle-specific 'latincheck' test program out of unequal.R into the central Recipe.
* Assorted char * -> const char * API changes.Simon Tatham2017-10-01
| | | | | | I went through all the char * parameters and return values I could see in puzzles.h by eye and spotted ones that surely ought to have been const all along.
* Return error messages as 'const char *', not 'char *'.Simon Tatham2017-10-01
| | | | | They're never dynamically allocated, and are almost always string literals, so const is more appropriate.
* Use a proper union in struct config_item.Simon Tatham2017-10-01
| | | | | | 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.
* New name UI_UPDATE for interpret_move's return "".Simon Tatham2017-10-01
| | | | | | | | | | | | | 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.
* Rework the preset menu system to permit submenus.Simon Tatham2017-04-26
| | | | | | | | | | | | | | | | | | | | 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.
* Put the game summaries from the website into gamedesc.txt.Simon Tatham2015-01-13
| | | | | | More sensible to bring all the pieces of per-puzzle descriptive text together into one place, so they can be easily reused everywhere they're needed.
* Permit selecting a diagonal of squares at once in Group.Simon Tatham2014-12-18
| | | | | | | | | When filling in a cyclic subgroup or one of its cosets, I've often found I wanted to set an entire diagonal to the same thing at once (usually SW-NE, but the other way round too in non-abelian groups), and it's a pain having to do that to each square individually. Restricting multiple selection to diagonals makes it easy to get the selection I really wanted.
* Fix a printf 64-bit-cleanness error.Simon Tatham2013-11-28
| | | | [originally from svn r10098]
* Fix an edge case of divider-obsoletion in Group.Simon Tatham2013-10-09
| | | | | | | | | | | When you drag group elements around, previous dividers are meant to dissolve whenever the same two elements are no longer on each side of it. One case in which this didn't happen was that of dragging an element from the left of a divider to the far right column - the divider became invisible, but would then startlingly reappear if you drag that element back to the left of whatever it was left of before. [originally from svn r10051]
* Faintly highlight the leading diagonal of Group's grid.Simon Tatham2013-10-09
| | | | | | | This makes it easier to spot elements whose square is known, which is useful in turn for identifying subgroups. [originally from svn r10050]
* Add a mechanism to the automake system to allow 'make install' to onlySimon Tatham2013-06-30
| | | | | | install the actual games, not the auxiliary binaries or nullgame. [originally from svn r9887]