149 Commits

Author SHA1 Message Date
a3310ab857 New backend function: current_key_label()
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.
2022-12-09 20:48:30 +00:00
69eca65ef3 Assert that the back-end has provided a background colour
If we're going to refer to a specific colour, it seems appropriate to
insist that it exists.
2022-12-06 13:34:27 +00:00
5157a18550 Extra key mappings: '*' to undo and '#' to redo
This is what I keep expecting on my phone.  Implemented in the mid-end
since no backend currently uses those keys.
2022-11-15 23:48:32 +00:00
2a02547755 Remove a couple of unused variables.
These broke the overnight build, due to -Werror.
2022-11-10 12:37:10 +00:00
4a37f7cf78 Add a way for midend_process_key() to report whether it handled a keypress
This adds a new bool * argument, which can be NULL if front ends don't
care whether the keypress was handled.  Currently they all do that.

Currently, "undo" and "redo" keys are treated as not handled if there's
no move to undo or redo.  This may be a little too strict.
2022-11-08 10:27:19 +00:00
e45cd43aaa Teach the mid-end about device pixel ratios
The device pixel ratio indicates how many physical pixels there are in
the platonic ideal of a pixel, at least approximately.  In Web browsers,
the device pixel ratio is used to represent "retina" displays with
particularly high pixel densities, and also to reflect user-driven
zooming of the page to different text sizes.

The mid-end uses the device pixel ratio to adjust the tile size at
startup, and can also respond to changes in device pixel ratio by
adjusting the time size later.  This is accomplished through a new
argument to midend_size() which can simply be passed as 1.0 in any front
end that doesn't care about this.
2022-11-08 00:57:36 +00:00
373dadacc0 Build fix: take declarations out of for loops.
The NestedVM build is still unhappy with this C99ism, unfortunately.
2022-10-21 07:52:14 +01:00
7f4d038258 Assert that everything written to a save file is printable ASCII
Apart from the newlines of course.
2022-10-20 23:59:05 +01:00
304796f9f1 Hex-encode non-ASCII random seeds in save files
The developer documentation claims that save files are long ASCII
strings.  This is mostly true, but there's nothing stopping a user
from entering non-ASCII characters as random seeds.  The ASCII
property of save files is useful, so encode seeds in hex before
writing them unless they consist only of printable ASCII characters.

Hex-encoded seeds are written under a new key, HEXSEED, to distinguish
them from unencoded seeds.  This means that old versions of the code
won't be able to load encoded seeds, but that's not a great loss:
seeds aren't generally portable between versions anyway.
2022-10-20 23:58:34 +01:00
9f2eef8762 Add assertions that game descriptions consist only of printable ASCII.
That they are ASCII is implied by their inclusion in save files.
Nothing requires an absence of control characters, but it seems polite
to make them slightly readable.
2022-10-20 23:56:43 +01:00
e29d8a3eca Add an assertion to check the format of encoded parameters
Whenever the midend calls encode_params, it also checks that the
result is a printable ASCII string that doesn't contain '#' or ':'.

Parameter strings are embedded in save files, so they have to fit within
ASCII.  They can't contain '#' or ':' because those delimit the
parameter section of a game ID.  Nothing explicitly says they can't
contain control characters, but those would be a particularly egregious
violation of the recommendation that parameter strings be easy to type
into a shell.
2022-10-20 23:54:18 +01:00
1bab1d1d2a Correct and enable the range check on statepos when loading
statepos == 0 shouldn't ever occur in a save file because it indicates
an uninitialised midend.  OTOH statepos == nstates is normal.  Also
added an equivalent assertion when saving because Simon and I spent
some time discussing whether it could happen.
2022-10-16 19:15:40 +01:00
02e5e93046 Add more validation to midend deserialisation routine
These are all pretty obvious and enforce constraints that would
otherwise be enforced by segfault.
2022-10-16 19:02:14 +01:00
2d2d7e8678 Reinsert some missing screen-clears.
I just introduced the 'first_draw' flag in the midend, which should
force a screen clear whenever we draw a puzzle with a fresh drawstate.
But in fact there were several places where the midend replaces the
drawstate and I hadn't set that flag to true.

In particular, a user just reported that when you press 'n' for a new
game in an existing Magnets window, the new puzzle's clues are drawn,
but any old clues in places where the new puzzle doesn't have one is
not _un_drawn. (Because Magnets has no code to undraw a single clue -
it never needs to!)

Added a set of first_draw wherever we call new_drawstate, which should
make this reliable again.
2021-04-27 07:08:08 +01:00
c0da615a93 Centralise initial clearing of the puzzle window.
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.
2021-04-25 13:07:59 +01:00
78bc9ea7f7 Add method for frontends to query the backend's cursor location.
The Rockbox frontend allows games to be displayed in a "zoomed-in"
state targets with small displays. Currently we use a modal interface
-- a "viewing" mode in which the cursor keys are used to pan around
the rendered bitmap; and an "interaction" mode that actually sends
keys to the game.

This commit adds a midend_get_cursor_location() function to allow the
frontend to retrieve the backend's cursor location or other "region of
interest" -- such as the player location in Cube or Inertia.

With this information, the Rockbox frontend can now intelligently
follow the cursor around in the zoomed-in state, eliminating the need
for a modal interface.
2020-12-07 19:40:06 +00:00
7f00725c97 Fix a handful of memory leaks in the midend.
I happened to notice these when running dominosa --generate under Leak
Sanitiser.
2019-04-05 19:29:23 +01:00
5f5b284c0b Use C99 bool within source modules.
This is the main bulk of this boolification work, but although it's
making the largest actual change, it should also be the least
disruptive to anyone interacting with this code base downstream of me,
because it doesn't modify any interface between modules: all the
inter-module APIs were updated one by one in the previous commits.
This just cleans up the code within each individual source file to use
bool in place of int where I think that makes things clearer.
2018-11-13 21:48:24 +00:00
a550ea0a47 Replace TRUE/FALSE with C99 true/false throughout.
This commit removes the old #defines of TRUE and FALSE from puzzles.h,
and does a mechanical search-and-replace throughout the code to
replace them with the C99 standard lowercase spellings.
2018-11-13 21:48:24 +00:00
cd6cadbecf Adopt C99 bool in the midend API.
This changes parameters of midend_size and midend_print_puzzle, the
return types of midend_process_key, midend_wants_statusbar,
midend_can_format_as_text_now and midend_can_{undo,redo}, the 'bval'
field in struct config_item, and finally the return type of the
function pointer passed to midend_deserialise and identify_game.

The last of those changes requires a corresponding fix in clients of
midend_deserialise and identify_game, so in this commit I've also
updated all the in-tree front ends to match. I expect downstream front
ends will need to do the same when they merge this change.
2018-11-13 21:46:39 +00:00
1d9cf25f27 Fix return value from newgame_undo_deserialise_read.
The read function used by midend_deserialise and friends is expected
never to perform a partial read (the main deserialisation code always
knows how many bytes it can expect to see), so it's specified to
return simply TRUE or FALSE for success/failure, rather than the
number of bytes read.

This probably wasn't breaking anything, since in the case of
deserialising from an internal memory buffer a short read could only
arise due to an outright bug constructing the buffer. But now I've
spotted it, I should fix it.
2018-06-21 19:02:21 +01:00
60a929a250 Add a request_keys() function with a midend wrapper.
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.
2018-04-22 17:04:50 +01:00
5247edd16d Forbid undo-of-new-game after midend_set_config.
This is another situation in which the midend's state, at the time
midend_new_game tries to save it, is not such as to generate a viable
serialisation. In this case, it's because after the user enters a game
id into the Game > Specific or Game > Random Seed dialog box,
midend_set_config will have _already_ started overwriting important
fields of the midend such as me->desc and me->seed, before
midend_new_game is even entered.

In fact this caused an assertion failure (thanks to Lennard Sprong for
reporting it), because one of those fields was set to NULL, so the
resulting serialisation buffer was incomplete, leading to a
deserialisation error later. But I was lucky: if I hadn't been, the
serialisation might have been complete, and valid according to the
deserialisation code, but would have contained a mixture of the new
game's description and the old one's move chain, which would surely
have had far stranger results.

For the moment, I'm fixing this by simply not storing a serialisation
in that situation. Perhaps a nicer approach might be to store one
before starting to overwrite midend fields, and then have
midend_new_game swap it in if it's already been generated. That way
you _could_ still undo past an action like this. But preventing the
assertion failure is a good start.
2017-12-09 21:28:41 +00:00
ee8ea9b978 Permit redoing past an undone New Game action.
Now, when we undo a New Game by deserialising the stored version of
the previous game, we start by serialising the _current_ game into a
second serialisation buffer in the midend. Then, if the user tries to
redo back past that undo action, we can re-serialise the earlier game
and re-deserialise the newer one.

A few users had complained (with various degrees of politeness) at the
lack of this ability, because in true xkcd #1172 style, it broke their
workflow. Specifically, if you were a fan of holding down 'u' to undo
all the way back to the start of your current game, you'd have
overshot into the previous game and then have no way to return to the
game you wanted to be at the start of.

This slightly changes the previous interaction of Redo with New Game.
Previously, New Game would save the entire undo chain of the
serialised game, including anything forward of the current position;
so if you took actions move1,move2,undo,newgame then the serialised
game state would include both move1 and move2 with the current
position between them; hence, an undo would restore the old game to a
position just after move1, and then a redo action would re-enact
move2. Now, midend_purge_states is called before serialising the old
game, so in that scenario move2 would be completely lost as a side
effect of the new-game action. (Just as it would be if you made any
_other_ undoable move in that situation.)

Conversely, making a move in the old game after you've undone back
into it will now wipe out the record of the later game, so you can't
redo into it any more.
2017-11-18 20:08:34 +00:00
e2514a72e6 Refactor to make me->newgame_undo a small struct.
The three related buf/len/size fields are now a sub-structure of the
main midend, and the serialise/deserialise functions that address
those fields now take a pointer to that sub-structure rather than to
the midend as a whole. This will make it easy for me to drop in a
second substructure alongside it, for redo, and reuse those read and
write functions by just changing the context pointer.
2017-11-18 20:05:07 +00:00
f6b2f47ef3 Fix assertion failure if you Undo right at startup.
The initial call to midend_new_game() was creating a partial
serialisation containing no game states at all, which meant that if
your first UI action was an undo operation, the game would try to
deserialise that and complain that it was incomplete. Now we detect
that in advance and don't create a useless serialisation in the first
place.
2017-10-06 19:49:05 +01:00
a58c1b216b Make the code base clean under -Wwrite-strings.
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.
2017-10-01 16:35:40 +01:00
3276376d1b Assorted char * -> const char * API changes.
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.
2017-10-01 16:35:00 +01:00
b3243d7504 Return error messages as 'const char *', not 'char *'.
They're never dynamically allocated, and are almost always string
literals, so const is more appropriate.
2017-10-01 16:34:41 +01:00
de67801b0f Use a proper union in struct config_item.
This allows me to use different types for the mutable, dynamically
allocated string value in a C_STRING control and the fixed constant
list of option names in a C_CHOICES.
2017-10-01 16:34:41 +01:00
eeb2db283d New name UI_UPDATE for interpret_move's return "".
Now midend.c directly tests the returned pointer for equality to this
value, instead of checking whether it's the empty string.

A minor effect of this is that games may now return a dynamically
allocated empty string from interpret_move() and treat it as just
another legal move description. But I don't expect anyone to be
perverse enough to actually do that! The main purpose is that it
avoids returning a string literal from a function whose return type is
a pointer to _non-const_ char, i.e. we are now one step closer to
being able to make this code base clean under -Wwrite-strings.
2017-10-01 15:18:14 +01:00
8ea15f3b35 Make newgame_undo_buf 'char *', not 'void *'.
This fixes a compile error under -pedantic at the point where we do
pointer arithmetic on it.
2017-10-01 13:52:16 +01:00
db313b3948 Forbid undo of new-game if it would change the params.
The newgame_undo data was being saved on every call to
midend_new_game, including the one just after midend_set_params when a
new puzzle preset was selected. So you could select a new preset from
the menu, and then press 'u', and the midend would _try_ to undo that
operation and restore the previous game with a different set of
parameters.

This would do the wrong thing in the front end, because front ends in
general will not be expecting that a change of game parameters might
result from an arbitrary keyboard event - they won't be expecting to
have to call the function that moves the highlight in the game-type
menu, for example, and they _certainly_ won't be expecting that a
window resize might be necessary in response to a random keystroke.

One possible response would be to fix all the front ends so that they
_are_ prepared for either of those consequences of a keystroke event,
and then it would be possible to undo not only the New Game menu
option and the 'n' key but also undo any selection of a preset from
the game-type menu, or even a full re-customisation of the game
settings. But that would be quite an upheaval even in _my_ front end
collection, and also probably be awkward for downstream front ends, so
until I'm convinced of the value of going to all the effort, the
simpler approach is just to disallow undoing a new game in those
situations.

(This does mean that re-selecting the _already active_ game preset
from the type menu will be treated as an undoable new-game event,
which I think is an acceptable UI oddity.)
2017-10-01 10:38:30 +01:00
9f6114e272 Style tweaks to the newgame_undo patch.
I've renamed the new midend variables to match my usual naming
convention of using 'size' for the total buffer size and 'len' for the
amount of currently used space (and a couple of other variables to
match those in turn), partly for consistency and also because the name
'midend_undo_used' made me half-expect it to be a boolean. The buffer
itself is called 'midend_undo_buf', again to avoid making it sound
like a function or flag.

Buffer growth is still geometric but less aggressive (factor of 5/4
each time instead of 2), in the hope of wasting less memory on low-RAM
platforms; newgame_undo_deserialise_read should have been static, and
now is; newgame_undo_buf is initialised using NULL rather than 0 so it
doesn't look like an integer, and is freed with the rest of the
midend.

And I think we _should_ enforce by assertion that midend_deserialise
didn't return an error, because there's no reason it ever should in
this situation (unlike when reading from a file, where the user might
have provided the wrong file or a corrupted one). This immediately
allowed me to spot a bug in the existing deserialisation code :-)
2017-10-01 10:38:01 +01:00
b9b73adb53 midend: Allow "new game" to be undone
It is annoying when one intends to choose "restart" and chooses "new
game" instead.  Right now, the puzzle one wanted to try again is
discarded.

To fix this we are going to have to save a lot more information than a
normal game state.  Handily, we already have the serialise/deserialise
machinery.

The advantage of using this is that the previous game is easily saved
in its entirety, including its own undo history, and also probably in
a more compact format.

The (de)serialisation interface is rather clunky for use with a memory
target.  Sadly none of the existing implementations of a resizing
memory array have been conveniently brought out into puzzles.h, and I
think that that's beyond the scope of what I wanted to do here.

We don't serialise the new game undo serialisation data.  So
loading/saving doesn't preserve any "new game" undo, as does "new
game" twice (and as does context switching on a Palm Pilot).

Signed-off-by: Ian Jackson <ijackson@chiark.greenend.org.uk>
2017-10-01 10:38:01 +01:00
9e62c710df midend_deserialise: accept an extra validation function.
This will let me do a 'conditional deserialisation' operation, in
which we fully decode the serialised data and then (assuming that gave
no errors) decide whether or not to actually install it based on some
arbitrary condition.

I don't think there's any possible use for the extra check function
_outside_ midend.c, so I've left the API for front ends as it is; the
externally visible midend_deserialise() doesn't have the new
parameter, and only midend_deserialise_internal() includes it.
2017-10-01 10:38:01 +01:00
c0503d4873 midend_deserialise: keep deserialised data in a struct.
Lots of the local variables in midend_deserialise are now fields of a
structure which contains everything that is _going_ to be written into
the midend once we finish validating it all. This makes it easy to
keep all that data together, and (in future) pass it to other
functions all in one go.

No functional change.
2017-10-01 10:03:50 +01:00
cdf1639531 deserialise: use the right one of {,c}params.
The serialised game stores a long-term and a short-term parameter
structure, which correspond to me->params (the thing that gets used by
the next New Game command) and me->curparams (the thing that _was_
used to generate _this_ game). So data relevant to the current game
ought to be validated against the latter, but in fact I was
accidentally passing the former to several validation calls.

I think this probably avoided causing a problem because typically
params and cparams don't differ very much: the usual reason why
they're not the same is that somebody has manually entered a game
description involving an incomplete description of the parameters
(lacking generation-specific details like difficulty level), but by
the very fact that those incomplete descriptions have to contain
_enough_ information to understand a specific game description,
copying just those parts of the description into the long-term params
structure makes the two similar enough that validation won't fail.

However, testing an upcoming patch which calls midend_deserialise at a
more difficult moment (specifically, just after midend_set_params,
meaning that the two params structures can now differ _arbitrarily_)
reveals my error. Fixed to use cparams where that's the right thing.
2017-10-01 09:51:01 +01:00
e4d05c36d9 Generate special fake keypresses from menu options.
This fixes an amusing UI bug that I think can currently only come up
in the unpublished puzzle 'Group', but there's no reason why other
puzzles _couldn't_ do the thing that triggers the bug, if they wanted
to.

Group has unusual keyboard handling, in that sometimes (when a cell is
selected for input and the key in question is valid for the current
puzzle size) the game's interpret_move function will eat keystrokes
like 'n' and 'u' that would otherwise trigger special UI events like
New Game or Undo.

The bug is that fake keypress events generated from the GUI menus
looked enough like those keystrokes that interpret_move would eat
those too. So if you start, say, a 16x16 Group puzzle, select an empty
cell, and then choose 'new game' from the menu, Group will enter 'n'
into the cell instead of starting a new game!

I've fixed this by inventing a new set of special keystroke values
called things like UI_NEWGAME and UI_UNDO, and having the GUI menus in
all my front ends generate those in place of 'n' and 'u'. So now the
midend can tell the difference between 'n' on the keyboard and New
Game from the menu, and so Group can treat them differently too. In
fact, out of sheer overcaution, midend.c will spot keystrokes in this
range and not even _pass_ them to the game back end, so Group
shouldn't be able to override these special events even by mistake.

One fiddly consequence is that in gtk.c I've had to rethink the menu
accelerator system. I was adding visible menu accelerators to a few
menu items, so that (for example) 'U' and 'R' showed up to the right
of Undo and Redo in the menu. Of course this had the side effect of
making them real functioning accelerators from GTK's point of view,
which activate the menu item in the same way as usual, causing it to
send whatever keystroke the menu item generates. In other words,
whenever I entered 'n' into a cell in a large Group game, this was the
route followed by even a normal 'n' originated from a real keystroke -
it activated the New Game menu item by mistake, which would then send
'n' by mistake instead of starting a new game!

Those mistakes cancelled each other out, but now I've fixed the
latter, I've had to fix the former too or else the GTK front end would
now undo all of this good work, by _always_ translating 'n' on the
keyboard to UI_NEWGAME, even if the puzzle would have wanted to treat
a real press of 'n' differently. So I've fixed _that_ in turn by
putting those menu accelerators in a GtkAccelGroup that is never
actually enabled on the main window, so the accelerator keys will be
displayed in the menu but not processed by GTK's keyboard handling.

(Also, while I was redoing this code, I've removed the logic in
add_menu_item_with_key that reverse-engineered an ASCII value into
Control and Shift modifiers plus a base key, because the only
arguments to that function were fixed at compile time anyway so it's
easier to just write the results of that conversion directly into the
call sites; and I've added the GTK_ACCEL_LOCKED flag, in recognition
of the fact that _because_ these accelerators are processed by a weird
mechanism, they cannot be dynamically reconfigured by users and
actually work afterwards.)
2017-09-20 18:01:52 +01:00
666c528326 Call game_id_change_notify_function after deserialisation.
That's a case in which the current game IDs have changed, so the
midend ought to be calling the front-end function (if any) that
notifies it when that happens.

The only front end of mine that was affected by this missing call was
the Javascript one, which uses that callback to update the 'Link to
this puzzle' links below the game canvas - but, of course, that front
end didn't ever call midend_deserialise until this month, so no wonder
I never noticed before.

(But downstream front ends might be affected too, for all I know.)
2017-09-14 19:06:44 +01:00
cefb84c2db Work around non-compliant sprintf().
Rockbox's sprintf() lacks the ability to left-justify a string. Fixed
by adding a copy_left_justfied() function to misc.c.

This is a new version of this commit, as the previous version broke
saving!
2017-04-30 18:32:36 +01:00
a7dc17c425 Rework the preset menu system to permit submenus.
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.
2017-04-26 21:51:23 +01:00
988b16a319 End victory flash on new game and restart game.
Net provides the best demonstration of why. Complete a game of net,
then press N while the victory flash is playing: then the victory
flash keeps playing on the new game board. (Tip: save a game which
but for a redo is completed, then you can reproduce this repeatedly
without having to complete a new game each time.)

The flash timer reset code is placed together with the animation
timer reset code, because the two are conceptually related. Note
that midend_restart_game resets animations via midend_finish_move.
2015-10-14 20:29:32 +01:00
bf81e9c1fa Reset midend animation counters on starting a new game.
This is already done in midend_restart_game via midend_finish_move.
If it's good enough for restarting a game, it ought to also be good
enough for starting new games.
2015-10-14 20:29:32 +01:00
af010d7283 Remove a redundant line of code.
Setting me->anim_time = 0.0 right before calling midend_finish_move is
redundant, since midend_finish_move itself sets me->anim_time = 0.
2015-10-14 20:29:32 +01:00
f3f0f009ff Don't stop animations when restarting an already restarted game.
Restarting a game that is already in the restarted state is meant to
be a no-op.  It stopped animations.  Don't do this.

Also, given that midmidend_restart_game called midend_stop_anim
twice, the invocation we remove was redundant.
2015-10-14 20:29:32 +01:00
156b0c3e23 Stop animations on a new game, no matter how it is started.
Animations were stopped if a new game was initiated with a keyboard
shortcut (n, N, Ctrl-N), but not via menu items such as presets or
custom configurations, nor (perhaps not a problem) on starting the
program. Fix this, so that animations are stopped on a new game no
matter how the new game is started.
2015-10-14 20:29:32 +01:00
c4198948a8 Fix typo in undo key handling.
Now we can undo with both 'u' and 'U', symmetrically with redoing with
both 'r' and 'R'.
2015-10-03 16:57:49 +01:00
f781937d0d Change the policy for parsing underspecified params strings.
In conversation with a user last week, it emerged that the command
'solo --generate 1 9jk#12345' was giving a different game from the one
it gave when I ran it, and it turns out that this is because I've set
SOLO_DEFAULT=7jxdi in my environment to make GUI Solo automatically
start up in my (current) favourite mode. And the difficulty setting
from that parameter string was being reused to fill in the unspecified
difficulty slot in the '9jk', so that the same params string was being
interpreted differently by our two machines.

This is certainly wrong - the whole point of random seed strings like
that is to be interpreted the same way everywhere. But it's a side
effect of something I did do on purpose, for people switching back and
forth between playing randomly generated games and playing a game id
pasted (or typed) in from elsewhere. So this fix, with a giant comment
explaining it, I _think_ should retain the behaviour I originally
wanted while getting rid of the behaviour I didn't.
2014-11-29 10:23:12 +00:00
120f6de605 Introduce some extra testing and benchmarking command-line options to
the GTK front end, plus a 'make test' target in the GTK makefile which
uses them to automatically generate 100 puzzles for each game at each
preset configuration, test-run them back through the solver without
their aux_info to ensure that can cope, and produce an HTML box plot
of game generation times for each preset.

As part of this work I've removed the TESTSOLVE mechanism from r9549,
since the new --test-solve option does the same thing better (in that
when something goes wrong it prints the random seed that caused the
problem).

[originally from svn r9825]
[r9549 == 5a095b8a08fa9f087b93c86aea0fa027138b028d]
2013-04-11 12:51:06 +00:00