Sunday, December 28, 2014

TDD as the crack cocaine of software

The psychologist Mihaly Csikszentmihalyi popularized the term "flow" to describe states of absorption in which attention is so narrowly focused on an activity that a sense of time fades, along with the troubles and concerns of day-to-day life. "Flow provides an escape from the chaos of the quotidian," he wrote. 
This is a snippet from the highly recommended book Addiction by Design, which not only gives you an incredibly complete overview of the gambling industry, but also insights into the human psyche which apply far outside the domain of gambling.

For me, this book was an eye-opener, with the biggest realization being that most gamblers don't play to win. They play to lose. To lose themselves. Slot machines and video poker are for many people the quickest and surest way to reach flow. It's this phenomenon that has earned machine gambling the title of "the crack cocaine of gambling."

It's not just gamblers that crave for flow though, we all do.

Some of us get up early on the weekends, to drive halfway across the country for a few hours of intensive mountain biking. Others come home after work, throw their laptop in the corner, to engage in an online shooter, zoning out for a good hour. Others will accidentally waste their entire Sunday morning solving a crossword puzzle they bumped on reading the newspaper.

All these activities meet a specific set of preconditions.
Csikszentmihalyi identified four preconditions of flow: first, each moment of the activity must have a little goal; second, the rules of attaining that goal must be clear; third, the activity must give immediate feedback so that one has certainty, from moment to moment, on where one stands; fourth, the tasks of the activity must be matched with operational skills, bestowing a sense of simultaneous control and challenge.
Machine play has all these properties. Let's look at video poker. The goal is to make a winning combination. The set of winning combinations should be easy enough to remember; they're similar to live poker. After pushing "deal" you get five cards. The player decides which cards to "hold". Pushing the "deal" button the second time will draw new cards from the same virtual deck. After the draw, you immediately know whether you've won or lost. Feedback is instantaneous. A game is over in a few seconds. Although the outcome is determined by chance, there is some degree of skill involved; it's up to you to hold the right cards.

As programmers we're lucky enough to inadvertently end up in the zone frequently. Without a doubt, it's in this state most of us do our best work. In the zone, it's constant feedback and a sense of moving forward that keep me going. One could argue that the zone is inherent to the activity of programming. I'd say that the length of the feedback loop and the size of the goals are critical and hard to maintain without working at it.

In this regard, there are a few techniques that help me reach a state of flow. At first I could get by just trying to get the code to compile or to just launch whatever it was I was working on. But once you're comfortable with a code base, getting it to compile isn't much of a challenge, and having to start your application to get feedback gets old real quick. Most often it's TDD that helps me get there these days. You start of with a failing test, your mission: to make it pass. The rules are simple; when your test goes from red to green, you're allowed to move on. It's important that tests are fast to be able to give you that immediate feedback. How fast? Fast enough for you not to lose focus. It stands for itself that the fourth precondition is met too; you're writing the code, doing your best to bend it your way.

When TDD is sold as a productivity booster, it are often strengths such as automated continuous validation of correctness, partitioning of work in smaller units and cleaner and better designed code that are used as arguments. While these are valid arguments, it's a shame that the power of TDD as a consistent gateway to flow gets neglected or undersold.

Getting in the zone by yourself is one thing, getting there surrounded by a group of people is often out of the question. Here Event Storming has helped me out. Small goals; what happens before this event? Rules; write the previous event down on a yellow post-it. Feedback; once the post-it is up, we see that we're reaching a better understanding of the big picture. Control and challenge; you're the one searching for deeper insight, writing and putting up the post-its.

The activities that get me in a state of flow are the ones that I enjoy the most and which enable me to output my best results. If you reread the four preconditions, and assess the things that get you going, you might learn that the same goes for you.

Sunday, December 14, 2014

Spinning the wheel: clustering and near misses

The previous post showed a simple model casinos use to manipulate the odds. Instead of relying on the physical wheel for randomness, they rely on a virtual list of indexes that maps to the physical wheel.

Using that same model, it's easy to fiddle with the virtual indexes so that they map to misses right next to the winning pocket, creating "near misses". "Near misses" make players feel less like losing, since you "almost won". Casinos use this technique to get the next spin out of you.

Let's create more specific labels - a label for each individual pocket.

The winning pocket is in the physical wheel at index two. We need the virtual indexes to make clusters next to the winning label. Four indexes map to Miss2, one maps to Win and three map to Miss3. We intentionally ignore Miss1.

Spinning the wheel one million times reveals the pattern; Miss1 gets ignored, while we hardly ever win but very often "just" miss.

Since the law states that randomness and visualization are two separate concepts, casinos are free to operate in this gray zone, as long as randomness stays untouched.

Thursday, December 11, 2014

Spinning the wheel: manipulating the odds

The previous post defined a basic set of data structures and functions to spin a wheel of fortune in F#.

There was very little mystery to that implementation though. The physical wheel had four pockets and spinning the wheel would land you a win one out of four spins. As a casino, it's impossible to come up with an interesting payout using this model.

To juice up the pot, casinos started adding more pockets to the wheel of fortune. This meant that the odds were lower, but the possible gain was higher. More pockets also allowed casinos to play with alternative payouts, such as multiple smaller pots instead of one big one.

Adding pockets to the wheel didn't turn out the way casinos hoped for though. Although players were drawn to a bigger price pot, they were more intimidated by the size of the wheel - it was obvious that the chances of winning were very slim now.

Today, instead of having the physical wheel determine randomness, randomness is determined virtually.

Casinos now define a second set of virtual indexes that map to the indexes of the physical wheel.

There are seven virtual indexes; six map to a miss pocket and only one maps to a win pocket - one out of seven is a win.

Instead of picking a random index in the physical wheel, we now pick a random index in the virtual indexes and map that back to an index in the physical wheel.

When we now spin the wheel a million times, the outcome is different. Although the physical wheel has four pockets, we now only win one out of seven times or 14% of the time.

Using this technique, the physical wheel only serves for interaction and visualization. Randomness is determined virtually, not physically.

In my next post, I'll describe how casinos have tweaked this model to create "near misses", making players feel as if they just missed the big pot.

Tuesday, December 9, 2014

Spinning the wheel

In this post, I'll define a basic set of data structures and functions to spin a wheel of fortune. In the next post, I'll show you the simple model casinos use to build a bigger, more attractive pot, without touching the physical wheel and without losing money. Finally, I'll show you how casinos tweak that model to bend the odds and create near misses.

Let's say we have a physical wheel with four pockets, which are labeled either miss or win.

Three out of four pockets are labeled as a miss, one is labeled as a win. This makes the odds to win one out of four, or 25%.

Spinning the wheel, we should end up in one of four pockets. We can do this by picking a random index of the physical wheel.

To avoid a shoulder injury spinning the wheel multiple times, we'll define a function that does this for us instead.

Now I can spin the wheel one million times.

If the math adds up, we should win 25% of the time. To verify this, we'll group the results by label and print them.

Give or take a few hundred spins, we're pretty close to winning 25% of the time.

When the odds are this fair, it's impossible to come up with an attractive enough payout without the casino going broke. What if we wanted to advertise a bigger pot, while keeping the same physical wheel, without losing money? Tomorrow, I'll write about the simple model casinos have been using to achieve this.