Posts By kfsone

‘amul’ breathes again

in 1990 it was a 16-bit, AmigaDOS system

I’ve mucked about trying to resurrect AMUL here and there over the years, reworked a bunch of it under the moniker “SMUGL” but once I was done with the particular aspect (sockets, classes, whatever) I never got to the important task of making it work.

After another couple of forays into poking the bear recently I tasked myself with strictly focusing on finding what was making it crash and fail to load.

It turned out that some time in probably 97-98 I’d deleted a line of code necessary for the game to figure out how much data it was loading, oops.

Largely it turned out to be my lack of C++ understanding in ’92. Apparently I learned the lesson but decide not to apply the learnings.

I’ve tried to mostly stick to pretty much C code, but then luxuriated in a few “really does something useful” C++ features to let me focus on the important and fun parts. I’m going to try and keep the struct/class hierarchies flat, with a very limited amount of inheritance to fill in for the absence of interfaces in C++.

It consists of three main components:

Compiler: Which is a bit generous of a name for what it really does, in my mind anyway. It consumes various text files and spits out a set of binary data files.

Engine: AMUL had a server (manager) and copies of the “frame” (a combination client/server) directly manipulated its memory. SMUGL has a single executable which simply forks itself to become a client. Static data is visible to the child and shared memory homes the mutually-modifiable data.

Game code: Someone actually has to describe the game world, commands and behaviors.

The language itself is part data definition and part functional programming, in that you are writing pattern matching sequences followed by lists of steps to execute when those patterns are matched.

verb=help           # How to deal with a player input starting with help
syntax=player=me    # more specific: "help me"
  respond "I'm just the narrator, ask another player?"
syntax=player
  checknear player  # make sure we're near the player you named
  if helping player fail "You're already helping them."
  if helping someone fail "You're already helping @hp"
  help player       # execute the built-in 'help' action
  tell player "@me is now helping you."
  respond "You are now helping @pl."
syntax=player=madhog verb=tank
  fail "I don't think it can be done."
syntax=player verb
  respond "That's not how this works, you tell *me* what *you* want to do."

The current language is overly specialized, but on a modern system I think I can quite comfortably address some of the issues that effectively forced my hand back in the day.

I’ll probably spend the next few days of hacking replacing the “Posix Shared Memory” code with memory-map backed storage so I can run it on Windows, and doing a better job of separating dynamic from static data. Then I’ll whittle down some of the “muscle work” code that I feel comfortable entrusting to the C++ standard library/my own simple classes/templates.

My big plans are for completely replacing the compiler’s parser and parser generators: I’ve fleshed out a design that intentionally falls short of being a complete parser generator but instead meets you half-way with a fairly clean and readable actual-code description of your language as a state machine.

// names starting lower-case are user-written functions that capture
// token(s) and validate them.
error_t newRoom(Token);     // write a function to capture a new room name
error_t addRoomFlag(Token); // write a function to capture/check each flag

auto RoomLine = Optional("room=") + (Identifier()->newRoom) +
                ZeroPlus(FromList(roomFlagList))->roomFlags +
                Peek(EndOfLine());

auto RoomShortDescription = LineOfText()->shortDescription;
auto RoomLongDescription = ZeroPlus(LineOfText())->longDescription;

auto RoomParser = RoomLine() + RoomShortDescription() + RoomLongDescription();

Lastly I want to abandon the current fork-per-client model. I’ve written a small replacement library that emulates a portion of the Amiga’s “Message Ports” message-passing system. By using that and “thread_local” on my excessive number of globals, I think I can quickly get to a working single-process, multi-threaded version (and then get rid of all the globals)

I’m trying to work up to opening up the source repos, but I’m not quite ready to do it.

FreeBSD!

The last functioning binary I have of my Linux port of my MUD language was apparently compiled on FreeBSD some time in the mid-2000s.

So I’m setting up a bunch of FreeBSD Hyper-V machines to try and get a working environment with which to demo it to someone.

And right now I’m all the way back to 4.2, but I have this hunch it was 2.x something, which will mean going back so far that I use CD ISOs.

I’d forgotten how 8-bit retro BSD feels even when it’s shiny new.

Ready to plus it up – a little

The foray into raw C has been fun, but there are three things that I miss: references from C++, multiple-return types from Go et al, and some variation of function-to-structure association.

References save a lot of null checking, and ‘.’ is two less keypresses than ‘->’.

Multiple return types lets you tackle the oddity of “pass me the address of the thing I’m going to give you”

// what I mean:
read(char* into, size_t limit) returns (bool success, size_t bytesRead)

// what c libraries do:
ssize_t /* -1=err */ read(char *into, size_t limit)

// what I do:
error_t read(char *into, size_t limit, size_t *bytesReadp)

But that pointer on the right means an input parameter to my function instead of the output I want to denote.

Methods give you name spacing, first and foremost, but they also just provide a logical separation I find I’ve missed in going back to C.

In particular, Go’s method implementation really appeals to me.

Go doesn’t have the complication of header files, so unlike the C+… family of languages, you aren’t bogged down with boiler-plate and it also didn’t feel the need to convolute structure definitions with pre-declarations of implementations of functions.

When viewed thru a C++, Java, C# etc lense, the following will make your skin crawl:

typedef Buffer struct {
    data     []byte
    cursor   int
}

func (b *Buffer) Read(into []byte) (bytesRead int, err error) {
    ....
}

On the left, (b *Buffer) is the “receiver” type, it’s how Read is associated with Buffer. On the right are the parameters, into, and after that is a list of the return values.

How are you supposed to know what methods a class has? That’s probably part of what made your skin itch.

The answer is: Probably not by going and reading header files or code. Go has incredibly powerful tooling that makes it a doozie to integrate with IDEs and editors. It’s sickeningly fast to parse, and documentation is generally highly accessible.

I’ve about gotten the AMUL code to a place where I’m ready to think about trying language only C++ – that is, C++ language features but none of the STL.

The thing continues

Ordinarily, at this point, I would be sharing my github repos so you can see the code I’m tinkering with. Two things are stopping me.

The last time I shared the code for AMUL, it was with someone I was discussing a possible port to Linux with back in ’94. That someone said “Can’t help you” and I got distracted with my job at Demon Internet. A few years later I found that a lot of concepts from AMUL had surfaced in another MUD language across the 6 months immediately after sharing the source, and that the individual I’d shared it with happened to be the author of said language…

More importantly, my snapshot is not of the last release. I don’t know why that bothers me (re sharing), except that I’m hoping I’ll find a more recent version that has the huge swath of cool stuff I introduced between the version I have code for and the AMUL900 that’s still out there. I think it’s knowing that I have probably lost the files at some point, or they are buried so deep in my nested collection of archives that I’m not finding them :)

Meanwhile, I’m still really super-enjoying working in pure C on this project. I wouldn’t necessarily choose it for a follow-up project, but I’m spending radically less time on boiler plate.

I spent a part of today formalizing bits of stuff I had in external folders – so now there’s a Dockerfile for an ubuntu and an alpine build environment.

One advantage of doing this in C, at least first, is that it’s proving a lot easier to static analyze and bug hunt.

Dyson Work Light

Saw a cool-looking desk lamp at Best Buy the other day and made the mistake of letting the Dyson vendor start talking to me about it.

It’s a work light.

That costs $599.

Because (a) the arm conducts heat away from the leds, you know how leds are infamous for burning out because of heat, right, well thanks to the arm these can last YEARS until you have to replace the entire unit because it’s special magic LED that will cost you more replace than a new worklight! (b) it has super-high-tech secret sensors that allow it to match the ambient light.

Or: It costs $599 because it has a special LED, designed to get really super hot, attached to a heat-conducting metal arm with a heat-pipe in it that will conduct that heat straight into your hand when you try and adjust the lamp – which you will do regularly because you can’t tell whether the light is on or not.

Frankly “can’t tell whether the light is on or not” is the opposite of what I look for in a lighting solution. And when the guy demod it for me, it really did match the ambient light so well that we both had to tilt our heads to look directly at the bulb to be able to tell it was on.

The guy took great pleasure in showing me how you could raise or lower the arm, how it rotated, and then nearly flipped out when I started to reach for it..
Not only can you not tell whether the light is on or not, you can’t point it where you want, and people keep breaking his floor models by trying to twist or pivot it. The mechanism on the stand looks exactly like the kind of mechanism that would allow you to tilt or twist the arm. The picture on the front of the box is even taken from a bizarre angle that makes it look like the lamp has had the head tilted upwards.

Actual:

But it was standing in-front of images like these:

And what I refer to as the “light comes out here” picture

But I think this actual Dyson promo picture sums it up

“The light from my phone is reflecting off the lamp”
“I can’t quite read whats on my phone, I’ll have to lean forward for a closer look”
“This posture looks totally natural”
“It’s a touch screen, that’s why I’m not looking at it”
“I’m calling 911 to report this thing, and not taking my eye off it”

Yep – if there’s one thing you want from a work-lamp, other than light, having it directly overhead of what you want to work on, right at eye level, that’s got to be right up there… I’d throw my money at the screen but it’s too dark in here to see my money or the screen…

I did a thing

A about a month ago, I dug up an old copy of my MUD language from 1990, and took a crack at refactoring some of it in C++, but I quickly got frustrated with just how much that felt like work rather than fun, especially after my recent foray into golang.

So I have this 29+ year old code, written in original K&R ANSI C, and I want to get it, say, at least compiling.

Why not take a shot at doing it in pure C?

Analytica

Cambridge Analytica weren’t doing rocket science or hacking. They didn’t get your social security number, your phone number or your browser history.

They built a few ad-targetting criteria with such low precision and accuracy any marketing person would be ashamed of the numbers.

That imprecision played to their ends. Remember the goal was to be disruptive, so although they were using ad-targetting technology, having built-in misses was actually a boon.

What they did was:

1. Get people to fill out a survey,
2. Collected their facebook profile data with consent,
3. Collected uninteresting public profile data about their friends like public group memberships,

Then they used some machine learning systems to:

a- Build an ad-targeting profile of the survey respondents using #1,
b- Build the same ad-targeting profile using #2, but “back-train” it by correlating #1 and (a),
c- Use (b) on that uninteresting public stuff in #3.

They weren’t trying to pin down anyones’ precise political alignment or belief system, they were looking for broad strokes: Watches Colbert, Watches Hannity; Loves Guns, Loathes Guns.

City-building for VR

There are a couple of RTS type games for VR, but they’re just projections of the existing style of game, and doing this stuff by hand is clunky and annoying.

What I’d like to see is a VR-capable building game that lets you operate from the old top-down perspective for viewing the big picture, but lets you zoom on down to the in-situ level to see what the people are doing and to do things like plan/upgrade buildings, and using gestures etc to give it a cyberspace-god-like feel.

Figure: You’re standing on the gravel path watching your woodworkers heading out to chop down trees. They mumble about being hungry as they pass. Oh yeah, I could use a bakery. Circle your hand to open the blue-glowing buildings rolodex, tap your hand on the glowing bakery image, and then throw it down to roughly where you want it; use both hands to twist/position it, and then bang your fist down to make it so.

You could, of course, do all of this from the more conventional menu systems, but including the creators-eye view would just make it that much more kick ass :)

 

What changed about the ‘net?

So “What changed in the last 15 years of the Internet?”

It’s not actually the Internet we’re talking about regulating. The truth is, in the USA, we’re talking about preventing Comcast and Charter.

On paper, Comcast’s internet subscribers passed their TV subscribers in 2015.

On paper.

The weakest link

Contemporary voice recognition systems over-emphasize learning based on explicit “a=b” training; that is, there is a vital absence of false training.

I imagine a parent and child: the parent says “It’s time for …” as a peal of thunder ripples through the room. This might be used as a comedic device precisely because we would not expect the child to respond “Yes, daddy, I’ve turned on the lights in the kitchen”. I’ve yet to hear a voice system ask me what “ACHOO” means or just say “what was that?”

After a hiatus, I return to Windows speech recognition and am confused by just how far ahead it is of the technology we rely on in Siri, Alexa, Google Home, even Microsoft’s own Cortana.

For training it still relies on the old “speak these words” explicit recognition training.¬†This is basically the same tech that shipped with Windows 7, and this comes back to my point: This approach was already not-even state-of-the-art when Windows 7 shipped.

I believe a far better approach would be to a decoupled training procedure: don’t tell the training system what the user is being asked to say. Instead, use a combination of pre-scripted phrases, common keywords, and insight into the state of the network, to decide what to ask me.

Then, ask the user to exclude options until they are down to something close enough to need individual words correcting.

There are two major gains here: 1. The user gets clear feedback on where the system is struggling to understand, 2. Instead of teaching the system that “*cough*pi” means pizza, and that “zzaplease”¬† means “please”, I can acknowledge the system’s ability match sounds to speech.

The problem of purely positive training is compounded by the assumption engineers make that the systems will only hear deliberate communication.

Think about this: You cough and your voice system activates. You say “I wasn’t talking to you”, and you get a witty reply.

Except: You actually just trained the system that it heard it’s activation word; it may have changed in recent months, but it was certainly true at the start of the year that all the big systems had this flaw.

Nor does being quiet help.

I think this is part of why all of the current systems have the ability to suddenly become dumber on you. Perhaps the microphone is suddenly muffled, or perhaps the subtle changes of you having a cold for a day totally reaffirmed some weak association in the engine and it’ll take you months to untrain it again so it recognizes your regular voice.

It’s my hunch this is why there is so often a clear honeymoon period with devices like Alexa, Google Home etc: you become less forgiving, the system becomes over-confident, the first thing you say gets misunderstood, and your speech pattern changes as you become annoyed, angry or bothered by the device. So instead of your normal voice being the voice it expects, your angry or shouty voice is the one it trains itself on the majority of the time.

Alexa does provide the ability to provide corrective feedback via the Alexa app, but that quickly becomes burdensome and after the first few months, largely seems to be ineffective.

Positive AND negative training are the way forward.