182 lines
3.9 KiB
Go
182 lines
3.9 KiB
Go
package main
|
|
|
|
import (
|
|
"bufio"
|
|
"fmt"
|
|
tea "github.com/charmbracelet/bubbletea"
|
|
"os"
|
|
"tildegit.org/jakew/wordle/game"
|
|
"tildegit.org/jakew/wordle/game/score"
|
|
"tildegit.org/jakew/wordle/game/util"
|
|
"tildegit.org/jakew/wordle/game/words"
|
|
"tildegit.org/jakew/wordle/update"
|
|
"unicode"
|
|
)
|
|
|
|
type model struct {
|
|
board *game.Board
|
|
buffer []rune
|
|
error string
|
|
}
|
|
|
|
func initialModel() model {
|
|
m := model{
|
|
board: game.NewBoard(),
|
|
buffer: []rune{},
|
|
}
|
|
|
|
lastGame, err := score.GetLastGame()
|
|
if err != nil {
|
|
m.error = fmt.Sprintf("Could not load last game: %v", err.Error())
|
|
return m
|
|
}
|
|
|
|
if lastGame != nil && lastGame.Day == m.board.Day {
|
|
m.error = fmt.Sprintf("Come back tomorrow for a new word")
|
|
m.board = &game.Board{
|
|
Guesses: [6]game.Guess{},
|
|
CurrentGuess: lastGame.Score,
|
|
Solution: "",
|
|
Done: true,
|
|
Day: lastGame.Day,
|
|
}
|
|
|
|
for i, line := range lastGame.Lines {
|
|
m.board.Guesses[i] = game.Guess{
|
|
Letters: []rune(line.Word),
|
|
Correct: line.Correct,
|
|
Present: line.Present,
|
|
}
|
|
}
|
|
}
|
|
|
|
return m
|
|
}
|
|
|
|
func (m model) Init() tea.Cmd {
|
|
return nil
|
|
}
|
|
|
|
func (m model) Update(msg tea.Msg) (tea.Model, tea.Cmd) {
|
|
switch msg := msg.(type) {
|
|
case tea.KeyMsg:
|
|
m.error = ""
|
|
switch msg.Type {
|
|
case tea.KeyCtrlC:
|
|
return m, tea.Quit
|
|
case tea.KeyBackspace:
|
|
if !m.board.Done && len(m.buffer) > 0 {
|
|
m.buffer = m.buffer[:len(m.buffer)-1]
|
|
}
|
|
case tea.KeyEnter:
|
|
if m.board.Done {
|
|
return m, nil
|
|
}
|
|
|
|
if len(m.buffer) != 5 {
|
|
m.error = "Word must be 5 long"
|
|
} else if !words.IsValid(string(m.buffer)) {
|
|
m.error = "Word not in dictionary"
|
|
} else {
|
|
msg := m.board.AddWord(string(m.buffer))
|
|
if msg != "" {
|
|
m.error = msg
|
|
return m, nil
|
|
}
|
|
// clear input
|
|
m.buffer = []rune{}
|
|
|
|
// save if done
|
|
if m.board.Done {
|
|
err := score.SaveBoard(m.board)
|
|
if err != nil {
|
|
m.error = fmt.Sprintf("Something went wrong saving the game: %v", err.Error())
|
|
}
|
|
}
|
|
}
|
|
default:
|
|
if m.board.Done || len(msg.Runes) < 1 {
|
|
return m, nil
|
|
}
|
|
|
|
r := unicode.ToLower(msg.Runes[0])
|
|
if r >= 'a' && r <= 'z' && len(m.buffer) < 5 {
|
|
m.buffer = append(m.buffer, r)
|
|
}
|
|
}
|
|
}
|
|
|
|
return m, nil
|
|
}
|
|
|
|
func (m model) View() string {
|
|
// header
|
|
s := headerStyle.Render(fmt.Sprintf("WORDLE #%d", m.board.Day)) + "\n"
|
|
|
|
for i, guess := range m.board.Guesses {
|
|
line := " "
|
|
for j := 0; j < 5; j++ {
|
|
if i < m.board.CurrentGuess || m.board.CurrentGuess == -1 {
|
|
style := charEmptyStyle
|
|
if util.ContainsInt(guess.Correct, j) {
|
|
style = charCorrectStyle
|
|
} else if util.ContainsInt(guess.Present, j) {
|
|
style = charWrongPositionStyle
|
|
}
|
|
|
|
line += style.Render(string(unicode.ToUpper(guess.Letters[j])) + " ")
|
|
} else {
|
|
line += charEmptyStyle.Render("_ ")
|
|
}
|
|
}
|
|
s += lineStyle.Render(line) + "\n"
|
|
}
|
|
|
|
if !m.board.Done {
|
|
footer := "> "
|
|
for i := 0; i < 5; i++ {
|
|
if i < len(m.buffer) {
|
|
footer += string(unicode.ToUpper(m.buffer[i]))
|
|
} else {
|
|
footer += "_"
|
|
}
|
|
footer += " "
|
|
}
|
|
footer += "<"
|
|
|
|
s += promptStyle.Render(footer) + "\n"
|
|
} else {
|
|
msg := ""
|
|
if m.board.CurrentGuess == -1 {
|
|
if m.board.Solution != "" {
|
|
msg += fmt.Sprintf("Oof! The word was %s.", m.board.Solution)
|
|
}
|
|
} else {
|
|
msg += fmt.Sprintf("Congrats! You guessed in %d.", m.board.CurrentGuess)
|
|
}
|
|
msg += " Come back tomorrow for the next word. (Press CTRL+C to exit)"
|
|
|
|
s += promptStyle.Render(msg) + "\n"
|
|
}
|
|
|
|
if m.error != "" {
|
|
s += errorStyle.Render(m.error) + "\n"
|
|
}
|
|
|
|
return s
|
|
}
|
|
|
|
func main() {
|
|
updateMsg := update.CheckVersion(update.GetGiteaRelease("tildegit.org", "jakew", "wordle"), BuildVersion)
|
|
if updateMsg != "" {
|
|
fmt.Println(fmt.Sprintf("%v. Press enter to continue...", updateMsg))
|
|
bufio.NewReader(os.Stdin).ReadBytes('\n')
|
|
}
|
|
|
|
p := tea.NewProgram(initialModel())
|
|
if err := p.Start(); err != nil {
|
|
fmt.Printf("Something has gone wrong: %v", err)
|
|
os.Exit(1)
|
|
}
|
|
}
|