aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/machine.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/casino/machine.go')
-rw-r--r--internal/casino/machine.go54
1 files changed, 19 insertions, 35 deletions
diff --git a/internal/casino/machine.go b/internal/casino/machine.go
index d9fa590..887e154 100644
--- a/internal/casino/machine.go
+++ b/internal/casino/machine.go
@@ -40,6 +40,7 @@ func newMachine(roomID int, cfg MachineConfig, rng *rand.Rand) *Machine {
if cfg.Payout > 0 {
profile = ScaleToRTP(profile, cfg.Payout)
}
+ profile = profile.Normalize()
return &Machine{RoomID: roomID, Config: cfg, phase: machineReady, profile: profile, rng: rng}
}
@@ -97,23 +98,14 @@ func (m *Machine) start(name string, wallet Wallet) []Event {
if m.bet <= 0 {
return m.private("Set a wager first with 'bet <amount>'.")
}
- wager := m.bet
- if m.freeSpins > 0 {
- m.spinBet = wager
- } else {
- if _, ok := wallet.Wager(wager); !ok {
- return m.private("You don't have enough chips and credits for that bet.")
- }
- m.spinBet = wager
+ if _, ok := wallet.Wager(m.bet); !ok {
+ return m.private("You don't have enough chips and credits for that bet.")
}
+ m.spinBet = m.bet
m.player.Wallet = wallet
m.spin = generateSlotSpinWithProfile(m.rng, m.spinBet, m.profile)
m.reel, m.clock, m.suspense = 0, 0, false
m.phase = machineSpinning
- if m.freeSpins > 0 {
- m.freeSpins--
- return m.playerAction(fmt.Sprintf("%s begins a free spin.", name), "You begin a free spin.")
- }
return m.playerAction(fmt.Sprintf("%s pulls the lever on the slots machine.", name), "You pull the lever on the slots machine.")
}
@@ -179,7 +171,7 @@ func (m *Machine) tick() []Event {
m.reel++
message := fmt.Sprintf("Reel %d stops...", m.reel)
events := m.publicSlot(message, m.reel)
- if m.reel < 5 && stoppedScatters(m.spin.Grid, m.reel) >= 2 && !m.suspense {
+ if m.reel < 5 && stoppedScatters(m.spin.Grid, m.reel, m.profile.FreeSpinTrigger) >= 2 && !m.suspense {
m.suspense = true
events = append(events, m.public("Two scatters! The remaining reels slow down...")...)
}
@@ -232,19 +224,16 @@ func (m *Machine) finishSpin() []Event {
if credits > m.spinBet {
winEvents[0].Color = "casino_big_win"
}
- if credits >= 2*m.spinBet {
- winEvents[0].Color = "casino_jackpot_win"
- }
events = append(events, winEvents...)
}
if len(m.spin.Wins) > 0 {
- winEvents := m.private(formatWins(m.spin.Wins))
+ winEvents := m.private(formatWins(m.spin.Wins, m.profile.Ways))
winEvents[0].Color = "casino_win"
events = append(events, winEvents...)
}
if m.spin.ScatterCount >= 3 && m.freeSpins == 0 {
- m.freeSpins = 8
- events = append(events, m.public("Three scatter symbols trigger 8 free spins!")...)
+ m.freeSpins = m.profile.FreeSpinCount
+ events = append(events, m.public(fmt.Sprintf("Three scatter symbols trigger %d free spins!", m.profile.FreeSpinCount))...)
}
if m.freeSpins > 0 {
m.freeSpins--
@@ -269,6 +258,7 @@ func (m *Machine) leave(name string) []Event {
}
m.player = nil
m.bet = 0
+ m.payoutRemainder = 0
return []Event{{RoomID: m.RoomID, TableID: m.Config.ID, Type: EventLeft, Player: name,
Message: fmt.Sprintf("%s stands up from the slots machine.", name), PrivateMessage: "You stand up from the slot machine.", PrivateTo: name, Color: "casino_action", Public: true}}
}
@@ -322,11 +312,11 @@ func (m *Machine) publicSlot(message string, stopped int) []Event {
Message: message, Color: "casino_action", Public: true, Slot: &SlotSnapshot{Grid: m.spin.Grid, StoppedReels: stopped}}}
}
-func stoppedScatters(grid [3][5]string, reels int) int {
+func stoppedScatters(grid [3][5]string, reels int, trigger string) int {
count := 0
for row := 0; row < 3; row++ {
for reel := 0; reel < reels && reel < 5; reel++ {
- if grid[row][reel] == "scatter" {
+ if grid[row][reel] == trigger {
count++
}
}
@@ -334,28 +324,22 @@ func stoppedScatters(grid [3][5]string, reels int) int {
return count
}
-func formatWins(wins []SlotWin) string {
- message := "Winning lines/ways (243-way evaluation):\n"
+func formatWins(wins []SlotWin, ways int) string {
+ message := fmt.Sprintf("Winning lines/ways (%d-way evaluation):\n", ways)
for _, win := range wins {
- message += fmt.Sprintf(" %s x%d: %d ways x %.4gx bet / 243 = %.4f credits\n", win.Symbol, win.Length, win.Ways, win.Multiplier, win.Payout)
+ message += fmt.Sprintf(" %s x%d: %d ways x %.4gx bet / %d = %.4f credits\n", win.Symbol, win.Length, win.Ways, win.Multiplier, ways, win.Payout)
}
return message[:len(message)-1]
}
+const slotMenuText = "Slot machine commands:\n bet <amount> Set your wager\n bet max Set the maximum wager\n spin Spin using your current wager\n autospin Start automatic betting\n stop Leave the slot machine"
+
func (m *Machine) privateMenu(prefix string) []Event {
- if m.phase != machineReady {
- events := m.private(prefix)
- events[0].Color = "casino_menu"
- return events
- }
- menu := "Slot machine commands:\n bet <amount> Set your wager\n bet max Set the maximum wager\n spin Spin using your current wager\n autospin Start automatic betting\n stop Leave the slot machine"
- if prefix == "" {
- prefix = "\n" + menu
- } else {
- prefix += "\n\n" + menu
- }
events := m.private(prefix)
events[0].Color = "casino_menu"
+ if m.phase == machineReady {
+ events[0].Menu = &MenuView{Kind: MenuSlotCommands, Body: slotMenuText}
+ }
return events
}