aboutsummaryrefslogtreecommitdiff
path: root/internal/game/hacking.go
diff options
context:
space:
mode:
authorhistoria <[not public]>2026-06-19 13:28:06 -0400
committerhistoria <[not public]>2026-06-19 13:28:06 -0400
commit3a58125d14bb307f861b38c6c5b0a63babde7e08 (patch)
treebd89e866447d55e6dffd447d8ef5fabf9b8fbe9d /internal/game/hacking.go
parent575a71dcfed3b9fa44af244836f638a23df05a9a (diff)
downloadthehouseoficarus-3a58125d14bb307f861b38c6c5b0a63babde7e08.tar.gz
feat: all skills kind of implemented, random prototype content added
Diffstat (limited to 'internal/game/hacking.go')
-rw-r--r--internal/game/hacking.go157
1 files changed, 157 insertions, 0 deletions
diff --git a/internal/game/hacking.go b/internal/game/hacking.go
new file mode 100644
index 0000000..dfefd5c
--- /dev/null
+++ b/internal/game/hacking.go
@@ -0,0 +1,157 @@
+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)
+}