Code Share: Source Censoring, Part 2

Original Author: Niklas Frykholm

A while ago I shared the tool we use for censoring source code in the Bitsquid engine.

Quick recap: We need to censor the code in our source distributions because there are parts of the code that are covered by NDAs to third parties and cannot be publicly disclosed. We do this with a tool that strips out the secret code and replaces it with blank lines, based on preprocessor definitions.

The stripping tool is only part of the solution, though. It works well if you only distribute code drops. You take a snapshot of the code, run the stripping tool to strip out secrets, zip it up. Done!

But frankly this is a terrible way of distributing source code. There is no history, no indication of what has changed from version to version and keeping local changes merged with the mainline is a constant pain in the ass.

The only sane way of distributing source code is to expose a mercurial (or git) source repository that you can pull changes from. This lets customers examine the history, find out which version introduced a particular bug, maintain their own branches that they merge with the mainline at their convenience, etc.

But of course, we cannot just share our own internal repository (because it contains secrets).

hg-clone.rb

We handle this with another tool, that we have inventively decided to call hg-clone.rb.

What hg-clone.rb does is pretty straight forward. Given two repositories as argument, a SOURCE and a DESTINATION, it checks out each revision in the SOURCE repository, runs a filter program (to strip out any secrets) and checks the result into the destination repository.

SRC:    0  --> 1  --> 2  --> 3  --> 4  --> 5  --> ...
 
      	|      |      |      |      |      |
 
      	F      F      F      F      F      F
 
      	|      |      |      |      |      |
 
          v      v      v      v      v      v
 
  DST:    0' --> 1' --> 2' --> 3' --> 4' --> 5' --> ...

You call the program as

hg-clone SOURCE DESTINATION --filter FILTER --target TARGET-REV --cutoff CUTOFF-REV

SOURCE and DESTINATION are the source and destination repositories. DESTINATION does not need to exist, if it doesn’t it will be created. FILTER is the filter program, it will be run once in the destination directory before each revision is committed.

TARGET-REV is the target revision that should be copied from the source to the destination. hg-clone will first transfer the parent(s) of the target revision to the destination repository (if they haven’t already been transfered), then it will transfer the target revision. This process is applied recursively, so if the parents’ parents haven’t been transferred, they will be transferred first, etc. Only the revisions that are ancestors of TARGET-REV will be transferred, so you can have secret development branches that won’t be copied to the destination until they have been merged with your release branch.

If you don’t specify a TARGET-REV, the last revision in the source repository will be used.

CUTOFF-REV can be used to cutoff the recursive parent transfer at a specific revision. If you set the cutoff to revision 1000, then any revision that has a parent before revision 1000 will be reparented to revision 1000 in the destination repository. Essentially, in the destination repository, history will start at revision 1000. This can be used to hide a shady past.

hg-clone tries its best to preserve authors, dates, messages, branches, etc between the source and destination repositories. It cannot however preserve version numbers, since those are based on a content hash, which changes when the filter is applied. What it does instead is to insert a marker [clonedfrom:116:91fe33c1a569] in the commit message that specifies which revision in the source repository the current revision in the destination repository was cloned from. This commitment marker is also used to determine the mapping between revisions in the source and the destination and whether a particular revision has already been copied over or not.

To use this in practice, you would typically set up one external repository for each customer with a corresponding filter program for stripping out the things that customer is not allowed to see. Then you would set up a cron job to run hg-clone and copy revisions from the main repository to the customer’s.

Instead of having one repository per customer, you could alternatively have one repository for each possible NDA combination (e.g., +PS3 +PS4 -X360). However, this can be problematic, because if a customer becomes disclosed for a platform you will have to switch them over to a new repository, which might be painful. If you have one repository per customer you can just change the filter function.

The hg-clone program is available from our bitbucket repository.

This has also been posted to The Bitsquid blog.

“App Of The Day” type apps can help indies with app discovery

Original Author: Kyle-Kulyk

Vex Blocks for Android. We’ve made the game, people seem to like the game, how do we get people to notice the game with our marketing budget as constrained as it is? I’d had a successful mobile developer recommend to me in the past that when you launch a new game, all you need to do is to pay the Russians $5,000-10,000 to get you to the top of the app charts and then see if you stay there. If your app doesn’t stay there, move on. That wasn’t the particular answer we were looking for with this game release and that’s where App Turbo helped out.

About a week and a half after we launched the paid version of Vex Blocks on Google Play, Yuhao Zeng of the Paris based App Turbo contacted me to ask if we’d be interested in promoting Vex Blocks with their “App of the Day” app. They expressed interest in our game and thought their users would too. The idea was simple enough. We make a full copy of our paid game available for 24 hours, free, and they’d promote it. As we had our hands full with free version of Vex Blocks, our app marketing had at that point consisted of a few press releases (where we could afford them) and emails to review sites who had historically ignored us. We received the details, talked them over among ourselves and ultimately decided on “What the hell?”

I don’t want to sound like an advertisement for their service, but I like when others share their indie development experiences and if I can help another dev in our shoes, I’m going to pass it along. Yuhao was fantastic throughout the process, quickly answering any and all questions I threw his way. The “App of the Day” app is regional, covering a good chunk of Europe as well as Russia, Canada, Australia, Mexico, Brazil and Japan. Prior to the promotion, the free version of Vex Blocks was managing roughly 100 downloads a day in the 2 weeks since it’s release. We were hoping that perhaps this promotion might give us a boost of a couple of thousand users and help us get the ball rolling a bit.

When all was said and done, over 90,000 users downloaded and played our game in the 24 hours the promotion ran this week, of which roughly 80% have so far stayed as active users. I’m sure that’s nothing to some developers, but for an indie team like ours this is a huge step forward. The next day, the free version of Vex Blocks jumped from it’s regular 100 a day to roughly 6000 where it’s stayed so far. The paid version of Vex Blocks is also experiencing a nice spike. For an English only game, I’m pleasantly surprised that so many decided to give us a try in non-English speaking countries and the feedback from users has been fantastic. The goal was to help Vex Blocks find it’s way into the hands of gamers and raise awareness, and in that this exercise was a complete success. It also served as an excellent opportunity to help narrow the list of the 2000 some Android devices that the game was available on and weed out a few devices that were incapable of playing our game.

There are a number of “Free App” type applications like “App of the Day” ( 

Life can be better (part 1 of 3)

Original Author: Amir Ebrahimi

TL;DR – If you’re happy, healthy, and have energy to make things happen most of the time, then keep doing what you’re doing. If not, or if you used to be and now aren’t, then you may be interested in what I have to say.

This May will mark the tenth year that I have worked in the video game industry. Technically, I could be classified as a “veteran”. However, whenever I think of that term — veteran — I conjure up images of other great developers, some of whom I have had the good fortune of working with, that are senior to me. Regardless of the appropriate use of the term veteran, I’m calling attention to it because one out of every three of us who came into the industry were not expected to be around after 5 years. Extend that period to ten years and it would either be you or the guy / gal next to you that would leave behind an empty chair.

Quality of Life Survey put out by the IGDA that I remember coming across back in 2004; only a year after joining the video game industry. I was disheartened to read that attrition was a concern in our industry and that, among all the reasons given, long hours and crunch were omnipresent. In other words, people weren’t leaving the industry because it was unfulfilling as a career. No; people were leaving because it was a choice between their health / sanity / relationship / family / social life / etc. and a creative endeavor that was bleeding them dry.

My experience at that time with others in the industry was that neither the IGDA, nor it’s report on quality of life were to be taken seriously. In my judgment, there was cowboy bravado at play that took pride in the fact that we worked ourselves to the bone; all of which was “necessary” to produce the next hit title. If you couldn’t keep up with that pace, then you weren’t cut out for the industry. I even had a senior manager tell me in an exit interview that he was surprised I was headed to work for another company in the industry instead of leaving altogether.

paid at least a minimum hourly rate for your time.

You may be wondering why I would be interested about an IGDA whitepaper, legalities of overtime, and classification for pay only after a year of being in the industry. Well, although I didn’t have much awareness about my well-being back then as I do now, I did know something was wrong. My first indicator was health; noticing that my overall energy level day-to-day had declined. I found that I was chronically tired, felt “heavy” to move around even though I wasn’t grossly overweight, and started to think that most things I had to get done were weighty tasks. The second indicator was my mood; noticing that the enthusiasm and optimism that I entered into the industry with had been replaced with irritability and negativity.

I decided to see a doctor for a health check up to see if anything was gravely wrong. Oddly enough, the blood work that was done indicated that nothing was awry. In fact, the results even showed that I had a high level of “good” cholesterol (HDL) and a low level of “bad” cholesterol (LDL). Nothing the doc found was abnormal and I was told to get better sleep and exercise more (which I eventually did start doing during lunch with coworkers). Had I had the awareness that I have now to understand that health was my responsibility, I would not have accepted the blood work as conclusive. My current understanding of doctors is that they aren’t in the business of making us healthier; they’re there to make sure we don’t get any sicker than we already are.

Over the next year, I worked on my third console title, lifted weights and exercised multiple times a week with co-workers, ate salads occasionally during lunch, and, unfortunately, was also drinking numerous cups of coffee during the day to fuel the work that I was doing. Commonly said, I was working hard and playing hard. Sure enough, at some point during development, we entered our multiple-month crunch during the project and sleep and free-time became a luxury. What’s odd about that time is that I was in the best physical shape I had been in since my years playing football in high school, yet my energy level, mood, and mental health were getting worse.

In parallel, a letter from a disgruntled ‘EA spouse’ and a class-action lawsuit against EA by a collection of artists both emerged in late 2004. Both spoke to the unfair working conditions that employees faced at EA. In 2005, the class-action lawsuit was settled for $15.6M and would later be succeeded by a separate class-action lawsuit composed of programmers (also settled out of court). In comparison to the film and television industry, the labor practices of the video game industry were and in some cases still are juvenile. For film and television, professionals get paid for overtime and although the health effects of crunch aren’t mitigated, at least the costs are made material.

I experienced overtime pay firsthand, when I joined a visual effects company, The Orphanage, here in San Francisco in 2008. I learned quickly how volatile the film industry could be — projects came and went, hours went up and down, and staff increased and decreased on a week-to-week basis. However, even with the volatility, there was a fundamental understanding that everyone would get paid for his or her time. The California Department of Industrial Relations released a working order in 2001 specifically for the film industry. The working order dictated how overtime would work within a single workday and workweek, required minimum days off, alternative workweeks, meal and rest periods, and even the temperature for working conditions. Even though I had a salary, I logged every hour that I worked against different projects at the company for budgeting purposes. What I found so cool about this process is that, not only would I be paid overtime when I worked longer hours for a specific project — it would show up in the cumulative costs for that specific project. Essentially, accountability was built into the process, since having people work longer hours resulted in more costs for the project. Unfortunately, I joined the company almost immediately after the Writers Guild of America (WGA) strike concluded, which left the film industry on shaky ground. Our goals as a company to re-build the VFX pipeline from the ground up were thwarted when a major project of ours was lost and multiple rounds of lay-offs ensued.

The awareness of unspoken quality of life issues in the video game industry that 2004 brought us was much needed. In my judgment, we’ve seen some improvements come out of that awareness, such as flexible working hours and smaller studios that attempt to treat their employees better. However, there is still a prevalence of crunch time across the video game industry. I see an opportunity here to spend more of my own energy inviting others in the industry to consider the awesome effects of what a happy, healthy, and energetic workforce would bring. In that regard, I’m doing my part as a studio owner to have reasonable working hours, minimize unhealthy levels of stress with projects, and respect our employees. My hope is that at the very least I will not perpetuate the cannibalism of creatives in our industry.

However, my attention right now and the purpose of these articles is to heal the damage that has already been done at a personal, individual level of health. My story continues past 2005 with more crunch periods, stress on relationships, and more health problems (including mental health). If any of what I’ve said so far resonates with you and you’ve come to accept as “normal” the sub-optimal ways you feel, think, and view life, then know that life can be better. Whatever you’ve been getting out of your body and mind under extended periods of stress comes at a cost. I wholeheartedly believe that whatever has been taken requires replenishing.

Over the past year and a half, I have focused on improving my own health. I have noticed that changes in the health of my body have resulted in improvements with the way I think and the performance of my mind. Another benefit is that with more energy, things that I wouldn’t have considered to do in the past come easier now, such as riding my bicycle to work. My hope for us all is to feel good in our bodies at a physical level, happy at an emotional level, and energized at a creative/intellectual level. Together, we’ll be able to make our industry a sustainable outlet for human creativity.

In the next article, I will go deeper into the health side of things as best as I have come to understand. I will share briefly a few anecdotes of my naivety as it relates to health and some of the things that I have done in an effort to make improvements. I will explain a bit about the PAT (pituary-adrenal-thyroid) axis and why it is so important to your overall well-being and your perception of well-being. If I find that there is more information to share or that this next article is too lengthy, then I may continue with further articles.

EDIT: I am a (hu)man, therefore I am imperfect. I have revised this article to remove references to what, unbeknownst to me, could be considered controversial — hair testing mineral analysis. I’ve become aware of arguments on both sides and would be happy to share with you the information, so that you can make your own educated decision. I have had my own positive experiences with hair testing/nutritional balancing, tailored supplements (as opposed to a catch-all or taking supplements that my body doesn’t need), a healthier diet, reduction of caffeine, drinking much more water than I thought was necessary, and a variety of other things. My goal is to raise awareness about health in our industry, provide one story as a reference point to others that may have had a similar experience, and offer some suggestions on how you may be able to improve your own health. My intention is not to back myself into a position of having to defend a specific approach to nutrition. What I have come to understand is that health and nutrition are not a simple thing. Simply Google ‘improve health’ and see all the various approaches and opinions that are returned. As to the Game Developer Performance Challenge that was originally linked here, I’d still like to challenge you to improve your own health if your day-to-day experience is sub-optimal.

A Fast, Type-safe & Minimal String Formatting Library, miniformat

Original Author: Jaewon Jung

The inspiration for tinyformat. Unfortunately it relies on the C++ iostream, basically std::cout, which is somewhat slow and definitely not everyone’s favorite. So I bit the bullet and got around to implement my own with minimal dependency and speed in mind.

Origin

I didn’t want to implement all the nitty-gritty of formatting a floating-point number to a string. Fortunately there was an awesome library called SourceTree, which currently doesn’t support Mercurial on Windows). Its usage was like:

std::string str;
 
  mini::format(str, "String: %1 Int: %0, Float: %(.3)2n", 100, "JJ", 3.141592);

Originally it supported only std::string as an output type by default, although one can support other string types by specializing function templates in string_adaptor namespace. By the way, keep in mind the caveat that it’s not supporting all the features of printf format specifiers(for instance, no hexadecimal/octal integer support).

Improvements

Recently I saw slides) and decide to apply the lessons there (as for number-to-string conversion) to the formatting library and see how it fares. I also wanted to add a support for raw char arrays as an output type by default since a potential heap allocation cannot be an option in some situations.

Here’s the original code for converting 32bit unsigned integer to a string:

template <typename String>
 
  void miniformat::detail::render(String& wstr, uint32_t value, int width, int)
 
  {
 
      int beginIndex = string_adaptor::length(wstr);
 
      // Conversion. Number is reversed.
 
      do 
 
      {
 
          string_adaptor::append(wstr, 1, (char)(48 + (value % 10))); 
 
      }
 
      while (value /= 10);
 
  
 
      // Handle the 'width' parameter.
 
      int spaceCnt = width - (string_adaptor::length(wstr)-beginIndex);
 
      if(spaceCnt > 0)
 
          string_adaptor::append(wstr, spaceCnt, ' ');
 
  
 
      int endIndex = string_adaptor::length(wstr)-1;
 
      // Reverse string.
 
      strreverse(string_adaptor::at(wstr, beginIndex), string_adaptor::at(wstr, endIndex));
 
  }

Pretty straightforward, other than the consideration for the ‘width’ parameter(the unnamed fourth parameter is a precision value, which is irrelevant for integers).

Here is the one after Andrei’s optimizations applied:

inline int miniformat::detail::digits10(uint32_t v)
 
  {
 
      static const uint32_t P01 = 10;
 
      static const uint32_t P02 = 100;
 
      static const uint32_t P03 = 1000;
 
      static const uint32_t P04 = 10000;
 
      static const uint32_t P05 = 100000;
 
      static const uint32_t P06 = 1000000;
 
      static const uint32_t P07 = 10000000;
 
      static const uint32_t P08 = 100000000;
 
      static const uint32_t P09 = 1000000000;
 
  
 
      if(v < P01) return 1;
 
      if(v < P02) return 2;
 
      if(v < P03) return 3;
 
      if(v < P08)
 
      {
 
          if(v < P06)
 
          {
 
              if(v < P04) return 4;
 
              return 5 + (v >= P05);
 
          }
 
          return 7 + (v >= P07);
 
      }
 
      return 9 + (v >= P09);
 
  }
template <typename String>
 
  void miniformat::detail::render(String& wstr, uint32_t value, int width, int)
 
  {
 
      static const char digits[201] =
 
          "0001020304050607080910111213141516171819"
 
          "2021222324252627282930313233343536373839"
 
          "4041424344454647484950515253545556575859"
 
          "6061626364656667686970717273747576777879"
 
          "8081828384858687888990919293949596979899";
 
  
 
      int next = string_adaptor::length(wstr);
 
      const int length = digits10(value);
 
  
 
      // Handle the 'width' parameter.
 
      int spaceCnt = width - length;
 
      if(spaceCnt > 0)
 
      {
 
          string_adaptor::append(wstr, spaceCnt, ' ');
 
          next += spaceCnt;
 
      }
 
  
 
      string_adaptor::append(wstr, length, '0');
 
      next += length-1;
 
  
 
      while(value >= 100)
 
      {
 
          const uint32_t i = (value % 100) * 2;
 
          value /= 100;
 
          *string_adaptor::at(wstr, next) = digits[i+1];
 
          *string_adaptor::at(wstr, next-1) = digits[i];
 
          next -= 2;
 
      }
 
  
 
      // Handle last 1-2 digits.
 
      if(value < 10)
 
      {
 
          *string_adaptor::at(wstr, next) = '0'+static_cast<char>(value);
 
      }
 
      else
 
      {
 
          const uint32_t i = static_cast<uint32_t>(value) * 2;
 
          *string_adaptor::at(wstr, next) = digits[i+1];
 
          *string_adaptor::at(wstr, next-1) = digits[i];
 
      }
 
  }

It now consists of two passes(and two corresponding functions) instead of one, but due to strength reduction, array writes minimization and other optimizations from Andrei’s post, should perform faster than before.

Here are timings of converting some random integers into std::string, before & after this optimization:

Win32 Release/before Release/after Debug/before Debug/after
uint32_t 0.85 0.57(1.5x) 4.64 2.44(1.9x)
int32_t 0.89 0.62(1.4x) 4.63 2.44(1.9x)
uint64_t 1.47 1.03(1.4x) 4.71 2.5(1.9x)
int64_t 1.49 1.08(1.4x) 4.71 2.5(1.9x)

 

x64 Release/before Release/after Debug/before Debug/after
uint32_t 0.93 0.54(1.7x) 1.38 0.78(1.8x)
int32_t 0.94 0.56(1.7x) 1.39 0.77(1.8x)
uint64_t 0.93 0.57(1.6x) 1.43 0.79(1.8x)
int64_t 0.94 0.63(1.5x) 1.45 0.82(1.8x)
  • Numbers are in seconds.
  • Iteration count: 10,000,000 for Release, 1,000,000 for Debug
  • Compiler used: VS2012
  • One can find the code for this in benchmark2() function template of miniformat.cpp in the project repository.

One can observe 1.4x ~ 1.9x performance improvements overall. Not bad. You can also notice that the performance degrades very much in Debug(keep in mind that the iteration count differs between Release and Debug), especially in Win32. It seems mainly due to the fact that I used std::string as an output in this benchmark, which has much more overhead in Debug.

As I said, I had bolted on a support for raw char arrays recently, but it wasn’t very efficient because I had originally structured the code on the implicit assumption that getting a length of a string is a constant operation. This holds true for std::string and similars, but not for a raw char array. For that, one should pass the current length of the output string through functions. You can see that the render() code above calls string_adaptor::length() in the beginning to get the current length. That’s far from optimal. So I fixed it.

Here are some timings of a benchmark comparing sprintf vs. miniformat(for the both cases of outputting to std::string and to char array), before & after this fix:

Win32 Release/before Release/after Debug/before Debug/after
Speed-up when outputting to std::string 4.42 4.20 0.26 0.24
Speed-up when outputting to char array 2.59 3.84 1.58 1.27

 

x64 Release/before Release/after Debug/before Debug/after
Speed-up when outputting to std::string 3.81 3.81 1.13 1.06
Speed-up when outputting to char array 2.19 5.13 3.91 3.51
  • Numbers mean a speed-up factor of miniformat compared to sprintf.
  • Compiler used: VS2012
  • One can find the code for this in benchmark() function of miniformat.cpp in the project repository.

Before this fix, the speed-ups in the case of outputting to char array were less than the ones in the case of outputting to std::string because of the inefficiency mentioned above(4.42 vs 2.59 on Win32/Release, 3.81 vs 2.19 on x64/Release). With the fix, the speed-ups of outputting to char array has come close to or exceeded the ones of outputting to std::string. Again, you can see the inefficiency of std::string on Debug, which actually makes the speed-up factor of miniformat less than one on Win32/Debug.

Conclusion

I think miniformat is now in a decent state. As I said, it’s not exactly functionally equivalent to sprintf and some people don’t like possible code bloat that an extensive use of C++ template brings. I definitely won’t say benchmarks above are scientific. Still, it brings type-safety and speed-up of up to 4~5x (than sprintf) as just a header-only library with no dependency.

It’s not yet using C++11 stuff. In a related node, one should still append .c_str() when putting std::string as an input argument. I tried to do without it, but without move constructor stuff in C++11, it seemed very difficult to not introduce any copying. std::ref)(also, available in C++11) can do the trick, but it requires more typing than adding .c_str()! If anyone knows a solution for this without introducing a dependency, please enlighten me.

I welcome suggestions!

(I posted this article to my personal blog, too.)

Android piracy still sucks

Original Author: Kyle-Kulyk

Vex Blocks, there’s an emotional, open-handed slap across the ear to be had when you realize that your release is being pirated at a rate of 20:1.  On the Android market, a developer’s hard work is so devalued that 95% of gamers would rather pirate your game by the thousands than pay a dollar to help support what you’re doing and enable you to feed your family.  Even though I was aware that piracy on Android was bad, it’s a soul shaking realization when it hits in relation to your own product and it left me to question if it’s even possible to make a living as an independent developer.  All piracy sucks and the Android market isn’t alone in fighting this scourge, but what can be done and how has it impacted the games we make?

We launched the paid, full version of Vex Blocks on Google Play first for the simple fact that it was finished first.  We knew the market for paid apps on Android was limited compared to others, but I don’t think we were really conscious of just how big a role piracy played.  Our first release, Itzy3d, marked our first steps into the world of mobile game development.  When we released Itzy3d, our plan was to have a full, paid version and then a free, lite version.  The paid version of Itzy3d was all but ignored on the Android marketplace, as we suspected it would be while the lite version was downloaded considerably more than its iOS counterpart, by roughly 5:1.  There was at least an appetite for our products on Android so skipping out on a Google Play release didn’t even occur to us with our follow-up title.

android_1What we didn’t know with Itzy3d was actual numbers on how many copies of the game were installed on devices compared to how many we sold via Google Play.  With Vex Blocks, we’re able to see how many copies are out in the wild compared to how many copies we’ve sold.  These statistics don’t change our approach to Android releases.  The impact is more of an emotional toll when you realize the bulk of gamers out there on Android you’re trying to reach with your product don’t have any interest in supporting that product, even if they use it.

Over the years I’ve heard plenty of arguments trying to justify why piracy isn’t really an issue for developers.  The main one you always hear is, “Those people would have never bought the game in the first place.  No money is lost.”

The idea that certain people just never buy games is ridiculous.  Arguing that pirate gamers would just cease gaming if they couldn’t pirate is utter nonsense.  Add to that the cost barrier for mobile gaming is generally so low, and it just boils down to pirates are cheap.  Full stop.  Pirates who can’t spend half the price of a large cup of coffee to support a game they want to play shouldn’t make excuses or try to rationalise their actions.  They’re cheap and they’d rather open themselves up to malware infected copies found in the gutters of the internet than compensate developers for their work.  Now I’m sympathetic to the fact that in some countries, due to government restrictions, the only way you can access television shows, music and, yes, mobile games is through illegal sites, but the bulk of pirated copies we’re seeing of our game aren’t coming from these countries.

Pirates will argue that nothing is stolen as the product is only copied, so it’s not even a crime, but of course the reality is every pirated copy of a game removes that person from the pool of potential customers and with 95% of your customers not willing to pay for your product, that doesn’t leave developers much room to work with on Android.  So, the piracy ship has sailed and aside from becoming bitter old men who rant on blogs and shake their fist at kids who walk in front of their house too slowly, what can be done?  Price competition isn’t a factor.  The race to the bottom is already over and, surprisingly, no one came out the victor.  Daring to even charge a dollar your game is in itself an invitation to pirate now.  The ease with which pirates can copy a developers work has fundamentally changed the way developers cope and the end result is a diminished product for all.

There are numerous ways a developer can attempt to limit the impact of piracy issues.  You could simply avoid developing for Android, but there is still a market consisting of legitimate Android users out there and it’s not that other platforms are immune to piracy.  I love creating games for Android devices and I’m humbled by the support we’ve received from our players.  I wouldn’t ignore the gamers who do support our products.  Many of the other methods to deal with piracy involve lessening the experience for legitimate gamers on mobile (and on other platforms).  DRM is one route.  The general thinking is, the harder you make it to pirate your work, the more chance that some pirates might actually pay to play your game due to the effort involved in cracking or finding a pirated version.  There’s certainly some validity to that approach but as we’ve witnessed with a few recent, high profile examples of digital rights management such as launch issues surrounding Diablo 3 and SimCity, this has the potential to backfire and hurt your paying users.

You can require mandatory sign-up as well, but this has a tendency to alienate those who simply want to buy a game and play, hassle free.  That leaves the freemium method of releasing your game filled with upgrades, advertisements or both.  It’s certainly the route that more mobile developers are choosing, including ourselves, but again this can lead to a lesser experience as advertisements throughout a game become tiresome quickly, and an over reliance of micro-transactions can also turn gamers away.

monkey_island_codewheelAlternately developers can choose to embrace piracy.  There’s the chance that a happy pirate may promote your game simply through word of mouth.  For indie developers, creating a great product is job one, but getting noticed is by far the real battle.  The next great novel could be sitting in a pile of thousands of books but if no one picks it up to read it in the first place the author could very likely die in obscurity.  Similarly, great games need to be played in the first place for anyone to discover them and if they’re played as a result of piracy and discovered in that fashion, the argument can be made that the pirates did the developer a service.  Of course it’s only a service if the pirates tell enough gamers from the 5-10% of Android gamers who legitimately support developers – ideally before those developers are forced to close their doors.

But hey, why should developers going under matter to pirates?  By that point they’ve already moved on to helping themselves to the next game.

Designing a game to behave in ways for which it was not designed

Original Author: Alex Norton

Prologue

I’d like to start this article by pointing out that it is merely a documenting of my own personal experience and thoughts that led from it, and in no way is a treatise on what I think everyone should do. Please take it with a grain of salt.

 

Introduction

Emergent behaviour is something that has really surprised and fascinated me in the past with gaming communities. A particularly clean-cut example is Minecraft. Despite being designed as a sandbox game, the game’s community has grown to accomplish some incredible feats including making games within the game, which – to my mind – is just incredible. Given enough momentum, and given the right design choices in a game project, people will start to play a game in ways that it was not designed for – sometimes to very interesting effect.

So naturally, when this sort of thing started happening – albeit in a less grandiose fashion – within my own game’s community, I really found it astounding, and it led to some interesting revelations and thoughts for expansion, which I will go into later.

 

My own experience with emergent player behaviour

First, let me explain what happened within my own community to lead to these revelations, and to the eventual typing of this article. Some of you may know me for my main project, Malevolence: The Sword of Ahkranox. Among those who know and play the game, it has become infamous for its difficulty – which it was designed for – and the sheer effort required just to stay alive in the game when everything in it tries to kill you in the most creative way possible. This factor alone has led to its small, but dedicated fan-base to have a somewhat gleefully masochistic view towards playing, and many community requests for expansion to the game have revolved around this mentality, including making dungeons darker and more difficult to traverse, making traps deadlier, combat less forgiving and primarily the addition of a perma-death option to greatly multiply the sense of risk.

The emergent player behaviour that led from this started out fairly simply. People wanted to know how long they could survive in the game’s hostile environment, which only gets more difficult the longer you stay alive, and so, competitions arose to see who could live the longest. To my mind, this was inevitable and very much tied into the base competitive nature of the modern gamer.

However, it soon escalated from there with the addition of functionality to be able to “claim” locations as being the first to discover it. The game world in Malevolence is infinite, and everyone is in an exact copy of the same world, so people can travel as far as they like to discover new locations which are procedurally generated by the game, but still exist in everyone else’s copy.

The procedural nature of Malevolence means there’s
always something new to find. This makes players feel
a sense of ownership if they’re the first to find something.

Designing “10000000″ as a Free To Play Game

Original Author: Raul Aliaga Diaz

success is as amazing and inspiring as the game itself.

The game in its PC/Mac port.

The game in its PC/Mac port.

What’s also interesting is that the game allows itself to be designed as a Free to play game. It is a particularly good example because is indisputably a great game, is accessible for any platform you’d like to play it and we can use it as an example for this thought experiment of making it Free to play.

here (not recommended).

Design changes and expansions

Free to play triangle lens we can discuss three venues for monetization: Skips, Unlocks and Boosts. They are based on traditional “sim management” games, so we can adapt the triangle here to Content, Unlocks and Boosts.

  • music can be a good and simple trick.

  • Unlocks: All the locks on things that are accessible through “repairs”, the list of upgrades, access to dungeons, the alchemist potions. An additional element could be putting caps or limits on the amount of resources (wood, rock, coins and XP) that can be had at a time and unlock them through monetization/other resources. In 10000000, you can carry at most 4 items on a run: another potential source of revenue could be selling the ability to increase that limit so players can carry more.

  • Boosts: This is relatively straightforward, since when you’re playing you receive weapons, food, keys, orbs and scrolls that you can carry to the next run and act as boosts. All of these can be sold separately.

There are also two key areas for feature expansion. The first is a storage room that can hold any extra boosts the player found while running or purchased at the store. This causes the player to manage more effectively how they proceed on each run. These limits could be expanded through purchases.

Second, the Alchemist room enables a particular effect at the cost of a trade off. This should be changed to a boost fashion in which these alchemist effects can last only for one run, possibly with less strict tradeoffs and also stored in your storage room.

The Alchemist’s room

The Alchemist’s room

funnel in a better way.

However, the Triangle suggests to monetize with at most two of the methods, which is sound advice. Given that 10000000 isn’t a place to “enjoy watching an aquarium” such as DragonVale or Hay Day, the clever thing would be to stick with unlocks and boosts.

here).

here.

10000000 is an excellent game to share video replays to feel closer to the excitement of the game itself and sharing amazing feats that can be achieved in it. One additional content tweak would be increasing the animations and “pyrotechnic effects” of achieving chain reactions with the tiles in the running zone. When you’re playing and doing amazing feats, you feel great but you’re focused on the tiles, and when someone else is viewing, it would be nice to have something for other people to watch that is spectacular.

SonicDashTrick

For example in Sonic Dash, they control the pacing of races and allow the player to do some “quick time swipes” for Sonic to breakdance in the air. This looks awesome and also wins some rings if done right.

If we want to go nuts, we can even discuss a room dedicated to store these glorious gameplay images and/or videos so the player herself can revisit them in the game or have it for her friends to see, but that’s a lot of additional work, development-wise.

Execution tradeoffs

We have discussed monetization and social aspects for the game to be considered a Free to play game, is that it? Well, not so much. Free to play games start when the game launches, and operate as a service, not a product. This cannot be stressed enough as it is easy to overlook in practical decisions and prioritizations how to approach the execution of these designs and handling the expectations associated to them.

So what does all this mean? In addition to the elements mentioned above they need to pass a check for game balance from a informed through analytics -especially when the game is already live. Additional checks must be passed regarding UI, accessibility, and timing of the monetization elements. There’s a huge amount of games that hide away the options to pay more under too many screens, unclear menus or the wrong timing for monetization, making it annoying instead of convenient.

spectacularly. Many times this is because developers fail to see the service aspects and just throw in some IAP without too much thought about them, only to claim foul when they don’t get disgustingly rich overnight.

Then all the work needed with art, programming, balancing and testing needs to be estimated and considered to be split in several iterations that have different tradeoffs on different platforms when they go live. For example, monetization re-designs would allow the game to be set free and include more revenue venues but it would not achieve all of its strength without the social features. On the other hand, working the social features first would put the game in the eyes of more potential players that still would be stopped at a paywall if they’re not willing to pay anyway. However, the social features discussed here can be integrated in the game without making it Free to play at all and it could potentially be a good thing anyway.

Asian localization). Then moving these changes to all platforms including the social features, that can be developed for the game to scale once you have data and revenue to support such scaling.

Where do we go from here?

This was a general discussion to a deeper level of how to take an already great game to millions of players through the Free to play model, considering several aspects of the decisions involved.

For more detailed discussions on monetization and Free to play, I recommend to check:

  • The Language of Monetization Design

  • Monetizing an Infinite Runner

  • Part 1)

  • Managing a Free-to-Play Product: a Publisher’s Perspective

To understand all the nuances involved in the design of a Free to play “casual” successful title, Candy Crush Saga:

  • Why Candy Crush Saga is taking over the world

  • Video: Candy Crush Saga uses luck in the right places (GDC 2013)

The controversial decision made by Candy Crush developers of not to use a virtual currency in their game and going with direct purchase of boosts draws special attention. This was a risky and bold decision (albeit a good one given the game’s performance).

Almost everything you need to know to enter mobile game development on 2013.

In summary, 10000000 is a great game, that includes within itself many options to make it a game that allow players themselves to put a better price on the value of the whole experience -a fun, convenient and social experience. When we analyze the tweaks and additions we can make to the game, we must take into consideration the costs and benefits of each improvement and how they can add value to the whole game incrementally. This will change from a finished, bounded product to an ongoing live service dedicated to its community of fans.