actions mode, prompt cleanup
Fixes some off-by-one errors. A 1-indexed UI in a 0-indexed language is always going to be prone to those and I will no doubt find more when I have enough of a test program to experiment with...
This commit is contained in:
		| @@ -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. | ||||
| 	} | ||||
| } | ||||
|   | ||||
		Reference in New Issue
	
	Block a user