Blog

What I'm Watching: Alphaville (1965)

I've seen Jean-Luc Goddard's bizarre SF film every decade or two. It makes no more sense each time but a different kind of non-sense. A Rorschach test for where society is.

Lemmy Caution 003 (Eddie Constantine, reprising his role from Poison Ivy and something like 20 other spy flicks), ostensibly a reporter for Pravda, wanders a bizarre artificial city, with a short target list. Everyone he meets is a drone, but often a drone with a non-drone social role, such as the "Seductress, Level 3" (what's level 1 or 2?!), or the scientists "Heckel & Jeckel" (from the cartoon crows). Or, ultimately, Dr. Nosferatu née Von Braun; they're as subtle as supervillains ever are.

His former colleague Henri Dickson (Akim Tamirof) is a dissolute wreck, unable to adapt to life in Alphaville, but unable or unwilling to betray it or leave before it consumes him. A buck for a room, a buck for a beer, and a buck for a whore, is a good way to kill a man. The analogy that ants started as individuals, with art and creativity, and then became part of the hive and now have nothing… it's very like Frank Herbert's Hellstrom's Hive, but that relies on biology not technology. The theme's also used in Shirow Masamune's Appleseed (read the manga, but the '80s anime deals with this part exceptionally well too), where the 20% natural Humans (using the term loosely for cyborgs like Deunan and Briareous) in Olympus are maintained by 80% Bioroids who pass as Human under the city's all-controlling artificial intelligence, and still the Humans despair and kill themselves because they're birds in a cage.

The extreme conformity and social control making everyone march along to their destruction is very familiar. The execution theatres are more humane than our current model of persecuting anyone who has ever made Human mistakes; they get shot and drowned by pretty girls, while we continue persecuting them forever. One can never expiate sin in 21st C society.

The croaking voice they used as the voice of the computer Alpha 60 is awful; HAL 9000 in 1968 is more like the real future of Siri. And yet obviously you should not ever watch movies in dub, only in the original language with subtitles. The slideshow/exhibition as art of the artificial society is plausibly unbearable to watch for a normal Human, not one of the mutants/controlled people of the city.

The metaphor the city uses of distant planets and galaxies confuses many viewers, and for that matter I don't know that Goddard didn't mean it literally himself even though it's bullshit; but it makes more sense that Alphaville is what it seems, a city in some isolated wasteland, transformed by Alpha 60, and everyone has been taught they're on a distant planet, along with all the other Newspeak and programming they endure. There's no evidence of spaceships, they drive in and out of Alphaville, and it's merely set 10 years in the "future" (stated: 30 years since America & Soviets got nuclear weapons, so 1975 from the film's 1965). And of course Lemmy Caution makes no sense wandering into a science fiction world, rather than just doing his James Bond-like spy shit in a mad genius's experiment.

The city looks great as long as all you can see are dark skylines and brightly-lit office windows, but in the occasional lit street scenes it looks like a sad ex-Warsaw Pact country. Star Trek managed a few large-scale sets in 1966, even though it often cheated and just had a matte and some styrofoam rocks, not actual street scenes. The car chase later is comically bad, slow-motion and visibly just a shitty suburb with cars saved from a wrecker.

The nonsense of "love" in the film is the one thing I really can't stand. Lemmy and Natacha have no connection, barely any interaction; she might at best be infatuated with the weird stranger, and her charms are superficial. I know, the French don't necessarily need such depth to start calling it "amour", but this is a weekend fling.

(reading "bible" aka redacted Newspeak dictionary): "Conscience. Not there. So nobody here knows what it means anymore."
—Natacha Von Braun (Anna Karina) describing Silicon Valley

My Rorschach reading for this viewing is conscienceless men using artificial intelligence to plan the destruction of Humanity and annihilation of home systems, to wit Facebook and Google (Amazon, Microsoft, and Apple being more of a Brave New World/THX-1138 style of consumerist dystopia). Sadly it is not so simple to solve as a few bullets and asking an AI some dumb riddles to blow its fuses (Alphaville, Logan's Run, and Star Trek got their computers from the same substandard maker, it seems). HAL goes crazy, but he's not defeated by anything as lame as a Sphinx.

I… IN… FIN, the ending spells. Is Alpha 60 saying "I am finished", or is it trying to spell infinity?

★★★★★ but it's madness.

Writing a Doorgame

So, how did I write this? Mystic BBS has a Pascal-based scripting, but I didn't really like using that; it's very powerful, but a pain in the ass to code/compile/test on, and it's just different enough from normal FreePascal to annoy me. And then tried to use Mystic's "integrated Python", which just doesn't work; I tried everything to make it find Python. And it's 2.7, so bleh. BUT: Adding a doorgame with the menu system lets you specify any executable, including a Python 3.7 script, and pass in a few command-line arguments about user and directories, so that's what I did (though the server I'm using only has Python 3.6, which hasn't been a problem yet, but be aware)…

The BBS handles all the redirection from network to stdin/stdout, otherwise I could use inetd for the same thing, but then I'd have to deal with all the login and networking state. Doing this as a door simplifies programming back to 1970s level!

I'll eventually open source it, but while I'm iterating and early on, I want to keep some of my secrets.

ANSI Color

There's ANSI color everywhere, of course. curses is fucking awful and archaic, and built to handle many incompatible terminals, which isn't a problem anymore. Mystic uses the same trick I'm using, and many others back in the day: Strings have escape codes |XX in them. Mystic uses numbers for colors, which is awful, and has hundreds of BBS-specific strings, which I have no need of. So all I did is this:

# set to 1200, 9600, etc. to simulate modem transmission rate
kModemSpeed = 0
kLinesPerScreen = 24

kAnsiEsc = "\x1b["

#      0   1   2   3   4   5   6   7   8   9   10
kAnsiBoxLine =  ["─",   "│",    "┌",    "┬",    "┐",    "├",    "┼",    "┤",    "└",    "┴",    "┘",]
kAnsiBoxDouble =["═",   "║",    "╔",    "╦",    "╗",    "╠",    "╬",    "╣",    "╚",    "╩",    "╝",]
kAnsiBoxHeavy = ["━",   "┃",    "┏",    "┳",    "┓",    "┣",    "╋",    "┫",    "┗",    "┻",    "┛",]

# ansiFilter, called by write/writeln, replaces |XX with escape codes:
kAnsiEscapeCode = {
    "CD": kAnsiEsc+"J",         # Clear Down
    "CL": kAnsiEsc+"2K",            # Clear Line
    "CS": kAnsiEsc+"2J"+kAnsiEsc+"H",   # Clear Screen
    "DI": kAnsiEsc+"2m",            # Dim
    "ES": "\x1b",               # Escape ASCII 27
    "GG": "\x07",               # Bell ASCII 7
    "HR": kAnsiBoxDouble[0] * 79,       # Horizontal Ruler
    "LI": kAnsiEsc+"1m",            # Light/Bright
    "PI": "|",              # Pipe char |
    "RE": kAnsiEsc+"0m",            # Reset Attributes
    "UN": kAnsiEsc+"4m",            # Underscore

    "FK": kAnsiEsc+"30m",           # Foreground Black
    "FR": kAnsiEsc+"31m",           # Foreground Red
    "FG": kAnsiEsc+"32m",           # Foreground Green
    "FY": kAnsiEsc+"33m",           # Foreground Yellow
    "FB": kAnsiEsc+"34m",           # Foreground Blue
    "FM": kAnsiEsc+"35m",           # Foreground Magenta
    "FC": kAnsiEsc+"36m",           # Foreground Cyan
    "FW": kAnsiEsc+"37m",           # Foreground White

    "LK": kAnsiEsc+"1;30m",         # Foreground Light Black
    "LR": kAnsiEsc+"1;31m",         # Foreground Light Red
    "LG": kAnsiEsc+"1;32m",         # Foreground Light Green
    "LY": kAnsiEsc+"1;33m",         # Foreground Light Yellow
    "LB": kAnsiEsc+"1;34m",         # Foreground Light Blue
    "LM": kAnsiEsc+"1;35m",         # Foreground Light Magenta
    "LC": kAnsiEsc+"1;36m",         # Foreground Light Cyan
    "LW": kAnsiEsc+"1;37m",         # Foreground Light White

    "BK": kAnsiEsc+"40m",           # Background Black
    "BR": kAnsiEsc+"41m",           # Background Red
    "BG": kAnsiEsc+"42m",           # Background Green
    "BY": kAnsiEsc+"43m",           # Background Yellow
    "BB": kAnsiEsc+"44m",           # Background Blue
    "BM": kAnsiEsc+"45m",           # Background Magenta
    "BC": kAnsiEsc+"46m",           # Background Cyan
    "BW": kAnsiEsc+"47m",           # Background White
}

def ansiFilter(s):
    """Replaces |XX codes with values defined in `kAnsiEscapeCode`."""
    out = ""
    slen = len(s)
    i = 0
    while i < slen:
        c = s[i]
        i += 1
        if c == "|":
            esc = s[i:i+2]
            i += 2
            out += kAnsiEscapeCode.get(esc, esc)
        else:
            out += c
    return out

def ansiGoto(pt):
    return "%s%s;%sH" % (kAnsiEsc, pt[1], pt[0])

def readln(prompt):
    """Calls input after filtering prompt."""
    return input(ansiFilter(prompt))

def write(s, end=None):
    """Filters `s` and writes to stdout, writes `end` if needed, flushes stdout."""
    if type(s) != str:
        s = str(s)
    lines = 0
    out = ansiFilter(s)
    for c in out:
        sys.stdout.write(c)
        if kModemSpeed:
            time.sleep(1.0/kModemSpeed)
        if c == '\n':
            lines += 1
        if lines >= kLinesPerScreen:
            readln("|RE|FC[MORE]|RE")
            lines = 0
    if end:
        sys.stdout.write(end)
    sys.stdout.flush()

def writeln(s):
    """Calls write with `end='\n'`."""
    write(s, end='\n')

Now if I want someone to talk in bold cyan (which I chose as my standard NPC color), I just
writeln("|RE|LC%s says, \"Mellow greetings, sir!\"|RE" % (npc["name"],))
RE before and after text is important, resetting colors from previous strings.

The one problem is I can't use | in ASCII art, so to generate my big character logos, I write a script mysticFiglet.zsh, making : the vertical char:

figlet -f small "$*"|sed "-es/|/:/g"

Flow Control

The great part about a doorgame is, no event loop. Oh, there's a REPL of sorts:

    def run(self):
        self.running = True
        try:
            #TODO: Python 3.8: while line := self.prompt():
            while self.running:
                line = self.prompt()
                if line == None:
                    break
                words = line.split()
                if len(words) == 0:
                    continue
                self.parseWords(words)
            self.save()
            self.doHelp("?", "_outro")
            return 0
        except (EOFError, KeyboardInterrupt):
            self.save()
            return 0
        except Exception:
            writeln("|GG|RE|BR|FWERROR! Something went wrong.|RE")
            logging.error("", exc_info=True)
            self.save()
            return 1

It just blocks at input (called by readln, called by prompt), and continues on until self.running = False, or an exception is thrown. Whee! The usual game loop makes it impossible to get stateful input without leaving giant memos of current state, so the event loop can keep cycling at 60fps.

Data Files

One solution would be to just make everything in classes, and use Python's pickle to archive everything. But the problem is that's pure binary, you can't easily hack on it or see what's happened, and on load you can't change any values. So instead I only use primitive types and archive everything to and from JSON. Floor maps and Players have a toData() method which produces a JSON-compatible data structure, and their initializers take a data structure and pull out or translate the values they need. It's a little more work, but means I can debug faster and add new fields faster.

The floors use a super-simple data file format, with an ASCII roguelike map and a series of command lines to create NPCs, traps, text, etc. The weapons and armor are listed in an even simpler format, with space-delimited fields.

Both the command lines and item formats are just run thru a tokenizer I wrote, that reads words, "strings", numbers, and [lists]:

type    name        cost    stat    bonus   damage  inflicts    twoh
wpn "Club"      5   Str 0   3   [blunt]     0

becomes:

{'type': 'wpn', 'name': 'Club', 'cost': 5, 'bonus': 0, 'damage': 3, 'inflicts': ['blunt'], 'twoh': 0}

Mystic Dungeon BBS

As previously mentioned, I'm interested in BBS's.
So I set mine up! After 30 years, The Dungeon is back as The Mystic Dungeon BBS!

mystic-dungeon-2019-02-23

Connect with: telnet mysticdungeon.club 1666
(soon I'll have a proper domain, and SSL cert so you can ssh host 2666)

Set your terminal for black background, 80x25, and UTF-8, I dunno what it'll do to DOS CP, but everything's Unicode now.

If your Mac doesn't ship with a telnet anymore, you can grab the previous OS's one from a backup, or port install inetutils and then use gtelnet.

Of course visit the Doors to try the Mystic Dungeon doorgame!

Dungeon-2019-02-23-23.56.20
Dungeon-2019-02-23-23.56.45

I wrote the start of this last weekend in a Ballmer Peak, and have been adding to it since. Now it has a town and a dungeon with 8 levels, 24 kinds of monsters, combat, an innkeeper for resting, a merchant for buying equipment, and banker for saving money between deaths.

Coming up are potions and other useful items, traps, chests (which are often trapped), and magic.

Right now, only Fighters make any sense to play, though different races have some advantages (Dwarf especially for long-range darkvision in the dungeon, since I don't sell light sources yet!). The character shown is a bit cheaty on cash and XP; it'll take a long, long time to reach that level legit.

Only Solutions Tuesday Music

Time to code like it's 1985, all fucked up on soda1 and listening to movie soundtracks:


  1. Pepsi, which is now ugh. I also drank (still do) very strong tea, just steep breakfast tea until it's undrinkable, then drink. I didn't switch to coffee, Jolt, and Coke until college. 

PowerSolo Sunday Music

It's super rare to hear a new-to-me band (duo) that just plays good rock 'n roll/rockabilly, and their video/stage act is astounding, like David Byrne all over again:

Albums:

Band info:

Bookmarklets

I just fixed a bug and re-uploaded these. They're little scripts that sit in a bookmark, like on your favorites bar, and do something useful to the web page. Monochrome Dark & Light change the page style; View Source puts source and plain text in boxes you can easily view and copy-paste from.

BBS

My teenage years IRL were difficult; I grew up in a time and place where to be a nerd was as bad as being a fag, you'd get beaten or murdered for that by the inbred hillbilly apes. Happily, there were local BBS's full of other nerds, COMER (cbbs? Terrible people, but it had dnd, a fairly complex D&D command-line game), Elvin Forest (Apple ][ board, nicer social group), Three Roses Inn (WWIV, Wil's board was our game hangout), a few others, and eventually my own, The Dungeon (first on Atari 800 running software I don't recall, later on Atari ST running STarnet) and later in Spokane I ran The Caves of Steel (Fnordadel on Atari ST/MiNT UNIX-like).

I still hit up telnet-based boards sometimes, I just tried lmorchard's Decafbad and did some turns in LORD, and I'll check back on that; I don't think he has Trade Wars, which was my game of choice, and the source of my old nickname Kamikaze. I've tinkered with reviving The Dungeon on MysticBBS and that may work out, but hosting's difficult. A better thing might be to make a web-based BBS, which is pretty trivial, but then it's not really a "board" anymore, you know?

So I watched the BBS Documentary again, it's been… 14 years?

The early days part of this, the culture of sharing and flame-warring, ah, the good old days. I had very little contact with/interest in FIDOnet and their horrible internal politics, I was on WWIVnet and Cit-net, both of which were much more chill. I loathed then and still loathe the cracker/h4xx0r parasites, totally useless wastes of skin. The ANSI art scene kiddies were wankers, but at least they made something. My bias then as now: I program, and I write, and those are what I respected back most.

But I find I'm still angry about SEA vs PKWare. SEA released public domain ARC software with source but no spec for the format, and then sued Phil Katz for using that source to make a better product, and later to make ZIP with a shared format everyone could use… Thom's sad he got some hate mail in among his giant corporate paychecks, oh no. Phil was so fucked up by it he drank himself to death. Fuck you, Thom, there is no justice in the world that you're alive and Phil's not.