martes, 2 de abril de 2019

What I Got Done In A Year With My Leisure Time

Yes, this is a selfish post that will probably help me more than anyone else that reads it, but it's worthwhile to reflect every so often on what you've accomplished. The beginning of a new year is as good a time as any to do this reflection and look ahead at the coming year to see what you want to change, improve, or add to what you did before. So that's what I'll be doing in this post, looking back at what I've done, and using that to inform how I want to approach the year ahead. I'm going to limit this introspection to what I do in my personal leisure time because it's the easiest part of my life to tally up like this, and, well, reasons.


Blog Posts


With this being a blog, I happened to write a few blog posts over the year. I've reduced my frequency of posting in the last couple years, and over the course of 2018 I maintained a rate of one post every three weeks, totaling 18 posts over the year. I won't list them all here, just some of the highlights.

I finished up the last half of my series on Simple Game Algorithms With Color Walk with seven more posts, and I was pretty happy with how that series turned out. I wrote six Book Face-Off reviews of six pairs of books, with the most-viewed review post being on the two Seven Programming Languages in Seven Weeks books that I thoroughly enjoyed working through. I really enjoy writing that style of review because I always want to know how books compare to each other instead of judging them in isolation, and I often find that lacking in other reviews. Finally, I wrote five posts about various other topics, including one about a simple retirement savings model in Python that garnered the most views of all of last year's posts.

I'm expecting to keep up the same rate of posting for the next year, so I should end up with another 18 posts by the end of 2019. I would also expect most of those posts to be face-off reviews for reasons you'll see in a minute, but I've got an idea for a rather fun series that I might start up near the end of the year. All in all, I enjoy writing and continue to see benefits to keeping up this blog in spite of blogs being mostly dead in the age of social media. I'll keep writing down my thoughts, if only for my own sake as much as anything else.

Technical Books


Looking back, I read a lot of books last year, including one doozy of an undertaking, Introduction to Algorithms, that took me six months to get through! In total it ended up being 18 books, (coincidentally the same as the number of posts I did) and I'll group them here into the good, the bad, and the tedious with a little summary and links to reviews for the ones that have been posted. The rest are still pending.

The Good
  • Seven Programming Languages in Seven Weeks - An excellent whirlwind tour of seven instructive and very different programming languages. This book was mind-opening and mind-blowing.
  • Seven More Programming Languages in Seven Weeks - Like its predecessor, but focusing on seven relatively new languages. I had twice the fun by reading about twice the languages.
  • The Seasoned Schemer - A whimsical romp through Scheme and the theory of computation that builds on The Little Schemer. It uses a Socratic dialog format to teach in an eccentric and engaging way.
  • The Reasoned Schemer - Same format as The Seasoned Schemer, but not quite as zany. This book develops a logic programming language that later appeared in the wild as miniKanren built on top of Clojure.
  • Confident Ruby - Learn how to write clear Ruby code with purpose, and do it with an easy, enjoyable read.
  • Breaking Windows - Remember when Microsoft was king and the Justice Department decided that wasn't a great thing, but in the mean time Microsoft nearly missed the Internet and completely whiffed on mobile, making the whole argument irrelevant? I had fun reliving that whole saga with this book.
  • Showstopper! - It's the story of how Windows NT was made. After reading it, I certainly wouldn't have wanted to participate in such an endeavor, but it was a wild story.
  • CoffeeScript - This is a quick, no-nonsense guide to CoffeeScript, a nice, possibly obsolete enhancement to JavaScript. The online documentation is sufficient, but it's nice to have it all laid out in a book like this. 
  • The Hidden Reality - I love reading popular physics books every once in a while. This one is about all the different ways parallel universes could exist. Very well written and accessible to anyone with some rudimentary physics knowledge.
  • Parallel Worlds - Like The Hidden Reality, this is another popular physics book about parallel universes. It's hard to decide which one is better. I enjoyed them both.
  • Python Data Science Handbook - A solid introductory book on using Python with pandas and scikit-learn to do data munging and analysis. I preferred it to the one I paired it with in an upcoming Tech Book Face-Off, Python for Data Analysis.
The Bad
  • Simplifying JavaScript - I felt like I was being talked down to through this whole book. Simple things were discussed ad nauseum and more complex things were glossed over. I didn't find it useful.
  • Python for Data Analysis - This is primarily a pandas reference, and the online documentation is much better than slogging through this book.
  • Metaprogramming Ruby 2 - I found the style and tone of this book to be quite annoying, and the content is certainly available in other, much better books.
  • Patterns of Software - Supposedly about software development insights, this book is full of irrelevant fluff, inane diatribes, and tiresome career stories. I should have passed after the first chapter.
The Tedious
  • Introduction to Algorithms - One of the classic algorithms texts, but unless you're going into a career in Computer Science, it's probably not worth sweating through this tome. If I ever pick up another algorithms text, it will be one geared more towards implementation than theory.
  • Linear Algebra and Differential Equations - It would have been good if it wasn't riddled with typos, bad definitions, and outright errors. I was constantly needing to correct what I was reading, but I suppose finding all of those errors gave me confidence that I understood the material.
  • The New Turing Omnibus - More of a collection of introductory blog posts than a cohesive book on computer science topics. This was probably the worst book I read last year—both bad and tedious.

Out of the 18 books, 11 of them were good to excellent, so on the whole, I would count that as a success. I'm hoping to be still more selective in the coming year, and at the same time bump up the number of tech books I read. My goal is 22, and I'm really looking forward to all of them. I think I've got some great ones on the list. While it seems like I'll be cramming four more books into the year, I won't be working through a 1200 page monster or a math book rife with errors. Those two books took way too much time without the corresponding benefit. I'm looking to change that with a better selection of books geared towards more enjoyment while helping to round out my development as a programmer. Hey, I'm doing this during my leisure time. I don't need to suffer.

Novels


Even with all of the technical books I read, I still found time to read quite a few novels for pure pleasure. The secret to fitting these in to busy days is listening to audiobooks during the daily commute. While I prefer curling up on the couch and reading a novel for hours, there's not always time for that, but I always have 20-30 minutes in the car twice a day. That adds up to a fair number of books over the year, and I've listed the ones I got through below, ranked in order of how much I liked them.
  • Seveneves - An excellent book by the great Sci-Fi writer, Neal Stephenson about what the human race does to survive the aftermath of the Moon exploding into seven pieces.
  • Insomnia - Stephen King does an incredible job painting the scenes of this book in the reader's mind. As the title says, it's about insomnia, but of course it's more than that.
  • The Talisman - Another great fantasy thriller by Stephen King, this time teaming up with Peter Straub. It was a fascinating journey through the vivid world of the Territories that they created.
  • The Defenders of Magic Trilogy - I've always loved the Dragonlance series, but I haven't read anything from the series in many years. This trilogy by Mary Kirchoff was an enjoyable return to the fantasy world of Krynn, full of magic and dragons and other fantastical creatures.
  • Foundation, Foundation and Empire, The Second Foundation - The first three books of the classic Sci-Fi series by Isaac Asimov, this series took me a while to get into because I didn't like the contrived feeling of the first book. Things got much more interesting when the Mule entered the picture in the second book, though, and I was really getting interested by the third book. I'll have to finish off this series soon.
  • A Wrinkle in Time - This is a fun, whimsical children's fantasy book by Madeleine L'Engle about an eccentric group of kids that go off in search of their lost father. I had never read this as a kid, and I was amazed at the vocabulary level for a children's book. 
  • American Gods - Neil Gaiman has an absolutely astounding imagination, and boy can he write. I've liked everything I've read of his, although I would rank this book near the bottom of the list. It was still good, but it didn't move me to want to keep reading like his other works.
  • The Dhamon Saga Trilogy - I enjoyed the return to the Dragonlance series so much with The Defenders of Magic that I tried for another trip with this trilogy by Jean Rabe. Unfortunately, it was not nearly as good. The characters started out as completely unlikable jerks that pretty much ended up the same way by the end. The only character I wanted to see survive was the draconian.
  • The Bourne Supremacy - I didn't particularly enjoy The Bourne Identity by Robert Ludlum, but I was hoping it would improve with this second book in the trilogy. Unfortunately, it didn't. I could never decide if it was trying to be a romance or a spy thriller, and it was poorly written in either case.
  • The Bourne Ultimatum - By now I just wanted to see what would happen by the end of the story, so I resigned to listening to one more installment of this bad romance/thriller. I shouldn't have bothered. The movies were quite different than the books, and much better.
Now I'm into The Way of Kings by Brandon Sanderson, and it's turning out to be an excellent fantasy book about a different world where special people can channel a power called stormlight. The dialog, politics, and character development are proving to be fascinating, but I've got a long way to go in this long book and even longer trilogy. I'm hoping to make my way through this and many more novels in the coming year. Last year I read a fair number of books from authors I had read before—King, Gaiman, Rabe, and Ludlum—so my goal this year is to read as many new authors as I can and expand my horizons. Sanderson is a good start.

Video Games & Movies


Regardless of how it may seem, I don't spend all of my leisure time reading and writing. I did manage to spend some time playing video games and watching movies. The movies are primarily for date nights with my wife, so they're too numerous to list here. I'll just say that Thor: Ragnarok and Deadpool 2 are pretty much tied for the best movie we saw last year.

I love playing LEGO games with my kids on the weekends, and find it's a great way to relax, solve some puzzles, and laugh at movie spoofs with them. We've at least started a number of new-ish LEGO games, including The LEGO Movie, Marvel Super Heroes, Jurassic World, LEGO City, The Hobbit, and Batman 3: Beyond Gotham. Every game has its unique mechanics and challenges, and I can always depend on them to be child-appropriate. I'm sure we'll play plenty of new ones this year, as there's a half-dozen more we haven't started, and they're always coming out with more.

I also squeaked in one game for myself with Final Fantasy XIII-2. (I know it's over 5 years old now, but I'm way behind on my game backlog. Give me a break!) I've always been a fan of the Final Fantasy franchise, partly because every story is completely unique, and partly because I'm fascinated by the new RPG mechanics in each game. In XIII-2 the complexity of the mechanics center around taming the different monsters in the game, and how best to upgrade and infuse the growing collection of monsters with their vast array of special abilities. I enjoy trying to figure out the shortest way to get to the most powerful party of monsters and then wipe the floor with the rest of the enemies in the game.

I'm hoping to have a bit more time this year to play more than one game. It's a great way to relax, and I've got so many options to choose from.

The Year Ahead


Looking back at this list, it's amazing what I got done last year, mostly within a couple hours a night. Looking at the year ahead, I want to stick to another 18 blog posts to keep up with my writing practice. I'm hoping to bump up my technical reading a bit to 22 books, although they'll be easier and shorter than some of the ones I tackled last year so I'm expecting to have a bit more time for other things as well. I'll likely read a few more novels with that extra time, maybe play an extra video game, and I'd like to pick up the guitar again.

I feel like the coming year will be somewhat of a wrapping up of the intense studying of a wide range of programming topics I've been pursuing. There will definitely be other books beyond those, but I'm finally reaching the point where I'll have read most of the major technical books that I intended to work through. If you know where you've been, it's easier to know where you want to go. That clarity provides the feeling of control and mental focus to keep making progress towards your goals instead of drifting from one day to the next. I'm looking forward to those accomplishments, and I'm interested to see what new subjects will come into view throughout the year.

The Complexity Fallacy

It is easy to think that the player sees all of the complexity you put into a game, but nothing could be further from the truth. A game's complexity is basically meaningless when it comes to the end experience. All that matters is what the player actually perceives. 

Brian Upton once told me the following anecdote about a game that he got pitched to him.

The game presented to him was a space sim where the player took on the role of a space pirate. A big part of the pitch was the virtual economy that the game had. It determined what sort of goods that planets needed, what the prices of various things would be and so forth. In turn this then determined the trading routes that ships would take and what sort of cargo you were most likely to find on them. This was a really complicated system and I guess they planned on devoting quite a bit of development time for it.

Sounds cool, right?

Problem was that none of this complexity was really apparent to the player. The only feedback that the player got from the whole system just boiled down to what sort of ships and cargo they would be encountering. From this meager data it was impossible for the player to get any sort of insight into underlying systems. If all of that system was replaced with a random number generator, the player wouldn't notice. So in essence, all of this complexity was a waste.

The reason something like this happens is quite easy to see when viewed through the lense of the SSM Framework. In this framework we divide the game into three separate spaces: system, story and a mental model. Something like the virtual economy would go into to the system space. But the problem is that these systems would never end up in the player's mental model. Understanding how this works is a fundamental, perhaps the single most important, part of the game design. The player doesn't play a game based on what happens in the computer, they play it based on what happens in their head. Any feature that doesn't have a mental representation might as well not exist.

Tynan Sylvester, who is currently working on the popular Rimworld, has a great article that addresses this very issue.
In play, the Game Model is irrelevant. Players can't perceive it directly. They can only perceive the Player Model in their minds. That's where the stories are told. That's where dilemmas are resolved. So the Game Model we create is just a pathway through which we create the Player Model in the player's mind.  
The Player Model Principle indicates a source of risk. Namely, anything in the Game Model that doesn't copy into the Player Model is worthless. That's what happened with the ecologies in Ultima Online and BioShock. They didn't enter the Player Model and so degraded into noise. This is a fairly obvious risk and is common in game design – all designers have seen players not understand a piece of their game.
[...]
What we want to do is create systems that are smaller and simpler than these giant hairballs, yet have more interesting, comprehensible interactions than simple systems like orbiting planets. What we really want is not a system that is complex, but a system that is story-rich. 
This is coming from a developer that is developing a hardcore simulation game. If it this sort of thinking applies to that genre then you can be sure that it applies to the entirety of game development.

Adding a feature is not about adding art and systems. It about is adding content that when played with will create a certain mental model in the player's head. In this sense, it's quite a bit like being a stage magician. Just like in games, the important thing in magic is not performing a hard trick, it is making the audience believe that you did one. In fact, many spectacular-seeming magic tricks have really boring explanations. But since the audience is never directly exposed to the method of implementation, it doesn't really matter. The only thing that matters is that the magician has a high chance of succeeding and what sort of reaction it gives the audience. Games works exactly like this too.

Most of the time, an increase in complexity is a bad thing. There is a higher chance of bugs, and it is less likely that you can maintain control of the system. This is why things like artificial neural networks doesn't have much use in games except for in very specific areas. While a neural net could accomplish a lot of cool things, robustness is more important. As a game developer you want to be able to intuit how a system works in order to properly use it in design. Go past a certain point of complexity and the output might as well be random. The KISS-approach is almost always the right one to take.

The simplest way of designing a system is, of course, not designing a system at all. It cannot get more simpler than zero. While this might sound a bit silly at first, it's a crucial part of game design. Last week I wrote about utilizing gaps of the imagination, which is really all about replacing something with nothing. The best way of understanding how to do this is to not see your features as concrete content, as complex machinery, but as experiences you want to evoke in the player. This is not just limited to fuzzy things like NPC emotions, but every single aspect of the game.

As I explained in the previous post, gaps have a lot of advantages over an explicit systemic implementation. Not only are they cheaper, but they are also more malleable and easier for the player to fit into their idiosyncratic view of the game and its virtual world. It is not always the solution, and sometimes the goal cannot be reached without having an actual system managing everything. The only way to make this decision is to look at games in the right way and understand that what matters is not the underlying machinery, but the mental states it gives rise to.

In games, if a tree falls and nobody hears it, it is a feature you should cut.

lunes, 1 de abril de 2019

Kriegsspiel: Big Trouble In Little Lardas

Two weeks ago, I participated in a week-long online Kriegsspiel run by Nick Skinner and Richard Clarke of Too Fat Lardies fame. With a total of 13 participants, two umpires and one observer, it was quite an undertaking. Set within a fictional "Imaginations" campaign of the "Lard War II," the players commanded either the forces of the Kingdom of Blue or the Red Republic. As Nick explained in the game:




Blue has invaded Red and achieved a breakthrough in the central South. Blue's armies are now pushing Northwards towards the crucial line of the NEMUNAS river and the strategically important city of LARDAS that stands at the confluence of two rivers. If they can push on, they will be threatening the capital city of REDBURG. Red forces though are well organised and aware of the danger. What will happen next?
For the participants, the planning portion was the meat and potatoes of the game. We started out by signing into a website and associated app called Discord. Nick set up a server and we joined it. We were immediately assigned to either the Blue or Red force rooms. From there we received our unit assignments and awaited orders. 

The Blue forces, of which I was a member, consisted of an airborne division. We had as players the commanding general, chief of staff, two para brigade commanders, a special reconnaissance squadron commander, a divisional artillery battalion commander and me. I was assigned as the commander of a brigade of glider troops.

Speaking of gliders. This film and the real events it represents may have provided may have provided some inspiration.
We confirmed that our organization and equipment was vaguely British. That meant I had three battalions of infantry, each with four companies of four platoons plus a support company. I was also assigned an ambulance company. This seemed a bad omen.

In the background, Nick was briefing the division commanding general and chief of staff with the division mission. A day or so later, after the CG and COS had some time to digest the mission, we received our unit missions. My mission in particular was to neutralize four forts that protect the southern flank of the city and conduct a follow on mission of clearing the two main routes to the city.

The small circles are my objectives, the forts. The larger circles are the landing zones for the gliders. The red areas? Anti-glider poles. To quote a certain British officer, "I'm thinking of a phrase that rhymes with 'plucking bell'." Umpire Nick Skinner took  an actual 1:50,000 map and appended new place names, grid line identifiers and other information.

Early in the plans process, I chose to land my initial assault gliders directly on the forts. I figured my best chance was to take the enemy completely by surprise and jump right on top, like at Eben Emael. I had limited resources to get my brigade on the ground. It would take three lifts over the course of two days to get my complete brigade into the battle area. Given my resources at hand, on the initial landings, I would have 20 platoons out of 48 on the ground. Not great odds, I thought. But I had to risk it. Who dares, wins, right?

Plans were set, then changed and changed again as the brigade commanders weighed options and made their cases with the CG and COS for why they should get resources. A feature of Discord that we found handy are voice chat rooms where members can talk via VOIP for planning, rock drills, etc. Blue had two conferences and we found them very beneficial. By the time we had our first conference, we had our plan largely in place and were discussing some of the finer points. The final conference was to make sure everybody had their plans finalized and ask final questions.

My set up for the day of battle. The cards have each lift marked on them with the units and target LZ. As the battle progressed, I put the markers on the map as needed. We didn't get past the first lift on Day 1, although we planned for four days.

The day of battle arrived. 
As time drew closer for us to climb in our imaginary planes and gliders, top level rooms were locked up and player-to-player communications stopped. We sat at our computers waiting for H-Hour. I received a message that I was on the ground at LZ Baker and could see paras taking heavy fire about a kilometer to the northeast. I could also see and here vicious combat in Fort 2, aka OBJ Grumpy. Then the various communication nets started going live in the form of restricted chat rooms in Discord.

My brigade net room was where I spoke with umpires to get reports from my battalions and request info from them. There was an "on the ground" room for commanders that were up on the division net. Finally there was a division HQ room for those who had established comms with the outside world. Receiving information, parsing it, confirming our own assumptions and then assessing it before putting it up in both the "on the ground" room and Division room was a significant challenge. Luckily, the game was set to last only three hours. 

During the game, we were mostly interacting with the umpires and relying on them for information. Issuing orders and requests for information from my imaginary subordinates. I then had to process that info and relay it to my in-game superiors. But only once our in-game communication nets were established! One of the para commanders didn't have comms because his radios got shot up on the DZ. He had to "walk" to where I was and then we could talk to each other and the had to use my "radios" to talk to higher.

Fort 1, OBJ Bashful was taken almost immediately with 30% casualties. Fort 2, OBJ Grumpy, fell only after receiving help from a platoon that had landed on Bashful. Fort 3, OBJ Dopey, was a see-saw battle and I tried mustering forces from Bashful and Grumpy to push it over the edge. Fort 4, OBJ Sleepy, only reported in once their ammo was all expended and the last holdouts were cornered in a bunker and calling "God save the King."

Enemy armored infantry and self-propelled guns had been spotted in the vicinity of Sleepy, so I called for air strikes on the fort with machine gun and cannon only, then follow up with bombs and rockets on the enemy vehicles. Imagine my surprise when I received the report that Sleepy had been destroyed from the air.

In the meantime, I was still trying to get enough forces scratched together to make a difference at Dopey to find it had fallen and was being evacuated, my troops being led away by the enemy. When I asked for clarification if it was Sleepy or Dopey, i was told, "No, it's Dopey, dopey!" Thanks, Rich.

Then the game ended. Luckily, our troops were wholly imaginary and our decisions didn't result in any real casualties. It was an exhilarating, exhausting, madcap, sobering, nervous, mind-blowing experience. I'm planning a podcast with Nick, Richard and the two force commanders. Stay tuned.

I will definitely be looking to do one of these for my J3 group and possibly for my fellow OCS instructors in the near future. Stay tuned for that, as well.