aboutsummaryrefslogtreecommitdiff
path: root/guess.c (follow)
Commit message (Collapse)AuthorAge
* Guess: validate peg colours in decode_ui()Ben Harris2023-01-15
| | | | | | | | | | | | | | | | | | | | | | | Peg colours in the current guess must be within the range of colours for the current game, just as they must be for completed moves. Otherwise is_markable() can cause a buffer overrun. Since there's no way for decode_ui() to report an error, it just ignores the bad peg colours. I've also added an assertion to catch this problem in is_markable(). The following save file demonstrates the problem when loaded in a build with AddressSanitizer: SAVEFILE:41:Simon Tatham's Portable Puzzle Collection VERSION :1:1 GAME :5:Guess PARAMS :9:c6p4g10Bm CPARAMS :9:c6p4g10Bm DESC :8:2de917c0 UI :7:7,7,7,7 NSTATES :1:1 STATEPOS:1:1
* Guess: Don't allow any moves once the game is solvedBen Harris2023-01-15
| | | | | | | | | | | | | | | | | | | | | | If the game is solved (either by a win or a loss), interpret_move() can never return a move, but execute_move() should also reject any moves in case we're loading a corrupt or malicious save file. Otherwise a save file with more guesses than the maximum allowed can cause a buffer overrun. This save file demonstrates the problem when loaded into a build of Puzzles with AddressSanitizer: SAVEFILE:41:Simon Tatham's Portable Puzzle Collection VERSION :1:1 GAME :5:Guess PARAMS :9:c6p4g1Bm CPARAMS :9:c6p4g1Bm DESC :8:b5f3faed NSTATES :1:3 STATEPOS:1:3 MOVE :8:G1,1,2,2 MOVE :8:G4,3,1,1
* Guess: Make 'H' key work properly with "Allow duplicates" offBen Harris2022-12-23
| | | | | | | | 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.
* guess: Remove an obsolete workaroundBen Harris2022-12-16
| | | | dup_params() has taken a const argument for some time.
* 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.
* guess: Much more efficient keyboard interfaceBen Harris2022-12-07
| | | | | | | | | | | | | | 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.
* guess: Move the cursor to the first peg position after a guessBen Harris2022-12-07
| | | | | | 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.
* guess: Fix keyboard access to hold functionBen Harris2022-12-05
| | | | | | This has been broken since 2015. It was accidentally using "IS_CURSOR_SELECT(button)" in place of "button == CURSOR_SELECT" and these are not the same thing.
* 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.
* 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.
* 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.
* Add hinting feature to Guess.Jonas Kölker2015-10-14
| | | | | | | | | Pressing H now suggests the lexicographically first row consistent with all previous feedback. The previous function of the H key to toggle a hold marker on the current peg is now performed by Space / CURSOR_SELECT2, which is more in line with other puzzles anyway.
* Fix a misrendering in Guess.Jonas Kölker2015-10-03
| | | | | | When the cursor was visible, redrawing after undo-redo or label toggling or resizing would draw background over the top of the circular cursor.
* Fix a memory error in Guess cursor handling.Jonas Kölker2015-10-03
|
* 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]
* Increase by 1 in every direction the size of the blitter used to saveSimon Tatham2012-04-08
| | | | | | | | the background under a Guess coloured peg in mid-drag. Currently it assumes the circle doesn't extend into the next pixel, which the docs for draw_circle warn might happen due to antialiasing. [originally from svn r9450]
* 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]
* Fix warnings generated by gcc 4.6.0 about variables set but notSimon Tatham2011-05-04
| | | | | | | | | | thereafter read. Most of these changes are just removal of pointless stuff or trivial reorganisations; one change is actually substantive, and fixes a bug in Keen's clue selection (the variable 'bad' was unreferenced not because I shouldn't have set it, but because I _should_ have referenced it!). [originally from svn r9164]
* 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]
* Patch from James H to fix some off-by-one errors in Guess's clickSimon Tatham2009-01-12
| | | | | | rectangle checking, preventing array bounds violation. [originally from svn r8409]
* Patch from James H providing lots more paranoid casting. Also oneSimon Tatham2008-09-13
| | | | | | | | | | actual behaviour change: Untangle now permits dragging with the right mouse button, which has exactly the same effect as it does with the left. (Harmless on desktop platforms, but helpful when "right-click" is achieved by press-and-hold; now the drag takes place even if you hesitate first.) [originally from svn r8177]
* Patch from James H to centralise some generally useful cursor-Simon Tatham2008-09-13
| | | | | | handling functionality into misc.c. [originally from svn r8176]
* 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]
* HTML Help support for Puzzles, with the same kind of automaticSimon Tatham2006-12-24
| | | | | | fallback behaviour as PuTTY's support. [originally from svn r7009]
* Optionally label the colours in Guess with letters of the alphabet.Simon Tatham2006-11-23
| | | | | | | | | | Labels are toggled on and off by pressing L (just like Map). Might help colour-blind users, and might also make it easier to describe game positions to other people because `abbc' has fewer syllables than `red, yellow, yellow, green', and hugely fewer letters if you're typing it. [originally from svn r6916]
* "Hold" function in Guess was completely broken.Jacob Nevins2006-03-03
| | | | | | | | Fix it, add holds to the undo history (by analogy with Net), and save the current holds in saved games. Also fix a couple of unrelated minor issues with string encoding. [originally from svn r6590]
* I've been pondering whether to do this for months: turn the ratherSimon Tatham2006-03-02
| | | | | | | | | | washed-out yellow and green in Guess into their full-brightness pure forms. This makes them hard to see against some backgrounds, so I'm also surrounding all coloured pegs with black outlines. Looks a little cartoony, but I think it's an overall improvement on the previous look. [originally from svn r6589]
* Cleanup: it was absolutely stupid for game_wants_statusbar() to be aSimon Tatham2005-10-22
| | | | | | | | | function, since it took no parameters by which to vary its decision, and in any case it's hard to imagine a game which only _conditionally_ wants a status bar. Changed it into a boolean data field in the backend structure. [originally from svn r6417]
* Cleanup: remove the game_state parameter to game_colours(). No gameSimon Tatham2005-10-22
| | | | | | | | | | | | was actually using it, and also it wasn't being called again for different game states or different game parameters, so it would have been a mistake to depend on anything in that game state. Games are now expected to commit in advance to a single fixed list of all the colours they will ever need, which was the case in practice already and simplifies any later port to a colour-poor platform. Also this change has removed a lot of unnecessary faff from midend_colours(). [originally from svn r6416]
* Cleanup: the `mouse_priorities' field in the back end has been aSimon Tatham2005-10-22
| | | | | | | more general-purpose flags word for some time now. Rename it to `flags'. [originally from svn r6414]
* I've dithered a bit in the past about whether or not it's allowableSimon Tatham2005-09-05
| | | | | | | | | | to call game_set_size() twice on the same drawstate. Finally, a definite decision: it isn't. Accordingly, midend.c arranges never to do so, the devel docs state that puzzles may enforce by assertion that it never happens, and the four puzzles which care (i.e. use blitters) do so. [originally from svn r6274]
* Substantial infrastructure upheaval. I've separated the drawing APISimon Tatham2005-08-18
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | as seen by the back ends from the one implemented by the front end, and shoved a piece of middleware (drawing.c) in between to permit interchange of multiple kinds of the latter. I've also added a number of functions to the drawing API to permit printing as well as on-screen drawing, and retired print.py in favour of integrated printing done by means of that API. The immediate visible change is that print.py is dead, and each puzzle now does its own printing: where you would previously have typed `print.py solo 2x3', you now type `solo --print 2x3' and it should work in much the same way. Advantages of the new mechanism available right now: - Map is now printable, because the new print function can make use of the output from the existing game ID decoder rather than me having to replicate all those fiddly algorithms in Python. - the new print functions can cope with non-initial game states, which means each puzzle supporting --print also supports --with-solutions. - there's also a --scale option permitting users to adjust the size of the printed puzzles. Advantages which will be available at some point: - the new API should permit me to implement native printing mechanisms on Windows and OS X. [originally from svn r6190]
* Another fix from Chris: Guess's allow-blanks mode wasn't allowingSimon Tatham2005-07-18
| | | | | | blanks... [originally from svn r6118]
* game_timing_state() now has access to the game_ui. This means thatSimon Tatham2005-07-10
| | | | | | | | | | | | whether the timer is currently going is no longer solely dependent on the current game_state: it can be dependent on more persistent information stored in the game_ui. In particular, Mines now freezes the timer permanently once you complete a grid for the first time, so that you can then backtrack through your solution process without destroying the information about how long it took you the first time through. [originally from svn r6088]
* Some patches from James H:Simon Tatham2005-07-06
| | | | | | | | | | | | | | - reinstate the initialisation of ds->w and ds->h in guess.c, which I'd accidentally removed during game_size() refactoring - reorganise Net's interpret_move() so that my uncommitted patch for drag-based UI (which he uses on the Palm port) will apply more easily - the interpret_move() changes make it easy to have a single move type which rotates a tile by 180 degrees, so this is now provided via the `F' key (but there's no spare button available to provide it via the mouse). [originally from svn r6070]
* Add a `full' parameter to validate_params(), analogous to the one inJacob Nevins2005-07-05
| | | | | | | | | | | encode_params(). This is necessary for cases where generation-time parameters that are normally omitted from descriptive IDs can place restrictions on other parameters; in particular, when the default value of a relevant generation-time parameter is not the one used to generate the descriptive ID, validation could reject self-generated IDs (e.g., Net `5x2w:56182ae7c2', and some cases in `Pegs'). [originally from svn r6068]
* Refactored the game_size() interface, which was getting reallySimon Tatham2005-07-05
| | | | | | | | | | | | | unpleasant and requiring lots of special cases to be taken care of by every single game. The new interface exposes an integer `tile size' or `scale' parameter to the midend and provides two much simpler routines: one which computes the pixel window size given a game_params and a tile size, and one which is given a tile size and must set up a drawstate appropriately. All the rest of the complexity is handled in the midend, mostly by binary search, so grubby special cases only have to be dealt with once. [originally from svn r6059]
* draw_polygon() and draw_circle() have always had a portabilitySimon Tatham2005-07-03
| | | | | | | | | | | | | | | | | | | constraint: because some front ends interpret `draw filled shape' to mean `including its boundary' while others interpret it to mean `not including its boundary' (and X seems to vacillate between the two opinions as it moves around the shape!), you MUST NOT draw a filled shape only. You can fill in one colour and outline in another, you can fill or outline in the same colour, or you can just outline, but just filling is a no-no. This leads to a _lot_ of double calls to these functions, so I've changed the interface. draw_circle() and draw_polygon() now each take two colour arguments, a fill colour (which can be -1 for none) and an outline colour (which must be valid). This should simplify code in the game back ends, while also reducing the possibility for coding error. [originally from svn r6047]
* Attempting to begin a drag from (i.e. just click on) the hint pegsSimon Tatham2005-06-30
| | | | | | | for a past guess caused strangeness up to and including segfault, thanks to bad bounds checking. Well spotted John Sullivan. [originally from svn r6040]
* When serialising this game, it's probably better to keep theSimon Tatham2005-06-29
| | | | | | half-finished guess in the game_ui rather than throwing it away. [originally from svn r6033]