aboutsummaryrefslogtreecommitdiff
path: root/internal/casino/table.go
blob: 80ae45133819e965459860c2244247c756c3f31b (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
package casino

import (
	"math/rand"
)

// tableGame is a multiplayer table game implementation. Table routes every
// player interaction through this interface so new games plug in without
// changing the dispatch layer.
type tableGame interface {
	join(name string) []Event
	leave(name string) []Event
	bet(name, spot string, amount int, wallet Wallet) []Event
	tick() []Event
	action(name, action string) []Event
	rebet(name string) (spot string, amount int)
	markDisconnected(name string) []Event
	hasParticipant(name string) bool
}

// tableBase carries the identity every table game needs to build events.
type tableBase struct {
	RoomID int
	Config TableConfig
}

func (b tableBase) event(message string, public bool) Event {
	return Event{RoomID: b.RoomID, TableID: b.Config.ID, Type: EventResult, Message: message, Public: public, Color: "casino_action"}
}

func (b tableBase) private(name, message string) Event {
	e := b.event(message, false)
	e.PrivateTo = name
	return e
}

func (b tableBase) playerAction(name, publicMessage, privateMessage string) Event {
	e := b.event(publicMessage, true)
	e.PrivateTo = name
	e.PrivateMessage = privateMessage
	return e
}

// Table is the manager-facing handle for a multiplayer table. It only holds
// routing state; all game logic lives in the tableGame implementation.
type Table struct {
	RoomID int
	Config TableConfig
	game   tableGame
}

// newTable builds the table game for cfg.Game, or nil when the game has no
// multiplayer table implementation.
func newTable(roomID int, cfg TableConfig, rng *rand.Rand) *Table {
	cfg = cfg.Normalize()
	t := &Table{RoomID: roomID, Config: cfg}
	switch cfg.Game {
	case GameBlackjack:
		t.game = newBlackjackTable(roomID, cfg, rng)
	case GameBaccarat:
		t.game = newBaccaratTable(roomID, cfg, rng)
	default:
		return nil
	}
	return t
}

func (t *Table) join(name string) []Event  { return t.game.join(name) }
func (t *Table) leave(name string) []Event { return t.game.leave(name) }

func (t *Table) bet(name, spot string, amount int, wallet Wallet) []Event {
	return t.game.bet(name, spot, amount, wallet)
}

func (t *Table) tick() []Event                      { return t.game.tick() }
func (t *Table) action(name, action string) []Event { return t.game.action(name, action) }
func (t *Table) rebet(name string) (string, int)    { return t.game.rebet(name) }

func (t *Table) markDisconnected(name string) []Event { return t.game.markDisconnected(name) }
func (t *Table) hasParticipant(name string) bool      { return t.game.hasParticipant(name) }