From 0ea4eec5dd2122c6704216971eb1249276297867 Mon Sep 17 00:00:00 2001 From: historia <[not public]> Date: Fri, 19 Jun 2026 18:20:26 -0400 Subject: shop fixes, 'toggle' completely removed, movement speed increased --- internal/game/hacking_liars_dice.go | 395 ------------------------------------ 1 file changed, 395 deletions(-) delete mode 100644 internal/game/hacking_liars_dice.go (limited to 'internal/game/hacking_liars_dice.go') diff --git a/internal/game/hacking_liars_dice.go b/internal/game/hacking_liars_dice.go deleted file mode 100644 index 12f76c1..0000000 --- a/internal/game/hacking_liars_dice.go +++ /dev/null @@ -1,395 +0,0 @@ -package game - -import ( - "fmt" - "math/rand" - "strconv" - "strings" -) - -type LiarsDiceGame struct { - playerDice []int - aiDice []int - currentBid LiarsBid - hasBid bool - playerTurn bool - round int - gameOver bool - won bool - playerLost int - completed bool -} - -type LiarsBid struct { - Quantity int - Face int -} - -func NewLiarsDiceGame() *LiarsDiceGame { - return &LiarsDiceGame{ - playerDice: make([]int, 5), - aiDice: make([]int, 5), - } -} - -func (l *LiarsDiceGame) Name() string { - return "Signal Bluff" -} - -func (l *LiarsDiceGame) Init(level int) string { - l.playerDice = make([]int, 5) - l.aiDice = make([]int, 5) - l.round = 0 - l.gameOver = false - l.playerTurn = true - l.hasBid = false - l.playerLost = 0 - l.completed = false - - var sb strings.Builder - sb.WriteString("=== SIGNAL BLUFF ===\n") - sb.WriteString("\n") - sb.WriteString("You've connected to a secure channel running a bluffing protocol.\n") - sb.WriteString("You and the system each have 5 signal fragments (dice). Each round,\n") - sb.WriteString("fragments are scrambled. You see only yours. Take turns making claims\n") - sb.WriteString("about the total count of a specific signal across ALL fragments.\n") - sb.WriteString("\n") - sb.WriteString("1s are wild -- they count as any signal.\n") - sb.WriteString("\n") - sb.WriteString("Commands:\n") - sb.WriteString(" bid - Claim at least N fragments show face F\n") - sb.WriteString(" (e.g., 'bid 3 4' = \"at least three 4s\")\n") - sb.WriteString(" call - Challenge the last bid (reveal all)\n") - sb.WriteString(" exact - Claim the bid is exactly right\n") - sb.WriteString(" status - Show your fragments and current bid\n") - sb.WriteString(" jack out - Disconnect (forfeit)\n") - sb.WriteString("\n") - sb.WriteString(l.startRound()) - return sb.String() -} - -func (l *LiarsDiceGame) HandleInput(input string) (string, bool, bool) { - input = strings.TrimSpace(strings.ToLower(input)) - parts := strings.Fields(input) - - if len(parts) == 0 { - return "Commands: bid , call, exact, status, jack out", false, false - } - - cmd := parts[0] - - switch cmd { - case "bid", "b": - if len(parts) < 3 { - return "Usage: bid (e.g., bid 3 4)", false, false - } - qty, err1 := strconv.Atoi(parts[1]) - face, err2 := strconv.Atoi(parts[2]) - if err1 != nil || err2 != nil { - return "Usage: bid (e.g., bid 3 4)", false, false - } - return l.doBid(qty, face) - case "call", "c", "intercept", "liar": - return l.doCall(false) - case "exact", "e": - return l.doExact() - case "status": - return l.doStatus(), false, false - default: - if len(parts) == 2 { - qty, err1 := strconv.Atoi(parts[0]) - face, err2 := strconv.Atoi(parts[1]) - if err1 == nil && err2 == nil { - return l.doBid(qty, face) - } - } - return "Commands: bid , call, exact, status, jack out", false, false - } -} - -func (l *LiarsDiceGame) doBid(qty, face int) (string, bool, bool) { - if face < 1 || face > 6 { - return "Face must be 1-6.", false, false - } - if qty < 1 { - return "Quantity must be at least 1.", false, false - } - if !l.playerTurn { - return "It's not your turn to bid. Use 'call' or 'exact'.", false, false - } - - if l.hasBid { - if qty < l.currentBid.Quantity || (qty == l.currentBid.Quantity && face <= l.currentBid.Face) { - return "You must bid higher (higher quantity or same quantity with higher face).", false, false - } - } - - l.currentBid = LiarsBid{Quantity: qty, Face: face} - l.hasBid = true - l.playerTurn = false - - return l.aiTurn() -} - -func (l *LiarsDiceGame) doCall(player bool) (string, bool, bool) { - if !l.hasBid { - return "No bid to call yet. Make a bid first.", false, false - } - - var sb strings.Builder - if player { - sb.WriteString("System intercepts!\n") - } else { - sb.WriteString("You intercept!\n") - } - - sb.WriteString(l.showAllDice()) - sb.WriteString(fmt.Sprintf("\nBid was: %d %s\n", l.currentBid.Quantity, faceNamePlural(l.currentBid.Face))) - - total := l.countFace(l.currentBid.Face) - sb.WriteString(fmt.Sprintf("Actual count: %d (%d %ss + %d wild 1s)\n\n", - total, - l.countFaceNonWild(l.currentBid.Face), - faceName(l.currentBid.Face), - l.countFace(1)-l.countFaceNonWild(1))) - - if total >= l.currentBid.Quantity { - sb.WriteString("The bid holds! ") - if player { - sb.WriteString("System loses a fragment.") - l.aiDice = l.aiDice[:len(l.aiDice)-1] - } else { - sb.WriteString("You lose a fragment.") - l.playerDice = l.playerDice[:len(l.playerDice)-1] - l.playerLost++ - } - } else { - sb.WriteString("Bluff called! ") - if player { - sb.WriteString("You lose a fragment.") - l.playerDice = l.playerDice[:len(l.playerDice)-1] - l.playerLost++ - } else { - sb.WriteString("System loses a fragment.") - l.aiDice = l.aiDice[:len(l.aiDice)-1] - } - } - - return l.checkGameOver(sb) -} - -func (l *LiarsDiceGame) doExact() (string, bool, bool) { - if !l.hasBid { - return "No bid to claim exact on. Make a bid first.", false, false - } - - var sb strings.Builder - sb.WriteString("You claim exact match!\n") - - sb.WriteString(l.showAllDice()) - total := l.countFace(l.currentBid.Face) - sb.WriteString(fmt.Sprintf("\nBid was: %d %s\n", l.currentBid.Quantity, faceNamePlural(l.currentBid.Face))) - sb.WriteString(fmt.Sprintf("Actual count: %d\n\n", total)) - - if total == l.currentBid.Quantity { - sb.WriteString("Exact match! You recover a fragment.\n") - if len(l.playerDice) < 5 { - l.playerDice = append(l.playerDice, rand.Intn(6)+1) - } - } else { - sb.WriteString("Not an exact match. You lose a fragment.\n") - l.playerDice = l.playerDice[:len(l.playerDice)-1] - l.playerLost++ - } - - return l.checkGameOver(sb) -} - -func (l *LiarsDiceGame) checkGameOver(sb strings.Builder) (string, bool, bool) { - if len(l.playerDice) == 0 { - sb.WriteString("\nYou've lost all your fragments. Connection terminated.") - l.gameOver = true - l.won = false - l.completed = true - return sb.String(), true, false - } - if len(l.aiDice) == 0 { - sb.WriteString("\nSystem has no fragments left. You win!") - l.gameOver = true - l.won = true - l.completed = true - return sb.String(), true, true - } - - sb.WriteString(l.startRound()) - return sb.String(), false, false -} - -func (l *LiarsDiceGame) showAllDice() string { - var sb strings.Builder - sb.WriteString(fmt.Sprintf("Your fragments: %s\n", l.diceStr(l.playerDice))) - sb.WriteString(fmt.Sprintf("System fragments: %s\n", l.diceStr(l.aiDice))) - return sb.String() -} - -func (l *LiarsDiceGame) diceStr(dice []int) string { - var parts []string - for _, d := range dice { - parts = append(parts, fmt.Sprintf("[%d]", d)) - } - return strings.Join(parts, " ") -} - -func (l *LiarsDiceGame) doStatus() string { - var sb strings.Builder - sb.WriteString(fmt.Sprintf("--- Cycle %d ---\n", l.round)) - sb.WriteString(fmt.Sprintf("Your fragments: %s (You: %d, System: %d)\n", - l.diceStr(l.playerDice), len(l.playerDice), len(l.aiDice))) - if l.hasBid { - who := "System" - if !l.playerTurn { - who = "System" - } else { - who = "you" - } - sb.WriteString(fmt.Sprintf("Current bid: %d %s (by %s)\n", l.currentBid.Quantity, faceNamePlural(l.currentBid.Face), who)) - } - if l.playerTurn { - sb.WriteString("Your turn: make a bid.") - } else { - sb.WriteString("Your turn: bid higher, call, or exact.") - } - return sb.String() -} - -func (l *LiarsDiceGame) startRound() string { - l.round++ - for i := range l.playerDice { - l.playerDice[i] = rand.Intn(6) + 1 - } - for i := range l.aiDice { - l.aiDice[i] = rand.Intn(6) + 1 - } - l.hasBid = false - l.playerTurn = true - - var sb strings.Builder - sb.WriteString(fmt.Sprintf("--- Cycle %d ---\n", l.round)) - sb.WriteString(fmt.Sprintf("Your fragments: %s (You: %d, System: %d)\n", - l.diceStr(l.playerDice), len(l.playerDice), len(l.aiDice))) - sb.WriteString("You go first. Make a bid.\n") - return sb.String() -} - -func (l *LiarsDiceGame) aiTurn() (string, bool, bool) { - totalDice := len(l.playerDice) + len(l.aiDice) - - aiCount := l.countFace(l.currentBid.Face) - unknownDice := len(l.playerDice) - estimated := float64(aiCount) + float64(unknownDice)/3.0 - - if float64(l.currentBid.Quantity) > estimated*1.5 { - return l.doCall(true) - } - - bestFace, bestCount := l.aiBestFace() - newQty := l.currentBid.Quantity - newFace := l.currentBid.Face - - if bestFace > newFace && bestCount >= newQty { - newFace = bestFace - } else { - newQty++ - } - - if newQty > totalDice { - return l.doCall(true) - } - - l.currentBid = LiarsBid{Quantity: newQty, Face: newFace} - l.playerTurn = true - - var sb strings.Builder - sb.WriteString(fmt.Sprintf("System broadcasts: %d %s.\n", newQty, faceNamePlural(newFace))) - sb.WriteString("Your turn: bid higher, call, or exact.\n") - return sb.String(), false, false -} - -func (l *LiarsDiceGame) aiBestFace() (face int, count int) { - counts := make(map[int]int) - for _, d := range l.aiDice { - if d == 1 { - continue - } - counts[d]++ - } - wilds := 0 - for _, d := range l.aiDice { - if d == 1 { - wilds++ - } - } - best := 2 - bestN := counts[2] + wilds - for f := 3; f <= 6; f++ { - n := counts[f] + wilds - if n > bestN || (n == bestN && f > best) { - best = f - bestN = n - } - } - return best, bestN -} - -func (l *LiarsDiceGame) countFace(face int) int { - count := 0 - for _, d := range l.playerDice { - if d == face || d == 1 { - count++ - } - } - for _, d := range l.aiDice { - if d == face || d == 1 { - count++ - } - } - return count -} - -func (l *LiarsDiceGame) countFaceNonWild(face int) int { - count := 0 - for _, d := range l.playerDice { - if d == face { - count++ - } - } - for _, d := range l.aiDice { - if d == face { - count++ - } - } - return count -} - -func faceName(f int) string { - names := []string{"", "one", "two", "three", "four", "five", "six"} - if f >= 1 && f <= 6 { - return names[f] - } - return fmt.Sprint(f) -} - -func faceNamePlural(f int) string { - names := []string{"", "ones", "twos", "threes", "fours", "fives", "sixes"} - if f >= 1 && f <= 6 { - return names[f] - } - return fmt.Sprint(f) -} - -func (l *LiarsDiceGame) BonusXP() int { - if l.completed && l.won && l.playerLost == 0 { - return 150 - } - return 0 -} -- cgit v1.2.3