From 1104c6e4e9ee9de5008a13a8d804a88cfc7a49a9 Mon Sep 17 00:00:00 2001 From: tolelom <98kimsungmin@naver.com> Date: Tue, 24 Mar 2026 13:44:43 +0900 Subject: [PATCH] fix: lock SoloMode at start, shop feedback, dead player exploration block Co-Authored-By: Claude Opus 4.6 (1M context) --- game/session.go | 3 --- ui/model.go | 18 ++++++++++++++++-- ui/shop_view.go | 18 ++++++++++-------- 3 files changed, 26 insertions(+), 13 deletions(-) diff --git a/game/session.go b/game/session.go index ffa611f..049ee22 100644 --- a/game/session.go +++ b/game/session.go @@ -154,9 +154,6 @@ func (s *GameSession) combatLoop() { } if changed { s.state.Players = remaining - if len(s.state.Players) <= 1 { - s.state.SoloMode = true - } if len(s.state.Players) == 0 { s.state.GameOver = true s.mu.Unlock() diff --git a/ui/model.go b/ui/model.go index 2b6666c..bfcc079 100644 --- a/ui/model.go +++ b/ui/model.go @@ -50,6 +50,7 @@ type Model struct { chatting bool chatInput string rankingSaved bool + shopMsg string } func NewModel(width, height int, fingerprint string, lobby *game.Lobby, db *store.DB) Model { @@ -121,7 +122,7 @@ func (m Model) View() string { case screenGame: return renderGame(m.gameState, m.width, m.height, m.targetCursor, m.moveCursor, m.chatting, m.chatInput) case screenShop: - return renderShop(m.gameState, m.width, m.height) + return renderShop(m.gameState, m.width, m.height, m.shopMsg) case screenResult: var rankings []store.RunRecord if m.store != nil { @@ -364,6 +365,15 @@ func (m Model) updateGame(msg tea.Msg) (tea.Model, tea.Cmd) { switch m.gameState.Phase { case game.PhaseExploring: + // Dead players can only observe, not move + for _, p := range m.gameState.Players { + if p.Fingerprint == m.fingerprint && p.IsDead() { + if isQuit(key) { + return m, tea.Quit + } + return m, nil + } + } neighbors := m.getNeighbors() if isUp(key) { if m.moveCursor > 0 { @@ -441,7 +451,11 @@ func (m Model) updateShop(msg tea.Msg) (tea.Model, tea.Cmd) { case "1", "2", "3": if m.session != nil { idx := int(key.String()[0] - '1') - m.session.BuyItem(m.fingerprint, idx) + if m.session.BuyItem(m.fingerprint, idx) { + m.shopMsg = "Purchased!" + } else { + m.shopMsg = "Not enough gold!" + } m.gameState = m.session.GetState() } case "q": diff --git a/ui/shop_view.go b/ui/shop_view.go index 31760b0..7afb87c 100644 --- a/ui/shop_view.go +++ b/ui/shop_view.go @@ -7,10 +7,13 @@ import ( "github.com/tolelom/catacombs/game" ) -func renderShop(state game.GameState, width, height int) string { +func renderShop(state game.GameState, width, height int, shopMsg string) string { headerStyle := lipgloss.NewStyle(). Foreground(lipgloss.Color("226")). Bold(true) + msgStyle := lipgloss.NewStyle(). + Foreground(lipgloss.Color("196")). + Bold(true) header := headerStyle.Render("── Shop ──") items := "" @@ -20,11 +23,10 @@ func renderShop(state game.GameState, width, height int) string { menu := "[1-3] Buy [Q] Leave Shop" - return lipgloss.JoinVertical(lipgloss.Left, - header, - "", - items, - "", - menu, - ) + parts := []string{header, "", items, "", menu} + if shopMsg != "" { + parts = append(parts, "", msgStyle.Render(shopMsg)) + } + + return lipgloss.JoinVertical(lipgloss.Left, parts...) }