Kistaro Windrider
c30aca1f31
* "Uncooperative cards" is now a warning. * Cards and actions get "Then" invoked before the card processor considers erroring out. * Terminal UI: Errors and warnings from actions are displayed during the response; they're not only added to the temporary messages now.
97 lines
2.5 KiB
Go
97 lines
2.5 KiB
Go
package cardsim
|
|
|
|
import (
|
|
"fmt"
|
|
"strings"
|
|
)
|
|
|
|
// Message is an opaque interface representing a displayable message.
|
|
// Using an interface here allows for implementation of new message display
|
|
// and formatting features without rewriting all existing callers.
|
|
type Message interface {
|
|
fmt.Stringer
|
|
}
|
|
|
|
// Titled desccribes any type that returns a Message as a title, given a Player
|
|
// (which it may ignore).
|
|
type Titled[C StatsCollection] interface {
|
|
Title(*Player[C]) Message
|
|
}
|
|
|
|
type stringMessage string
|
|
|
|
func (s stringMessage) String() string {
|
|
return string(s)
|
|
}
|
|
|
|
// MsgStr returns a Message representing a fixed string.
|
|
func MsgStr(s string) Message {
|
|
return stringMessage(s)
|
|
}
|
|
|
|
// Msgf is a Sprintf-like function that produces a Message equivalent to the
|
|
// one created by MsgStr.
|
|
func Msgf(f string, args ...any) Message {
|
|
return stringMessage(fmt.Sprintf(f, args...))
|
|
}
|
|
|
|
// ErrorMessage returns a Message representing an Error.
|
|
// This is preferred over Msgf for errors, since future versions of the library
|
|
// may perform special message formatting for errors.
|
|
func ErrorMessage(e error) Message {
|
|
if e == nil {
|
|
return nil
|
|
}
|
|
if IsSeriousError(e) {
|
|
return MultiMessage{MsgStr("SERIOUS ERROR:"), Msgf("%v", e)}
|
|
}
|
|
return MultiMessage{MsgStr("Warning:"), Msgf("%v", e)}
|
|
}
|
|
|
|
// A SpecialMessage is a specific, uniquely identifiable message.
|
|
type SpecialMessage struct {
|
|
msg Message
|
|
}
|
|
|
|
// String implements Message.
|
|
func (s *SpecialMessage) String() string {
|
|
if s == nil {
|
|
return ""
|
|
}
|
|
return s.msg.String()
|
|
}
|
|
|
|
// Messages that various display surfaces or other components may have a special interpretation of
|
|
// and identify specifically. These are largely sentinel values. Nil is a paragraph break.
|
|
var (
|
|
SectionBreak = &SpecialMessage{MsgStr(" -------------------------------------------------------------------- ")}
|
|
ChapterBreak = &SpecialMessage{MsgStr(" ==================================================================== ")}
|
|
)
|
|
|
|
// IsSpecialMessage returns whether a provided Message is a specific SpecialMessage.
|
|
func IsSpecialMessage(m Message, s *SpecialMessage) bool {
|
|
if m == nil {
|
|
return s == nil
|
|
}
|
|
if s2, ok := m.(*SpecialMessage); ok {
|
|
return s == s2
|
|
}
|
|
return false
|
|
}
|
|
|
|
// MultiMessage is a sequence of messages treated like one message.
|
|
type MultiMessage []Message
|
|
|
|
func (m MultiMessage) String() string {
|
|
s := make([]string, len(m))
|
|
for i, msg := range m {
|
|
if msg == nil {
|
|
s[i] = ""
|
|
continue
|
|
}
|
|
s[i] = msg.String()
|
|
continue
|
|
}
|
|
return strings.Join(s, "\n")
|
|
}
|