diff options
Diffstat (limited to 'internal/game/cmd_verbs.go')
| -rw-r--r-- | internal/game/cmd_verbs.go | 117 |
1 files changed, 68 insertions, 49 deletions
diff --git a/internal/game/cmd_verbs.go b/internal/game/cmd_verbs.go index d13b803..5cbbd5f 100644 --- a/internal/game/cmd_verbs.go +++ b/internal/game/cmd_verbs.go @@ -45,28 +45,23 @@ var alwaysAvailable = []string{ "drop", } -func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { - p := sess.Player - // A seated casino player has no room verbs: the only valid commands are - // the game's live hints, so what/verbs shows those instead of exits and - // objects that cannot be used mid-hand. - if g.Casino != nil { - if table, playing := g.Casino.Participation(p.Name); playing { - if table != nil { - g.showCasinoHints(sess, table.Hints(p.Name)) - } else if machine, ok := g.Casino.MachineFor(p.Name); ok { - g.showCasinoHints(sess, machine.Hints()) - } - return - } - } - showAll := len(args) == 1 && strings.ToLower(args[0]) == "all" +// roomCommandSections holds the interactable commands advertised for the +// player's current room, before rendering. It is shared by the verbs display +// and by prefix resolution, so an abbreviation can only beat a same-prefix +// rival when the player can actually use it here. +type roomCommandSections struct { + objects []string + mobs []string + exits []string + ground []string +} +// collectRoomCommands builds the room's object, mob, exit and ground command +// listings without writing anything to the session. +func (g *Game) collectRoomCommands(sess *net.Session) roomCommandSections { + p := sess.Player + var rc roomCommandSections seen := make(map[string]bool) - var sectionObjs []string - var sectionMobs []string - var sectionExits []string - var sectionGround []string for _, st := range g.World.AllObjInstances(p.RoomID) { def, _, err := g.resolveObjectDef(p.RoomID, st.DefID) @@ -80,25 +75,25 @@ func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { if bt == "gather" && def.Gather != nil { for verb, skill := range verbSkill { if strings.EqualFold(def.Gather.Skill, skill) { - addUnique(§ionObjs, &seen, verb+" "+name) + addUnique(&rc.objects, &seen, verb+" "+name) } } } if bt == "talk" { - addUnique(§ionObjs, &seen, "talk "+name) + addUnique(&rc.objects, &seen, "talk "+name) } for _, ui := range def.OnUse { if ui.ItemID == "" && (ui.Condition == nil || g.checkCondition(sess, ui.Condition)) { - addUnique(§ionObjs, &seen, "use "+name) + addUnique(&rc.objects, &seen, "use "+name) break } } recipes := g.stationRecipes(p, def.ID) if len(recipes) > 0 { - addUnique(§ionObjs, &seen, "use "+name) + addUnique(&rc.objects, &seen, "use "+name) for _, r := range recipes { c := r.FirstCraft() key := c.Subtype @@ -107,13 +102,13 @@ func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { } if info, ok := productionTypes[key]; ok { if info.ActionType != behavior.TypeCombine && info.ActionType != behavior.TypeFletch && info.ActionType != behavior.TypeMix { - addUnique(§ionObjs, &seen, string(info.ActionType)) + addUnique(&rc.objects, &seen, string(info.ActionType)) } } for _, c := range r.FirstCraft().Ingredients { for _, itemID := range c.Items { if itemDef, err := g.ItemStore.Load(itemID); err == nil { - addUnique(§ionObjs, &seen, "use "+itemDef.Name+" on "+name) + addUnique(&rc.objects, &seen, "use "+itemDef.Name+" on "+name) } } } @@ -123,31 +118,31 @@ func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { for _, ui := range def.OnUse { if ui.ItemID != "" && (ui.Condition == nil || g.checkCondition(sess, ui.Condition)) { if itemDef, err := g.ItemStore.Load(ui.ItemID); err == nil { - addUnique(§ionObjs, &seen, "use "+itemDef.Name+" on "+name) + addUnique(&rc.objects, &seen, "use "+itemDef.Name+" on "+name) } } } if def.Steal != nil && len(def.Steal.Drops) > 0 { - addUnique(§ionObjs, &seen, "steal "+name) + addUnique(&rc.objects, &seen, "steal "+name) } - addUnique(§ionObjs, &seen, "look "+name) + addUnique(&rc.objects, &seen, "look "+name) } for _, m := range g.MobStore.MobsInRoom(p.RoomID) { mName := strings.ToLower(m.Name) if !m.Protected { - addUnique(§ionMobs, &seen, "attack "+mName) + addUnique(&rc.mobs, &seen, "attack "+mName) } if m.IsTalkable() { - addUnique(§ionMobs, &seen, "talk "+mName) + addUnique(&rc.mobs, &seen, "talk "+mName) } if len(m.StealDrops) > 0 { - addUnique(§ionMobs, &seen, "steal "+mName) + addUnique(&rc.mobs, &seen, "steal "+mName) } - addUnique(§ionMobs, &seen, "look "+mName) + addUnique(&rc.mobs, &seen, "look "+mName) } if room, err := g.World.LoadRoom(p.RoomID); err == nil { @@ -163,7 +158,7 @@ func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { exitDirs = append(exitDirs, string(dir)) } if len(exitDirs) > 0 { - sectionExits = append(sectionExits, strings.Join(exitDirs, ", ")) + rc.exits = append(rc.exits, strings.Join(exitDirs, ", ")) } } @@ -171,42 +166,66 @@ func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { if len(ground) > 0 { for itemID := range ground { if def, err := g.ItemStore.Load(itemID); err == nil { - addUnique(§ionGround, &seen, "get "+def.Name) + addUnique(&rc.ground, &seen, "get "+def.Name) } } - addUnique(§ionGround, &seen, "get all") + addUnique(&rc.ground, &seen, "get all") } - if info := g.CourseStore.GetObstacle(p.RoomID); info != nil { - addUnique(§ionGround, &seen, info.Verb) + if g.CourseStore != nil { + if info := g.CourseStore.GetObstacle(p.RoomID); info != nil { + addUnique(&rc.ground, &seen, info.Verb) + } } if g.canUseBank(p) { - addUnique(§ionObjs, &seen, "bank") + addUnique(&rc.objects, &seen, "bank") } if g.findTerminalInRoom(p.RoomID) != "" { - addUnique(§ionObjs, &seen, "jack") + addUnique(&rc.objects, &seen, "jack") } - hasRoomCmds := len(sectionObjs) > 0 || len(sectionMobs) > 0 || len(sectionExits) > 0 || len(sectionGround) > 0 + return rc +} + +func (g *Game) executeVerbs(sess *net.Session, args []string, rawInput string) { + p := sess.Player + // A seated casino player has no room verbs: the only valid commands are + // the game's live hints, so what/verbs shows those instead of exits and + // objects that cannot be used mid-hand. + if g.Casino != nil { + if table, playing := g.Casino.Participation(p.Name); playing { + if table != nil { + g.showCasinoHints(sess, table.Hints(p.Name)) + } else if machine, ok := g.Casino.MachineFor(p.Name); ok { + g.showCasinoHints(sess, machine.Hints()) + } + return + } + } + showAll := len(args) == 1 && strings.ToLower(args[0]) == "all" + + rc := g.collectRoomCommands(sess) + + hasRoomCmds := len(rc.objects) > 0 || len(rc.mobs) > 0 || len(rc.exits) > 0 || len(rc.ground) > 0 if hasRoomCmds { - if len(sectionObjs) > 0 { + if len(rc.objects) > 0 { sess.WriteLine("Objects:") - writeCmdLines(sess, sectionObjs) + writeCmdLines(sess, rc.objects) } - if len(sectionMobs) > 0 { + if len(rc.mobs) > 0 { sess.WriteLine("Mobs:") - writeCmdLines(sess, sectionMobs) + writeCmdLines(sess, rc.mobs) } - if len(sectionExits) > 0 { + if len(rc.exits) > 0 { sess.WriteLine("Exits:") - writeCmdLines(sess, sectionExits) + writeCmdLines(sess, rc.exits) } - if len(sectionGround) > 0 { + if len(rc.ground) > 0 { sess.WriteLine("Ground:") - writeCmdLines(sess, sectionGround) + writeCmdLines(sess, rc.ground) } } else { sess.WriteLine("There is nothing notable to interact with here.") |
