~nromdotcom/gemif

66f404282e7ddae188b2f63de0478bc7738c035b — Norm MacLennan 11 months ago 7757494
Minor refactor to move things out of GameManager and into the components they actually belong
3 files changed, 40 insertions(+), 46 deletions(-)

M pkg/gamemanager/gamemanager.go
M pkg/gamemanager/gamestate.go
M pkg/gamemanager/room.go
M pkg/gamemanager/gamemanager.go => pkg/gamemanager/gamemanager.go +3 -46
@@ 72,40 72,6 @@ func (gm *GameManager) GetRoomByID(storyID string, roomID string) (Room, error) 
	return Room{}, fmt.Errorf("%w: %s", ErrRoomNotFound, roomID)
}

// UseExit mutates gameState based on the selected exitID.
func (gm *GameManager) UseExit(gameState GameState, exitID string) (GameState, error) {
	currentRoom, err := gm.GetRoomByID(gameState.StoryID, gameState.CurrentRoom)
	if err != nil {
		return GameState{}, fmt.Errorf("couldn't find room %s in story %s: %w", gameState.CurrentRoom, gameState.StoryID, err)
	}

	for _, e := range currentRoom.Exits {
		if e.ID == exitID {
			if e.IfCondition != "" && !gameState.ConditionMet(e.IfCondition) {
				fmt.Printf("Cant use exit %s due to not meeting condition\n", e.ID)

				continue
			}

			if e.NotCondition != "" && gameState.ConditionMet(e.NotCondition) {
				fmt.Printf("Can't use exit %s due to meeting condition\n", e.ID)

				continue
			}

			gameState.CurrentRoom = e.Destination

			if e.SetCondition != "" {
				gameState.MeetCondition(e.SetCondition)
			}

			return gameState, nil
		}
	}

	return GameState{}, fmt.Errorf("%w: %s", ErrExitNotFound, exitID)
}

// DeserializeState converts a stateToken into a GameState.
func (gm *GameManager) DeserializeState(stateToken string) (GameState, error) {
	decodedString, decodeErr := base64.StdEncoding.DecodeString(stateToken)


@@ 163,18 129,9 @@ func (gm *GameManager) SerializeState(gameState GameState) (string, error) {
func (gm *GameManager) ConstructSpeculativeStates(gameState GameState, currentRoom Room) ([]SpeculativeState, error) {
	speculativeStates := make([]SpeculativeState, len(currentRoom.Exits))

	for i, e := range currentRoom.Exits {
		if e.IfCondition != "" && !gameState.ConditionMet(e.IfCondition) {
			continue
		}
		if e.NotCondition != "" && gameState.ConditionMet(e.NotCondition) {
			continue
		}

		newState, exitErr := gm.UseExit(gameState, e.ID)
		if exitErr != nil {
			return speculativeStates, fmt.Errorf("trouble using exit %s: %w", e.ID, exitErr)
		}
	usableExits := currentRoom.filterExits(gameState)
	for i, e := range usableExits {
		newState := gameState.UseExit(e)

		token, serializeErr := gm.SerializeState(newState)
		if serializeErr != nil {

M pkg/gamemanager/gamestate.go => pkg/gamemanager/gamestate.go +13 -0
@@ 19,6 19,19 @@ func (gs GameState) ConditionMet(cond string) bool {
	return isInSlice(gs.Conditions, cond)
}

// UseExit applies an exit's consequences to the GameState
// to produce a new GameState.
func (gs GameState) UseExit(exit Exit) GameState {
	newState := gs
	newState.CurrentRoom = exit.Destination

	if exit.SetCondition != "" {
		newState.MeetCondition(exit.SetCondition)
	}

	return newState
}

func isInSlice(slice []string, val string) bool {
	for _, item := range slice {
		if item == val {

M pkg/gamemanager/room.go => pkg/gamemanager/room.go +24 -0
@@ 1,5 1,7 @@
package gamemanager

import "fmt"

// Room contains information about a room and its Exits.
type Room struct {
	ID          string `yaml:"room_id" json:"room_id" binding:"uuid"`


@@ 17,3 19,25 @@ type Exit struct {
	IfCondition  string `yaml:"if_condition,omitempty" json:"if_condition"`
	NotCondition string `yaml:"not_condition,omitempty" json:"not_condition"`
}

func (r Room) filterExits(gameState GameState) []Exit {
	usableExits := []Exit{}

	for _, e := range r.Exits {
		if e.IfCondition != "" && !gameState.ConditionMet(e.IfCondition) {
			fmt.Printf("Cant use exit %s due to not meeting condition\n", e.ID)

			continue
		}

		if e.NotCondition != "" && gameState.ConditionMet(e.NotCondition) {
			fmt.Printf("Can't use exit %s due to meeting condition\n", e.ID)

			continue
		}

		usableExits = append(usableExits, e)
	}

	return usableExits
}