Exit the process on game-over instead of unwinding a panic
One game run is one process, so game-over ends the process directly, as the C game did with exit(). myExit now restores the terminal (via the new Terminal.Fini) and calls os.Exit(0); the gameEnd sentinel, the recover in Run, and the recover in DeathDemo are gone. Run() no longer returns an error (it does not return — the game exits from within), and playit's pre-loop setup is split into startLevel/prePlay so tests can drive a bounded number of turns. Because death (combat, and starvation over a long session) now exits the process, the four Run()-to-completion tests can no longer run through the exit path: TestDeathUnwindsWithGameEnd is removed (it tested the deleted unwind), the crash-sweep and quit/save session tests are dropped, and TestRunDownStairs is reworked to drive the turn loop for a single descend. Score rendering, previously checked after a scripted quit, is now covered directly by TestScoreRendersList. Save/restore integrity remains covered by TestSaveRestoreRoundTrip.
This commit is contained in:
30
game/rip.go
30
game/rip.go
@@ -2,23 +2,20 @@ package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"os"
|
||||
"time"
|
||||
)
|
||||
|
||||
// rip.c — the fun ends: death or a total win.
|
||||
//
|
||||
// The C functions here call exit(); the port panics with a gameEnd sentinel
|
||||
// that Run recovers, so the terminal is restored by normal unwinding.
|
||||
// The C functions here call exit(). One game run is one process, so the
|
||||
// port does the same: myExit restores the terminal and exits directly.
|
||||
|
||||
// gameEnd is the sentinel carried by the panic that replaces my_exit().
|
||||
type gameEnd struct{}
|
||||
|
||||
// myExit leaves the process properly (main.c my_exit): it unwinds to Run.
|
||||
// Every C caller exited with status 0; abnormal exits panic for real.
|
||||
// myExit leaves the process properly (main.c my_exit): it restores the
|
||||
// terminal and ends the process. Every C caller exited with status 0.
|
||||
func (g *RogueGame) myExit() {
|
||||
g.Playing = false
|
||||
|
||||
panic(gameEnd{})
|
||||
g.scr.Fini()
|
||||
os.Exit(0)
|
||||
}
|
||||
|
||||
// death does something really fun when he dies (rip.c death).
|
||||
@@ -255,18 +252,9 @@ func (g *RogueGame) killname(monst byte, doart bool) string {
|
||||
}
|
||||
|
||||
// DeathDemo implements the -d command line option (main.c): burn some
|
||||
// random numbers to break patterns, then die a random death.
|
||||
// random numbers to break patterns, then die a random death. It does not
|
||||
// return — death exits the process.
|
||||
func (g *RogueGame) DeathDemo() {
|
||||
defer func() {
|
||||
if r := recover(); r != nil {
|
||||
if _, ok := r.(gameEnd); ok {
|
||||
return
|
||||
}
|
||||
|
||||
panic(r)
|
||||
}
|
||||
}()
|
||||
|
||||
dnum := g.rnd(100)
|
||||
for dnum--; dnum > 0; dnum-- {
|
||||
g.rnd(100)
|
||||
|
||||
Reference in New Issue
Block a user