Organizing KeyForge

Sorting the un-sortable

The Day the Magic Died

I used to play a LOT of Magic: The Gathering.

From the mid-90’s to about 2000. I played a lot with friends at school. I liked collecting new cards, opening packs, being surprised by the cards I found, and then making completely bonkers decks. The more bizarre or silly they were, the better. I even made it a mission to collect the complete Parody Set of Unglued, which I foolishly sold off (I wish I had held onto that set…).

But, around 2000, something changed.

I started going to more “serious” tournaments. I would notice that my silly, or thrown-together decks would never do very well… and I kept seeing the same handful of very powerful cards show up all the time, and often, multiple people would show up playing very, very similar decks. I was witnessing the birth of The Meta.

I remember exactly how it happened. I was at a tournament. I had a deck that I was very proud of. It was mono-Green (using only green cards), and was all about playing big creatures and making them bigger to attack with. There were actually duplicates of some cards, which, to me, made it feel like a “real” deck, and not just something I had thrown together from the cards I happened to have lying around (although it totally was).

I think it was either before, after, or between rounds at the tournament, and my Best Friend - who was (and still is!) much more serious about the game than I was - asked if I wanted to play a round to pass the time. I agreed, and we sat down to play. Shuffled and cut our decks, drew our hands, and I remember thinking that I had a fun combo available in my starting hand that I could play in a turn or two, and then my friend played a handful of cards, triggered a bunch of effects which triggered other effects, which cascaded into more effects, and then, after matter-of-factly explaining all the things that he was doing, looked at me and with calm, unworried voice of someone who knew they had assured victory, explained that “basically these cards would keep triggering like this and would go on indefinitely until he won”.

And the game was over.

It was at that exact moment that I fell out-of-love with Magic.

A New Kind of Magic

Over the following years, I maintained a love for obsession with tabletop games. And, while I would sometimes dip my toe back into Magic, and a little bit of Pokémon, the TCG no longer held the appeal for me as it once did. The surprise and the excitement was gone and what was left was too competitive and stressful, because it required you to be constantly up-to-date with every card before it was even released, and to know what every deck was that was being used in tournaments in order to even stay relevant in the game.

For a short time, I tried playing the Lord of the Rings LCG, but, it was frustratingly difficult, so, even though I had collected a ton of the sets that had been released, and loved the idea of the game, I ended up growning cold on it over time.

…and then, in 2018, I started hearing chatter about a new kind of card game… one that completely broke the formula. It was designed by Richard Garfield, the designer of Magic, but it would be a completely different beast.

In November of 2018, KeyForge was released.

I went to a release-day Sealed tournament to learn the game - and was instantly hooked! I took my daughter, Naomi, to play at the next tournament, and (up until the pandemic hit last year), we went to nearly every weekly tournament at our local game store.

We can not WAIT to be able to start playing with people again!

Procedurally Generated Goodness

Playing the game is certainly fun, and the mechanics and card design are a lot of fun. But the biggest, and most fun part of KeyForge are the decks.

In KeyForge, you don’t buy packs of randomized cards of different rarity and use them to build decks, or pre-made decks of the same, uniform cards. You buy a deck of 36 cards for about $10, which, is procedurally generated from all of the cards that have been made so-far in such a way that there will never be two identical decks ever produced!

What this means is, the Meta is nearly non-existant! We like to play in Sealed tournaments, where you show up, pay a fee of just a little more than the cost of 1 deck, and then everyone in the tournament is given an opened, never-before-seen deck to play with for the tournament!

Naomi Says:

I like going to weekly sealed deck tournaments. You can walk in with no experience with the game and they give you a deck and you can easily just jump right in. The community is very friendly and will help out if you're confused about anything. And it's not like games like Pokemon or Magic where someone finds the perfect deck before the cards are even released, with Keyforge it's completely up in the air. Some people like buying decks off of others, but it's still very random. And in sealed tournaments, nobody knows anything about their deck. No one can become overpowered because no one knows what they'll get. Sure, with other games, you don't know what's in the card packs, but you still build the deck yourself.

Neutron Shark

My favorite deck that we have is Ruthlessly Tragic Darius. It's from the very first set, "Call of the Archons". I've played with it in tournaments a lot. It's got a special card in it called a Maverick, which is a rare card that is normally in one house, but in this specific deck, it's in another, which gives the deck unique properties.

The Maverick card in this deck is Neutron Shark, which is usually in the house Logos, but is instead in house Dis in this deck. This card, normally, makes you destroy things that are out on the board until you discard a Logos card. However, since this deck has no Logos cards, it essentially turns Neutron Shark into a board wipe. And we got this deck simply by chance!

It may seem like that's way overpowered and goes against everything I've said, but in fact, Darius has lost 12 times and won 5. And that's the fun of it, you can have a game-breaking play and still lose. Or you could have the worst deck in the history of mankind and still win. It's all up to chance and skill. You can't buy your way to the finish line. You just get to have fun with it.

Wild Wormhole

One of the best parts of getting a new deck is seeing which 3 of the 11 different houses will be part of your deck, and which cards you get. Sometimes you get some fun, weird stuff: like a deck with 4 Wild Wormholes - a card that puts the top card of your deck into play and whatever happens, happens!

On top of that, there are common, uncommon, and rare cards that will in your decks in a predictable ratio (more commons than uncommons, etc), but there can also be other rare, and unpredictable cards that can be added to your deck.

🔹 There are “Special Rarity” cards which are added to the deck based on some set of parameters that the deck has to meet, such as Qincan’s Blaster, which will only show up if Sci. Officer Qincan is also in the deck.

Qincan's Blaster
Sci. Officer Qincan

🔹 Naomi mentioned Mavericks - you can sometimes have a card show up in your deck changed to be in one house when it normally always shows up in another.

🔹 There are Legacy cards, which is a card that is from a previous set, but is no longer in the ‘current’ set, but it shows up in your deck anyway!

🔹 There are Anomaly cards which are cards that can show up in your deck that are from future sets that haven’t been released yet!

🔹 There are cards that have the Enhance keyword which actually change what is printed on other cards in the deck!

🔹 Oh, and remember how I mentioned that there will never be two identical decks produced? Well, in this most-recently released set, Dark Tidings, they’ve added a new feature to the way decks are generated where, there’s a chance that a deck is generated identical to an existing deck, but then it will be modified to become an Evil Twin: a handful of the cards in the deck will be changed to have slightly different good and bad changes applied (like adding more power but removing some armor, etc), and they will be given alternate art - and the deck will have it’s name mutated to be similar to the original deck’s name, but with the inclusion of “Evil Twin” somewhere in the name.

It is absolutely fascinating the different crazy things you can get in a deck! …and since no two decks are the same, it encourages picking up a lot of different decks, and, like I mentioned, Sealed tournaments where you are guaranteed to walk away with a brand new deck!

…so this all finally leads us to the point of this blog post!

The Organization Conundrum

After playing Sealed tournaments nearly every week for 2+ years, you start to accrue an awful lot of decks - all with crazy names and different houses, and, eventually, you start to run into the problem of storage and organization!

We started to realize that we had a problem during quarantine… the number of decks and our “system” of storing/locating them was seriously lacking.

I knew that we needed marry the physical storage location of our many, many decks with a database that listed all of our decks.

1 of the 3 Large Boxes in our Collection

I wanted to make sure we did the following:

  • ◻ Using cardboard card boxes, store every deck in a logical way that can be logged and tracked
  • ◻ Have all of the Archon (Card List) cards for each deck in a place that can be used cross-referenced to compare and find decks in the boxes and from the list
  • ◻ Make it as easy to update and maintain as possible!

KeyForge has a website, The KeyForge Master Vault, where they encourage you to add your decks (by scanning the QR code on the deck list card with your phone, or by typing in the unique 15-digit code on the same care), so that you can keep track of your collection. You can also browse all the other added decks, and, when playing in tournaments, you can win shards, and keep track of your wins/losses, and your decks’ wins/losses.

The KeyForge Master Vault

This seems great on paper, but, the site is lacking a LOT of functionality.

It has also said that it was in Beta since the game launched in 2018.

For one, it only lets you see a handful of your decks, at once, with only some basic information. It’s fine for looking at the cards in your deck, or tracking stats, but that’s about it. You can’t really use it to help you find the decks we have in storage.

Originally, I thought we could pull the information of all our decks from the KeyForge site. They have some API logic that is hidden away in the site, but, with some digging, you can see how to use some of those API calls - however, while it’s very easy to get the information on specific deck via it’s 15-digit key, or to search for decks by name, or to even get a complete list of every deck ever scanned, it proved to be nearly impossible to get just a full list of all the decks that we owned. And the API, since it was undocumented, was hard to deal with and use.

Enter Decks of KeyForge

Decks of KeyForge

There is another website, Decks Of KeyForge, which does a much better job of sorting and displaying deck information - plus, they have a free, and actually useful API that you can use to access their data! It also has a feature where it will come up with a rating for every deck added to the site based on the cards in the deck, and how well those cards “synergize” with each other. This rating is called the SAS, and it’s a novel way to see which decks are “stronger” or “weaker” in general (although a low-scoring deck can still be a lot of fun!).

DoK is a lot better in terms of functionality, but it is still missing a few of the things that we needed to help with organization. You can’t really add your own data, and it doesn’t really show any helpfully identifiable information about your decks, other than the name.

Also, in order to add your decks to this website, you need to add them manually. One-at-a-time.

Thankfully, someone else solved that problem for us.

The Library Access: KeyForge Deck Sync Tool is a Chrome Extentension which will, once you’ve logged into the Master Vault, click a button to scrape the keys of ALL of your decks, and then, when you open up DoK, you can click a button to have ALL of them get added to DoK! This saves a TON of time!

At this point, we were on our way to making the functional organization system that I had envisioned. We had every deck we owned and had scanned into the Master Vault now added to DoK, and DoK offered a handy way to access those decks with an API call…

Building our System

Next, we needed to actually grab, and DO something with our deck data.

We also needed to figure out a way to give each deck a unique ID, and figure out where it should go into our box system.

Enter Google Sheets! With some simple scripting, we were able to setup a Table that has all the fields we need, and, with a button press, will grab the DoK data via API and populate the table - giving each deck a unique ID, based on the order the deck was acquired, and telling us the exact Box, Row, and Slot every deck should be placed in our storage boxes!

Here is the complete script that we used:

// get the active sheet
const sheet = SpreadsheetApp.getActiveSheet();

// For Storing decks:

// how many rows are in one box?
const ROWS_BOX = 5;

// how many decks will fit in one row?
const DECKS_ROW = 21;

// when the spreadsheet is opened, we add a new menu item to refresh our deck list from DoK
function onOpen() {
  var ui = SpreadsheetApp.getUi();
  ui.createMenu("🔑 KeyForge")
    .addItem("⟳ Refresh Collection from DoK", "getDoKDeckList")
    .addToUi();
}

// when you click on "Refresh Collection", this function will run and grab all the decks
function getDoKDeckList() {
  var headers = {
    "Api-key": "GET YOUR OWN API KEY FROM DoK",
  };

  var params = {
    method: "GET",
    headers: headers,
  };

  var url = "https://decksofkeyforge.com/public-api/v1/my-decks";

  // grab the deck data from DoK using GET and our API key
  var response = UrlFetchApp.fetch(url, params);

  // parse the response as a json
  var json = response.getContentText();
  var data = JSON.parse(json);

  var deck, newID;

  // get a list of all the deck IDs we already added
  var ids = getExistingIDs();

  // sort the deck data by id# - this is DoK's ID, and is in the same order the decks were scanned into KeyForge Master Vault
  data.sort((a, b) => a.deck.id - b.deck.id);

  // for every item in the data, loop
  for (i = 0; i < data.length; i++) {
    deck = data[i].deck;

    // if this is not a deck we already have in our table, we add it
    if (!ids.includes(deck.id)) {
      // our deck's ID is simply the number of rows already filled in our spreadsheet!
      newID = sheet.getDataRange().getLastRow();
      sheet.appendRow([
        newID,
        deck.name,
        deck.keyforgeId,
        getExpansionAbb(deck.expansion),
        "",
        deck.sasRating,
        deck.aercScore,
        deck.wins,
        deck.losses,
        getDeckLocation(newID),
        "",
        deck.id,
      ]);

      sheet.getRange(newID + 1, 11).insertCheckboxes();
      sheet.getRange(newID + 1, 13).insertCheckboxes();
    }
  }
}

// determine where the deck should be stored
function getDeckLocation(ID) {

  var box, row, slot;

  var total_decks_box = DECKS_ROW \* ROWS_BOX;

  var id = ID - 1;

  box = Math.floor(id / total_decks_box) + 1;

  row = Math.floor((id % total_decks_box) / DECKS_ROW) + 1;

  slot = ((id % total_decks_box) % DECKS_ROW) + 1;

  return "Box " + box + ", Row " + row + ", Slot " + slot;
}

// get the abbreviation of the expansion
function getExpansionAbb(Expansion) {
  (Expansion) {
    case "CALL_OF_THE_ARCHONS":
      return "CoA";
      break;
    case "AGE_OF_ASCENSION":
      return "AoA";
      break;
    case "WORLDS_COLLIDE":
      return "WC";
      break;
    case "MASS_MUTATIONS":
      return "MM";
      break;
    case "DARK_TIDINGS":
      return "DT";
      break;
  }
}

// this returns all the existing DoK ids we have in our table
function getExistingIDs() {
  var ids = [];
  var data = sheet.getDataRange().getValues();
  for (var i = 1; i < data.length; i++) {
    ids.push(data[i][11]);
  }
  return ids;
}

Oh, and if anyone is curious, they can take a look at our spreadsheet of decks here: The Hely Collection - KeyForge Decks

Our Finished Spreadsheet