diff --git a/cardsim/card.go b/cardsim/card.go index 472f216..cd921b6 100644 --- a/cardsim/card.go +++ b/cardsim/card.go @@ -101,6 +101,15 @@ func (b *BasicCard[C]) Drawn(_ *Player[C]) bool { return true } +// RefundAction returns a func that can be used as an AfterOption, which returns +// the player's action point. +func RefundAction[C StatsCollection]() func(c Card[C], p *Player[C], option CardOption[C]) error { + return func(c Card[C], p *Player[C], option CardOption[C]) error { + p.ActionsRemaining++ + return nil + } +} + // A PanelCard is a Card that takes its title and text from an InfoPanel, // while options, urgency, and the post-option callback are specified // (like a BasicCard). It never does anything in particular when drawn. diff --git a/cardsim/debugging.go b/cardsim/debugging.go new file mode 100644 index 0000000..95a8dce --- /dev/null +++ b/cardsim/debugging.go @@ -0,0 +1,103 @@ +package cardsim + +// Named debug verbosity levels. Using the raw constants is fine too. This +// is roughly consistent with "standard" meanings for these debug levels. +const ( + HideWarnings = -1 + NotDebugging = 0 + DebugWarning = 1 + DebugInfo = 2 + DebugDetail = 3 + DebugFine = 4 + DebugSuperfine = 5 +) + +// ActionCounterDebugCard constructs a BasicCard intended for use only as a +// Debug Action that tinkers with the player's action counter. +func ActionCounterDebugCard[C StatsCollection]() Card[C] { + return &BasicCard[C]{ + CardTitle: MsgStr("Adjust Action Counter"), + CardText: MsgStr("Change the number of actions you have available this turn."), + CardOptions: []CardOption[C]{ + &BasicOption[C]{ + Text: MsgStr("Get an extra action."), + Effect: func(p *Player[C]) error { + p.ActionsRemaining += 2 // counteract the one this costs + return nil + }, + Output: MsgStr("Gotten."), + }, + &BasicOption[C]{ + Text: MsgStr("Waste an action."), + Effect: func(p *Player[C]) error { + return nil + }, + Output: MsgStr("Wasted."), + }, + &BasicOption[C]{ + Text: MsgStr("Get a thousand actions."), + Effect: func(p *Player[C]) error { + p.ActionsRemaining = 1000 + return nil + }, + Output: MsgStr("ActionsRemaining set to 1000."), + }, + &BasicOption[C]{ + Text: MsgStr("Go to exactly 1 action remaining."), + Effect: func(p *Player[C]) error { + p.ActionsRemaining = 1 + return nil + }, + Output: MsgStr("ActionsRemaining set to 1."), + }, + &BasicOption[C]{ + Text: MsgStr("End the turn. (Set actions to 0.)"), + Effect: func(p *Player[C]) error { + p.ActionsRemaining = 0 + return nil + }, + Output: MsgStr("ActionsRemaining zeroed out."), + }, + }, + } +} + +// DebugModeCard constructs a BasicCard to change the player's debug level. +// It is intended for use only as a Debug Action. +func DebugModeCard[C StatsCollection]() Card[C] { + return &BasicCard[C]{ + CardTitle: MsgStr("Change Debug Level"), + CardText: MsgStr("Adjust verbosity of output, or exit debug mode entirely (not recommended)."), + CardOptions: []CardOption[C]{ + debugLevelOption[C]{1, "Enable debug mode. Show warnings."}, + debugLevelOption[C]{2, "Enable debug mode. Show info messages."}, + debugLevelOption[C]{3, "Enable debug mode. Show detailed messages."}, + debugLevelOption[C]{4, "Enable debug mode. Show individual details of operations."}, + debugLevelOption[C]{5, "Enable debug mode. Show every event in excruciating detail."}, + debugLevelOption[C]{0, "NOT RECOMMENDED. Disable debugging (show warnings). IT CAN'T BE TURNED BACK ON."}, + debugLevelOption[C]{-1, "NOT RECOMMENDED. Disable debugging (hide warnings). IT CAN'T BE TURNED BACK ON."}, + }, + AfterOption: RefundAction[C](), + } +} + +type debugLevelOption[C StatsCollection] struct { + level int + description string +} + +// OptionText implements CardOption[C]. +func (d debugLevelOption[C]) OptionText(*Player[C]) (Message, error) { + return Msgf("Set debug level %d: %s", d.level, d.description), nil +} + +// Enact implements CardOption[C]. +func (d debugLevelOption[C]) Enact(p *Player[C]) (Message, error) { + p.DebugLevel = d.level + return Msgf("Debug level is now %d.", d.level), nil +} + +// Enabled implements CardOption[C]. +func (d debugLevelOption[C]) Enabled(p *Player[C]) bool { + return true +} diff --git a/cardsim/player.go b/cardsim/player.go index 40dc85b..0722c73 100644 --- a/cardsim/player.go +++ b/cardsim/player.go @@ -178,51 +178,8 @@ func InitPlayer[C StatsCollection](stats C) *Player[C] { DebugActions: []Card[C]{ &DeckDebugger[C]{}, &PanelCard[C]{Panel: RuleDumper[C]{}}, - &BasicCard[C]{ - CardTitle: MsgStr("Adjust Action Counter"), - CardText: MsgStr("Change the number of actions you have available this turn."), - CardOptions: []CardOption[C]{ - &BasicOption[C]{ - Text: MsgStr("Get an extra action."), - Effect: func(p *Player[C]) error { - p.ActionsRemaining += 2 // counteract the one this costs - return nil - }, - Output: MsgStr("Gotten."), - }, - &BasicOption[C]{ - Text: MsgStr("Waste an action."), - Effect: func(p *Player[C]) error { - return nil - }, - Output: MsgStr("Wasted."), - }, - &BasicOption[C]{ - Text: MsgStr("Get a thousand actions."), - Effect: func(p *Player[C]) error { - p.ActionsRemaining = 1000 - return nil - }, - Output: MsgStr("ActionsRemaining set to 1000."), - }, - &BasicOption[C]{ - Text: MsgStr("Go to exactly 1 action remaining."), - Effect: func(p *Player[C]) error { - p.ActionsRemaining = 1 - return nil - }, - Output: MsgStr("ActionsRemaining set to 1."), - }, - &BasicOption[C]{ - Text: MsgStr("End the turn. (Set actions to 0.)"), - Effect: func(p *Player[C]) error { - p.ActionsRemaining = 0 - return nil - }, - Output: MsgStr("ActionsRemaining zeroed out."), - }, - }, - }, + ActionCounterDebugCard[C](), + DebugModeCard[C](), }, } }