May 30, 2015

Using Data To Balance Your Game: Pony Clicker Analysis

The only thing more addicting than heroine are numbers that keep getting larger.

Incrementer and idle games are seemingly simplistic games where you wait or click to increase a counter, then use that counter to buy things to make the counter go up faster. Because of the compounding effects involved, these types of games inevitably turn into a study of growth rates and how different functions interact. Cookie Clicker is perhaps the most well-known, which employs an exponential growth curve for the costs of buildings that looks like this:
\[ Cost_n = Cost_0\cdot 1.15^n \]
Where $$Cost_0$$ is the initial cost of the building. Each building, however, has a fixed income, and so the entire game is literally the player trying to purchase upgrades and buildings to fight against an interminable exponential growth curve of the cost function. Almost every single feature added to Cookie Clicker is yet another way to battle the growth rate of the exponential function, delaying the plateauing of the CPS as long as possible. This includes the reset functionality, which grants heavenly chips that yield large CPS bonuses. However, no feature can compensate for the fact that the buildings do not have a sufficient growth rate to keep up with the exponential cost function, so you inevitably wind up in a dead end where it becomes almost impossible to buy anything in a reasonable amount of time regardless of player action.

Pony Clicker is based off Cookie Clicker, but takes a different approach. Instead of having set rates for each building, each building generates a number of smiles based on the number of ponies and friendships that you have, along with other buildings that "synergize" with that building. The more expensive buildings generate more smiles because they have a higher growth rate than the buildings below them. This makes the game extremely difficult to balance, because you only have equations and the cost curves to work with, instead of simply being able to set the per-building SPS. Furthermore, the SPS of a building continues to grow and change over the course of the game, further complicating the balance equation. Unfortunately, in the first version of the game, the growth rate of the end building exceeded the growth rate of the cost function, which resulted in immense end-game instability and all around unhappiness. To address balance problems in pony clicker, rather than simply throwing ideas at the wall and trying to play test them infinitely, I wrote a program that played the game for me. It uses a nearly optimal strategy of buying whatever the most efficient building is in terms of cost per +1 SPS increase. This is not a perfectly optimal strategy, which has to take into account how long the next building will need to take, but it was pretty close to how players tended to play.

Using this, I could analyze a game of pony clicker in terms of what the SPS looked like over time. My first graph was not very promising:



The SPS completely exploded and it was obviously terrible. To help me figure out what was going on, I included a graph of the optimal store purchases and the time until the next optimal purchase. My goal in terms of game experience was that no building would be left behind, and that there shouldn't be enormous gaps between purchases. I also wanted to make sure that the late game or the early game didn't take too long to get through.



In addition to this, I created a graph of the estimate SPS generation of each individual building, on a per-friendship basis. This helped compensate for the fact that the SPS changed as the game state itself changed, allowing me to ensure the SPS generation of any one building wasn't drastically out of whack with the others, and that it increased on a roughly linear scale.



This information was used to balance the game into a much more sane curve:



I then added upgrades to the main graph, and quickly learned that I was giving the player certain upgrades way too fast:



This was used to balance the upgrades and ensure they only gave a significant SPS increase when it was really needed (between expensive buildings, usually). The analysis page itself is available here, so you can look at the current state of pony clicker's growth curve.

These graphs might not be perfect, but they are incredibly helpful when you are trying to eliminate exponential explosions. If you got a value that spirals out of control, a graph will tell you immediately. It makes it very easy to quickly balance purchase prices, because you can adjust the prices and see how this affects the optimal gameplay curve. Pony Clicker had so many interacting equations it was basically the only way i could come up with a game that was even remotely balanced (although it still needs some work). It's a great example of how important rapid feedback is when designing something. If you can get immediate feedback on what changing something does, it makes the process of refining something much faster, which lets you do a better job of refining it. It also lets you experiment with things that would otherwise be way too complex to balance by hand.

May 14, 2015

Pony Clicker Postmortem

Never Again...
Cloud Hop here! Pony Clicker was intended to be a fun experiment in designing an HTML5 game. It was developed over a period of about 2 weeks, which was a lot longer than I had anticipated. Normally I build games using low level graphics APIs and highly optimized physics engines, so I wanted to try something that would be simple, where I could rely on HTML5 to do most of the work for me... right?

Wrong. The key thing I learned when designing Pony Clicker was that HTML is evil. If you are making just about anything even remotely interactive in HTML, I strongly recommend using the HTML5 canvas. Everything else will almost inevitably fall over. CSS animations simply aren't going to cut it, and the eccentricities of HTML rendering cause enormous problems with game interfaces. Save yourself the pain and just slap a giant canvas on the screen and render everything to it. Even with the known performance issues with the HTML5 canvas, it will probably still be faster than HTML5 anyway, except now you have much more control over what everything is doing.

I also managed to find a memory leak of sorts in Chrome's DOM renderer. For this reason, Pony Clicker will always take 550 MB of memory while actively using it, until the GC wakes up and actually does its job. The exact details of this are complicated, but the gist of it is that I can create a page that contains no javascript, only a <canvas> element and a <div> element below it with an :active effect, and by clicking on the div element that does absolutely nothing, I can make chrome allocate 20 megs of memory each time. It would be funny if it wasn't so horrifying. I'll write up a seperate blog for that issue.

In terms of game design, Pony Clicker is a more complex version of Cookie Clicker. In Cookie Clicker, each building simply gives you more cookies. That's it. In Pony Clicker, you construct a graph of relationships, and then buy buildings that give you smiles based on how many friends, ponies, or other buildings you have. It's basically Graph Theory Meets Growth Rates: The Game, where each successive building utilizes a function with an ever increasing growth rate. Thus, by the time you reach a limited factorial function, each later building is providing enormous numbers of smiles simply because of the generating function's explosive growth.

Predictably, this made balancing the game difficult. At first, I was excited, because I could start using all that crap I learned in Combinatorics and derive a bunch of equations to balance the game for me based on a few curves that I defined. Inevitably, this did not work. Either the equations were too complex to get reasonable solutions out of, or they simply didn't work, because I was relying heavily on heuristic functions to guess how many buildings would be owned at a given point. I ended up using a combination of functions that allowed me to predict the SPS of any building at any given time, and then used this to define the costs of all the buildings in terms of the cost curve of the friendships. Thus, everything in the game is keyed off the friendship cost curve, which can be modeled by a recurrence relation:
\[F_{n+1} = r F_n\]where r is the curve value (Pony Clicker uses a value of 1.6, because that's close to the golden ratio and it seemed to work nicely). This is a trivial linear recurrence relation, so we can get a closed form solution out of it:
\[F_n = F_0 r^n \]The same kind of curve is used for just about everything else in the game, including cost curves of the buildings. Cookie Clicker uses the same curve for all it's buildings, where $$r = 1.15$$. This stops working for Pony Clicker because the later buildings provide ever increasing amounts of smiles, by design. To compensate, the cost curve is much more aggressive for the later buildings. Initial costs were supposed to be chosen based on the number of friendships that would be bought at the time of the initial building price, but this kind of fell apart. However, it was still useful to key the cost off of the friendship curve, so I ended up with a really weird initial price array: [4,12,30,35,45,45,45,51,51,100]

To host the game, I used GitHub's pages, which means it's all being hosted out of a gh-pages branch in the github repo. I commit changes to the master branch, then do a git pull into the gh-pages branch and then git push to sync it with the master branch. So far this has required me to have the deployment branch checked out - if you know of a way to merge changes from one branch into another without cloning that branch, I'd love to know about it. Also, if you want to contribute to the game, with upgrade suggestions, more witty news articles, art, etc., feel free to either send me a message, or just submit a pull request on GitHub!

I used Visual Studio Code to write this project. It's intended for web development, and in fact is just a webpage being rendered in a container. It actually works pretty well for small projects, but once a file exceeds around 800-1000 lines of javascript, it's auto-complete is too busy compiling running around with its hair on fire to be of any real use, which is a shame. I'm kind of wondering why it was implemented as a webpage though. Perhaps to make a point? If they wanted to make the point "web apps are still slow as crap when they need to do anything nontrivial", I guess they succeeded.

Last but not least, I am a community guest at Everfree Northwest this year! If you're going to be there, be sure to say hi!

~ Cloud Hop

May 8, 2015

Am I Making The World A Better Place?

A while ago, I watched The Internet's Own Boy, a documentary about Aaron Swartz. It was immensely painful to learn about someone as amazing as he was, someone who seemed to look at the world in the same way I did, after he committed suicide. At 24 minutes, Aaron's brother says something that continues to stick with me.
"The way Aaron always saw it, is that programming is magic—you can accomplish these things that normal humans can't, by being able to program. So, if you had magical powers, would you use them for good, or to make you mountains of cash?" — Ben Swartz
From a young age, I recognized that I had an unfair advantage over my peers. My programming abilities ensured that I would be able to sail through life without ever having to worry about money. I was also aware of oppression. I recognized parallels between the intellectual bullying I was subjected to in middle school and the real world, where I saw powerful people abuse the advantages they had over their peers to make themselves rich at the expense of everyone else. I was told that life simply wasn't fair, and there's nothing you can do about it.

I said that I'd make life fair.

I realized that if someone used their advantage to make things more fair instead of less fair, they'd be able to make the world a better place. Furthermore, I had what Aaron called "magical powers". I already had an advantage. This mirrors Aaron Swartz's own epiphany about using software to do something about serious problems in the real world.
"I feel very strongly that it's not enough to just live in the world as it is and just take what you're given and follow the things that adults told you to do and that your parents told you to do and that society tells you to do. I think you should always be questioning, and take this very scientific attitude that everything you've learned is just provisional, that it's always open to recantation or refutation or questioning, and I think the same applies to society. Once I realized that there were real, serious problems, fundamental problems, that I could do something to address, I didn't see a way to forget that."— Aaron Swartz
Everything I've done since then has been an (occasionally misguided) attempt towards accomplishing this. My singular goal in life became maximizing my positive influence on the world. Of course, I am not Aaron Swartz, and I did not have access to an enormous fortune. This meant making sacrifices in the short-term so that I could pursue my dreams in the long-term, and hopefully have a lasting impact.

A year ago, that meant making a choice. I needed to pay the bills, and so I now make a six figure salary working for a large software company. I am not happy there, which confuses people who think I'm successful. They are mistaken; I am not making the world a better place yet, so I am not successful yet.

While it's easy to determine if you are improving people's lives right now, what about in the long-term? If you spend your entire life helping some kids in Africa versus starting a billion dollar corporation and then hiring thousands of people to help kids in Africa, what had more lasting impact? Trying to think about the future changes how you view things. Building an enormous company with a technology that helps a lot of people and then selling it for a billion dollars to a corporation that immediately proceeds to either shut it down or simply ruin it is short-term thinking. I love the Clock of the Long Now, because it mirrors my efforts to think far in the future, not just a few years. Will your actions have a positive effect on the world in ten years? Twenty? Fifty? How can you choose a path that will ripple across the sands of time, finding ways to help people long after you've died?

What is your legacy?

This is the question that drives me. How can I change the course of history for the better? How can I maximize my impact? Even if it's only by a fraction of an inch, with our combined efforts, we might one day get there.

...

I'm still at that nameless software corporation. I am still languishing in its depths, unable to work on anything that actually matters because of a particularly annoying non-compete agreement. I won't stay much longer, but now that I am on my last leg, I am beginning to wonder if I have perhaps already stayed too long. How much money do I need to save up? What is the optimal point of departure? Have I already missed it?

Am I still working towards making the world a better place, or am I simply making mountains of cash?

March 16, 2015

Is There A Commercial Open Source License?

"Any headline that ends in a question mark can be answered by the word 'No'." - Davis' law
Putting Commercial and Open-Source together is often considered an oxymoron. Part of this is caused by constant confusion between the terms Open-Source and Free Software, which is made even worse by people who have more liberal interpretations of the phrase "Open-Source". In many cases, keeping the source code of a product proprietary serves no other purpose than to prevent people from stealing the product. Putting an application under the GPL and selling it is perfectly reasonable for software aimed at end-users, whom are unlikely to know how to compile the freely available source. Libraries aimed at developers, however, usually must resort to Dual Licensing.

To me, dual licensing is a bit of a hack job. Using two fundamentally incompatible licenses at the same time always rubbed me the wrong way, even if it's perfectly legal for the creator of the software. The other problem is that this is usually done via copyleft licenses, and I would prefer more permissive licenses, given that I only care about whether or not the result is commercial or not. This, however, turns out to be a bit of a problem.

My ideal license for a commercial library would state that anyone is free to modify, distribute, or use the source code in anything they want, provided the resulting source code retains the provided license. If the resulting product is strictly noncommercial, it would be free. If, however, the source code or any derivation of the source code is used in a commercial product, there would be a fee. It'd basically be an MIT license with an added fee for commercial derivative works, with additional restrictions on what commercial derivative works are allowed.

The problem is, even if I were to use a dual-licensing strategy, there is no open-source license that contains a noncommercial restriction, because this isn't open-source. Specifically, it violates Freedom 1 as defined by OSI:
1. The license shall not restrict any party from selling or giving away the software as a component of an aggregate software distribution containing programs from several different sources. The license shall not require a royalty or other fee for such sale.
So, the first sentence of the definition of open-source software has made it abundantly clear that my software isn't open-source because I'm trying to make money off of it. This seems overly restrictive to me, because the source code is still freely available for people to distribute and modify, just not sell. Even then, they can still sell things made with the source code, they just pay a royalty or fee for it.

Now, there are good reasons why actual free software would forbid this. For example, if someone made an open-source library that required a royalty for commercial use whose code was repeatedly modified over and over again until it crept into all sorts of projects, it could then claim royalties on all of those products, even if only a few lines of its source code were used. This is obviously not conducive to creating a culture of sharing code.

However, there is another benefit of open-source software, which is now becoming progressively more obvious. It's the fact that, if you have the source code and compile it yourself, you can verify the NSA (probably) hasn't injected a backdoor into it. This is a benefit of visibility, and I think it should be encouraged. The problem is that the restrictions placed on free software are too harsh for most commercial libraries, who will then often resort to simply being proprietary.

So, sadly, there are no open-source commercial licenses, because those aren't open-source. Perhaps we need a new term, for software whose source is accessible but has usage restrictions. Even then, it's not entirely apparent what such a license would look like, or if sites like GitHub would actually allow it on public repositories. I took a peek at the Unreal Engine 4 license, but despite claiming to have it's source code available on github, it's actually in a private repository you must gain access to. To make matters worse, the actual Unreal Engine 4 license is incredibly restrictive. You are only allowed to distribute the engine code to other people who have agreed to the license! This obviously isn't what I want, but apparently no one else seems to think that software that's kind of open-source is actually valuable.

It's an awful shame, because I really don't want to make my project proprietary, but right now I don't have much choice. As far as I'm concerned, releasing something under a restricted open-source license is preferable to making it entirely proprietary. Unfortunately, the loudest programmers are also the least likely to be willing to compromise over ideological divides.

February 18, 2015

Does Anyone Actually Want Good Software?

Are there any programmers left that actually care about writing good software? As far as I can tell, the software development industry has turned into a series of echo chambers where managers scream about new features and shipping software and analyzing feedback from customers. Then they ignore all the feedback and implement whatever new things are supposed to be cool, like flat design, or cloud computing, or software as a service.

The entire modern web is built on top of the worst programming language that's still remotely popular. It's so awful that IE now supports asm.js just so we can use other languages instead. With everyone relentlessly misquoting "Premature optimization is the root of all evil", it's hard to get programmers to optimize any of their code at all, let alone get them to care about things like CPU caches and why allocation on the heap is slow and how memory locality matters.

Some coders exist at large corporations that simply pile on more and more lines of code and force everyone to use gigantic frameworks built on top of more gigantic frameworks built on top of even more gigantic frameworks and then wonder why everything is so slow. Other coders exist in startups that use Scala/Hadoop/Node.js and care only about pumping out features or fixing bugs. The thing is, all of these companies make a lot of money, which leads me to ask, does anyone actually want good software anymore?

Do customers simply not care? Is everyone ok with Skype randomly not sending messages and trying (poorly) to sync all your messages and randomly deciding that certain actions are always unread on other computers and dropping calls and creating all sorts of other strange and bizarre bugs? Is everyone ok with an antivirus that demands you sign in to a buggy window that keeps losing focus every time you try to type in your password? Is everyone ok with Visual Studio deciding it needs to open a text file and taking 15 seconds to actually start up an entirely new instance even though I already have one running just to display the stupid file?

It seems to me that we're all so obsessed with making cool stuff, we've forgotten how to make stuff that actually works.

Did you know that every single person I know (except for two people) hates flat design? They don't like it. I don't like it. There's a bunch of stuckup, narcissistic designers shoving flat design down everyone's throats and I hate it. The designers don't care. They insist that it's elegant and modern and a bunch of other crap that's all entirely subjective no matter how hard they try to pretend otherwise. Design is about opinions. If I don't like your design, you can't just go and say my opinion is wrong. My opinion isn't wrong, I just don't agree with you. There's a difference.

However, it has become increasingly apparent to me that opinions aren't allowed in programming. I'm not allowed to say that garbage collectors are bad for high performance software. I'm not allowed to say that pure functional programming isn't some kind of magical holy grail that will solve all your problems. I'm not allowed to say that flat design is stupid. I'm definitely not allowed to say that I hate Python, because apparently Python is a religion.

Because of this, I am beginning to wonder if I am simply delusional. Apparently I'm the only human being left on planet earth who really, really doesn't like typing magical bullshit into his linux terminal just to get basic things working instead of having a GUI that wasn't designed by brain-dead monkeys. Apparently, I'm the only one who is entirely willing to pay money for services instead of having awful, ad-infested online versions powered by JavaScript™ and Node.js™ that fall over every week because someone forgot to cycle the drives in a cloud service 5000 miles away. Apparently, no one can fix the audio sample library industry or the fact that most of my VSTi's manage to use 20% of my CPU when they aren't actually doing anything.

Am I simply getting old? Has the software industry left me behind? Does anyone else out there care about these things? Should I throw in the towel and call it quits? Is the future of software development writing terrible monstrosities held together by duct tape? Is this the only way to have a sustainable business?

Is this the world our customers want? Because it sure isn't what I want.

Unfortunately, writing music doesn't pay very well.