1
0
mirror of https://github.com/maaslalani/gambit.git synced 2024-11-24 08:22:12 +02:00
gambit/server/game.go
2022-02-14 22:08:25 -05:00

129 lines
3.0 KiB
Go

package server
import (
"fmt"
"strings"
tea "github.com/charmbracelet/bubbletea"
"github.com/maaslalani/gambit/game"
"github.com/maaslalani/gambit/style"
)
// NoteMsg is a message that is sent to the client when a message is added to
// the game.
type NoteMsg string
// SharedGame is a game that is shared between players. It wraps gambit bubble
// tea model and synchronizes messages among players and server.
type SharedGame struct {
player *Player
game *game.Game
note string
turn bool
observer bool
whiteToMove *bool
sync chan tea.Msg
}
// NewSharedGame creates a new shared game for a player.
func NewSharedGame(p *Player, sync chan tea.Msg, roomTurn *bool, turn, observer bool, pos string) *SharedGame {
g := game.NewGameWithPosition(pos)
g.SetFlipped(!turn)
r := &SharedGame{
player: p,
game: g,
turn: turn,
observer: observer,
whiteToMove: roomTurn,
sync: sync,
}
return r
}
// Init implements bubble tea model.
func (r *SharedGame) Init() tea.Cmd {
return nil
}
// SendMsg sends a message to the room.
func (r *SharedGame) SendMsg(msg tea.Msg) {
go func() {
r.sync <- msg
}()
}
// Update implements bubble tea model.
func (r *SharedGame) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
var cmds []tea.Cmd
switch msg := msg.(type) {
case game.NotifyMsg:
if !r.observer && r.turn != msg.Turn {
r.SendMsg(game.MoveMsg{From: msg.From, To: msg.To})
if msg.Checkmate {
r.SendMsg(NoteMsg(fmt.Sprintf("%s wins!", r.player)))
}
}
case game.MoveMsg:
g, cmd := r.game.Update(msg)
r.game = g.(*game.Game)
cmds = append(cmds, cmd)
case NoteMsg:
r.note = string(msg)
return r, nil
case tea.MouseMsg:
if !r.observer && r.turn == *r.whiteToMove {
if msg.Type != tea.MouseLeft {
return r, nil
}
g, cmd := r.game.Update(msg)
cmds = append(cmds, cmd)
r.game = g.(*game.Game)
}
case tea.KeyMsg:
switch msg.String() {
case "ctrl+c", "q":
g, cmd := r.game.Update(msg)
r.game = g.(*game.Game)
cmds = append(cmds, cmd)
cmds = append(cmds, tea.Quit)
case "ctrl+f":
g, cmd := r.game.Update(msg)
cmds = append(cmds, cmd)
r.game = g.(*game.Game)
default:
if !r.observer && r.turn == *r.whiteToMove {
g, cmd := r.game.Update(msg)
cmds = append(cmds, cmd)
r.game = g.(*game.Game)
}
}
default:
if !r.observer && r.turn == *r.whiteToMove {
g, cmd := r.game.Update(msg)
cmds = append(cmds, cmd)
r.game = g.(*game.Game)
}
}
return r, tea.Batch(cmds...)
}
// View implements bubble tea model.
func (r *SharedGame) View() string {
s := strings.Builder{}
turn := "Black's move"
if *r.whiteToMove {
turn = "White's move"
}
s.WriteString(r.game.View())
s.WriteRune('\n')
s.WriteString(fmt.Sprintf(" %s %s", style.Title("Gambit"), turn))
s.WriteRune('\n')
s.WriteString(style.Faint(fmt.Sprintf(" Room %s as %s playing %s", r.player.room.id, r.player.session.User(), r.player.ptype)))
s.WriteRune('\n')
return s.String()
}