Ben and I did some work over the weekend. I have taught him a few things over the last couple of years, but we do it so sporadically that it's hard to keep the information fresh in his mind. So we started with this exercise: opened several of the programs that he has worked on in the past, then read through each one and predicted what it was going to do, and why. Doing this helped him get back into his headspace from earlier sessions, and also drilled the syntax back into his mind pretty quickly. Speaking for myself, I also find that reading my own code can help to refamiliarize myself with a language much more quickly than reading somebody else's examples.
Up until now it was clear that we'd done a lot of programs that were really brief -- single problem, single solution. Print all the powers of two up to a million. Print out a times table. Create a simple password verification program (which insults you if you fail; that's a ten year old mindset for you). These problems are interesting in their own right, but the real fun of programming is making a project with no immediate end goal, something you can tinker with over a long period.
Ben is very into gaming, just like his dad. We've been playing World of Warcraft together since he was seven. This seemed like a promising starting point, so I had him create a simple system of rules which could represent a fight between a hero and a monster. So we started out with a few basic hard coded numbers: Hero hit points, monster hit points, hero damage value, monster damage value. Then we wrote a loop so that the fight would keep going until one of the hit point values dropped below zero.
The program is pretty predictable at this point; the beauty of the concept is that we can build on the basic concept over time. So the first thing Ben wanted to do was tweak the numbers: The hero should always win, but just barely. So we did some math to figure out how to make that happen, and we saw the outcome change as the starting values got closer to numbers that "felt right."
This was a good time to introduce functions, which I don't think I've explained in detail before. We had a function for printing the current status ("The hero has X hit points! The monster has Y hit points!"); a function called "hithero" and another called "hitmonster". Initially the hit functions removed a fixed amount of damage; then we got a little more sophisticated, passed in the damage as a parameter, and also printed the action to the screen. After that we also added in weapon descriptions, so it then said "The hero hit the monster for 20 damage with his sword of epicness!"
It's a fun exercise and it has Ben's enthusiasm up, so he now thinks of it as "The first program I wrote mostly by myself!" (I did give him a whole lot of guidance, actually, but I've let him steer the creative direction of the program, so he does have plenty to be proud about.)
We now have a bug and feature wish list which is surely going to grow:
- Make it so hit points can't go negative.
- Make a "death" message.
- Have multiple kinds of weapons; enable weapon switching.
- Randomize damage within a range, like 16-24.
- Allow the hero to pick a type of action, a la Pokemon, such as a direct damage attack or a debuff attack.
- At some point we should probably start discussing object-oriented programming, before we get to the point where we bring in multiple monsters.
- Item drops?
- Visiting locations?
- Ben really wants to make graphics, but that is a very advanced topic, and I'd rather he get solid with the fundamentals before touching that one.
- I'm a web programmer, and putting stuff in web pages is a great way to showcase your work to friends. So maybe that's a better direction to go than graphics.
Obviously the best part of programming, as per the title of this blog, is building castles in the air -- constructing projects which seems to take on their own reality. So I'm looking forward to some more sessions where we make this thing interesting, while keeping it accessible to a kid who will be twelve soon.