diff --git a/internal/solitaire/solitaire.go b/internal/solitaire/solitaire.go index 9fcc82a..6967112 100644 --- a/internal/solitaire/solitaire.go +++ b/internal/solitaire/solitaire.go @@ -1,8 +1,6 @@ package solitaire import ( - "strings" - "github.com/brianstrauch/solitaire-tui/pkg" tea "github.com/charmbracelet/bubbletea" "github.com/charmbracelet/lipgloss" @@ -13,13 +11,15 @@ type deckType int const ( stock deckType = 0 waste deckType = 1 - foundation deckType = 2 - tableau deckType = 6 + empty deckType = 2 + foundation deckType = 3 + tableau deckType = 7 ) var deckTypes = []deckType{ stock, waste, + empty, foundation, foundation, foundation, @@ -33,22 +33,6 @@ var deckTypes = []deckType{ tableau, } -var deckLocations = []cell{ - {0, 0}, - {6, 0}, - {18, 0}, - {24, 0}, - {30, 0}, - {36, 0}, - {0, 5}, - {6, 5}, - {12, 5}, - {18, 5}, - {24, 5}, - {30, 5}, - {36, 5}, -} - type Solitaire struct { decks []*pkg.Deck selected *index @@ -58,22 +42,22 @@ type Solitaire struct { maxHeight int } -type cell struct { - x int - y int -} - type index struct { deck int card int } func New() *Solitaire { - decks := make([]*pkg.Deck, 13) - - decks[stock] = pkg.NewFullDeck() - for i := 1; i < len(decks); i++ { - decks[i] = pkg.NewEmptyDeck() + decks := make([]*pkg.Deck, len(deckTypes)) + for i := range decks { + switch deckTypes[i] { + case stock: + decks[i] = pkg.NewFullDeck() + case empty: + decks[i] = nil + default: + decks[i] = pkg.NewEmptyDeck() + } } for i := 0; i < len(decks)-int(tableau); i++ { @@ -124,9 +108,13 @@ func (s *Solitaire) Update(msg tea.Msg) (tea.Model, tea.Cmd) { } func (s *Solitaire) click(x, y int) { + n := len(s.decks) / 2 + for i, deck := range s.decks { - loc := deckLocations[i] - if ok, j := deck.IsClicked(x-loc.x, y-loc.y); ok { + xi := (i % n) * pkg.Width + yi := (i / n) * pkg.Height + + if ok, j := deck.IsClicked(x-xi, y-yi); ok { switch deckTypes[i] { case stock: if deck.Size() > 0 { @@ -143,11 +131,14 @@ func (s *Solitaire) click(x, y int) { } case foundation: if s.selected != nil && s.selected.deck != i { - ok := s.move(&index{deck: i}) - if !ok { + if !s.move(&index{deck: i}) && deck.Size() > 0 { + s.toggleSelect(nil) s.toggleSelect(&index{deck: i, card: deck.Size() - 1}) } } else if deck.Size() > 0 { + if s.selected != nil && s.selected.deck != i { + s.toggleSelect(nil) + } s.toggleSelect(&index{deck: i, card: deck.Size() - 1}) } case tableau: @@ -159,10 +150,10 @@ func (s *Solitaire) click(x, y int) { } else if s.selected != nil && s.selected.deck != i { ok := s.move(&index{deck: i, card: j}) if !ok { - s.toggleSelect(&index{deck: i, card: j}) + s.toggleSelect(nil) s.toggleSelect(&index{deck: i, card: j}) } - } else if deck.Get(j).IsVisible { + } else if deck.Size() > 0 && deck.Get(j).IsVisible { if s.selected != nil && s.selected.deck == i && s.selected.card != j { s.toggleSelect(&index{deck: i, card: j}) } @@ -220,7 +211,7 @@ func (s *Solitaire) toggleSelect(selected *index) { card.IsSelected = false } s.selected = nil - } else { + } else if s.decks[selected.deck].Size() > 0 { s.selected = selected for _, card := range s.decks[s.selected.deck].GetFrom(s.selected.card) { card.IsSelected = true @@ -229,25 +220,16 @@ func (s *Solitaire) toggleSelect(selected *index) { } func (s *Solitaire) View() string { - view := lipgloss.JoinHorizontal(lipgloss.Top, - s.decks[0].View(), - s.decks[1].View(), - strings.Repeat(" ", 6), - s.decks[2].View(), - s.decks[3].View(), - s.decks[4].View(), - s.decks[5].View(), - ) + "\n" + n := len(s.decks) / 2 - view += lipgloss.JoinHorizontal(lipgloss.Top, - s.decks[6].View(), - s.decks[7].View(), - s.decks[8].View(), - s.decks[9].View(), - s.decks[10].View(), - s.decks[11].View(), - s.decks[12].View(), - ) + "\n" + var view string + for i := 0; i < 2; i++ { + row := make([]string, n) + for j := range row { + row[j] = s.decks[i*n+j].View() + } + view += lipgloss.JoinHorizontal(lipgloss.Top, row...) + "\n" + } return view } diff --git a/pkg/card.go b/pkg/card.go index fd1ba84..ae77ecf 100644 --- a/pkg/card.go +++ b/pkg/card.go @@ -12,8 +12,8 @@ var ( ) const ( - width = 6 - height = 5 + Width = 6 + Height = 5 ) type Card struct { @@ -63,11 +63,11 @@ func (c *Card) String() string { func viewCard(design, shorthand, color string) string { style := lipgloss.NewStyle().Foreground(lipgloss.Color(color)) - padding := strings.Repeat("─", width-2-lipgloss.Width(shorthand)) + padding := strings.Repeat("─", Width-2-lipgloss.Width(shorthand)) view := style.Render("╭") + shorthand + style.Render(padding+"╮") + "\n" - for i := 1; i < height-1; i++ { - view += style.Render("│"+strings.Repeat(design, width-2)+"│") + "\n" + for i := 1; i < Height-1; i++ { + view += style.Render("│"+strings.Repeat(design, Width-2)+"│") + "\n" } view += style.Render("╰"+padding) + shorthand + style.Render("╯") diff --git a/pkg/deck.go b/pkg/deck.go index 7807411..3963d6b 100644 --- a/pkg/deck.go +++ b/pkg/deck.go @@ -43,6 +43,10 @@ func (d *Deck) Expand() { } func (d *Deck) View() string { + if d == nil { + return strings.Repeat(" ", Width) + } + // Outline if d.Size() == 0 { return viewCard(" ", "", "#EEEEEE") @@ -62,20 +66,24 @@ func (d *Deck) View() string { } func (d *Deck) IsClicked(x, y int) (bool, int) { + if d == nil { + return false, 0 + } + if d.Size() == 0 { - return x >= 0 && x < width && y >= 0 && y < height, 0 + return x >= 0 && x < Width && y >= 0 && y < Height, 0 } if d.isExpanded { for i := d.Size() - 1; i >= 0; i-- { - if x >= 0 && x < width && y >= i && y < i+height { + if x >= 0 && x < Width && y >= i && y < i+Height { return true, i } } return false, 0 } - return x >= 0 && x < width && y >= 0 && y < height, 0 + return x >= 0 && x < Width && y >= 0 && y < Height, 0 } func (d *Deck) Add(cards ...*Card) {