mirror of
https://github.com/prosolis/gogobee.git
synced 2026-07-16 08:52:42 +00:00
Branching zones G6: dependent surfaces re-keyed on graph nodes
- Harvest tables (expedition + standalone) now keyed by node_id; legacy room-idx entries auto-migrate via read-fallback + drop-on-save. - Narration salts swapped from run.CurrentRoom to narrationCadence(run) (= len(visited_nodes)-1) so flavor pickers survive G9 column drop. - !zone map renders the graph (BFS by PosX/PosY) when the gate is on: ✓/▶/· status, ╳ for locked-only edges, secrets hidden until visited. - Region-boundary hook in graph advance/!zone go updates expedition CurrentRegion + visited list when from/to nodes differ — without burning supplies or retiring runs (the graph IS the run state). Co-Authored-By: Claude Opus 4.7 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -7,6 +7,7 @@ import (
|
||||
"fmt"
|
||||
"log/slog"
|
||||
"math/rand/v2"
|
||||
"strconv"
|
||||
"strings"
|
||||
|
||||
"gogobee/internal/db"
|
||||
@@ -25,28 +26,42 @@ import (
|
||||
// belong to the expedition system. Standalone harvest is the casual
|
||||
// flow: roll d20 vs DC, get yield, decrement node, save.
|
||||
|
||||
// loadStandaloneHarvestNodes reads the run's harvest map and returns the
|
||||
// nodes for the given room. Lazy-seeds from the zone registry on first
|
||||
// access. Caller persists via saveStandaloneHarvestNodes.
|
||||
func loadStandaloneHarvestNodes(runID string, zoneID ZoneID, roomIdx int) ([]HarvestNode, error) {
|
||||
// loadStandaloneHarvestNodes reads the run's harvest map and returns
|
||||
// the nodes for the given graph node. Lazy-seeds from the zone registry
|
||||
// on first access. Caller persists via saveStandaloneHarvestNodes.
|
||||
//
|
||||
// G6 migration: rows written before the re-key used the room-index
|
||||
// integer as the storage key. When the node-id key is absent and the
|
||||
// id maps back to a legacy room index, we read from the old key so
|
||||
// in-flight runs don't lose harvest state. The next save writes under
|
||||
// the new key (and drops the old one).
|
||||
func loadStandaloneHarvestNodes(runID string, zoneID ZoneID, nodeID string) ([]HarvestNode, error) {
|
||||
table, err := loadStandaloneHarvestTable(runID)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
roomKey := roomHarvestKey(roomIdx)
|
||||
roomKey := nodeHarvestKey(nodeID)
|
||||
if existing, ok := table[roomKey]; ok {
|
||||
return existing, nil
|
||||
}
|
||||
if idx, ok := legacyRoomIdxFromNodeID(nodeID, zoneID); ok {
|
||||
if existing, ok := table[strconv.Itoa(idx)]; ok {
|
||||
return existing, nil
|
||||
}
|
||||
}
|
||||
return seedRoomNodes(zoneID), nil
|
||||
}
|
||||
|
||||
// saveStandaloneHarvestNodes writes nodes back into the run's harvest map.
|
||||
func saveStandaloneHarvestNodes(runID string, roomIdx int, nodes []HarvestNode) error {
|
||||
func saveStandaloneHarvestNodes(runID string, zoneID ZoneID, nodeID string, nodes []HarvestNode) error {
|
||||
table, err := loadStandaloneHarvestTable(runID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
table[roomHarvestKey(roomIdx)] = nodes
|
||||
table[nodeHarvestKey(nodeID)] = nodes
|
||||
if idx, ok := legacyRoomIdxFromNodeID(nodeID, zoneID); ok {
|
||||
delete(table, strconv.Itoa(idx))
|
||||
}
|
||||
raw, err := json.Marshal(table)
|
||||
if err != nil {
|
||||
return fmt.Errorf("marshal harvest table: %w", err)
|
||||
@@ -93,8 +108,8 @@ func (p *AdventurePlugin) handleStandaloneHarvest(ctx MessageContext, char *DnDC
|
||||
prettyRoomType(run.CurrentRoomType())))
|
||||
}
|
||||
|
||||
roomIdx := run.CurrentRoom
|
||||
nodes, err := loadStandaloneHarvestNodes(run.RunID, run.ZoneID, roomIdx)
|
||||
nodeID := harvestNodeIDFor(run)
|
||||
nodes, err := loadStandaloneHarvestNodes(run.RunID, run.ZoneID, nodeID)
|
||||
if err != nil {
|
||||
return p.SendDM(ctx.Sender, "Couldn't load harvest state.")
|
||||
}
|
||||
@@ -155,7 +170,7 @@ func (p *AdventurePlugin) handleStandaloneHarvest(ctx MessageContext, char *DnDC
|
||||
b.WriteString(flavor.Pick(flavor.NodeDepleted))
|
||||
}
|
||||
|
||||
if err := saveStandaloneHarvestNodes(run.RunID, roomIdx, nodes); err != nil {
|
||||
if err := saveStandaloneHarvestNodes(run.RunID, run.ZoneID, nodeID, nodes); err != nil {
|
||||
slog.Error("standalone harvest: save nodes", "user", ctx.Sender, "run", run.RunID, "err", err)
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user