dovin: A proof assistant for Magic: The Gathering puzzles.

[ bsd3, games, library, program ] [ Propose Tags ]

Please see the README on GitHub at https://github.com/xaviershay/dovin#dovin


[Skip to Readme]
Versions [faq] 0.1.0.0, 0.1.0.1, 0.2
Dependencies base (>=4.7 && <5), containers, dovin, hashable, lens, mtl, parsec, split, unordered-containers [details]
License BSD-3-Clause
Copyright 2019 Xavier Shay
Author Xavier Shay
Maintainer contact@xaviershay.com
Category Games
Home page https://github.com/xaviershay/dovin#readme
Bug tracker https://github.com/xaviershay/dovin/issues
Source repo head: git clone https://github.com/xaviershay/dovin
Uploaded by xaviershay at Sun Jun 23 02:18:36 UTC 2019
Distributions NixOS:0.2
Executables mtgtc, dovin
Downloads 294 total (74 in the last 30 days)
Rating (no votes yet) [estimated by rule of succession]
Your Rating
  • λ
  • λ
  • λ
Status Hackage Matrix CI
Docs available [build log]
Last success reported on 2019-06-23 [all 1 reports]

Modules

[Index] [Quick Jump]

Downloads

Maintainer's Corner

For package maintainers and hackage trustees


Readme for dovin-0.2

[back to package description]

Dovin

A proof assistant for Possibility Storm-style Magic: The Gathering puzzles.

He has an innate talent, heightened by magic, that allows him to clearly see the flaws in any system or machine. After mere moments of scrutiny, Dovin can provide a complete analysis, noting a particular machine's weaknesses, highlighting its shortcomings, and predicting with startling accuracy exactly how and when it will fail. --- Dovin Baan, Planeswalker

It provides a haskell DSL for expressing Magic actions, with tracking of life and other counters and validation of pre- and post- conditions. For example, if you try to tap a permanent that is already tapped, it will error. Or if you try to target a creature with hexproof. It can also track state-based effects, such as "all creatures get +1/+1" or "other creatures gain hexproof".

It does not try to provide a full ruleset implementation, instead it's more akin to letting you lay out cards and counters in front of you and manipulate them as you would in a real game of paper magic.

I've only added actions "as needed" to solve problems, so the built-in functions are rather incomplete right now. It is straightforward to add more though. See src/Dovin/V2.hs in conjuction with src/Dovin/Actions.hs for supported and tested actions, and src/Dovin/Dump.hs for untested experimental ones.

Example

module Solutions.Example where

import Dovin

main = run formatter solution

solution :: GameMonad ()
solution = do
  step "Initial state" $ do
    setLife Opponent 3

    withLocation Hand $ addInstant "Plummet"
    withLocation Play $ do
      addLands 2 "Forest"

    as Opponent $ do
      withLocation Play $ do
        withAttributes [flying, token] $ addCreature (4, 4) "Angel"
        withAttributes [flying]
          $ withEffect
              matchInPlay
              (matchOtherCreatures <> (const $ matchAttribute creature))
              (pure . setAttribute hexproof)
          $ addCreature (3, 4) "Shalai, Voice of Plenty"

  step "Plummet to destroy Shalai" $ do
    tapForMana "G" (numbered 1 "Forest")
    tapForMana "G" (numbered 2 "Forest")
    cast "1G" "Plummet"
    resolve "Plummet"
    with "Shalai, Voice of Plenty" $ \enemy -> do
      target enemy
      validate (matchAttribute flying) enemy
      destroy enemy

formatter :: Step -> Formatter
formatter step = case view stepNumber step of
  1 -> manaFormatter
    <> cardFormatter "opponent creatures" (matchLocation (Opponent, Play))
  _ -> boardFormatter

manaFormatter = attributeFormatter $ do
  attribute "availble mana" $
    countCards (matchAttribute land <> missingAttribute tapped)

run uses the supplied formatter to print out the board state at each step:

1. Initial state
      (Active,Hand):
        Plummet (instant)
      (Active,Play):
        Forest 1 (land)
        Forest 2 (land)
      (Opponent,Play):
        Angel (creature,flying,hexproof,token) (4/4, 0)
        Shalai, Voice of Plenty (creature,flying) (3/4, 0)
2. Plummet to destroy Shalai
      availble mana: 0
      opponent creatures:
        Angel (creature,flying,token) (4/4, 0)

Solutions Index

See src/Solutions for more extensive usage (spoiler alert: these are solutions for published Possibility Storm puzzles!)

  • Dominaria5 uses a planeswalker.
  • RivalsOfIxalan7 uses withEffect to model exert effects, and shows how to verify multiple blocking scenarios.
  • Core19_9 has a fancy formatter to correctly track how much mana is available when working with Powerstone Shard, as well as spell tracking for Aetherflux Reservoir.
  • GuildsOfRavnicaPre2 uses forCards to model undergrowth for a Rhizome Lurcher.
  • GuildsOfRavnica1 uses mentor.
  • GuildsOfRavnica3 uses a sacrifice wrapper to repeatedly create treasure tokens.
  • GuildsOfRavnica8 shows using counters to correctly track Muldrotha, the Gravetide usage.
  • GuildsOfRavnica9 handles storm.
  • ExplorersOfIxalanContest handles some pretty weird damage interactions.
  • UltimateMasters shows how to track opponent actions.
  • ChannelFireball automatically calculates High Tide mana.
  • WarOfTheSpark2 shows off a hack for effects that depend on attributes of other cards (hopefully will have a better fix in API soon!)

Development

bin/dev  # Launch an interactive REPL
bin/test # Runs all tests and lints
bin/run  # Runs all solutions

src/Dovin/Dump.hs is currently a dumping ground for prototype code. Actions are in the process of being moved to Dovin.Actions. To be moved they must:

  • Be unit tested.
  • Be documented.
  • The primary target card of an action should be the final parameter.