game

package
v0.0.0-...-f3028fa Latest Latest
Warning

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

Go to latest
Published: Oct 21, 2022 License: MIT Imports: 10 Imported by: 3

Documentation

Index

Constants

View Source
const (
	GenPlayer  = "player"
	GenMonster = "monster"
)

Permissible genera of actors.

View Source
const (
	FOVRadiusMax = 8
	FOVRadius    = 4
	ScentRadius  = FOVRadius
)
View Source
const (
	// Player species.
	SpecHuman = "human"

	// Monster species.
	SpecOrc = "orc"
	SpecAnt = "ant"
)
View Source
const (
	SlotHand = iota
	SlotHead
	SlotBody
	SlotArms
	SlotLegs
	SlotRelic
)
View Source
const (
	EffectTypeBrand = iota
	EffectTypeResist
	EffectTypeStatus
	EffectTypeSlay
	EffectTypeFlag
)

Types of permissible effects.

View Source
const (
	SpecFist         = "fist"
	SpecSword        = "sword"
	SpecLeatherArmor = "leatherarmor"

	SpecCure    = "cure"
	SpecStim    = "stim"
	SpecHyper   = "hyper"
	SpecRestore = "restore"
)
View Source
const (
	FamActor = "actor"
	FamItem  = "item"
)

Permissible families of objects.

View Source
const (
	BaseCritDiv = 7
)

The base divisor to use for crits.

View Source
const GenConsumable = "consume"

Something you can eat / drink / use a single time.

View Source
const GenEquipment = "equipment"

Something you can equip.

View Source
const MaxFloor = 5
View Source
const RegenPeriod = 100

We expect a speed 2 actor to fully recover in 100 turns.

Variables

View Source
var (
	ErrAlreadyLearning = errors.New("AlreadyLearning")
	ErrNotLearning     = errors.New("NotLearning")
	ErrNotEnoughXP     = errors.New("NotEnoughXP")
	ErrNoPointsLearned = errors.New("NoPointsLearned")
)
View Source
var (
	ErrMove0Dir        = errors.New("Move0Dir")
	ErrMoveTooFar      = errors.New("MoveTooFar")
	ErrMoveHit         = errors.New("MoveHit")
	ErrTooScaredToHit  = errors.New("TooScaredToHit")
	ErrMoveBlocked     = errors.New("MoveBlocked")
	ErrMoveOutOfBounds = errors.New("MoveOutOfBounds")
	ErrMoveSwapFailed  = errors.New("MoveSwapFailed")
	ErrMoveOpenedDoor  = errors.New("MoveOpenedDoor")
)
View Source
var (
	// Base regen that actors get every turn.
	AEBaseRegen = ActiveEffect{
		OnTick: func(e *ActiveEffect, t Ticker, diff int) bool {
			sheet := t.Obj().Sheet
			regen := sheet.Regen()

			e.Counter += regen * diff
			delayPerHp := RegenPeriod * GetDelay(2) / sheet.MaxHP()
			heal := e.Counter / delayPerHp

			if heal > 0 {
				sheet.Heal(heal)
				e.Counter -= heal * delayPerHp
			}
			return false
		},
		Stacks: AEStackIgnore,
	}
	AEPoison = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			var msg string
			if prev == 0 {
				msg = "%s is poisoned."
			} else {
				msg = "%s is more poisoned."
			}
			t.Obj().Game.Events.Message(fmt.Sprintf(msg, t.Obj().Spec.Name))
		},
		OnTick: hpdecay,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Game.Events.Message(fmt.Sprintf("%s recovers from poison.", t.Obj().Spec.Name))
		},
		Stacks: AEStackAdd,
	}
	AECut = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			var msg string
			if prev == 0 {
				msg = "%s is wounded."
			} else {
				msg = "%s is more wounded."
			}
			t.Obj().Game.Events.Message(fmt.Sprintf(msg, t.Obj().Spec.Name))
		},
		OnTick: hpdecay,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Game.Events.Message(fmt.Sprintf("%s is healed from wounds.", t.Obj().Spec.Name))
		},
		Stacks: AEStackAdd,
	}
	AEStun = ActiveEffect{
		OnBegin: func(e *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetStun(getstunlevel(e.Counter))
		},
		OnTick: func(e *ActiveEffect, t Ticker, _ int) bool {
			e.Counter -= 1
			t.Obj().Sheet.SetStun(getstunlevel(e.Counter))
			return e.Counter <= 0
		},
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetStun(NotStunned)
		},
		Stacks: AEStackAdd,
	}
	AECorrode = ActiveEffect{
		OnBegin: func(e *ActiveEffect, t Ticker, prev int) {
			sheet := t.Obj().Sheet
			sheet.SetCorrosion(sheet.Corrosion() + 1)

			var msg string
			if prev == 0 {
				msg = "%s armor is damaged."
			} else {
				msg = "%s armor is more damaged."
			}
			t.Obj().Game.Events.Message(fmt.Sprintf(msg, poss(t.Obj().Spec.Name)))
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetCorrosion(0)

			msg := "%s armor is fixed."
			t.Obj().Game.Events.Message(fmt.Sprintf(msg, poss(t.Obj().Spec.Name)))
		},
		Stacks: AEStackAdd,
	}
	AEBlind = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetBlind(true)
			msg := fmt.Sprintf("%s is blinded.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetBlind(false)
			msg := fmt.Sprintf("%s can see again.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackAdd,
	}
	AESlow = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetSlow(true)
			msg := fmt.Sprintf("%s is slowed.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetSlow(false)
			msg := fmt.Sprintf("%s speeds up again.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackAdd,
	}
	AEConfuse = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetConfused(true)
			msg := fmt.Sprintf("%s is confused.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetConfused(false)
			msg := fmt.Sprintf("%s recovers from confusion.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackAdd,
	}
	AEFear = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetAfraid(true)
			msg := fmt.Sprintf("%s is scared.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetAfraid(false)
			msg := fmt.Sprintf("%s recovers from fear.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackAdd,
	}
	AEPara = ActiveEffect{
		OnBegin: func(ae *ActiveEffect, t Ticker, _ int) {
			log.Printf("Para: %d turns", ae.Counter)
			t.Obj().Sheet.SetParalyzed(true)
			msg := fmt.Sprintf("%s is paralyzed.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetParalyzed(false)
			msg := fmt.Sprintf("%s can move again.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackIgnore,
	}
	AEPetrify = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetPetrified(true)
			msg := fmt.Sprintf("%s is turned to stone.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetPetrified(false)
			msg := fmt.Sprintf("%s is no longer a statue.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackIgnore,
	}
	AESilence = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetSilenced(true)
			msg := fmt.Sprintf("%s is silenced.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetSilenced(false)
			msg := fmt.Sprintf("%s can speak again.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackAdd,
	}
	AECurse = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, _ int) {
			t.Obj().Sheet.SetCursed(true)
			msg := fmt.Sprintf("%s is cursed.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			t.Obj().Sheet.SetCursed(false)
			msg := fmt.Sprintf("%s is no longer cursed.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
		},
		Stacks: AEStackAdd,
	}
	AEStim = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			msg := fmt.Sprintf("%s feels a rush!", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			if prev == 0 {
				modAllSkills(t.Obj().Sheet, 2)
			}
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			msg := fmt.Sprintf("%s feels the rush wear off.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			modAllSkills(t.Obj().Sheet, -2)
		},
		Stacks: AEStackReplace,
	}
	AEHyper = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			msg := fmt.Sprintf("%s is supercharged!", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			if prev == 0 {
				modAllStats(t.Obj().Sheet, 2)
			}
		},
		OnTick: basictick,
		OnEnd: func(_ *ActiveEffect, t Ticker) {
			msg := fmt.Sprintf("%s feels the supercharge wear off.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			modAllStats(t.Obj().Sheet, -2)
		},
		Stacks: AEStackReplace,
	}
	AEDrainStr = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			msg := fmt.Sprintf("%s loses strength.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Str, -1)
		},
		OnTick: func(_ *ActiveEffect, _ Ticker, _ int) bool {
			return false
		},
		OnEnd: func(ae *ActiveEffect, t Ticker) {
			msg := fmt.Sprintf("%s regains strength.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Str, ae.Counter)
		},
		Stacks: AEStackAdd,
	}
	AEDrainAgi = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			msg := fmt.Sprintf("%s loses agility.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Agi, -1)
		},
		OnTick: func(_ *ActiveEffect, _ Ticker, _ int) bool {
			return false
		},
		OnEnd: func(ae *ActiveEffect, t Ticker) {
			msg := fmt.Sprintf("%s regains agility.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Agi, ae.Counter)
		},
		Stacks: AEStackAdd,
	}
	AEDrainVit = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			msg := fmt.Sprintf("%s loses vitality.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Vit, -1)
		},
		OnTick: func(_ *ActiveEffect, _ Ticker, _ int) bool {
			return false
		},
		OnEnd: func(ae *ActiveEffect, t Ticker) {
			msg := fmt.Sprintf("%s regains vitality.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Vit, ae.Counter)
		},
		Stacks: AEStackAdd,
	}
	AEDrainMnd = ActiveEffect{
		OnBegin: func(_ *ActiveEffect, t Ticker, prev int) {
			msg := fmt.Sprintf("%s loses mind.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Mnd, -1)
		},
		OnTick: func(_ *ActiveEffect, _ Ticker, _ int) bool {
			return false
		},
		OnEnd: func(ae *ActiveEffect, t Ticker) {
			msg := fmt.Sprintf("%s regains mind.", t.Obj().Spec.Name)
			t.Obj().Game.Events.Message(msg)
			t.Obj().Sheet.ChangeStatMod(Mnd, ae.Counter)
		},
		Stacks: AEStackAdd,
	}
)

Implementation of specific active effects. TODO: This could have more simply been an interface type with a factory function to create the right implementation for the given effect enum value. I'm not quite sure how we got here. Maybe fix this. Oops. Although, all those structs would really have looked the same and just been aliases of a base struct.

View Source
var (
	FeatWall       = &Feature{Type: "FeatWall", Solid: true, Opaque: true}
	FeatFloor      = &Feature{Type: "FeatFloor", Solid: false, Opaque: false}
	FeatClosedDoor = &Feature{Type: "FeatClosedDoor", Solid: true, Opaque: true}
	FeatOpenDoor   = &Feature{Type: "FeatOpenDoor", Solid: false, Opaque: false}
	FeatStairsUp   = &Feature{Type: "FeatStairsUp", Solid: false, Opaque: false}
	FeatStairsDown = &Feature{Type: "FeatStairsDown", Solid: false, Opaque: false}
)

Prototype map for effects that are applied every tick.

View Source
var EffectsSpecs = EffectsSpec{
	BrandFire:   {Type: EffectTypeBrand, ResistedBy: ResistFire},
	BrandElec:   {Type: EffectTypeBrand, ResistedBy: ResistElec},
	BrandIce:    {Type: EffectTypeBrand, ResistedBy: ResistIce},
	BrandPoison: {Type: EffectTypeBrand, ResistedBy: ResistPoison},
	BrandAcid:   {Type: EffectTypeBrand, ResistedBy: ResistAcid},

	SlayPearl:  {Type: EffectTypeSlay, Slays: WeakPearl},
	SlayHunter: {Type: EffectTypeSlay, Slays: WeakHunter},
	SlayBattle: {Type: EffectTypeSlay, Slays: WeakBattle},
	SlayDispel: {Type: EffectTypeSlay, Slays: WeakDispel},

	EffectBaseRegen: {Type: EffectTypeStatus},
	EffectStun:      {Type: EffectTypeStatus, ResistedBy: ResistStun},
	EffectPoison:    {Type: EffectTypeStatus, ResistedBy: ResistPoison},
	EffectCut:       {Type: EffectTypeStatus},
	EffectBlind:     {Type: EffectTypeStatus, ResistedBy: ResistBlind},
	EffectSlow:      {Type: EffectTypeStatus, ResistedBy: ResistSlow},
	EffectConfuse:   {Type: EffectTypeStatus, ResistedBy: ResistConfuse},
	EffectFear:      {Type: EffectTypeStatus, ResistedBy: ResistFear},
	EffectPara:      {Type: EffectTypeStatus, ResistedBy: ResistPara},
	EffectSilence:   {Type: EffectTypeStatus, ResistedBy: ResistSilence},
	EffectCurse:     {Type: EffectTypeStatus, ResistedBy: ResistCurse},
	EffectPetrify:   {Type: EffectTypeStatus, ResistedBy: ResistPetrify},
	EffectBless:     {Type: EffectTypeStatus},
	EffectStim:      {Type: EffectTypeStatus},
	EffectHyper:     {Type: EffectTypeStatus},
	EffectVamp:      {Type: EffectTypeStatus, ResistedBy: ResistVamp},
	EffectShatter:   {Type: EffectTypeStatus},
	EffectDrainStr:  {Type: EffectTypeStatus},
	EffectDrainAgi:  {Type: EffectTypeStatus},
	EffectDrainVit:  {Type: EffectTypeStatus},
	EffectDrainMnd:  {Type: EffectTypeStatus},

	WeakPearl:  {Type: EffectTypeFlag},
	WeakHunter: {Type: EffectTypeFlag},
	WeakBattle: {Type: EffectTypeFlag},
	WeakDispel: {Type: EffectTypeFlag},

	ResistFire:    {Type: EffectTypeResist},
	ResistElec:    {Type: EffectTypeResist},
	ResistIce:     {Type: EffectTypeResist},
	ResistAcid:    {Type: EffectTypeResist},
	ResistStun:    {Type: EffectTypeResist},
	ResistPoison:  {Type: EffectTypeResist},
	ResistBlind:   {Type: EffectTypeResist},
	ResistSlow:    {Type: EffectTypeResist},
	ResistConfuse: {Type: EffectTypeResist},
	ResistFear:    {Type: EffectTypeResist},
	ResistPara:    {Type: EffectTypeResist},
	ResistCurse:   {Type: EffectTypeResist},
	ResistPetrify: {Type: EffectTypeResist},
	ResistCrit:    {Type: EffectTypeResist},
	ResistVamp:    {Type: EffectTypeResist},
	ResistDrain:   {Type: EffectTypeResist},
}

Mapping of effects to their types.

View Source
var Items = []*Spec{
	&Spec{
		Family:  FamItem,
		Genus:   GenEquipment,
		Species: SpecSword,
		Name:    "SWORD",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Equipment: NewEquipment(Equipment{
				Damroll: NewDice(2, 5),
				Melee:   0,
				Evasion: 1,
				Weight:  3,
				Slot:    SlotHand,
				Effects: NewEffects(map[Effect]int{EffectVamp: 1, SlayPearl: 1}),
			}),
		},
	},
	&Spec{
		Family:  FamItem,
		Genus:   GenEquipment,
		Species: SpecLeatherArmor,
		Name:    "LEATHER",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Equipment: NewEquipment(Equipment{
				Protroll: NewDice(1, 4),
				Melee:    0,
				Evasion:  -1,
				Weight:   4,
				Slot:     SlotBody,
				Effects:  NewEffects(map[Effect]int{ResistFire: 1, ResistPoison: 1, ResistStun: 1}),
			}),
		},
	},
	&Spec{
		Family:  FamItem,
		Genus:   GenConsumable,
		Species: SpecCure,
		Name:    "CURE",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Consumable: NewConsumable(curefunc),
		},
	},
	&Spec{
		Family:  FamItem,
		Genus:   GenConsumable,
		Species: SpecStim,
		Name:    "STIM",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Consumable: NewConsumable(stimfunc),
		},
	},
	&Spec{
		Family:  FamItem,
		Genus:   GenConsumable,
		Species: SpecHyper,
		Name:    "HYPER",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Consumable: NewConsumable(hyperfunc),
		},
	},
	&Spec{
		Family:  FamItem,
		Genus:   GenConsumable,
		Species: SpecRestore,
		Name:    "RESTORE",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Consumable: NewConsumable(restorefunc),
		},
	},
}
View Source
var Monsters = []*Spec{
	&Spec{
		Family:  FamActor,
		Genus:   GenMonster,
		Species: SpecOrc,
		Name:    "ORC",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 2,
		},
		Traits: &Traits{
			Mover: NewActorMover,
			AI: NewSMAI(SMAI{
				Brain: SMAIWanderer,
				Personality: &Personality{
					Fear:        25,
					Persistence: 1000,
				},
			}),
			Fighter: NewActorFighter,
			Packer:  NewActorPacker,
			Senser:  NewActorSenser,
			Ticker:  NewActorTicker,
			Dropper: NewItemDropper(&ItemDropper{
				num: 2,
			}),
			Sheet: NewMonsterSheet(&MonsterSheet{
				stats: &stats{
					stats: statlist{
						Str: 2,
						Agi: 0,
						Vit: 1,
						Mnd: 0,
					},
				},
				skills: &skills{
					skills: skilllist{
						Chi: 10,
					},
				},
				speed: 2,
				maxhp: 20,
				maxmp: 10,

				attacks: []*MonsterAttack{
					{
						Attack: Attack{
							Melee:   0,
							Damroll: NewDice(2, 7),
							CritDiv: 4,
							Effects: NewEffects(map[Effect]int{EffectPoison: 1}),
							Verb:    "hits",
						},
						P: 1,
					},
					{
						Attack: Attack{
							Melee:   3,
							Damroll: NewDice(1, 11),
							CritDiv: 2,
							Effects: Effects{},
							Verb:    "stabs",
						},
						P: 1,
					},
				},
				defense: Defense{
					Evasion:  1,
					ProtDice: []Dice{NewDice(1, 4)},
					Effects:  NewEffects(map[Effect]int{}),
				},
			}),
		},
	},
	&Spec{
		Family:  FamActor,
		Genus:   GenMonster,
		Species: SpecAnt,
		Name:    "DRAGON",
		Gen: Gen{
			Floors:    []int{1},
			GroupSize: 1,
		},
		Traits: &Traits{
			Mover: NewActorMover,
			AI: NewSMAI(SMAI{
				Brain: SMAITerritorial,
				Personality: &Personality{
					Fear:        50,
					Persistence: 0,
				},
			}),
			Fighter: NewActorFighter,
			Packer:  NewActorPacker,
			Senser:  NewActorSenser,
			Ticker:  NewActorTicker,
			Dropper: NewItemDropper(&ItemDropper{
				num:   4,
				boost: 3,
			}),
			Sheet: NewMonsterSheet(&MonsterSheet{
				stats: &stats{
					stats: statlist{
						Str: 3,
						Agi: 3,
						Vit: 1,
						Mnd: 0,
					},
				},
				skills: &skills{
					skills: skilllist{},
				},
				speed: 2,
				maxhp: 20,
				maxmp: 10,

				attacks: []*MonsterAttack{
					{
						Attack: Attack{
							Melee:   3,
							Damroll: NewDice(2, 9),
							CritDiv: 4,
							Effects: Effects{},
							Verb:    "claws",
						},
						P: 3,
					},
					{
						Attack: Attack{
							Melee:   0,
							Damroll: NewDice(2, 15),
							CritDiv: 4,
							Effects: NewEffects(map[Effect]int{BrandFire: 1}),
							Verb:    "bites",
						},
						P: 3,
					},
				},
				defense: Defense{
					Evasion:  5,
					ProtDice: []Dice{NewDice(2, 4)},
					Effects:  NewEffects(map[Effect]int{}),
				},
			}),
		},
	},
}
View Source
var PlayerSpec = &Spec{
	Family:  FamActor,
	Genus:   GenPlayer,
	Species: SpecHuman,
	Name:    "DEBO",
	Traits: &Traits{
		Mover:    NewActorMover,
		Fighter:  NewActorFighter,
		Packer:   NewActorPacker,
		Equipper: NewActorEquipper,
		User:     NewActorUser,
		Sheet:    NewPlayerSheet,
		Senser:   NewActorSenser,
		Ticker:   NewActorTicker,
		Learner:  NewActorLearner,
	},
}
View Source
var SMAITerritorial = SMAIStateMachine{
	{smaiUnborn, smaiStart}:          smaiAtHome,
	{smaiAtHome, smaiFoundPlayer}:    smaiChasing,
	{smaiAtHome, smaiFlee}:           smaiFleeing,
	{smaiChasing, smaiLostPlayer}:    smaiWaiting,
	{smaiChasing, smaiFlee}:          smaiFleeing,
	{smaiWaiting, smaiStopWaiting}:   smaiGoingHome,
	{smaiWaiting, smaiFoundPlayer}:   smaiChasing,
	{smaiWaiting, smaiFlee}:          smaiFleeing,
	{smaiGoingHome, smaiFoundHome}:   smaiAtHome,
	{smaiGoingHome, smaiFoundPlayer}: smaiChasing,
	{smaiGoingHome, smaiFlee}:        smaiFleeing,
	{smaiFleeing, smaiStopFleeing}:   smaiWaiting,
}

A territorial monster. Guards its home (spawn) square and returns there when player is out of LOS.

View Source
var SMAIWanderer = SMAIStateMachine{
	{smaiUnborn, smaiStart}:            smaiWaiting,
	{smaiWaiting, smaiStopWaiting}:     smaiWandering,
	{smaiWaiting, smaiFoundPlayer}:     smaiChasing,
	{smaiWaiting, smaiFlee}:            smaiFleeing,
	{smaiWandering, smaiStopWandering}: smaiWaiting,
	{smaiWandering, smaiFoundPlayer}:   smaiChasing,
	{smaiWandering, smaiFlee}:          smaiFleeing,
	{smaiChasing, smaiLostPlayer}:      smaiWaiting,
	{smaiChasing, smaiFlee}:            smaiFleeing,
	{smaiFleeing, smaiStopFleeing}:     smaiChasing,
}

A wandering monster. Randomly picks destinations to walk to, until it detects the player.

View Source
var ZeroDice = Dice{}

Functions

func Coinflip

func Coinflip() bool

func DieRoll

func DieRoll(d, s int) int

Roll a set of d s-sided die.

func FixRandomDie

func FixRandomDie(ints []int) func(int) int

An intsource that subtracts 1 to each element in the list. This makes it compatible with rigging dierolls directly, since DieRoll has to add one to each int to represent a roll from 1 to n (instead of 0 to n-1).

func FixRandomSource

func FixRandomSource(ints []int) func(int) int

"Fix" the random generator to return ints from the given sequence. Also returns the closure that substitutes intsource, if you want to chain it in subsequent fakes.

func Generate

func Generate(n, floor, wiggle int, specs []*Spec, g *Game) [][]*Obj

Given the floor # of the level and the "wiggle" (i.e. permissible range outside the floor), this will generate n "groups" of objects made from specs that are guaranteed not to be outside [floor - wiggle, floor + wiggle] based on its given floor. Group sizes are taken from the GroupSize entry for each spec -- if this is a monster, it's intended to be the pack size, and if it's an item it is intended to be the stack size.

func GetDelay

func GetDelay(spd int) int

Given the speed of an actor, this will tell you how much delay to add after each of its turns.

func NewConsumable

func NewConsumable(cf ConsumeFunc) func(*Obj) *Consumable

Given a consumefunc, this creates a factory function for consumables with this action.

func NewEquipment

func NewEquipment(equipspec Equipment) func(*Obj) *Equipment

See NewSheet in actor.go to understand why this is written this way.

func NewItemDropper

func NewItemDropper(spec *ItemDropper) func(*Obj) Dropper

func NewMonsterSheet

func NewMonsterSheet(sheetspec *MonsterSheet) func(*Obj) Sheet

Given a copy of a MonsterSheet literal, this will return a function that will bind the owner of the sheet to it at object creation time. See the syntax for this in actor_spec.go.

func NewSMAI

func NewSMAI(spec SMAI) func(*Obj) AI

func OneIn

func OneIn(n int) bool

func PathCost

func PathCost(l *Level, loc math.Point) int

Returns the "cost" of moving onto 'loc' in level l.

func RandInt

func RandInt(low int, high int) int

func RestoreRandom

func RestoreRandom()

Restore the random generator the way it was.

func StringLevel

func StringLevel(pic string) func(l *Level) *Level

Creates a level based on an ascii 'picture'. Used for testing.

Types

type AEStackType

type AEStackType uint
const (
	AEStackAdd AEStackType = iota
	AEStackReplace
	AEStackIgnore
)

type AI

type AI interface {
	Objgetter
	Init()
	Act() bool
}

A thing that can move given a specific direction.

type ActiveEffect

type ActiveEffect struct {
	// The effect counter. Might be turns, accumulated delay, residual damage, etc.
	Counter int
	// What to do when the effect is first inflicted on an actor. The last
	// integer argument will hold the previous value of the counter for this
	// effect if it is being continued / augmented (e.g. "X is more poisoned")
	OnBegin func(*ActiveEffect, Ticker, int)
	// Responsible for updating Left given the delay diff, plus enforcing the
	// effect. A return value of 'true' indicates that the effect should be
	// terminated.
	OnTick func(*ActiveEffect, Ticker, int) bool
	// What to do when the effect has run its course.
	OnEnd func(*ActiveEffect, Ticker)
	// How should this effect stack? Should we add to the counter, replace it
	// with the new value, or ignore the addition altogether?
	Stacks AEStackType
}

An instance of an effect that is currently affected an actor. These are managed by the actor's ticker.

func NewActiveEffect

func NewActiveEffect(e Effect, counter int) *ActiveEffect

Creates a new ActiveEffect record for the given effect.

type ActorEquipper

type ActorEquipper struct {
	Trait
	// contains filtered or unexported fields
}

func (*ActorEquipper) Body

func (a *ActorEquipper) Body() *Body

func (*ActorEquipper) Equip

func (a *ActorEquipper) Equip(index int) bool

func (*ActorEquipper) Remove

func (a *ActorEquipper) Remove(slot Slot) bool

func (*ActorEquipper) TryEquip

func (a *ActorEquipper) TryEquip()

func (*ActorEquipper) TryRemove

func (a *ActorEquipper) TryRemove()

type ActorFighter

type ActorFighter struct {
	Trait
}

Melee combat.

func (*ActorFighter) Hit

func (f *ActorFighter) Hit(other Fighter)

type ActorLearner

type ActorLearner struct {
	Trait
	// contains filtered or unexported fields
}

Used by the player to track what they have seen, and how much XP they have.

func (*ActorLearner) BeginLearning

func (l *ActorLearner) BeginLearning() (*SkillChange, error)

func (*ActorLearner) CancelLearning

func (l *ActorLearner) CancelLearning() error

func (*ActorLearner) EndLearning

func (l *ActorLearner) EndLearning() error

func (*ActorLearner) GainXPFloor

func (l *ActorLearner) GainXPFloor(floor int)

func (*ActorLearner) GainXPKill

func (l *ActorLearner) GainXPKill(mon *Obj)

func (*ActorLearner) GainXPSight

func (l *ActorLearner) GainXPSight(obj *Obj)

func (*ActorLearner) LearnSkill

func (l *ActorLearner) LearnSkill(sk SkillName) (*SkillChange, error)

func (*ActorLearner) TotalXP

func (l *ActorLearner) TotalXP() int

func (*ActorLearner) UnlearnSkill

func (l *ActorLearner) UnlearnSkill(sk SkillName) (*SkillChange, error)

func (*ActorLearner) XP

func (l *ActorLearner) XP() int

type ActorMover

type ActorMover struct {
	Trait
}

A universally-applicable mover for actors.

func (*ActorMover) Ascend

func (p *ActorMover) Ascend() bool

Try to go up stairs. If the current tile is not an upstair, return false.

func (*ActorMover) Descend

func (p *ActorMover) Descend() bool

Try to go down stairs. If the current tile is not an downstair, return false.

func (*ActorMover) Move

func (p *ActorMover) Move(dir math.Point) (bool, error)

Try to move the actor. Return err describing what happened if the actor could not physically move on the map; there may have been another event that had to happen instead that still requires a turn to pass (e.g. a door was opened, an attack was initiated.) If a turn should pass, the boolean return value from this function will be true. This idea of a 'turn passing' is in the context of the player's turn -- calling code can decide whether or not a monster's turn should be over, regardless of this value.

func (*ActorMover) Rest

func (p *ActorMover) Rest()

Rest a turn. If p is confused, there is still a chance that it will attempt to move. Calling this should always consume a turn.

type ActorPacker

type ActorPacker struct {
	Trait
	// contains filtered or unexported fields
}

An attacker that works for all actors.

func (*ActorPacker) Drop

func (a *ActorPacker) Drop(index int) bool

Returns false if no actual action was taken.

func (*ActorPacker) Inventory

func (a *ActorPacker) Inventory() *Inventory

func (*ActorPacker) Pickup

func (a *ActorPacker) Pickup(index int) bool

func (*ActorPacker) TryDrop

func (a *ActorPacker) TryDrop()

func (*ActorPacker) TryPickup

func (a *ActorPacker) TryPickup() bool

type ActorSenser

type ActorSenser struct {
	Trait
	// contains filtered or unexported fields
}

func (*ActorSenser) CalcFields

func (a *ActorSenser) CalcFields()

Calculates this actor's fields. If it's the player, they get FOV + scent. Monsters just get FOV. Instead of making two different Senser implementations to do this, we use simple branch in this method. If this is the player, calculating fields will also update the relevant bits on the map (scent, visibility.)

func (*ActorSenser) CanSee

func (a *ActorSenser) CanSee(other *Obj) bool

func (*ActorSenser) FOV

func (a *ActorSenser) FOV() Field

type ActorTicker

type ActorTicker struct {
	Trait

	// The effects currently active on this actor.
	Effects map[Effect]*ActiveEffect
	// contains filtered or unexported fields
}

func (*ActorTicker) AddEffect

func (t *ActorTicker) AddEffect(e Effect, counter int)

Adds a new active effect to this actor.

func (*ActorTicker) Counter

func (t *ActorTicker) Counter(e Effect) int

func (*ActorTicker) RemoveEffect

func (t *ActorTicker) RemoveEffect(e Effect) bool

func (*ActorTicker) Tick

func (t *ActorTicker) Tick(delay int)

type ActorUser

type ActorUser struct {
	Trait
}

func (*ActorUser) TryUse

func (a *ActorUser) TryUse()

func (*ActorUser) Use

func (a *ActorUser) Use(index int) bool

type AscendCommand

type AscendCommand struct{}

type Attack

type Attack struct {
	Melee   int
	Damroll Dice
	CritDiv int
	Effects Effects
	Verb    string
}

Details about an actor's melee attack, before the melee roll is applied -- i.e. what melee bonus + damage should be done if no crits happen? What's the base divisor to use for calculating # of crits? What base verb should we use if it hits? (This latter may be altered by applybs() based on which effects actually end up working.)

func (Attack) Describe

func (atk Attack) Describe() string

func (Attack) RollDamage

func (atk Attack) RollDamage(extradice int) int

Roll damage for this attack, given that `crits` crits were rolled.

type Body

type Body struct {
	Slots [numSlots]*Obj
}

func NewBody

func NewBody() *Body

func (*Body) ArmorEffects

func (b *Body) ArmorEffects() Effects

Accumulate all the effects on all of our armor.

func (*Body) Evasion

func (b *Body) Evasion() int

Get the total bonus/malus to evasion from equipment worn on this body.

func (*Body) Melee

func (b *Body) Melee() int

Get the total bonus/malus to melee from equipment worn on this body.

func (*Body) Naked

func (b *Body) Naked() bool

func (*Body) ProtDice

func (b *Body) ProtDice() []Dice

func (*Body) Remove

func (b *Body) Remove(slot Slot) *Obj

func (*Body) Weapon

func (b *Body) Weapon() *Obj

func (*Body) Wear

func (b *Body) Wear(item *Obj) *Obj

type CancelLearningCommand

type CancelLearningCommand struct{}

type Command

type Command interface{}

A command given _to_ the game.

type Consumable

type Consumable struct {
	Trait
	Consume ConsumeFunc
}

Consumable trait.

type ConsumeFunc

type ConsumeFunc func(user User)

Function that actually does something when this item gets used.

type Defense

type Defense struct {
	Evasion  int
	ProtDice []Dice
	CorrDice []Dice
	Effects  Effects
}

Details about an actor's defense, before the evasion roll is applied. i.e. what evasion bonus should be added and what protection dice should be rolled when attacked?

func (Defense) Describe

func (def Defense) Describe() string

func (Defense) RollProt

func (def Defense) RollProt() int

Rolls protection dice - corrosion dice

type DescendCommand

type DescendCommand struct{}

type Dice

type Dice struct {
	Dice  int
	Sides int
}

func NewDice

func NewDice(dice, sides int) Dice

func (Dice) Add

func (d Dice) Add(dice, sides int) Dice

func (Dice) Roll

func (d Dice) Roll() int

func (Dice) String

func (d Dice) String() string

type Dropper

type Dropper interface {
	DropItems()
}

A thing that drops items when it dies.

type Effect

type Effect uint

An effect is something that a monster or a piece of equipment can have. This includes, brands, resists, status effects, etc.

const (
	// Sentinel.
	EffectNone Effect = iota

	// Brands
	BrandFire
	BrandElec
	BrandIce
	BrandPoison
	BrandAcid

	// Slays
	SlayPearl
	SlayHunter
	SlayBattle
	SlayDispel

	// Effects
	EffectBaseRegen // Regen that is applied every tick to every actor.
	EffectStun
	EffectPoison
	EffectCut
	EffectBlind
	EffectSlow
	EffectConfuse
	EffectFear
	EffectPara
	EffectSilence
	EffectCurse
	EffectPetrify
	EffectBless
	EffectStim
	EffectHyper
	EffectVamp
	EffectShatter
	EffectDrainStr
	EffectDrainAgi
	EffectDrainVit
	EffectDrainMnd

	// Resists
	ResistFire
	ResistElec
	ResistIce
	ResistStun
	ResistPoison
	ResistBlind
	ResistSlow
	ResistConfuse
	ResistFear
	ResistPara
	ResistSilence
	ResistCurse
	ResistPetrify
	ResistCrit
	ResistVamp
	ResistAcid
	ResistDrain

	// Flags
	WeakPearl
	WeakHunter
	WeakBattle
	WeakDispel

	// Sentinel
	NumEffects
)

Brands, effects, resists, vulnerabilities found in the game.

type EffectInfo

type EffectInfo struct {
	*EffectSpec
	Count int
}

A single instance of an effect on a creature, attack, defense, etc.

type EffectSpec

type EffectSpec struct {
	Type       EffectType
	ResistedBy Effect
	Slays      Effect
}

Defines basic information about an effect -- i.e what type it is, and if it is an offensive effect or brand, what it is resisted by.

type EffectType

type EffectType uint

An effect 'type' is a grouping of that effect e.g. is it a brand, a status effect, etc.

type Effects

type Effects map[Effect]EffectInfo

A collection of effects on a monster, piece of equipment, etc.

func NewEffects

func NewEffects(counts map[Effect]int) Effects

Given a histogram of Effect -> resist/vuln count, this will create a Effects collection with the given counts in place.

func (Effects) Brands

func (effects Effects) Brands() Effects

Filters out the brands from this collection of effects.

func (Effects) Has

func (effects Effects) Has(effect Effect) int

Returns the number of 'pips' of this effect that this collection has.

func (Effects) Merge

func (e1 Effects) Merge(e2 Effects) Effects

Produces a new Effects that is the union of 'e1' and 'e2', accumulating the counts of each effect. This does not mutate either of the inputs.

func (Effects) ResistDmg

func (e Effects) ResistDmg(effect Effect, dmg int) int

Given the amount of raw damage done by an effect 'effect', this figures out how much damage should actually be done after resistances or vulnerabilities to 'effect' are taken into account.

func (Effects) Resists

func (effects Effects) Resists(effect Effect) int

How many pips of resistance do I have against 'effect'? This can be negative, which indicates a vulnerability to 'effect'.

func (Effects) SlainBy

func (effects Effects) SlainBy(effect Effect) int

Does our collection of effects contain a vulnerability to the slay 'effect'?

func (Effects) Slays

func (effects Effects) Slays() Effects

Filters out slays.

type EffectsSpec

type EffectsSpec map[Effect]*EffectSpec

Definition of _all_ effects and their types.

type Equipment

type Equipment struct {
	Trait
	Damroll  Dice
	Protroll Dice
	Melee    int
	Evasion  int
	Weight   int
	Slot     Slot
	Effects  Effects
}

Equipment trait.

type Equipper

type Equipper interface {
	Objgetter
	// Bring up the equipper screen if anything in inventory can be equipped.
	TryEquip()
	// Bring up the remover screen if anything on body can be removed.
	TryRemove()
	// Equip the item at index 'index' in inventory. Return true if a turn
	// should pass.
	Equip(index int) bool
	// Remove the item equipped in the given slot. Return true if a turn should
	// pass.
	Remove(slot Slot) bool
	// Get the underlying entity's Body.
	Body() *Body
}

func NewActorEquipper

func NewActorEquipper(obj *Obj) Equipper

type Event

type Event interface{}

Events are complex objects (unlike commands); you have to type-assert them to their concrete types to get at their payloads.

type EventQueue

type EventQueue struct {
	// contains filtered or unexported fields
}

A queue of events that are produced by the game and consumed by the client. There are first-class verbs on this queue for each of the event types that the game needs to send; nothing pushes directly to the queue.

func (*EventQueue) Empty

func (eq *EventQueue) Empty() bool

Is this queue empty of events?

func (*EventQueue) Len

func (eq *EventQueue) Len() int

The number of events waiting to be consumed.

func (*EventQueue) Message

func (eq *EventQueue) Message(msg string)

Send a message to be rendered in the message console.

func (*EventQueue) More

func (eq *EventQueue) More()

Tell client to force a --more-- confirm.

func (*EventQueue) Next

func (eq *EventQueue) Next() Event

The next event in the queue. Calling this will remove it from the queue and furnish the event as a result.

func (*EventQueue) SkillChange

func (eq *EventQueue) SkillChange(c *SkillChange)

func (*EventQueue) SwitchMode

func (eq *EventQueue) SwitchMode(mode Mode)

Tell client we're switching game modes to mode.

type Family

type Family string

e.g. "Actor", "Item"

type Feature

type Feature struct {
	Type   FeatureType
	Solid  bool
	Opaque bool
}

func (*Feature) String

func (f *Feature) String() string

type FeatureType

type FeatureType string

type Field

type Field []math.Point

type Fighter

type Fighter interface {
	Objgetter
	Hit(other Fighter)
}

Anything that fights in melee.

func NewActorFighter

func NewActorFighter(obj *Obj) Fighter

type FinishLearningCommand

type FinishLearningCommand struct{}

type Game

type Game struct {
	Player   *Obj
	Level    *Level
	Events   *EventQueue
	Progress *Progress
	// contains filtered or unexported fields
}

Backend for a single game.

func NewGame

func NewGame() *Game

Create a new game.

func (*Game) ChangeFloor

func (g *Game) ChangeFloor(dir int)

Switch floors on the player.

func (*Game) Handle

func (g *Game) Handle(c Command)

Handle a command from the client, and then evolve the world.

func (*Game) Kill

func (g *Game) Kill(actor *Obj)

func (*Game) NewObj

func (g *Game) NewObj(spec *Spec) *Obj

Create a new object for use in this game.

func (*Game) Start

func (g *Game) Start()

Temp convenience method to init the game before playing.

func (*Game) SwitchMode

func (g *Game) SwitchMode(m Mode)

type Gen

type Gen struct {
	Floors    []int
	GroupSize int
}

Stores everything you need to know about randomly generating this object ingame. 'Floors' is a list of the native floors of this object. 'GroupSize' means "pack size" for monsters and "stack size" for consumables.

func (Gen) Findable

func (g Gen) Findable(low, high int) bool

Should this entry be "findable" in the given range of floors?

func (Gen) First

func (g Gen) First() int

The first floor you can find this on.

type Genus

type Genus string

e.g. "Player", "Monster", "Potion"

type IntSource

type IntSource func(int) int

Thin wrapper over math/rand so that we can stub out in tests. This is basically "what do you want me to use as Intn(n)".

type Inventory

type Inventory struct {
	Items *list.List
	// contains filtered or unexported fields
}

A container that holds any type of item.

func NewInventory

func NewInventory() *Inventory

Create a new empty inventory with capacity `inventoryCapacity`.

func NewInventoryWithCap

func NewInventoryWithCap(capacity int) *Inventory

func (*Inventory) Add

func (inv *Inventory) Add(item *Obj) bool

Tries to add item to this inventory. Returns false if the item doesn't fit.

func (*Inventory) At

func (inv *Inventory) At(index int) *Obj

Peeks at the item at the given index without removing it. Returns nil if there is no item at that index.

func (*Inventory) EachItem

func (inv *Inventory) EachItem(f func(o *Obj))

Call f on each item in inventory.

func (*Inventory) Empty

func (inv *Inventory) Empty() bool

Is this inventory empty?

func (*Inventory) Full

func (inv *Inventory) Full() bool

Is this inventory at capacity?

func (*Inventory) HasEquipment

func (inv *Inventory) HasEquipment() bool

Does this inventory have anything to equip in it?

func (*Inventory) HasUsables

func (inv *Inventory) HasUsables() bool

Does this inventory have anything to use in it?

func (*Inventory) Len

func (inv *Inventory) Len() int

The number of items in this inventory.

func (*Inventory) Take

func (inv *Inventory) Take(index int) *Obj

Returns the item at index 'index' and removes it from the inventory. Returns nil if there was no item at the given index.

func (*Inventory) Top

func (inv *Inventory) Top() *Obj

Gets the item at the "top" of this inventory. This item can be used to visually represent the entire inventory if it is a floor stack, for example. Returns nil if inventory is empty.

type ItemDropper

type ItemDropper struct {
	Trait
	// contains filtered or unexported fields
}

func (*ItemDropper) DropItems

func (i *ItemDropper) DropItems()

type LearnSkillCommand

type LearnSkillCommand struct{ Skill SkillName }

type Learner

type Learner interface {
	XPGainer
	SkillLearner
}

Aggregate learner interface.

func NewActorLearner

func NewActorLearner(obj *Obj) Learner

Implementation of player's learner. Monsters don't need this because they don't gain or spend XP.

type Level

type Level struct {
	Map    Map
	Bounds math.Rectangle
	// contains filtered or unexported fields
}

func LynnRoomsLevel

func LynnRoomsLevel(l *Level) *Level

This implements lynn's algorithm for laying out angband-ish rooms without a lot of fuss.

The idea is to randomly place rooms, and then draw L-shaped corridors to connect them. The connection points are randomly-selected "joints" placed one-per-room.

We do this by: a) Creating and randomly placing an odd-sized room where it fits. We don't

allow new rooms to overlap existing rooms or corridors.

b) Selecting a random, odd-aligned joint in this new room. c) If there is at least one predecessor room, dig an L-shaped path between

the joints. At this stage, corridors are allowed to blast through
intervening rooms.

See http://i.imgur.com/WhmnByV.png for a terse graph-ical explanation.

func NewDungeon

func NewDungeon(g *Game) *Level

Generates a new dungeon level.

func NewLevel

func NewLevel(width, height int, game *Game, gen func(*Level) *Level) *Level

Create a level that uses the given game to create objects, generated by the given generator function.

func SquareLevel

func SquareLevel(l *Level) *Level

Generates a simple square test level suitable for unit tests.

func (*Level) Around

func (l *Level) Around(loc math.Point) []*Tile

Returns a list of the tiles "around" p (but not including p.)

func (*Level) At

func (l *Level) At(p math.Point) *Tile

func (*Level) Evolve

func (l *Level) Evolve()

Advances the game until the player's next turn.

func (*Level) FindPath

func (l *Level) FindPath(start, end math.Point, cost func(*Level, math.Point) int) (path Path, ok bool)

Finds a reasonably direct path between start and dest in this level. If no path could be found, 'path' will be zero and 'ok' will be false. This uses Dijkstra's algorithm.

func (*Level) HasPoint

func (l *Level) HasPoint(p math.Point) bool

func (*Level) Place

func (l *Level) Place(o *Obj, p math.Point) bool

Place `o` on the tile at `p`. Returns false if this is impossible (e.g. trying to put something on a solid square.) This will remove `o` from any tile on any map it was previously on.

func (*Level) RandomClearTile

func (l *Level) RandomClearTile() *Tile

func (*Level) Remove

func (l *Level) Remove(o *Obj)

Removes 'o' from the level.

func (*Level) SwapActors

func (l *Level) SwapActors(x *Obj, y *Obj)

func (*Level) UpdateScent

func (l *Level) UpdateScent(scent Field)

Update the player's smell on the map.

func (*Level) UpdateVis

func (l *Level) UpdateVis(fov Field)

Update what the player can see. Also notify the player's learner of what it has seen.

type Map

type Map [][]*Tile
type MenuCommand struct{ Option int }

type MessageEvent

type MessageEvent struct {
	Text string
}

A message that we want to show up in the message console.

type Mode

type Mode int

Modes that the game can be in.

const (
	ModeHud Mode = iota
	ModeInventory
	ModePickup
	ModeEquip
	ModeRemove
	ModeDrop
	ModeUse
	ModeSheet
	ModeGameOver
)

type ModeCommand

type ModeCommand struct{ Mode Mode }

type ModeEvent

type ModeEvent struct {
	Mode Mode
}

Tells the client that we've switched game 'modes'.

type MonsterAttack

type MonsterAttack struct {
	Attack
	// How relatively frequently should we use this attack?
	P int
}

A spec for a monster attack.

func (*MonsterAttack) Weight

func (m *MonsterAttack) Weight() int

type MonsterSheet

type MonsterSheet struct {
	Trait
	// contains filtered or unexported fields
}

Sheet used for monsters, which have a lot of hardcoded attributes.

func (*MonsterSheet) Afraid

func (m *MonsterSheet) Afraid() bool

func (*MonsterSheet) Attack

func (m *MonsterSheet) Attack() Attack

func (*MonsterSheet) Blessed

func (p *MonsterSheet) Blessed() bool

func (*MonsterSheet) Blind

func (m *MonsterSheet) Blind() bool

func (*MonsterSheet) CanAct

func (m *MonsterSheet) CanAct() bool

func (*MonsterSheet) ChangeSkillMod

func (m *MonsterSheet) ChangeSkillMod(skill SkillName, diff int)

func (*MonsterSheet) ChangeStatMod

func (m *MonsterSheet) ChangeStatMod(stat StatName, diff int)

func (*MonsterSheet) Confused

func (m *MonsterSheet) Confused() bool

func (*MonsterSheet) Copy

func (m *MonsterSheet) Copy() *MonsterSheet

Make a deep copy of this sheet.

func (*MonsterSheet) Corrosion

func (m *MonsterSheet) Corrosion() int

func (*MonsterSheet) Cursed

func (p *MonsterSheet) Cursed() bool

func (*MonsterSheet) Dead

func (m *MonsterSheet) Dead() bool

func (*MonsterSheet) Defense

func (m *MonsterSheet) Defense() Defense

func (*MonsterSheet) HP

func (m *MonsterSheet) HP() int

func (*MonsterSheet) Heal

func (m *MonsterSheet) Heal(amt int)

func (*MonsterSheet) HealMP

func (m *MonsterSheet) HealMP(amt int)

func (*MonsterSheet) Hurt

func (m *MonsterSheet) Hurt(dmg int)

func (*MonsterSheet) HurtMP

func (m *MonsterSheet) HurtMP(amt int)

func (*MonsterSheet) MP

func (m *MonsterSheet) MP() int

func (*MonsterSheet) MaxHP

func (m *MonsterSheet) MaxHP() int

func (*MonsterSheet) MaxMP

func (m *MonsterSheet) MaxMP() int

func (*MonsterSheet) Paralyzed

func (m *MonsterSheet) Paralyzed() bool

func (*MonsterSheet) Petrified

func (m *MonsterSheet) Petrified() bool

func (*MonsterSheet) Regen

func (m *MonsterSheet) Regen() int

func (*MonsterSheet) SetAfraid

func (m *MonsterSheet) SetAfraid(fear bool)

func (*MonsterSheet) SetBlessed

func (p *MonsterSheet) SetBlessed(b bool)

func (*MonsterSheet) SetBlind

func (m *MonsterSheet) SetBlind(b bool)

func (*MonsterSheet) SetConfused

func (m *MonsterSheet) SetConfused(conf bool)

func (*MonsterSheet) SetCorrosion

func (m *MonsterSheet) SetCorrosion(amt int)

func (*MonsterSheet) SetCursed

func (p *MonsterSheet) SetCursed(c bool)

func (*MonsterSheet) SetParalyzed

func (m *MonsterSheet) SetParalyzed(b bool)

func (*MonsterSheet) SetPetrified

func (m *MonsterSheet) SetPetrified(p bool)

func (*MonsterSheet) SetSilenced

func (m *MonsterSheet) SetSilenced(sil bool)

func (*MonsterSheet) SetSkill

func (m *MonsterSheet) SetSkill(skill SkillName, amt int)

func (*MonsterSheet) SetSlow

func (m *MonsterSheet) SetSlow(s bool)

func (*MonsterSheet) SetStat

func (m *MonsterSheet) SetStat(stat StatName, amt int)

func (*MonsterSheet) SetStun

func (m *MonsterSheet) SetStun(level StunLevel)

func (*MonsterSheet) Sight

func (m *MonsterSheet) Sight() int

func (*MonsterSheet) Silenced

func (m *MonsterSheet) Silenced() bool

func (*MonsterSheet) Skill

func (m *MonsterSheet) Skill(skill SkillName) int

func (*MonsterSheet) SkillMod

func (m *MonsterSheet) SkillMod(skill SkillName) int

func (*MonsterSheet) Slow

func (m *MonsterSheet) Slow() bool

func (*MonsterSheet) Speed

func (m *MonsterSheet) Speed() int

func (*MonsterSheet) Stat

func (m *MonsterSheet) Stat(stat StatName) int

func (*MonsterSheet) StatMod

func (m *MonsterSheet) StatMod(stat StatName) int

func (*MonsterSheet) Stun

func (m *MonsterSheet) Stun() StunLevel

func (*MonsterSheet) UnmodSkill

func (m *MonsterSheet) UnmodSkill(skill SkillName) int

func (*MonsterSheet) UnmodStat

func (m *MonsterSheet) UnmodStat(stat StatName) int

type MoreEvent

type MoreEvent struct {
}

Force the player to --more--.

type MoveCommand

type MoveCommand struct{ Dir math.Point }

type Mover

type Mover interface {
	Objgetter
	Move(dir math.Point) (bool, error)
	Rest()
	Ascend() bool
	Descend() bool
}

A thing that can move given a specific direction.

func NewActorMover

func NewActorMover(obj *Obj) Mover

Constructor for actor movers.

type NoCommand

type NoCommand struct{}

type Obj

type Obj struct {
	Spec *Spec

	Tile  *Tile
	Level *Level
	Game  *Game
	Seen  bool

	// Actor traits.
	Mover    Mover
	AI       AI
	Sheet    Sheet
	Fighter  Fighter
	Packer   Packer
	Equipper Equipper
	User     User
	Senser   Senser
	Ticker   Ticker
	Dropper  Dropper
	Learner  Learner

	// Item traits. Since these don't ever conceivably need alternate
	// implementations, they are not interface types.
	Equipment  *Equipment
	Consumable *Consumable
	// contains filtered or unexported fields
}

Specifically, an in-game object that can be placed on a map and can Do Something. Its traits determine what it can do.

func (*Obj) IsPlayer

func (o *Obj) IsPlayer() bool

Does this object represent the player?

func (*Obj) Pos

func (o *Obj) Pos() math.Point

What point on the map is this object on?

func (*Obj) String

func (o *Obj) String() string

type Objgetter

type Objgetter interface {
	Obj() *Obj
}

Trait basics; the ability to backreference the attached object.

type Packer

type Packer interface {
	Objgetter
	// Tries to pickup something at current square. If there are many things,
	// will invoke stack menu. Returns true if a turn should pass because the
	// player picked up a single item below them without switching modes.
	TryPickup() bool
	// Pickup the item on the floor stack at given index. Return true if a turn
	// should pass.
	Pickup(index int) bool
	// Tries to drop something at current square.
	TryDrop()
	// Drop the item at index in inventory to the floor stack. Return true if
	// an action was taken that requires a turn to pass.
	Drop(index int) bool
	// Get this Packer's inventory.
	Inventory() *Inventory
}

A thing that that can hold items in inventory. (A "pack".)

func NewActorPacker

func NewActorPacker(obj *Obj) Packer

type Path

type Path []math.Point

Return type of FindPath. This is what you follow to travel the found route.

type Personality

type Personality struct {

	// Roughly how many turns will I spend chasing a player by smell, out of
	// LOS? 0 means I'll only chase in LOS.
	Persistence int
	// What percent HP do I need to be at before I run away? '25' means '25%'.
	Fear int
	// contains filtered or unexported fields
}

Stuff that this AI likes to do.

type PlayerSheet

type PlayerSheet struct {
	Trait
	// contains filtered or unexported fields
}

Sheet used for player, which has a lot of derived attributes.

func NewPlayerSheetFromSpec

func NewPlayerSheetFromSpec(pspec *PlayerSheet) *PlayerSheet

For testing.

func (*PlayerSheet) Afraid

func (p *PlayerSheet) Afraid() bool

func (*PlayerSheet) Attack

func (p *PlayerSheet) Attack() Attack

func (*PlayerSheet) Blessed

func (p *PlayerSheet) Blessed() bool

func (*PlayerSheet) Blind

func (p *PlayerSheet) Blind() bool

func (*PlayerSheet) CanAct

func (p *PlayerSheet) CanAct() bool

func (*PlayerSheet) ChangeSkillMod

func (p *PlayerSheet) ChangeSkillMod(skill SkillName, diff int)

func (*PlayerSheet) ChangeStatMod

func (p *PlayerSheet) ChangeStatMod(stat StatName, diff int)

func (*PlayerSheet) Confused

func (p *PlayerSheet) Confused() bool

func (*PlayerSheet) Copy

func (p *PlayerSheet) Copy() *PlayerSheet

func (*PlayerSheet) Corrosion

func (p *PlayerSheet) Corrosion() int

func (*PlayerSheet) Cursed

func (p *PlayerSheet) Cursed() bool

func (*PlayerSheet) Dead

func (p *PlayerSheet) Dead() bool

func (*PlayerSheet) Defense

func (p *PlayerSheet) Defense() Defense

func (*PlayerSheet) HP

func (p *PlayerSheet) HP() int

func (*PlayerSheet) Heal

func (p *PlayerSheet) Heal(amt int)

func (*PlayerSheet) HealMP

func (p *PlayerSheet) HealMP(amt int)

func (*PlayerSheet) Hurt

func (p *PlayerSheet) Hurt(dmg int)

func (*PlayerSheet) HurtMP

func (p *PlayerSheet) HurtMP(amt int)

func (*PlayerSheet) MP

func (p *PlayerSheet) MP() int

func (*PlayerSheet) MaxHP

func (p *PlayerSheet) MaxHP() int

func (*PlayerSheet) MaxMP

func (p *PlayerSheet) MaxMP() int

func (*PlayerSheet) Paralyzed

func (p *PlayerSheet) Paralyzed() bool

func (*PlayerSheet) Petrified

func (p *PlayerSheet) Petrified() bool

func (*PlayerSheet) Regen

func (p *PlayerSheet) Regen() int

func (*PlayerSheet) SetAfraid

func (p *PlayerSheet) SetAfraid(fear bool)

func (*PlayerSheet) SetBlessed

func (p *PlayerSheet) SetBlessed(b bool)

func (*PlayerSheet) SetBlind

func (p *PlayerSheet) SetBlind(b bool)

func (*PlayerSheet) SetConfused

func (p *PlayerSheet) SetConfused(conf bool)

func (*PlayerSheet) SetCorrosion

func (p *PlayerSheet) SetCorrosion(amt int)

func (*PlayerSheet) SetCursed

func (p *PlayerSheet) SetCursed(c bool)

func (*PlayerSheet) SetParalyzed

func (p *PlayerSheet) SetParalyzed(para bool)

func (*PlayerSheet) SetPetrified

func (p *PlayerSheet) SetPetrified(pet bool)

func (*PlayerSheet) SetSilenced

func (p *PlayerSheet) SetSilenced(sil bool)

func (*PlayerSheet) SetSkill

func (p *PlayerSheet) SetSkill(skill SkillName, amt int)

func (*PlayerSheet) SetSlow

func (p *PlayerSheet) SetSlow(s bool)

func (*PlayerSheet) SetStat

func (p *PlayerSheet) SetStat(stat StatName, amt int)

func (*PlayerSheet) SetStun

func (p *PlayerSheet) SetStun(level StunLevel)

func (*PlayerSheet) Sight

func (p *PlayerSheet) Sight() int

func (*PlayerSheet) Silenced

func (p *PlayerSheet) Silenced() bool

func (*PlayerSheet) Skill

func (p *PlayerSheet) Skill(skill SkillName) int

func (*PlayerSheet) SkillMod

func (p *PlayerSheet) SkillMod(skill SkillName) int

func (*PlayerSheet) Slow

func (p *PlayerSheet) Slow() bool

func (*PlayerSheet) Speed

func (p *PlayerSheet) Speed() int

func (*PlayerSheet) Stat

func (p *PlayerSheet) Stat(stat StatName) int

func (*PlayerSheet) StatMod

func (p *PlayerSheet) StatMod(stat StatName) int

func (*PlayerSheet) Stun

func (p *PlayerSheet) Stun() StunLevel

func (*PlayerSheet) UnmodSkill

func (p *PlayerSheet) UnmodSkill(skill SkillName) int

func (*PlayerSheet) UnmodStat

func (p *PlayerSheet) UnmodStat(stat StatName) int

type Progress

type Progress struct {
	// Floor player is on.
	Floor int
	// Floor player was previously on.
	PrevFloor int
	// The highest floor this player has been on.
	MaxFloor int
	// How many turns have passed.
	Turns int
}

func (*Progress) ChangeFloor

func (p *Progress) ChangeFloor(dir int) bool

Change floor. Returns `true` if this is higher than the player has gone before.

type QuitCommand

type QuitCommand struct{}

type RestCommand

type RestCommand struct{}

type SMAI

type SMAI struct {
	Trait
	// Fixed attributes for this AI.
	Personality *Personality
	// My behaviour in the form of a state machine.
	Brain SMAIStateMachine
	// contains filtered or unexported fields
}

State-machine-based "AI".

func (*SMAI) Act

func (s *SMAI) Act() bool

func (*SMAI) Init

func (s *SMAI) Init()

type SMAIStateMachine

type SMAIStateMachine map[smaiKey]smaiState

A specification of a certain behaviour.

type SQ

type SQ []*scheduled

Shoehorning into container/heap's interface. SQ acts as the actual priority queue.

func (SQ) Less

func (s SQ) Less(i, j int) bool

func (*SQ) Pop

func (s *SQ) Pop() interface{}

func (*SQ) Push

func (s *SQ) Push(x interface{})

func (SQ) Swap

func (s SQ) Swap(i, j int)

type Scheduler

type Scheduler struct {
	// contains filtered or unexported fields
}

Schedules which actors should act when.

func NewScheduler

func NewScheduler() *Scheduler

func (*Scheduler) Add

func (s *Scheduler) Add(actor *Obj)

Add an actor to the schedule.

func (*Scheduler) EachActor

func (s *Scheduler) EachActor(f func(o *Obj))

Runs f on each actor in the scheduler. Be careful with this, we assume you're not doing anything that should affect the schedule at all. We do this instead of passing back a slice of actors so that we don't have to accumulate them out of the heap. Also, it just seemed fun. Sorry.

func (*Scheduler) Len

func (s *Scheduler) Len() int

func (*Scheduler) Next

func (s *Scheduler) Next() *Obj

Picks the next actor to act, and moves time forward for everyone else.

func (*Scheduler) Remove

func (s *Scheduler) Remove(actor *Obj)

Removes an actor from the scheduler.

type Senser

type Senser interface {
	Objgetter
	CalcFields()
	FOV() Field
	CanSee(other *Obj) bool
}

Senses all the things an actor can sense.

func NewActorSenser

func NewActorSenser(obj *Obj) Senser

type Sheet

type Sheet interface {
	Objgetter

	// Get the total value for statistic 'stat', including mods.
	Stat(stat StatName) int
	// Set the base value for statistic 'stat'.
	SetStat(stat StatName, amt int)

	// Get the unmodified (base) value of statistic 'stat'.
	UnmodStat(stat StatName) int
	// Get the mod for statistic 'stat'.
	StatMod(stat StatName) int
	// Change the mod for 'stat' by 'diff'.
	ChangeStatMod(stat StatName, diff int)

	// Get the total value for skill 'skill', including mods.
	Skill(skill SkillName) int
	// Set the base value for skill 'skill'.
	SetSkill(skill SkillName, amt int)

	// Get the unmodified (base) value of skill 'skill'.
	UnmodSkill(skill SkillName) int
	// Get the mod for skill 'skill'.
	SkillMod(skill SkillName) int
	// Change the mod for skill 'skill'.
	ChangeSkillMod(skill SkillName, diff int)

	// Get information about this actor's melee attack capability.
	Attack() Attack
	// Get information about this actor's defensive capability.
	Defense() Defense

	// Get this actor's current HP.
	HP() int

	// Get this actor's maximum HP.
	MaxHP() int

	// Does this actor still have > 0 HP?
	Dead() bool

	// Remove 'dmg' hitpoints. Will kill the actor if HP falls <= 0.
	Hurt(dmg int)
	// Heal 'amt' hp; actor's hp will not exceed maxhp.
	Heal(amt int)

	// Get this actor's current MP.
	MP() int

	// Get this actor's current MP.
	MaxMP() int

	// Remove 'amt' mp. Will clamp MP to 0.
	HurtMP(amt int)
	// Add 'amt' mp; actor's mp will not exceed maxmp.
	HealMP(amt int)

	// Regen factor. Normal healing is 1; 2 is twice as fast, etc.
	// 0 means no regen.
	Regen() int

	// How stunned is this actor? See StunLevel definition to see what each
	// level means.
	Stun() StunLevel
	// Set stun level. Effects are documented with the stun level definitions
	// in this module.
	SetStun(lvl StunLevel)

	Blind() bool
	SetBlind(blind bool)

	Slow() bool
	SetSlow(slow bool)

	Confused() bool
	SetConfused(conf bool)

	Afraid() bool
	SetAfraid(fear bool)

	Paralyzed() bool
	SetParalyzed(para bool)

	Petrified() bool
	SetPetrified(para bool)

	Silenced() bool
	SetSilenced(sil bool)

	Cursed() bool
	SetCursed(c bool)

	// #blessed
	Blessed() bool
	SetBlessed(c bool)

	Corrosion() int
	SetCorrosion(level int)

	// Sight radius.
	Sight() int

	// Get this actor's current speed.
	// 1: Slow (0.5x normal)
	// 2: Normal
	// 3: Fast (1.5x normal)
	// 4: Very fast (2.x normal)
	Speed() int

	// Can this actor do stuff right now. This is false if they are paralyzed,
	// asleep, etc.
	CanAct() bool
	// contains filtered or unexported methods
}

A 'character sheet' for an actor. Basically, all the attributes for an actor that are required to make calculations and game decisions live here.

func NewPlayerSheet

func NewPlayerSheet(obj *Obj) Sheet

type SkillChange

type SkillChange struct {
	TotalCost int
	Changes   map[SkillName]SkillChangeItem
}

Stores the state of a player's current request to upgrade their skills by spending XP.

type SkillChangeEvent

type SkillChangeEvent struct {
	Change *SkillChange
}

Sent while editing skills.

type SkillChangeItem

type SkillChangeItem struct {
	Points int
	Cost   int
}

type SkillLearner

type SkillLearner interface {
	// Start buying skills. This cannot be called again until CancelLearning or
	// EndLearning has been called.
	BeginLearning() (*SkillChange, error)
	// Buy 1 point of sk. If this costs too much, the existing change will be
	// returned along with ErrNotEnoughXP.  Otherwise, will return the current
	// state of the skillchange being requested. This will spend xp and change
	// skill allocations on the character sheet -- these changes will be
	// reverted if CancelLearning is called. Will return
	// ErrNotLearning as err if BeginLearning() was not called before this.
	LearnSkill(sk SkillName) (*SkillChange, error)
	// Refund 1 point of sk. This is only allowed if some of sk has already
	// been bought -- will return the current change and ErrNoPointsLearned if
	// not. Otherwise, will return the current state of the skillchange being
	// requested. This will refund xp and change skill allocations on the
	// character sheet -- these changes will be reverted if CancelLearning is
	// called. Will return ErrNotLearning as err if BeginLearning() was not
	// called before this.
	UnlearnSkill(sk SkillName) (*SkillChange, error)
	// Cancel the current learning change. This will return the character sheet
	// back to what it was before the changes were proposed. It is safe to call
	// BeginLearning again after this has been called.
	CancelLearning() error
	// Finalize the learning changes. It is safe to call BeginLearning again
	// after this has been called.
	EndLearning() error
}

Something that can "spend" XP to increase skill points.

type SkillName

type SkillName uint

Index into stats arrays.

const (
	// Called FIGHT in the game, but that is nasty to grep.
	Melee SkillName = iota
	// Called DODGE in the game, but also very verby.
	Evasion
	// SHOOT
	Shooting
	// SNEAK
	Stealth
	// CHI
	Chi
	// SENSE
	Sense
	// MAGIC
	Magic
	// SONG
	Song
	// Sentinel.
	NumSkills
)

The actual stats our actors have.

type Slot

type Slot int

Slots where items are worn/wielded on an actor's body.

type Spec

type Spec struct {
	Family  Family
	Genus   Genus
	Species Species
	Name    string
	Traits  *Traits
	Gen     Gen
}

A specification for a type of game object.

type Species

type Species string

e.g. "Orc", "HealPotion"

func (Species) Describe

func (species Species) Describe() string

type StartLearningCommand

type StartLearningCommand struct{}

type StatName

type StatName uint

Index into stats arrays.

const (
	Str StatName = iota
	Agi
	Vit
	Mnd
	NumStats
)

The actual stats our actors have.

type StunLevel

type StunLevel uint
const (
	// Not stunned, no effect.
	NotStunned StunLevel = iota
	// -2 to all skills
	Stunned
	// -4 to all skills
	MoreStunned
)

Stun status definitions.

type Ticker

type Ticker interface {
	Objgetter
	// Notify the actor that 'delay' time has passed. This must be called
	// exactly once per actor turn, before the actor acts.
	Tick(delay int)
	// Add an active effect to this actor for a duration of 'counter'. It is up
	// to the corresponding ActiveEffect to decide how to interpret the units
	// of counter (may be in delay, may be in turns, etc.)
	AddEffect(e Effect, counter int)
	// Forcibly remove an activeeffect, if it exists. Returns 'true' if there
	// was a nonzero counter to remove.
	RemoveEffect(e Effect) bool
	// What is the counter remaining for the current effect?
	Counter(e Effect) int
}

Does all of the required upkeep to an actor before they take their turn.

func NewActorTicker

func NewActorTicker(obj *Obj) Ticker

type Tile

type Tile struct {
	Feature *Feature
	Actor   *Obj
	Items   *Inventory
	Pos     math.Point
	Visible bool
	Seen    bool
	Scent   int
}

func (*Tile) String

func (t *Tile) String() string

type Trait

type Trait struct {
	// contains filtered or unexported fields
}

func (*Trait) Obj

func (t *Trait) Obj() *Obj

type Traits

type Traits struct {
	Mover    func(*Obj) Mover
	AI       func(*Obj) AI
	Sheet    func(*Obj) Sheet
	Fighter  func(*Obj) Fighter
	Packer   func(*Obj) Packer
	Equipper func(*Obj) Equipper
	User     func(*Obj) User
	Senser   func(*Obj) Senser
	Ticker   func(*Obj) Ticker
	Dropper  func(*Obj) Dropper
	Learner  func(*Obj) Learner

	Equipment  func(*Obj) *Equipment
	Consumable func(*Obj) *Consumable
}

A specification object for newObj. Each key maps to a factory function for the specific implementation of the desired trait. If an object is not supposed to have a specific trait, leave it unspecified.

type TryDropCommand

type TryDropCommand struct{}

type TryEquipCommand

type TryEquipCommand struct{}

type TryPickupCommand

type TryPickupCommand struct{}

type TryRemoveCommand

type TryRemoveCommand struct{}

type TryUseCommand

type TryUseCommand struct{}

type UnlearnSkillCommand

type UnlearnSkillCommand struct{ Skill SkillName }

type User

type User interface {
	Objgetter
	// Bring up the 'use' screen if anything in inventory can be used.
	TryUse()
	// Use the item at index 'index' in inventory. Return true if a turn should
	// pass.
	Use(index int) bool
}

A thing that can use single-use things.

func NewActorUser

func NewActorUser(obj *Obj) User

type Weighter

type Weighter interface {
	Weight() int
}

func WChoose

func WChoose(choices []Weighter) (pos int, chosen Weighter)

Selects 1 item from a weighted list of choices. In the weighted list {a: 1, b: 2, c: 1}, we'd expect to see a selected 25% of the time, b selected 50% of the time, and c selected 25% of the time.

type XPGainer

type XPGainer interface {
	// Call this when a specific instance of an item or monster has been seen.
	GainXPSight(obj *Obj)
	// Call this when a specific instance of a monster has been seen.
	GainXPKill(mon *Obj)
	// Gain XP for seeing a new floor.
	GainXPFloor(floor int)
	// How much XP does this actor have?
	XP() int
	// How much have they accumulated in total?
	TotalXP() int
}

Something that gains XP from new experiences.

Jump to

Keyboard shortcuts

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