diff options
Diffstat (limited to 'internal/game/hacking.go')
| -rw-r--r-- | internal/game/hacking.go | 157 |
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) +} |
