Compare commits
1 Commits
3a01283358
...
3bc2e09e24
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
3bc2e09e24 |
@@ -1559,17 +1559,10 @@ yet run `DoDaemons(After)`, `DoFuses(After)` or `ringTurnEffects`. Restoring
|
||||
re-enters `playit` at the top of `command` in either case, so the rest of that
|
||||
command never runs — its AFTER daemons and fuses and its ring effects are lost —
|
||||
and the restored game opens with a fresh BEFORE pass on top of the one already
|
||||
in the snapshot: `rollwand`, a live BEFORE daemon once `swander` has fired,
|
||||
ticks again, and any BEFORE fuse is decremented again. Not every consequence of
|
||||
that pass is shared by both service points, though. `visuals` returns
|
||||
immediately unless `g.After`, and `After` is part of the snapshot, so `DVisuals`
|
||||
never re-ticks after a shell-escape save — `shell` sets `g.After = false` as its
|
||||
first statement, before it parks — whereas after a `readchar` save it usually
|
||||
does, because `turnUpkeep` sets `g.After = true` just before the top-of-turn
|
||||
read; the exception is a handler that clears `After` before prompting, as
|
||||
`identifyTrapCommand` does ahead of `promptDirection`. The result is a coherent
|
||||
state one turn's worth of effects off, which is the price of being able to save
|
||||
at all for a player whose line dropped mid-prompt or who is away in a shell.
|
||||
in the snapshot: `rollwand` ticks again, any BEFORE fuse is decremented again.
|
||||
The result is a coherent state one turn's worth of effects off, which is the
|
||||
price of being able to save at all for a player whose line dropped mid-prompt or
|
||||
who is away in a shell.
|
||||
|
||||
The shell escape runs the shell on a helper goroutine so that the game goroutine
|
||||
stays free to answer, but a panic out of `Terminal.ShellEscape` (which is how a
|
||||
|
||||
38
TODO.md
38
TODO.md
@@ -70,25 +70,25 @@ wizard commands).
|
||||
the save, which still reads the old file whole after it. Each was
|
||||
mutation-proved: reverting `AutoSaveOnSignal` to encode on the calling
|
||||
goroutine (the pre-fix behavior) makes the turn-loop test fail under `-race`
|
||||
with over a hundred reports, and removing each of the three service points
|
||||
fails exactly the test for that park with its own message. `pendingSaver` now
|
||||
reads the game out from under its mutex instead of delegating with it held,
|
||||
because the delegated call blocks until the save is taken — the PR #23
|
||||
review's N3 note, load-bearing rather than hypothetical, and pinned by a test.
|
||||
The SIGINT/SIGQUIT no-save decision and the single-signal-read ordering
|
||||
guarantee are untouched; `savesOnSignal`'s third ground ("safety") is
|
||||
rewritten, since the corruption window it weighed no longer exists.
|
||||
`MEMORY.md` stops listing signal-time autosave among the deliberate `_ =`
|
||||
discards and states the new discipline; `ARCHITECTURE.md` §5.3, the `Terminal`
|
||||
sketch, the C-to-Go mapping row and §9's SIGTSTP paragraph are corrected to
|
||||
match. Two things review caught and this entry records so they are not undone:
|
||||
moving the shell onto a helper goroutine also moved `term.Tcell.ShellEscape`'s
|
||||
`panic` on a failed `Screen.Resume` there, and a panic at the top of any
|
||||
goroutine kills the process without running the deferred calls of the others —
|
||||
including `cmd/rogue/main.go`'s `defer t.Fini()`, so the tty would have been
|
||||
left raw on exactly the path where the terminal is already broken (issue #12's
|
||||
failure, reintroduced on a new path). `runShellEscape` recovers the helper's
|
||||
panic and re-raises it on the game goroutine, pinned by
|
||||
with 113 reports, and removing each of the three service points fails exactly
|
||||
the test for that park with its own message. `pendingSaver` now reads the game
|
||||
out from under its mutex instead of delegating with it held, because the
|
||||
delegated call blocks until the save is taken — the PR #23 review's N3 note,
|
||||
load-bearing rather than hypothetical, and pinned by a test. The
|
||||
SIGINT/SIGQUIT no-save decision and the single-signal-read ordering guarantee
|
||||
are untouched; `savesOnSignal`'s third ground ("safety") is rewritten, since
|
||||
the corruption window it weighed no longer exists. `MEMORY.md` stops listing
|
||||
signal-time autosave among the deliberate `_ =` discards and states the new
|
||||
discipline; `ARCHITECTURE.md` §5.3, the `Terminal` sketch, the C-to-Go mapping
|
||||
row and §9's SIGTSTP paragraph are corrected to match. Two things review
|
||||
caught and this entry records so they are not undone: moving the shell onto a
|
||||
helper goroutine also moved `term.Tcell.ShellEscape`'s `panic` on a failed
|
||||
`Screen.Resume` there, and a panic at the top of any goroutine kills the
|
||||
process without running the deferred calls of the others — including
|
||||
`cmd/rogue/main.go`'s `defer t.Fini()`, so the tty would have been left raw on
|
||||
exactly the path where the terminal is already broken (issue #12's failure,
|
||||
reintroduced on a new path). `runShellEscape` recovers the helper's panic and
|
||||
re-raises it on the game goroutine, pinned by
|
||||
`TestShellEscapePanicUnwindsTheGameGoroutine`. And the doc comment took two
|
||||
rounds to get right: the first version claimed in four places that nothing is
|
||||
half-mutated at the `readchar` service point, and the revision that fixed that
|
||||
|
||||
14
game/io.go
14
game/io.go
@@ -174,14 +174,12 @@ func stepOk(ch byte) bool {
|
||||
// save runs here, on the game goroutine, before reading again.
|
||||
//
|
||||
// What that buys is a snapshot taken by the goroutine that owns the
|
||||
// state, so it is internally consistent and restorable. It is never a
|
||||
// between-commands snapshot: readchar is reached from readCommand at the
|
||||
// top of a turn that has already run its BEFORE daemons and turnUpkeep,
|
||||
// and from prompts raised part-way through a command — --More--,
|
||||
// askOverwrite, getStr, the direction and pack prompts — by which point
|
||||
// the command has mutated state as well. See serviceAutoSaveRequest
|
||||
// (save.go) for the full statement of what the handoff guarantees and
|
||||
// what it costs the player.
|
||||
// state, so it is internally consistent and restorable. It is not
|
||||
// necessarily a between-commands snapshot: readchar is also reached from
|
||||
// prompts raised part-way through a command — --More--, askOverwrite,
|
||||
// getStr, the direction and pack prompts — and mutation has already
|
||||
// happened by then. See serviceAutoSaveRequest (save.go) for what that
|
||||
// costs the player.
|
||||
func (g *RogueGame) readchar() byte {
|
||||
for {
|
||||
ch, ok := g.scr.term.ReadChar()
|
||||
|
||||
13
game/save.go
13
game/save.go
@@ -801,18 +801,7 @@ func (g *RogueGame) AutoSaveOnSignal(timeout time.Duration) bool {
|
||||
// fresh BEFORE pass on top of the one already in the snapshot. That
|
||||
// second BEFORE pass is not free: rollwand, a live Before daemon once
|
||||
// swander has fired, ticks again and draws from the RNG every fourth
|
||||
// tick, and any Before fuse is decremented again.
|
||||
//
|
||||
// Not every consequence of that pass is shared by both, though. visuals
|
||||
// returns immediately unless g.After, and After is part of the snapshot,
|
||||
// so DVisuals never re-ticks after a shell-escape save: shell sets
|
||||
// g.After = false as its first statement, before it parks. After a
|
||||
// readchar save it usually does re-tick, because turnUpkeep sets
|
||||
// g.After = true just before the top-of-turn read; the exception is a
|
||||
// handler that clears After before prompting, as identifyTrapCommand
|
||||
// does ahead of promptDirection.
|
||||
//
|
||||
// The result is still a
|
||||
// tick, and any Before fuse is decremented again. The result is still a
|
||||
// coherent game state, one turn's worth of effects off — strictly better
|
||||
// than the torn encode this replaced, and the cost of being able to save
|
||||
// a player whose line dropped mid-prompt, or who is away in a shell, at
|
||||
|
||||
Reference in New Issue
Block a user