Finish save.go split: header/player halves, drop inline err
This commit is contained in:
137
game/save.go
137
game/save.go
@@ -177,8 +177,48 @@ func (g *RogueGame) packIdx(obj *Object) int {
|
|||||||
|
|
||||||
// snapshot captures the complete game state.
|
// snapshot captures the complete game state.
|
||||||
func (g *RogueGame) snapshot() *SaveState {
|
func (g *RogueGame) snapshot() *SaveState {
|
||||||
p := &g.Player
|
st := g.snapshotHeader()
|
||||||
st := &SaveState{
|
|
||||||
|
// the map, sans monster pointers (rebuilt on load)
|
||||||
|
st.Places = make([]savedPlace, len(g.Level.Places))
|
||||||
|
for i := range g.Level.Places {
|
||||||
|
st.Places[i] = savedPlace{
|
||||||
|
Ch: g.Level.Places[i].Ch,
|
||||||
|
Flags: g.Level.Places[i].Flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// level objects by value; remember their pointers for dest encoding
|
||||||
|
objAt := make(map[*Object]int, len(g.Level.Objects))
|
||||||
|
for i, o := range g.Level.Objects {
|
||||||
|
st.Objects = append(st.Objects, *o)
|
||||||
|
objAt[o] = i
|
||||||
|
}
|
||||||
|
|
||||||
|
st.Player = g.snapshotPlayer()
|
||||||
|
|
||||||
|
// monsters, with chase targets as (kind, index) references
|
||||||
|
for _, m := range g.Level.Monsters {
|
||||||
|
sc := savedCreature{
|
||||||
|
Pos: m.Pos, Turn: m.Turn, Type: m.Type, Disguise: m.Disguise,
|
||||||
|
OldCh: m.OldCh, Flags: m.Flags, Stats: m.Stats,
|
||||||
|
RoomIdx: g.roomIdx(m.Room),
|
||||||
|
}
|
||||||
|
for _, o := range m.Pack {
|
||||||
|
sc.Pack = append(sc.Pack, *o)
|
||||||
|
}
|
||||||
|
|
||||||
|
st.Monsters = append(st.Monsters, sc)
|
||||||
|
st.Dests = append(st.Dests, g.destRefFor(m, objAt))
|
||||||
|
}
|
||||||
|
|
||||||
|
return st
|
||||||
|
}
|
||||||
|
|
||||||
|
// snapshotHeader captures the scalar game state (the field list of
|
||||||
|
// state.c rs_save_file).
|
||||||
|
func (g *RogueGame) snapshotHeader() *SaveState {
|
||||||
|
return &SaveState{
|
||||||
Version: saveFormatVersion,
|
Version: saveFormatVersion,
|
||||||
Seed: g.Rng.Seed,
|
Seed: g.Rng.Seed,
|
||||||
Dnum: g.Dnum,
|
Dnum: g.Dnum,
|
||||||
@@ -226,25 +266,14 @@ func (g *RogueGame) snapshot() *SaveState {
|
|||||||
AllScore: g.AllScore,
|
AllScore: g.AllScore,
|
||||||
Screen: g.scr.Std.Contents(),
|
Screen: g.scr.Std.Contents(),
|
||||||
}
|
}
|
||||||
|
|
||||||
// the map, sans monster pointers (rebuilt on load)
|
|
||||||
st.Places = make([]savedPlace, len(g.Level.Places))
|
|
||||||
for i := range g.Level.Places {
|
|
||||||
st.Places[i] = savedPlace{
|
|
||||||
Ch: g.Level.Places[i].Ch,
|
|
||||||
Flags: g.Level.Places[i].Flags,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// level objects by value; remember their pointers for dest encoding
|
// snapshotPlayer captures the player, equipment as pack indices (the
|
||||||
objAt := make(map[*Object]int, len(g.Level.Objects))
|
// player half of snapshot).
|
||||||
for i, o := range g.Level.Objects {
|
func (g *RogueGame) snapshotPlayer() savedPlayer {
|
||||||
st.Objects = append(st.Objects, *o)
|
p := &g.Player
|
||||||
objAt[o] = i
|
|
||||||
}
|
|
||||||
|
|
||||||
// the player
|
sp := savedPlayer{
|
||||||
st.Player = savedPlayer{
|
|
||||||
Body: savedCreature{
|
Body: savedCreature{
|
||||||
Pos: p.Pos, Turn: p.Turn, Type: p.Type, Disguise: p.Disguise,
|
Pos: p.Pos, Turn: p.Turn, Type: p.Type, Disguise: p.Disguise,
|
||||||
OldCh: p.OldCh, Flags: p.Flags, Stats: p.Stats,
|
OldCh: p.OldCh, Flags: p.Flags, Stats: p.Stats,
|
||||||
@@ -260,25 +289,10 @@ func (g *RogueGame) snapshot() *SaveState {
|
|||||||
MaxStats: p.MaxStats, VfHit: p.VfHit,
|
MaxStats: p.MaxStats, VfHit: p.VfHit,
|
||||||
}
|
}
|
||||||
for _, o := range p.Pack {
|
for _, o := range p.Pack {
|
||||||
st.Player.Body.Pack = append(st.Player.Body.Pack, *o)
|
sp.Body.Pack = append(sp.Body.Pack, *o)
|
||||||
}
|
}
|
||||||
|
|
||||||
// monsters, with chase targets as (kind, index) references
|
return sp
|
||||||
for _, m := range g.Level.Monsters {
|
|
||||||
sc := savedCreature{
|
|
||||||
Pos: m.Pos, Turn: m.Turn, Type: m.Type, Disguise: m.Disguise,
|
|
||||||
OldCh: m.OldCh, Flags: m.Flags, Stats: m.Stats,
|
|
||||||
RoomIdx: g.roomIdx(m.Room),
|
|
||||||
}
|
|
||||||
for _, o := range m.Pack {
|
|
||||||
sc.Pack = append(sc.Pack, *o)
|
|
||||||
}
|
|
||||||
|
|
||||||
st.Monsters = append(st.Monsters, sc)
|
|
||||||
st.Dests = append(st.Dests, g.destRefFor(m, objAt))
|
|
||||||
}
|
|
||||||
|
|
||||||
return st
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// destRefFor encodes a monster's chase target as a (kind, index)
|
// destRefFor encodes a monster's chase target as a (kind, index)
|
||||||
@@ -315,7 +329,32 @@ func (g *RogueGame) destRefFor(m *Monster, objAt map[*Object]int) destRef {
|
|||||||
|
|
||||||
// applySnapshot rebuilds live game state from a snapshot.
|
// applySnapshot rebuilds live game state from a snapshot.
|
||||||
func (g *RogueGame) applySnapshot(st *SaveState) {
|
func (g *RogueGame) applySnapshot(st *SaveState) {
|
||||||
p := &g.Player
|
g.applyHeader(st)
|
||||||
|
|
||||||
|
for i := range g.Level.Places {
|
||||||
|
g.Level.Places[i] = Place{
|
||||||
|
Ch: st.Places[i].Ch,
|
||||||
|
Flags: st.Places[i].Flags,
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// level objects
|
||||||
|
g.Level.Objects = nil
|
||||||
|
for i := range st.Objects {
|
||||||
|
o := st.Objects[i]
|
||||||
|
g.Level.Objects = append(g.Level.Objects, &o)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.applyPlayer(st)
|
||||||
|
g.applyMonsters(st)
|
||||||
|
g.applyDests(st)
|
||||||
|
|
||||||
|
g.scr.Std.SetContents(st.Screen)
|
||||||
|
}
|
||||||
|
|
||||||
|
// applyHeader restores the scalar game state (the field list of
|
||||||
|
// applySnapshot).
|
||||||
|
func (g *RogueGame) applyHeader(st *SaveState) {
|
||||||
g.Rng.Seed = st.Seed
|
g.Rng.Seed = st.Seed
|
||||||
g.Dnum = st.Dnum
|
g.Dnum = st.Dnum
|
||||||
g.Whoami = st.Whoami
|
g.Whoami = st.Whoami
|
||||||
@@ -360,22 +399,12 @@ func (g *RogueGame) applySnapshot(st *SaveState) {
|
|||||||
g.LastScore = st.LastScore
|
g.LastScore = st.LastScore
|
||||||
g.AllScore = st.AllScore
|
g.AllScore = st.AllScore
|
||||||
g.Playing = true
|
g.Playing = true
|
||||||
|
|
||||||
for i := range g.Level.Places {
|
|
||||||
g.Level.Places[i] = Place{
|
|
||||||
Ch: st.Places[i].Ch,
|
|
||||||
Flags: st.Places[i].Flags,
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// level objects
|
// applyPlayer restores the player, resolving equipment pack indices
|
||||||
g.Level.Objects = nil
|
// (the player half of applySnapshot).
|
||||||
for i := range st.Objects {
|
func (g *RogueGame) applyPlayer(st *SaveState) {
|
||||||
o := st.Objects[i]
|
p := &g.Player
|
||||||
g.Level.Objects = append(g.Level.Objects, &o)
|
|
||||||
}
|
|
||||||
|
|
||||||
// the player
|
|
||||||
sp := &st.Player
|
sp := &st.Player
|
||||||
p.Pos = sp.Body.Pos
|
p.Pos = sp.Body.Pos
|
||||||
p.Turn = sp.Body.Turn
|
p.Turn = sp.Body.Turn
|
||||||
@@ -412,11 +441,6 @@ func (g *RogueGame) applySnapshot(st *SaveState) {
|
|||||||
p.NoFood = sp.NoFood
|
p.NoFood = sp.NoFood
|
||||||
p.MaxStats = sp.MaxStats
|
p.MaxStats = sp.MaxStats
|
||||||
p.VfHit = sp.VfHit
|
p.VfHit = sp.VfHit
|
||||||
|
|
||||||
g.applyMonsters(st)
|
|
||||||
g.applyDests(st)
|
|
||||||
|
|
||||||
g.scr.Std.SetContents(st.Screen)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// applyMonsters rebuilds the monster list and its map index from a
|
// applyMonsters rebuilds the monster list and its map index from a
|
||||||
@@ -507,7 +531,8 @@ prompt:
|
|||||||
|
|
||||||
g.FileName = buf
|
g.FileName = buf
|
||||||
|
|
||||||
if err := g.saveFile(g.FileName); err != nil {
|
err := g.saveFile(g.FileName)
|
||||||
|
if err != nil {
|
||||||
g.msg("%s", err.Error())
|
g.msg("%s", err.Error())
|
||||||
|
|
||||||
continue
|
continue
|
||||||
|
|||||||
Reference in New Issue
Block a user