Skip to content

Purely functional Haskell "Magic: The Gathering" card model and game engine.

License

Notifications You must be signed in to change notification settings

thomaseding/mtg-pure

Folders and files

NameName
Last commit message
Last commit date

Latest commit

 
 
 
 
 
 
 
 
 
 
 
 
 
 
 

Repository files navigation

mtg-pure

Purely functional Haskell "Magic: The Gathering" card model and game engine.


About:

MtgPure is a showcase of how to make an elegant purely functional "Magic: The Gathering" DSL model and rules engine.


Model Goals:

  • The world's best MTG encoding.
  • Pure data modelling of cards as a type-safe DSL.
  • Card model is a deep embedding.
  • Card model is algebraic and recursive.
  • Cards type-check if and only if they are valid cards. (Barring a few exceptions such as bottom(⊥) appearing in card definitions.) Examples: creatures in graveyards can't be dealt damage; non-player objects can't draw cards, etc.
  • Card model is expressive enough to replicate its source code through introspection.
  • Cards can be used in arbitrary game formats without change.
  • Formal changes to game rules should not require re-modelling cards. (Cards may be rewritten if they get errata.)
  • Model can encode complex and outlier interactions without brute-force special casing. For example, the model will not contain stuff such as ScrambleverseEffect.

Engine Goals:

  • Exhaustive and type-checked engine.
  • Event-based programmatic control.
  • Solitaire CLI. You control all player actions.
  • Good for exploring card and game-state interactions.

Quickstart Interesting Files For Model


Quickstart Interesting Files For Engine


Quickstart:

$ cabal install fourmolu  # for code generation ; add to PATH if needed
$ cd src
$ runhaskell MtgPure/Model/Object/ToObjectN/CodeGen.hs
$ cd ..
$ cabal build
$ cabal repl
ghci> :m +MtgPure MtgPure.AllCards MtgPure.Cards MtgPure.Model.BasicLandType MtgPure.Model.LandType MtgPure.Model.Recursive
ghci> :i allCards
allCards :: [AnyCard]   -- Defined in `MtgPure.AllCards'
ghci> :i island
island :: Card OTLand   -- Defined in `MtgPure.Cards'
ghci> compare island island
EQ
ghci> print island
Card "Island" $ ElectCardFacet $ LandCharacteristic [] [BasicLand Island] $ LandSpec []
ghci> island == (Card "Island" $ ElectCardFacet $ LandCharacteristic [] [BasicLand Island] $ LandSpec [])
True
ghci> island == (Card "Island" $ ElectCardFacet $ LandCharacteristic [] [BasicLand Mountain] $ LandSpec [])
False
ghci> mainDemoGameplay -- runs Demo.MtgPure.Gameplay

Notes:

  • Setting -Wno-type-defaults so the Show instances for cards don't need to constantly specify Num types when Integer is good enough for authoring. (Too much noise adding annotations for Integer or even Int or an alias I.)
  • src/MtgPure/Model/Object/ToObjectN/Instances.hs imports large generated files and will take a while to compile, hence the -fobject-code flag to cache the result inside the ghci-compiled.bat script.
  • Using -fobject-code with ghci seems to require quitting and reentering ghci in order to get it to pick up the right runtime behavior after making code changes.

Screenshots:

Demo.MtgPure.Gameplay

vlc-record-2023-02-21-17h22m25s-2023-02-21.17-05-23.mkv-.mp4

App.AnsiInspector App.AnsiInspector

Contributors:

Contributions may or may not be accepted. If you are concerned about your time being wasted, please open an issue first to discuss. Entry-level contributions would probably be for card definitions or tests. More advanced contributions would be for the engine or model design.


Low priority:

  • AI
  • GUI

Will not fix issues related to:

  • Handling of integer overflow. I don't want to use unbounded integer types, and I'm okay with deviating from official MTG rules here.

Haskell language options:

  • Safe (For the model and rules engine. UI and other stuff needs to interface with Unsafe libraries.)
  • NoIncoherentInstances
  • NoOverlappingInstances (todo: write a script that generates non-overlapping ToManaCost/ToManaPool instances needed to achieve this)
  • NoTemplateHaskell
  • NoUndecidableInstances

About

Purely functional Haskell "Magic: The Gathering" card model and game engine.

Topics

Resources

License

Stars

Watchers

Forks

Packages

No packages published