aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/manager.go
diff options
context:
space:
mode:
Diffstat (limited to 'internal/casino/manager.go')
-rw-r--r--internal/casino/manager.go137
1 files changed, 66 insertions, 71 deletions
diff --git a/internal/casino/manager.go b/internal/casino/manager.go
index 60bf14d..a9bab92 100644
--- a/internal/casino/manager.go
+++ b/internal/casino/manager.go
@@ -22,6 +22,10 @@ func NewManager(seed int64) *Manager {
}
}
+func tableKey(roomID int, tableID string) string {
+ return fmt.Sprintf("%d:%s", roomID, tableID)
+}
+
func (m *Manager) EnsureMachine(roomID int, cfg MachineConfig) *Machine {
cfg = cfg.Normalize()
key := tableKey(roomID, cfg.ID)
@@ -35,10 +39,8 @@ func (m *Manager) EnsureMachine(roomID int, cfg MachineConfig) *Machine {
return machine
}
-func tableKey(roomID int, tableID string) string {
- return fmt.Sprintf("%d:%s", roomID, tableID)
-}
-
+// EnsureTable returns the table for cfg, or nil when cfg.Game has no
+// multiplayer table implementation.
func (m *Manager) EnsureTable(roomID int, cfg TableConfig) *Table {
cfg = cfg.Normalize()
key := tableKey(roomID, cfg.ID)
@@ -48,6 +50,9 @@ func (m *Manager) EnsureTable(roomID int, cfg TableConfig) *Table {
return table
}
table := newTable(roomID, cfg, m.rng)
+ if table == nil {
+ return nil
+ }
m.tables[key] = table
return table
}
@@ -58,13 +63,30 @@ func (m *Manager) Table(roomID int, tableID string) *Table {
return m.tables[tableKey(roomID, tableID)]
}
-func (m *Manager) Tick() []Event {
+// snapshotTables copies the live table list under the lock so callers can
+// iterate without holding it (table methods take their own locks).
+func (m *Manager) snapshotTables() []*Table {
m.mu.Lock()
tables := make([]*Table, 0, len(m.tables))
for _, table := range m.tables {
tables = append(tables, table)
}
m.mu.Unlock()
+ return tables
+}
+
+func (m *Manager) snapshotMachines() []*Machine {
+ m.mu.Lock()
+ machines := make([]*Machine, 0, len(m.machines))
+ for _, machine := range m.machines {
+ machines = append(machines, machine)
+ }
+ m.mu.Unlock()
+ return machines
+}
+
+func (m *Manager) Tick() []Event {
+ tables := m.snapshotTables()
sort.Slice(tables, func(i, j int) bool {
if tables[i].RoomID != tables[j].RoomID {
return tables[i].RoomID < tables[j].RoomID
@@ -75,12 +97,7 @@ func (m *Manager) Tick() []Event {
for _, table := range tables {
events = append(events, table.tick()...)
}
- m.mu.Lock()
- machines := make([]*Machine, 0, len(m.machines))
- for _, machine := range m.machines {
- machines = append(machines, machine)
- }
- m.mu.Unlock()
+ machines := m.snapshotMachines()
sort.Slice(machines, func(i, j int) bool {
if machines[i].RoomID != machines[j].RoomID {
return machines[i].RoomID < machines[j].RoomID
@@ -93,62 +110,61 @@ func (m *Manager) Tick() []Event {
return events
}
-func (m *Manager) JoinMachine(roomID int, cfg MachineConfig, name string) []Event {
- return m.EnsureMachine(roomID, cfg).join(name)
-}
-
-func (m *Manager) SetMachineBet(roomID int, machineID, name string, amount int, wallet Wallet) []Event {
+// withMachine runs fn against the named machine when it exists.
+func (m *Manager) withMachine(roomID int, machineID string, fn func(*Machine) []Event) []Event {
m.mu.Lock()
machine := m.machines[tableKey(roomID, machineID)]
m.mu.Unlock()
if machine == nil {
return nil
}
- return machine.setBet(name, amount, wallet)
+ return fn(machine)
+}
+
+func (m *Manager) JoinMachine(roomID int, cfg MachineConfig, name string) []Event {
+ return m.EnsureMachine(roomID, cfg).join(name)
+}
+
+func (m *Manager) SetMachineBet(roomID int, machineID, name string, amount int, wallet Wallet) []Event {
+ return m.withMachine(roomID, machineID, func(machine *Machine) []Event {
+ return machine.setBet(name, amount, wallet)
+ })
}
func (m *Manager) StartMachine(roomID int, machineID, name string, wallet Wallet) []Event {
- m.mu.Lock()
- machine := m.machines[tableKey(roomID, machineID)]
- m.mu.Unlock()
- if machine == nil {
- return nil
- }
- return machine.start(name, wallet)
+ return m.withMachine(roomID, machineID, func(machine *Machine) []Event {
+ return machine.start(name, wallet)
+ })
}
func (m *Manager) EnableMachineAutoBet(roomID int, machineID, name string, wallet Wallet) []Event {
- m.mu.Lock()
- machine := m.machines[tableKey(roomID, machineID)]
- m.mu.Unlock()
- if machine == nil {
- return nil
- }
- return machine.enableAutoBet(name, wallet)
+ return m.withMachine(roomID, machineID, func(machine *Machine) []Event {
+ return machine.enableAutoBet(name, wallet)
+ })
}
func (m *Manager) StopMachineAutoBet(roomID int, machineID, name string) ([]Event, bool) {
- m.mu.Lock()
- machine := m.machines[tableKey(roomID, machineID)]
- m.mu.Unlock()
- if machine == nil {
- return nil, false
- }
- return machine.stopAutoBet(name)
+ stopped := false
+ events := m.withMachine(roomID, machineID, func(machine *Machine) []Event {
+ events, ok := machine.stopAutoBet(name)
+ stopped = ok
+ return events
+ })
+ return events, stopped
}
func (m *Manager) LeaveMachine(roomID int, machineID, name string) []Event {
- m.mu.Lock()
- machine := m.machines[tableKey(roomID, machineID)]
- m.mu.Unlock()
- if machine == nil {
- return nil
- }
- return machine.leave(name)
+ return m.withMachine(roomID, machineID, func(machine *Machine) []Event {
+ return machine.leave(name)
+ })
}
func (m *Manager) Join(roomID int, cfg TableConfig, name string) []Event {
- return m.EnsureTable(roomID, cfg).join(name)
+ table := m.EnsureTable(roomID, cfg)
+ if table == nil {
+ return []Event{{RoomID: roomID, TableID: cfg.ID, Type: EventResult, PrivateTo: name, Message: "That game is not available here."}}
+ }
+ return table.join(name)
}
func (m *Manager) Leave(roomID int, tableID, name string) []Event {
@@ -179,40 +195,19 @@ func (m *Manager) Rebet(roomID int, tableID, name string) (string, int) {
return "", 0
}
+// MarkDisconnected removes the player from every table and machine,
+// forfeiting any wager they had committed, so seats free up immediately.
func (m *Manager) MarkDisconnected(name string) []Event {
- m.mu.Lock()
- tables := make([]*Table, 0, len(m.tables))
- for _, table := range m.tables {
- tables = append(tables, table)
- }
- m.mu.Unlock()
var events []Event
- for _, table := range tables {
+ for _, table := range m.snapshotTables() {
events = append(events, table.markDisconnected(name)...)
}
- m.mu.Lock()
- machines := make([]*Machine, 0, len(m.machines))
- for _, machine := range m.machines {
- machines = append(machines, machine)
- }
- m.mu.Unlock()
- for _, machine := range machines {
+ for _, machine := range m.snapshotMachines() {
events = append(events, machine.markDisconnected(name)...)
}
return events
}
-func (m *Manager) MarkConnected(name string) {
- m.mu.Lock()
- defer m.mu.Unlock()
- for _, table := range m.tables {
- table.markConnected(name)
- }
- for _, machine := range m.machines {
- machine.markConnected(name)
- }
-}
-
func (m *Manager) Participation(name string) (*Table, bool) {
m.mu.Lock()
defer m.mu.Unlock()