-
Notifications
You must be signed in to change notification settings - Fork 102
Add keyword abilities for cards #285
Comments
Seems like a big change for what isn't a very general use case. In your program, couldn't you just use a smarter regex, such as |
Yea, I could probably do that. Another use case I thought of is if you want to search for cards with cheap abilities, but since it's not something I'm looking for right now, I'm fine closing this. |
Focusing in on the problem of providing static ability keywords. Take Akroma of Fury for example. "Begins with" matching will fail to catch her protection and trample abilities. This is possible to implement, but it can get tricky with the edge-cases. Basic logic...
I'm certain Wizards has a few quirky edge-cases that will show up when working on this code, but that's the basics to handle it. We should not include conditional keywords, as they are non-static and far less useful than quickly finding any thing with a given static keyword. For example, the provided Sedris example would not have any keyword abilities listed. As he does not statically have it, but he provides it to other cards conditionally. If you're trying to find cards that provide abilities to others, the filtering for pre-computed values is far more extreme and imo we shouldn't be tackling that just yet. |
Yea, I was thinking of that case this morning, where it's a list of static abilities. I think the solution @Garbee described might work. In the particular application I'm writing, I think I'm going to lean towards writing a function that returns the right set of abilities for each card, because I have a small set of them. In a larger app, that wouldn't be feasible unless they were in this data set, which is why I made this issue. I completely agree about the comment about conditional keywords. It would be much harder to compile that data, and not very useful. |
That data is actually extremely useful to provide users a search function to filter by cards that will provide the effect they are looking to make a combo out of. But, it's far lesser-done and due to the difference in language used card-to-card much harder to make a decision based on static analysis of the card text. |
Funny this should come up; I'm actually working on a project to tackle this problem. It's a ways off completion for now, but I'll figure it out eventually. For purely extracting static evergreen abilities, regex should work fine. However anything beyond those would be extraordinarily tricky with regex alone. |
I just got around to updating my app (which can be found here now, btw) to use @Garbee's method for abstracting the abilities from a card's text. Here's the resulting javascript code, with some test cases at the bottom: const ABILITIES = [
'Deathtouch', 'Defender', 'Double Strike', 'Enchant', 'Equip', 'First Strike', 'Flash', 'Flying', 'Haste', 'Hexproof', 'Indestructible', 'Lifelink', 'Menace', 'Prowess', 'Reach', 'Trample', 'Vigilance', 'Absorb', 'Affinity', 'Amplify', 'Annihilator', 'Aura Swap', 'Awaken', 'Banding', 'Battle Cry', 'Bestow', 'Bloodthirst', 'Bushido', 'Buyback', 'Cascade', 'Champion', 'Changeling', 'Cipher', 'Conspire', 'Convoke', 'Cumulative Upkeep', 'Cycling', 'Dash', 'Delve', 'Dethrone', 'Devoid', 'Devour', 'Dredge', 'Echo', 'Entwine', 'Epic', 'Evoke', 'Evolve', 'Exalted', 'Exploit', 'Extort', 'Fading', 'Fear', 'Flanking', 'Flashback', 'Forecast', 'Fortif', 'Frenzy', 'Fuse', 'Graft', 'Gravestorm', 'Haunt', 'Hidden Agenda', 'Hideaway', 'Horsemanship', 'Infect', 'Ingest', 'Intimidate', 'Kicker', 'Landhome', 'Landwalk', 'Level Up', 'Living Weapon', 'Madness', 'Megamorph', 'Miracle', 'Modular', 'Morph', 'Myriad', 'Ninjutsu', 'Offering', 'Outlast', 'Overload', 'Persist', 'Phasing', 'Poisonous', 'Protection', 'Provoke', 'Prowl', 'Rampage', 'Rebound', 'Recover', 'Reinforce', 'Renown', 'Replicate', 'Retrace', 'Ripple', 'Scavenge', 'Shadow', 'Shroud', 'Soulbond', 'Soulshift', 'Splice', 'Split Second', 'Storm', 'Substance', 'Sunburst', 'Surge', 'Suspend', 'Totem Armor', 'Transfigure', 'Transmute', 'Tribute', 'Undying', 'Unearth', 'Unleash', 'Vanishing', 'Wither'
]
function abilities(cardText) {
function cleanupAbility(text) {
return text.replace(/\(.*\)/, '') // Remove reminder text
.replace(/\{.*\}/, '') // Remove the cost
.trim() // Remove whitespace from start and end
}
const text = cardText;
const lines = text.split("\n")
const keywordLines = lines.filter((line) => {
const firstPossibleAbility = cleanupAbility(line.split(/,/)[0])
return ABILITIES.includes(firstPossibleAbility)
})
return keywordLines
.map((line) => line.split(/,(\{.+\})?\s?/))
.reduce( ( acc, cur ) => acc.concat(cur), [])
.map((rawAbilityText) => cleanupAbility(rawAbilityText));
}
abilities("First Strike")
abilities("Unearth, First Strike, Vigilance")
abilities("Vigilance, Trample")
abilities("Unearth")
abilities("{1}{B}: Regenerate target Zombie.\nMorph {2}{B} (You may cast this card face down as a 2/2 creature for {3}. Turn it face up any time for its morph cost.)")
abilities("Skeleton creatures you control and other Zombie creatures you control get +1/+1 and have deathtouch.")
abilities("When Rotting Rats enters the battlefield, each player discards a card.\nUnearth {1}{B} ({1}{B}: Return this card from your graveyard to the battlefield. It gains haste. Exile it at the beginning of the next end step or if it would leave the battlefield. Unearth only as a **sorcery.)")** A couple thoughts:
|
@dkniffin I like this code. A lot. I'll implement it in March, after I move. |
For whatever its worth, I am a newer player and don't know cards by name but I know what I might want to add to a deck. So I would look up Green Dinosaurs with Trample + Haste. |
Isn't that achievable by searching the card text for the most part? |
It would be, but it would be a better experience to include it as a possible search facet so that you can reflect matching card counts as you make other selections. |
No disagreement there :) |
If someone would like to reopen this to restart a discussion on V4, we can talk about it there. Otherwise, unfortunately I am closing this ticket |
It'd be nice if the json for each card included an array with the keyword abilities for the card. I'm writing a program that uses this data, and right now, there's no reliable way to determine if a card has a certain ability, other than using a regex against the card text, which isn't too reliable. For example, if I want to see if a card has Unearth, I'd have to do something like
/unearth/.test(cardText)
, but that would also match something like Sedris, the traitor kingI'm not sure how this data is compiled, but if it's manual, it might also be worth adding costs for the abilities at the same time. Something like this maybe?
(Edit: I changed the json example from Sedris to Rotting Rats. I meant to do that initially, because Rotting Rats has the actual static ability, whereas Sedris has a conditional ability.)
The text was updated successfully, but these errors were encountered: