aboutsummaryrefslogtreecommitdiff
path: root/go/game/card.go
diff options
context:
space:
mode:
Diffstat (limited to 'go/game/card.go')
-rw-r--r--go/game/card.go157
1 files changed, 116 insertions, 41 deletions
diff --git a/go/game/card.go b/go/game/card.go
index 07ef033b..d4515676 100644
--- a/go/game/card.go
+++ b/go/game/card.go
@@ -1,6 +1,7 @@
package game
import (
+ "fmt"
"io"
"log"
"net/http"
@@ -15,30 +16,30 @@ import (
type CardType int
const (
- UndefinedCardType CardType = iota
- UnitType
- SpellType
- ArtifactType
- EquipmentType
- PotionType
- IntentionType
+ undefinedCardType CardType = iota
+ unitType
+ spellType
+ artifactType
+ equipmentType
+ potionType
+ intentionType
)
func (ct CardType) String() string {
switch ct {
- case UndefinedCardType:
+ case undefinedCardType:
return "undefined"
- case UnitType:
+ case unitType:
return "unit"
- case SpellType:
+ case spellType:
return "spell"
- case ArtifactType:
+ case artifactType:
return "artifact"
- case EquipmentType:
+ case equipmentType:
return "equipment"
- case PotionType:
+ case potionType:
return "potion"
- case IntentionType:
+ case intentionType:
return "intention"
}
log.Panicf("Switch not exhausting %d", ct)
@@ -53,26 +54,63 @@ var CardTypes = struct {
Potion CardType
Intention CardType
}{
- Unit: UnitType,
- Spell: SpellType,
- Artifact: ArtifactType,
- Equipment: EquipmentType,
- Potion: PotionType,
- Intention: IntentionType,
+ Unit: unitType,
+ Spell: spellType,
+ Artifact: artifactType,
+ Equipment: equipmentType,
+ Potion: potionType,
+ Intention: intentionType,
}
var CardTypeNames = map[string]CardType{
- "unit": UnitType,
- "spell": SpellType,
- "artifact": ArtifactType,
- "equipment": EquipmentType,
- "potion": PotionType,
- "intention": IntentionType,
+ "unit": unitType,
+ "spell": spellType,
+ "artifact": artifactType,
+ "equipment": equipmentType,
+ "potion": potionType,
+ "intention": intentionType,
+}
+
+type cardImplementation interface {
+ spawnTiles(*State, *Player) []*Tile
+ fullActionPrototypes(*Unit) []*FullActionPrototype
+ freeActionPrototypes(Permanent) []*FreeActionPrototype
+}
+
+// Default implementation of the cardImplementation interface.
+//
+// Card Implementations should embed this struct to "inherit" the
+// default behavior.
+type cardImplementationBase struct{}
+
+func (impl *cardImplementationBase) spawnTiles(*State, *Player) []*Tile {
+ return nil
+}
+
+func (impl *cardImplementationBase) fullActionPrototypes(*Unit) []*FullActionPrototype {
+ return nil
+}
+
+func (impl *cardImplementationBase) freeActionPrototypes(Permanent) []*FreeActionPrototype {
+ return nil
+}
+
+// Map of all card implementations
+var cardImplementations map[string]cardImplementation
+
+func getCardImplementation(c *Card) cardImplementation {
+ if impl, found := cardImplementations[c.Path()]; found {
+ return impl
+ }
+
+ impl := newParsedCardImplementation(c)
+ cardImplementations[c.Path()] = impl
+ return impl
}
const (
CARD_DATA_URL string = "data/cards"
- NOT_BUYABLE int = -1
+ NOT_BUYABLE int = -1 // Maybe this needs to be changed some day to allow more design space
)
type Card struct {
@@ -81,9 +119,22 @@ type Card struct {
Type CardType
BuyCost int
Values map[string]interface{}
+ Impl cardImplementation
}
-var cards = map[string]map[string][]byte{}
+var cardDefinitions = map[string]map[string][]byte{}
+
+func getCardDefinition(set, cardName string) []byte {
+ cardDefinition, found := cardDefinitions[set][cardName]
+ if !found {
+ cardDefinition = retrieveCardDefinition(path.Join(set, cardName))
+ if cardDefinitions[set] == nil {
+ cardDefinitions[set] = map[string][]byte{}
+ }
+ cardDefinitions[set][cardName] = cardDefinition
+ }
+ return cardDefinition
+}
func retrieveCardDefinition(cardPath string) []byte {
url := PROTOCOL + path.Join(BASE_URL, CARD_DATA_URL, cardPath+".yml")
@@ -135,12 +186,16 @@ func (card *Card) parseDefinition(definition []byte) {
bc, found := data["buy"]
if found {
card.BuyCost = bc.(int)
+ } else {
+ card.BuyCost = NOT_BUYABLE
}
delete(data, "buy")
for k, v := range data {
card.Values[k.(string)] = v
}
+
+ card.Impl = getCardImplementation(card)
}
func (card *Card) getCanonicalValues(key string) []string {
@@ -187,9 +242,23 @@ func (card *Card) hasEffect(effect string) bool {
return slices.Contains(card.getEffects(), effect)
}
-func (card *Card) hasMovementEffect(effect string) bool {
+func (card *Card) getXEffect(effect string) (int, error) {
+ for _, e := range card.getEffects() {
+ if !strings.Contains(e, effect) {
+ continue
+ }
+
+ tokens := strings.SplitN(e, " ", 2)
+ return strconv.Atoi(tokens[1])
+ }
+ return 0, fmt.Errorf("Crad %s has no effect %s", card.Name, effect)
+}
+
+func (card *Card) hasPlacementConstrain(effect string) bool {
if slices.Contains(card.getEffects(), effect) {
return true
+ } else if card.Type != CardTypes.Unit {
+ return false
}
movementDesc := card.getCanonicalValues("movement")[0]
@@ -208,16 +277,15 @@ func NewCard(cardPath string) *Card {
cardName := path.Base(cardPath)
set := path.Dir(cardPath)
- cardDefinition, found := cards[set][cardName]
- if !found {
- cardDefinition = retrieveCardDefinition(cardPath)
- if cards[set] == nil {
- cards[set] = map[string][]byte{}
- }
- cards[set][cardName] = cardDefinition
- }
+ cardDefinition := getCardDefinition(set, cardName)
- c := Card{"", SetIdentifierNames[set], UndefinedCardType, -1, map[string]interface{}{}}
+ c := Card{
+ Name: "",
+ Set: SetIdentifierNames[set],
+ Type: undefinedCardType,
+ BuyCost: NOT_BUYABLE,
+ Values: map[string]interface{}{},
+ }
c.parseDefinition(cardDefinition)
return &c
}
@@ -228,12 +296,19 @@ func (c *Card) Path() string {
}
func (c *Card) IsPermanent() bool {
- return c.Type != UndefinedCardType && c.Type != SpellType && c.Type != IntentionType
+ return c.Type == CardTypes.Unit ||
+ c.Type != CardTypes.Artifact ||
+ c.Type != CardTypes.Equipment ||
+ c.Type != CardTypes.Potion
+}
+
+func (c *Card) IsBuyable() bool {
+ return c.BuyCost != NOT_BUYABLE
}
-func (c *Card) GetPlayCosts() int {
+func (c *Card) PlayCosts() int {
switch c.Type {
- case UnitType:
+ case CardTypes.Unit:
return c.Values["upkeep"].(int)
default:
return c.Values["play"].(int)