aboutsummaryrefslogtreecommitdiff
path: root/galaxies.c (follow)
Commit message (Collapse)AuthorAge
* Last-ditch grid-size limit for GalaxiesBen Harris2023-01-15
| | | | At least prevent integer overflow when constructing the grid.
* 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.
* galaxies: Use the same code for handling all dropped arrowsBen Harris2022-12-07
| | | | | | | 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.
* Galaxies: store game solution in the aux string.Simon Tatham2021-10-21
| | | | | | | | | Most games store a string in 'aux' during new_game_desc() that saves solve_game() during gameplay from having to reconstruct the solution from scratch. Galaxies had all the facilities available to do that, but apparently just forgot to use them. (Reindents existing code: diff best viewed with whitespace ignored.)
* galaxieseditor: make 'copy to clipboard' give the game id.Simon Tatham2021-05-25
| | | | | | | | | | | | | | | | | | | 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.
* Build a lot of conditioned-out test and helper programs.Simon Tatham2021-05-25
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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)).
* Galaxies: clean up draw/undraw code for dragged arrows.Simon Tatham2021-05-21
| | | | | | | | | | | | | | | | | | | | | 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!
* Galaxies: avoid division by zero in draw_arrow().Simon Tatham2021-05-21
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | 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.
* Galaxies: disallow placing an edge touching a dot.Simon Tatham2021-05-20
| | | | | | | | | 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.
* 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.
* Galaxies: fix assertion failure when adding out-of-bounds association.Franklin Wei2020-12-07
| | | | | | | | | | 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.
* 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.
* Galaxies: prevent creation of empty undo-chain items.Simon Tatham2019-02-18
| | | | | | | | | | | | | | 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.
* Add missing 'static' to game-internal declarations.Simon Tatham2018-11-13
| | | | | | | | | 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.
* 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 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.
* Make the code base clean under -Wwrite-strings.Simon Tatham2017-10-01
| | | | | 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.
* 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.
* Enforce more than one dot in Galaxies puzzles.Chris Boyle2015-09-26
| | | | | | | | 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.
* Handle replacing an existing arrowKevin Lyles2015-05-11
|
* Fix the extra arrow hanging around while moving the opposite existing arrowKevin Lyles2015-05-11
|
* Mark some arguments constantKevin Lyles2015-05-11
|
* Fix the issue with adding only one arrow when the other end was already whiteKevin Lyles2015-05-11
|
* Add/remove the opposite arrow when you let goKevin Lyles2015-05-11
|
* Draw the opposite arrow only while draggingKevin Lyles2015-05-11
|
* Moved all function declarations to the top of the fileKevin Lyles2015-05-11
|
* Use the game_state and space typedefsKevin Lyles2015-05-11
|
* Always use ret instead of state in execute_moveKevin Lyles2015-05-11
|
* Fixed a typo in a commentKevin Lyles2015-05-11
|
* Giant const patch of doom: add a 'const' to every parameter in everySimon Tatham2013-04-13
| | | | | | | | | | | | | | 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]
* Add 'const' to the game_params arguments in validate_desc andSimon Tatham2013-04-12
| | | | | | | | | | | | 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]
* New rule: interpret_move() is passed a pointer to the game_drawstateSimon Tatham2012-09-09
| | | | | | | | | | | | | | | | 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]
* Swap a 'max' for a 'min', fixing an out-of-range colour componentSimon Tatham2012-04-08
| | | | | | being passed to the front end. [originally from svn r9451]
* Changed my mind about midend_is_solved: I've now reprototyped it asSimon Tatham2011-06-19
| | | | | | | | | | | | | | | | 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]
* Add a function to every game backend which indicates whether a gameSimon Tatham2011-04-02
| | | | | | | | | | | 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]
* Memory management and other fixes from James H.Simon Tatham2009-06-17
| | | | [originally from svn r8596]
* Keyboard cursor support in Galaxies, by James H.Simon Tatham2009-01-15
| | | | [originally from svn r8413]
* New infrastructure feature. Games are now permitted to beSimon Tatham2008-09-06
| | | | | | | | | | | | | | | | | | | | | | _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]
* Revise the printing colour framework so that we can explicitlySimon Tatham2008-04-07
| | | | | | | request either of hatching or halftoning, and also choose which to supply as a fallback when printing in colour. [originally from svn r7976]
* Kyle Brazell points out that the completion checker considers aSimon Tatham2007-03-23
| | | | | | | 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]
* My favourite kind of patch, from James H: one which decreases theSimon Tatham2007-03-03
| | | | | | | | | | | | 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]
* Fix problems with arrow UI with non-square grid.Jacob Nevins2007-03-02
| | | | [originally from svn r7355]
* Silliness! Here's a somewhat hacky patch which builds an additionalSimon Tatham2007-03-01
| | | | | | | | | | | | | | | | | 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]
* Cleanup patch from James H: disable the `s' key, which was only inSimon Tatham2007-03-01
| | | | | | there by accident. [originally from svn r7351]
* Bound edge thicknesses below so that they're always thicker than theSimon Tatham2007-03-01
| | | | | | grid lines. [originally from svn r7349]