There have been a few times in my life where I’ve found myself pressing up against the limitations of a particular programming language. This happened to me on my first real programming project – a generative music composer I called (imaginatively) GenComp. Written in PureData and comprising thousands of nodes, it became impossible for me to add to or debug and so I had to bite the bullet and learn a ‘real’ programming language (I chose Java, which was a good foundation for C# and Unity as it turned out!)
A similar thing happened with Mountaineer in early 2016. Mountaineer was built in Processing, which was fine in the early days when all Mountaineer did was draw a trapezoid on a screen, keep the time and write to a CSV file. But as I used Mountaineer, I introduced more and more features – linear regression modelling, real time graph display, previous session exploring, various display modes, etc. This made the application more difficult to add to without introducing bugs.
One of the main problems with Processing is its inability to handle exceptions gracefully. A single exception results in the application effectively crashing – this is a problem for Mountaineer because even if the app stops keeping time, the Joint keeps burning. This means that a crash effectively results in the loss of the data associated with that session. And because the Mountaineer data set represents a largely unbroken list of every Joint I’ve smoked since late 2014, a single crash meant an unrecoverable corruption of the data set. So being able to add features reliably without introducing bugs was critical. After almost losing a session, I realised sadly that I couldn’t add anything else to Mountaineer while it still lived within Processing.
By the time I realised this, I was very comfortable with Unity, and so Unity was the obvious choice for ‘Mountaineer 2.0’. After about two years of procrastinations and false starts, in July last year I started earnestly working on a Unity version of Mountaineer.
The Road to 2.0
My initial goal was very straightforward – bring Mountaineer 2.0 to the point where I could record a session with perfect reliability and the same amount of data as Mountaineer 1.4. Once I had reached that point, using the app while high would generate lots of ideas on how to improve it, and the app could, for the first time in over two years, continue to evolve.
By the end of October I’d finished Mountaineer 2.0 – the list of new features was nonexistent, but I’d effectively replicated Mountaineer 1.4’s most important features in Unity:
- Ability to input Joint dimensions and weight
- Ability to save image of Joint
- Ability to record session drags, ashes, lights, drinks (in JSON now)
- Ability to record Joint volume percentage over time
The new version had none of the prediction or real-time graphing functionality of 1.x, however – that would have to come later! After recording a single session with both 2.0 and 1.4 running simultaneously (to ensure I didn’t lose data on an untested recording application), I added some important quality-of-life features, incremented the version number to 2.1, and started a refactor.
The 3.0 Refactor
Once I sort of sat back and looked over everything I’d written for 2.1, I realised the codebase was a messy, tangled, incoherent mess and I was heading down the same road I’d been on with Mountaineer 1.4. So I breathed a heavy sigh of resignation and began deleting all my code.
After rewriting about 80% of the scripts in the project and rebuilding the scene hierarchy from the ground up, I found myself with a project different enough from 2.1 that I decided to increment the major version number – Mountaineer 3.0. The only new feature I’d added was a simple real-time graph of drags and mass over time, but almost every script was tighter, cleaner and better-organised. I’d also laid a lot of the groundwork for prediction.
And so, over my christmas break, I finally added the few missing parts to officially bring the Mountaineer Rebuild up to feature parity with 1.4:
- Past Session explorer, where I can inspect previous sessions (including those from the 1.x days)
- Predictions for drags and time remaining shown in a toggleable UI
- Proper real-time graph functionality
Mountaineer 3.1 is definitely the most complete version of Mountaineer I’ve made. I’m very proud of it, and I now can confidently put the Processing version of Mountaineer gently to bed. It served me well (106 Joints recorded over four years!), but times change, and now that I can actually add features to Mountaineer with confidence, I have big plans!
Already there are a number of things that 3.1 can do that 1.4 could not:
- The ability to record typed notes mid-session
- The graph system for the real-time graph is the same as the one for the Joint Explorer (a.k.a. Analysis Suite), and so any improvements to one improves both
- Predictions are now powered by a proper machine-leaning algorithm, improving accuracy
A Wound to the Mind
The prediction point is worth stressing – I realised (to my horror) about a year ago, that the predictions being served by Mountaineer 1.4 were flawed to the point of being legitimately harmful to know about. An incorrect, pessimistic view of the future is like a wound to the mind! The way the prediction worked was this:
- Calculate the volume percentage previous joints were put out at, and average them
- Calculate a linear regression of volume against time (from the check graph)
- Extrapolate that graph until the volume percentage equals the result from step 1, and record the time at that point on the regression
- Calculate a linear regression of drags against time (from the drag graph)
- Extrapolate that a linear regression to the time point recorded in step 2, and report the drag count at that point
- Subtract the current drag count from that number – you have your remaining drag count!
You might already be able to see the problem – it was a harmless assumption on my part, made sometime in 2013: I assumed that I would stop taking drags, and put the Joint out, at a typical time. That is, I assumed that I would bow to the past and not be brave. I was regularly finding myself with quite a bit of Joint remaining, feeling fine, then checking the drags-remaining UI element and seeing that there was one or none remaining. Especially when very high, that starts making me paranoid that maybe something has gone wrong, or maybe I am feeling like stopping after all… Because Mountaineer’s main purpose is to help me in treating cannabis like a Psychedelic, which involves taking as high a dose as possible in a safe, comfortable environment, these incorrect predictions were anathema to the entire spirit of the application. And so, when I discovered the prediction’s inaccuracy, I stopped using them.
But the predictions in 3.1 assume that the Joint volume will be put out when there is no cannabis remaining, and because the algorithm for the regression calculations is much more robust, the predictions are more accurate over time as well! So I’m able to confidently bring back the old prediction UI elements and, with any luck (3.1 is yet untested) they will help me in my pursuit of the cannabis state of mind once more!
I’ve got a variety of plans for Mountaineer – some grand, some humble. In the short-term, I want to make it a full-screen application with a music-visualizer running on the majority of the screen (probably LineCircles to start with). This will also give me more real-estate to expand out the UI and graphs if I want to. I also need to add back the combination graphs from the 1.x Analysis Suite, which should only be a half-days work with my robust little GraphCanvas system.
But longer term, I hope to turn Mountaineer into more of an art project. Since I first started working on Mountaineer, I’ve slowly learned that I react physiologically to cannabis differently to most people. I don’t get sleepy, drowsy, hungry or lazy. I get energetic, thoughtful, creative and restless. I believe this is largely due to my approach to actually taking cannabis. Throughout my life I have preferred to smoke high doses of cannabis alone in exactly the same way – listening to an album I have never heard before with several dated pieces of blank paper in front of me. I smoke, and sit, ready to write down the ideas that come – and they always do. Most of my personal work and life-optimisation ideas have stemmed, in one way or another, from a cannabis session like this (including Mountaineer and its rework!).
I’ve realised that the Mountaineer data set reveals something about my cannabis use. The sessions are infrequent (between once a week and once every few months), long (30 – 40 minutes), and show high doses (600 to 1200mg) smoked regularly and intentionally. I could dig up the pages of notes I wrote for each session, and gaps in activity show when I was writing the pages. Once Mountaineer has a visualisation system attached to it, I could tie session events to changes in visualisation parameters. I could play that session back, perhaps even including the name of the album I was listening to during the session. I imagine recording more data, and potentially even using VR to show people what cannabis can be like. I don’t mean this as a condemnation in any way, but I feel like the vast, vast majority of cannabis use is frivolous – doses too low with poor set and setting. Cannabis definitely has its place as a social lubricant (and definitely should replace alcohol in this function), but I want to show the world that if used carefully, it can be something more – perhaps, anyway!
That’s all for now regarding Mountaineer – I’m probably going to keep tinkering with it as I use it – regularly using my own applications is the best way for me to decide what to add next. I do plan on making Mountaineer publicly available at some point, but probably not until I have figure out a good way of communicating to people exactly why I built it and how to use it. There’s a fair bit of stigma associated with drug use, and an application designed to help you take more drugs is hardly going to be well-received without careful explanation.