|
|
|
@ -8,14 +8,14 @@ import (
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
var (
|
|
|
|
|
ErrUncooperativeCards = errors.New("a milion cards refused to join the hand")
|
|
|
|
|
ErrInvalidCard = errors.New("invalid card specified")
|
|
|
|
|
ErrInvalidChoice = errors.New("invalid choice specified")
|
|
|
|
|
ErrNotUrgent = errors.New("action not urgent when urgent card is available")
|
|
|
|
|
ErrNoActions = errors.New("no actions remaining")
|
|
|
|
|
ErrNotDebugging = errors.New("this is a debug-only feature and you're not in debug mode")
|
|
|
|
|
ErrInvalidCard = errors.New("invalid card specified")
|
|
|
|
|
ErrInvalidChoice = errors.New("invalid choice specified")
|
|
|
|
|
ErrNotUrgent = errors.New("action not urgent when urgent card is available")
|
|
|
|
|
ErrNoActions = errors.New("no actions remaining")
|
|
|
|
|
ErrNotDebugging = errors.New("this is a debug-only feature and you're not in debug mode")
|
|
|
|
|
|
|
|
|
|
WarningStalemate = errors.New("no actions can be taken")
|
|
|
|
|
WarningStalemate = &Warning{errors.New("no actions can be taken")}
|
|
|
|
|
WarningUncoperativeCards = &Warning{errors.New("a milion cards refused to join the hand")}
|
|
|
|
|
)
|
|
|
|
|
|
|
|
|
|
// Player stores all gameplay state for one player at a specific point in time.
|
|
|
|
@ -272,9 +272,9 @@ func (p *Player[C]) StartNextTurn() error {
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// Draw draws a card into the hand, informing the card that it has been drawn.
|
|
|
|
|
// If more than a million cards refuse to enter the hand, this crashes with
|
|
|
|
|
// ErrUncooperativeCards. If the deck does not have enough cards, this
|
|
|
|
|
// returns WarningTooFewCards.
|
|
|
|
|
// If more than a million cards refuse to enter the hand, this gives up and
|
|
|
|
|
// returns WarningUncooperativeCards. If the deck does not have enough cards,
|
|
|
|
|
// this returns WarningTooFewCards.
|
|
|
|
|
func (p *Player[C]) Draw() error {
|
|
|
|
|
for attempts := 0; attempts < 1000000; attempts++ {
|
|
|
|
|
if p.Deck.Len() == 0 {
|
|
|
|
@ -286,13 +286,13 @@ func (p *Player[C]) Draw() error {
|
|
|
|
|
return nil
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
return ErrUncooperativeCards
|
|
|
|
|
return WarningUncoperativeCards
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// FillHand draws up to the hand limit, informing cards that they have been
|
|
|
|
|
// drawn. If more than a million cards refuse to enter the hand, this crashes
|
|
|
|
|
// with ErrUncooperativeCards. If the deck does not have enough cards, this
|
|
|
|
|
// returns WarningTooFewCards.
|
|
|
|
|
// drawn. If more than a million cards refuse to enter the hand, this gives up
|
|
|
|
|
// and returns WarningUncooperativeCards. If the deck does not have enough
|
|
|
|
|
// cards, this returns WarningTooFewCards.
|
|
|
|
|
func (p *Player[C]) FillHand() error {
|
|
|
|
|
var lastErr error
|
|
|
|
|
for p.Deck.Len() > 0 && len(p.Hand) < p.HandLimit {
|
|
|
|
@ -386,17 +386,14 @@ func (p *Player[C]) EnactCardUnchecked(cardIdx, choiceIdx int) (Message, error)
|
|
|
|
|
|
|
|
|
|
ret, err := options[choiceIdx].Enact(p)
|
|
|
|
|
errs.Add(err)
|
|
|
|
|
if IsSeriousError(err) {
|
|
|
|
|
p.State = GameCrashed
|
|
|
|
|
return ret, errs.Emit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = card.Then(p, options[choiceIdx])
|
|
|
|
|
errs.Add(err)
|
|
|
|
|
|
|
|
|
|
err = errs.Emit()
|
|
|
|
|
if IsSeriousError(err) {
|
|
|
|
|
p.State = GameCrashed
|
|
|
|
|
}
|
|
|
|
|
return ret, errs.Emit()
|
|
|
|
|
return ret, err
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EnactCard executes a card choice, removes it from the hand, and decrements
|
|
|
|
@ -470,17 +467,13 @@ func (p *Player[C]) enactActionUnchecked(actionSource []Card[C], actionIdx, choi
|
|
|
|
|
|
|
|
|
|
ret, err := chosen.Enact(p)
|
|
|
|
|
errs.Add(err)
|
|
|
|
|
if IsSeriousError(err) {
|
|
|
|
|
p.State = GameCrashed
|
|
|
|
|
return ret, errs.Emit()
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
err = card.Then(p, chosen)
|
|
|
|
|
errs.Add(err)
|
|
|
|
|
if IsSeriousError(err) {
|
|
|
|
|
retErr := errs.Emit()
|
|
|
|
|
if IsSeriousError(retErr) {
|
|
|
|
|
p.State = GameCrashed
|
|
|
|
|
}
|
|
|
|
|
return ret, errs.Emit()
|
|
|
|
|
return ret, retErr
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// EnactPermanentAction executes a permanently-available card and decrements
|
|
|
|
@ -512,15 +505,11 @@ func (p *Player[C]) ReportError(e error) {
|
|
|
|
|
if e == nil || p.DebugLevel < -1 {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
if p.DebugLevel < 0 && !IsSeriousError(e) {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
p.ChapterBreak()
|
|
|
|
|
severity := "[Warning]"
|
|
|
|
|
minLvl := NotDebugging
|
|
|
|
|
if IsSeriousError(e) {
|
|
|
|
|
severity = "[ERROR]"
|
|
|
|
|
minLvl = HideWarnings
|
|
|
|
|
}
|
|
|
|
|
p.TemporaryMessages = append(p.TemporaryMessages, Msgf("%s: %v", severity, e))
|
|
|
|
|
p.Debug(minLvl, ErrorMessage(e))
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
// CanAct returns whether the player has actions theoretically available.
|
|
|
|
@ -534,6 +523,7 @@ func (p *Player[C]) Debug(minLevel int, msg Message) {
|
|
|
|
|
if p.DebugLevel < minLevel || msg == nil {
|
|
|
|
|
return
|
|
|
|
|
}
|
|
|
|
|
p.ChapterBreak()
|
|
|
|
|
p.TemporaryMessages = append(p.TemporaryMessages, msg)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|