Showing posts with label Python. Show all posts
Showing posts with label Python. Show all posts

Monday, January 19, 2026

Building a tiny Lisp interpreter with C++

I made a very simple Lisp interpreter using C++. I decided to focus on Lisp after a failed experience of trying to write a tiny BASIC interpreter for a cyberdeck build I'm working on putting together. I ended up shifting to Lisp for a variety of reasons. It is an interpreted language, meaning it relies on a program to act as a sort of middle man to execute the code versus compiling it to machine language. It also is one of the oldest computer languages with an extremely simple syntax. I decided to use C++ rather than Python for this task. C++ runs extremely fast compared to Python (which is also an interpreted language), and interpreters really require that speed provided by the program running as native machine code. This project could have been done using Python, but my guess is that running the program would have suffered from the increased headroom necessary of running in interpreter within an interpreter.

The interpreter is very basic by any standard. It currently can process the following mathematical operations: addition, subtraction, multiplication, division, absolute value, square root, and calculating powers. It can define and set variables, as well as print both numbers and strings to the console. It can handle floating point numbers. Essentially, it's an extremely simple programmable calculator!

So what did I learn from this? The first thing is, under the hood, there is nothing basic about BASIC. I was shocked at how challenging it is to write a simple interpreter for such as simple language. The second is the robustness and honestly the beauty of Lisp. The language, even in it's extremely simplified form is a joy to work with. I've always thought that there is magic to be found when working with limitations, and while Lisp seems to be extremely limited compared to more modern interpreted languages like Python, the structure of the language lends itself to some really creative solutions. 

Here is an example of code that runs in my interpreter to solve quadratic equations:

> (define a 1)
=> 1
> (define b -5)
=> -5
> (define c 6)
=> 6
> (define discriminant (- (* b b) (* 4 (* a c))))
=> 1
> (define x1 (/ (+ (- 0 b) (sqrt discriminant)) (* 2 a)))
=> 3
> (define x2 (/ (- (- 0 b) (sqrt discriminant)) (* 2 a)))
=> 2
> (print "Solutions: x1 =" x1 ", x2 =" x2)
Solutions: x1 = 3 , x2 = 2

 Below is a video of me running a demo of the interpreter to show the basic syntax for some of the operations and showing how to set up a simple program that converts Celsius to Fahrenheit.

 



The robotic voice in the video was created by a separate program I built with Python that converts text to speech and then saves the output as a .WAV file. Still working out some of the kinks with that, but it's fine for now.

 

Tuesday, November 18, 2025

Zarphield Says...

While grappling with the daily existential crisis that modern life has devolved into, I wrote an app in Python that sits on my desktop and spits out a fusion of quotes by 80's cat icon Garfield and swinging space pirate Zaphod Beeblebrox. This is Zarphield. Feed him lasagna, Earth man.



 

Sunday, November 9, 2025

Constructing a homebrew "Cable Channel" Part 2

 It's relatively easy to use a Raspberry Pi to approximate the experience of having your own custom cable television channel similar to what folks of a certain age may remember from their youth. In a previous post I went over some of the basic steps to get a Raspberry Pi 4 set up as a "retro box" that automatically plays a curated collection of movies and shows from the 1970s, including period correct public service announcements and commercials. After a couple of weeks of testing - which was essentially just letting the box run to make sure that the flow of the programing actually felt like watching period correct television - I decided that I needed to ramp things up. It wasn't good enough to just have a Raspberry Pi that played old movies and commercials. Any modern computer can do that. This needed to actually have the entire aesthetic of a classic 1970s cable channel. It needed to dress the part.

That's where eBay comes back. Some quick searching and I was able to locate an untested cable box circa early 80's for parts/repair that had a buy now price of only $3.81 (plus $12 for shipping). This box included a front channel display and was roomy enough to house both the Raspberry PI and an Arduino UNO (more on that below). I decided to go with the 80's style box, since the larger encloser would make it much easier to work with, and I had some ideas about utilizing the front channel display screen.

 

When the box arrive it was immediately obvious that the particular Jerrold 550 Starcom converter had lived a rough life. The was some serious damage to one corner of the plastic face plate due to what I can only attribute as "falling damage" from being dropped on a hard surface, and the unit was covered in old masking tape and 40+ years of grime. I also noticed that the unit's enclosure was secured with rivets, probably since the majority of these units were distributed by local cable companies and they didn't want to make it easy for industrious hackers to open them up to try to figure out how to get free Home Box Office. The first step was to drill out the rivets so I could take the unit apart.


 
After I parted the case out I spent some time scrubbing the case down with dish detergent and using a liberal amount of Goo Be Gone to get all that sticky tape residue cleaned up. Once everything was clean and dry, I could spend some time attending to the smashed corner of the face plate. I had a couple of options for the repair, but I decided that the easiest (and structurally most secure) fix would be to recreate the corner using Green Stuff two-part epoxy. For folks not familiar with Green Stuff, it essentially is a two-part epoxy that you mix by hand and then mold like a really rigid Play Dough into to place. It is typically used a lot when kit bashing models for games like Warhammer 40K, when you need to sculpt a custom piece, and maybe adhere a particularly tricky portion of a model together. It works well, can be easily sculpted, and takes simple water-based acryllic paint just fine. I eyeballed the amount that would be needed to recreate the missing/damaged corner, mixed it up, and then went to work sculpting the corner as best as I could. Green Stuff sets pretty quickly - typically with 5-10 minutes - so I didn't have the luxury of time here. My goal was good, not great. After the epoxy set I mixed up a fairly good approximation of the color of the faceplate using acrylic paint to blend the repair in as best as I could. Overall, I'm pretty happy with it. From across the room it's not noticeable and the Green Stuff actually made the faceplate much more sturdy that it was previous to the repair.


 
Once the plastic was repaired I started brainstorming how to use the front channel display. I immediately though about using an Arduino UNO to power a small LED screen, since I'd used that pairing to great effect on a couple of smaller projects. I suppose I could have powered the LED's from the Raspberry Pi, but to be honest it was quicker and easier for me to wire up the display to an extra UNO R3 I had and I was able to repurpose a sketch that I had written for a handheld snake game. The Pi can power the UNO via USB, and if I ever want to change the display it is super easy to do (and doesn't affect the functionality of the Pi). It also gives me to option of adding a module for a remote control if want later down the line. I played around with different text for the display, finally settling on having an asterisk gliding across the display. It looked cool and I'm a sucker for moving LED's (let's just blame that on "Knight Rider"). After some tweaks for placement and a couple of generous blobs of hot glue to hold the screen in place, I had a functioning display that I could easily modify to anything that used a basic character set.
 

 
The final stretch was just to drop the Raspberry Pi into the box and get everything secured. I cut and glued some rubber welcome mat materials to the bottom of the case to assist with giving everything a nice, non-conductive floor to mount the pieces on, and mapped out the most efficient layout to screw everything down.

 



And there it is...a working retro "cable channel" that lives inside a period correct cable box with a customizable LED front panel. Eventually I will add an Arduino remote control module that I will use to change up the front display to a couple of different visual options. I still need to come up with a reasonable plan for cable management that will allow me to plug in a mouse and keyboard into the back. I can remote into the box from another computer to add videos if I want. Overall, I'm pretty stoked on this little project. I'd like to make another one at some point using a Raspberry Pi 3 with composite video so I can easily run the signal to one of the CRT televisions I have. This is the first project I'm done that has utilized both the Raspberry Pi and the Arduino boards and I love the flexibility of having both in a build. Now it's time to watch some TV!
 

Sunday, October 19, 2025

Using HTML to generate random horrors from beyond...

A webpage that generates random "Elder God" names in the style of H.P. Lovecraft? Sure! This started as a Python project that would generate a list of 10 random names in the style of the infamous Elder Gods from the Lovecraft pantheon. I had so much fun with that I decided to port it over to the land of HTML.

 The page is available on my GitHub, in case anybody wants to summon an unthinkable horror with too many consonants.

https://robot-sword78634.github.io/elder-names/ 

The HTML uses the same syllable list and logic as the original Python code, but instead utilizes Javascript. It also adds some nifty apostrophes for that added Lovecraft flair.

 

Thursday, October 2, 2025

Let's create a cable TV channel!

I’ve become infatuated with Raspberry Pi single-board computers recently, and thanks to a low-grade eBay addiction, I now have several of them just sitting around, mocking me to make them useful. Recently, I read about someone who turned one into a sort of personal cable channel, and I got fired up on the idea of creating my own “cable channel” of highly curated videos—which I’m sure nobody else would want to watch.

It probably would have been easier to just follow the tutorial I found online for this type of project, but as usual, I felt it necessary to reinvent the wheel for the sake of “learning.” For me, the basic parts of getting a home cable channel working are:

  1. Figure out how to randomize/play/loop videos from a folder

  2. Determine how to “broadcast” the content (HDMI, Wi-Fi, etc.)

  3. Decide what content to use

I kept the first part simple. Since I’d be running this project on a spare Raspberry Pi 4 with Pi OS, I decided to use VLC as the media player. VLC natively does everything I needed (randomize, play, loop from a folder), and it can be controlled via terminal/bash scripts—perfect for making everything restart automatically if the system reboots.

I skipped the broadcasting question for now and focused on getting the system running. The fun part, after all, was deciding on a theme for my channel and grabbing videos! I’ve always been a movie buff and grew up watching late-night “midnight movie” flicks on TV, so it was a no-brainer to load up the Pi with movies and shows that fit that vibe.

I could have taken the easy route and gone straight to the Internet Archive, but instead, I pulled material from YouTube. A little-known fact: YouTube not only streams video content but also allows you to download files. Since I’d need a large number of videos, I wrote a quick Python script to batch-download user-curated playlists. Python makes this easy with the pytube library, which was designed for this purpose. The script asks for a YouTube URL and a save location, then pulls down the highest-quality stream available.

At first, I ran into certificate errors on macOS. Instead of troubleshooting libraries, I just ran the script on an Ubuntu machine and it worked without issues.

The flow is straightforward:

  1. Prompt for the YouTube URL and the save folder

  2. Use pytube to get the highest-resolution stream

  3. Download it to the folder

It’s a short and simple tool, but it does the job—a quick way to grab videos for offline viewing. After downloading a bunch of nostalgic movies and TV shows, I started scraping vintage 1970s commercials too. Since VLC randomizes playback, there’s a chance that after a movie or show, one or two commercials will play before the next feature. After raiding YouTube’s vaults, I had a solid library for my channel. Then came the fun part: testing and tweaking.

Long story short—it worked! It feels like watching a real TV channel from the 1970s. Videos flowed seamlessly from one to the next, with a nice balance of movies, shows, and commercials. (I might add more commercials later—it’s surprisingly fun to see a 1972 McDonald’s ad pop up.)

My startup bash script launches VLC at boot, runs everything in fullscreen, randomizes playback, and loops continuously without showing the user interface:

#!/bin/bash
vlc --fullscreen --loop --random /home/pi/Videos/

Right now, I have the Pi hooked up to a spare TV via HDMI, but I’m tempted to pick up an HDMI-to-RF modulator so I can run the channel on a CRT I keep around for playing Nintendo. Ideally, I’d love to broadcast to multiple TVs around the house—but I don’t know if I want to run 100 feet of coax cable just to watch Leonard Nimoy’s In Search Of in every room.

Or do I?



 


 

 

Sunday, September 28, 2025

Through a Glass Darkly: Building a Philip K. Dick Inspired Text Adventure in Python

As someone who's spent countless hours lost in the paranoid, twisting realities of Philip K. Dick's novels, I’ve always thought it would be fascinating to bring that sense of dislocation and uncertainty into a playable form. At the same time, I have a deep love for the classic text adventure games of the 1980s, especially Infocom’s masterpieces like Zork, where every room, every object, and every line of text contributes to an immersive narrative. It occurred to me that blending these two interests could produce something truly engaging: a text adventure where nothing is quite what it seems, and every discovery feels like piecing together fragments of a memory.

I decided to code this game in Python, keeping a few core design goals in mind. First, I wanted the game to feel like an Infocom adventure, so I structured it around a series of interconnected rooms, each with its own description, items, and NPCs. The player moves through these spaces using simple two-word commands like "go north" or "take wallet," much like the old parser systems that made classic interactive fiction so approachable and fun.

The game engine itself is data-driven. Rooms, items, and NPCs are all stored in dictionaries with unique identifiers, which makes it straightforward to expand the world later. Each room defines its exits, items present, and NPCs in place. Items can have clues associated with them, and NPCs can offer dialogue that hints at larger mysteries. Using Python’s dataclasses made it easy to encapsulate these properties while keeping the code readable and maintainable.

Player actions are handled through simple functions tied to verbs: go, take, use, talk, and so on. For instance, when the player uses the take command, the code checks whether the item is present and portable, adds it to the inventory, and collects any associated clues. Use commands allow the player to interact with objects or room features to trigger additional story events, like unlocking a door or revealing hidden information. There's also a clue and memory system that monitors the player’s discoveries; once enough clues are collected, the player recovers a key memory, which acts as a milestone in uncovering their identity.

Save and load functionality was also important, reflecting the classic adventure game experience where progress mattered. The game can save the current room, inventory, NPC states, and collected clues to a JSON file, and restore everything from that file later.

The narrative logic is built around the idea of memory recovery in a dystopian world—a theme central to Dick's work. The player starts with no memory and must piece together their identity by exploring the environment, interacting with NPCs, and collecting items. Clues are scattered across the world, and certain items or interactions trigger additional revelations. The balance between exploration, discovery, and narrative progression aims to capture the same unsettling tension found in Dick's novels, where reality is mutable and perception is unreliable.

This project was a perfect pairing for my interests: the procedural, logic-driven structure of a text adventure married to the thought-provoking themes and disorienting world-building of Philip K. Dick. It's designed to be extensible, so I can easily add more rooms, items, and puzzles in the future. For fans of either classic interactive fiction or Philip K. Dick's writing, this game represents a small but enjoyable intersection of those worlds—a place where the past, memory, and reality are constantly up for interpretation.

The code can be downloaded here if you want to try it out.

Now to see if ChatGPT can pass the Voight-Kampff test...

Sunday, March 30, 2025

"Hello Dr. Faulken. Would you like to play a game?"

I recently re-watched the classic proto-hacker 80's film "WarGames" starring Mathew Broderick and Ally Sheedy. The famous final scene, where the supercomputer Joshua blazes through game scenarios to final come to the conclusion that "the best way to win is not to play" got me thinking and inspired me to try my hand at writing a Python script that pits a computer against itself in a game of Tic-Tac-Toe, using the basic behavioral science concepts of positive and negative reinforcement, to see if I could approximate the fundamental principle of machine learning. After I got the script up and running, I added the ability to dump the results of each game played to an Excel spreadsheet, and then wrote another script using Matplotlib to visual the results. The hypthothesis is that after a certain amount of games, applying a basic machine learning algorythm the program will eventually move towards a state of optimal play, where the game registers more draws than wins. Essential the program is rewarded for making "good" moves that end in a win and penalized for making "bad" moves that result in a loss. The program will reach a state of optimal play when every game results in a draw. Essentially, when both the X and O are playing in an optimal state, the game plays to prevent a loss by achieving a draw.

Building the AI-Powered Tic-Tac-Toe

The foundation of the program is Q-learning, a reinforcement learning algorithm. The AI starts with no knowledge of the game and gradually improves by assigning values to moves based on rewards and penalties.

Here’s a quick breakdown of the main components:

  • Q-learning: The AI maintains a dictionary of board states, updating its move choices based on rewards.

  • State Representation: Each board is stored as a flattened tuple, allowing the AI to recognize patterns.

  • Exploration vs. Exploitation: Initially, the AI picks random moves to explore, but over time, it relies on learned strategies.

  • Game Logic: The program enforces Tic-Tac-Toe rules and determines wins, losses, or draws.

With this in place, I let the AI play itself continuously, logging the results to an Excel file.


 

Tracking 15,000 Games in Excel

To measure progress, I recorded each game’s outcome in an Excel file using pandas and openpyxl. The data captured:

  • Game number

  • Result (X wins, O wins, or Draw)

The AI played nonstop, generating a dataset of over 15,000 games. The expectation was clear: over time, the number of draws should increase as the AI moves toward optimal play.

Visualizing Learning with Matplotlib

Once the data was collected, I used Matplotlib to analyze how the AI improved. The key visualization was a draw percentage over time graph, calculated as:

Draw Percentage = (Total Draws / Total Games) * 100

Plotting this gave us a clear trajectory of improvement. Initially, wins and losses fluctuated wildly, but as the AI refined its strategy, the percentage of draws steadily climbed. By the end, draws accounted for over 40% of games played—a strong indication that the AI was approaching a level of optimal play.


 

Results: AI in Action

The final graph showed exactly what we hoped for: a sharp increase in draws, meaning the AI was learning to avoid losing. In Tic-Tac-Toe, perfect play from both sides should always result in a draw. The fact that the was AI approaching 100% draws proved that it was learning over time to eventually solve the game.

Final Thoughts

This project was a cool dive into reinforcement learning, data tracking, and visualization. Watching the AI evolve from random flailing to calculated mastery was incredibly rewarding. If you’re interested in AI, I highly recommend trying something similar—watching an algorithm teach itself is a fascinating experience. While 15,000 games of Tic-Tac-Toe seems like a LOT of games for a computer to begin to teach itself such a simple game, there are a few tweaks to the code that could be made to accelerate the learning. I'll probably continue to tinker with this one for a bit, as it is a surprisingly satisfying to watch the machine start to rack up draws against itself.


The Lost Art of Tree Fishing

Now that the Northeast seems to have finally shaken off the icy grip of winter, I've taken the first reluctant steps outside of my cave ...