Saturday, April 12, 2014

Vaisahki

Someone threw a party in our street today, and 50,000 people showed up. We attended last year as well, the event took place very soon after we moved into our house. The weather was awesome, and there is free food everywhere. Xander and Amy got a photo op with Justin Trudeau.

Monday, March 24, 2014

My Toronto stock market adventure so far.

Three years ago I began my Toronto Stock market adventure. So it's a good time to reflect. There is some good news: I beat the TSX market index by quite a bit. The bad news is that in 3 yrs time, the index was overall just flat.

The big spike in portfolio value (blue) of feb 1 2012, was thanks to a takeover of Gennum by Semtech. The price of Gennum more than doubled that day.

A 13.8% return is modest for a 3yr investment, but it beats the lousy interest on saving accounts these days. I remember saving as a child in the Netherlands, and getting a hefty 10% annual interest from 'the Zilvervloot'. I also traded on NYSE and Nasdaq. Even though the US stocks were more profitable than my Canadian stock, I failed to match either NYSE or Nasdaq performance.

Anyway, my lessons learned so far:

  • Got burned by Arise, a solar panel company. It went bankrupt soon after I bought it. Don't get suckered into green tech: they don't all have Tesla like stock performance. They typically falter.
  • You need a lot of patience with irrational market sentiments. Why is AAPL still not valued properly? It's my biggest US holding, and I lost money on it.
  • Take over bids tend to be good news, with an instant hike in stock price. It happened to me a lot. I think a lot of Canadian industries are consolidating.
  • Often, the real money can be made on dividends, instead of stock price. It pays to concentrate on companies that pay their investors well.
  • My biggest money maker was a US stock: Stratasys, which makes 3D printers. When I bought it, it was expensive, but still it tripled in value in a short period. Market leaders in brand new industries tend to do well. (I missed out on Tesla, but that would be in the same category.)

Tuesday, December 31, 2013

2013 totals

I have published some download statistics of The Little Crane That Could. Like 2012, the year 2013 was another blast.

Wednesday, December 11, 2013

Bitcoin, logarithmically

Some time ago, I purchased a bitcoin for a little under $300,- CAD. My reasoning went like this:

  • There is a non-zero chance of bitcoin replacing USD as default currency. Let's put it at 1 in 1000.
  • There is a hard limit of 21M bitcoins.
  • If in 2030, the world uses bitcoins, then those 21M coins will represent the entire money supply of the world's default currency.
  • My 1 bitcoin will represent 1/21Mth of the world's money in 2030, with a 1:1000 chance.
  • The world money supply divided by 21M and then divided by 1000, is still worth a lot more than the $300,- I paid for it.
In addition, I've started mining the bitcoin as well, using an ASIC miner. The bitcoin price fluctuates wildly, and it's hard to make sense of it. However, I find that treating the price logarithmically helps a lot. You can actually make out a trend, when you use that. Here is the price up to dec 11, 2013.

Friday, August 2, 2013

A spin-off.

Please let me introduce to you, a new blog thelittleengineerthatcould.blogspot.ca. It is a spin off from this blog. I decided to do this, so that game development blogs and personal items would not be mixed together anymore. If you like following my indie game development efforts, hop on over! I look forward to reading your comments.

Friday, July 12, 2013

Irrational Investor

Because I've been fortunate with my app store ventures, I have some money to invest. I want to share with you the story behind my worst investment, so that others may learn from my mistakes. When it comes to investing, it is hard to remain rational. One of the psychological hurdles to take, is to let go of buy-price. You should be able to reassess your holding at any time, and sell below cost if necessary. If you can't you are 'anchored' and this will hurt you. Here is what happened to me when I first started investing on the Toronto Stock Exchange:

My instinct was telling me that solar energy would be a growth opportunity, so I sought out solar panel producers. I found these two on the Toronto Stock Exchange:

  • Day4 Energy Inc. (DFE)
  • ARISE Technologies Corporation. (APV)

So I studied them carefully: the earnings, the price, their debt, the news items on them. After this study I decided to go with Day4, as it had just got certified in an important market. So I made the online trade, worth $9000, using the online investment website of my broker (RBC). The thing is: I had typed in the wrong symbol. So there I was, holding $9000,- APV instead of $9000,- DFE.

If I had been rational, I would have sold the APV and bought the DFE. However, I really did not like to spend two more transaction fees of $9.95 each. Psychologically, I was not prepared to take my $20,- loss on a stupid mistake, so I let it be. Hopefully, APV would see some nice yield. In reality, APV was bankrupt within a year, and I lost my entire $9000,- investment in 'green technology.'

I can laugh about it now, but darn, did I feel like a fool. Trying to penny pinch and save $20,- transaction costs, ending up losing my $9000,- principle. Talk about being anchored... Anyway, I still hope that for the rest of my holdings, all I have to do is wait long enough and everything will be in the plus. I'm a long term investor, and see much wisdom in the ideas of Warren Buffet. Currently, my largest holding is AAPL, which currently yielded -24% for me (not counting dividend.) I'm pretty confident that within a 5 years it will be the shooting star it once was, so I don't plan on selling before that one hits the cool $1000,- milestone (or $100,- when the stock finally splits 1:10 or so.)

Thursday, June 6, 2013

Quadratic Equations, solving 8 in one go.

Today I found out that modern intel CPUs can do 256 bit wide SIMD. This is possible with the Advanced Vector Extensions, or AVX. Operating on 8 floats at the same time is even better than what the PS3 Cell processor was capable of. So I wrote this neat little function that can solve 8 quadratic equations in a single go, without branching. It should come in handy when implementing a Fast Marching Method to implement Continuum Crowds. For SIGGRAPH 2008, some people at ATI implemented this on the GPU for their amazing Froblins Demo.

/*
 * solve aX^2 + bX + c = 0
 * solves 8 instances at the same time, using AVX SIMD without any branching to avoid stalls.
 * returns two solutions per equation in root0 and root1.
 * returns FLT_UNDF if there is no solution due to discriminant being negative.
 */
static const __m256 zero8 = _mm256_set_ps( 0, 0, 0, 0,  0, 0, 0, 0 );
static const __m256 undf8 = _mm256_set_ps( FLT_UNDF, FLT_UNDF, FLT_UNDF, FLT_UNDF, FLT_UNDF, FLT_UNDF, FLT_UNDF, FLT_UNDF );
static const __m256 four8 = _mm256_set_ps( 4, 4, 4, 4,  4, 4, 4, 4 );
inline void evaluate_quadratic8( __m256 a, __m256 b, __m256 c, __m256& root0, __m256& root1 )
{
 __m256 minb   = _mm256_sub_ps( zero8, b ); // -b
 __m256 bb     = _mm256_mul_ps( b, b );  // b*b
 __m256 foura  = _mm256_mul_ps( four8, a ); // 4*a
 __m256 fourac = _mm256_mul_ps( foura, c ); // 4*a*c
 __m256 det    = _mm256_sub_ps( bb, fourac ); // b*b - 4*a*c
 __m256 twoa   = _mm256_add_ps( a, a );  // 2*a

 __m256 dvalid = _mm256_cmp_ps( fourac, bb, _CMP_LE_OS );
 __m256 sr     = _mm256_sqrt_ps( det );
 root0 = _mm256_add_ps( minb, sr );
 root1 = _mm256_sub_ps( minb, sr );
 root0 = _mm256_div_ps( root0, twoa );
 root1 = _mm256_div_ps( root1, twoa );

 root0 = _mm256_blendv_ps( undf8, root0, dvalid );
 root1 = _mm256_blendv_ps( undf8, root1, dvalid );
}

Wednesday, May 22, 2013

2012 and 2013 goals.

So, this post is verbatim from an old indiegamer.com forum posting. On this old forum, it was tradition to set goals for the year, share them with the board community, and evaluate afterwards. indiegamer.com is down today, and I suspect it may be gone forever now. Readership was dwindling, spam was a plague, so I think it will be dead, if not now, soon. So let's preserve my goals here on my own blog.

The goals I set for 2012:
  • Add support for this awesome input device to the little crane that could for MacOSX.
    SUCCESS
  • Maintain my 2011 income (had a very good year).
    BIGGER SUCCESS
  • Release my first Android Game.
    SUCCESS
  • Release an update for Hover Biker.
    SUCCESS
  • New level for the little crane that could iOS version.
    SUCCESS
  • Port the little crane that could to Android.
    SUCCESS
  • Attend GDC.
    SUCCESS

It is amazing, but I hit all my goals. Maybe it is true what they say about: writing down goals make them come true. Although I did cheat a tiny bit: 'Port Little Crane to Android' and 'Publish Android Game' were originally intended to be separate games, but meh.

For 2013 I will:
  • Publish an OUYA game.
  • Hit 30K OUYA downloads.
  • Hit 10M downloads (cumulative over all platforms, all years) for Little Crane That Could.
  • Maintain 2012 income.
  • Reach 750 followers on Twitter.
  • Publish my first multiplayer game.

Monday, May 6, 2013

Ethics, not octane

I wonder what would happen if we stopped selecting Octane Numbers at the gas pump. Instead, we pay a premium for fuel that is guaranteed not to fund oppressive regimes. Maybe I am naive, but I think it could solve so many problems. That is why I built the ethics-not-octane website. This could solve so many problems.

Saturday, May 4, 2013

Mad Carpentry Skillz

I inherited my grandfather's carpentry skills, it seems. With a little coaching from my father I managed to build this mean looking stainless steel kitchen in my basement. The parts come mainly from IKEA supplemented with a few Home Depot parts. Water, drainage and vents are self installed as well. If you want to build one like this yourself, look into IKEA's AKURUM line with RUBRIK stainless steel finishing. It is quite time consuming, and I now know why kitchen installs are so expensive. It is simply a whole lot of work. The IKEA parts are quite clever though, and make such a project doable for a handy amateur. A big thanks to my father for all the coaching.

Friday, April 19, 2013

25 releases in 26 months.

I think I can rightfully call myself a game developer dedicated to his creation. The Little Crane That Could saw 25 releases in just 26 months. Each release making it a better game. (Except for the 4.4.1 version which made the game crash upon launch. Argh!) I can only put the blame on myself for that and a little bit on Apple, who just for that particular release, decided not to test my update. (It got approved immediately after going into state 'in review'). And I did not even count the Android, Raspberry Pi and OUYA releases here.

I clearly remember the first release when frankly, it was an unfinished product. I launched with too few levels, without sound, with penetrating music that could not be switched off and other shortcomings. Still it managed to be a hit from week 1. Not day 1, as I also clearly remember my first sales report. I was horrified to find that the game had managed to sell one single copy. At that point I had given up hope, and decided to do contracting jobs from now on, for other people's apps. However, the next days, sales increased 10 fold every day, hitting a high of 6000 sales in a single day. The game still brings in good money, so that is why the updates keep coming. Today I submitted version 5.07 for review by Apple. I hope they test launch it this time before approving.

Wednesday, April 17, 2013

Trailer for Buggy Bang! Bang!

My upcoming title 'Buggy Bang! Bang!' is nearing completion. Therefore, I have created this promotional video with a great soundtrack to give it a nice epic feeling.

EDIT - Now available on iTunes.

Thursday, April 11, 2013

Googling "Little Crane"

Since january 2011, the release date of The Little Crane That Could, people have been googling the term, mainly in the UK and the US. The big spike of dec 2012 coincides with the Android release.

Wednesday, April 10, 2013

False sense of security

So my new house came with Weiser Smart Key locks for the back, garage and basement doors. One morning, I could no longer open my garage. There was no way to get to my car to pickup my little monkey from day care. My builder is a great guy, so was on site with his installer in 15 minutes. They helped me get in by drilling out the lock. The next day, another guy came in and put in a replacement Weiser deadbolt lock. And what do you know, 10 minutes after he left, I discovered the same thing had happened, with a different lock, different set of keys.

At this time, I had lost all confidence in Weiser locks, and decided to replace them all. I got ANSI Grade 1 fixed key deadbolts from Schlage, and installed those on all doors that previously had that Weiser crap on them. They are robust, super smooth, and rated top grade for commercial use. My advice: never go with those 'programmable' locks known as Smart Key or SecureKey. See the photo above of all the useless crappy locks I removed from my house. Professionals rate the Weiser Smart Key of the same caliber as that lock that could be opened with a Bic pen. See this video on how to open any Weiser Smart Key lock in a few seconds.

So to sum up: Never get a programmable key, especially not the crap from Weiser that will lock you out at random. Instead get a lock that is not programmable, and rated ANSI Grade 1, for instance, this one from Schlage.

Wednesday, March 27, 2013

Ackermann

When I created Little Crane 2½ years ago, I naively thought that when a car turns left, both front wheels will turn in at the same angle. This is not the case in real cars, as this would cause scrubbing of the tyre. Instead, the inner wheel in steered in more than the outer wheel.

When creating my next games, A Blocky Kind of Love and Buggy Bang! Bang! I knew better, so implemented proper Ackermann steering. Today I ported this code back into the Little Crane code base, so the next version will feature a smoother ride. I also implemented a drive differential, so that the outer rear wheel is driven to spin faster than the inner rear wheel in turns.

It was invented in 1816 by Georg Lankensperger, whose agent was Rudolf Ackermann. This Rudolf Ackermann is not to be confused by Prof. Dr. Ir. Akkermans.

Friday, March 1, 2013

Proportional Integral Differential

I am a game programmer that spends the bulk of his time on writing physics simulations of virtual worlds. In these virtual worlds, there are typically people or vehicles. When such a person or vehicle is not under player control, but controlled by the computer, we often call this AI (Artificial Intelligence) or NPC (Non player character.) A common problem is to realistically move these entities around in the world.

A naive way to move these virtual actors would be to write code that sets the new position during each frame of the simulation. This is typically how a ghost in pacman or a space invader is moved on the screen. However, for a proper simulation this is the wrong way to do it. Modern complex games use physics simulations that calculates forces and accelerations.

This means that steering an object in the world becomes a very indirect way of steering. The algorithm sets a force (linear, or torque) which results in acceleration, or change in velocity. The velocity, lastly, will change the position and orientation of the object. This makes steering a hard problem: how do you move an object to position X? If X is far away, you would apply force towards X, but if X is near, and we are quickly approaching X, we need to apply force away from X so that we come to a halt on X without overshooting.

Luckily, this problem has been solved for us by the engineers in process control. When heating a building for instance, knowing when and how much to run the heater depends not only on the current and desired temperature, but also how the difference between the two have been changing in the past. If the temperature is rising quickly (because the heater was running full blast) it is time to stop the heater, as the the lag in the system will cause the temperature to continue rising. If a lot of cold air is entering the building causing the temperature not to rise much in the near past, heating needs to be increased. For this, the engineers use so called PID Controllers.

PID control splits the steering into three different components:

  • Proportional (what is the error right now?)
  • Integral (what is the historic error?)
  • Differential (how is the error changing?)
...where the error is simply the difference between the current value and the desired value. Steering based on the differential of the error means that if we are fast approaching the desired value, we steer away, and if we fast retreating from the desired value, we steer towards. Steering based on integral means that the longer we have had a large error in the past, the harder we steer towards the desired value.

Humans actually steer the same way naturally. For instance, when we need to open a door of unknown weight. First we push a little if it is closed. The longer the door remains closed, the harder we push (this is the integral part). And the faster it swings open (error decreases quickly), the less we push it, or even start pulling it. The PID system is nicely adaptive. If a hard wind is blowing the door shut, the integral steering will make that we compensate by pushing harder. This is what is called steady-state-error. The entities in our simulation will seem smarter for it, if they can adapt to changing conditions.

The PID controller calculates the required force for us, each time step in our simulation. The error is calculated from desired and actual values. Note that the desired value does not have to remain fixed, it can be a moving target. PID will cope with this automagically, e.g. when trying to aim a rifle at a chaotically moving target.

So, are there no downsides to this miracle technique? Well, not really, as long as the controller is tuned roughly correctly. We need to determine with what weights we mix the P, I and D control. We need to select three P, I, D coefficients, and the optimal values are typically different in each application. Personally, I find that selecting P roughly 10 times larger than D, and I somewhere in between always makes my steering converging nicely without much overshoot, and reasonably quickly. Note that all three coefficients need to be negative. (We need to steer against current error, against historic error and against rate of change of error. Just start with some default values (-10, -2, -1) and tweak them with the following guide:

  • When system explodes due to excessive force, lower all coefficients.
  • When overshoot is large, increase D, lower I.
  • When convergence is slow, increase P and I, decrease D.
  • When observed value jitters a lot, decrease P and increase I.

It's high time for some code now. The code is really concise, if it carries a little bit of state (previous error, historic error) along with the P,I,D coefficients.

//! Scalar PID controller
typedef struct
{
 float P;
 float I;
 float D;
 float previousError; // Last error
 float integralError; // Historic error
 bool  fresh; // If set, we have no 'last error' yet.
 bool  angular; // Angular PIDs have errors wrap around at -pi and +pi.
} pid1_t;


//! Reset a PID controller. Clears historial error.
void pid1_reset( pid1_t &p )
{
 p.previousError = p.integralError = 0.0f;
 p.fresh = true;
}

//! Calculate the steering force based on current value (ist) and desired value (soll).
float pid1_update( pid1_t &p, float dt, float ist, float soll )
{
 if ( dt <= 0.0f ) return 0.0f;
 float error = ist - soll;
 if ( p.angular )
 {
  // normalize angular error
  error = ( error < -M_PI ) ? error + 2 * M_PI : error;
  error = ( error >  M_PI ) ? error - 2 * M_PI : error;
 }
 p.integralError = ( p.fresh ) ? error : p.integralError;
 p.previousError = ( p.fresh ) ? error : p.previousError;
 p.integralError = ( 1.0f - dt ) * p.integralError +  dt * error;
 float derivativeError = ( error - p.previousError ) / dt;
 p.previousError = error;
 p.fresh = false;
 return p.P * error + p.I * p.integralError + p.D * derivativeError;
}

And to use this PID controller to aim a turret in a tower-defence game:

pid1_t pid;
pid.reset();
pid.angular = true;
pid.P = -10.0f;
pid.I = -2.0f;
pid.D = -1.0f;
while ( simulating )
{
    ...
    float desired = angleTowardsTarget( turret, enemy );
    float actual  = angleOfGun( turret );
    float steer   = pid1_update( &pid, dt, actual, desired );
    applyTorque( turret, steer );
    ...
}

And that is pretty much it. The only thing to watch out for, is that if the turret suddenly selects a different target, the PID controller needs to be reset, so that the historic error based on previous target does not influence the steering for the new target. This causes a quicker convergence. To do this, just clear the historic error. And there you have it, a smoothly targeting turret that does not need kludges for smooth-in/smooth-out parts of a synthetic animation. Animation is bad, simulation is good.

I use this PID code to:

  • Smoothly move my camera.
  • Smoothly reorient my camera.
  • Smoothly have a tank aim at a moving enemy.
  • Smoothly balance a helicopter at a desired attitude.
  • Smoothly push, pull and twist oars of a rowing boat.
  • Smoothly hover a bike over undulating terrain.
  • Smoothly steer a missile towards a fast moving target.
and much much more. To see many of them in action, download one of my games, they are free. Search for 'Abraham Stolk' on Google Play or iOS App Store.