Page 1 of 1

I'm Insane: An auto-coding tool

PostPosted: 08 May 2015, 19:57
by Xander9009
I've had an idea for a long time of a tool like thefiremind's generators, but more powerful. I wanted it to be able to parse abilities that are relatively simple, but too complex for the generators.

I've started work on it, and it's actually coming along very nicely. It's being written in AutoHotKey, because what I'm most comfortable in. It's not the most powerful language for a tool like this, and I should probably write it in Python or something. But, I decided to just jump into it, and that means using what I know.

It can currently handle life gain, life loss, card drawing, targeting (single targets only), and destruction. It can build a simple filter that only consists of card types, subtypes, supertypes, and permanent (or any of those prefixed with "non"). It can also handle any number of those together. So, "noncreature permanent" results in the filter you'd expect.

Determines everything about the ability from the text alone, meaning from the user's point of view, the only thing they do is tell it the ability text and card name, and it'll produce the code to do so.

Run the program with the parameters "Destroy target nonbasic land." "Some Card Name", and the clipboard will be set to the following (note that "Some Card Name" is there because it requires the name of the card being processed in case the ability itself has the card name in reference to itself):
Code: Select all
<SPELL_ABILITY>
<TARGET tag="CARD_QUERY_CHOOSE_CREATURE_TO_DESTROY" definition="0" compartment="0" count="1" />
<TARGET_DEFINITION id="0">
local filter = ClearFilter()
filter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE)
</TARGET_DEFINITION>
<RESOLUTION_TIME_ACTION>
local target = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
if target ~= nil then
target:Destroy()
end
</RESOLUTION_TIME_ACTION>
</SPELL_ABILITY>
(I have another utility which can be used after the card is saved to indent everything properly.)
It can't handle more the one target, though. And it doesn't yet handle AI_SIMPLIFIED_TARGETING tags. But it's more versatile than I expected it to be after just a few hours of works.

Just for testing, I tried out "Destroy target nonlegendary creature. Draw a cards. Lose 2 life." and got the following (which I manually indented, but otherwise didn't change).
Code: Select all
<SPELL_ABILITY>
   <TARGET tag="CARD_QUERY_CHOOSE_NONLEGENDARY_CREATURE_TO_DESTROY" definition="0" compartment="0" count="1" />
   <TARGET_DEFINITION id="0">
      local filter = ClearFilter()
      filter:Add( FE_SUPERTYPE, OP_NOT, SUPERTYPE_LEGENDARY)
      filter:Add( FE_TYPE, OP_IS, CARD_TYPE_CREATURE)
   </TARGET_DEFINITION>
   <RESOLUTION_TIME_ACTION>
      local target = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)
      if target ~= nil then
         target:Destroy()
      end
   </RESOLUTION_TIME_ACTION>
</SPELL_ABILITY>

<SPELL_ABILITY>
   <RESOLUTION_TIME_ACTION>
      EffectController():DrawCards(1)
   </RESOLUTION_TIME_ACTION>
</SPELL_ABILITY>

<SPELL_ABILITY>
   <RESOLUTION_TIME_ACTION>
      EffectController():LoseLife(2)
   </RESOLUTION_TIME_ACTION>
</SPELL_ABILITY>
Obviously, I'll have to make it keeps abilities in the same ability block where possible, but I'm rather pleased with it. I don't imagine it'll ever be able to handle anything complicated, but I should be able to manage to get it to handle: performing an action on multiple targets (Downpour), resolutions separated by 'and' (Night's Whisper), tapping, bouncing, exiling, scrying, typical mana abilities (not ones with strange effects, but Abzan Banner should be doable), cloning, creating tokens, damaging, sacrificing, discarding, milling, regeneration/regen prevention, possibly granting simple abilities, and probably most of the filtering functions. That's the goal, at least. Just to see how much can be done without anyone having to manually code them. (Also, because of the way I'm using the clipboard to temporarily store the output and because I'll eventually add an optional save to file function, it should be usable from just about any language, so it can be easily tied into TFM's Card Generator.)

Current code | Open
Code: Select all
FileEncoding, UTF-8

Parameters = %0%
If ( Parameters = 2 )
{
   AbilityText = %1%
   CardName = %2%
} Else If ( Parameters = 0 )
{
   AbilityText := "Draw two cards."
   CardName := "Divination"
} Else
{
   MsgBox, Invalid number of parameters. Expected 2 parameters.`n1: "%1%"`n2: "%2%"
   ExitApp
}

AbilityList := Object()
SubjectList := Object()
VerbList := Object()
ObjectList := Object()
DetailsList := Object()

SubjectDictionary := Object()
SubjectDictionary.Insert("you", "EffectController()")
SubjectDictionary.Insert("owner", "GetOwner()")
SubjectDictionary.Insert("CARDNAME", "EffectSource()")

VerbDictionary := Object()
VerbDictionary.Insert("draw", "draw")
VerbDictionary.Insert("draws", "draw")
VerbDictionary.Insert("life", "life")
VerbDictionary.Insert("destroy", "destroy")
VerbDictionary.Insert("discard", "discard")
VerbDictionary.Insert("discards", "discard")

ObjectDictionary := Object()
ObjectDictionary.Insert("you", "EffectController()")
ObjectDictionary.Insert("card", "card")
ObjectDictionary.Insert("cards", "card")
ObjectDictionary.Insert("target", "target")

DetailsDictionary := Object()
DetailsDictionary.Insert("gain", "gain")
DetailsDictionary.Insert("gains", "gain")
DetailsDictionary.Insert("lose", "lose")
DetailsDictionary.Insert("loses", "lose")

ResolutionVerbs := Object()
ResolutionVerbs.Insert("draw", 1)
ResolutionVerbs.Insert("destroy", 2)
ResolutionVerbs.Insert("discard", 3)
ResolutionVerbs.Insert("life", 3)

FE_Misc := Object()
FE_Misc.Insert("permanent", "FE_IS_PERMANENT, true")
FE_Misc.Insert("nonpermanent", "FE_IS_PERMANENT, false")

FE_Type := Object()
FE_Type.Insert("artifact", "CARD_TYPE_ARTIFACT")
FE_Type.Insert("creature", "CARD_TYPE_CREATURE")
FE_Type.Insert("enchantment", "CARD_TYPE_ENCHANTMENT")
FE_Type.Insert("instant", "CARD_TYPE_INSTANT")
FE_Type.Insert("land", "CARD_TYPE_LAND")
FE_Type.Insert("plane", "CARD_TYPE_PLANE")
FE_Type.Insert("planeswalker", "CARD_TYPE_PLANESWALKER")
FE_Type.Insert("sorcery", "CARD_TYPE_SORCERY")
FE_Type.Insert("scheme", "CARD_TYPE_SCHEME")
FE_Type.Insert("tribal", "CARD_TYPE_TRIBAL")

FE_SuperType := Object()
FE_SuperType.Insert("basic", "SUPERTYPE_BASIC")
FE_SuperType.Insert("legendary", "SUPERTYPE_LEGENDARY")
FE_SuperType.Insert("world", "SUPERTYPE_WORLD")
FE_SuperType.Insert("snow", "SUPERTYPE_SNOW")
FE_SuperType.Insert("ongoing", "SUPERTYPE_ONGOING")

FE_SubType := Object()
FE_SubType.Insert("contraption", "ARTIFACT_TYPE_CONTRAPTION")
FE_SubType.Insert("equipment", "ARTIFACT_TYPE_EQUIPMENT")
FE_SubType.Insert("fortification", "ARTIFACT_TYPE_FORTIFICATION")
FE_SubType.Insert("aura", "ENCHANTMENT_TYPE_AURA")
FE_SubType.Insert("shrine", "ENCHANTMENT_TYPE_SHRINE")
FE_SubType.Insert("curse", "ENCHANTMENT_TYPE_CURSE")
FE_SubType.Insert("desert", "LAND_TYPE_DESERT")
FE_SubType.Insert("forest", "LAND_TYPE_FOREST")
FE_SubType.Insert("island", "LAND_TYPE_ISLAND")
FE_SubType.Insert("lair", "LAND_TYPE_LAIR")
FE_SubType.Insert("locus", "LAND_TYPE_LOCUS")
FE_SubType.Insert("mine", "LAND_TYPE_MINE")
FE_SubType.Insert("mountain", "LAND_TYPE_MOUNTAIN")
FE_SubType.Insert("plains", "LAND_TYPE_PLAINS")
FE_SubType.Insert("swamp", "LAND_TYPE_SWAMP")
FE_SubType.Insert("tower", "LAND_TYPE_TOWER")
FE_SubType.Insert("urzas", "LAND_TYPE_URZAS")
FE_SubType.Insert("human", "CREATURE_TYPE_HUMAN")
FE_SubType.Insert("advisor", "CREATURE_TYPE_ADVISOR")
FE_SubType.Insert("anemone", "CREATURE_TYPE_ANEMONE")
FE_SubType.Insert("angel", "CREATURE_TYPE_ANGEL")
FE_SubType.Insert("anteater", "CREATURE_TYPE_ANTEATER")
FE_SubType.Insert("antelope", "CREATURE_TYPE_ANTELOPE")
FE_SubType.Insert("ape", "CREATURE_TYPE_APE")
FE_SubType.Insert("archer", "CREATURE_TYPE_ARCHER")
FE_SubType.Insert("archon", "CREATURE_TYPE_ARCHON")
FE_SubType.Insert("artificer", "CREATURE_TYPE_ARTIFICER")
FE_SubType.Insert("assassin", "CREATURE_TYPE_ASSASSIN")
FE_SubType.Insert("atog", "CREATURE_TYPE_ATOG")
FE_SubType.Insert("aurochs", "CREATURE_TYPE_AUROCHS")
FE_SubType.Insert("avatar", "CREATURE_TYPE_AVATAR")
FE_SubType.Insert("badger", "CREATURE_TYPE_BADGER")
FE_SubType.Insert("barbarian", "CREATURE_TYPE_BARBARIAN")
FE_SubType.Insert("basilisk", "CREATURE_TYPE_BASILISK")
FE_SubType.Insert("bat", "CREATURE_TYPE_BAT")
FE_SubType.Insert("bear", "CREATURE_TYPE_BEAR")
FE_SubType.Insert("beast", "CREATURE_TYPE_BEAST")
FE_SubType.Insert("beeble", "CREATURE_TYPE_BEEBLE")
FE_SubType.Insert("berserker", "CREATURE_TYPE_BERSERKER")
FE_SubType.Insert("bird", "CREATURE_TYPE_BIRD")
FE_SubType.Insert("blinkmoth", "CREATURE_TYPE_BLINKMOTH")
FE_SubType.Insert("boar", "CREATURE_TYPE_BOAR")
FE_SubType.Insert("bringer", "CREATURE_TYPE_BRINGER")
FE_SubType.Insert("brushwagg", "CREATURE_TYPE_BRUSHWAGG")
FE_SubType.Insert("camarid", "CREATURE_TYPE_CAMARID")
FE_SubType.Insert("camel", "CREATURE_TYPE_CAMEL")
FE_SubType.Insert("caribou", "CREATURE_TYPE_CARIBOU")
FE_SubType.Insert("carrier", "CREATURE_TYPE_CARRIER")
FE_SubType.Insert("cat", "CREATURE_TYPE_CAT")
FE_SubType.Insert("centaur", "CREATURE_TYPE_CENTAUR")
FE_SubType.Insert("cephalid", "CREATURE_TYPE_CEPHALID")
FE_SubType.Insert("chimera", "CREATURE_TYPE_CHIMERA")
FE_SubType.Insert("citizen", "CREATURE_TYPE_CITIZEN")
FE_SubType.Insert("cleric", "CREATURE_TYPE_CLERIC")
FE_SubType.Insert("cockatrice", "CREATURE_TYPE_COCKATRICE")
FE_SubType.Insert("construct", "CREATURE_TYPE_CONSTRUCT")
FE_SubType.Insert("coward", "CREATURE_TYPE_COWARD")
FE_SubType.Insert("crab", "CREATURE_TYPE_CRAB")
FE_SubType.Insert("crocodile", "CREATURE_TYPE_CROCODILE")
FE_SubType.Insert("cyclops", "CREATURE_TYPE_CYCLOPS")
FE_SubType.Insert("dauthi", "CREATURE_TYPE_DAUTHI")
FE_SubType.Insert("demon", "CREATURE_TYPE_DEMON")
FE_SubType.Insert("deserter", "CREATURE_TYPE_DESERTER")
FE_SubType.Insert("devil", "CREATURE_TYPE_DEVIL")
FE_SubType.Insert("djinn", "CREATURE_TYPE_DJINN")
FE_SubType.Insert("dragon", "CREATURE_TYPE_DRAGON")
FE_SubType.Insert("drake", "CREATURE_TYPE_DRAKE")
FE_SubType.Insert("dreadnought", "CREATURE_TYPE_DREADNOUGHT")
FE_SubType.Insert("drone", "CREATURE_TYPE_DRONE")
FE_SubType.Insert("druid", "CREATURE_TYPE_DRUID")
FE_SubType.Insert("dryad", "CREATURE_TYPE_DRYAD")
FE_SubType.Insert("dwarf", "CREATURE_TYPE_DWARF")
FE_SubType.Insert("efreet", "CREATURE_TYPE_EFREET")
FE_SubType.Insert("egg", "CREATURE_TYPE_EGG")
FE_SubType.Insert("elder", "CREATURE_TYPE_ELDER")
FE_SubType.Insert("elemental", "CREATURE_TYPE_ELEMENTAL")
FE_SubType.Insert("elephant", "CREATURE_TYPE_ELEPHANT")
FE_SubType.Insert("elf", "CREATURE_TYPE_ELF")
FE_SubType.Insert("elk", "CREATURE_TYPE_ELK")
FE_SubType.Insert("eye", "CREATURE_TYPE_EYE")
FE_SubType.Insert("faerie", "CREATURE_TYPE_FAERIE")
FE_SubType.Insert("ferret", "CREATURE_TYPE_FERRET")
FE_SubType.Insert("fish", "CREATURE_TYPE_FISH")
FE_SubType.Insert("flagbearer", "CREATURE_TYPE_FLAGBEARER")
FE_SubType.Insert("fox", "CREATURE_TYPE_FOX")
FE_SubType.Insert("frog", "CREATURE_TYPE_FROG")
FE_SubType.Insert("fungus", "CREATURE_TYPE_FUNGUS")
FE_SubType.Insert("gargoyle", "CREATURE_TYPE_GARGOYLE")
FE_SubType.Insert("giant", "CREATURE_TYPE_GIANT")
FE_SubType.Insert("gnome", "CREATURE_TYPE_GNOME")
FE_SubType.Insert("goat", "CREATURE_TYPE_GOAT")
FE_SubType.Insert("goblin", "CREATURE_TYPE_GOBLIN")
FE_SubType.Insert("golem", "CREATURE_TYPE_GOLEM")
FE_SubType.Insert("gorgon", "CREATURE_TYPE_GORGON")
FE_SubType.Insert("graveborn", "CREATURE_TYPE_GRAVEBORN")
FE_SubType.Insert("gremlin", "CREATURE_TYPE_GREMLIN")
FE_SubType.Insert("griffin", "CREATURE_TYPE_GRIFFIN")
FE_SubType.Insert("hag", "CREATURE_TYPE_HAG")
FE_SubType.Insert("harpy", "CREATURE_TYPE_HARPY")
FE_SubType.Insert("hellion", "CREATURE_TYPE_HELLION")
FE_SubType.Insert("hippo", "CREATURE_TYPE_HIPPO")
FE_SubType.Insert("homarid", "CREATURE_TYPE_HOMARID")
FE_SubType.Insert("homunculus", "CREATURE_TYPE_HOMUNCULUS")
FE_SubType.Insert("horror", "CREATURE_TYPE_HORROR")
FE_SubType.Insert("horse", "CREATURE_TYPE_HORSE")
FE_SubType.Insert("hound", "CREATURE_TYPE_HOUND")
FE_SubType.Insert("hydra", "CREATURE_TYPE_HYDRA")
FE_SubType.Insert("illusion", "CREATURE_TYPE_ILLUSION")
FE_SubType.Insert("imp", "CREATURE_TYPE_")
FE_SubType.Insert("incarnation", "CREATURE_TYPE_INCARNATION")
FE_SubType.Insert("insect", "CREATURE_TYPE_INSECT")
FE_SubType.Insert("jellyfish", "CREATURE_TYPE_JELLYFISH")
FE_SubType.Insert("juggernaut", "CREATURE_TYPE_JUGGERNAUT")
FE_SubType.Insert("kavu", "CREATURE_TYPE_KAVU")
FE_SubType.Insert("kirin", "CREATURE_TYPE_KIRIN")
FE_SubType.Insert("kithkin", "CREATURE_TYPE_KITHKIN")
FE_SubType.Insert("knight", "CREATURE_TYPE_KNIGHT")
FE_SubType.Insert("kobold", "CREATURE_TYPE_KOBOLD")
FE_SubType.Insert("kor", "CREATURE_TYPE_KOR")
FE_SubType.Insert("kraken", "CREATURE_TYPE_KRAKEN")
FE_SubType.Insert("lammasu", "CREATURE_TYPE_LAMMASU")
FE_SubType.Insert("leech", "CREATURE_TYPE_LEECH")
FE_SubType.Insert("leviathan", "CREATURE_TYPE_LEVIATHAN")
FE_SubType.Insert("lhurgoyf", "CREATURE_TYPE_LHURGOYF")
FE_SubType.Insert("licid", "CREATURE_TYPE_LICID")
FE_SubType.Insert("lizard", "CREATURE_TYPE_LIZARD")
FE_SubType.Insert("manticore", "CREATURE_TYPE_MANTICORE")
FE_SubType.Insert("masticore", "CREATURE_TYPE_MASTICORE")
FE_SubType.Insert("mercenary", "CREATURE_TYPE_MERCENARY")
FE_SubType.Insert("merfolk", "CREATURE_TYPE_MERFOLK")
FE_SubType.Insert("metathran", "CREATURE_TYPE_METATHRAN")
FE_SubType.Insert("minion", "CREATURE_TYPE_MINION")
FE_SubType.Insert("minotaur", "CREATURE_TYPE_MINOTAUR")
FE_SubType.Insert("monger", "CREATURE_TYPE_MONGER")
FE_SubType.Insert("mongoose", "CREATURE_TYPE_MONGOOSE")
FE_SubType.Insert("monk", "CREATURE_TYPE_MONK")
FE_SubType.Insert("moonfolk", "CREATURE_TYPE_MOONFOLK")
FE_SubType.Insert("mutant", "CREATURE_TYPE_MUTANT")
FE_SubType.Insert("myr", "CREATURE_TYPE_MYR")
FE_SubType.Insert("mystic", "CREATURE_TYPE_MYSTIC")
FE_SubType.Insert("nautilus", "CREATURE_TYPE_NAUTILUS")
FE_SubType.Insert("nephilim", "CREATURE_TYPE_NEPHILIM")
FE_SubType.Insert("nightmare", "CREATURE_TYPE_NIGHTMARE")
FE_SubType.Insert("nightstalker", "CREATURE_TYPE_NIGHTSTALKER")
FE_SubType.Insert("ninja", "CREATURE_TYPE_NINJA")
FE_SubType.Insert("nomad", "CREATURE_TYPE_NOMAD")
FE_SubType.Insert("octopus", "CREATURE_TYPE_OCTOPUS")
FE_SubType.Insert("ogre", "CREATURE_TYPE_OGRE")
FE_SubType.Insert("ooze", "CREATURE_TYPE_OOZE")
FE_SubType.Insert("orb", "CREATURE_TYPE_ORB")
FE_SubType.Insert("orc", "CREATURE_TYPE_ORC")
FE_SubType.Insert("orgg", "CREATURE_TYPE_ORGG")
FE_SubType.Insert("ouphe", "CREATURE_TYPE_OUPHE")
FE_SubType.Insert("ox", "CREATURE_TYPE_OX")
FE_SubType.Insert("oyster", "CREATURE_TYPE_OYSTER")
FE_SubType.Insert("pegasus", "CREATURE_TYPE_PEGASUS")
FE_SubType.Insert("pentavite", "CREATURE_TYPE_PENTAVITE")
FE_SubType.Insert("pest", "CREATURE_TYPE_PEST")
FE_SubType.Insert("phelddagrif", "CREATURE_TYPE_PHELDDAGRIF")
FE_SubType.Insert("phoenix", "CREATURE_TYPE_PHOENIX")
FE_SubType.Insert("pincher", "CREATURE_TYPE_PINCHER")
FE_SubType.Insert("pirate", "CREATURE_TYPE_PIRATE")
FE_SubType.Insert("plant", "CREATURE_TYPE_PLANT")
FE_SubType.Insert("prism", "CREATURE_TYPE_PRISM")
FE_SubType.Insert("rabbit", "CREATURE_TYPE_RABBIT")
FE_SubType.Insert("rat", "CREATURE_TYPE_RAT")
FE_SubType.Insert("rebel", "CREATURE_TYPE_REBEL")
FE_SubType.Insert("reflection", "CREATURE_TYPE_REFLECTION")
FE_SubType.Insert("rhino", "CREATURE_TYPE_RHINO")
FE_SubType.Insert("rigger", "CREATURE_TYPE_RIGGER")
FE_SubType.Insert("rogue", "CREATURE_TYPE_ROGUE")
FE_SubType.Insert("salamander", "CREATURE_TYPE_SALAMANDER")
FE_SubType.Insert("samurai", "CREATURE_TYPE_SAMURAI")
FE_SubType.Insert("sand", "CREATURE_TYPE_SAND")
FE_SubType.Insert("saproling", "CREATURE_TYPE_SAPROLING")
FE_SubType.Insert("satyr", "CREATURE_TYPE_SATYR")
FE_SubType.Insert("scarecrow", "CREATURE_TYPE_SCARECROW")
FE_SubType.Insert("scorpion", "CREATURE_TYPE_SCORPION")
FE_SubType.Insert("scout", "CREATURE_TYPE_SCOUT")
FE_SubType.Insert("serf", "CREATURE_TYPE_SERF")
FE_SubType.Insert("serpent", "CREATURE_TYPE_SERPENT")
FE_SubType.Insert("shade", "CREATURE_TYPE_SHADE")
FE_SubType.Insert("shaman", "CREATURE_TYPE_SHAMAN")
FE_SubType.Insert("shapeshifter", "CREATURE_TYPE_SHAPESHIFTER")
FE_SubType.Insert("sheep", "CREATURE_TYPE_SHEEP")
FE_SubType.Insert("skeleton", "CREATURE_TYPE_SKELETON")
FE_SubType.Insert("slith", "CREATURE_TYPE_SLITH")
FE_SubType.Insert("sliver", "CREATURE_TYPE_SLIVER")
FE_SubType.Insert("slug", "CREATURE_TYPE_SLUG")
FE_SubType.Insert("snake", "CREATURE_TYPE_SNAKE")
FE_SubType.Insert("soldier", "CREATURE_TYPE_SOLDIER")
FE_SubType.Insert("soltari", "CREATURE_TYPE_SOLTARI")
FE_SubType.Insert("spawn", "CREATURE_TYPE_SPAWN")
FE_SubType.Insert("specter", "CREATURE_TYPE_SPECTER")
FE_SubType.Insert("spellshaper", "CREATURE_TYPE_SPELLSHAPER")
FE_SubType.Insert("sphinx", "CREATURE_TYPE_SPHINX")
FE_SubType.Insert("spider", "CREATURE_TYPE_SPIDER")
FE_SubType.Insert("spike", "CREATURE_TYPE_SPIKE")
FE_SubType.Insert("spirit", "CREATURE_TYPE_")
FE_SubType.Insert("splinter", "CREATURE_TYPE_SPLINTER")
FE_SubType.Insert("sponge", "CREATURE_TYPE_SPONGE")
FE_SubType.Insert("squid", "CREATURE_TYPE_SQUID")
FE_SubType.Insert("squirrel", "CREATURE_TYPE_SQUIRREL")
FE_SubType.Insert("starfish", "CREATURE_TYPE_STARFISH")
FE_SubType.Insert("survivor", "CREATURE_TYPE_SURVIVOR")
FE_SubType.Insert("tetravite", "CREATURE_TYPE_TETRAVITE")
FE_SubType.Insert("thalakos", "CREATURE_TYPE_THALAKOS")
FE_SubType.Insert("thopter", "CREATURE_TYPE_THOPTER")
FE_SubType.Insert("thrull", "CREATURE_TYPE_THRULL")
FE_SubType.Insert("treefolk", "CREATURE_TYPE_TREEFOLK")
FE_SubType.Insert("triskelavite", "CREATURE_TYPE_TRISKELAVITE")
FE_SubType.Insert("troll", "CREATURE_TYPE_TROLL")
FE_SubType.Insert("turtle", "CREATURE_TYPE_TURTLE")
FE_SubType.Insert("unicorn", "CREATURE_TYPE_UNICORN")
FE_SubType.Insert("vampire", "CREATURE_TYPE_VAMPIRE")
FE_SubType.Insert("vedalken", "CREATURE_TYPE_VEDALKEN")
FE_SubType.Insert("viashino", "CREATURE_TYPE_VIASHINO")
FE_SubType.Insert("volver", "CREATURE_TYPE_VOLVER")
FE_SubType.Insert("wall", "CREATURE_TYPE_WALL")
FE_SubType.Insert("warrior", "CREATURE_TYPE_WARRIOR")
FE_SubType.Insert("weird", "CREATURE_TYPE_WEIRD")
FE_SubType.Insert("whale", "CREATURE_TYPE_WHALE")
FE_SubType.Insert("wizard", "CREATURE_TYPE_WIZARD")
FE_SubType.Insert("wolf", "CREATURE_TYPE_WOLF")
FE_SubType.Insert("wolverine", "CREATURE_TYPE_WOLVERINE")
FE_SubType.Insert("wombat", "CREATURE_TYPE_WOMBAT")
FE_SubType.Insert("worm", "CREATURE_TYPE_WORM")
FE_SubType.Insert("wraith", "CREATURE_TYPE_WRAITH")
FE_SubType.Insert("wurm", "CREATURE_TYPE_WURM")
FE_SubType.Insert("yeti", "CREATURE_TYPE_YETI")
FE_SubType.Insert("zombie", "CREATURE_TYPE_ZOMBIE")
FE_SubType.Insert("zubera", "CREATURE_TYPE_ZUBERA")
FE_SubType.Insert("ally", "CREATURE_TYPE_ALLY")
FE_SubType.Insert("trap", "CREATURE_TYPE_TRAP")
FE_SubType.Insert("eldrazi", "CREATURE_TYPE_ELDRAZI")
FE_SubType.Insert("praetor", "CREATURE_TYPE_PRAETOR")
FE_SubType.Insert("werewolf", "CREATURE_TYPE_WEREWOLF")

StringReplace, AbilityText, AbilityText, %CardName%, CARDNAME, ALL

CurrentIndex := 0
Actions := 0

Loop, Parse, AbilityText, .
{
   CurrentIndex += 1
   AbilityList[CurrentIndex] := A_LoopField
   Loop, Parse, A_LoopField, %A_Space%
   {
      StringLower, LoopField, A_LoopField
      If ( SubjectList[CurrentIndex] = "" )
      {
         If SubjectDicationary.HasKey(LoopField)
         {
            SubjectList[CurrentIndex] = SubjectDictionary[LoopField]
            Continue
         }
      }
      If ( VerbDictionary.HasKey(LoopField) )
      {
         VerbList[CurrentIndex] := VerbDictionary[LoopField]
         Actions += 1
         Continue
      } Else If ( ObjectDictionary.HasKey(LoopField) )
      {
         ObjectList[CurrentIndex] := ObjectDictionary[LoopField]
         Continue
      } Else If ( DetailsDictionary.HasKey(LoopField) or DetailsDictionary.HasKey(SubStr(LoopField, 4, StrLen(LoopField)-3)) or FE_Type.HasKey(LoopField) or FE_Type.HasKey(SubStr(LoopField, 4, StrLen(LoopField)-3)) or FE_SubType.HasKey(LoopField) or FE_SubType.HasKey(SubStr(LoopField, 4, StrLen(LoopField)-3)) or FE_SuperType.HasKey(LoopField) or FE_SuperType.HasKey(SubStr(LoopField, 4, StrLen(LoopField)-3)) or FE_Misc.HasKey(LoopField))
      {
         AddDetails(CurrentIndex, LoopField)
         Continue
      } Else If ToNumber(LoopField) is Number
      {
         AddDetails(CurrentIndex, ToNumber(LoopField))
         Continue
      }
   }
}
Index := 1
CurrentAbilityType := ""
CurrentActionType := ""
While ( Index <= Actions )
{
   ;MsgBox, %Index%/%Actions%
   Ability := AbilityList[Index]
   Subject := SubjectList[Index]
   Verb := VerbList[Index]
   Object := ObjectList[Index]
   Details := DetailsList[Index]
   Details1 := Details[1]
   Details2 := Details[2]
   ;MsgBox, Ability: %Ability%`nSubject: %Subject%`nVerb: %Verb%`nObject: %Object%`nDetails1: %Details1%`nDetails2: %Details2%
   Code := ""
   
   If ( Subject = "" )
   {
      Subject := "EffectController()"
   }
   Code .= OpenAbilityBlock(Ability) . "`n"
   Code .= PerformAction(Subject, Object, Verb, Details) . "`n"
   Code .= CloseAbilityBlock() . "`n"
   
   CodeFinal .= Code . "`n"
   Index += 1
}
OldClipboard := Clipboard
Clipboard := CodeFinal
While ( Clipboard = CodeFinal )
{
   Sleep, 1
}
Clipboard := OldClipboard
ExitApp

ToNumber(String)
{
   If String is Number
   {
      Return String
   } Else If ( String = "a" or String = "an" or String = "one" )
   {
      Return 1
   } Else If ( String = "two" )
   {
      Return 2
   } Else If ( String = "three" )
   {
      Return 3
   } Else If ( String = "four" )
   {
      Return 4
   } Else If ( String = "five" )
   {
      Return 5
   } Else If ( String = "six" )
   {
      Return 6
   } Else If ( String = "seven" )
   {
      Return 7
   } Else If ( String = "eight" )
   {
      Return 8
   } Else If ( String = "nine" )
   {
      Return 9
   } Else If ( String = "ten" )
   {
      Return 10
   } Else
   {
      Return NotANumber
   }
}

AddDetails(Index, Detail)
{
   Global
   If ( DetailsList[Index].MaxIndex() = "" )
   {
      DetailsList[Index] := Object()
   }
   DetailsList[Index].Insert(Detail)
}

OpenAbilityBlock(Ability)
{
   Global
   IfInString, Ability, :
   {
      CurrentAbilityType := "<ACTIVATED_ABILITY>"
      Return "<ACTIVATED_ABILITY>"
   } Else If ( SubStr(Ability, 1, 5) = "When " or SubStr(Ability, 1, 9) = "Whenever " or SubStr(Ability, 1, 3) = "If " or SubStr(Ability, 1, 3) = "At " )
   {
      CurrentAbilityType := "<TRIGGERED_ABILITY>"
      Return "<TRIGGERED_ABILITY>"
   } Else
   {
      CurrentAbilityType := "<SPELL_ABILITY>"
      Return "<SPELL_ABILITY>"
   }
}

CloseAbilityBlock()
{
   Global
   AbilityCloseTag := "</" . SubStr(CurrentAbilityType, 2, StrLen(CurrentAbilityType)-1)
   CurrentAbilityType = ""
   Return AbilityCloseTag
}

OpenActionBlock(Verb)
{
   Global
   If ( ResolutionVerbs.HasKey(Verb) )
   {
      CurrentActionType := "<RESOLUTION_TIME_ACTION>"
      Return "<RESOLUTION_TIME_ACTION>"
   } Else If ( ContinuousVerbs.HasKey(Verb) )
   {
      CurrentActionType := "<CONTINUOUS_ACTION>"
      Return "<CONTINUOUS_ACTION>"
   }
   CurrentActionType := ""
   Return ""
}

CloseActionBlock()
{
   Global
   ActionCloseTag := "</" . SubStr(CurrentActionType, 2, StrLen(CurrentActionType)-1)
   CurrentActionType = ""
   Return ActionCloseTag
}

HasValue(Object, Value)
{
   For Index, Element in Object
   {
      If ( Element = Value )
      {
         Return True
      }
   }
   Return False
}

If FE_Type.HasKey("creature")
{
   MsgBox, FE_Type has key: creature
}

FilterLookUp(Type)
{
   Global
   StringUpper, TypeUpper, Type
   If ( SubStr(Type, 1, 3) = "non" )
   {
      StringTrimLeft, Type, Type, 3
      Operator := "OP_NOT"
   } Else
   {
      Operator := "OP_IS"
   }
   If FE_Type.HasKey(Type)
   {
      Return "FE_TYPE, " . Operator . ", " . FE_Type[Type]
   } Else If FE_SubType.HasKey(Type)
   {
      Return "FE_SUBTYPE, " . Operator . ", " . FE_SubType[Type]
   } Else If FE_SuperType.HasKey(Type)
   {
      Return "FE_SUPERTYPE, " . Operator . ", " . FE_SuperType[Type]
   }   Else If FE_Misc.HasKey(Type)
   {
      Return FE_Misc[Type]
   }
   MsgBox, Not found
}

PerformAction(Subject, Object, Verb, Details)
{
   Global
   If ( Object = "target" )
   {
      LocalIndex := 1
      While ( LocalIndex <= Details.MaxIndex() )
      {
         DetailsTemp := Details[LocalIndex]
         StringUpper, TargetTypeTemp, DetailsTemp
         TargetType := TargetType = "" ? TargetTypeTemp : TargetType . "_" . TargetTypeTemp
         LocalIndex += 1
      }
      StringUpper, VerbUpper, Verb
      Code .= "<TARGET tag=""CARD_QUERY_CHOOSE_" . TargetType . "_TO_" . VerbUpper . """ definition=""0"" compartment=""0"" count=""1"" />`n"
      Code .= "<TARGET_DEFINITION id=""0"">`n"
      Code .= "local filter = ClearFilter()`n"
      LocalIndex := 1
      While ( LocalIndex <= Details.MaxIndex() )
      {
         Code .= "filter:Add( " . FilterLookUp(Details[LocalIndex]) . ")`n"
         LocalIndex += 1
      }
      Code .= "</TARGET_DEFINITION>`n"
      Code .= OpenActionBlock(Verb) . "`n"
      Code .= "local target = EffectDC():Get_Targets(0) and EffectDC():Get_Targets(0):Get_CardPtr(0)`n"
      Code .= "if target ~= nil then`n"
      OpenEnded += 1
   } Else
   {
      Code .= OpenActionBlock(Verb) . "`n"
   }
   If ( Verb = "destroy" )
   {
      Code .= Object . ":Destroy()`n"
   } Else If ( Verb = "draw" )
   {
      Code .= Subject . ":DrawCards(" . Details[1] . ")`n"
   } Else If ( Verb = "life" )
   {
      First := Details[1]
      Second := Details[2]
      If ( First = "gain" or Second = "gain" )
      {
         Function := "GainLife"
      } Else If ( First = "lose" or Second = "lose" )
      {
         Function := "LoseLife"
      }
      If First is Number
      {
         Amount := First
      } Else If Second is Number
      {
         Amount := Second
      }
      If ( ( Function = "GainLife" or Function = "LoseLife" ) and (Amount != "" ) )
      {
         Code .=  Subject . ":" . Function . "(" . Amount . ")`n"
      }
   }
   While ( OpenEnded > 0 )
   {
      Code .= "end`n"
      OpenEnded -= 1
   }
   Code .= CloseActionBlock()
}

Re: I'm Insane: An auto-coding tool

PostPosted: 08 May 2015, 23:00
by RiiakShiNal
Well, I'll state that you're less insane than I am. It is a sound idea, you acknowledge that you will likely hit an upper limit to what can be done, you found a project that you wanted to do (which will likely be appreciated by several members of the community), and you have already shared your source code (that based on your basic tests appears to be working). On the bonus side you started small.