A Game in Thirty Days: Part Two

I made a game in thirty days! And now I’m writing about it. In part one of this mini-series I talked about the process of getting started: setting my goal, picking my tools, etc. Now, in part two, I’d like to talk about a few things I learned along the way.

As a quick refresher, this is the end product:

It’s a short Zelda-like action game built with GameMaker Studio 2. The game consists of a village, a dungeon, a quest, and “remembered” progression — that is, if you unlock a door or complete a puzzle, the dungeon will remember.

Lesson: Don’t just dive in

More than once, I decided what to do next and started working on it right away. The time this bit me hardest was when I originally implemented elevation changes and pits you could fall into.

Originally the game had just two elevations. Collisions worked with tile layers, one for each elevation, and had multiple tile maps for each elevation. This worked fine, but ended up being a lot more work than it needed to be: code to set depth/z-ordering based on an entity’s current elevation; code and triggers to change elevation; code to reset elevation when certain conditions were met; extra work mapping “portions” of the map; so on.

Then came time to implement pitfalls. In Zelda you can walk over a pit or hole, or knock an enemy into one, and you fall. I tried to do this using objects, collision, and triggers, and eventually got something that worked most of the time, except for if you walked funky or collided without realizing it. This ended up being frustrating if you didn’t take the happy path. I spent a lot of time tuning and tweaking these triggers. It felt like I was banging my head against GameMaker for a while.

I spent an entire day on these pits before scrapping the feature altogether.

Five days later the solution came to me, along with a way to unify both features and simplify the collision system. I spent another day doing this, as well as adding ledge jumping, while also removing large swaths of code and combining everything into a sort of “collision state machine.”

Doing this made it easier to implement all of these features, and more, with less code. The end result was more robust, required less work to build out when creating new maps, and made it easier to extend to add new features. A similar approach was used by the Pokemon games, which is where I got the idea.

Plus, it looks kind of neat.

collision tile map

The collision tile map. Each tile represents a different state or elevation.

The main lesson here? A little bit of planning can save days of work. If I had sat back and thought about this a little while before jumping in, I’d have had at least an extra day to work on other things.

Lesson: Get friendly with graph paper

Pen and paper will always be cheaper and easier to use than writing code or building tilemaps or whatever else. This is, luckily, something I did not have to learn the hard way.

Before placing a single tile in GameMaker, I drew every room of the dungeon on a graph pad. I placed doors, monsters, traps, chests, in little squares on paper, and ran through the dungeon in my imagination. Once I found a tileset to use, it was just a matter of putting the pieces together in GameMaker and running through to make sure it was all right.

Iterating on paper instead of in-game reduced the overall time spent on the project by a considerable amount.

That said, there were still a few changes made in-game once I was able to playtest the dungeon. A puzzle got scrapped, a room was rearranged, and a new room was added.

Still, pen and paper proved invaluable, and for the next steps in the project I’ve been doing almost all the up-front work on my trusty graph pad. If anything can be mapped visually or sketched up, then it’s probably worth doing that before you even think of writing code or building maps or anything of that nature.

Lesson: Waste your time wisely

I’m not an artist. In the beginning of this project I spent a little too much time trying to draw my own sprites and animations. The fourth time I scrapped everything and closed GraphicsGale in frustration, I decided it was time to find some art to use.

There’s almost too much good, free, and open art to use on the internet. You could spend hours looking through everything, which I did. The point is, as usual, just to pick something and stick with it. It’s not worth spending too much time on the visual appearance of your game at the early stages. As long as it’s tolerable, or at least the intent is clear in your presentation, it doesn’t matter how it looks until much, much later.

In the end I paid for some assets and drew some others. It’s probably clear which ones were “mine”: the slimes and the bosses don’t necessarily jive with the rest of the game’s aesthetic. But that’s fine.

Lesson: Play it!

You can’t know if your game is fun unless you play it. Not just the one room you’re working on, or the new feature you’re building and testing in your debug room.

Before releasing the demo, I went through the game beginning to end more than a dozen times. In the process I tweaked hitboxes, changed some behaviors, found some bugs (and left some bugs! for the attentive player to exploit if they want), and adjusted the difficulty.

Me, almost getting wrecked by a simple encounter.

This might have also worked against me. I was worried the game would be too easy, but the first feedback I got was exactly the opposite. One of my first players spent nearly an hour, collecting 12 heart containers and throwing 23 bombs, and still struggled with the final boss.

(This was partially due to the fight difficulty and partially due to the control scheme being a struggle, but the point stands! I added a new control scheme and it became easier for him. )

Details aside, the bottom line is this: if you’re not having fun playing in, then others won’t, either.

Wrapping Up

If nothing else, the thing to take away from all this is, “plan ahead, and plan the right way for what you’re doing.”

Or don’t. Five hours of work can save you twenty whole minutes of planning. 😉

The Game

If you want to view, download, or leave feedback for the game, click here:

A Game in Thirty Days: Part One

Recently, I was struck by that familiar urge: to make a video game. After a few hours of reading and thinking I decided I was going to jump in and do it, but this time it would be different. I would just pick a platform, start working, and make a game in thirty days.

This is the result.

As you can see it’s got a few rough edges, and it’s obviously incomplete (no title screen, no saving, etc.), but for now it’s “done” and it’s time to reflect, take away some key lessons, and move on to the next project. For the curious, I’ll put a link to the download page on Itch.io at the bottom of this post.

I want to talk about this project: how it was formed, what I learned, and what’s next. This post is part one in a series.

The Plan

Obviously, the Zelda games were a huge inspiration for this project. A Link to the Past is my favorite game in the series and in my opinion one of the greatest games of all time. I always thought that, given the rise of nostalgia titles and revivals of older genres, no one had really given ALTTP the same treatment.

(This isn’t entirely true. There have been some. But none that have really captured the essence of the games, like the two I linked above. But that’s probably a topic for another blog post.)

So I thought I should be the change I wanted to see. It was time to dig in.

Picking My Tools

In every past attempt to make a game, I always focused too hard on vague future possibilities. Not picking Tool X because I might want to do XYZ thing in the future. Or picking Tool Y because I wanted better control over ABC thing. This focus on tools, platforms, or languages limited me and doomed my projects from the beginning: by focusing too much on some nebulous definition of quality or maintainability or extensibility, the projects became about the code and not the game.

This is not to say that these things are unimportant! Just that when you’re making a game, the game comes first. If you’re not producing something that can be played, you’re not making a game. And that’s fine if the goal is to learn about specific aspects of game development, because there are a lot. But this time, my goal was to make a game.

So my mantra became make it work; make it right; make it fast.

I closed my eyes, picked an engine, and downloaded the 30 day trial of GameMaker Studio. No further thought or planning went into this, for better or worse. The important thing was to just stick with something and make a game with it.

The first week of my thirty day trial I spent learning about GameMaker Studio and GML, its scripting language. The official resources and Shaun Spalding are excellent, and I could not have done this so quickly without help from his ARPG tutorials.

Picking My Battles

After all that, the next most important thing to focus on was scope. I didn’t want this to balloon out of control and become another thing I wouldn’t finish because I decided I wanted to do more than was possible. So I decided, one dungeon. That was it. If time allowed, maybe a little more, like a village.

If I was going to stick with the Zelda format, one dungeon meant kind of a lot. Secret rooms, special items, chests, a variety of monsters, traps, a boss battle, item drops. The idea was to write out a list of these high-level ideas. Each day I would pick an item from the list and implement it.

This was a huge help even if I wasn’t completely successful at it. There are a few features I implemented that aren’t even really visible in the end product. On top of that, there are a few features I started to implement then scrapped when I realized they were too much work, or not very fun. I probably spent a week total on these things.

A few other features I started to implement, took a break, then came back and restarted with fresh eyes. Sometimes this meant throwing away everything I’d done before, and others it was just a wall I’d hit and I needed a break. Sometimes a feature I thought would take me an hour took me a day.

I wouldn’t consider any of this lost or wasted time. That’s part of making a game: if it isn’t fun, scrap it. So it was important to frequently playtest and make sure even this narrow slice of gameplay was fun and satisfying.

The Process

During the development process I kept a devlog, just kind of raw notes at the end of each day going over everything I did and what I wanted to do the next day. This was helpful for me because I could come back without that “what now?” feeling: I already knew what was next, and Past Me told Present Me exactly what it was.

I also started sharing screenshots and gifs with some friends and family over Discord and Twitter. Feedback, even if it was just “that’s cool, keep it up,” really helped keep my motivation up.

The devlog details my setbacks and triumphs. Originally I kind of wanted to post daily or weekly updates with the devlog but decided it would take too much time to clean up and post and would detract from the energy I needed to make the game. Later, I’ll clean it up and post it. I always enjoy reading other developers talk about their process and it’s always heartening to read about others facing and overcoming their own setbacks. I want to share my own experiences with that.

Next

This post is already longer than I thought it would be, so I’ll cut things short for next time, where I’ll go over some specific lessons I learned, a few techniques I used, and more.

The Game

View the game, download it, etc., below.

How to Teach Yourself to Code

Several times over the past few years I’ve been asked how I learned to code. I didn’t go to school for it, and it wasn’t originally something I aspired to do. So I never really had a good, straightforward answer, and just ended up rambling on for a while. The more I thought about it, the more I realized that my path to becoming a software developer was almost as meandering as my answers, and just as packed with fitful starts and dead ends. So, I figured I would sit down and write it down, though unlike my Teach Yourself SQL post, this post’s scope is much wider, on just how to teach yourself to code in general.

Or, more specifically, how I taught myself. Everyone learns differently, so just because something worked for me this doesn’t mean it will work for someone else. I’ll try to also include “further reading” and other types of resources that I didn’t use, but I know to be useful.

So… how do you teach yourself to code?

0. Get Very Comfortable with Google

Or your search engine of choice.

The point is that part of being a software developer, or working in any capacity with technology, is being able to find and parse information online. You need to be able to form your question in a way someone else can understand, then find the appropriate resource, then understand what you’re reading.

This might be official documentation from a company about its products. It might be a StackOverflow post, or a thread on a forum. You might need to be the one to ask the question, because it hasn’t been asked before. Which leads into the more important point, way more important than just knowing how to google something:

A fundamental part of being any good at any of this is the ability to clearly define your problem.

This will not only make it easier to find answers to your questions, but it will make it easier for you to solve your own problems. The vast majority of the work is taking a nebulously-defined problem, breaking it down into solvable chunks, and then solving those chunks. Remember word problems in your math classes in high school? It’s like that, forever.

1. Pick a Language

I know this seems like a weird first step. How do you pick a programming language if you don’t know anything about programming? In reality it doesn’t matter very much which language you pick; what matters is that you pick a language and stick with it.

This advice I drop with personal experience. The list of languages I picked up and forgot is longer than the list of languages I use today. First was Ruby, when I was 11 or 12 and building games with RPG Maker XP. Then it was C, then C++, then JavaScript… the problem was, every time I started with a new language it was like starting over. This was because I didn’t stick around long enough to master the fundamentals. Once you get the fundamentals down, then moving languages is easy. But you’ve gotta stick around long enough to do that. That’s the hard part.

That said, if I were to start again today, I’d pick one of these and stick with them.

  • C#: Developed by Microsoft. The tools are free, the documentation is extensive and detailed, and you can pretty much choose exactly how deep you want to dive here. The language and the tools have everything built-in to let you get started easily, and learn its inner workings at your own leisure. This is my favorite language, and my default when starting a new project.
  • JavaScript: If you can use a web browser, you can write and run JavaScript. Nothing extra is needed to run this code, making it the easiest to just get up and running. As a bonus, you’ll never be out of a job if you can master this language.
  • Python: Similar to JavaScript in a lot of ways, this still requires some setup before you can use it. Once set up, though, Python is another great language to start with, and perfect for building everything from small tasks to games to big web server applications.

Obviously, you should do your own research, but don’t get too deep in the weeds. Just pick a language, any language, and decide that it’s the language you’ll use to learn how to program. Some do come with a learning curve just because extra tooling might be needed to run them (C#, Python), so decide if you want to fiddle with installers or just get going (JavaScript).

2. Learn Your Fundamentals

Now it’s time to hunker down and start the real learning. I linked to some documentation for each language above, which is a great place to start.

From a bird’s-eye view, your learning path would cover:

  • Data Types: These are the building blocks of programming, and are how your code is represented to you, the coder, and how it’s interpreted by the machine. It’s the difference between an integer (1), a decimal (1.0), and regular text ("1")—and how these can and can’t interact with each other.
  • Operators: These are how you set and update your data. Like mathematical operations, they let you add things together, check for equality, and more.
  • Conditions and Loops: “If-this-then-that” logic, or “for every item in this list” logic.
  • Functions / Methods: Like formulas, or small mini-programs. If data types, operators, and conditions are water, rocks, and paste, then functions and methods are the bricks that make the foundation for a program. You put everything together into a method, then call that method from other code to do a predefined set of work. Like “2+2=4”.

Remember that Google is your friend, and there are countless resources on all of the above out there. The official documentation for the languages I posted above includes info on these terms, or the resources I will link to below will guide you through them in a more structured manner.

3. Dive a Little Deeper

This is where the Computer Science comes in: algorithms and data structures.

This is a big topic. Entire textbooks are written on just this alone. The important thing to remember is that every piece of code you write comes with its own complexity. Some code will perform better than other code, and many problems can be generalized, or abstracted, and solved with algorithms that some other smart people have already figured out. Like, what’s the best way to sort a list of items of a certain type?

Anyway, here are two specific places to start:

  • Look up “Big O Notation” and how it relates to the speed or complexity of an algorithm. You don’t need to know specific algorithms to understand this. It’s a good primer on efficiency, and an important part of describing the complexity of a particular piece of software.
  • You like video games? Look up “binary space partitions” and how they’re used to generate dungeons in roguelikes. Here’s a link to check out, without any code in it. This is a great example of taking a more generalized data structure / algorithm, and applying it to the specific problem of “how do I automatically generate dungeons for my video game?”

4. Make Something

As I stressed in my SQL post, if you don’t use it, you lose it. All this reading is worthless if you don’t do anything with it. It will just fall out of your head in six months and you’ll have to start over again.

Pick a project, any project. Find a small task you do that’s repetitive and might be automated and try to automate it. Go through this list of project ideas and work down it. Build a Pong clone, or a Breakout clone. Find a textbook and do the questions at the end of each chapter.

Start small, and work your way up to bigger things. Don’t overwhelm yourself. But keep going, keep building. It’s okay to just follow tutorials and copy code as long as you’re also thinking critically about what you’re copying and why it works—and better, how you might do things differently on your own. Go past the end of the tutorial. Keep going. It’s okay to get stuck, it’s okay to break things. That’s how you learn.

But keep going. Keep building and learning and growing.

5. Read

Maybe this should have been first. Or maybe it should replace everything above. Textbooks remain the single best method of distributing and acquiring knowledge. The good ones structure themselves in a logical and approachable way so that you can start out as ignorant as the day you were born, and finish as an adept.

The only downside is that technology moves at a fast pace, and textbooks for things like specific languages might be a little outdated by the time you find them. That’s okay, really. Most languages don’t change enough for it to matter, or you could use the book’s structure to set your pace and help you find more modern materials that are available elsewhere.

Or you could focus on books that aren’t about a particular language. Some of the best books on programming are more about how to approach the work, ways to think about code, and the “soft skills” many of us lack in the industry; that is, how to navigate people, culture, and politics. Here’s a good list of these books.

6. Further Resources

Okay, you’ve made it this far, but maybe everything above is still too vague to really get started. Here’s a list of free resources designed to get you going. Most of these are structure learning, like online classes, for you to do at your own pace.

  • Harvard University’s CS50 Course: My advice above kind of contradicts this course in the sense that the course covers multiple programming languages. When in doubt, trust the professionals, because they know better than me. This course covers everything from the very basic on through to some fairly complex projects. Really, you can’t beat this. There are other universities out there like MIT that also post courses online for free.
  • /r/learnprogramming: A friendly little community with good resources and helpful community members. I just linked to the wiki, but the sub itself is great for if you have questions and for finding even more great programming links. Click around in here and you’ll definitely be able to find where to get started on just about anything.
  • The Odin Project: Everything you need to know to become a successful and well-versed web developer. A full curriculum, from start to finish.
  • Project Euler: Not necessarily a tutorial resource, but a great way to flex your math and problem solving skills. This website is a series of math problems that start fairly simple and very quickly escalate. These are a great way to get your bearing on a new language.
  • The RogueBasin Roguelike Tutorial: This is a tutorial for making a roguelike game using Python and a Python library called libtcod. It’s a great tutorial, has pointers on using Python in general, and by the end you have a fully functioning game base which you could extend, or at the very least you’ll learn a great deal about handling user input, graphics, dungeon generation algorithms, and more. It’s fun and the roguelike genre is a great playground for any developer.

That’s all, folks!

This was by no means an exhaustive how-to. Nor did it cover the actual path I took. But I started over this is how I might do it today. Learning new things is a skill all on its own. Sometimes the best thing is to just get a few pointers and go off to explore on your own. That’s how my brain works.

Custom Authorization Schemes in .Net Core 3

Recently while working on a .Net Core API project I had to add some authorization features to further protect endpoints based on user-level security. This security scheme was conceptually pretty simple, but a little complicated to implement. In the end I had to implement some custom authorization middleware myself, so I would have just the right level of granularity and control.

The Problem

The project I was working on has some fairly granular and customizable security controls originally implemented in the legacy codebase. This API needed to reimplement the same security controls for parity with the legacy codebase, so that from a user’s standpoint nothing changes at all.

To do this, I wanted to put a top-level auth check on a resource, or endpoint, so the API could reject unauthorized requests right off the bat without even thinking of going any further. A simple want, but the details were a little hairier.

In this system, each user is assigned a security group. These security groups determine the accessibility of roughly 800 controls, actions, data points, and more. This translates to roughly 800 VMAD-style permission combinations. Further, security groups were customizable per-installation. So an ADMIN at one site might be a SYSADMIN at another—or, even if the names are the same, the permissions for the ADMIN groups at each site might be just slightly different.

This immediately ruled out any baked-in authorization feature. I couldn’t use role-based and policy-based authorization, because these rely on roles or policies to be named in a standard fashion, and for that I had zero guarantee.

Claims-based authorization was likely out. Stuffing the required data into claims data itself didn’t appeal to me. Neither did having to write out the requirements for every possible VMAD permission needed.

Fortunately, there was one constant across all this: because of the way the permission data was stored, the index of the permission would never change. So the ability to “view(44)” meant the same no matter what configurations you made.

So I decided my end goal would be simple: slap a custom authorize attribute on the endpoints that need one, and then move on. It would look like this1:

[CanView(44)]

The Solution

In the end I needed to implement my own IAuthorizationProvider, along with custom attributes and an in-memory cache storing configured security information.

I’ll show some examples for a theoretical “CanView” requirement, assuming we’re implementing a classic VMAD permission scheme with the structure I outlined above.2

Defining an Authorize Attribute

We’ll need to start with the authorization attribute first. This includes the IAuthorizationRequirement as well as a new attribute implementation.

public class CanViewRequirement : IAuthorizationRequirement
{
  public int Index { get; }

  public CanViewRequirement(int index)
  {
    Index = index;
  }
}

[AttributeUsage(AttributeTargets.Class | AttributeTargets.Method, AllowMultiple = true)]
internal class CanViewAttribute : AuthorizeAttribute
{
  const string POLICY_PREFIX = "CanView";
  
  public int Index
  {
    get
    {
      if (int.TryParse(Policy.Substring(POLICY_PREFIX.Length), out var index))
      {
        return index;
      }
      return default;
    }
    set
    {
      Policy = $"{POLICY_PREFIX}{value}";
    }
  }

  public CanViewAttribute(int index)
  {
    Index = index;
  }
}

internal class CanViewAuthorizationHandler : AuthorizationHandler<CanViewRequirement>
{
  private readonly IServiceProvider Services;

  public CanViewAuthorizationHandler(IServiceProvider services)
  {
    Services = services;
  }

  protected override async Task HandleRequirementAsync(AuthorizationHandlerContext context, CanViewRequirement requirement)
  {
    if (!context.User.Identity.IsAuthenticated)
    {
      return;
    }

    SecurityGroup security;
    using (var scope = Services.CreateScope())
    {
      var securityService = scope.ServiceProvider.GetRequiredService<MySecurityGroupService>();
      security = await securityService.GetSecurityGroupInfoAsync(context.User).ConfigureAwait(false);
    }

    if (security.CanView(requirement.Index))
    {
      context.Succeed(requirement);
    }
    else
    {
      // reject and log the request accordingly
    }

    return;
  }
}

Okay, there’s a bit going on here. First, we create a class that implements the IAuthorizationRequirement interface. The CanViewRequirement simply holds the index of the permission in our data, and implements that interface so we can use it for our AuthorizationHandler down below in HandleRequirementsAsync.

In HandleRequirementsAsync, we check an in-memory cache holding the security groups to see if the calling user’s security group does indeed have the requested permission. If so, context.Succeed(requirement) allows the request through—otherwise, we log the failed request and it’s rejected by default.

The CanViewAttribute class simply lets me set all this up as defined above, by using an attribute on a method or endpoint like this: [CanView({index})]

A note about attributes

In C# attributes can be used for metadata and code extensions. They go above your method declaration and provide helpful documentation, often extending behavior in a standardized way. It’s helpful to think of attributes as wrappers around methods, especially in this case. If you look at a method like this:

[CanView(44)]
public async Task<IActionResult> GetFooAsync()
{
  // do things
  return Ok();
}

And then unbox it, it might look something like this (pseudocode):

public async Task<IActionResult> CanGetFooAsync(int index, GetFooAsync getMethod)
{
  if (authService.IsAllowed(CanView, index))
  {
    return await getMethod;
  }
  return Unauthorized();
}

public async Task<IActionResult> GetFooAsync() 
{ 
  // do things 
  return Ok(); 
}

The Authorization Provider

All the above is well and good, but none of it does anything on its own. We have to set up a policy provider for the right code to get called when the attribute is reached. For this, we need to implement IAuthorizationPolicyProvider:

internal class VmadPolicyProvider : IAuthorizationPolicyProvider
{
  const string POLICY_PREFIX_VIEW = "CanView";
  public DefaultAuthorizationPolicyProvider FallbackPolicyProvider { get; }

  public VmadPolicyProvider(IOptions<AuthorizationOptions> options)
  {
    FallbackPolicyProvider = new DefaultAuthorizationPolicyProvider(options);
  }

  public Task<AuthorizationPolicy> GetDefaultPolicyAsync() =>
    FallbackPolicyProvider.GetDefaultPolicyAsync();

  public Task<AuthorizationPolicy> GetFallbackPolicyAsync() => 
    FallbackPolicyProvider.GetFallbackPolicyAsync();

  public Task<AuthorizationPolicy> GetPolicyAsync(string policyName)
  {
    if (policyName.StartsWith(POLICY_PREFIX_VIEW, StringComparison.OrdinalIgnoreCase) &&
        int.TryParse(policyName.Substring(POLICY_PREFIX_VIEW.Length), out var index))
    {
      var policy = new AuthorizationPolicyBuilder(JwtBearerDefaults.AuthenticationScheme);
      policy.AddRequirements(new CanViewRequirement(index));
      return Task.FromResult(policy.Build());
    }

    return FallbackPolicyProvider.GetPolicyAsync(policyName);
  }
}

All this is a semi-fancy way to generate the policies we need on an as-needed basis. Instead of hardcoding every CanViewRequirement possibility from 1 to 800, these are built for us by the attributes and requirements as we go. The interface also specifies that we add a default and fallback policy provider, from which I simply grabbed the defaults from the default, created in the class’s constructor.3

This is the ultimate goal of the code: do the work once, and use it everywhere. If we wanted to extend or refine details behind our CanView security, that is only done in one place.

Plugging it All In

Since this is .Net Core 3, we’re relying on dependency injection to keep things afloat. So we need to add services for everything we’re using here:

services.AddSingleton<IAuthorizationHandler, CanViewAuthorizationHandler>();
services.AddSingleton<IAuthorizationPolicyProvider, VmadPolicyProvider>();
services.AddAuthorization();

This tells the software that we’re using some custom authorization handlers and policy providers and points it to their definitions.

After this, using custom authorization attributes for our endpoints is a breeze. With just one line, we can narrow access to a single flag in the database out of thousands. Extending this would likewise be a breeze. Definitely easier than defining every single one manually, or crossing our fingers and hoping a security group name doesn’t change!

Wrapping Up

This may or may not be the best way to solve this particular problem. But we analyzed the trade-offs and made a calculated decision. If you were to go through and comment the code above with the intentions behind it all, I personally believe it would be easier for a new developer to hop on and get going than the alternatives. While complexity has to go somewhere, it’s better for these types of abstractions to have a gentle curve. Let someone care about the details only if they need to.

2020: Year in Review

I don’t generally agree with the way some services do their year-end reviews, like Spotify who does theirs at the beginning of December. The year’s not over yet – there’s still a whole month left to go! Typically I’d wait until January to really start thinking about the last year, but since it’s 2020 and I’ve been on vacation for a few weeks I’ve had some extra time to stew.

This year I went through several periods of idleness, though not inactivity, punctuated by a few bursts of productivity. I didn’t write nearly as much as a normal year, but I did take back up photography. I programmed some, but not as much as I’d have liked. And I watched a ton of movies.

Writing

Tracking my Progress

I keep a spreadsheet where each tab represents a year in writing. Over the years I’ve added or removed columns but it’s remained fairly consistent in its use. Although Scrivener does keep track of your progress over time, this is just on a per-project basis, and I like to have a broader view of things.

work tracker

I’ve started and restarted projects to turn this into a little app, similar to the NaNoWriMo tracker: goal tracking, project management, progress reports. Sometimes it has some social features, sometimes it’s desktop app, sometimes it’s just a command line interface. I’ve done this so often now that it’s basically become how I evaluate new programming languages or frameworks.

But no matter how I dress it up, or how refined I build my user interface, I still just come back to the spreadsheet. Apps introduce complexity. A spreadsheet is as simple and dumb as you can get. Very little is as useful as a plain spreadsheet.

This Year’s Word Count

word count progess

I think it’s obvious what happened here, at least in that first long horizontal line. But I’ll explain a little.

In the beginning of the year we moved to the city. Late last year I started a job that was 100% remote, and living in the suburbs was not cutting it for me. A little too much ennui, there. The hope was that living smack dab in the middle of the city would alleviate some of the problems working from home introduces.

And for the first month things were great! City life was awesome! Then the lockdowns came. That was okay, because at least outside my window wasn’t a lawn and another lawn and another lawn and endless quiet. Even under the lockdowns, there was still life outside my window.

But, it became difficult to keep up with things like writing or programming in my free time or doing very much at all, really. Being productive during a pandemic just wasn’t a priority. I had to reassess what it meant to me to be productive, or if I needed to be productive at all in order to feel satisfied with how I spent my time. The short answer was, I didn’t need to be productive; I just needed to be.

I’ve always written for myself more than anything else. I rarely share what I write, although I do sometimes talk about it. While I do think it would be nice to someday be published traditionally, that’s not the only goal and it’s not why I write. The problem here is that I didn’t really think much about the exact reasons why I write. It’s a compulsion, more than anything. Stories or premises appear in my head and I have to write them down.

Because of all this I think it was inevitable that I grew unhappy with my writing in general. The lockdowns and the stresses of the pandemic, of the protests that marched by my apartment, of everything else that happened, these all were handy excuses for taking a long break and really evaluating my reasons for doing what I do. The joy in writing had been evaporating, and it took all this for me to think about it deeply.

So these long horizontal lines are my time doing a little soul-searching, doing workshop exercises, trying to re-find and refine my reasons for writing as well as my craft.

Once I started back up, I think I made good pace! Even an emergency appendectomy didn’t stop my progress once I started. Minus the two days in the hospital.

Programming

All in all, I wrote nearly as many lines of code as I did words this year. Generally LOC are not a good metric for progress, but I thought this was an interesting metric, anyway. Maybe this is another reason I felt a little burnt out sometimes: 40,000 words written, and over 30,000 lines of code in a year! I guess I have been busy.

Photography

Earlier this year I bought a used Nikon D3 and have tried to revive and maintain my interest in photography.

I’ve learned, and re-learned, a few important things with this camera:

One, photography as a skill is not like riding a bike, and you really need to keep up at it to keep your eye. Otherwise you end up starting over, redeveloping skills you used to have and rebuilding muscle memory. This is frustrating and discouraging and the worst part of picking up any hobby after a long absence.

Two, post-processing continues to be the maker and breaker of photos. Few photos are perfect straight out of the camera. With a little extra care, many photos that at first seem unspectacular can really grow into something special.

Three, it’s just as important to look at photos as it is to take photos. This helps you figure out the things you like and gives you goals for styles to develop on your own.

Four, don’t pay attention to Instagram. It’s a toxic black hole of chasing likes, thumbs-up emojis, and pointless trends. Social media continues to be cancer to creative endeavors. I spent about a month maintaining an active photography account before I got tired of that rat race and moved on.

Movies

I watched over 150 movies this year! It doesn’t take much active engagement to just watch movies, though. I did semi-participate in Hooptober, where I watched a horror movie every day through October. This gave me the opportunity to fill in a lot of gaps in my knowledge of the horror canon. I love horror movies, but it’s taken me until now, my 29th year of life, to finally watch the Night of the Living Dead, which may have been made in the 1960s but feels as modern as anything released in the past year.

In Review

It’s easy to review the past year in terms of numbers when you’re a little metrics-obsessed. I track everything from the words I write to the music I listen to to the movies I watch.

Even so, there were long stretches of the year where I “did” nothing at all: nothing got tracked. This kind of unplugging, for me, really helped me keep my head on straight as it felt like things were getting more and more out of hand in the world around me. As spooky news became a pandemic, and protests turned to riots and businesses shuttered and never took down the plywood over their windows, as the election ramped up and petered out, as long as focused on my own little corner of the world and doing what good I could with what I had, I managed to stay okay.

From WordPress to Pelican and Back to WordPress

This blog started out built on WordPress. For some reasons that made sense to me at the time, last year I moved everything over to a platform called Pelican.

Pelican is a static site generator that takes plain text input and converts it to web pages.  This is great for a variety of reasons, especially if you like writing in Markdown or want to keep your blog in some kind of source control.

Both of those sounded pretty neat to me and I got tired of WordPress, so I made the jump. I downloaded my WordPress installation, ran a script to convert its posts to Markdown, then tinkered with a few themes and plugins until I had something that looked fairly close to the original.

For a time, things were good. I enjoyed writing in Markdown. It took me back to the “old days” of plain text, scratching out the words without care for how they might appear. There was a kind of magic to the process. Writing, then waiting, then finally seeing the article published. All it took was Notepad++ and a command line and baby, I had a blog going.

Then I took a break. Life got in the way. I finally returned to add new posts, but when it came time to publish I actually forgot for a moment what the damn tool was even called. Then I forgot the command line options. Then I forgot where the output went. Most recently, I tried linking one article to another and this caused the generator to throw new errors. I googled around for about ten minutes before thinking, “I don’t have time for this.”

So instead of fixing that problem I spent an evening restoring WordPress. If you’re curious, here’s how to do it like I did:

  • Create a brand new WordPress installation
  • Google “export pelican to wordpress”, then wonder if you have your old backup still
  • Find the backup *.tar.gz file and poke around its contents
  • Upload everything over FTP
  • Play Master of Orion while you wait for 3,500+ files to upload
  • Update wp-config to point to the new database
  • Drop all the tables and recreate them with the old WordPress DB table contents
  • Find the functions.php file for your theme and add a few lines of code to programmatically update all mentions of the old URL to the new URL
  • Refresh the login page about 5 times
  • Log in and update WordPress
  • Update hyperlinks in posts
  • Copy-paste the Pelican posts into WordPress posts

And voila! It’s like I never left WordPress! Except for all the times I linked to the old old blog, then destroyed them by moving to Pelican, and then destroyed those links by moving again over here. One day I’ll write a redirect so folks following those old links will come here, instead. Another day.

Mang 1.0 is Released

As part of my ongoing work with SCOREDIT, I’ve been working on porting some old code to a new utility for use in my newer project as well as a few other things I’ve got going on. To that end, I released Mang (Markov Name Generator), a tool for generating names and words.

Sigh… A procrastinator’s work is never done…

Mang uses Markov chains to generate output that is similar to, but not the same as, a given set of inputs. This means if you feed it a dictionary of English words, it will output words that look like English but are just a little bit off. This is great for building up conlangs, creating NPC names for your tabletop games, etc.

The library comes “batteries included,” meaning it already has a small collection of names you can use for name generation. The readme has more details on this. You can also browse the source to see what all is available.

I’ve had the old Mang lying around for a long time gathering dust. Built with WPF, it was serviceable and the output was okay. But I wanted to extract the Markov and name generation code and make it into something more portable. I was also frequently unhappy with the output, hitting the refresh button forever until I found something inspiring.

The new Mang has a few improvements to word generation to ensure no gibberish is put out. The library itself is tiny – just a few files. And its interface is small and foolproof.

To prove all these things to myself I plugged it into SCOREDIT today and got to generating:

Mang used with SCOREDIT to generate words

As you can see, it’s not all perfect, but there’s a few good ones in there to serve as starting points. In the future I plan to extend the generation capabilities to come up with more “realistic” output, but that’s another blog post.

Head on over to the repo to check it out!

SCRL: Week 06

After motivation petered off, it was easy to rationalize not doing anything on this project. The excuses rolled in: what’s the point, it will never make money; no one will play it; making games fun is hard. Etc.

Times like these, I remind myself when motivation wanes, it’s usually because of a good reason. I’d hit a wall, and it had nothing to do with the excuses I was making. After some thought and false starts, I finally found out what was happening: working on SCRL was no longer fun.

Above all else this project is supposed to be fun for me. It’s a side project for a game that likely no one will ever play but me. So why not make it fun just for me? And why not work on the things that are fun and interesting to me? With that in mind, I thought about what I dreaded doing the most for the project, then thought of a way to make it fun for myself to do it.

Enter… SCOREDIT! (I am not good at naming things.)

SCOREDIT is a GUI application to add and edit game data, from NPCs to game regions (dungeons and towns) to treasure drops. A few semi-difficult decisions were made in the process of setting this up:

  • The GUI will be written in WPF.
  • The CSV files are getting replaced with a SQLite database.

I went with WPF because I know it and can move relatively quickly with it. SQLite (along with Dapper) will make it so I worry less about how I’m serializing/deserializing data and more about the data itself. Plus, most of the data does require some kind of relational integrity, such as monsters referencing aspects, treasure classes, and other monsters. Using a proper mini-database will make it harder for me to shoot myself in the foot.

a screenshot of SCOREDIT

Nothing pretty, but that’s not the goal here. So far it’s purely UI. I’m using this as a kind of mockup phase, where as I think of attributes or pieces of data to add, I add the boxes for them. Then, once I’m done, I’ll write up the database to back it. After that, I’ll rewire SCORLIB to talk to the database instead of the CSV files.

So far, for the screen above what I like the most is the auto-generation of stats. Of course, this could be done at runtime, but I like to tweak things beforehand and I don’t want to rely too much on in-game random generation for things like this. The plan is to choose a monster type — is it a tank? magic user? a speed demon? — and adjust its stat distribution accordingly. When I was still staring at the CSV files, manually choosing and writing out stats was one of the things I dreaded most.

This UI is bound to change quite a bit before it’s finished.

SCRL: Week 05

2020-03-28

Wow. Already been a month since I started working on this project. Kind of crazy how quickly that time just… disappeared.

Anyway, today I started working on some random generation utilities. Not a lot of this was new work — I’ve already done 90% of that job in SCORLIB. My factories are serving me well, so far. But, in order to actually test and make sure the random generation is producing sensible results — for some definition of sensible, I guess — I needed a way to hammer generation without loading up game levels.

Enter SCORLIB CMD:

cmd line output

(Naming things is hard.)

Essentially, I wanted a command line utility I could use to generate the things I tell it to generate. I want to be able to inspect the output of this generation in a game-agnostic way just to see how things work and make sense, because this is how I think about things. This is not a way to test game balance (though in the future it might get some features like that), nor to test anything specifically game related at all.

Say I want to see what treasure a gordix1 drops:

command line output

Or I want to see a full list of possible drops:

command line output

This is a very simply use case; the screenshots are just illustrative. Because this game is going to be fairly loot-driven, I need to iron out how “good” the loot drops themselves feel. I think this is the first step to making sure it’s all right. Once I have a decent amount of Things for monsters to drop, I can throw them into the game and then run around and test there. …after I implement the inventory system…

2020-03-29

Cleaned up SCORLIB a little and had it load some item properties that weren’t being read from data files. Then I started work on a proper Inventory screen. Not much to show yet – still rough work, and I think I need to step away from the code and use a pen and paper to sketch possible layouts before I do any more work.

2020-03-30

I spent 2 hours modding Fallout 4 today. So, in other words, I was not productive at all.

2020-04-01

Brain is feeling fried this evening. Tinkered with the Inventory screen some more. Decided to probably start off from something like the ADOM inventory screen, more or less, and go from there. Figured they got something good going. I got just a little bit done as far as drawing everything up properly – not enough to show or feel productive about.

SCRL: Weeks 03 & 04

2020-03-15

Spent some time writing up another blog post on how I want Aspects and similarities to work. That post will probably go up later this week. After writing, I went and sketched up some code to calculate the “similarity index” between two monsters, and made a little command line application that I could use to test SCORLIB components and run through the code without having to run the game and test there. This made it very easy to compare a few different approaches to calculating this index, which I go over in that blog post.

2020-03-19

It’s been a busy week and I haven’t had any time to work on this project, except for some thinking here and there. The last time I started working on this I started to implement loading game data from SCORLIB. This involved parsing flat files into game objects and setting up factories that I would use to retrieve new objects / mobs / items / etc. as needed. This all works really well – I even have loot generation going, very similar to Diablo’s mostly because I straight up stole the Diablo II file format and style of loot / mob generation.

However, I came across a snag: I want SCORLIB to be as “pure” as possible. Meaning, I don’t want to sully the library with implementation details for whatever game “front-end” is using it. So, even though this game is a roguelike and uses ASCII graphics, I still might want to use SCORLIB with another project later. The problem here is I still need somewhere to store graphics-related metadata so my factories can function without huge gobs of code gluing them together and slapping graphics on things. I think what I’ll end up doing is adding a second set of metadata files to SCORLIB in their own folder / namespace and joining the graphics data (colors, the character glyphs representing entities, etc.) with game data. This way these graphics settings are still separate, but also still loaded from disk instead of hard coded.

2020-03-24

Decided to combine two weeks of dev journaling because… well, I didn’t do much last week.

Today I got a good portion of the work done for my monster factory to a) load in all the game data from SCORLIB from disk and b) load in all Monogame-specific data, also from disk. So at “design time” in my tab-delimited text file I can set all required display settings for my in-game objects, divorced from the logic behind it all (stats and other rules). If my parser somehow fails to conver the string to a proper color / glyph representation (like if I fat-finger while typing) then it gracefully falls back to hot-pink foreground, blue background, and ‘?’ as a glyph.

Because all these objects are relatively small in the grand scheme of things, I just hoover everything up into memory when the game starts, so when I need a new instance of something I request it from the factory. Like so many decisions before this, if it does become a problem, I will revisit it — but I want to move forward adding things to the game without spending too much time right now on what may be premature optimization.

The factory stuff isn’t done, but the loading from disk is 90% done. Probably tomorrow I’ll finish the monster factory and start generating monsters randomly for real!

2020-03-25

It is done!

Monsters, both their stats and display info, are drawn from disk into little factories where they can get pumped out onto maps at will. Because of the number of properties and objects that live inside the Monster class, instead of trying to get clever with reflection or MemberwiseClone or any number of things, I just sucked it up and wrote out all the assignments needed for cloning operations. It took two excruciatingly long minutes to do, but in the end it was far easier to write, test, and look at than any other code would have been — and it runs faster, too. Imagine that.

Next it’s time to extend the MapFactory to randomly assign the next map type, then assign that map a Deity type. I think I want the map factory methods to populate the maps with their creatures, as well. I’m not sure what’s next, but there’s a few options:

  • Spawning boss monsters
  • Spawning monsters in groups based on their monstats metadata
  • Implementing treasure classes for loot

Week(s) In Review

Can’t always have productive weeks. When your day job is also programming, sometimes it’s hard to motivate yourself to do more of the same during your free time. In any case, I got a few key things done these past couple weeks, and now things are starting to get “hard”. Designing and implementing systems is easy, but making them playable and fun? That’s the challenge.