fix: lock SoloMode at start, shop feedback, dead player exploration block

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
2026-03-24 13:44:43 +09:00
parent c555ff6e92
commit 1104c6e4e9
3 changed files with 26 additions and 13 deletions

View File

@@ -154,9 +154,6 @@ func (s *GameSession) combatLoop() {
} }
if changed { if changed {
s.state.Players = remaining s.state.Players = remaining
if len(s.state.Players) <= 1 {
s.state.SoloMode = true
}
if len(s.state.Players) == 0 { if len(s.state.Players) == 0 {
s.state.GameOver = true s.state.GameOver = true
s.mu.Unlock() s.mu.Unlock()

View File

@@ -50,6 +50,7 @@ type Model struct {
chatting bool chatting bool
chatInput string chatInput string
rankingSaved bool rankingSaved bool
shopMsg string
} }
func NewModel(width, height int, fingerprint string, lobby *game.Lobby, db *store.DB) Model { 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: case screenGame:
return renderGame(m.gameState, m.width, m.height, m.targetCursor, m.moveCursor, m.chatting, m.chatInput) return renderGame(m.gameState, m.width, m.height, m.targetCursor, m.moveCursor, m.chatting, m.chatInput)
case screenShop: case screenShop:
return renderShop(m.gameState, m.width, m.height) return renderShop(m.gameState, m.width, m.height, m.shopMsg)
case screenResult: case screenResult:
var rankings []store.RunRecord var rankings []store.RunRecord
if m.store != nil { if m.store != nil {
@@ -364,6 +365,15 @@ func (m Model) updateGame(msg tea.Msg) (tea.Model, tea.Cmd) {
switch m.gameState.Phase { switch m.gameState.Phase {
case game.PhaseExploring: 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() neighbors := m.getNeighbors()
if isUp(key) { if isUp(key) {
if m.moveCursor > 0 { if m.moveCursor > 0 {
@@ -441,7 +451,11 @@ func (m Model) updateShop(msg tea.Msg) (tea.Model, tea.Cmd) {
case "1", "2", "3": case "1", "2", "3":
if m.session != nil { if m.session != nil {
idx := int(key.String()[0] - '1') 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() m.gameState = m.session.GetState()
} }
case "q": case "q":

View File

@@ -7,10 +7,13 @@ import (
"github.com/tolelom/catacombs/game" "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(). headerStyle := lipgloss.NewStyle().
Foreground(lipgloss.Color("226")). Foreground(lipgloss.Color("226")).
Bold(true) Bold(true)
msgStyle := lipgloss.NewStyle().
Foreground(lipgloss.Color("196")).
Bold(true)
header := headerStyle.Render("── Shop ──") header := headerStyle.Render("── Shop ──")
items := "" items := ""
@@ -20,11 +23,10 @@ func renderShop(state game.GameState, width, height int) string {
menu := "[1-3] Buy [Q] Leave Shop" menu := "[1-3] Buy [Q] Leave Shop"
return lipgloss.JoinVertical(lipgloss.Left, parts := []string{header, "", items, "", menu}
header, if shopMsg != "" {
"", parts = append(parts, "", msgStyle.Render(shopMsg))
items, }
"",
menu, return lipgloss.JoinVertical(lipgloss.Left, parts...)
)
} }