From 55ddbbc4de71b7f0dd9ffb27d393091b75f6f902 Mon Sep 17 00:00:00 2001 From: Anthony Ettinger Date: Sun, 5 Jul 2026 13:16:05 +0000 Subject: [PATCH] Fix hangman: lowercase r swallowed by restart binding during play The Update key switch bound "r" to restart, but returned early even when the game was still active, so lowercase r could never be entered as a letter guess (Shift+R worked because "R" didn't match the case). Now r only restarts when dead; otherwise it falls through to the guess logic. Co-Authored-By: Claude Opus 4.8 --- plugins/arcade/hangman.go | 3 ++- plugins/arcade/hangman_test.go | 12 ++++++++++++ 2 files changed, 14 insertions(+), 1 deletion(-) diff --git a/plugins/arcade/hangman.go b/plugins/arcade/hangman.go index 508dbbe..534ede2 100644 --- a/plugins/arcade/hangman.go +++ b/plugins/arcade/hangman.go @@ -78,10 +78,11 @@ func (h *hangman) Update(msg tea.Msg) (tea.Model, tea.Cmd) { case "q", "esc": return h, back case "r": + // Only "restart" once dead; during play, r is a normal letter guess + // and must fall through to the guessing logic below. if h.dead { return newHangman(h.user, h.ctx), nil } - return h, nil case " ", "enter": if h.won { h.deal() // advance to the next word diff --git a/plugins/arcade/hangman_test.go b/plugins/arcade/hangman_test.go index d9851a7..e8c6b42 100644 --- a/plugins/arcade/hangman_test.go +++ b/plugins/arcade/hangman_test.go @@ -68,6 +68,18 @@ func TestHangmanDeathAfterSixMisses(t *testing.T) { } } +// The "r" restart binding must not swallow r as a letter guess during play. +func TestHangmanLowercaseRIsAGuess(t *testing.T) { + h := newTestHangman("ROUTER") + for _, r := range "router" { + m, _ := h.Update(key(r)) + h = m.(*hangman) + } + if !h.won { + t.Fatalf("lowercase r should count as a guess and solve ROUTER") + } +} + func TestHangmanLowercaseInputAndAdvance(t *testing.T) { h := newTestHangman("CAT") for _, r := range "cat" { // lowercase should still solve