The best kittens, technology, and video games blog in the world.

Showing posts with label magic the gathering. Show all posts
Showing posts with label magic the gathering. Show all posts

Monday, May 28, 2018

Preconstructed Magic Decks on mtg.wtf

2018-05-28-13 by RobynAnderson from flickr (CC-NC-ND)

There's now a number of search engines for Magic cards, but some information is still missing from them all.

I just fixed one of such areas. mtg.wtf now has searchable contents of all preconstructed decks ever released. They contain cards from correct set, so viewing a decklist like this you can see actual cards which are in the deck. Every other decklist visualizer I've ever seen just gives you the most recent scans (like this for example), which looks really weird, especially for older decks.

You can view the decks, download decklists, or mix deck queries with other queries. For example to see which cards from Feline Ferocity are Modern-legal, just use deck:"Feline Ferocity" f:modern.

All this information is available in simple machine readable format.

Raw data is in magic-preconstructed-decks, and compiled jsons are in magic-search-engine repository.

Future enhancements

There's still room for improvement - information which cards are foil is missing, but easy to add. In theory it should be possible to find exact card printing instead of just set it's from (how many copies of which basic land etc.), in practice it might be a bit too much work.

Decklist visualizer could get extra features like sample hand, mana curve statistics etc.

And inevitably like with every project, there's going to be some errors. If you find any, please report them on github.

Friday, October 28, 2016

Review of scryfall - mtg.wtf competitor

♥  My Girl ♥ by Trish Hamme from flickr (CC-BY)

After magiccards.info got borderline abandoned, I wrote mtg.wtf as a much better search engine for Magic cards.

There have been a few other attempts by other people, but they generally had extremely simple search functionality, so nothing worth writing about. A few days ago a new site came out - scryfall - which is at least seriously trying to support MCI-style syntax, so let's take a look.

Basic design choices

Let's compare MCI, MW, and SF:
  • All search engines treat every printing and every card part as a separate object
  • SF follows MW, and avoids polluting search results with non-English cards
  • SF unfortunately follows MCI and pollutes o: search with remainder text
  • SF includes nonstandard cards (like Planes) in all searches. MCI completely skips them. MW only searches for them if requested explicitly (by t:* or by specific search like t:plane).
  • SF decided to skip un-cards. MCI has them, and MW not only has them, it even has a lot of special queries (like for fractional cmc) which only makes sense for un-cards.
  • I have no idea why the hell SF included this. Is that some joke, or a phantom card?
I feel fairly ambiguous about including nonstandard cards by default, and perhaps SF's simple approach is better. As for everything else, they'd probably be better off matching MW.

Search engine issues

I tried to run searches from their syntax example page and compare them with what mtg.wtf returns.

Their results had a lot of bugs, such as:
  • wrong cmc for all meld cards
  • wrong cmc for some DFC cards
  • many cards wrongly tagged as is:commander, like Brisela, Voice of Nightmares, Kenzo the Hardhearted, or Ormendahl, Profane Prince.
They also made some really weird design choices, which I'd honestly just call bugs, as all of them make searching less useful:
  • color identity search being >=, while what you want pretty much every time is <= - you're generally filtering for cards fitting specific commander, not the other way around
  • mana search being >= on symbols, so if you search m:4 it matches {4}{G} but not {5}. That's weird as hell, as the natural search would be equality, and failing that at least treating {4} as {1}{1}{1}{1}.
  • Weirdly they decided that cards with changeling should be returned for searches for all creature/tribal types. So if you're searching for monkeys, you get 1 monkey and 30 changelings.
  • cards like conspiracies are listed as "banned" instead of simply excluded from all formats
Some of their choices are probably fine either way, but MW generally follows MCI in such borderline cases:
  • is:timeshifted changed its meaning from MCI, and SF is:colorshifted does what MCI is:timeshifted would.
  • color search being "and" instead of "or" like MCI/MW. So c:rg searches for cards which are red and green, as well as any additional colors. This is easily achieved on MCI/MW with search for c:r c:g.
  • they treat 2015 frame update as different frame type, which MCI/MW doesn't
SF doesn't have any of MW's extensions. First such limitation I ran into is that there's no way to search for split cards like Fire // Ice or t:creature // t:planeswalker.

They added a bunch of search aliases like color:red for c:r - I looked through the list, and I added some of them to MW as well, because there's pretty much no cost.

mtg.wtf's codebase is all open source, so I'd recommend them to just take my test suite, and try to make theirs work better.

Extra features

The most ambitious feature they have is that they want to instantly include cards from upcoming sets as they are revealed, not only after set appears on Gatherer. This is sweet, and definitely seems like way too much work for me at mtg.wtf.

They have card price integration, which I still haven't added, as all card pricing information seems to be hidden behind private APIs.

They have online API, which I guess I could add as well, but you can just download the code from github, and run it all locally, without even bothering with the API. I could add API to MW quite easily too, but it would be useful to do some performance testing first, as APIs often end up having order of magnitude more requests than real users.

SF has much better feedback for search query syntax errors than MW. That's definitely a good area of improvement. On the other hand their spelling correction is awful - compare SF with MW.

MW has been rather conservative with website design, and SF is trying something much more ambitious.

Wednesday, October 12, 2016

How I made mtg.wtf fast

red kitten 01 by mathias-erhart from flickr (CC-SA)
Website speed was one of the most common complaints about mtg.wtf, so I decided to do something about it.

It won't be necessary, but if you want more background, you can read about architecture of mtg.wtf in my previous post.

Verify the problem

The site seemed "fast enough" to me, but multiple users complained about its performance, so presumably there was something real about it.

I still wanted to make sure. It's important to verify that the problem you're trying to fix is real and on your side, as to not waste time fixing problems which might be caused by someone's crappy mobile connection or ISP throttling.

I checked Rails logs, and indeed - timing I've seen there were pretty poor. There wasn't even much need for statistical analysis - very simple queries shouldn't routinely took ~1000ms.

Have a test suite

Before I started any performance work, I needed to have a test suite to validate that I'm not breaking anything. Fortunately mtg.wtf was as TDD as it gets, and had very comprehensive tests - even if I'm retrospectively somewhat regretting using minitest for that.

If you don't have good test suite, don't despair - for optimizations you just need to find a reasonably representative sample of inputs (which you can use logs for), and record current version's outputs for them. If something broke in process, you'll get different results, so you'll instantly know.

It's not as good as dedicated test suite, as your random sample probably lacks important edge cases a proper test suite would generally have, but you get 80% of value for 20% of effort, and you can add a few test for edge cases as you go.

Generate a benchmark

This was easy enough - I downloaded logs, extracted list of queries from them, took a random sample, and tested time per request.

The best thing about this set was that I could very easily generate new benchmarks for specific types of queries with just grep - so when optimizing let's say card type searches, I can look for t:, which will give a much more accurate result than just throwing everything at it. (assuming my optimizations don't affect other query types of course)

As secondary benchmark I also recorded time to run the test suite. I didn't expect it to be super sensitive measurement, but it's nice to have extra validation for zero effort, and I was going to run the tests a lot anyway.

A small complication for any kind of benchmarking is that you want your computer to not be overly busy, or it will contaminate the results. It doesn't need to be completely idle, as computers have multiple cores and you'll generally be using only one core, but I closed things like Chrome and used my other computer for sucht things for a while.

Profiler

This is optional, and profiling tools in ruby are fairly weak and awkward, but I ran ruby-prof anyway to get some idea about code hot spots.

It would identify which parts of the code were taking the most time, but it's mostly there to generate some suggestions.

Precompute data

Shockingly the biggest hot spot was very simple query ConditionExact, which corresponds to querying for exact card - with queries like !goblin guide or !Far // Away.

The query was actually very slow, as it was going through entire database, and doing something like this:
  • go through the whole database, every card printing
  • take query, downcase, fix unicode, fix spacing
  • take card.name, downcase, fix unicode, fix spacing
  • if they're the same, it's a match
That was really slow, and also quite silly. Card names don't have spacing problems (like double spaces between words), and we're already fixing unicode silliness like the "Æ" ligature when we load the database. As for the query, we can precompute this data when we parse it and create Condition object.

It still needed the card name downcase step as card name was something like Goblin Guide, but it needed to match goblin guide, GOBLIN GUIDE and whichever other capitalization people use.

So the algorithm became:
  • go through the whole database, every card printing
  • take preprocessed query
  • take card.name, downcase
  • if they're the same, it's a match
That's still fairly inefficient, but it skips huge amount of pointless string manipulation.

Similar preprocessing was later applied to a lot of other conditions.

Separate common and uncommon cases

Going back to ConditionExact, it was actually two different queries:
  • exact card name - like !Goblin Guide
  • multipart card name - like !Far // Away
The multipart case was much more complex, as search engine represents every part of a multipart card as a separate object, so it needed somewhat complex logic to handle this.

So I moved all rare and complex code to ConditionExactMultipart and I just had the commond and simpler case left to optimize.

In a few other cases I set a flag if certain complex processing was needed. For example we support queries like o:"when ~ enters the battlefield", where "~" matches name of the card - so for example it matches Zealous Conscripts as it contains text "When Zealous Conscripts enters the battlefield, ...".

Such queries require more complex logic than most o: (card text) queries, which just look for same text every time, and can do more preprocessing.

In this case we set a flag in ConditionOracle constructor and then follow different logic based on that flag.

This optimization only makes sense when simpler condition is also the common one - if most cases are complex, you're not really gaining much by splitting them.

Use indexes

Most queries use ConditionSimple, which just tests card printings one at a time with match? method.

The alternative is for condition to process whole database and generate Set of results in one go.

These two modes are combined by he most common ConditionAnd to first get all Sets, take their intersection, and then filter them with each ConditionSimple one at a time.

Direct result Set generation was already used for a few queries already - like searching for cards printed in a specific edition, or specific block. I added that to format search as well, as f:standard is reasonably common phrase in queries which benefits a lot from this kind of early culling. Bigger formats like f:modern or f:commander didn't significantly benefit from this optimization, but they didn't seem to suffer either, so I applied it everywhere.

Of course the biggest beneficiary of direct access was ConditionExact which got a downcased card name index, and can now result results almost instantly.

I didn't add any more indexes as ruby is very memory hungry and keeping memory use low is very important. Other queries were either much less common or wouldn't benefit anywhere near as much.

Optimize memory use

I wanted to take a quick go at reducing memory use, unfortunately ruby memory profiling tools are still very poor, so I just did a few intuitive things like removing unnecessarily duplicated data.

I pondered going further, but speed improvement I got for random sample of queries were already huge. I didn't need anything complex like adding caching, getting bigger box, trying JRuby, or moving search engine to external service.

Verify the solution

Even though changes looked really good in benchmark mode, it's important to verify them in production. So I checked the results, and indeed vast majority of requests are fast now.

There's a few which are still somewhat slow - like for example someone trying to get 52nd page of result of all cards in EDH, but it's a reasonably safe bet that most of such weird requests are made by bots.

Overall, it's been a fairly straightforward and successful process.

Monday, October 10, 2016

Architecture of mtg.wtf search engine

There's nothing revolutionary here, it's a reasonably straightforward design. All the code discussed can be seen in its repository.

What are we searching?

We're searching "cards", but that's not specific enough, as there are two big complications:
  • Some cards have multiple printings
  • Some cards have multiple parts
So we need to decide if our searchable object is:
  • one part, one printing
  • one part, all printings
  • all parts, one printing
  • all parts, all printings
Far // Away is an example of multipart card

Vast majority of cards have only one part, and a lot of the time card's properties are the same between printings, so we could get away with other choices, or even inconsistent semantics, but I've chosen to operate on most granular "a single part of a single printing of a card".

Indexer

Raw data comes mostly from mtgjson, but first step is converting into a more usable form, which is actually just more json. I keep both raw and processed json files in repository, mildly annoying github, but in this case it's best practice as tests can't run without that, so code is incomplete without those jsons.

Indexer does some transformations and validations, and groups data by properties which should be same between cards (like name, text, cost, color) and those which can vary (like artist, rarity, flavor text).

When I started the project mtgjson data was of high quality, but it got a lot worse since it got new maintainers, so now I need to do a lot more fixing (and reporting those bugs upstream did nothing).

Every now and then I feel like I should just fork mtgjson and fix all those issues, but it's a pile of javascript and duct tape, so I mostly hope they get their act together again.

Because indexer started as very simple script and accumulated hacks over time (mostly due to deteriorating mtgjson quality), it's the ugliest part of the codebase. It has no dedicated tests, but as the whole test suite is operating on real data, any bug in indexer or mtgjson is likely to be picked by tests down the line.

Loading data

The library loads data from processed json files and transforms them into in-memory representation of Ruby objects. There's no dedicated database or anything like that - we're doing everything directly.

There's currently 16686 cards and 31648 printings, so it's not tiny dataset, but it's not unreasonably huge for this fairly naive approach to work.

Query Parser

We parse any query with StringScanner - which is one of the least known parts of ruby standard library, generating Query object.

Query object contains a tree of Condition objects corresponding to the query. In addition to searching Query object is also responsible for sorting results (by name, most recent etc., with sort: operator) and for time travel.

Yes, time travel - I find it occasionally useful to sometimes search for results as if I was searching at particular date in the past - so cards not printed at that time are not in search results, and format legalities are changed accordingly. This isn't literally going into the past, as we're not trying to do anything like updating Oracle text to old wording (which wouldn't be all that helpful), but that's how you can search what to play when you somehow get to play flashback Innistrad Standard.

time: operator is on query level, so you can't do cute things like asking for cards legal in both Ravnica Standard and Return to Ravnica Standard.

Condition

Condition objects must implement #search(db) method which takes database and returns Set of matching card printings.

This probably seems like a weird interface, and most conditions (those returning true when asked #simple?) also implement secondary interface of #match?(card_printing) returning true or false and avoiding allocations of intermediate Sets.

ConditionAnd, ConditionOr, and ConditionNot use one or the other API depending on type of their subconditions.

The reason for this design is that some subqueries ask about other part of the card, or other printing. For example you can check for cards printed in both M10 (Magic 2010) and M11 (Magic 2011) by e:m10 alt:e:m11. Doing recursive search and checking all subconditions would be exponentially slow in the worst case, and this design is always linear is query size.

Searching for edition (e:) and block (b:) always return small number of results, and we already have to maintain set data, so we reuse it as index and return small result Sets from them. Other queries don't use any indexing and just check cards one by one.

For most conditions either all printings match a query or none do, so special case for conditions which don't deal with anything printing-specific could potentially speed up a lot of queries. On the other hand while some cards have crazy number of printings, average is just 1.9 printings/card, so it's hard to tell if such savings would be worth added complexity.

Of course more indexes and more sophisticated query optimizer would be possible - or even using some dedicated search engine like solr. This didn't seem necessary due to relatively small amount of data. Fortunately the search engine has very extensive tests, so if I ever feel like developing one, it would be reasonably easy to do so safely.

Spelling correction

Many Magic cards have names which are very easy to misspell.
How do I spell this exactly?
QueryParser deal with it - if search returns zero results, it sets fuzzy flag on Conditions and retries the whole search. A few conditions will autocorrect your query, and any such autocorrection are logged and displayed with search results.

This two step process (as well as diacritics stripping and very limited amount of stemming) deals with most misspelled searches with good usability while keeping false positives to very low level.

Results coalescence

At this point we get a sorted list of printings, which is not quite what we want to display - all printings of the same card need to be merged (which is just .group_by(&:name)) - and since we'll be displaying card picture from specific printing we also want to choose the most appropriate one.

The algorithm for that:
  • choose only from matching printings
  • prefer those with card picture (small number of rare promos don't have pictures) - that's a frontend consideration database has no idea about
  • otherwise use order returned by search engine, which is:
    • whichever order was explicitly requested if any
    • name in alphabetical order
    • Standard-legal sets first
    • most recent first
After that we paginate the results.

Future direction for mtg.wtf

The most common requests are:
  • improving website performance
  • adding card pricing information via some third party API
  • advanced search form
Advanced search form is a UI problem, for which I don't have a solution yet, as all advanced search forms are atrocious, leave most possible options out, or both.

Third party API for pricing ended up more complex than I thought, but I'll probably get there at some point.

Performance complaints probably mean that current architecture could use some improvements after all. It seems fast enough to me, but possibly that's not good enough.

Saturday, October 08, 2016

Lessons from making mtg.wtf mobile-friendly

When you are weary,  feeling small by Michael Taggart Photography from flickr (CC-NC)
mtg.wtf is currently the best search engine for Magic: the Gathering cards. It's reasonably successful and popular, so let's go through its history quickly.

It started as a wishlist of improvements I'd like to see for magiccards.info

Then once magiccards.info stopped being updated, I decided to write a replacement. I started by wring a bunch of tests for how I'd like it to work, mostly using data from mtgjson

After I had tests, I wrote a search engine as Ruby library with command line interface. I thought about making it a standalone gem at this point, but I'm not sure how useful people would find it, considering json data is out there already.

After that I added rudimentary Rails frontend with minimal styling and put it online.

At this point it was text only, so I had to find card scans. WotC only publishes somewhat low quality scans, which are usable enough, but I wished to get something better. For about 2/3 of cards I found those higher quality scans, but it was a fairly slow and manual process. That still leaves some rare promos there's just no source of any kind - it wasn't a huge deal, as few people search specifically for them, the search engine just needed to display card with good picture instead of most recent version (which might be weirdo promo).

Then I added some CSS on-hover animations. Most cards have regular layout, but there are some cards which are double-faced, have horizontal layout ("split" cards), or have content on top and tobbom ("flip" cards). Later they even added pairs of cards which merge ("meld") into one big card with halves printed on their back face. All those cases for decent usability required either completely different display layout, or some animation support, and CSS animations turned out to be pretty easy to add.

Bootstrap

At this point I was getting feedback that it doesn't work too well on mobiles.

Well it's not too hard, we just need to add header telling mobile browsers to not be stupid:

  <meta content='width=device-width, initial-scale=1' name='viewport'>

Then I installed bootstrap, and replaced some existing layout code with bootstrap 12-column grid. It was surprisingly easy retrofit - other that bootstrap's use of .card colliding with my use of .card I don't remember any surprises. Markup looked a bit worse due to extra <div class="row">, <div class="col-md-8"> etc., but it's not too bad thanks to HAML.

Making it responsive

I have a bunch of mobile devices around, and testing on one or two devices is not too much trouble, but I wanted to make sure site will work well on everything, so I used Device Mode in Chrome Developer Tools to make sure everything works in wide range of sizes, portrait and landscape, added a bunch of responsive bootstrap tags, and I pushed the changes to the server.

  • For big screens site used desktop layout - 4 column for card picture, 6 column for card information, 2 columns for extra intformation
  • For medium screens layout was 6 column for pic, 6 column for information, and extras were hidden
  • For small screens layout was full row for card pic, and full row for card information underneath, with extras hidden
That was the most usable configuration in Chrome Device Mode.

Animation problems

There were two immediate problems - first Mobile Safari users reported that CSS animations are broken - it turned out that it required some prefixed properties for backface-visibility which nobody told Rails CSS autoprefixer about.

Second problem was that on very small screen sizes (where card was already full screen width) there was simply no space to do some of the animations - I ended up doing messy screen size queries in my CSS code matching Bootstrap size thresholds to turn them off.

And it was all wrong because "pixel" is a lie

I was quite happy with it, so I expected my users to be as well, but feedback I got was overwhelmingly negative. Users found the site unusable on mobiles, even though I crammed as much information as could reasonably fit in Chrome Device Mode.

The thing that got the most backlash was placing card text under card pic. But if I put tiny card picture next to text nobody could see anything, right? Oh wait, those mobile "pixel" numbers are total bullshit. That 100 "pixel" width is actually a lot more device pixels, so even though card looked like completely unreadable thumbnail in Chrome Device Mode, it looked just fine when I tried to use it on an actual phone.

And even if card picture was too small, so what? It's just as easy to pinch to zoom as it is to scroll down a bit - something that doesn't apply to desktops (where Cmd+ / Cmd- can zoom, but they don't focus on specific area, so they're much less useful).

This also means that 6 pic / 6 info layout on bigger devices was excessive - so I switched all non-desktop devices to 5 pic / 7 info as that's what looked best on actual mobiles and tablets I tried it on, even it looks horrible in Chrome Device Mode.

So now the site looked good on desktop (with big browser window), and on mobile devices with 2x or higher pixel density (of any size).

That doesn't cover using mobile devices with 1x pixel density (which fortunately basically nobody uses any more), or desktop browser with small window size (which happens, but worst case users can resize the window).

That leads to two big lessons:
  • Chrome Device Mode is horribly unrepresentative as it uses 1x not 2x pixel density
  • Bootstrap device width targeting is fairly unrepresentative as it ignores pixel density
Getting rid of whole-width card pic layout let me get rid of most CSS animation workarounds. There are still some for gallery view, like Nils Hamm's cards from Dragon's Maze where animations need to be aware of which column the card's in.

Soft Keyboard

Now it looked good, but I ran into one more problem. On desktop we want to start search box focused with HTML5 autofocus attribute, so user can start typing the query without clicking anything.

Now most good browsers understand opensearch annotations, so if you ever visited mtg.wtf, they'll remember it, so you can just type mtg<tab>your query from URL bar, and they'll get you straight to search results - but not everybody uses it this way.

But we don't want to autofocus on mobiles - as then huge soft keyboard appears covering half of results and making it all miserable. At least on some mobile browsers, others sensibly require click to show soft keyboard even with autofocus attribute.

Unfortunately I never found any way to query if device has real keyboard or not. So backup logic of autofocusing on home page (which has no results, so soft keyboard covering empty space is no big deal), but not on other pages (which have some result) ended up being a workable compromise.

It would be nice if someone figured out which browser/device combinations have this issue, and created some device specific autofocus library, as it can't be the only site affected by the problem.

Overall, it wasn't too bad


Even with all the surprises, it all went better than expected.

But imagine the world could have been different - once upon a time mobiles tried to create their own separate web with completely separate protocols and formats. How insane would it be if they succeeded?

Monday, July 18, 2016

mtg.wtf now supports Eldrich Moon

095 by d315thedeity from flickr (CC-BY)

I update mtg.wtf pretty much immediately whenever new set comes out, so I don't usually write announcements for it, but here's a small one - mtg.wtf is the only search engine which correctly handles converted mana cost of double faced and meld cards. For example queries like:
return correct results as per new rules, while other search engines have it wrong, and don't support anything like is:meld (or layout:meld).

Wednesday, December 02, 2015

Introducing mtg.wtf

Abby's String Theory by DirtBikeDBA (Mike) from flickr (CC-NC-ND)
Have you ever heard a name of a card and wondered WTF is that? Or wondered WTF you're going to put into your new Commander deck? Worry no more, mtg.wtf is there to answer all such questions you might have.

It has more useful syntax than any other Magic search engine, cleaned up output unpolluted by foreign cards and reminder text accidentally matching the results, supports time travel to the past, can sort things by most recent Standard printing, and generally does everything I ever wanted Magic search engine to do.

Except I didn't decide if I want to put pictures there yet, but hosting solution I decided to use makes it fairly simple, so I'll probably find some card pictures and put them there quite soon.

As a bonus, here's some really nicely formatted and hyperlinked Comprehensive Rules.

For some previous posts about this: one, two, three.

The website should integrate with multiple search engines support in all major web browsers. If you ever visited it, your browser should let you search for cards by just typing "mtg.wtf" or something similar.

As for the name, I originally planned a more conventional one, but everything was either taken or way too long. Then I discovered newly opened .wtf TLD, and that was strangely appropriate for this project.

Contact me any way you want with bug reports and feature requests - I'm pretty sure I'm available on all social networks ever invented. I have a few ideas for cool new things to add to the site, but let's start with what's there. I tend to respond to such very quickly.

I'm not sure how well servers will handle the load. They should be just fine, but if it turns out they can't deal with it, I'll take a look at making things faster or getting bigger option from my hosting provider.

Sunday, November 29, 2015

Let's Play Civilization 5 as Jarad of Golgari Swarm - in Polish

After my fun "Let's Play Civilization 5 as Poland in Polish" series I wanted to do one more series in Polish, and I also wanted to play one more Civ5 game on Ravnica, so I did both those things at once and started a Polish Golgari game.

Here's playlist, and here's the first episode:


As usual schedule is one episode per day, at exactly the same time of day.

There are a few minor changes compared with Izzet campaign:
  • It's in Polish. For now I plan to keep the channel something like 80% English and 20% Polish, and all Polish stuff will be very obviously marked as such - as you can see from flag above.
  • I'm playing on Standard sized map with 8 civilizations, not obvious 10 civilizations on large map as before. 10 guilds is better flavor, but standard game speed is sort of balanced around standard map size, and increasing map size strongly implies bumping game speed to epic speed (or domination becomes really hard), which together would make campaign twice as long. I feel standard map speed/size lead to just better flowing campaign, at least as default.
  • I downgraded EUI to older version. New version unfortunately breaks a lot of mods. For some reason EUI authors don't provide links for downloading previous working version, in spite of new version being known broken, which goes very much against basic etiquette of all things software. I hereby denounce them for that. Fortunately I had old version saved locally.
  • As a result a few mods which were broken in Izzet campaign are working fine now - in particular More Luxuries mod.
  • I removed "Race for Religion" mod, as I'm playing with "New Beliefs Pack" mod, and it was silly to have both.
  • I manually fixed XP From Forts mod so it doesn't have crazy requirement that citizen needs to work citadel/fort tile (like that wasn't underpowered enough) and now I'm playing with it. It's been modestly useful, but nothing crazy.
Here's all guild mods:
Here's all other mods:

Other things I want to do on the channel


Right now the channel is fairly busy with 1 Factorio and 4 Civilization 5 series. Even counting Polish Civilization 5 as something separate, that's still a bit less diversity than I planned. Then again, I really wanted to play more Civilization 5 after that America campaign, and it's like the most recordable game ever.

So I'm planning to do a few more series for games other than Civilization 5, and I also want to do some non-gaming content.

An awkward side effect of this is that it's going to be a huge number of videos being published every day. Initially I just told youtube to autoannounce every video on my twitter, facebook, and google+ feeds, but that's getting a bit silly at this point due to volume of such automated announcements.

On the other hand, it's not like I have a better idea. But you should totally subscribe if you like my videos.

Oh and if anybody has any idea how to get channel art to be something more sensible than my Google profile pic + random landscape, please tell me.

Tuesday, November 24, 2015

Let's Play Civilization 5 on Ravnica as Niv Mizzet of Izzet League

The first time I played Civilization 5 I thought it's OK game, but nothing special. Gradually my attitude changed to something like this:

Yo dawg, I heard you like civ5...

So without waiting for other series to finish getting published, here's another one! Just like my previous series (Poland in Polish, America on Great Plains map, and China on China map) it's just a tiny bit gimmicky: we're playing with all 10 guilds of Ravnica on a large fractal map.

Here's episode one. Episodes will be released one a day at same time.

The playlist where they'll all get published is here. Or you could just follow my channel on youtube.

The goal is to take all 10 guild halls, get voted Supreme Ruler of Ravnica, or build a spaceship to Innistrad or some other plane. Well, technically culture victory is also a possibility, but it never seemed even remotely viable in any of my previous campaigns, so I don't normally give that much thought.

Our guild is Izzet League, led by great dragon Niv-Mizzet. All 10 guilds seem to be extremely powerful, so they're sort of balanced against each other, but would be somewhat overpowered mixed with regular civs.

Our uniques are:

  • All science buildings are upkeep free, give +1 gold, and +2 happiness
  • Izzet Boilerworks - factory replacement which doesn't require coal, and gives +4 science and +50% science
  • Hypersonic Dragon - basically medieval Helicopter Gunship, a Knight replacement with strength 20, movement 5, bonus vs mounted units, and hover. It can't take cities, and doesn't upgrade to anything.
Sounds pretty strong? Just watch the series to see what other guilds get. Their uniques gave me more trouble than I had from uniques in any other campaign (my suffering in America campaign was mostly self-inflicted).

In the campaign I play mostly decently (unlike in that America campaign...). There's a good deal of unwarranted arrogance which sometimes backfires, but I totally blame all that on roleplaying an elder dragon.


The mods for guilds are:
Other mods used:
There were a few issues with these mods:
  • New version of Extended User Interface has some absolutely dreadful default behaviour with dialogs autoclosing, I wanted to roll back to old version but that's extremely unsafe with civ5 mods, and can easily result in corrupted campaign impossible to continue (my Germany campaign was lost this way). Fortunately after the campaign I figured out how to turn off silly behaviour.
  • I have two mods changing religions - Race for Religions, and New Beliefs Pack. I planned to just go for one of them, but somehow I messed it up and it's another campaign with both. It was actually surprisingly good due to some other choices I made, but I'll make sure to pick just one in the future.
  • I used different mod for unit promotions, and I'm still really tempted to just write my own. Unless you know of another I should give a shot first.
  • Units donated by militaristic city states with 0xp feel worthless. Is there any mod that lets them have higher XP? I tried one that was supposed to give units 1xp/turn from just sitting in a citadel (until some maximum based on your tech), but it never worked.
  • Are there any mods which change puppet cities priorities to something more sensible (production focus instead of gold focus would be a good start)?
  • Are there any mods which fix priorities for tile expansions? The algorithm is completely ridiculous choosing featureless ocean tiles and tundra leading nowhere over strategic/luxury resource tiles, which requires a lot of money, but also a lot of tile assignment babysitting, which is not part of the game I enjoy particularly much and prefer to leave automated 90% of the time.
In any case, I had tons of fun, and I'll definitely start another civ5 campaign soon.

Monday, November 09, 2015

Writing replacement for magiccards.info - syntax improvements

my adorable cat by pinkiwinkitinki from flickr (CC-SA)
A couple years ago I started bitching about how magiccards.info could be improved. Unfortunately that on its own rarely leads anywhere, so a couple of weeks ago I decided to write a replacement for magiccards.info. Since then it turns out that magiccards.info got sort of reactivated, so my project became a lot less urgent, but I got so much cool stuff implemented that I decided to come back and finish it.

All the code is available on github. It has somewhat unpolished Ruby on Rails-based frontend (without any card pictures) as well as command line interface and ruby API.

You can run it locally on just about any OSX machine if you know how to run Rails (git clone, bundle install,  rails s), and it should works on Windows and Linux even somehow if you can run Rails there.

I obviously need to look for some hosting solution so it's usable for average person. It would be relatively easy to add images to it, it's really mostly hosting issue. Frontend links to Gatherer (as well as magiccards.info), so except for a few weirdo cards in mtgjson database but not on Gatherer like International Collector Edition picture is one click away, so I guess I could enable hotlinking for local use, but let's not give WotC's paradoid lawyers any more reasons to go after this.

If anybody has hosting recommendations, I'd love to hear them. Oh and it should probably be called something more unique than magic-search-engine.

The search engine is backwards compatibly with about 90% of magiccards.info syntax, so you won't need to break your habits. Here I'm documenting just major additions and fixes.

Weirdly even some completely undocumented syntax from magiccards.info works the same - like is:reserved and loyalty>=6 work identically on both search engines, even thought I had no idea magiccards.info had that when I added them to my search engine (it's in mtgjson data we both use, so it's not entirely accidental).

Full documentation for all the syntax is available in the frontend.

Automatic data cleanup

Real data is full of silly inconsistencies and it's search engine's job to try to clean them up. The most important such cleanup is completely stripping out reminder text from o: queries, so it's finally possible to search for flying green creatures with straightforward o:flying c:g t:creature - or to correctly have Transguild Courier and Dryad Arbor match is:vanilla for your sweet Muraganda Petroglyphs deck.

Another thing that's not matched because it shouldn't be is foreign names in default mode, so you don't get unrequested silliness like this.

These are the biggest cleanups, but there are some weird things I ran into which I told the search engine to fix as well.  For example would you like to search for planeswalkers with -3 loyalty ability? That would be t:planeswalker o:-3, right? Well, that won't work because on planeswalkers it's a Unicode minus sign (U+2212), not ASCII symbol which your keyboard and all other cards have. Except on DFC's Garruk flip side, where it's ASCII again.

Much better spelling suggestion system

If you try to search for "kolagan command" on magiccards.info, it will helpfully ask if you meant "Kolaghan's Command", which with one more click you can get to. But that works only for full card names - searching "kolagan" will return no cards and no suggestions.

Here it's much better, if search engine can't find precisely what you were looking for, it extends all names which were not in any title of real Magic card to all misspellings. So you can search "kolagan", "purphuros", "tezeret seeker", "joira of githu" and so on.

The engine is smart enough to know not to do that if something is a real magic card, so if you search for "mox f:standard", it will not try to autocorrect it to "ox" and return Standard-legar "Yoked Ox".

Sensible sorting

You can specify how to sort the results as part of the query with  sort:new,  sort:old, sort:name etc.

sort:new / sort:old sensibly treat all supplemental sets as lower priority than every Standard set, so random duel deck reprints won't pollute your results when you're trying to search by actually newest.

Use sort:newall and sort:oldall if you want to treat all sets equally.

Robust handling of multipart cards

This is probably the most complex additional syntax.

On base level search engine operates on individual parts of cards, so "Tear" or "Chandra, Roaring Flame" are what it cares about, not "Wear // Tear" or "Chandra, Fire of Kaladesh // Chandra, Roaring Flame" together. The only exception is color identity (ci:), which is defined by rules to apply on cardboard level (and which is currently broken on magiccards.info).

Of course sometimes you actually care about whole cards, so there's new syntax for that.

A // B will return any card with one part matching A, and the other part matching B. It can be used for title matches like Wear // Tear or Gideon // Kytheon, but queries can be anything like t:human // t:insect, or mana=1r // mana=w.

You don't even need to specify the other side if what you've got is specific enough. c:r t:werewolf // will return all multipart cards which have red Werewolf on one of their parts.

I'd guess this is most useful syntax, but if you want to be more specific you can use other:condition to specify what goes on the other (not returned) side of the card, like with c:w t:creature other:(c:b) returning just Cloistered Youth and Loyal Cathar (but not their black sides).

There's also part:condition syntax for specifying that either side matches, so for example part:t:enchantment matches cards which are either enchantments, or their other sides are.

For vast majority of queries I expect people to just use A // B syntax - which for that matter expands to part:(A other:B) behind the scenes.

To simply query particular type of multipart card you can use is:flip, is:split, is:dfc or particular kinds of them, or is:multipart to get them all.

Searching for multiple card versions

As analogue of part: system you can also query other printings of same card with alt:.

For example to find a card which was printed by both Rebecca Guay and someone who's not Rebecca Guay, ask a:"rebecca guay" alt:(-a:"rebecca guay"). Or to find all cards which stood test of time and were printed in both 1993 and 2015 ask year=1993 alt:year=2015.

Block queries

You want to get all equipment from Mirrodin block? That would be t:equipment (e:A or e:B or e:C) kind of query, if only you could remember set symbols for all its sets - and it doesn't help that Gatherer, magiccards.info, and mtgjson often use different symbols for same sets (for example Alpha can be 1ED, LEA, or AL in different sources).

That has trivial fix in t:equipment b:mirrodin syntax, which matches all equipment in a block. For that matter if you remember symbol of first set in the block, you can use it as a shortcut, so b:rtr t:angel returns you all Angels from Return to Ravnica block. Some sensible logic is used to prevent matches for overlapping blocks, so b:ravnica matches only original Ravnica.

For that matter you have third alternative of using syntax like f:"mirrodin block" t:land for individual block formats, but that's more wordy, and excludes banned cards.

Time travel

You can time travel and search Magic cards as they used to be. So to search Standard as it was during New Phyrexia just ask for time:nph f:standard.

If you time travel it obviously won't show you any printing from the future, and formats will be as they were at that point, with set legality and banned and restricted list.

Historical banned and restricted list should be fully accurate from September 2004 Legacy/Vintage split onwards. Earlier than that best available data is often not fully consistent, so it's only going to be mostly correct. Quite often there's unbanning announcement, but original banning is lost somewhere in depths of rec.games.deckmaster Usenet group. If anybody has better data than what I managed to find (spending far more time on this than is reasonable), I'd love to hear about it.

Search engine doesn't plan to do anything as extreme as getting old version of Oracle text, then again it would be kinda fun.

time: currently moves the entire query to a certain point in the past, so you can't mix multiple times in same query.

Reprint search

Database supports queries like e:ktk firstprint<ktk which would return all cards from Khans of Tarkir which are reprints. You can use either set code or specific date (year or day) and any comparison operator, like let's say print>wwk t:jace (Jaces printed after Worldwake), firstprint=1993 r:mythic (all cards first printed in 1993 which ended up as mythic rares), or lastprint=8e (cards for which last printing was 8th edition) is supported.

Unfortunately technically prerelease promos count as prior printing as prerelease cards are "released" one week before actual set. That might need some changing.

Support for nonstandard card types

By default only "normal" card types are included, but you can explicitly request other kinds by type, like with t:conspiracy, t:scheme or even t:dominaria.

You can also request all cards with t:*, presumably followed by more specific criteria.

This is implemented as a special filter - any reference to type of non-standard cards anywhere in the query will switch query from regular mode to everything mode, so for example if you ask for -t:scheme it will expand the query to match Planes, Conspiracies etc.

Tokens are currently not included, but since they're in mtgjson database I might change that.

English only

If English was good enough for Jesus, it ought to be good enough for Jace. Search results are not polluted by fake matches from foreign language cards like they are on magiccards.info.

Foreign card names are still in the database, so it's possible to add a mode to search for it, but it's going to be strictly English only by default.

Really minor improvements

Various information about card frame like layout:leveler (for card layout), w:gruul (for watermarks) is supported in addition to already existing queries like is:black-bordered, is:future etc.

You can use either f:edh or f:commander - they both work.

All is: queries can be negated with not: like not:reserved.

Unhinged fractional power, toughness, and cmc queries like pow=0.5 or cmc=0.5 work, at least mostly.

Split card system supports 5-part cards too, all one of them.

mana= queries check actual mana, not converted mana cost, so mana=0 will nor returns lands and manaless suspend cards, only cards with actual mana cost equal to 0.

mana= queries treat hybrid etc. mana as their own kind, because I couldn't come up with any consistent logic to do otherwise which would fit all special mana types. So Bioshift is mana={u/g}, not mana=g anything like it.

Everything is documented on help page in the application.

Saturday, October 10, 2015

Writing replacement for magiccards.info

♥  My Girl ♥ by Trish Hamme from flickr (CC-BY)

magiccards.inf is probably the most useful MTG site out there. Comparing it to Gatherer is like comparing Birthing Pod to Search the City.

It has a few issues I wrote about, but it never bothered me enough to do anything more than complain on the blog. Unfortunately it seems to be abandoned, so someone needs to write a replacement, and that someone might just as well be me.

The plan

The plan is very simple:
  • get data on cards
  • write search engine which accepts magiccards.info style queries
  • write a web frontend to search engine
  • host it somewhere
  • get images
  • add extra functionality
  • avoid lawyers

Gathering data

Step one seemed like a messy Gatherer scrapping, but it turns out mtgjson website already hosts 99% of data we need. I manually entered a few more bits like which sets belong to which blocks, etc. There's still some missing bits like assigning frame types to individual promo cards, but it's really low priority.

For that matter I'm not sure magiccards.info is doing a particularly good job on it. For example what makes Unhinged Forests is:funny? No idea.

Writing search engine

I wasn't sure how complex it's going to be, but it turned out it's fairly easy. I wrote a search engine in Ruby, and put it on github. It can be used from command line, or as a library.

Vast majority of queries like a:"steve argyle" t:elf, e:gatecrash r:mythic t:legendary t:angel, f:standard pow>cmc c:g, or "Birds of Paradise" translate to very simple code.

The search engine still misses a few things. Biggest remaining problems are:
  • How to handle 2-in-1 cards (split, flip, DFC) - are these simple two cards which just happen to share cardboard (and color identity for commander), or is it one card. In certain way Wear // Tear should return true when asked cmc=1 cmc=2 (this query is why Counter-Top loves this card so much), in certain way it shouldn't.
  • What the hell expressions like mana>={u/g} even mean? mana is a reasonable query when both card and query are just made out of "normal" mana symbols - or even Unhinged half-mana symbols - but is {u/g}>={r/u} true or false or what?
  • How to make it a bit more performance, as loading 50MB JSON file takes about 3s on my laptop (and then individual queries are super fast) and well as too much memory for my liking.
  • Some fallback method to deal with spelling errors.
And there's still some small remaining bits. But generally, search engine is about as good as one on magiccards.info. A lot of improvements are already there. For example:
  • reminder text is stripped from Oracle, so you can now reasonably search for green flying creatures without hitting all reach creatures - and it also correctly makes Dryad Arbor match is:vanilla
  • support for b:Innistrad style queries for filtering cards by block
  • support for loyalty: queries
  • support for Unhinged fractional values
  • color identity queries ci:wb actually mean something now (in this case - can go into White/Black Commander deck)
  • support for querying random metadata mtgjson had like watermark:gruul
  • proper differentiation between cards with mana cost 0 and no mana cost (like lands)
  • some convenience features like not:black-bordered
There's still stuff to do, but I'd say it's about 80% done after one productive all-nighter.

Writing web frontend

Search engine is written in Ruby, so it would be fairly easy to do a Rails front-end. This runs into issue of how to present the data (just text, no pictures yet), write some syntax guide etc., but none of that is terribly complicated.

I could also do a silly thing and write a coffeescript version (or cross-compile ruby to javascript to run on client side) where all calculations are done client-side - which would incidentally completely solve hosting problem, as hosting static sites is really easy to set up.

Host it somewhere

Somehow it's been a long while since I last put any nontrivial website online myself, usually I use other people's EC2 accounts or servers for that.

It's mostly awkward from monetary point of view, as it could get significant traffic (especially if magiccards.info never recovers). For text it's not too bad, but for tons of images it could get painful.

I'll look at it once I get previous step done. It's probably something I should take a look at anyway.

Get images

Search engine doesn't necessarily require pictures - it could get away with just text data, card images are sort of more decoration than anything else. But it would be better with images. I'm not entirely sure where to get them from - presumably from wherever programs like cockatrice get them. Hosting them is a bit of a bandwidth cost risk.

Add extra functionality

Once I go through trouble of setting it all up, I could add some extra features like Sealed pool simulators. (I wrote a few before), or whatever I feel like. No point talking about it that early.

Avoid lawyers

Unfortunate side effect of doing anything Magic-related online is that technically WotC lawyers can screw you up any time they want - and sometime they go on a rampage with tons of innocent casualties, like fan art, draft simulators, etc.

It's pretty much random, as thousands of sites (blogs, shops, etc.) use Magic card images, it's well within boundaries of traditional fair use, and most of the time Wizards couldn't care less, but it would suck horribly to put all effort (and own money for hosting) into setting up such site, and then get it removed by a lawyer on a power trip.

Coming soon


Anyway, I'll keep you posted, or if you're impatient just check my github project. If you have any feature requests, github is probably the easiest way, or just contact me in any other way.

Saturday, September 26, 2015

Reviewing Magic sets is still hard



A while ago I wrote a post with a lot of examples of pros making rather embarrassing mistakes in card evaluations for Constructed.

It's been a few sets since then, and examples keep coming four times a year.

The usual disclosures apply - I'm posting it to show that reviewing sets is hard, and you should take whatever people say with a grain of salt, not to mock anyone.

Fate Reforged - Gurmag Angler

Constructed: 0.5

Technically can be a one mana 5/5, but I think the other delve options are just better, even going back to cards like Hooting Mandrills.

Khans of Tarkir - Treasure Cruise

Constructed: 2.0

I suspect Dig Through Time has made Treasure Cruise nearly obsolete, but Treasure Cruise is more splashable and is better raw card draw, so there’s a chance it sees some play.

Khans of Tarkir - Dig Through Time

Constructed: 2.5

I want this to be good and I’m going to spend a lot of time digging to make that happen, but it’s still an 8-mana spell to begin with. [...] It’s not quite Sphinx’s Revelation.

Magic 2015 - Aggressive Mining

Constructed: 3.0

This is an aggressive rating for a very interesting card. I could see this seeing zero play, because it certainly is hard to utilize (and very dangerous when implemented incorrectly), but the card is just so powerful that I can’t help but imagine it being awesome in the right deck. One way to approach this is to play it as the top of the curve in a deck that really doesn’t need lands past three or four. Playing this on seven lands makes it close to a draw six, and that really isn’t that bad.

Born of the Gods - Brimaz, King of Oreskos

Constructed: 4.0 (the only such rating in the entire set)

Brimaz is going be the one king to rule them all, at least in terms of white beatdown decks. In Standard, he's going to be an auto-include in Plains-heavy aggressive decks, and is powerful enough to try many different builds of such decks. He's even purrfect for some different Modern decks, and it's funny that both Bitterblossom and Wild Nacatl could both potentially be paired with Brimaz to great success. The size, cost, and abilities all line up so well here that Brimaz is just impossible to ignore.

Journey Into Nyx - Mana Confluence

Constructed: 5 (Fives are ever-present cards that heavily warp a format or see heavy play across multiple formats. Jace, the Mind Sculptor, Deathrite Shaman, and Tarmogoyf are good examples of fives.)

Many might not realize why this is so strong. It is because having perfect fixing for a three to five color deck found in a single land is worth some damage over the course of a game. Decks that play this will either have access to life gain, to offset the downside, or will be very proactive and aggressive, like combo decks, so that they don't care that they did three damage to themselves before killing you. This will be moderately played in Standard but heavily played in older formats wherever City of Brass has popped up in the past.

Saturday, May 31, 2014

Bechdel test and Magic: the Gathering

Warning: Do not treat this post seriously.

Bechdel test is a famous test for female presence in movies, but it can apply just as well to any other work of fiction.

So I had this thought - Wizards of the Coast has pretty good reputation when it comes to gender balance in their storyline, but how well would actual Magic: the Gathering decks do at passing the Bechdel test? So here's the equivalent test for decks:

  • It contains cards representing at least two female characters - creatures, planeswalkers, or spells clearly featuring female characters in name, art, and/or flavor text (multiple cards representing the same character like Chandra, Pyromaster and Flames of the Firebrand only count once); the character does not have to be named or human (but it should generally be some kind of humanoid at least)
  • which interact with each other
  • and the interaction is not about some man (like both counting as devotion to the same male God)
And let's now evaluate a bunch of decks.
The deck is one big sausagefest - all of its creatures are either male or monstrous and of unspecified gender, and their only interaction is being devoted to Erebos, God of the Dead and his Gray Merchant of Asphodel.

The only female presence in the deck is an occasional Pharika's Cure sideboard, but that card doesn't really count since it actually shows Solon, (male) acolyte of Pharika, and even if it did it won't be curing any of course creatures.

Score: Fail. (and its Bg and Bw variants aren't any better)
The central character in the deck is Thassa, God of the Sea, and some of her supporting characters like Tidebinder Mage and Hypnotic Siren are female as well, and between their devotion, and Thassa making them unblockable and helping them with her Bident, interactions are pretty strong.

Score: Pass.
This deck depends on the build. The deck is very light on creatures, and central two characters are Elspeth, Sun's Champion and Jace, Architect of Thought. Other popular characters are Aetherling, Nyx-Fleece Ram, Mutavault - none of them female.

The deck occasionally plays sideboard Archangel of Thune, and Elspeth's ultimate sort of interacts with her, or Archangel's ability can help Elspeth's soldiers (but not Elspeth herself). This could count if Archangel was a common mainboard card, but it feels too weak.

Score: Fail (some builds arguably weak pass).
The deck doesn't feature them directly, but Chandra and Aurelia both feature in art of many cards.

Cards in the deck rarely interact with each other, other than by all burning opponent's face, but Warleader's Helix bringing back Chandra's Phoenix from the grave technically counts. 

Score: Pass.
People were totally obsessed asking if Domri Rade is a boy or a girl, but word of god is that he's a he - it would have made matters simpler if they decided otherwise, since Domri interacts with every creature in your deck, but let's look at the rest of it.

Sylvan Caryatid and Courser of Kruphix seem female, as far as I can judge plant and centaur anatomy, and Caryatid can tap for mana to cast Courser, which is a fairly weak interaction.

Looking at sideboard, the deck sometimes features Nylea's Disciple, Vraska the Unseen, and Chandra, Pyromaster. Nylea's Disciple interacts with all your green cards via their shared devotion to Nylea, God of the Hunt, and Chandra's synergy with Courser of Kruphix is just amazing.

These interactions aren't very strong or involve SB-only cards, but there's lot of them.

Score: Pass.
This deck is just filled with creatures but except for Thrill-Kill Assassin (also knows as Massacre Girl) none of them are women.

Score: Fail.
The deck features Bassara Tower Archer and Gladecover Scout, but the very point of the deck is that they're hexproof and don't interact with anybody ever. They only make exception for Ajani.

Score: Fail
The deck generally includes Pharika, God of Affliction, and all the creatures in it are devoted to her, and she returns the favour by turning their dead bodies into poisonous snakes... People can be weird like that sometimes.

Some builds try to work without Pharika, and while there are some minor interactions, I'd say they generally fail the test.

Score: Pass (for Pharika builds).

Summary

Of decks I checked 4/8 passed. That's honestly a lot more than I expected.

While I was checking various decks another thing became clear - while other colors have decent cast of female characters, black seems to be very heavily male-dominated. Think of it what you will.

Friday, January 31, 2014

Reviewing Magic sets is hard



Every time a new Magic set comes out, everybody on the Internet is totally sure they totally know which cards are going to be overpowered and which will be completely unplayable.

It turns out, people are not really that amazing at predicting what's going to be good. Sometimes there are good excuses for these misjudgements - Melira was only a thing in Modern, which was just starting back then, Stoneforge Mystic didn't have any good targets at time of its printing, and hybrid mana cards like Burning-Tree Emissary wouldn't see as much play if it wasn't for unrevealed at a time devotion.

Still - a lot of these mistakes have no excuses. Titans in Magic 2011 and devotion in Theros have been horribly underestimated by just about everyone (and I'm showing only the most extreme examples below), even though all cards for Theros Standard were known, and Titans would have been very playable in just about any Standard.

The list below is provided not to shame anybody. It's just for your entertainment, and in hope people will have a bit more scepticism about their ability to predict how good cards will be without playing.

EDIT: Apparently Grave Exchange rating was supposed to be a joke, it's hard to tell among so many awfully missed reviews which are serious mistakes and which are jokes. Anyway, I removed it since there are enough unintentional failures to enjoy.

EDIT: A year later, I wrote followup post with more extremely missed ratings.

Worldwake - Stoneforge Mystic

Constructed: 2.0

This is unlikely to make a splash in Standard, but getting Umezawa's Jitte in Extended makes this quite interesting. I doubt that it makes something as clunky as Tatsumasa, the Dragon's Fang worth it, but even if it only can get Jitte, there are decks that are interested.

Magic 2011 - Frost Titan

Constructed: 1.0

Would shroud really have been too much to ask for? As is, this Titan doesn't even net you a whole card when you play it, and its ability doesn't really protect it by the time you get around to playing it.

Magic 2011 - Sun Titan

Constructed: 2.0

I don't have high hopes for this particular member of the band. He is doomed to play bass while Primeval Titan and Grave Titan fight over the mic, since getting a small permanent back is just not sexy enough. Yes, getting back O-Ring is pretty sweet, but how often does O-Ring actually hit the bin? Opposing O-Rings are the most likely answer, and Sun Titan doesn't help there. As for getting back Tectonic Edge or a fetchland"¦that isn't my idea of an exciting six-drop. Just play Sphinx of Jwar Isle or Baneslayer Angel at that point, since Sphinx dodges removal and Baneslayer flat wins the game if they don't have it. Sun Titan does neither.

Magic 2011 - Inferno Titan

Constructed: 2.0

This passes the value test (if it dies immediately you still got value, in case that wasn't clear), and is a solid threat in its own right. The effect isn't as powerful as its undead cousin, and red isn't very well set up to play six-drops, but as a card it is good enough to consider. Finding a deck might be difficult for this, since it doesn't fit into any of the existing archetypes.

Scars of Mirrodin - Sword of Body and Mind

Constructed: 1.0

I was excited to find out that they were continuing the Sword of Fire and Ice cycle (sorry Light and Shadow, but that’s how it is), but my excitement dimmed as soon as I read Sword of Body and Mind. The abilities just don’t match up at all, and neither is particularly powerful. Milling them while bashing for 4+ damage doesn’t accomplish anything, and is actually more likely to be a drawback than anything else. Sending a bunch of Vengevines to their yard is not quite what I’m looking to be doing. Besides the useless mill ability, you get to make a singular Grizzly Bears, which is also not that great. I have higher hopes for the rest of the cycle, since this one just isn’t good enough.

New Phyrexia - Melira, Sylvok Outcast

Constructed: 1.0

I don’t see this working out very well as a sideboard card. If it didn’t take away infect, it would be an awesome hoser for block, but playing a 2/2 for 2 that just gains you a bunch of life against one very specific deck isn’t going to cut it.

Innistrad - Delver of Secrets

Constructed: 2.0

This might actually work, which is pretty sweet, since this is one of the many cards in the set with awesome flavor. Dropping one of these guys and Pondering should just about do it, and random flipping in a deck full of spells doesn’t seem out of the question. If there is an all-spell sort of deck, he could be a legitimate threat.

Innistrad - Skaab Ruinator

Constructed: 3.5

This thing is gonna ruin some hopes and dreams. Coming out early and often doesn’t seem unrealistic at all, and there are even multiple ways to achieve this goal. The first is Birthing Pod, since he even only costs three, and once sacrificed, can be easily brought back. Multiple 5/6’s on turn four and five is tough to beat, and that’s without the backup plan of recasting them if the opponent manages to kill both all your guys and the Pod itself.

The second way to maul them involves milling yourself, probably with Forbidden Alchemy and Dream Twist, and likely alongside Unburial Rites and other sweet Flashback cards. This deck seems a bit more creature-light than the ‘Pod deck, but between Snapcaster Mage, Skaab Ruinator, and possibly even Armored Skaab, you have a good start.

Either way, I expect there to be much ruinating over the next year, and it should be pretty sweet.

Return to Ravnica - Ethereal Armor

Constructed: 1

If Enchantress decided they want to start winning on the back of their enchantress itself, this has a shot. The big problem there, is typically the only enchantress that sees play has Shroud (that's like a more fair version of Hexproof for all you young'n's), so there aren't actually any good targets for this.

Return to Ravnica - Pack Rat

Constructed: 2.0

PV (@PVDDR_Quotes on Twitter) compared this to Bitterblossom. Even though he was joking, given enough time, the opponent will be plagued with Rats in short order. If they don’t pack enough removal, you get more and more value with each activation, and the copies retain the activated ability in case of the original dying.

The power level here is interesting, and if there are enough attrition-based matchups, this could certainly be a thing.

Gatecrash - Burning-Tree Emissary

Constructed: 2

These types of cards are always begging to be broken. I am not sure if this one will end up being in that level of power, but rumors have already begun spreading about some of the things you can do with this in Standard, including Human Reanimator.

Dragon's Maze - Aetherling

Constructed: 2

While I love a win condition with a lot of versatility and utility on it, the high cost of this might keep it from seeing too much play. You really need to wait until at least seven mana to have this protected at least a little, which is quite a lot to ask. This will probably see light play, maybe in sideboards, etc., but I would not be expecting a Titan level of play.

Theros - Gray Merchant of Asphodel

Constructed: 1

This could end up being some weird win condition in a combo or control deck looking to flood the board with black mana symbols. Costing five mana is a big drawback, but the effect is unique enough that you never know.

Theros - Voyaging Satyr

Constructed: 1.0

Keep on walking.