This is the busiest time of year for me, and several weekends were filled up with activities. For example as mentioned in post 1197 we did a trail Ragnar race in New Jersey at the beginning of the month. I have done a few Ragnar-type races before (e.g. post 1162 or 1174), but only the kind where the team drives the course in a van and it covers several hundred real miles. With the trail style, you have a camp site where you stay the whole time, and all the running starts and ends near there, with team members all doing the same three routes. Since we had a last-minute dropout I ended up doing one of the loops twice in quick succession, even. The distance was mild but the terrain in this park (Wawayanda) was pretty bad, with tree roots and loose boulders everywhere. I got sick of hearing the word "technical." It was especially ankle-sprainy in the dark (since it runs continuously, everybody has at least one middle-of-the-night run with a headlamp) but I was somehow unscathed. I missed the component of actually covering a lot of ground, but it was nice to not be cramped in a smelly car so much. My 4th leg was noticeably easier than usual, perhaps because I was able to walk around and sleep reasonably to recover. We were helped by perfect weather and it was low on COVID, being pretty much entirely outdoors.
I did find a little time for projects. I'm still hacking on this custom ML package with some audio applications in mind, although I'm letting myself get distracted by some simple toy problems (e.g. word embeddings) since with those it's easier to understand whether it's working. One of the main things I did recently was to make it possible for layers to mix various configurations (e.g. a dense component and two convolutional components with different window sizes), which is basically straightforward but required me to gut the whole thing and deal with a lot of fiddly bits. (When I'm programming for fun I really do like problems where performance matters, and this is one of them!) Since I was having some disappointing results on these toy problems I tried adding some known techniques (e.g. adaptive per-feature learning rates), which helped. It helps even more to find bugs: Several times it was "kind of working but disappointing," but when I investigated there was actually some serious problem. (Example bug: I was zeroing only the first quarter of a vector because I forgot to multiply by sizeof (float). But it was still able to learn effectively with 3/4 of its brain damaged. Other bug: I separated a kernel into two passes, but then forgot to call the second pass. It was still able to learn something because the gradients were only wrong half the time, and only on earlier layers.) Fixing those bugs is even more satisfying than performance fiddling. Makes you kinda want to add bugs on purpose like little puzzles for yourself. But, nothing of interest to share from this endeavor yet; I'm mostly just staring at homemade visualizations like this:
This actually ends well, believe it or not
Video gaming: I finished Deathloop, which I definitely enjoyed, although it had several flaws and doesn't quite live up to its premise. Certainly it was no Outer Wilds! I also played through Axiom Verge 2, which was okay but not as good as the first, and had some serious problems (pretty much all the "boss" fights you could just brute force, at least if you had been collecting the fairly easy "secrets" as you played). It was a reasonable appetizer for Metroid: Dread, which I am playing now. The Alien: Isolation aspect is a good fit for this aging genre, I think.
It was my birthday and I became 42 years old! I would have appreciated being this number of years a lot more when I was 17 (but that's literally impossible), though it still has some minor specialness. When I started this blog I was still hanging out in an IRC channel I started called #42 (e.g. see the 20 year-old but surprisingly tasteful-looking #42 posse page, and don't snooze on those MIDIs!) which was basically just a magnet for random Douglas Adams fans or people who perused the list of channels alphabetically and got bored pretty quickly. But, at this point I've had so many birthdays that it hardly matters.
Sort of for my birthday I finally caved and bought a new fancy graphics card, which I have been trying to do without buying from scalpers for over a year, but that just wasn't working. I got the NVidia RTX 3080 Ti Founders Edition, which is definitely overkill, but I appreciate the industrial design (especially that it is NOT brimming with "gamer" bling) and the fact that it specifically tries to thwart cryptocurrency mining, which is part of the reason these cards are so hard to get, among the many problems with cryptocurrency. It is a very fast card. It runs my custom ML stuff several times faster out of the box (but I still need to do a lot of performance tuning here), it can drive my new monitor at 120hz (which is pretty compelling, I must say, and displaystream compression is completely fine even for these sensitive eyes) including playing some new games at 4k at 60+ fps. So that's great. I did play a lot of video games: I finished Filament; this was good and I do recommend it, although the end was pretty weak after the various mystery build-up, and I did not end up going after all the puzzles. I played through Tetris Effect which is "Tetris but Winamp." I had some fun with the multiplayer (especially the co-op "boss fight" stuff) but the matchmaking is ridiculously bad (90% of games don't even start) so I just got tired of it. For games that actually put the graphics card to the test, I started Psychonauts 2 which is great, and Deathloop which also is pretty intriguing but I haven't gotten far enough to render a real opinion yet. All of a sudden there are so many games I want to play; there's Outer Wilds DLC and Deltarune 2 magically appearing, a new Metroid game soon, Axiom Verge 2, and so on. I'm very impressed that people were able to finish these projects during pandemic (whether working small/solo or on a large team). I haven't been good about it, for sure.
I did finish a few things. As mentioned in the previous post I've upped my classic font game, first starting with this slightly improved version of FixedSys, which I have been using at 2x size on the 4k monitor, which is beautifully chunky:
... but it is a little bit silly to use "pixels" that are 2x2 screen pixels, and it the idea that I could perhaps improve stuff like diagonal lines without sacrificing the computery crispness kept haunting me. So a few weeks ago I cleaned up the 2x bitmap by hand, and I'm pretty happy with it so far:
(These will probably miss the point if you are not using a 1:1 display.)
A bigger project was finally shipping the updates to the Destroy FX plugins with 64-bit support, new GUIs, and other improvements! I think I pretty much posted all the graphical changes throughout the last year here, but I invite you to download them for real now. We got a kick out of seeing the reaction from people (presumably 42 year-olds) who missed these babies from the 90s and 2000s and were surprised to see updates... Some of them had been keeping the plugins alive on a dusty Windows XP machine or inside some janky "laser suspension womb"-style emulation harness, and others had figured they'd just never override their buffers again. I particularly enjoyed this article and some of the excitement on Twitter and forums like this one. I am still hacking on a new experimental effect, but it's so hard to know if it'll be interesting at all until it's much further along!
This weekend we are going to do a trail run in the woods, but I can recap that when I get back. Stay safe.
Hello! It's vacation season around here, this time a trip to see some vaccinated and covid-tested friends in northern Michigan on a lake. I thought maybe I'd get some recreational programming done while I was up there, but the atmosphere was a bit more like kids, commotion and party than it was like meditative retreat with just a typewriter and an acoustic guitar, but that was okay too.
Earlier in the month, I worked on adding stuff to my bespoke machine learning setup ("tom7flow"), since I have recurring urges to use this for wacky projects, and a specific thing in mind to try for Destroy FX (of course this very hacking distracted me from just finishing the one last piece of the Buffer Override UI, after which we can just release those bad boys!). I added support for convolutional layers, a classic trick for reducing the number of parameters by repeating the same pattern over and over. For example when trying to do some processing of a NES video frame, of size 256x240, instead of having a layer with 256x240 "pixels" on it with independent weights, you might instead learn weights for an 8x8 block but repeat that 32x30 times. In fact I revived some earlier failed NES ML project (it looks like I never posted about it?) as an example to develop with, and I can at least show you the pretty ways that it distorts NES graphics:
I love those dirty pixels. I even "wasted" an additional afternoon building a real-time version that lets me play games through the model at 60fps (also with sound; unnecessary!), and then played glitchy Nintendo games for a while. Unnecessary! And speaking of pixels, with my new high-DPI monitor I've been futzing again with the fonts I use, and I've decided to go back to the venerable FixedSys (my all-time favorite bitmap font), but to use it at 2x size. I like the giant fonts for my aging eyes, but also to reduce the visual distractions when I'm writing or programming. (To be clear the draw of a big high-resolution monitor for me personally is mostly about the visual quality of images, video, and games, not about 'screen real estate' to pack full of blinkenlights and multi-pane IDEs.) In order to revive this font I manually converted it to a fake-bitmap TTF (using previously described convenient tech) and fixed some of the few flaws with the font (e.g. I think the  characters descend lower than they should) and added some missing unicode characters that I'd like to have around, yielding FixederSys. I managed to get it rendering perfectly in emacs, and I'm really happy with it now! Since I'm using it at 2x, I have in mind that I may be able to improve this font further using the increased bitmap resolution, while still keeping the chunky pixel character that I admire. So I will try that out on some rainy day.
In media news, I finished up Sniper Ghost Warrior II: Contracts: Ghost Killer Snipe Wars or whatever, which was what I was in the mood for, I guess. I finally got around to playing Ghost Trick since they fixed some serious playability issues on iOS. It was creative and great and I endorse the consensus that it's an oft-overlooked gem. Then I started Filament, which is a pretty neat puzzle game that I'm enjoying so far, although I'm not sure I will 100% this one with Psychonauts 2 just sitting there teasing me to be played!
We participated in the 2021 ICFP Programming Contest. I have done a lot of these (including organizing the 2006 contest some 15 years ago) although it has been a while (recently someone always seems to be getting married etc. that same weekend). This was a well-designed problem which I can summarize briefly: Given a graph and some simple polygon, find an isomorphic graph that fits within the polygon, (mostly) preserving edge lengths and trying to get edge vertices near vertices of the polygon. Everything takes place on an integer grid, which makes the optimization problems much harder, especially for instances where the edge lengths have to be preserved almost exactly. I worked with David and Jason and Ben, working virtually/extremely-online (as is the fashion these days) and spent most of my time on a C++ optimizer based on a blackbox optimizer that I have been using for projects recently. Blackbox optimization is not a good way to solve this problem (it's a bit like "just throw machine learning at it" except less capable) but it is a fun way to make progress without beating your head against various frustrations. Jason also made a web UI for solving the problem manually, and most of our solutions were some combination of human solving and computer optimization. Here's a screenshot of the debugging UI improving a solution (or nolution):
We certainly didn't win, but we found a valid solution to every problem and had a good time! I actually liked the problem enough that I kept tinkering with my optimizer after the contest ended, since I kept getting ideas while running that I just wanted to see whether they'd work.
I also basically finished this pixely UI for the classic Destroy FX plugin Buffer Override. I drew it in Aseprite, which I'm trying to develop my muscle memories in, and used the NES palette as an unnecessary challenge:
This one is best viewed with crisp pixels, so maybe click that bad boy. The only missing part here is the programmatic visualization of the state, to go in the brown box on the top left. After this one's done I think we'll be ready to launch the new versions of all the plugins, all 64 bit, and after that I have some other in-progress plugins and ideas I'm itching to try. For the plugin UI work I also made a pipeline for generating TTF (based on code from the Uppestcase and Lowestcase project) pixely fonts, and created three specimen for the plugins, including a new version of "snoot.org pixel10" with some problems fixed, like missing ∞ and ± symbols. I like making bitmap fonts so perhaps I shall find a place for these my Divide By Zero Fonts site, although I'm not sure they really belong in that series. Completists can just snag 'em out of the DFX repository, though.
Speaking of crisp pixels, I also got a new monitor, since these 120hz 4k 32" displays that were supposed to be coming out like 18 months ago are finally actually available. I'm still getting used to it, with one major bummer being that 4k (even at 32") is probably a bit too high-dpi for my aging eyes to read comfortably at normal UI sizes. But I kept getting mad at the various other imperfections with UI scaling turned on (especially when working on developing pixel-perfect UI above!). So I have been going back and forth on settings until I get used to something. High-res photographs, video, and games look just fantastic on it though. I was playing ScourgeBringer, which I think is a very polished roguelike that I did like, but I was at the point where I unlocked all the help and I either needed to invest a lot more time to get good enough to actually beat it, or move on, and for this one I (wisely?) moved on. I consider this a kind of maturity like when I bought the well-liked pixel art software instead of "just" writing my own, but maybe it can alternatively be seen as a kind of softness. Anyway, to make good use of the big new monitor I switched to some 3D games that can at least pretend to be 4k, first Sensorium. This was a first-person puzzle game that I ended up rather enjoying. It's similar to The Witness and Antichamber (although I think both of those are better; prefer them) with some ideas I've seen before, and a handful of very good new ones. The postgame puzzles were the most up my alley, including that I found my way out of the map and off to some stray geometry on the horizon in search of one of the octagons. Good stuff. Now I am playing Sniper: Ghost Warrior: Contracts II which is exactly what you'd expect.
Here I am again! I was going to say that month went by quickly, but when I re-read last month's post it seems like ages ago.
We drove the car on a road trip; other than when I drove twice to West Virginia in a Zipcar to get vaccinated this was my only time significantly far from my house in a year, so that was kind of weird, but good. Still trying to stay outdoors or masked if around potentially unvaccinated people. The main event was to go to southern Connecticut to visit my family, since there is a new nephew (1 year old!) since last we met, and the other nieces and nephews have also grown at least a year, which is a lot for kids. They were excited to show me their video games, and I was excited to show them some science stuff (turns out you can get perfectly decent handheld microscopes for less than $20, which were a hit with the kids, at least for a few minutes), and the siblings were excited to drink beer together. We even got some real New Haven pizza, which is the main reason that most people would consider going to Connecticut. Driving straight through takes over eight hours, which is doable but very tedious, and I'm trying to get in a mindset of not hating driving so much (I mean the act of driving; I don't think I'll ever really "like" the idea of driving, especially the obsession with car infrastructure in cities), so we stopped "on the way" in Watkins Glen, which is in the Finger Lakes. I can recommend this place for a day, especially the state park. It's this mile-long gorge that has stone walkways and bridges and caves built into it where you go up the spiral stairs and emerge behind the waterfall that spills into the giant basin, and then you keep going and again there's another better waterfall that you could just slip and fall into, and soon you are just so completely over waterfalls, not like in a bad way, but say where you feel judgey if you see anybody take a photograph, because like, come on, there are SO many waterfalls. Aside from its many wineries and beereries, I discovered that this town has some kind of car racing history, and if you pay them $30 they let you drive around their race track, so I did that also in the spirit of trying to hate driving less. That is definitely more fun than driving on the highway.
Still working on the Pac Tom endgame, which I have done some significant construction on, although I made one discouraging mistake that set me back a bit. The main problem is that to finish the project and the filming, I need a decent weekend (like: not on a road trip, not hosting visitor, not 95°F, not raining) and these have not been forthcoming. I did a redesign of the Buffer Override UI for Destroy FX (mostly because the current one is so dang tiny) but it's not quite ready to share. Part of that was distracting myself by using my newly minted abilities of generating TTFs to make some bitmap fonts for this project, instead of clicking the pixels by hand (??), which I am pretty efficient at, but jeez. I've been using Aseprite as discussed in the previous post, for both the UI work and the fonting. I do like it, although its similarity to Photoshop keys/behavior does put a spotlight on some of the things I expect to be there but aren't (say, holding shift when drawing with the pencil to constrain it to a straight line). It's great to be able to write scripts, though, and have native support for animation!
I finished Project Hail Mary and I think I basically liked it; a few things fell better into place than I was expecting, or at least it didn't fall apart like the (somewhat similar) "Seveneves" did. By the way I always pronounce that Se-VEN-eh-vess. Now I'm reading The Utopia of Rules which isn't what I was expecting but is interesting, and in some Wikipedia rabbit hole (I think it was about cryogenic brain preservation) I was reminded of how much I like Nick Bostrom's brand of bonkers but nonetheless hard-to-refute writing, and so I have been catching up on some of his papers since I last thought about that guy. I did in fact finish the game Caveblazers (it's no Spelunky or Isaac but it was a very solid Roguelike) in time to pick up Nifflas's new Ynglet. I think Nifflas made some of the best indie "Metroidvanias" out there, with the creative movement and clever hidden challenges, and I was sort of expecting this one to be in that vein. It's not, but it was a very good short game anyway, with a really cool presentation style and vibe. Then I finished Slime Rancher too (charming), and now I am on to Outbuddies DX (I expect to finish it, but I think it has too many rough edges to recommend).