Cheerful coding for fun
I do programming for living, and running in my free time. That's about it, really.
There was a time though when most of my spare time was spent on sitting at my computer and typing in endless lines of code. That was decades ago, before Internet, in the era of 8-bit computing. And then... a long row of robust family years appeared out of nowhere.
Now here I am, writing this text 5 am in the morning, after a month of hectic hobby programming.
The idea
Did I mention that I do running in my free time? To be more precise, I have developed an interest in a niche sport of foot orienteering, and sprint orienteering in particular. The sprint is a fast paced running sport where you try to find your way in a course, marked as controls in your map, as fast as you can. The events are usually organized in an urban or semi-urban environment.
I like this sport because is much more than running. It is like solving these little navigation puzzles while you run. You can think of playing a game of chess during a 5K road race.
There used to be apps for training the foot navigation skills during the off-season. However, none of those really focused on the tricky route selection challenges special to the sprint discipline. I knew I could change the state of the affairs... just that I don't code in my free time any more.
Except that I do, now. A month ago I decided to give it a try. I even gave the application a name: Sprint-O-Matic.
Week 1: The Foundations
I started to develop the app as a side project, working simultaneously full time at my current employer. The idea was to make a game-like skills training tool for sprint orienteering. A coffee table discussion with my employer seniors resolved any doubts of a conflict of interest - after all I do firmware at work, not applications. The main constraint was the time available time for the hobby project. I knew I had to be fast in order to get it done. For example, I would choose 2D instead of the fancy 3D to save some precious time. Later on I would have all the time to polish, if I was happy with the initial result.
As much as I am a long-time C++ programmer, now I had to make a different choice. A compiled language was just not agile enough for my purpose. After some research, I turned to Python and the Pygame library. Python is famous for speedy development, and Pygame for a decent cross-platform support. My code hosting of choice was GitHub free account.
Fast forward a couple of nights, and I had the first version ready. One map, one course, collision detection with fences and buildings. It was playable, yes, but it was boring. The content is the king, you know. I added better sounds, even a nice home screen, but it did not help much.
The first big idea was to give the user some company: A couple of non-player characters to run along. I named them "pacemakers". For one second I though this is too much for a serious training app, but what a heck. It made the app better.
After struggling some more time with the shortest-route-finder AI for the pacemakers, I saw that this was not enough to save the day. What I needed was more maps and tracks. Much more.
Week 2: Conquer the City
The first experiment to solve the map content problem was to generate it automatically. What a great idea: infinite amounts of randomly generated maps and tracks. I even gave it a name, Infinite Oulu, according to my home town that has a regular block city plan, quite easy to mimic.
Another sequence of late-night coding and the map generator was getting pretty good. So good, that half of the development time was spent on playing. Somehow I was still disappointed. I had this idea to engage the enthusiasts of this niche sport. That would not happen, if I made all the content automatically. The users would need to have a say. This became an issue that reached almost philosophical levels in my head. At the end, I decided to open up the system.
I opened the code under Apache 2.0 license, and more importantly, I also opened the map collection for extension. The technical idea was simple: a public easy-to-edit master list of teams and maps hanging out somewhere in the web, with pointers to other similar lists edited by others, and links to actual map images thereof, ad infinitum. The app would use the excellent requests library to fetch all this data. Any URL to a map image would do, accompanied with the necessary credits and the map license information.
Week 3: Conquer the World
Two weeks and I had a playable game released out to the open, Windows and Linux downloads, a comprehensive README file, and a set of recorded video streams in the YouTube.
领英推荐
The feedback from the early players was nice, so I started to wait for the user-generated content to arrive. One hour, two hours. Patience of a gnat.
Seriously? It takes time to get anybody engaged. Providing the map content takes more than a swipe. If I wanted the app to succeed, there would have to be a super-easy way to get more content.
When it comes to maps, there is plenty of data available. The format might not be that of an orienteering map, though. For example, in most of the cities the OpenStreetMap has quite enough details. The data just needs some re-formatting and decoration and voilà - a sprint orienteering map por favor.
Over a single weekend, 16 hours a day, I constructed a sprint map renderer on top of the wonderful overpass API and threw out 662 sprint orienteering maps from 72 major cities for starters, each of them with infinite number of courses.
Now there is some content! I also revised the means of engagement. From now on, it is enough to suggest me a prospective city or a coordinate, and the map becomes visible to the players in matter of seconds. If I want it to.
Week 4: Conquer the Web
All was good and well, except for one thing.
As a long term firmware developer, I forgot something very important, when it comes to user-facing applications. Not every user is the same. Installing an application from a GitHub page is not easy to everybody. Then again, not everyone even has Windows 11 or Ubuntu 22.04. There are those MacBooks, for instance. Tuning the README file would not get me out of this. I would have to create a Web application.
It sounded easy at first. There is a tool-chain called Pygbag that converts Pygames into browser applications. But there is also a catch. The Python apps run much slower in the browser. Using with my lightning fast PC, I forgot to stay lean when it comes to the consumption of the processor cycles.
In particular, the glorious shortest-route-finder was a multi-process beast. I optimized and optimized it, but it still made the web app sluggish as a sloth in the morning. I was about to give up on it entirely.
One night last week I saw a strange dream. There I was, a speaker in a mathematics conference, ending my speech about the game. After the speech, two gentlemen walked to me and represented their congratulations. Their names were, weird enough, Prof. Clockwise and Prof. Counter-Clockwise. The names were so strange that I woke up. It was 3 am and I knew I had a solution at hand.
In the 80's, there was a popular game called Boulder Dash. In that beautiful game, you would dig tunnels into the soil, collect diamonds, and beware of the monsters. The two notable monsters were the clockwise monster and the counter-clockwise monster. The former would circle any obstacle in a clockwise manner and the latter would do the opposite. These guys would help me with the browser-friendly shortest-route-finder algorithm.
The idea was the following. The new algorithm would walk from the starting point directly towards the goal until it bumped on the first obstacle. Then it would summon a pair of monsters, a clockwise one and a counter-clockwise one, and let them do their thing until one of them reaches the straight line at the other side of the obstacle. In fact, either one or the other is guaranteed to find a route, if it exists at all. The algorithm would follow the successful monster to the other side, and continue to the next obstacle, repeating the procedure as many times as needed, until the goal is reached.
At this point, there would be a route, but not necessarily a smooth one. This is the point when the serious magic happens. I forgot to mention that the algorithm carried a virtual rubber band with it. Now it just tightens the rubber band into a beautiful near-optimal route. And more importantly, this procedure is multiple orders of magnitude faster than the conventional number-cruncher that I had before.
Today
The deployment of the web application was smooth as silk, after the aforementioned problem was solved. I even found a GitHub plugin that triggers automatic web deployments for the Pygame apps. The web app is not yet at the level of the native one, but playable.
The story ends here, for now. The month of cheerful coding is over and I need to be back with the regular rhythm of life. Here is the details of the app if you want to give it a try:
I think I made the right choices on the way - now it is just a matter of minutes if I want to beautify the graphics or add some bells and whistles. That does not distract my exercise routine, does it? And that is the whole point, with cheerful coding for fun.
#technology #software #programming #application #python #web #innovation #development #sports