package views import ( "fmt" "github.com/boozec/rahanna/pkg/p2p" "github.com/charmbracelet/bubbles/list" tea "github.com/charmbracelet/bubbletea" "github.com/notnil/chess" ) // UpdateMovesListMsg is a message to update the moves list type UpdateMovesListMsg struct{} // ChessMoveMsg is a message containing a received chess move. type ChessMoveMsg string type item struct { title string } func (i item) Title() string { return i.title } func (i item) Description() string { return "" } func (i item) FilterValue() string { return i.title } func (m *GameModel) getMoves() tea.Cmd { m.network.AddReceiveFunction(func(msg p2p.Message) { payload := string(msg.Payload) m.incomingMoves <- payload }) return func() tea.Msg { move := <-m.incomingMoves if move == "🏳️" { return EndGameMsg{abandoned: true} } return ChessMoveMsg(move) } } func (m *GameModel) updateMovesListCmd() tea.Cmd { return func() tea.Msg { return UpdateMovesListMsg{} } } func (m GameModel) handleUpdateMovesListMsg() GameModel { if m.isMyTurn() && m.game != nil { var items []list.Item for _, move := range m.chessGame.ValidMoves() { var promo string if move.Promo().String() != "" { promo = " " + move.Promo().String() } items = append( items, item{title: fmt.Sprintf("%s → %s%s", move.S1().String(), move.S2().String(), promo)}, ) } m.availableMovesList.SetItems(items) m.availableMovesList.Title = "Choose a move" m.availableMovesList.Select(0) m.availableMovesList.SetShowFilter(true) m.availableMovesList.SetFilteringEnabled(true) m.availableMovesList.ResetFilter() } return m } func (m GameModel) handleChessMoveMsg(msg ChessMoveMsg) (GameModel, tea.Cmd) { err := m.chessGame.MoveStr(string(msg)) cmds := []tea.Cmd{m.getMoves(), m.updateMovesListCmd()} if err != nil { m.err = err } else { m.turn++ m.err = nil } if m.chessGame.Outcome() != chess.NoOutcome { cmds = append(cmds, m.endGame(m.chessGame.Outcome().String())) } return m, tea.Batch(cmds...) }