package game import ( "fmt" "strings" "thehouseoficarus/internal/net" "thehouseoficarus/internal/player" ) type HackingMinigame interface { Init(level int) string HandleInput(input string) (output string, done bool, won bool) Name() string } type XPBonuser interface { BonusXP() int } type HackingSession struct { Minigame HackingMinigame TerminalID string Level int ReqLevel int Started bool } type TerminalDef struct { ObjectID string Level int Minigame func() HackingMinigame BaseXPWin int BaseXPLose int Name string } var terminalDefs = map[string]TerminalDef{ "terminal_basic": { ObjectID: "terminal_basic", Level: 1, Minigame: func() HackingMinigame { return NewWumpusGame() }, BaseXPWin: 50, BaseXPLose: 10, Name: "Hunt the Wumpus", }, "terminal_advanced": { ObjectID: "terminal_advanced", Level: 20, Minigame: func() HackingMinigame { return NewMastermindGame() }, BaseXPWin: 150, BaseXPLose: 30, Name: "Code Breaker", }, "terminal_secure": { ObjectID: "terminal_secure", Level: 40, Minigame: func() HackingMinigame { return NewLiarsDiceGame() }, BaseXPWin: 300, BaseXPLose: 50, Name: "Signal Bluff", }, } func (g *Game) handleHackingInput(sess *net.Session, input string) { p, ok := sess.Player.(*player.Player) if !ok { sess.State = net.StateGame return } hs, ok := g.hackingStates[p.Name] if !ok { sess.State = net.StateGame g.writePrompt(sess) return } input = strings.TrimSpace(input) lower := strings.ToLower(input) if lower == "jack out" || lower == "quit" || lower == "disconnect" { g.endHacking(sess, p, false, false) return } hs.Started = true output, done, won := hs.Minigame.HandleInput(input) sess.WriteLine(output) if done { g.endHacking(sess, p, true, won) return } sess.Write("\nhack> ") } func (g *Game) endHacking(sess *net.Session, p *player.Player, completed bool, won bool) { hs, ok := g.hackingStates[p.Name] if !ok { sess.State = net.StateGame g.writePrompt(sess) return } tDef := terminalDefs[hs.TerminalID] var xp int if completed && won { xp = hackingXP(tDef.BaseXPWin, hs.Level, hs.ReqLevel) sess.WriteLine(fmt.Sprintf("\nConnection terminated. Contract complete.")) } else if completed { xp = hackingXP(tDef.BaseXPLose, hs.Level, hs.ReqLevel) sess.WriteLine(fmt.Sprintf("\nConnection lost.")) } else if hs.Started { xp = hackingXP(tDef.BaseXPLose, hs.Level, hs.ReqLevel) sess.WriteLine("\nYou jack out of the terminal.") } else { sess.WriteLine("\nYou jack out of the terminal.") } if won { if b, ok := hs.Minigame.(XPBonuser); ok { bonus := b.BonusXP() if bonus > 0 { xp += hackingXP(bonus, hs.Level, hs.ReqLevel) } } } if xp > 0 { if newLevel := p.AddSkillXP(player.Hacking, xp); newLevel > 0 { sess.WriteLine(g.colorize(sess, "level_up", fmt.Sprintf("*** You are now level %d hacking! ***", newLevel))) } if p.OptionBool("xp_drops") { sess.WriteLine(g.colorize(sess, "xp", fmt.Sprintf("(+%dxp %s)", xp, player.SkillAbbr[player.Hacking]))) } g.AccountStore.SaveCharacter(p) } delete(g.hackingStates, p.Name) p.ActionState = nil sess.State = net.StateGame g.writePrompt(sess) } func hackingXP(baseXP int, playerLevel int, reqLevel int) int { multiplier := 1.0 + 0.01*float64(playerLevel-reqLevel) if multiplier < 1.0 { multiplier = 1.0 } return int(float64(baseXP) * multiplier) }