Documentation ¶
Overview ¶
Package game implements game state and advancement.
Index ¶
- Variables
- func IsDetail(t Targetable) bool
- func IsEgress(t Targetable) bool
- func IsItem(t Targetable) bool
- func IsNPC(t Targetable) bool
- type Conversation
- type Detail
- type DialogAction
- type DialogStep
- type Egress
- type IODevice
- type Inventory
- type Item
- type NPC
- type Pathfinder
- type PronounSet
- type Room
- func (room Room) Copy() Room
- func (room Room) GetDetailByAlias(alias string) *Detail
- func (room Room) GetEgressByAlias(alias string) *Egress
- func (room Room) GetItemByAlias(alias string) *Item
- func (room Room) GetNPCByAlias(alias string) *NPC
- func (room Room) GetTargetable(alias string) (t Targetable)
- func (room *Room) RemoveItem(label string)
- func (room Room) String() string
- type Route
- type RouteAction
- type State
- func (gs *State) Advance(cmd command.Command) error
- func (gs *State) ExecuteCommandDebug(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandDrop(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandExits(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandGo(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandHelp(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandInventory(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandLook(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandTake(cmd command.Command) (string, error)
- func (gs *State) ExecuteCommandTalk(cmd command.Command) (string, error)
- func (gs *State) Expand(s *tunascript.Template) string
- func (gs *State) GetNPCInfo(label string) (string, error)
- func (gs *State) ListFlags() string
- func (gs *State) ListNPCs() string
- func (gs *State) Look(alias string) (string, error)
- func (gs *State) MoveNPCs()
- func (gs *State) RunConversation(npc *NPC) error
- func (gs *State) StepNPCs() (moved, stayed int)
- type Targetable
Constants ¶
This section is empty.
Variables ¶
var ( // PronounsFeminine is the predefined set of feminine pronouns, commonly // referred to as "she/her" pronouns. PronounsFeminine = PronounSet{"SHE", "HER", "HERS", "HER", "HERSELF", false} // PronounsMasculine is the predefined set of masculine pronouns, commonly // referred to as "he/him" pronouns. PronounsMasculine = PronounSet{"HE", "HIM", "HIS", "HIS", "HIMSELF", false} // PronounsNonBinary is the predefined set of non-binary pronouns, commonly // referred to as "they/them" pronouns. PronounsNonBinary = PronounSet{"THEY", "THEM", "THEIRS", "THEIR", "THEMSELF", true} // PronounsItIts is the predefined set of pronouns commonly referred to as // "it/its". PronounsItIts = PronounSet{"IT", "IT", "ITS", "ITS", "ITSELF", false} )
var DialogActionsByString map[string]DialogAction = map[string]DialogAction{ DialogEnd.String(): DialogEnd, DialogLine.String(): DialogLine, DialogChoice.String(): DialogChoice, DialogPause.String(): DialogPause, }
DialogActionsByString is a map indexing string values to their corresponding DialogAction.
var RouteActionsByString map[string]RouteAction = map[string]RouteAction{ RouteStatic.String(): RouteStatic, RoutePatrol.String(): RoutePatrol, RouteWander.String(): RouteWander, }
RouteActionsByString is a map indexing string values to their corresponding RouteAction.
Functions ¶
func IsDetail ¶ added in v0.2.0
func IsDetail(t Targetable) bool
IsDetail returns whether the Targetable is a room detail and thus can be only be looked at by the player.
func IsEgress ¶ added in v0.2.0
func IsEgress(t Targetable) bool
IsEgress returns whether the Targetable is an Egress and thus can be traversed by the player.
func IsItem ¶ added in v0.2.0
func IsItem(t Targetable) bool
IsItem returns whether the Targetable is an Item and thus can be picked up by the player and placed in inventory.
func IsNPC ¶ added in v0.2.0
func IsNPC(t Targetable) bool
IsNPC returns whether the Targetable is an NPC and thus can be talked to by the player.
Types ¶
type Conversation ¶
type Conversation struct { Dialog []*DialogStep // contains filtered or unexported fields }
Conversation includes the dialog tree and the current position within it. It can be created simply by manually creating a Conversation and assigning a sequence of steps to Dialog.
func (*Conversation) JumpTo ¶
func (convo *Conversation) JumpTo(label string)
JumpTo makes the Conversation JumpTo the step with the given label, so that the next call to NextStep returns that DialogStep. If an invalid label is given, the next call to NextStep will return an END step. This is a valid option for moving the convo to the appropriate position after the user has entered a choice.
func (*Conversation) NextStep ¶
func (convo *Conversation) NextStep() *DialogStep
NextStep gets the next DialogStep in the conversation. If it returns a DialogStep with an Action of DialogEnd, the dialog is over and there is nothing further to do. If it returns a DialogStep with an Action of DialogLine, NextStep can be safely called to go to the next DialogStep after that one is processed. If it returns a DialogStep with an Action of DialogChoice, JumpTo should be used to jump to the given alias before calling NextStep again.
type Detail ¶ added in v0.2.0
type Detail struct { // Aliases is the aliases that the player can use to target the detail. Aliases []string // Description is the long description of the detail, shown when the player // LOOKs at it. Description string // contains filtered or unexported fields }
Detail is an additional piece of detail in a room that the user is allowed to look at and/or target as objects of commands. If targeted by something that it cannot handle, player would not be allowed to do that with it. Every detail at minimum can be LOOKed at.
func (Detail) GetAliases ¶ added in v0.2.0
func (Detail) GetDescription ¶ added in v0.2.0
func (d Detail) GetDescription() *tunascript.Template
type DialogAction ¶
type DialogAction int
const ( DialogEnd DialogAction = iota DialogLine DialogChoice DialogPause )
func (DialogAction) String ¶
func (dst DialogAction) String() string
type DialogStep ¶
type DialogStep struct { Action DialogAction // The line of dialog. Not used if action is END. Content string // How the player responds to the line. Only used if action is LINE, else // use choices. Response string // Choices is a series of options for a CHOICE type dialog step. Choices [][2]string // Label of the DialogStep. If not set it will just be the index within the // conversation tree. Label string // Resume is the label to resume the conversation with after coming back // after a PAUSE step. It is only relevant if Action is DialogPause. If // blank on a PAUSE step, it will resume with the next step in the tree. ResumeAt string // contains filtered or unexported fields }
DialogStep is a single step of a Dialog tree. It instructions a Dialog as to what should happen in it and how to do it. A step either specifies an end, a line, or a choice.
func (DialogStep) Copy ¶
func (ds DialogStep) Copy() DialogStep
Copy returns a deeply-copied DialogStep.
func (DialogStep) String ¶
func (ds DialogStep) String() string
type Egress ¶
type Egress struct { // DestLabel is the label of the room this egress goes to. DestLabel string // Description is the long description of the egress point. Description string // TravelMessage is the message shown when the player uses this egress // point. TravelMessage string // Aliases is the list of aliases that the user can give to travel via this // egress. Note that the label is not included in this list by default to // prevent spoilerific room names. Aliases []string // contains filtered or unexported fields }
Egress is an egress point from a room. It contains both a description and the label it points to.
func (Egress) GetAliases ¶ added in v0.2.0
func (Egress) GetDescription ¶ added in v0.2.0
func (egress Egress) GetDescription() *tunascript.Template
type IODevice ¶
type IODevice struct { // The width of each line of output. Width int // a function to send output. If s is empty, an empty line is sent. Output func(s string, a ...interface{}) error // a function to use to get string input. If prompt is blank, no prompt is // sent before the input is read. Input func(prompt string) (string, error) // a function to use to get int input. If prompt is blank, no prompt is // sent before the input is read. If invalid input is received, keeps // prompting until a valid one is entered. InputInt func(prompt string) (int, error) }
TODO: this should rly be an interface, not a struct.
type Inventory ¶
Inventory is a store of items.
func (Inventory) GetItemByAlias ¶
GetItemByAlias returns the item from the Inventory that is represented by the given alias. If no Item in the inventory has that alias, the returned item is nil.
type Item ¶
type Item struct { // Label is a name for the item and canonical way to index it // programmatically. It should be upper case and MUST be unique within all // labels of the world. Label string // Name is the short name of the item. Name string // Description is what is shown when the player LOOKs at the item. Description string // Aliases are all of the strings that can be used to refer to the item. It // must have at least one string that is unique amongst the labels in the // world it is in. It does not include Label by default, this must be // explicitly given. Aliases []string // contains filtered or unexported fields }
Item is an object that can be picked up. It contains a unique label, a description, and aliases that it can be referred to by. All aliases SHOULD be unique in case an item is dropped with another, but as long as at least ONE alias is present, we can handle the ambiguous case by asking player to restate.
func (Item) GetAliases ¶ added in v0.2.0
func (Item) GetDescription ¶ added in v0.2.0
func (item Item) GetDescription() *tunascript.Template
type NPC ¶
type NPC struct { // Label is a name for the NPC and canonical way to index it // programmatically. It should be upper case and MUST be unique within all // NPC labels of the world. Label string // Name is the short description of the NPC. Name string // Aliases is all names that can be used to refer to an NPC. Aliases []string // Pronouns is used to programatically refer to the NPC in auto-generated // phrases. Pronouns PronounSet // Description is the long description given when a player LOOKs at the NPC. Description string // Start is the label of the room that the NPC is in at the start of the // game. Start string // Movement is the type of Movement that the NPC engages in. Movement Route // Dialog is the Dialog tree that the NPC engages in with the player. Dialog []*DialogStep // Convo is the currently active conversation with the NPC. If not set or // set to nil, there is no active conversation between the player and the // NPC. Convo *Conversation // contains filtered or unexported fields }
NPC is a NonPlayerCharacter in the world. They may move between rooms depending on their Movement property and can be talked to by the player. If they can move, they only do so when the player does.
func (NPC) GetAliases ¶ added in v0.2.0
func (NPC) GetDescription ¶ added in v0.2.0
func (npc NPC) GetDescription() *tunascript.Template
func (NPC) NextRouteStep ¶
NextRouteStep gets the name of the next location this character would like to travel to. If it returns an empty string, the NPC's route dictates that they should stay.
room is the current room that they are in.
func (*NPC) ResetRoute ¶
func (npc *NPC) ResetRoute()
ResetRoute resets the route of the NPC. It should always be called before attempting to call NextRouteStep().
type Pathfinder ¶
Pather performs pathfinding operations on the given world. It also retains already-completed lookups so that it becomes faster with use. Changing World does not invalidate the cache, therefore World should not be set to anything else once it is initially set and the first operation is called on the Pathfinder.
func (*Pathfinder) Dijkstra ¶
func (pf *Pathfinder) Dijkstra(startLabel, endLabel string) []string
Dijkstra uses Dijkstra's Algorithm to find the shortest path from one node to another in the world. This only checks if it is ever possible, not if it is *currently* possible to traverse with no further actions. Callers should verify that the returned sequence of rooms is traversable before attempting to use it for such purposes.
Returns nil or empty []string if the startLabel does not exist in the world, if the endLabel does not exist in the world, or if the path is not possible.
func (*Pathfinder) ValidatePath ¶
func (pf *Pathfinder) ValidatePath(path []string, loop bool) error
ValidateRoute verifies whether the given route is a sequence of labels of rooms in the world that can be visited in the order given. If it is not a valid route, a non-nil error is returned containing info on why the route is not possible.
type PronounSet ¶
type PronounSet struct { // Nominative is the pronoun used in the nominative case. 'SHE', 'HE', or // 'THEY' for example; the pronoun that would be used to replace 'NPC' in // the following sentence: "NPC WENT TO THE STORE." Nominative string // Objective is the pronoun used in the objective case. 'HER', 'HIM', or // 'THEM' for example; the pronoun that would be used to replace 'NPC' in // the following sentence: "YOU TALK TO NPC." Objective string // Possessive the pronoun used in the possesive case. 'HERS', 'HIS', or // 'THEIRS' for example; the pronoun that would be used to replace "NPC'S" // in the following sentence: "THAT ITEM IS NPC'S." Possessive string // Determiner is the pronoun used in the possesive case when using a pronoun // as an adjective of some noun to show ownership. 'HER', 'HIS', or 'THEIR' // for example; the pronoun that would be used to replace "NPC's" in the // following sentence: "THAT IS NPC'S ITEM." Determiner string // Reflexive is the pronoun used to show the pronoun-user refering back to // themself. 'HERSELF', 'HIMSELF', or 'THEMSELF' for example; the pronoun // that would be used to replace "NPCSELF" is the following sentence: "NPC // THINKS ABOUT NPCSELF A LOT". Reflexive string // Plural is whether the pronoun requires plural conjugation of verbs; e.g. // use 'NOMINATIVE are' instead of 'NOMINATIVE is'. Plural bool }
PronounSet is a set of pronouns for an NPC that can be used by code that generates references to NPCs without being specific to a particular one. You can create your own Pronouns struct, or just stick to the previously-defined ones. These should be all upper-case.
func (PronounSet) Short ¶
func (ps PronounSet) Short() string
Short returns the string representing the shortened version of the pronoun set. Only nominative, objective, and possessive are shown.
If Nominative isn't set, the output will show it as "<?>". If Objective isn't set, the output will show it as the same as whatever Nominative is set to. If Possessive isn't set, the output will show it as the same as whatever Objective is set to but with an 's' added.
If Possessive is just Objective but with 's' at the end, it will be omitted from the output.
func (PronounSet) String ¶
func (ps PronounSet) String() string
type Room ¶
type Room struct { // Label is how the room is referred to in the game. It must be unique from // all other Rooms. Label string // Name is used in short descriptions (prior to LOOK). Name string // Description is what is returned when LOOK is given with no arguments. Description string // Exits is a list of room labels and ways to describe them, pointing to // other rooms in the game. Exits []*Egress // Items is the items on the ground. This can be changed over time. Items []*Item // NPCs is the non-player characters currently in the world. NPCs map[string]*NPC // Details is the details that the player can look at in the room. Details []*Detail // contains filtered or unexported fields }
Room is a scene in the game. It contains a series of exits that lead to other rooms and a description. They also contain a list of the interactables at game start (or will in the future).
func (Room) GetDetailByAlias ¶ added in v0.2.0
GetDetailByAlias returns the Detail from the room that is referred to by the given alias. If no Detail has that alias, the returned *Detail will be nil.
func (Room) GetEgressByAlias ¶
GetEgressByAlias returns the egress from the room that is represented by the given alias. If no Egress has that alias, the returned egress is nil.
func (Room) GetItemByAlias ¶
GetItemByAlias returns the item from the room that is represented by the given alias. If no Item has that alias, the returned item is nil.
func (Room) GetNPCByAlias ¶
GetNPCByAlias returns the NPC from the room that is referred to by the given alias. If no NPC has that alias, the returned NPC is nil.
func (Room) GetTargetable ¶ added in v0.2.0
func (room Room) GetTargetable(alias string) (t Targetable)
GetTargetable returns the first Targetable game object (Egress, Item, NPC, or Detail) from the room that is referred to by the given alias. If no Targetable has that alias, the returned Targetable will be nil.
func (*Room) RemoveItem ¶
RemoveItem removes the item of the given label from the room. If there is already no item with that label in the room, this has no effect.
type Route ¶
type Route struct { // Action is the type of action the route has the NPC move. RouteStatic is // not moving, RoutePatrol is follow the steps in 'Patrol', RouteWander is // to wander about but stay within AllowedRooms (if defined) or out of // ForbiddenRooms (if defined). Action RouteAction // Path is the steps that the route takes, by their room labels. It is // only used if Action is set to RoutePatrol Path []string // AllowedRooms is the list of rooms by their label that wandering movement // will stay within. It is only used if Action is set to RouteWander. If // neither this nor ForbiddenRooms has entries, the NPC is permitted to // wander anywhere. If both are set and contain the same entry, // ForbiddenRooms takes precedent and the room will be forbidden. AllowedRooms []string // ForbiddenRooms is the list of rooms by their label that wandering // movement will stay out of. It is only used if Action is set to // RouteWander. If neither this nor AllowedRooms has entries, the NPC is // permitted to wander anywhere. If both are set and contain the same entry, // ForbiddenRooms takes precedent and the room will be forbidden. ForbiddenRooms []string }
Route is a type of movement for an NPC to take
type RouteAction ¶
type RouteAction int
RouteAction is the type of action that a route has an NPC take.
const ( RouteStatic RouteAction = iota RoutePatrol RouteWander )
func (RouteAction) String ¶
func (ra RouteAction) String() string
type State ¶
type State struct { // World is all rooms that exist and their current state. World map[string]*Room // CurrentRoom is the room that the player is in. CurrentRoom *Room // Inventory is the objects that the player currently has. Inventory Inventory // contains filtered or unexported fields }
State is the game's entire state. It should not be used directly; call New to create and initialize one.
func New ¶
func New(world map[string]*Room, startingRoom string, flags map[string]string, ioDev IODevice) (*State, error)
New creates a new State and loads the list of rooms into it. It performs basic sanity checks to ensure that a valid world is being passed in and normalizes them as needed.
startingRoom is the label of the room to start with. ioDev is the input/output device to use when the user needs to be prompted for more info, or for showing to the user. io.Width is how wide the output should be. State will try to make all output fit within this width. If not set or < 2, it will be automatically assumed to be 80.
func (*State) Advance ¶
Advance advances the game state based on the given command. If there is a problem executing the command, it is given in the error output and the game state is not advanced. If it is, the result of the command is written to the provided output stream.
Invalid commands will be returned as non-nil errors as opposed to writing directly to the IO stream; the caller can decide whether to do this themself.
Note that for this, QUIT is not considered a valid command is it would be on a controlling engine to end the game state based on that.
TODO: differentiate syntax errors from io errors
func (*State) ExecuteCommandDebug ¶
ExecuteCommandDebug executes the DEBUG command with the arguments in the provided Command and returns the output. The DEBUG command has varied arguments and may do different things based on what else is provided.
func (*State) ExecuteCommandDrop ¶
ExecuteCommandDrop executes the DROP command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandExits ¶
ExecuteCommandExits executes the EXITS command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandGo ¶
ExecuteCommandGo executes the GO command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandHelp ¶
ExecuteCommandHelp executes the HELP command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandInventory ¶
ExecuteCommandInventory executes the INVENTORY command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandLook ¶
ExecuteCommandDrop executes the LOOK command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandTake ¶
ExecuteCommandTake executes the TAKE command with the arguments in the provided Command and returns the output.
func (*State) ExecuteCommandTalk ¶
ExecuteCommandTalk executes the TALK command with the arguments in the provided Command and returns the output. This will enter into an input loop that will not exit until the conversation is PAUSED or an END step is reached in it.
func (*State) Expand ¶ added in v0.3.0
func (gs *State) Expand(s *tunascript.Template) string
Expand executes the given template text and turns it into the resulting text. Any tunascript queries required to evaluate template flow-control statements are executed at this time.
func (*State) ListFlags ¶
ListFlags returns a text table of the Flags in the game and their current values.
func (*State) ListNPCs ¶
ListNPCs returns a text table of the NPCs in the game and some general information about them.
func (*State) Look ¶
Look gets the look description as a single long string. It returns non-nil error if there are issues retrieving it. If alias is empty, the room is looked at. The returned string is not formatted except that any seperate listings (such as items or NPCs in a room) will be separated by "\n\n". The returned string will be expanded from its tunascript template.
func (*State) MoveNPCs ¶
func (gs *State) MoveNPCs()
MoveNPCs applies all movements on NPCs that are in the world.
func (*State) RunConversation ¶
type Targetable ¶ added in v0.2.0
type Targetable interface { // GetAliases returns all names that the player may use to refer to the /// thing. GetAliases() []string // GetDescription returns the template AST representing the description to // show when the player looks at it. GetDescription() *tunascript.Template }
Targetable is something that can be targeted by a player command. All can be looked at.