Skip to content

Instantly share code, notes, and snippets.

Embed
What would you like to do?
Noodling around with core.spec, modelling M:tG card data
(ns magic-the-gathering-card-spec
(:require [clojure.spec :as s]
[clojure.spec.gen :as gen]))
(s/def ::pos-int (s/and int? (complement neg?)))
(s/def ::set string?)
(s/def ::set-number ::pos-int)
(s/def ::artist string?)
(s/def ::metadata (s/keys :req-un [::set ::set-number ::artist]))
(s/def ::name string?)
(s/def ::type #{:land :creature :artifact :enchantment :sorcery :instant :planeswalker})
(s/def ::types (s/and set? (s/+ ::type)))
(s/def ::sub-type ::type)
(s/def ::rules string?)
(s/def ::legendary? boolean?)
(s/def ::world? boolean?)
(s/def ::base-card (s/keys :req-un [::name ::types ::metadata ::rules]
:opt-un [::sub-type ::legendary? ::world?]))
(s/def ::amount ::pos-int)
(s/def ::color #{:white :blue :black :red :green})
(s/def ::mana (s/keys :req-un [::amount]
:opt-un [::color]))
(s/def ::manas (s/+ ::mana))
(s/def ::cost (s/* ::manas))
(s/def ::spell (s/and ::base-card (s/keys :req-un [::cost])))
(s/def ::power int?)
(s/def ::toughness int?)
(s/def ::creature (s/and ::spell (s/keys :req-un [::power ::toughness])))
(s/def ::loyalty int?)
(s/def ::planeswalker (s/and ::spell (s/keys :req-un [::loyalty])))
(defmulti card-spec ::types)
(defmethod card-spec #{:land} [_] ::base-card)
(defmethod card-spec #{:creature} [_] ::creature)
(defmethod card-spec #{:artifact} [_] ::spell)
(defmethod card-spec #{:enchantment} [_] ::spell)
(defmethod card-spec #{:sorcery} [_] ::spell)
(defmethod card-spec #{:instant} [_] ::spell)
(defmethod card-spec #{:planeswalker} [_] ::planeswalker)
(defmethod card-spec #{:artifact :creature} [_] ::creature)
(defmethod card-spec #{:enchantment :creature} [_] ::creature)
(defmethod card-spec #{:artifact :enchantment} [_] ::spell)
(s/def ::card (s/multi-spec card-spec ::types)) ;; doesn't work yet, because generating `s/and` requires extra effort
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
You can’t perform that action at this time.