Narthenian, Part 3

Screenshot of Narthenian game with an innkeeper greeting the player

I managed to fit a couple of hours in today for adding innkeepers and staying at an inn to The Narthenian Conspiracy. Since inns charge for a stay, I had to add gold to the game, and let the player collect gold from slain monsters. I also added a new sprite that will be used for merchants and innkeepers. It looks more like a wizard or a gnome, or maybe a gnome wizard, but that’s the extent of my art skills.

Innkeepers are their own class, and Merchants will be also. I could probably avoid some unnecessary code duplication by making NPC an abstract class, and subclassing the already existing NPCs, Merchants, and Innkeepers from it. I would probably have to turn the NPC vector associated with each map into a vector of pointers in order to make use of polymorphism. Whatever. I’ll deal with the consequences of my design choices for now and learn the lesson for later.

Staying at an inn fades the screen to black, and then fades back in to the usual display as a simple visual effect for going to sleep. I did this simply by drawing a black rectangle over the screen with alpha going from 0 to 255 and back. It probably goes a little to quickly as it is, so I may come back and tweak it to take longer later. Initially, the screen went straight to black; fading out and in wasn’t working. I realized that SDL3 ignores the alpha channel when drawing rectangles unless you call SDL_SetRenderDrawBlendMode on the renderer and set it to SDL_BLENDMODE_BLEND. This is probably also the case for earlier versions of SDL, but I have always copied portions of textures rather than drawn plain rectangles.

I wanted to put in a sound effect for sleeping at the inn, but haven’t created the sound yet. I may go with a different approach, and have the game play a “chiptune” arrangement of Brahm’s Lullaby during the whole interaction with the innkeeper, rather than using a sound effect just during the sleeping state. That’s something I’ll decide on soon: I’m currently learning my way around MilkyTracker in order to put together some background music for the game (it will ultimately be in .wav or .mp3 files; I don’t feel like implementing a reader/player for .mod files or pulling in too many external libraries for a relatively simple game). In any case, the decision need not be permanent if I don’t like how it turns out.

The game is becoming a little more playable with the ability to sleep at an inn and recover HP, so that going out and fighting and leveling up can continue. There is a lot to go with tweaking enemy stats, adding more enemies, adding items and spells, adding quests, etc., etc., etc. But little by little there is more to the game. While I’m working on the music, I probably need to also finish up the Carathusia town map, and put together some maps for the floors of the castle. Anyway, it’s easy to get overwhelmed thinking about everything that still needs to be done. More fun to focus on the enjoyment of seeing the little steps forward.

Narthenian, Part 2

Dialog scene from the game

I got the initial framework for NPCs and dialog set up, and I have uploaded the code to Github. You can find the game in its current, very early state, at https://github.com/jstoddard/narthenian. There are only a couple of NPCs and very simple dialog at this point: They only say one thing at you. There are some data structures and framework for a more complicated dialog system in which there can be some back and forth, with the player selecting a keyword or phrase from a menu to continue the dialog, and with NPCs able to give the player an item or update a quest. These features, however, need a lot more work to be implemented.

NPCs are kept in a vector in the AreaMap in which they are located. In the drawing routine that is run each frame, the game iterates over the NPCs in the current map and identifies and draws the ones that are within the bounds of the screen. The game interprets an ENTER keypress, and in the future the A button on an XBox controller or corresponding button on another gamepad (this was already implemented in the BASIC prototype) as a command called “ACTION1.” When the game receives an ACTION1 command, it looks for an NPC in the tile that the player is facing. If an NPC is there, the game goes into dialog mode, which currently comprises displaying the NPC’s dialog on screen and waiting for the player to hit ENTER again (or SPACE a.k.a. “ACTION2”) before returning to the normal mode of letting the player wander around the map.

Before fleshing out the dialog system with the upcoming features, I will probably set up merchants and inkeepers so that the player can rest and buy weapons, armor, and other items. I think that doing so will go a long way toward making this early stage of the game somewhat fun to play—an important consideration, since I need to spend a lot of time playing it, even in its unfinished state, for testing and bug-catching. I am not sure yet whether I will subclass NPCs for these characters, or make separate classes for them. There are some tradeoffs to consider. If they are subclassed from NPC, a single loop can handle drawing of all three character types, and another single loop can handle the ACTION1 command as discussed above. However, the latter is somewhat complicated by the fact that a merchant or inkeeper will often be behind a counter, so checking will be a little different, and we will want to switch to a shopping system or sleep system that will probably be distinct from the dialog system. This can be handled by moving the checking and mode-switching code from the loop into virtual functions in the NPC class, and just having the loop call those functions instead. The Merchant and Inkeeper subclasses would just override the functions.

Well, I’ll decide what to do over the next day or two. Meanwhile, I have a couple more monsters to add to the world, as I think I mentioned in the last post.

Narthenian, Part 1

I think I’m going to keep a devlog of a simple tile-based RPG that I’m working on. Although it’s not a huge undertaking, progress is and will be slow, since it’s just a spare-time project worked on a few hours a week in order to learn a little bit of modern C++. The original prototype was actually written in QB64 Phoenix Edition, a somewhat-modernized variant of the QuickBasic language. Here is a video of that early prototype in action:

I have rewritten it in C, and have been adding additional features in hopes of eventually turning it into a complete game. The tiles are based on a set from Lanea Zimmerman, username “Sharm” on OpenClipArt.Org. The melee scenes—which now have a nicer background than seen on the video—are based on AI slop with some editing. I’m not proud of that, but that’s the current situation.

The game is currently being written on an old Lenovo Thinkpad purchased for $150 and running FreeBSD. I have gotten tired of plain text editors and command lines, and, remembering the nice programming environments from the days of QuickC and Turbo C++, I have opted to work in the CLion IDE and enjoy letting a program handle most of the housekeeping tasks, provide easy refactoring and debugging, and generally keeping things easy. It’s nice having nothing to prove through programming asceticism. Graphics are edited on a MacBook Pro. The maps, for now, are put together with a simple map editor written in QB64 Phoenix, and the sound effects are recorded from sounds generated in QB64 Phoenix. The sound effects are simple and could be generated directly in C++, but QB64’s sound statement is almost like working with an old Yamaha sound chip, allowing me to set tone, duration, effects, and noise, which is easier than generating the waveform directly.

The current state of the program is that the player can wander around the world and fight a couple of enemies (the serpent and gigarat seen in the video, with more designed and about to be added), level up, and switch maps (i.e., enter and exit a town). I’m currently working on setting up NPCs and dialog, after which I expect to upload the work-in-progress to Github. Items and quests are in the works together with NPCs and dialog, but I don’t know how complete they will be before the initial Github commit. Spells need to be implemented, but I’m not sure when that will happen. (I’m about to set up a Mage enemy, but it will be stuck on plain attacks for a while!) Saving and loading games will be added once all those things are working. The overworld map is also sort of sparse, and there’s only one unfinished town working so far, so there is still a long way to go before a reasonably complete RPG is ready to play.

I’ll put up screenshots and discuss the development process as things proceed. For now, here’s the general background story behind the game:

When the heavens and the underworld made a joint attack on the people of the earth, the six cities united under the leadership of Carathusia for defense. Narthenus, one of the greatest warriors of the Forest People, disapproved of his people’s decision to submit to Carathusia, and betrayed both his army and the joint army’s battle plans to the underworld. The traitor’s actions nearly brought an end to the world, but under the Carthusian general’s leadership, the six cities managed to save the mortal races.

The unified kingdom lasted for centuries, until four thousand years after the great war, when a cult calling themselves the Narthenians attempted to overthrow the kingdom and break up the rule of the people once again. Civil war lasted for many years until the cult was finally driven out, but not destroyed. The leader of the cult, Tarpeya, fled to the deserts in the north with her few remaining followers. Rumors from the desert city Erimea suggest that the cult has established camp in the western part of the desert.

Although Carathusia’s resources were nearly exhausted after the civil war, the king was troubled by the reported movements of the remaining Narthenians. Concerned that Tarpeya was up to something more than just hiding out, he summoned a young warrior who had distinguished himself in service during the civil war. The young hero was sent to investigate and advised to travel first to Adon, where the dungeon held a former adviser to Tarpeya who may know more about her activities.

The rest of the story will come out during the game. Please be aware that some of these posts will likely contain spoilers. I’ll try to note that at the top of posts, but I can’t promise I’ll be perfect…

Portals

“For what it’s worth, I believe you,” the officer said, “but our hands are tied. We can’t do anything. Look, I can be upfront with you because nobody will believe any of this. We’ve already investigated these things and saw the same sort of stuff as you. One of our men committed suicide after seeing what he saw. But the district attorney thinks it’s bullshit, and even if she didn’t, there’s no way in hell we could convince a jury that this stuff is real.”

The officer was right, of course. I could go to the media, but any respectable journalist would laugh in my face. It was just too incredible, like the visions of a raving madman.

I myself had never believed in the portals. Only the gullible, the superstitious, the overly religious types could believe in that stuff. I preferred to stay grounded in reality. If it wasn’t reported in the New York Times, and if there wasn’t a scientific consensus behind it, it couldn’t be real. Until one February morning my friend took me to meet a shaman somewhere out in the middle of the Sonoran desert.

I know what you’re thinking. It was some cheap parlor trick. That’s what I thought, too, when the shaman first opened one of the portals, disappeared through it, and came back a few moments later. If I was at a loss to explain how he did that, much less could I explain how I was able to enter the portal myself afterward. I found myself in a jungle. I have no idea where it was, whether in South America, or China, or some other world. I think it must have been India, though, based on the appearance of the man over there and the accent of his broken English.

The man must have been some sort of shaman, too. He had the appearance of one of those Hindu ascetics who spend their days in meditation and eat little, if anything. We didn’t talk much, as I wasn’t there for more than a minute or so. He said he was a friend of the shaman, and that he was there to make sure I didn’t become disoriented and wander off, but that I made it back.

I walked into the portal a skeptic, but I came out a believer, even though I wasn’t sure exactly what it was that I was beginning to believe. The shaman showed me and my friend how to open the portals. It was a simple ritual, which I won’t describe here because I’ve come to realize the danger of these portals and their attractiveness to the wrong sort of people. He warned us to be careful, to never step into a portal we weren’t familiar with without someone who was familiar with it.

“There are many portals that nobody knows where they go to,” he explained, “because nobody who entered them has ever come back out.” Caution was warranted where experimentation could prove deadly.

The portals attract a strange sort of people, just the sort who would believe in portals. Neopagans, witches, hippies, and others who don’t quite fit in normal society. Many of them can’t open the portals and have never seen them in actual use. Only the true believers can actually open them.

I later found out that many don’t even need the ritual. It’s just a crutch for those of us who are inexperienced and awkward in these matters. It helps us to focus our spiritual energies, but it can be done with just some concentration as long as the person opening the portal doesn’t doubt his ability to do so.

The portals themselves can be found just about anywhere. People say that their locations were sacred sites to the ancient peoples. There must have been much more communication across cultures in the ancient world than we have imagined, maybe even communication across worlds. Some people have said that Buddhist missionaries from China visited the Americas long before Columbus. If that’s so, they may not have come by boat.

Once you’ve been through a few portals, you begin to recognize where others are. There’s a sort of energy emanating from the earth at those points. You can feel it. I always remembered the shaman’s warning, though, and never went through a portal that nobody I knew was familiar with. I never dared even to open them up.

I have visited every continent, and places that I think were on other planets, in other galaxies, since going through that first portal. I have met many other people, many other portal-hoppers, during that time. There are probably around ten thousand people or so who use the portals, so you end up seeing some of the same people over and over again, and get to know at least a few quite well. We never talked about the dark side of the portal culture, though. Nobody ever told me in direct terms about the malicious people among us.

It’s obvious in retrospect. The portals are just too appealing. If you’re into some shady business, say drugs or even human trafficking, such a quick, invisible travel method is a real boon to your enterprise. Not only that, but the portals to nowhere, that nobody ever returns from, are convenient for making your enemies disappear or disposing of the occasional body.

I’m not naive. I always knew that there was evil in the world. Sure, the human traffickers in particular make me naseous, but it’s the capacity for evil in seemingly ordinary people that really makes my stomach churn. I get sick even thinking about what I saw. I haven’t used a portal again since that day, and I nearly have a panic attack whenever I feel the energy of one nearby.

It was a morning in late winter in Arizona again, this time near Sedona. A couple had brought their young daughter, probably about seven or eight years old, to visit a portal I had not known about. I happened to arrive just after they did. I walked up to an area from where I felt a strange energy, an energy I recognized as indicative of a portal. They were already opening it up when I caught up with them.

It seemed that they were unfamiliar with the portal, too, since they hesitated to enter it. Eventually they convinced their daughter to stick her hand inside. She did. As soon as they heard her scream, they pulled her away, as a bloody stump where her forearm used to be emerged from the portal. A loud argument between the parents ensued, which I heard over the shrieking of the terrified little girl. I only remember two phrases from the chaotic moments, but those two phrases are seared into my memory forever.

“How are we going to explain this?” yelled the father.

“We aren’t,” responded the mother, and shoved her own daughter into the portal.

I was stunned. I don’t think it’s an exaggeration to say so. I stood in shock, unable to move or comprehend what I had just witnessed. Before I came to my senses, the former parents departed calmly, as if I wasn’t present, and as if their daughter had never existed.

That scene has haunted me since. Days later I worked up the courage to report it to the police, but they said that they could do nothing for me. They’re right. Who is going to believe a crazy story about a couple feeding their daughter to a killer portal in the desert? But it’s true. I saw it with my own eyes, and I can’t unsee it.

If only I knew how to do so, I would destroy every one of those damned portals.

Jack’s Prediction

“Have you read Metamorphoses? The one by Apuleius?”

It was a strange question. Or rather, it was strange that it was posed by Jack, the stereotypical dumb jock. Jack was the embodiment of a cliché: Tall, blonde, blue eyes, a thick, muscular build. Captain of the junior varsity football team. As if to complete the picture, he dated a cheerleader.

“No, of course not. We’re only in second year Latin. We don’t even really get into Caesar until next year, let alone stuff like Apuleius.”

Timothy, who never went by just “Tim,” was the quintessential bookworm, in many ways the opposite of Jack. Lanky and of medium height, bespectacled and disinclined to sports or any sort of athleticism, he spent his time in the library, where he read everything he could: Fantasy, science fiction, historical fiction, history and science without the “fiction,” books on computing, books about languages. But everything was in English; as much as he loved Latin, he just wasn’t proficient enough yet to take on classical literature in the original language.

“Oh, I thought that wouldn’t have stopped you from jumping ahead on your own. You really ought to. It’s been a minute since I read it, but it starts out with some witches peeing on some dude, later some old lady tells the story of Cupid and Psyche, and in the end the whole thing turns out to be a missionary tract for Apuleius’s crazy mystery religion.”

“But how do you know all this?”

“I’ll tell you a secret. I started Latin early at home. It’s a guilty pleasure. Just don’t tell anyone. It could hurt my reputation.”

“I would never have guessed.” Timothy told the truth. “What else have you read? What do you like most?”

“Look, the best stuff is from the middle ages. There’s this play called ‘Lydia’ but Lydia is kind of a whore and the whole thing is full of innuendo and double-meanings. I don’t know why people call it the dark ages. They were just like us, except without iPhones. There’s this story about some students who stay at this guy’s house and through some trickery please his wife during the night.”

“Wow.” Timothy was dumbfounded and more than a little embarrassed that the football player seemed to have read much more Latin literature than he had.

“Look,” said Jack, “You’re going to be a classics professor someday. It’s obvious. You’re the best in every class except P.E., but you can’t hide the fact that Latin sparks a different kind of joy in you than the other subjects. When we get into Greek next year, it’ll probably blow your mind. It’s your destiny. And we both know that I’m going to play football, but that doesn’t last forever. After my career in sports, I’m going to become a medievalist. Maybe we’ll even end up teaching in the same university. You’ll teach Caesar and Cicero to your students, maybe Terentius and Plautus for a little fun, and then I’ll blow them away with the middle ages, where they’ll find stuff that’d make Catullus blush.” Jack let out a hearty laugh.

Jack had breathed life into Timothy’s dormant competitive spirit. Even if he would never be a sports champion, he had to excel in something. He couldn’t allow the star athlete of his class to leave him in the dust in the classics. He would hit the books and get caught up in Latin and maybe even get a head start in Greek. Meanwhile, his concept of the dumb jock took a serious hit. His newfound respect for Jack may not have eliminated the stereotype, but from then on he knew that he couldn’t count on it to always hold.

He also hoped that Jack’s prediction would come true.

The Bunker

“Pull harder!” exclaimed Tim, as he and Carlos tugged on the flat, round piece of metal. Just enough faded paint remained among the rust to reveal that it once was green and probably neatly camouflaged among the tall weeds and grass that fluttered this way and that in the light breeze. The old oaks were too few to call the place “woods,” but they strained upward from the ground, then outward, at random intervals, making it apparent that this place was outside the city, even if just barely. Their branches and leaves were too proud to join the herbs on the ground in their dance, so instead they sat motionless as if suspended, timeless, in empty space beyond the edge of the universe.

To Tim and Carlos, it was the edge of the universe. They had skipped class, not for the first time, and slipped into a steam tunnel they had found the week prior. The tunnel allowed them to avoid the hall monitors and the assistant principal up to a place near the playground. Their chosen exit was conveniently situated near a part of the fence that they called their “secret exit.” The fence was a series of equidistant metal posts with a rail near the top, and another rail near the bottom. At the secret exit, one of the posts was not evenly spaced, leaving just enough room for the kids to squeeze through. Having reached the outside of their scholarly prison, they made way to the uncharted territory just outside the city limits, which provided the dual benefits of a lack of truancy officers and undiscovered treasures like whatever the round piece of metal hid.

It didn’t budge. A new strategy was needed.

“If only we were near my house,” lamented Carlos. “I could get us the crowbar from my dad’s toolbox.”

“Too risky,” Tim replied, “We’d get caught. But there must be something around here we can use as a lever to pry it open. Look around.”

The two kids scoured the area, looking for anything that might be requisitioned as a lever to pry open the metal cover. Some tree branches could be found scattered here and there on the ground, but Tim quickly wrote them off as too thin and flimsy, and Carlos agreed. Something firmer would be needed. Either a thicker branch, or…

“I got it!” yelled Carlos. “The farmhouse! There must be something we can use in there!”

About half a mile toward town, only a couple hundred yards from the last city block, stood an old abandoned shack. The boys, unaware of whatever purpose it had once served, had dubbed it “the farmhouse.” Inside was a single large room, or at least no interior walls had been left. The room was empty, having been ransacked decades earlier, except for a broken table and a couple of untrustworthy chairs, and, more relevant to the purposes of the moment, some two-by-fours and other rubbish strewn across the floor.

Tim didn’t need to respond. A brief glance between the boys communicated the necessary agreement, and they were off in a gallop toward the farmhouse. Not much more than three minutes had passed when the informal half mile race was over. Carlos arrived just moments before Tim, and the boys passed through the doorless doorway into the one and only room of the farmhouse. Carlos immediately grabbed one of the two-by-fours lying on the floor, while Tim looked around a bit before deciding on an iron rod that was probably once part of a gate or a fence. The boys walked their cargo back to the field with the mysterious metal lid, their chatter along the way full of speculation about the secrets it hid.

“There must be a buried treasure hidden underneath,” asserted Carlos, whose primary goal in life had always centered around searching for hidden treasure. At least ever since he saw a treasure map complete with ‘X’ marking the spot in a book about pirates, even before he could read.

Tim, always more practical, replied that it almost certainly covered some secret alien technology that the government had hidden many years ago, but forgot about.

The conversation continued along those lines for the fifteen-or-so minutes that it took to get back to the field and the metal circle.

Upon arrival, the boys immediately got to work. Tim shoved the rod under the metal plate and began to pull upward, while Carlos used a nearby rock as a fulcrum for the two-by-four, and pushed it down in order to lift the lid. The metal circle showed a stubborn reluctance to give way, but little by little the boys were able to force it until the thing sprung open with a snap. A rusty set of hinges had held it in place, but, vanquished by youthful ingenuity and determination, had broken into pieces.

“Oh wow,” remarked Tim. Removal of the lid revealed a hole consisting of a metal tube just over three feet in diameter that descended downward about fifteen feet. A set of metal bars, each shaped like a flattened U, stood one above the other to form a ladder on one side of the hole. “Who’s going in first?”

Carlos gulped. He felt a little queasy in the stomach, while his chest burned with excitement. As fear battled with curiosity, Tim took advantage of his friend’s reticence to make the first move. Tim’s head was already descending below the surface when Carlos decided to follow him down.

“Bad ass!” cried Tim when he reached the bottom. “There’s a whole house down here!”

Carlos finished his climb down and strained to look around as his eyes adjusted to the little bit of light that made it so far down into the subterranean dwelling place. They were in a cylindrical room, like a tipped-over can, except the circular cross-section was interrupted by a flat floor about three-quarters of the way down. On either side of the boys was a bunk bed. At the end of the beds stood a bookshelf against one wall and a small desk and chair against the other. The limited light failed to provide sufficient visibility to see what was on the other side of the room. Undeterred, the boys made their way past the bunk beds to try to make out what was there.

Books and magazines filled the bookshelf. Carlos took some interest in these, but exploration was the initial priority. As they progressed past the bookshelf, they found themselves in a small kitchen with a sink, stove, and some cupboards on the left, and shelves of canned food and packages to the right. Tim tossed one of the packages to Carlos, who took it over by the bunk beds to see what it was in greater light.

The package was brown or dull green; the color wasn’t entirely clear in the limited light. Carlos red aloud the words printed in black on its surface.

“Meal, ready to eat. Spaghetti with meatballs.”

He walked over to Tim and put the package back on the shelf. Over at the end of the kitchen, beside some large drums of water, was a door hanging slightly open. Pitch black reigned on the other side, and the boys decided that they would have to return later with flashlights to see what was inside.

“I bet it’s the bathroom,” commented Tim.

While Tim browsed through the cupboards and cans in the kitchen, Carlos returned to the middle part of the room. The desk wasn’t much more than a small writing table, similar to the student desks at school. The shelves held probably between forty and fifty books, and at least a couple dozen magazines. Carlos tried his best to make out the titles. Although the books were limited in number, they seemed to be quite varied: Carlos thought he could make out novels, science and math books, self-help books, and practical books on home repair, gardening, and troubleshooting cars. The nature of the discovery finally dawned on him.

“We’re in a bomb shelter!” Carlos had seen such things in an old television program about nuclear war, after which he read everything the school library had on the cold war, nuclear weapons, bomb and fallout shelters, and anything related he could find. Tim had seen the television show, but was more inclined to experiential knowledge than to books.

“Whoa, cool!” Tim responded after making sense of what Carlos had just said.

It was starting to get late. School would be getting out soon, and Carlos and Tim needed to make it back to their respective homes. After climbing out of the shelter, they carefully placed the circular metal plate over the downward-leading aperture. Without the hinges, only its weight would hold it in place now, but that was sufficient: It took the two kids working together to move it into place, and they made sure it would stay put. Their new secret hideout needed to stay protected, after all.

The light breeze had died down, and the grass and herbs were as still as the oak leaves when Tim and Carlos began the walk back toward civilization.

A Little Bit of Luddism

The internet is primarily a source of outrage and pornography. If that is not the most original thought, it is because it is apparent to many.

That is not to say that the internet provides nothing else. Certainly it offers unceasing advertisements for those of insufficient digital sophistication to use an ad blocker, as well as privacy invasions, and even the occasional malware. It may even provide something useful now and then, but these are not the central purpose of the modern internet.

Do I exaggerate? Maybe. But it takes only a moment to remember how productive I was before the internet became widely adopted. Being a little older provides the opportunity to remember a world that those just a little younger did not get to experience. It also provides the opportunity to join the chorus of every generation lamenting the fall of society and claiming that things were better in the old days.

Write me off as such a geezer, if you wish. You may be correct. I am writing my thoughts, but I do not feel it important that anyone accept them as correct. Nonetheless, I will still reminisce and make my comparisons. Perhaps I will even take some action to see if my life now might be improved by what I consider to be acquired wisdom.

Where was I again? Oh yes, productivity. I ought to be infinitely more productive with the vast repository of the world’s knowledge at my fingertips—a veritable tower of babel, if you believe those who assert that it was built as a central library of all human understanding. Between Wikipedia, scientific journals, legal and illegal book downloads, how-to videos on YouTube or how-to texts on websites, and seemingly infinite other sources of information, in principle I can learn how to do virtually anything.

I could, in principle. Yet I did, and much better, before I had all these resources available at all times. The encyclopedia, the library, and the bookstore, clubs and classes, provided what I needed before. Perhaps the greater expenditure of time and energy left me more insistent on finishing a project. Or perhaps the lack of immediately available entertainment, or links to related videos, left me undistracted from the task at hand. But without YouTube tutorials on Python, I managed to learn programming: First BASIC, then C, and even just a little bit of assembly language. Books and trial and error were sufficient teachers, since I found no teachers for this topic at high school. BBSes provided useful text files, but I often ended up turning to books that provided the same information in a more easily understood format. I learned the ins and outs of the PC… after learning the ins and outs of the Apple IIe.

I continued to learn programming after getting connected to the internet, but progress increasingly slowed as the internet became more immersive and faster. I learned new programming languages, I learned new libraries, but I no longer learned new things about programming. It was all “new” ways of doing the same thing, perhaps with a nicer interface, and perhaps networked, but no longer innovative. And it took me longer to learn each new, not-new thing.

I do not think it is merely me getting old, or having learned all there is to learn about programming. Once in a while I do learn something new and profound, and I have moments of great productivity in both coding and learning. This happens on the rare occasions when I close the web browser, pick up a book, and try out what it is trying to teach.

Programming is just the easiest example on which I can reflect. This phenomenon has affected several aspects of my life. Online examples were generally unhelpful when I was studying physics at university. If I had trouble understanding something, the library was where I solved the issue. My best work in law school occurred when I turned away from LexisNexis and opened up restatements, Corpus Juris Secundum, and the case reporters in the library. Even with gardening, YouTube videos are neat, but have not translated into great real-world results like just getting outside and experimenting with shovel, seeds, and a notebook.

This very article is being written on an Apple IIe. Otherwise, it probably would not be written: With a wide internet and infinite entertainment at one’s fingertips, who has time to write? Ironically, that Apple IIe is actually connected to the internet, but naturally such access is quite limited, and the non-multitasking machine will not browse the web while the AppleWorks word processor is open.

I could be that crazy old guy who is remembering the past a little rosier than it actually was. I don’t think so—I remember it as slightly more productive, not perfect—but it is possible. But my luddite self is testing the hypothesis right now. I am not crazy enough to entirely forego the internet. For better or worse, modern life depends on the internet. I could not do my job without it, and I would lose out on many great conveniences. I did say that it may provide something useful now and then, after all. So I am merely cutting out a significant chunk of leisure internet. When I would spend a couple of hours watching YouTube, or browsing news (or polemics) or social media, I am picking up a book, or using an old computer like this Apple IIe to write or do some old-style programming, or going outside for a walk.

It will be interesting to see what, if anything, I can get done that I was not doing before. Will I write about the results? Maybe. I can’t say. As I mentioned, I do not feel it important that you believe me, anyway.

(Mc)CLIM and Becoming Enlightened

This is a cross post from a Gemini site I recently set up.

About four years ago (based on Github’s estimate), I took an interest in the Common Lisp Interface Manager (CLIM), and more particularly in the McCLIM implementation of CLIM. I made a couple of YouTube videos of myself poking around and learning how to use it, but I did not get far at the time: I had quit my programming job some years earlier and was in law school, and mostly quit programming even as a hobby shortly thereafter. My favorite of the videos was a snake game, by the way:

Drawing in McCLIM (And a Snake Game)

When I decided to jump back into Common Lisp a couple of weeks ago, one of the first things I did was go back to that game, clean up the code a bit, and remove a line using a feature that is not present in current versions of McCLIM (and thus prevented the game from running). I had a lot of fun trying to learn McCLIM, but I constantly felt somewhat overwhelmed. The documentation seemed to hint at great power, but I could not see it. It seemed too complicated for a GUI library with a very dated appearance.

I finally obtained the first spark of enlightenment while writing my Gemini client. The client suffers from the same problem of treating McCLIM like a GUI library, but a couple of tasks changed my perspective. The first was links: I needed a way to get some “clickable” text onto a page, and perform an action when it was clicked. The second was similar: Bookmarks. In Observatory’s bookmark interface, bookmarks act like links that you can click on to visit a page, but have the additional option of deleting the bookmark when you bring up a context menu by right-clicking. The bookmark issue was fairly easy after I got links working (and, admittedly, gave up on a more complicated bookmark interface).

I spent several hours reading through the CLIM specifications and McCLIM’s user guide in order to figure out what to do about links. I had thought about just using push buttons (I think there may be a Gemini client out there that did just that), but I really wanted to use normal, albeit perhaps colored, text that was clickable. I had the idea that this thing called “presentations” might do the trick. I read through the portions of the documentation that describe presentations a couple of times before deciding that they wouldn’t work: They seemed to be about presenting an object to the user, and perhaps requesting user input to manipulate the object. I mean, you write translators to change objects into other objects, and these are somehow associated with presentations. What was that all about, and what could it possibly have to do with just making text clickable? Too much for links, and not quite relevant. I looked into putting gadgets (CLIM’s term for widgets) into the stream (the main pane of the output window is set up as a stream in Observatory, so the document can be displayed by pointing standard output to it), but again, I decided I wouldn’t be satisfied with buttons for links. Finally I read about presentations again, and this time I carefully reviewed the with-output-as-presentation and define-presentation-to-command-translator macros. This was the beginning of enlightenment.

Here is the code for writing a link to the application window in Observatory:

(defmethod write-doc-part ((line link-line))
  (let ((res (link-line-uri line)))
    (if res
    (if (string= (resource-protocol res) "gemini")
        (with-drawing-options (t :ink *link-color*)
          (with-output-as-presentation (t line 'link-line)
        (format t "~a" (resource-get-uri res))))
        (format t "~a" (resource-get-uri res)))))
  (format t " -- ~a~%" (link-line-description line)))

It works a little different from links in other Gemini clients: Instead of showing the link description and making it clickable, it displays the URI and makes it clickable, with the link description beside it. It would be trivial to make it work like other clients, but I found this to be more informative to the user about where he or she is being taken. But that is not relevant here. The point is, the clickable portion of the link is within with-drawing-options (which changes the color to blue) and with-output-as-presentation. The later is the important part: It associates the text that gets printed out by the call to format with ‘line’, an instance of the class ‘link-line’. We make it clickable by creating the aforementioned presentation to command translator:

(define-presentation-to-command-translator follow-link
  (link-line com-follow-link observatory-app
         :gesture :select
         :menu t)
  (object) (list object))

The above code associates the ‘link-line’ class with the command (defined elsewhere) ‘com-follow-link’. This command is run whenever the ‘select’ gesture is performed on a presentation of a link-line, resulting in the link being followed. The ‘select’ gesture is associated with a left-click by default in CLIM. (As an aside, “:menu t” makes the command show up in a context menu when you right click, so there are actually two ways to follow a link.)

Bookmarks have another option, since they can be deleted. So they have their own class with another presentation to command translator. This one also shows up in the right-click context menu:

(define-presentation-to-command-translator delete-bookmark
    (bookmark-holder com-delete-bookmark observatory-app
             :gesture :delete
             :menu t)
    (object) (list object))

The delete gesture is associated with SHIFT+middle-click, if I understand the documentation correctly, but I just assume users will use the right-click menu to perform the action. I expect ‘bookmark-holder’ will end up as a subclass of ‘link-line’ eventually, as I clean up some things in Observatory, assuming I continue to work on it.

Where is the enlightenment, you ask? Well, I learned from this experience that I should not think of CLIM as a GUI library. It is first and foremost an abstraction for presenting objects to the user, and providing him or her with operations, such as commands, that act on or using those objects. The interface is secondary, and should arise naturally from the commands made available to the user. This is a different paradigm from traditional event-driven GUI libraries, in which one crafts out the interface and then associates widgets with callback functions. It has its event loop, sure, but the programmer is expected to think more in terms of asking the user for input and acting on it, like a command line program, rather than waiting for events. Or really, a strange hybrid of the two programming styles, with some new concepts about how users interact with objects in the program. If my memory retains a correct history of those videos I made a few years ago, I remember being impressed by McCLIM’s interactor pane (which does not make an appearance in Observatory, by the way). I thought it could be something neat and useful, but I never really figured it out. I think I understand now: It is another way to get commands and references to objects from the user.

The next time I write a CLIM program, I will start out with a different type of thinking and different expectations. The interface will grow out of the needs of the program, rather than the program being made to fit into a predetermined type of interface. I will think about what type of things I want to do, and what data I want to operate on, and start out by providing commands for the user to work on that data. When a need arises for the user to provide input to a command, such as a reference to an object, that is where a bit of the interface will arise, naturally to fulfill a purpose.

Haunted

“It’s your fault! They told you the house was haunted, but you didn’t listen!”

Tod wasn’t convinced. Certainly a few strange things had happened since he and Joanne had moved in with their daughter Julia two weeks prior, but nothing that couldn’t be explained away.

The first incident had occurred on their third day in the house. They came back from the store to find a vase shattered on the living room floor. It had been in the kitchen. At first, they thought that they had been victims of a burglary, but a quick search through the house found nothing else amiss. Maybe it was a burglar—thought Tod—but one who had second thoughts and left without taking anything. Or perhaps a neighbor’s cat, or a wild animal, found some way in and out.

The following night Joanne and Tod had been awakened by a scream from Julia’s room. Somebody had tugged at her feet, she insisted, but nobody was there. Just a child’s imagination.

Over the next few days, Julia had developed a new imaginary friend: the ghost of a young girl named Emily. Emily, recounted Julia, had died of the flu about a year after her father and older brother both died in the war. Julia also met Emily’s mother, Elizabeth, who, bereft of her husband and her two children, died of a broken heart shortly thereafter. Tod was unsure whether he approved of the macabre direction in which Julia’s imagination was developing.

Tod was, however, extremely happy with Julia’s new school. After just a few days in the new neighborhood, Julia had memorized and often recited several poems by Emily Dickinson. Tod didn’t recall having learned of the great American poet as early as first grade, so the education system here must be doing something right. Julia, of course, insisted that Elizabeth had taught her the poems. The deceased matriarch seemed to have been a dedicated reader of poetry during her life, and named her daughter after her favorite poet. Julia’s favorite was “The Chariot,” though Tod was unfamiliar with that title. He had heard it referred to by its first line, “Because I could not stop for Death,” but that was, of course, a long time ago. In any case, Julia’s claims to have learned that particular poem from a ghost were amusing, and seemed nothing more than the regular operation of a seven-year-old’s imagination.

During their two weeks in the house, both Tod and Joanne had, at moments, thought they had seen some figure moving from the corner of their eye, but this was the most easily dismissed of all the occurrences.

The voice that evening, however, had frightened Joanne enough to momentarily drive off any doubt. Tod had heard the voice as clearly as she did—a woman’s voice advising Tod not to go to work on Monday—but notwithstanding such clear evidence, Tod was not inclined to start believing in ghosts. They had somehow experienced a mutual hallucination, he insisted. Whatever it was, Joanne was none too pleased about it, nor about the recently acquired house. With some persistence, and after a visit to each room of the house to ensure that nobody else, besides Julia, was there, Tod was able to convince her it was nothing. They settled down to sleep. Disconcerting as the voice had been, neither Tod nor Joanne gave a moment’s thought to its warning.

The following Monday, some time after Tod had left for work, Julia approached her mother. “Mom,” she said, “Emily says that you didn’t pay attention to her mother’s warning and now Dad is in trouble. But don’t worry. Her brother and her father went to help him, so he’ll be alright.”

Joanne was, needless to say, a bit taken aback by her daughter’s comments. She and Tod had not told Julia about the voice the other night, but perhaps she had heard it, too. Or perhaps it was all just a strange coincidence. “Don’t be silly,” she said to Julia.

A few minutes later she turned on the news. The main bridge into town had collapsed onto the freeway that morning. Several people had died, and a search for survivors was ongoing.

As if by instinct, Joanne picked up the phone. She dialed Tod’s number. No answer. She called the office where he worked. “He hasn’t come in yet today.” Joanne shivered. A sinking feeling took up residence in her stomach, and a pain in her chest as if her heart were attempting to beat its way out of it.

Julia noticed her mother’s agitation. “Don’t worry, Mom. Dad’s alright. Emily says so.”

Joanne wasn’t in the mood for her daughter’s games right then, but she admitted to herself that the words brought some mild comfort. She composed herself, and a few phone calls later found out that her husband wasn’t missing, even though he was on the bridge when it collapsed. He was in the hospital, but nobody could tell her what his condition was. At least they thought he was alive.

Joanne wasted no time. Within five minutes she and her daughter were on the road. In less than half an hour they pulled into the hospital parking lot. In the emergency room lobby, they found out that Tod was in stable condition, and they received directions to the pod where they could find him.

Tod was conscious and in good spirits. The doctors said that, other than a few scratches and bruises, he had a concussion and a noncomminuted tibial fracture. No surgery would be needed, and he would be able to return home that day. The injuries were remarkably light in view of the accident, considering that his car had been completely crushed by debris after falling with the approximately twenty-foot-high bridge. The ambulance technicians had said that they found him a few feet away from his car, on a relatively flat piece of fallen stone rather than buried along with everyone and everything else. This had allowed the first responders to get to him and treat him quickly, while even at this time many people were still buried under the rubble.

Todd said that the events almost seemed like a dream. It doesn’t make sense, he confessed, but the way he remembered it, it was as if the bridge were still in mid-collapse when two men were pulling him out of the falling car. They wore curious outfits that made them look like World War One soldiers. But they were gone by the time the first responders had arrived, and no other witnesses had seen them.

Looking Backward

Steve’s feet sunk only slightly into the wet sand, just enough to feel it between his toes. Only the sound of the breaking waves interrupted the eerie silence. Not even a seagull graced the shoreline to provide a sign of life on the empty beach. As Steve pondered on the unusual emptiness, the shock of icy water hitting his feet jolted him out of his thoughts. He suppressed his reaction and continued walking, allowing the periodic flows to come and go over his steps, as if the ocean were breathing over them. It tempered the feeling of solitude, but only for a moment.

A set of footprints. Someone else had been on the beach. In the wet sand. Recently, since the tide had gone out. They extended southward, away from the houses and other signs of civilization. Nothing beside the single set of footprints. The lone and smooth sands stretched out as far as eye could see in both directions.

“There are no return steps,” Steve muttered to himself, “whoever was out here must still be on the beach.”

He took a step forward, almost involuntarily. A strange feeling compelled him to follow the footprints. Like the sound of the waves breaking and the crash of water against his ankles, the footprints failed to hinder the feeling of solitude. Step by step he followed them as the sun sank toward the horizon and the water shifted imperceptibly inward as the tide began to roll in.

Steve walked, lost not in thought, but in a strange thoughtlessness. Perceiving, not pondering. He was acutely aware of the water and the sand, the shifting tone of the sky as dusk approached, the houses no longer visible in the distance behind him. The angry sun beat down heavily on the sole trespasser in the void over which it ruled, as if bitter over its own impending disappearance at the rapidly approaching end of the day. Steve perceived but didn’t react. In his awareness without thought, he continued after the footprints, step by step.

He walked. He felt the sand between his toes. He felt the water washed away. He felt the non-presence of the mysterious person whom he compulsively followed, but who didn’t seem to exist.

The footprints shifted slightly inward, away from the water and away from the incoming tide. The mysterious being couldn’t be far ahead, but Steve still could not see him.

The sun hit the horizon. The footprints made an abrupt turn. Steve turned toward the water. Against the wide sun melting into the sea stood a man among the waves. As the icy water hit Steve’s feet once again, the chill ran up his spine and into his chest. He tried to call out to the man, but the mysterious figure dove into a wave and disappeared, just as the last of the sun disappeared below the horizon in a green flash.

Steve stood motionless, frozen solid. He waited. The figure did not rise back out of the water. He waited. The sky turned a deep blue and Steve could make out the first stars. He turned to head back. The squawk of a seagull interrupted the silence as the bird flew past Steve. He glanced back for a moment and saw the silhouette of a black dog in the distance.