Sunday, June 5, 2011

DDTe2 hours 16 to 17 Infinite Loop Bug

This is the final installment of my making of Dozen Days of Tiles episode 2. At this point in time, the game has been created but a showstopper bug has been discovered.

Finding bugs is never nice, but the very nature of programming makes bugs pretty much an inevitable thing. Bugs are often the result of a very minor mistake, such as was the case with this bug. Thankfully, with tools such as FireBug available, finding the cause of the bug was very easy. By being able to stop the program while it was in an infinite loop allowed me to take a look at the puzzle data at the time the infinite loop was happening which is where I discovered that the puzzle generation would occasionally result in a puzzle that had invalid data in it.

The solution to this problem was to add a sanity check to the fifth phase of the puzzle generation. Instead of simply returning the finished puzzle, phase 5 added the following puzzle verification checking code:

           var cntrRow, cntrCol;
      done = true; // assume valid until proven otherwise
           for (cntrRow = 1; cntrRow < 10; ++cntrRow)
                   for (cntrCol = 1; cntrCol < 10; ++cntrCol)
                           if (this._model.getValue(cntrRow, cntrCol) == 0)
                                   done = false;
           if ( ! done )
               this._phase = 1;
Problem solved. Many programmers would consider their job done. Good programmers, and those who want to become good programmers, know that there is still a bug in the code. This is when a serious look at the puzzle generation phases happens. I like to try and work through what the code is doing to find puzzles, though certainly walking through the code using breakpoints and stepping over/through statements will work.

As I worked through the code in my head, the problem hit me like a flying brick. What a dumb mistake! Setting the phase back to 1 when there is an error is fine, but for some reason, I also set it to the next phase if the row is valid. The next phase change should not happen until after all three rows in the phase have been successfully completed. When I wrote the code I was thinking that I was at the end of the generation, not just the end of the loop. A simple mistake, but that is all it takes.

What was happening was that the first or second row would not be able to generate a valid combination that would work with the puzzle. The loop would continue and if the last row was able to generate a valid combination then the next phase would be triggered. The real bug fix, then, is to take the next phase setting out of the row loop (which it shouldn’t have been in to begin with) and only go to the next phase if the phase has not been set to 1. Likewise, because there may be more iterations in the row loop, when the puzzle is invalid, the row loop should be broken out of.

The problem solved means that the project is finished. For the next episode, I am considering putting a twist on the game in a day challenge. Instead of developing a game in under 24 hours (development time not real time) I am going to instead see how many games I can create in under 24 hours.

No comments: