Prototype for TablePolicy
This commit is contained in:
parent
e018bd0ad6
commit
ba5171fd67
27
.vscode/koboldsimsnippets.code-snippets
vendored
Normal file
27
.vscode/koboldsimsnippets.code-snippets
vendored
Normal file
@ -0,0 +1,27 @@
|
||||
{
|
||||
// Place your KoboldSim workspace snippets here. Each snippet is defined under a snippet name and has a scope, prefix, body and
|
||||
// description. Add comma separated ids of the languages where the snippet is applicable in the scope field. If scope
|
||||
// is left empty or omitted, the snippet gets applied to all languages. The prefix is what is
|
||||
// used to trigger the snippet and the body will be expanded and inserted. Possible variables are:
|
||||
// $1, $2 for tab stops, $0 for the final cursor position, and ${1:label}, ${2:another} for placeholders.
|
||||
// Placeholders with the same ids are connected.
|
||||
// Example:
|
||||
// "Print to console": {
|
||||
// "scope": "javascript,typescript",
|
||||
// "prefix": "log",
|
||||
// "body": [
|
||||
// "console.log('$1');",
|
||||
// "$2"
|
||||
// ],
|
||||
// "description": "Log output to console"
|
||||
// }
|
||||
"KoboldMine Add case": {
|
||||
"scope": "go",
|
||||
"prefix": "case",
|
||||
"body": [
|
||||
"case ${1:field}:",
|
||||
"\tk.${1:field} += amount",
|
||||
"\treturn k.${1:field}",
|
||||
],
|
||||
}
|
||||
}
|
@ -9,6 +9,7 @@ import (
|
||||
var (
|
||||
ErrOptionNotEnabled = errors.New("option not enabled")
|
||||
ErrPolicyNotEnacted = errors.New("cannot unenact policy that is not enacted")
|
||||
ErrNoFieldLabel = errors.New("field does not exist")
|
||||
|
||||
// ErrUnimplemented and ErrKeepMessaage are "non-errors". They are used
|
||||
// as special signals that the result needs to be handled in a special way;
|
||||
@ -190,7 +191,7 @@ type BasicPolicy struct {
|
||||
}
|
||||
|
||||
// YesWeCan returns true. It's the default value for BasicPolicy.CanDo / BasicPolicy.CanUndo.
|
||||
func YesWeCan(*BasicPolicy, *Player) bool {
|
||||
func YesWeCan[T any](T, *Player) bool {
|
||||
return true
|
||||
}
|
||||
|
||||
@ -260,6 +261,94 @@ func (b *BasicPolicy) Is(p Policy) bool {
|
||||
return false
|
||||
}
|
||||
|
||||
// TablePolicy is a Policy where all numerical changes are defined by
|
||||
// adding a constant to some set of fields (defined by `EffectsTable``)
|
||||
// and subtracting it back out when de-enacting. If the currently
|
||||
// enacted option is re-enacted, it refunds the player's action point.
|
||||
type TablePolicy struct {
|
||||
Desc cardsim.Message
|
||||
UnenactedDesc cardsim.Message
|
||||
EnactedDesc cardsim.Message
|
||||
NothingChanged cardsim.message
|
||||
EffectsTable map[FieldLabel]float64
|
||||
CanDo func(*TablePolicy, *Player) bool
|
||||
|
||||
CurrentlyEnacted bool
|
||||
LastEnactedPolicy Policy
|
||||
LastEnactedIdx int
|
||||
}
|
||||
|
||||
// LastEnacted notifies t about the last-enacted policy in its group. It updates
|
||||
// t.currentlyEnacted accordingly.
|
||||
func (t *TablePolicy) LastEnacted(i int, p Policy) {
|
||||
t.LastEnactedPolicy = p
|
||||
t.LastEnactedIdx = i
|
||||
t.CurrentlyEnacted = t.Is(p)
|
||||
}
|
||||
|
||||
// OptionText implements CardOption.
|
||||
func (t *TablePolicy) OptionText(*Player) (cardsim.Message, error) {
|
||||
if t.CurrentlyEnacted {
|
||||
if t.EnactedDesc == nil {
|
||||
return nil, ErrUnimplemented
|
||||
}
|
||||
return t.EnactedDesc, nil
|
||||
}
|
||||
if t.UnenactedDesc == nil {
|
||||
return nil, ErrUnimplemented
|
||||
}
|
||||
return t.UnenactedDesc, nil
|
||||
}
|
||||
|
||||
// Enact implements CardOption.
|
||||
func (t *TablePolicy) Enact(p *Player) (cardsim.Message, error) {
|
||||
if t.EffectsTable == nil {
|
||||
return nil, ErrUnimplemented
|
||||
}
|
||||
if t.CurrentlyEnacted {
|
||||
p.ActionsRemaining++
|
||||
if t.NothingChanged == nil {
|
||||
t.NothingChanged = cardsim.MsgStr("You continue your current approach.")
|
||||
}
|
||||
return t.NothingChanged, nil
|
||||
}
|
||||
var errs cardsim.ErrorCollector
|
||||
for label, amount := range t.EffectsTable {
|
||||
errs.Add(p.Stats.Add(label, amount))
|
||||
}
|
||||
return t.EnactedDesc, errs.Emit()
|
||||
}
|
||||
|
||||
// Unenact implements Policy.
|
||||
func (t *TablePolicy) Unenact(p *Player) error {
|
||||
if !t.CurrentlyEnacted {
|
||||
return ErrPolicyNotEnacted
|
||||
}
|
||||
var errs cardsim.ErrorCollector
|
||||
for label, amount := range t.EffectsTable {
|
||||
errs.Add(p.Stats.Add(label, -amount)
|
||||
}
|
||||
return errs.Emit()
|
||||
}
|
||||
|
||||
// Enabled implements CardOption.
|
||||
func (t *TablePolicy) Enabled(p *Player) bool {
|
||||
if t.CurrentlyEnacted {
|
||||
return true
|
||||
}
|
||||
if t.CanDo == nil {
|
||||
panic(ErrUnimplemented)
|
||||
}
|
||||
return t.CanDo(t, p)
|
||||
}
|
||||
|
||||
func (t *TablePolicy) Is(p Policy) bool {
|
||||
if o, ok := p.(*TablePolicy); ok {
|
||||
return o == b
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
// A VerbosePolicy is a group of related policies pretending to all be the same
|
||||
// policy. Which policy is used is determined by what the previous policy for
|
||||
// the card was (as reported via a call to LastEnacted):
|
||||
|
@ -164,3 +164,50 @@ func NewKoboldMine() *KoboldMine {
|
||||
Secrecy: 95,
|
||||
}
|
||||
}
|
||||
|
||||
type FieldLabel string
|
||||
|
||||
const (
|
||||
BasePopulation FieldLabel = "BasePopulation"
|
||||
Scavenging FieldLabel = "Scavenging"
|
||||
Militarism FieldLabel = "Militarism"
|
||||
FoodSupply FieldLabel = "FoodSupply"
|
||||
ForeignRelations FieldLabel = "ForeignRelations"
|
||||
Rebellion FieldLabel = "Rebellion"
|
||||
Madness FieldLabel = "Madness"
|
||||
Cruelty FieldLabel = "Cruelty"
|
||||
Authoritarianism FieldLabel = "Authoritarianism"
|
||||
)
|
||||
|
||||
func (k *KoboldMine) Add(which FieldLabel, amount float64) error {
|
||||
switch(which) {
|
||||
case BasePopulation:
|
||||
k.BasePopulation += amount
|
||||
return nil
|
||||
case Scavenging:
|
||||
k.Scavenging += amount
|
||||
return nil
|
||||
case Militarism:
|
||||
k.Militarism += amount
|
||||
return nil
|
||||
case FoodSupply:
|
||||
k.FoodSupply += amount
|
||||
return nil
|
||||
case ForeignRelations:
|
||||
k.ForeignRelations += amount
|
||||
return nil
|
||||
case Rebellion:
|
||||
k.Rebellion += amount
|
||||
return nil
|
||||
case Madness:
|
||||
k.Madness += amount
|
||||
return nil
|
||||
case Cruelty:
|
||||
k.Cruelty += amount
|
||||
return nil
|
||||
case Authoritarianism:
|
||||
k.Authoritarianism += amount
|
||||
return nil
|
||||
}
|
||||
return fmt.Errorf("cannot add %d to %q: %w", amount, which, ErrNoFieldLabel)
|
||||
}
|
||||
|
Loading…
Reference in New Issue
Block a user