Monday, August 21, 2017

What is playability?

What is playability?

When a gamer first takes to the controllers or keyboard to interface themselves with the game, they are creating a seamless connection with themselves and the game.  This interface should be fluid and easy to learn, the same way a person has a intimate connection when sitting in the driver seat of the car.  The player shouldn't have to look down to look for buttons, and there should be no distractions, from the game or elsewhere.

When a seamless interface is created, it is said that immersion has occurred.  At this point, the player is in the game and does not realize that they are connected via a controller.  This creates an optimal play experience and it is expected of any gaming experience.  Hence, the act of getting into this "magic circle" called immersion is what playability is all about.

There are a number of things that can distract.  Some are external and the game developer would have no natural control over there.  This could include the door bell ringing, a dog barking, or something as simple as an alarm going off indicating its time to quit playing.

External Distractions

  •  Unintentional
    • Door bell ringing, dog barking, health reasons, etc.
  •  Intentional
    • Scheduled alarms, conscious thoughts, etc.

On the other hand, there are internal sources of distraction that should and must be minimized by the game developer.  These include glitches in the game, discontinuities in stories, poor system performance, or poor network lag (which could be both a problem at the network side or with the poor usage of data streams being sent across the network which could've been made more efficient.)

Internal Distractions

  • Performance
    • Network Latency
    • Inefficient operations, menu takes too long to load, etc
  • Discontinuities
    • Gaps in story, missing but expected considerations or implementations, etc.
  • Defects
    • Glitches that make you go "what the... "
    • Designs that are disconcerting, tutorials that take too long/too obvious, slow load times that aren't due to inefficiencies, etc
Software Performance Engineering
https://www.slideshare.net/TanzaIratier/joe-krall-presentation
Study on latency in games leads to lower overall enjoyability index (http://dl.acm.org/citation.cfm?id=566500.566511&preflayout=tabs)

https://link.springer.com/content/pdf/10.1007/978-3-540-74873-1_53.pdf

Friday, August 18, 2017

The gameplay lifecycle

All games go through this gameplay lifecycle.  Consider the perspective of the gamer.  As an individual, their attention and interest must first be obtained and piqued.  Then, with enough interest and motivation, they will buy the game and begin playing it.  The first play is critical, because it will define how long they play it thereafter.  Eventually after completing or beating the game, they'll put it down, and perhaps do one of two things: either sell it, or keep it for later.  In the case of the latter, they'll wait until the game becomes interesting enough to once again replay it.


Once a game product is finished, and even before, it begins in the Advertising & Marketing stage, where players are given First Glance opportunities.  These could actually come from trailers and other pre-marketing strategies, such as demos or screenshots.  During this time, a player is contemplating whether he or she wants to buy the game when it is available.  The player also develops expectation levels about how good they think the game will be.  If the expectation is more than what is essentially their threshold for buying the game, then they will do so.

At that point, the game is bought, and the player enters the First Play stage.  This represents the game's Playability phase.  At this point, all expectation is either brought to realization or it isn't.  If it is, and the game successfully minimizes distraction from immersion, then the player will keep playing it, absorbing the content and entering the "Game Replay" stage.

At the point of Game Replay, the player has made the conscious choice to play the game for various reason encompassing the aspects of replayability.  All the while, playability considerations remain important, because unplayable content will add to the player's growing list of reasons to quit the game.  If that list of reasons becomes too heavy, the player will quit, which is the final stage of gameplay lifecycles.

Quitting a game isn't so bad as it sounds, as long as its for the right reasons.  The wrong reasons mean that the game didn't provide enough reasons to keep playing, i.e. the aspects of replayability.  Other wrong reasons could mean the game didn't minimize distractions from immersion.  Sometimes such distractions are impossible to avoid -- the player could simply be too busy for good life reasons.  Other distractions should and must be avoided, such as game lag (network or system), discontinuities in the story, bugs and defects, unfair content (i.e. challenge flow zone not correct), and more.

In any case, the player must quit at some point.  This is inevitable.  When that does happen, the player can resume game play at any time at a later date.  If they sell the game, they may be reconvinced through First Glance to buy it again.  If they keep the game, they may decide to simply play it later, with different experiences (playing for impact) or for other reasons.  And lastly, the most common, they quit because they're simply done (or ran out of time) for the day.  Their gameplay session done, they'll go to sleep, wake up the next morning, go to work, come home and have another gameplay session in the Game Replay stage, and so on.

Understanding the gameplay lifecycle is important because, it can help game developers understand how their end-users are behaving.  It is likely something they already know, deep-down inside, but to put it to voice and reason and on paper can be very helpful.  First and foremost, developers should know that every product they make has the destiny of being quit by their end-users.  But that isn't a bad thing as long as its for the right reasons.  Understanding the branch points when players make their decisions can help identify what the reasons might be.  For example, if players aren't committing to purchasing the game, then its because of poor First Glances, which could be due to bad advertising & marketing.  With this kind of information, the developers can then address those concerns, and make their game (or the next one) a little better.

Thursday, August 17, 2017

Advertising and Marketing in the Game Industry

Advertising and marketing are some lesser talked about topics in game design, but I find them important.  They may fall outside the domain of software developers and game designers, but at least a solid theory of what they are and why they're important should be a requisite for any successful game developer.  These topics not only encompass game development, but also other forms of entertainment, such as movie production and book authoring.

Advertising

Advertising is necessary because it lets people know about your game.  It is a complement to virality, and you need both.  With virality, all the advertising in the world will do little good, as virality can work both ways - it can advocate your game or it can alienate your game.  Players who love the game will tell their friends.  Players who don't will also tell their friends that they don't, which will discourage others from buying it, despite seeing it being advertised.

With a high virality, meaning players greatly advocate to their friends that they enjoy the game and that it's worth their time and cost to buy, the game advertises itself locally as popularity spreads.  Without advertisement, that virality will remain localized and will not spread as much globally.  With advertisement in addition to great virality, many "initial contact points" occur, and from within each, the game is spread virally.  This is optimal.

Marketing

Marketing is also just as important.  If you have both advertisement and virality, the popularity does little good if buyers can't find a location to purchase the game.  The internet today is an excellent resource for marketing today, and there are still in-person options available for shops like Gamestop, Walmart, Best Buy and others.  With in-person shops, research must be done to determine how many copies should be provided to the shop, and the rate of purchase for restock.  An audience must also be researched.  The game may sell better in Pennsylvania than it does in Nevada, for example.  If that were the case, Gamestops in Pennsylvania should get more copies of the game to sell.

Marketing via the internet is another topic.  Online retailers like Amazon are already quite popular.  Other retailers need to be advertised so that potential buyers are aware of where to go.  And hence, to market properly sometimes you need to advertise your marketing strategy.

Summary

Both advertisement and marketing is necessary for successful game development.  This also includes virality of the game product, which arises as a result of good game design.  Advertising lets players know about your game, and marketing lets players know how to find it.  Successful marketing thereby also needs to be advertised along with your game.

Tuesday, July 25, 2017

BSP Dungeon Generation

Overview

One topic I love to talk about is an algorithm for building random dungeons.  A dungeon is essentially a maze which could be one of many styles.  The style of dungeons that I enjoy is one where there are connected rooms, and one must crawl their way through the dungeon in search of something, perhaps an exit.

The Binary Space Partitioning (BSP) algorithm is a very interesting one, because it provides an absolutely wonderful way of building a random dungeon in the style that I enjoy.  When combined with dungeon generation, it can develop truly fantastic procedural content generation (PCG).  Behold:

A random dungeon built using the BSP algorithm.  The green triangle is the player and the red stairs represent an exit.
This kind of dungeon is special because it holds a number of properties.  It will always be fully connected, meaning there will never be an area of the dungeon inaccessible from the rest.  Additionally, there will never be any cycles (in terms of rooms), meaning the pathway from any room in the dungeon to any other is unique.

The fully connected property is very cool in PCG.  It prevents the need to perform content validation, meaning the complexity for this kind of dungeon generation is efficient, whereas this is sometimes a drawback to deploying PCG solutions in gaming.

Details

As a recursive algorithm, this kind of dungeon generation is difficult to analyze.  It works by roughly splitting the area until the rooms are small enough, but it also does so in a random manner.  Consider the starting point, which is a dungeon with no interior walls and only an exterior outside boundary wall:

An empty dungeon with only the player and an exit.


The first step of our algorithm is to then choose randomly to either split this in half vertically or horizontally.  Running this with a fixed random seed, I can pause the algorithm and tell it when to stop, allowing me to generate these pictures.  We can see that in the first division, the algorithm chose to split horizontally.

A single partition has generated a dungeon having two rooms.

In choosing to split horizontally, the algorithm chose a semi-random location to do so; somewhere near the middle, for aesthetic purposes, and not riding along the edges of the outer dungeon.  After adding the wall for the split, the next step was to provide an entryway to reach from one side to the other.  This is what allows for the fully connected property.

Going one step further, the algorithm will traverse into both of the newly created halves.

An addition split in the northern room now produces a three-room dungeon.
Here, recursion stepped into the top half, where it again chose to split horizontally.  An entryway was placed, and two more partitions were created.

Four-room dungeon with yet another partition.


Continuing into the top-most of the new partitions, a split was chosen vertically.  The entryway was placed, and recursion continues into both of the new partitions.  Only this time, since the (top left) room was considered sufficiently small enough (termination criteria of the recursion), it stopped subdividing and moves onto the next sibling (top right room).

The same situation happens in that room as well, and so the traversal visits the next sibling, which is the middle room.  The middle is fortunately wide enough to split vertically, although not tall enough to split horizontally, so the choice is forced to be a vertical split.

Five-room dungeon.

And so on.  These middle rooms are small enough.  Hence, we move onto the bottom room which again can only be split vertically, giving us our final result as that split produces sufficiently small rooms.

In each of these partitions, care is given not to select a split that might potentially obscure a previously installed entryway.

The BSP algorithm also has a by-product, called the BSP-Tree, which is easy to see.  The root node is the empty room, and a single split divides the tree into two.  It is always a binary tree and it is with this tree we can prove that the dungeon is fully connected.

Conclusion


There are many applications of the BSP algorithm, but creating dungeons with it is one of my favorite.  Hopefully this blog post will have enlightened a game developer and inspired ideas.  In the future, I will drop some code onto this post and detail how it works to implement this kind of random dungeon generation.


Friday, June 9, 2017

Unit Testing and Test Driven Development (TDD)

Since my time with GE, I've learned a lot about the Agile Software Development process.  It had always been something I was exposed with, especially throughout my doctoral studies.  I mean after all, I did build a medium sized simulation of agile requirements engineering called POM3.  So going forward, I was excited to dig around into the wealth of knowledge already out there surrounding the topic of unit testing.  And here's what I found out.

Overview


Unit tests are an essential part of test driven development (TDD) and is part of the Agile Paradigm for software development.  "Get something working now and perfect it later."  Unit tests provide the most basic form of testing available to the developer and they are a great boon in aiding the developer in implementing features and user stories.  Some benefits are listed here:
  • Very cheap to run given their unitary nature in a decreased complexity environment
  • Offers an entry point to otherwise complex code
  • Very easily facilitates automation as a form of code-validation upon code check-in
  • Can be very entertaining to see failing tests made passing
It can be difficult to convince project managers to the benefit of unit testing.  Why waste time writing unit tests?  The simple answer: it is an effective means to retire risk early, thus saving on project costs in the long run.  It is important to note though, that this kind of investment is not for everyone.  Unit tests require maintenance, and if requirements often change, then unit tests need to be updated.  There are ways to mitigate these hindrances, however, by writing good unit tests that usually lead to good design.

Reading

Kent Beck is one of the premier authors on test driven development and unit testing, having introduced the concepts in 1970.  Your first stop for unit test literature should be here, and its not even that large of a book:
Another great book on Unit Testing, and in .NET, by author Roy Osherove, which is a bit newer:
Martin Fowler is also one of the original authors of the Agile Manifesto.  You can also find a wealth of content on his personal website.  Also a co-author (along with Kent Beck, listed above) of a good read on Refactoring.

Summary: How To Unit Test

TDD proposes unit testing as an integral part of development.  Before even typing a single key stroke, you should sit down and think about the user story you're working on.  That's step one -- to create a list of tests that you want to run.  The list of tests should be driven to cover as many code paths as possible around the user story.  The list should also be sorted in easiest-first order, where easy is defined as requiring the least amount of code to make it pass.
Each unit test should basically contain a standard arrange-act-assert (AAA) framework.  The arrange section provides some setup code that enables the calling of tested functionality in the 'act' portion of the test, and finally, the 'assert' section validates the functionality.  Consider writing each unit test in a reverse fashion: write assertions first, then act, and then arrange.
Writing your first test should occur before writing any production code.  At first, it should be a test that doesn't compile properly.  If you haven't written anything on the production side, then you'll have to provide the basic skeleton necessary to get the test to compile.  When the test is working properly, you'll get your first failing test, and will need to make it green by adding the code necessary to pass the test.  With a passing test comes the time to do any possible refactoring to clean up the code on both the test and production code.  Any then you move on to the next test in the list, repeating this red-green-refactor flow.  As you develop more tests, remember that each previous one must also pass, and the opportunity to refactor will likely be greater.  Typically this process is known as "red-green-refactor".
To Recap:
  1. Come up with a list of tests
  2. Write a failing test
  3. Make changes to code to pass that test
  4. Refactor code and move onto next test in list

Principles

The following are a list of seven ideas that can help with making good unit tests.  This list of principles doesn't necessarily come from any single source – it is a list of principles that came together as a result of digging through dozens of them.  At the end of this page is a rather large list of links that point to all sorts of discussions on unit testing and TDD in general, and they are definitely a recommended read for anyone interested.

#1: Unit Tests Are Not About Finding Bugs

Unit tests are actually about preventing bugs.  This is most often emphasized by automating the tests prior to check-in of new code.  If any existing unit tests are failing, then the build server will not accept your code changes.  This is a preventative measure.

#2: Use Mocks and Don't Use Mocks

You should do both.  Tests should both validate the functionality of code as well as its behavior.  When not mocked, a method can be tested to see if it returns the correct result.  When mocked, the method is tested to see if it was called properly and with the correct parameters. Granted, in smaller projects, mocks may not make a lot of sense given the triviality of the project.  Equally so, larger projects may inhibit the use of not mocking, since mocked objects can help to reduce complexity and provide that necessary level of isolation in a unit test.

#3. Everything Public Must Be Tested

So don't make everything public!  This may be a tendency, but a good design will probably hide a lot of layers of private abstraction behind a public interface.  If you do that, then you only need to test the public interface.  A test-first design will probably facilitate this.  Remember that if a five public classes each have five public dependencies, then you need to test twenty-five things.  And if requirements change, the code changes and all of your unit tests also have to be updated.  That's a lot of work!  

#4: Use Less dependencies

Dependencies should also be tested.  So it makes sense that if you have a lot of them, that's a lot of work.  If requirements change, code must be changed and so too do all the tests.  A lot of dependencies may sometimes exist because of duplication, and a good unit testing practice is to refactor these under common public interfaces.

#5: Don't Mock Everything

To mock a class object, it must be public.  Recalling from principle #3, that could be bad if you mock everything.  There are good suggestions on when to mock.  File IO is one of these, but DB access is probably not.  One good rule of thumb is to mock across significant architectural boundaries, and not within.  Also, don't mock third party tools that are not owned, since they can change at whim.  Remember the purpose of mocks: isolation.

#6: One Behavior One Test

Do try to keep each unit test down to one single assert.  That may not always be possible, but the premise remains.  A "unit" test should be testing a single "unit" of your software.  That *usually* means that one project is one test project, one class is one test class, and one method is at least one test case.  If you have more than one asserts in a single test case, consider the possibility of splitting the test into two cases.

#7: DAMP vs DRY

In principle, favor DRY in production code and DAMP in test code.  DAMP stands for "descriptive and meaningful phrases".  DRY stands for "don't repeat yourself".  Probably coined by Jay Fields (https://leanpub.com/wewut).  These two are not necessarily opposites, and you should quite certainly always be removing duplication as a means to refactor in both production and test code.  More than being a drab sequence of statements in test code, there should be a higher emphasis on "easier to read" in test code.  This means you can escape some standard patterns of good production code design, such as having method names like "TestThatWhenAdding2And2YouGet4" and "SetupTheCalculatorSoThatICanControlItWithMyPrivateAPI".  The reason for this is that whenever a test case fails, it should be immediately and directly clear why it failed.

Tuesday, March 21, 2017

Evolution - Survival of Fittest

Orange dots are animals.  Green dots are plants.  Can the animals adapt and survive to your conditions?

Evolution is a "game" or rather, more of a simulation really, taken from the book "Land of Lisp" by Conrad Barski (see: http://landoflisp.com/), where it was written in Lisp.  I created a demo of that game a while back, in Lua using the Love module for graphics.  Today, I've finished a demo of that game with more sophisticated GUI controls in Visual C# with .NET.


Overview

Evolution starts with a world that includes plants and animals.  Plants do not move and provide energy to animals that happen across them.  Animals consist of genetic material that guides their motion, as they expend energy while searching for food to sustain themselves, and ultimately, to reproduce and grow as a society.  Reproductions halve an animal's energy and their newly created offspring have the chance to incur mutations to their direction-sense genetic material.  During the course of a single "day" in the game, new plants are added to the world and they are more frequently added into the "lush forest" area of the map, a special section of the world designated by a square box.

Hence, it stands to region that from an evolutionary sense, and under the right conditions, the animals will evolve as a society that thrives wherever the lush forest is.  Any animal that adventures beyond the lush forest becomes a "roamer", and its chances of survival and reproduction are much less in the severe wilds.

GUI Controls

Under the right conditions, its easy to see, upon firing up the simulator provided by this C# demo, that the animal population will indeed converge fairly quickly upon the lush forest.  To make things more interesting, I've provided a number of "god" controls for the user to play with and see how they effect the natural evolution of the animals in the game.

Lush Forest

using the mouse, the user can click to establish a new grounds for the lush forest.  Additionally, the mouse wheel can control the size of the lush forest.  The larger the forest, the more active the plant life within needs to be, or else, the lush forest will just seem like another section of the entire world without any special properties.

Speed Controls 

the bottom right offers a number of controls for expediting the length of each day.  This helps to see convergence happen much quicker.

Parameters

A number of parameters are editable in this demo.

  • "Plant Growth" specifies the number of new plants per day to be added in random places in the entire world.
  •  "Lush Plant Growth" specifies the number of new plants per day added in the lush forest section.
  •  "Animal Energy Use" specifies how much energy per day is spent by each animal
  •  "Animal Reprod Energy" specifies how much energy an animal requires before it can reproduce.
  •  "Initial Animals" specifies how many initial animals to start with in the simulation
  •  "Plant Energy" specifies how much energy an animal will gain when it eats a plant


4-Way/8-Way/16-Way

Animals in the world follow one of these three systems.  4-way are the cardinal four directions while 8-way adds the cardinal diagonals.  16-way adds eight more directions that represent the "L" steps a Knight can take on a chess board.  You might expect learned animals to figure out that more advanced directional choices are higher on the evolutionary chain than the simplest four cardinal directions, unless the lush forest was so small that every "L" step might cause an animal to keep "missing" where plants are.

Wrap World Control

When checked, the control indicates that animals that walk off the edges of the world will wrap around to the other side.  Otherwise, animals that prefer a single direction are doomed to stick to the wall until they die.

Interesting Scenarios

Sporadic Microbursts

Try adjusting the "Animal Reprod Energy" to something very small, perhaps even to 1 energy.  Animals will reproduce every turn they get, halving their energy until they become so halved and weakened that they die.  This will result in extremely intense but also awfully short population bursts.

Crossroads

Sometimes an animal will learn that all it has to do to survive is to walk in a single direction forever, bounding around the world with enough energy provided to it from the plant it eats from the lush forest.  Now go ahead and be cruel and turn off the world wrapping.  If you wait for a lot of very high-energy animals to get stuck on the wall, and then re-enable world wrapping, you will begin to see some cool visual patterns among all of the animals as they bound across the ends of the world in unison.

Nothing to Learn

If plant growth inside and outside of the lush forest are roughly equivalent per cell, then you'll begin to see fairly consistent randomized motion among all the animals, as the conditions for life are simply not harsh enough to promote adaptation behaviors.

Too Harsh to Live

If you set conditions for animals to live that are too harsh, then a civilization of animals will never be possible.  Animals will die out before they ever find food, and become extinct.  If this happens in auto mode, the simulation will automatically restart.

How to Play

You can grab the file from here: http://fun.unbox.org/apps/Evolution.exe.  Your computer will probably suspect this file as malicious, so you may need to bypass the warnings.

Requirements

.Net Framework, maybe (try: https://www.microsoft.com/en-us/download/details.aspx?id=53344)

Monday, December 5, 2016

Supervised vs Unsupervised Data Science

After I finished my Ph.D, I had the opportunity to work for a startup company located in Reno, NV, called LoadIQ.  The domain subject of which I would be completing my initial postdoctoral work with them was in energy and non-intrusive load monitoring (NILM).  Of course this field to me at the time was a blind one -- I was a software engineer with very little to no exposure to anything electrical.  Luckily, I was able to successfully dive into that field and found out that I was absorbing the material very rapidly.  I thought then what I had always thought -- I was first and foremost an engineer, talented at finding out how things work.  Writing code for the energy domain was no different: I had to discover that necessary understanding and then I was able to interface with the domain through my code.

Granted, there are still many things about energy that I do not know.  My experience with the field is very hands-on, and I often find myself stumbling over new and old buzzwords.  I have an understanding, but it is my own, with my own terminology and syntax that relates to my own coding style and the systems I engineered during my time at LoadIQ.  One way to overcome this is to study as much as I can by reading research papers and looking at other companies in the energy software domain - by seeing how others talk about energy and then consolidate their words with my own.

I then later wrote a paper for the NILM Workshop back in March of 2016.  My initial drafts here were certainly void of what the proper phrasings for many of my concepts were, but together with my supervisor, I was able to polish out a good submission that then later became accepted by the peer-review board for their workshop.  I had written papers for publications in journals and conferences before -- this one was quite a bit less hassle as it was accepted on its first review and this I know to be a proud accomplishment.

One other way to become more engrossed with the energy domain is to work with other companies.  Indeed just this week, I have the opportunity to interview with another company.  From researching their company, I see right away a dozen new buzzwords making up their phraseology that were strange and new to me -- DERs, DROMS, VPP, and more.  And I realized then that working with other companies was the absolute perfect way to expand my knowledge and experience with the energy domain.  I am always and ever will be first a software engineer, prominent at writing code, especially Python.  But new things do excite me, and I take pleasure in being able to work with new things and apply my engineering expertise to them.

One thing had always worried me: I was given the title of Chief Data Scientist -- I was the only data scientist at LoadIQ at the time, but if we were to hire and expand, I would certainly be in leadership and management roles over others.  I viewed my title as one in where I was given control and leadership of how we pursued our everlasting quest for further algorithmic improvements and quality assurance.  I'm proud of that, but the thing that worries me is what others think when they see the phrase "data scientist", because as I hear it, there seems to be many different styles of data science.  Was I actually a data scientist or was I just a software-systems engineer?

However, the more I think of it, the less I feel confused.  I believe I really am a data scientist, just not the kind most people might think of when they hear that job role.  To be specific: I believe there are really only two kinds of data science.  There's the more common "supervised" data science as it is related to studying training data and building models that can successfully predict missing class labels (of data in the future or past).  A clear example of that is to estimate the amount of energy a building might use for a particular hour of a day in a year.  By studying past data from the energy usage of that building, we can build a very solid model that can take advantage of features such as temperature, day of week, hour of the day, etc, and predict to less than 5% error margin, what the energy usage might be.

Back to LoadIQ: as a data scientist there, my primary task was a little different.  Due to the nature of the product we were serving, there was no prior training data to learn from.  Any model built to deliver our predictions were entirely devoid of knowing the "truth" of the class labels, and we were forced to fall back on internal consistency metrics to make sure our results were tangible enough to provide quality assurance.  Moreover, our models being built were not typical of data science -- we didn't use Random Forests or Neural Networks or any other mathematical model such as Linear Regression.  Instead, we had to be much more clever and devise very innovative algorithms which may in time, come to gain names of fame in our field of NILM.

As I explore my career, I remain primarily interested in "data science", whether it be unsupervised or supervised.  This I realize explores a greatly nuanced field that crosses over into Machine Learning.  One very interesting and simple method is called Decision Trees, which can be used in the typical model building nature of supervised data science and training data.  If there's one thing you should know when you study decision trees, its to understand what is meant by "entropy and information gain".  I end this blog post by leaving you a superb answer for this, written in response to a StackOverflow question by username 'Amro', located at http://stackoverflow.com/questions/1859554/what-is-entropy-and-information-gain.