game

package
v0.3.0 Latest Latest
Warning

This package is not in the latest version of its module.

Go to latest
Published: Jun 11, 2023 License: MIT Imports: 13 Imported by: 0

Documentation

Overview

Package game implements game state and advancement.

Index

Constants

This section is empty.

Variables

View Source
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}
)
View Source
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.

View Source
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) Copy added in v0.2.0

func (d Detail) Copy() Detail

Copy returns a deeply-copied Egress.

func (Detail) GetAliases added in v0.2.0

func (d Detail) GetAliases() []string

func (Detail) GetDescription added in v0.2.0

func (d Detail) GetDescription() *tunascript.Template

func (Detail) String added in v0.2.0

func (d Detail) String() string

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) Copy

func (egress Egress) Copy() Egress

Copy returns a deeply-copied Egress.

func (Egress) GetAliases added in v0.2.0

func (egress Egress) GetAliases() []string

func (Egress) GetDescription added in v0.2.0

func (egress Egress) GetDescription() *tunascript.Template

func (Egress) String

func (egress Egress) String() string

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

type Inventory map[string]*Item

Inventory is a store of items.

func (Inventory) GetItemByAlias

func (inv Inventory) GetItemByAlias(alias string) *Item

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) Copy

func (item Item) Copy() Item

Copy returns a deeply-copied Item.

func (Item) GetAliases added in v0.2.0

func (item Item) GetAliases() []string

func (Item) GetDescription added in v0.2.0

func (item Item) GetDescription() *tunascript.Template

func (Item) String

func (item Item) String() string

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) Copy

func (npc NPC) Copy() NPC

Copy returns a deeply-copied NPC.

func (NPC) GetAliases added in v0.2.0

func (npc NPC) GetAliases() []string

func (NPC) GetDescription added in v0.2.0

func (npc NPC) GetDescription() *tunascript.Template

func (NPC) NextRouteStep

func (npc NPC) NextRouteStep(room *Room) string

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().

func (NPC) String

func (npc NPC) String() string

type Pathfinder

type Pathfinder struct {
	World map[string]*Room
	// contains filtered or unexported fields
}

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) Copy

func (room Room) Copy() Room

Copy returns a deeply-copied Room.

func (Room) GetDetailByAlias added in v0.2.0

func (room Room) GetDetailByAlias(alias string) *Detail

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

func (room Room) GetEgressByAlias(alias string) *Egress

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

func (room Room) GetItemByAlias(alias string) *Item

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

func (room Room) GetNPCByAlias(alias string) *NPC

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

func (room *Room) RemoveItem(label string)

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.

func (Room) String

func (room Room) String() string

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

func (Route) Copy

func (r Route) Copy() Route

Copy returns a deeply-copied Route.

func (Route) String

func (r Route) String() string

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

func (gs *State) Advance(cmd command.Command) error

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

func (gs *State) ExecuteCommandDebug(cmd command.Command) (string, error)

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

func (gs *State) ExecuteCommandDrop(cmd command.Command) (string, error)

ExecuteCommandDrop executes the DROP command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandExits

func (gs *State) ExecuteCommandExits(cmd command.Command) (string, error)

ExecuteCommandExits executes the EXITS command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandGo

func (gs *State) ExecuteCommandGo(cmd command.Command) (string, error)

ExecuteCommandGo executes the GO command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandHelp

func (gs *State) ExecuteCommandHelp(cmd command.Command) (string, error)

ExecuteCommandHelp executes the HELP command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandInventory

func (gs *State) ExecuteCommandInventory(cmd command.Command) (string, error)

ExecuteCommandInventory executes the INVENTORY command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandLook

func (gs *State) ExecuteCommandLook(cmd command.Command) (string, error)

ExecuteCommandDrop executes the LOOK command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandTake

func (gs *State) ExecuteCommandTake(cmd command.Command) (string, error)

ExecuteCommandTake executes the TAKE command with the arguments in the provided Command and returns the output.

func (*State) ExecuteCommandTalk

func (gs *State) ExecuteCommandTalk(cmd command.Command) (string, error)

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) GetNPCInfo

func (gs *State) GetNPCInfo(label string) (string, error)

func (*State) ListFlags

func (gs *State) ListFlags() string

ListFlags returns a text table of the Flags in the game and their current values.

func (*State) ListNPCs

func (gs *State) ListNPCs() string

ListNPCs returns a text table of the NPCs in the game and some general information about them.

func (*State) Look

func (gs *State) Look(alias string) (string, error)

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

func (gs *State) RunConversation(npc *NPC) error

func (*State) StepNPCs

func (gs *State) StepNPCs() (moved, stayed int)

StepNPCs has all NPCs take a movement step, and returns the number of NPCs moved to a new location and the number of NPCs who stayed in the same location.

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.

Jump to

Keyboard shortcuts

? : This menu
/ : Search site
f or F : Jump to
y or Y : Canonical URL