/piece

An unofficial MTG Rules Engine

Primary LanguageRustApache License 2.0Apache-2.0

Piece

Piece is an unofficial rules engine for MTG. It is currently very much a work-in-progress with no AI.

Future plans:

  • A large number of cards supported.
  • An AI capable of making interesting matches.

Adding Cards

Editor

There is a barebones editor which can be used by running cargo run --release --bin editor

YAML

Cards are written in yaml format. You can see examples in the cards directory. The proto schema is defined in the protos directory. In particular, check out the card, effect, and restriction definitions for all of the fields available. See also the counter, and keyword implementations for their definitions. Some keywords work as-is, some need to be implemented as the appropriate ability/effect. In general, if the keyword's effects are always the same (i.e. neither the cost nor the effect vary e.g. Battle Cry, Cascade), specifying the keyword for the card is enough. If the keyword varies (e.g. cycling), then it must be implemented using effects - typically as an activated or triggered ability.

Text-to-enum conversions

  • Counters accepts the text +1/+1 and -1/-1 for P1P1 and M1M1 counters.
  • Enums accept any format of Title Case, UpperCamelCase, lower case, etc. The only thing to be careful of is types, where the typeline needs compound types to not be space-separated. E.g. PowerPlant needs to be in UpperCamelCase, snake_case, SCREAMING_SNAKE, etc. Otherwise it is ambiguous if the types are Power and Plant or just Power Plant.

Quirks to be aware of

  • Assume most effects are pulling targets from anywhere (battlefield, graveyard, exile, etc) and use restrictions to narrow down the target list appropriately.
  • Type, subtype, keyword, and color list fields must be written as a comma separated list of values. The parser automatically converts these to a list of the appropriate type. This means that you write:
    types: Artifact, Creature
    colors: Blue
    The same is true of mana gain abilities, which are written with the standard {W}, {U}, {B}, {R}, {G}, {C} notation for White, Blue, Black, Red, Green, and Colorless respectively:
    gain: !Specific
      # This is not comma separated, it's just a list of mana to gain.
      gain: '{W}{U}'
    gain: !Choice
      # This separates each choice with a comma
      choices: '{W}{U}, {U}{B}'
  • When adding restrictions, individual restrictions are AND'd together. So
    - restriction: !OfType
        types: Artifact
    - restriction: !OfType
        types: Creature
    will match anything that is both an artifact and a creature. This is different from subfields in restrictions, which are OR'd together. So
    - restriction: !OfType
        types: Artifact, Creature
    will matching anything that is either an artifact or a creature (or both).
  • The yaml tags are UpperCamelCase versions of the snake_case field names for oneofs in the proto definitions. E.g. battlefield_modifier is !BattlefieldModifier and modify_target is !ModifyTarget for the effect oneof field in the Effects proto.

Why Protos?

  • The author is familiar with their usage.
  • They provide a convenient one-stop location for the card schema.
  • They load very fast (less than 30ms for ~24k cards from a scryfall dump on the author's laptop).
    • The two-stage build process allows the binary proto files to be exported at build time, while allowing changes to the yaml & proto card definitions (including changing proto tag numbers - normally a nono).
  • Proto reflection allows a minimal editor to be built very easily.

Mana symbols are sourced from: https://github.com/andrewgioia/Mana