aboutsummaryrefslogtreecommitdiff
Commit message (Collapse)AuthorAge
...
* Solo: use new move_cursor() featuresBen Harris2023-08-13
|
* Slant: use new move_cursor() featuresBen Harris2023-08-13
|
* Singles: use new move_cursor() featuresBen Harris2023-08-13
|
* Signpost: use new move_cursor() featuresBen Harris2023-08-13
|
* Rectangles: use new move_cursor() featuresBen Harris2023-08-13
|
* Pattern: use new move_cursor() featuresBen Harris2023-08-13
|
* Palisade: use new move_cursor() featuresBen Harris2023-08-13
|
* Mosaic: use new move_cursor() featuresBen Harris2023-08-13
|
* Mosaic: remove some unused structure membersBen Harris2023-08-13
| | | | | | As far as I could tell, cur_x, cur_y, prev_cur_x, and prev_cur_y in game_drawstate were never used. prev_cur_x and prev_cur_y in game_ui were assigned but never referenced. So they may as well all go.
* Mines: use new move_cursor() featuresBen Harris2023-08-13
|
* Magnets: use new move_cursor() featuresBen Harris2023-08-13
|
* Keen: use new move_cursor() featuresBen Harris2023-08-13
|
* Galaxies: use new move_cursor() featuresBen Harris2023-08-13
|
* Flip: use move_cursor() for cursor movementBen Harris2023-08-13
|
* Flood: use move_cursor() for cursor movementBen Harris2023-08-13
|
* 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.
* Distinguish MOVE_UNUSED from MOVE_NO_EFFECT in Light UpBen Harris2023-08-09
| | | | | | | Light Up is unusual in that clicking outside the grid hides the cursor, so the return value from clicks outside the grid is MOVE_NO_EFFECT or MOVE_UI_UPDATE rather than the more usual MOVE_UNUSED.
* Light Up: use new move_cursor() featuresBen Harris2023-08-09
|
* Dominosa: use new move_cursor() featuresBen Harris2023-08-09
|
* Use move_cursor() for cursor movement in Same GameBen Harris2023-08-09
| | | | No significant behavioural change.
* Appropriately generate MOVE_NO_EFFECT from '\b' in GuessBen Harris2023-08-09
| | | | This is the case that I care about for KaiOS.
* Use move_cursor() for cursor movement in GuessBen Harris2023-08-09
| | | | | This makes interpret_move() properly return MOVE_NO_EFFECT when the cursor can't move, and simplifies the code as well.
* 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.
* Guess: define constants for flags OR'ed into peg coloursBen Harris2023-08-09
|
* Guess: move hold marker upward by two pixelsBen Harris2023-08-08
| | | | | | | | | | | | | | | | | | This means that it now potentially overlaps the peg above it (part of the current guess), rather than potentially overlapping the empty hole below. More importantly, it means that the hold marker is erased by the erasure of the rest of the peg area, so there's no need to explicitly draw absent hold markers in the background colour. That in turn means that absent hold markers don't nibble the tops off all the pegs at some tile sizes. Instead of this fix, I could have properly made the hold markers part of the first row of empty holes, but that would have been rather fiddly and I've long thought that the hold markers were too far from the peg that they're holding. I've also removed part of a comment about the drawing order of hold markers that seems to have been obsolete even before this commit.
* Pearl: re-use a single grid structure when generatingBen Harris2023-08-06
| | | | | | | | | | | | | | Pearl generally has to generate quite a lot of candidate loops before it can find one that makes a viable puzzle. Before this change it generated a new grid structure for each of those candidate loops. The result was that grid_new() accounted for over 5% of the puzzle-generation time. Pulling grid_new() out of the loop-generation loop makes "pearl --generate 100 8x8dt#0" about 6% faster on my laptop, while producing precisely the same output. Most of this change is just renaming the "grid" variable in new_clues() so it doesn't collide with the typedef of the same name.
* Same Game: level-triggered keyboard cursor hidingBen Harris2023-08-01
| | | | | | | | | | | | | | | | | Same Game doesn't want to show the keyboard cursor when the game is in a state where no move is possible. Previously, it did this by having game_changed_state() hide the cursor on entry to such a state. That meant that reaching a dead end and undoing out of it hid the cursor, which was confusing. Now the cursor is hidden in game_redraw() if the game is in a dead-end state without changing the displaysel flag in the game_ui. That way, if you undo out of a dead end, the cursor becomes visible again if it was visible before. This does mean that you can move the cursor in a dead-end state without being able to see where it's going. I think that's tolerable, but maybe the cursor keys should be disabled in that state as well.
* Distinguish MOVE_UNUSED from MOVE_NO_EFFECT in Same GameBen Harris2023-07-31
|
* Same Game: don't hide keyboard cursor on unrecognised keysBen Harris2023-07-31
| | | | | Pressing "undo", for instance, should leave the keyboard cursor visible if it's visible already. Only mouse clicks should hide it.
* Same Game: scale TILE_GAP with tilesizeBen Harris2023-07-31
| | | | | | | | | | | | TILE_GAP represents the gap between the coloured parts of adjacent different-coloured tiles. Rather than a fixed 2 pixels, it's now 1/16 of the tilesize (rounded to nearest). This looks the same at the default tilesize of 32, but behaves better with larger or smaller tilesizes. At tilesizes below 8, the gap disappears altogether, but that seems appropriate: at 7 pixels there's not much space for the inner and outer squares and the cursor, and those are all more important than the gap..
* Flood: don't draw zero-width tile separatorsBen Harris2023-07-30
| | | | | | | | | | Flood's draw_tile() extravagantly uses up to eight rectangles to draw separators around each tile. This could be substantially improved, but a particularly low-hanging optimisation is not do draw them when the separator width is zero. This at least means that Flood completes its initial drawing on my test KaiOS device.
* Same Game: more efficient tile_redrawBen Harris2023-07-30
| | | | | | | | | | | | | | | | | | | | | I've rewritten tile_redraw to reduce the number of calls to draw_rect(). Before, it would generally make five calls to draw_rect() when drawing a tile. Now it makes at most three, and usually two. That's one draw_rect() for each colour that appears in the tile, which is as good as it can get. This reduces the time to draw a large puzzle by about 35% on Firefox 102. This is of significance to me because CanvasRenderingContext2D on my test KaiOS device seems to have a limit on the number of fill() and fillRect() calls that it will tolerate in a short time. This means that if you issue more than 1024 fillRect() calls in rapid succession, the later ones are simply ignored. Same Game's largest preset called draw_rect() so much that it hit this limit. That meant that the right-hand side of the grid didn't get properly drawn when starting a new game. Now that it is less profligate with draw_rect() it fits comfortably within the limit and I get to see the entire grid.
* js: keep colour strings in JavaScript rather than in CBen Harris2023-07-30
| | | | | | | | | | | | | | | The drawing routines in JavaScript used to take pointers to a C string containing a CSS colour name. That meant that JavaScript had to create a new JavaScript string on ever call to a drawing function, which seemed ugly. So now we instead pass colour numbers all the way down into JavaScript and keep an array of JavaScript strings there that can be re-used. The conversion from RGB triples to strings is still done in C, though. This doesn't seem to have fixed either of the bugs I hoped it would, but it does measurably improve drawing performance so I think it's worth doing.
* midend_get_prefs: Don't free memory that we just copied elsewhere.Asher Gordon2023-07-29
| | | | | | | | We were using free_cfg(be_prefs) after we copied be_prefs to all_prefs, but we actually want to use sfree(be_prefs) since we don't want to free each element that has been copied. None of the games so far use string preferences, which is why they haven't been affected by this bug.
* Use the standard game_mkhighlight in Same GameBen Harris2023-07-27
| | | | This should ensure that the cursor is visible on the background.
* Same Game: darken light colours to make keyboard cursor visibleBen Harris2023-07-27
| | | | | | | | | The keyboard cursor in Same Game is white. The default yellow, cyan, and light green were light enough to make the cursor hard to see. I've darkened them all (without changing their hues) so that the cursor is acceptably visible. This doesn't leave an ideal set of colours, but they are at least still adequately distinct from one another.
* Refactor the new icon installation code.Simon Tatham2023-07-14
| | | | | It's horribly repetitive, and we had a list of all the icons' pixel sizes anyway!
* Install the icons to the right location on LinuxEmmanuel Gil Peyrot2023-07-14
| | | | | | | | | | That way, any application displaying the .desktop with its icon will pick the icon size it deems the best one for the current rendering. See the Icon Theme Specification: https://specifications.freedesktop.org/icon-theme-spec/latest/ar01s07.html Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
* Generate more common icon sizesEmmanuel Gil Peyrot2023-07-14
| | | | | | | | | | | | This adds sizes 24×24 (common on Linux desktop, for instance in application bars), as well as 64×64 and 128×128 (common on Linux mobile). I kept the existing border sizes, but using the same one from 44×44 to 96×96 sounds a bit weird, it’d probably be best to revisit them at some point. Signed-off-by: Emmanuel Gil Peyrot <linkmauve@linkmauve.fr>
* grid_edge_bydots_cmpfn: remove dangerous pointer comparison.Simon Tatham2023-07-14
| | | | | | | | | | | Commit e6cdd70df867f06 made the grid_dot structures for a grid no longer be elements of the same array. But I didn't notice that grid_edge_bydots_cmpfn was doing pointer subtraction on them on the assumption that they were. Fixed by comparing the dots' new index fields, which should correspond exactly to their previous positions in the single array, so the behaviour should be just what it was before the change.
* osx.m: avoid division by zero in startConfigureSheet.Simon Tatham2023-07-13
| | | | | | | | | | | | | | | | | | | | | When we set up a configuration sheet, we track the minimum overall width that the controls will fit into (in a variable 'totalw'), and separately, the minimum width needed by each of the left and right columns containing control labels and actual controls ('leftw' and 'rightw'). If totalw > leftw+rightw at the end of the process, then we must expand the two columns so that they have the right sum. However, sometimes leftw+rightw can be zero, while totalw > 0. This occurs if _no_ control in the box was of a type that used the left and right columns for different things, so that the entire loop over the controls only incremented totalw, and not leftw or rightw. For example, in a puzzle such as Cube that defines no preferences of its own, the only control in the preferences pane is midend.c's standard "Keyboard shortcuts without Ctrl" preference, which is C_BOOLEAN and only uses totalw. In that situation, the code for proportionate distribution of the excess divides by zero. So it needs a special case.
* grid.c: new and improved Penrose tiling generator.Simon Tatham2023-07-07
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | The new generator works on the same 'combinatorial coordinates' system as the more recently written Hats and Spectre generators. When I came up with that technique for the Hats tiling, I was already tempted to rewrite the Penrose generator on the same principle, because it has a lot of advantages over the previous technique of picking a randomly selected patch out of the subdivision of a huge starting tile. It generates the exact limiting distribution of possible tiling patches rather than an approximation based on how big a tile you subdivided; it doesn't use any overly large integers or overly precise floating point to suffer overflow or significance loss, because it never has to even _think_ about the coordinates of any point not in the actual output area. But I resisted the temptation to throw out our existing Penrose generator and move to the shiny new algorithm, for just one reason: backwards compatibility. There's no sensible way to translate existing Loopy game IDs into the new notation, so they would stop working, unless we kept the old generator around as well to interpret the previous system. And although _random seeds_ aren't guaranteed to generate the same result from one build of Puzzles to the next, I do try to keep existing descriptive game IDs working. So if we had to keep the old generator around anyway, it didn't seem worth writing a new one... ... at least, until we discovered that the old generator has a latent bug. The function that decides whether each tile is within the target area, and hence whether to make it part of the output grid, is based on floating-point calculation of the tile's vertices. So a change in FP rounding behaviour between two platforms could cause them to interpret the same grid description differently, invalidating a Loopy game on that grid. This is _unlikely_, as long as everyone uses IEEE 754 double, but the C standard doesn't actually guarantee that. We found this out when I started investigating a slight distortion in large instances of Penrose Loopy. For example, the Loopy random seed "40x40t11#12345", as of just before this commit, generates a game description beginning with the Penrose grid string "G-4944,5110,108", in which you can see a star shape of five darts a few tiles down the left edge, where two of the radii of the star don't properly line up with edges in the surrounding shell of kites that they should be collinear with. This turns out to be due to FP error: not because _double precision_ ran out, but because the definitions of COS54, SIN54, COS18 and SIN18 in penrose.c were specified to only 7 digits of precision. And when you expand a patch of tiling that large, you end up with integer combinations of those numbers with coefficients about 7 digits long, mostly cancelling out to leave a much smaller output value, and the inaccuracies in those constants start to be noticeable. But having noticed that, it then became clear that these badly computed values were also critical to _correctness_ of the grid. So they can't be fixed without invalidating old game IDs. _And_ then we realised that this also means existing platforms might disagree on a game ID's validity. So if we have to break compatibility anyway, we should go all the way, and instead of fixing the old system, introduce the shiny new system that gets all of this right. Therefore, the new penrose.c uses the more reliable combinatorial-coordinates system which doesn't deal in integers that large in the first place. Also, there's no longer any floating point at all in the calculation of tile vertex coordinates: the combinations of 1 and sqrt(5) are computed exactly by the n_times_root_k function. So now a large Penrose grid should never have obvious failures of alignment like that. The old system is kept for backwards compatibility. It's not fully reliable, because that bug hasn't been fixed - but any Penrose Loopy game ID that was working before on _some_ platform should still work on that one. However, new Penrose Loopy game IDs are based on combinatorial coordinates, computed in exact arithmetic, and should be properly stable. The new code looks suspiciously like the Spectre code (though considerably simpler - the Penrose coordinate maps are easy enough that I just hand-typed them rather than having an elaborate auxiliary data-generation tool). That's because they were similar enough in concept to make it possible to clone and hack. But there are enough divergences that it didn't seem like a good idea to try to merge them again afterwards - in particular, the fact that output Penrose tiles are generated by merging two triangular metatiles while Spectres are subdivisions of their metatiles.
* grid.c: add dot coordinates to debugging dumps.Simon Tatham2023-07-07
| | | | | | | I wanted these in order to try to check whether all the faces of a grid were being traversed in the right orientation. That turned out not to be the cause of my problem, but it's still useful information to put in diagnostics.
* grid.c: allocate face/edge/dot arrays incrementally.Simon Tatham2023-07-07
| | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | | Previously, the 'faces', 'edges' and 'dots' arrays in a grid structure were arrays of actual grid_face, grid_edge and grid_dot structures, physically containing all the data about the grid. But they also referred to each other by pointers, which meant that they were hard to realloc larger (you'd have to go through and rewrite all the pointers whenever the base of an array moved). And _that_ meant that every grid type had to figure out a reasonably good upper bound on the number of all those things it was going to need, so that it could allocate those arrays the right size to begin with, and not have to grow them painfully later. For some grid types - particularly the new aperiodic ones - that was actually a painful part of the job. So I think enough is enough: counting up how much memory you're going to need before using it is a mug's game, and we should instead realloc on the fly. So now g->faces, g->edges and g->dots have an extra level of indirection. Instead of being arrays of actual structs, they're arrays of pointers, and each struct in them is individually allocated. Once a grid_face has been allocated, it never moves again, even if the array of pointers changes size. The old code had a common idiom of recovering the array index of a particular element by subtracting it from the array base, e.g. writing 'f - g->faces' or 'e - g->edges'. To make that lookup remain possible, I've added an 'index' field to each sub-structure, which is initialised at the point where we decide what array index it will live at. This should involve no functional change, but the code that previously had to figure out max_faces and max_dots up front for each grid type is now completely gone, and nobody has to solve those problems in advance any more.
* Move mul_root3 out into misc.c and generalise it.Simon Tatham2023-07-07
| | | | I'm going to want to reuse it for sqrt(5) as well as sqrt(3) soon.
* js: Copy-to-clipboard supportBen Harris2023-07-05
| | | | | | | | | | | | | | Now using the browser's "copy" operation while the focus is in the puzzle will copy the puzzle state to the clipboard. Browsers seem to have odd ideas about whate element to target with the "copy" event: Firefox targets the parent of the <canvas> while Chromium targets the <body>. To cope with these and possible future weirdness I attach the event handler to the document and then look to see if it's plausibly related to the canvas. Arguably we might want to handle a wider range of "copy" events, maybe any where the selection isn't empty. I'm not sure, though, so we'll start with the minimal change.
* Add user preference for Bridges' "G" key (show_hints)Ben Harris2023-06-26
| | | | | | | | | | I missed this in my previous addition of preferences for UI controls (4227ac1fd5dc25c247e7526526079b85e1890766) because it wasn't documented. Now it is documented and it has a preference. I've phrased it as showing possible bridge locations, which doesn't really make clear that "possible" relates only to the locations of islands and not to anything already placed. Improvements welcome!
* Bridges: remove a comment for a deleted line of codeBen Harris2023-06-26
| | | | The line was deleted in 5027095ce2a6dd844ce10489c91dc08bbc174a19.
* Fix control-character generation fixBen Harris2023-06-26
| | | | | | | The change I made in c224416c76e41f284b318adc51f08c3ed11de8e2 was incorrect: I accidentally removed a "return" statement and left in a debugging printf() when I meant to keep the return and drop the printf().