diff --git a/cardsim/terminalui.go b/cardsim/terminalui.go index 26234a5..aa01686 100644 --- a/cardsim/terminalui.go +++ b/cardsim/terminalui.go @@ -87,18 +87,25 @@ func pickNextAction[C StatsCollection](p *Player[C]) (isCard bool, cardIdx int, max := displayHandMenu(p, handOffset) divider() - fmt.Printf("Show just (M)essages, (I)nfo Panels, (A)ctions, make a choice (1-%d), or (Q)uit? > ", max+1) + fmt.Printf("Show just (M)essages, (I)nfo Panels, (A)ctions, or consider an action (1-%d), or (Q)uit? > ", max) input := getResponse() switch input { // Special cases case "m", "msg", "message", "messages": cls() - displayMessageSection(p) + if displayMessageSection(p) { + divider() + } + displayOnePanel(p, p.Prompt) wait() case "s", "stat", "stats", "i", "info", "p", "panel", "panels", "infopanel", "infopanels": statsMode(p) case "a", "act", "actions": - actionsMode(p) + var committed bool + isCard, cardIdx, choiceIdx, committed, err = actionsMode(p) + if committed { + return + } case "q", "quit", "exit": confirmQuit() default: @@ -106,29 +113,22 @@ func pickNextAction[C StatsCollection](p *Player[C]) (isCard bool, cardIdx int, if err != nil { fmt.Println("Sorry, I don't understand.") wait() - return pickNextAction(p) - } - if i > max { - fmt.Println("That's not a valid action.") + } else if i > max { + fmt.Println("That's not on this menu. If the menu is too big to read, choose a detail view.") wait() - return pickNextAction(p) - } - i -= 1 - if i < actionsOffset { + } else if i <= actionsOffset { cls() - displayOnePanel(p, p.InfoPanels[i]) + displayOnePanel(p, p.InfoPanels[i-1]) wait() } else if i < handOffset { - cls() - i -= actionsOffset + i = i - actionsOffset - 1 option, promptErr := promptCard(p, p.PermanentActions[i]) if option >= 0 || IsSeriousError(promptErr) { return false, i, option, promptErr } } else { - cls() - i -= handOffset - option, promptErr := promptCard(p, p.Hand[i]) + i = i - handOffset - 1 + option, promptErr := promptCard(p, p.Hand[i-handOffset-1]) if option >= 0 || IsSeriousError(promptErr) { return true, i, option, nil } @@ -352,3 +352,57 @@ func statsMode[C StatsCollection](p *Player[C]) error { // Loop to re-display info panels menu. } } + +func actionsMode[C StatsCollection](p *Player[C]) (isCard bool, cardIdx, choiceIdx int, committed bool, err error) { + var errs ErrorCollector + for { + cls() + pOff := displayPermanentActionsMenu(p, 0) + if pOff > 0 { + fmt.Println() + } + max := displayHandMenu(p, pOff) + + if max <= 0 { + fmt.Println("There are no actions available and no cards in hand.") + fmt.Println("That's a problem. The game is stuck.") + confirmQuit() + errs.Add(WarningStalemate) + return false, -1, -1, true, errs.Emit() + } + + fmt.Println() + fmt.Printf("Go (B)ack, (Q)uit, or consider an action (1-%d)? > ", max) + input := getResponse() + switch input { + case "b", "back": + return false, -1, -1, false, errs.Emit() + case "q", "quit": + confirmQuit() + default: + v, err := strconv.Atoi(input) + if err != nil { + fmt.Println("Sorry, I don't understand.") + wait() + } else if v < 1 || v > max { + fmt.Println("That's not a card or action.") + wait() + } else if v <= pOff { + v-- + optIdx, err := promptCard(p, p.PermanentActions[v]) + errs.Add(err) + if optIdx >= 0 || IsSeriousError(err) { + return false, v, optIdx, true, errs.Emit() + } + } else { + v = v - pOff - 1 + optIdx, err := promptCard(p, p.Hand[v]) + errs.Add(err) + if optIdx >= 0 || IsSeriousError(err) { + return true, v, optIdx, true, errs.Emit() + } + } + } + // Re-prompt to get a valid choice. + } +}