Files
Programming-Game-AI-by-Exam…/chapter-2-state-driven-agent-design/westworld/state_quench_thirst.go
T
jonas 2764849943 feat: add Chapter 2 gold miner FSM example in Go
Port the finite state machine from "Programming Game AI by Example"
chapter 2: BaseGameEntity, a generic State[T]/StateMachine[T] pair
(Go generics standing in for the book's C++ templates), and a Miner
that cycles through digging, banking, sleeping, and drinking states.
VisitBankAndDepositGold, GoHomeAndSleepTilRested, and QuenchThirst
are original implementations based on the book's written behavior
description, since their C++ source wasn't available. Includes a
runnable demo in main.go.
2026-09-03 11:36:05 +02:00

54 lines
1.6 KiB
Go

package westworld
import (
"fmt"
"sync"
)
// quenchThirst is the Go version of the (not yet pasted) singleton
// class QuenchThirst from the book. Same pattern as
// enterMineAndDigForNugget: unexported type, one shared instance,
// reached only through the function below.
type quenchThirst struct{}
var (
quenchThirstInstance *quenchThirst
quenchThirstOnce sync.Once
)
// QuenchThirst is the Go stand-in for "QuenchThirst::Instance()".
func QuenchThirst() *quenchThirst {
quenchThirstOnce.Do(func() {
quenchThirstInstance = &quenchThirst{}
})
return quenchThirstInstance
}
var _ State[Miner] = (*quenchThirst)(nil)
// The book hasn't shown us this state's real code, so this is our
// own implementation based purely on its written description: "he
// visits the saloon in order to buy a whiskey. When his thirst is
// quenched, he changes state to EnterMineAndDigForNugget."
// Enter sends the miner to the saloon, if he isn't there already.
func (s *quenchThirst) Enter(m *Miner) {
if m.Location() != saloon {
fmt.Printf("\n%s: Headin' to the saloon for a whiskey", GetNameOfEntity(m.ID()))
m.ChangeLocation(saloon)
}
}
// Execute buys and drinks one whiskey, which is all it takes to
// quench the thirst, then goes straight back to digging.
func (s *quenchThirst) Execute(m *Miner) {
fmt.Printf("\n%s: That's mighty fine sippin' liquor", GetNameOfEntity(m.ID()))
m.BuyAndDrinkAWhiskey()
m.ChangeState(EnterMineAndDigForNugget())
}
// Exit announces that the miner is leaving the saloon.
func (s *quenchThirst) Exit(m *Miner) {
fmt.Printf("\n%s: Leavin' the saloon, feelin' good", GetNameOfEntity(m.ID()))
}