Introduction

How Pokemon got me to where I am today

As a senior in college, just about to finish my Business Management Degree, I found out about coding. I did Code.org and Codecademy.com (back in the early days of Codecademy), and when I felt like I had a bit of a grasp, I started my first Pokemon Game.

It was stupid simple. It was a case statement that did the dialog of you picking your first Pokemon. That was it.

My second Pokemon Game was after I finished my Procedural Programming in C++ course, and because I didn't know about custom types and classes, each Pokemon was an array, and each index specified a stat or HP, or move that it knew. It was bad. But I quickly got better!

I proceeded to build better, more complex games in Python, Javascript, Node.js, C#, Go, Elixir, React, Vue, Angular, you name it! As I did it more times, I got more familiar with the problem, and instead of having to solve the problem over and over, it was "how do I get to this solution better, and in the language/framework I'm working in?"

When building Pokemon Games, you can go anywhere with it. Want to study Databases or use a new ORM or Adapter? Do it! I've done it in databases like MarkLogic, Mongo, Postgres, JSON, Dgraph. And I've implemented it in ORM's like Prisma, Knex.js, ActiveRecord, sqlc, TypeORM, Hasura, Supabase, Firebase, Ecto, and others!

Want to study building API's? Make a Pokemon Generator API that takes in a level, a species ID (like Pikachu is #25) and have it generate all the stats, some randomly assigned moves that species can learn, and more! I've done it in GraphQL, gRPC, REST API's, in probably 5 or 6 languages. And I've built battle API's, where you have turned based attacks (although I haven't yet done real-time! I want to and want to try it in this blog!)

Want to build UI's or Graphics? I've built Overworlds (the top down map in the game) with Sprite and Tilesheets, letters and symbols in a CLI, in Web Assembly with Rust, OpenGL in C++, vanilla Javascript and HTML, etc.

What I'm trying to say is that this can be as complicated or simple as you want it to be! I'm no game development expert, I've never been a professional game developer, and I'm not a super proficient writer, but I want to get there! So join me! Give me feedback! Let's learn together.

I wasn't able to copy over my Node.js Pokemon Game to Elixir, because there are massively contrasting paradigms. For example, here is an earlier version of my "Elemental Advantage" calculation in Typescript, followed by a far sleeker, Elixir version of the same thing:

export enum TypeAdvantage {
  Strong = 2.0,
  Weak = 0.5,
  Normal = 1.0,
  None = 0,
}
export enum Type {
  NONE = "none",
  BUG = "bug",
  DARK = "dark",
  DRAGON = "dragon",
  ELECTRIC = "electric",
  FAIRY = "fairy",
  FIGHTING = "fighting",
  FIRE = "fire",
  FLYING = "flying",
  GHOST = "ghost",
  GRASS = "grass",
  GROUND = "ground",
  ICE = "ice",
  NORMAL = "normal",
  POISON = "poison",
  PSYCHIC = "psychic",
  ROCK = "rock",
  STEEL = "steel",
  WATER = "water",
}

export function getTypeAdvantage(atk: Type, def: Type): TypeAdvantage {
  switch (atk) {
    case Type.NORMAL:
      switch (def) {
        case Type.ROCK:
        case Type.STEEL:
          return TypeAdvantage.Weak;
        case Type.GHOST:
          return TypeAdvantage.None;
        default:
          return TypeAdvantage.Normal;
      }
    case Type.FIGHTING:
      switch (def) {
        case Type.NORMAL:
        case Type.ROCK:
        case Type.STEEL:
        case Type.ICE:
        case Type.DARK:
          return TypeAdvantage.Strong;
        case Type.FLYING:
        case Type.POISON:
        case Type.BUG:
        case Type.PSYCHIC:
        case Type.FAIRY:
          return TypeAdvantage.Weak;
        case Type.GHOST:
          return TypeAdvantage.None;
        default:
          return TypeAdvantage.Normal;
      }
 ... // you get the point

Super verbose. If I did again (which I know I will), I'd do a map, but meh. You live and you learn! Here is a similar function, but far more concise, using Elixir's pattern matching:

  defp advantage(_, :none), do: 1
  defp advantage(:normal, x) when x in [:ghost], do: 0
  defp advantage(:normal, x) when x in [:rock, :steel], do: 0.5

  defp advantage(:fire, x) when x in [:fire, :water, :rock, :dragon], do: 0.5
  defp advantage(:fire, x) when x in [:grass, :ice, :bug], do: 2

  defp advantage(:water, x) when x in [:water, :grass, :dragon], do: 0.5
  defp advantage(:water, x) when x in [:fire, :ground, :rock], do: 2

Take chances, make mistakes, and get messy!

I don't think I need to clarify that that was Ms. Frizzle, but I want that to be the theme for this tutorial.

My hope is that, as you go through this process, you'll be able to find those ways to improve. You'll challenge yourself to do things in new ways, and even say "Hey Mike! I found a better way to do what you did, wanna see?" and my response will always be "Hell yeah! Lemme see!!"

Last updated