My little rat Anna

We were in a Petco buying mealworms for our pet lizards when I saw a young rat in a box that said “Free”. She was free because she’d lost half her tail in an accident, and she was a mess, but she was so inquisitive and friendly that I had to take her home. I’d had a couple rats years before, but I didn’t really expect much: in hindsight I think my old rats were unusually dumb.

Anna in her younger years

A young Anna, about a year old

Anyway, Anna was a much more enthusiastic learner than my old rats. She learned to come to her name (though she would only bother when she was hungry for treats). She learned to open ziplocks full of treats when we weren’t looking. She liked to run around the floor of the living room, and when she was tired of exploring, I trained her — or maybe she trained me — that if she climbed up my chair and rested on my shoulder, I would take her home and give her a treat.

But Anna didn’t have a lot of luck with her health. In fact, she’s like the unluckiest rat of all time:

  • Lost her tail,
  • Was allergic to most beddings, giving her itchy skin,
  • Got hay fever every year, emitting little ratty sneezes,
  • Had poor eyesight and had to weave back and forth to see anything,
  • Developed an ingrown tooth that required major rat surgery,
  • Got an infection after the surgery that gave her a stroke,
  • Developed more tooth problems, requiring dental work every six weeks

But despite it all, she was still the same friendly, inquisitive, and determined little pet. “Not an ounce of self-pity” on her, as Mary Oliver would say. Over the years, we’ve acquired three more rats to keep her company (rats need friends), but our vet told us to keep her separated from them: he was worried they would start picking on her. That was never necessary — she was always bitchy enough to hold her own.

The last time she visited the vet for her regular tooth-fixing, she looked like a nightmare creature: thin, patchy fur, scarred nose, and freaky movements due to the stroke. But she just kept on going. The vet remarked that apparently she was immortal, and I have to admit that I suspected she would live another year or so, because she just wouldn’t give up.

But the other day she started having bouts where she could barely breathe. This terrified her — she would run all around trying to get more air, clearly confused, causing her heart rate to accelerate, which gave her even more trouble breathing. She went on antibiotics and seemed to be getting better… until she wasn’t.

At the end, when she was freaking out, she would climb up onto my shoulder and collapse there, waiting for me to help her. It was heartbreaking.

It was 2am when we took her to an emergency veterinarian to be put down, and I was crying freely as I held my little gasping rat. Apparently this freaked the receptionist out, because grown men aren’t supposed to cry about rodents. I can’t say I’m embarrassed about crying though. She was a good pet and I’ll miss her.

As for the other rats, two of them are completely oblivious, but her friend Margarat has become sullen and depressed by Anna’s absence, and will need a few days to get back to normal. You and me both, Margarat.

Road Trip: Georgia Here I Come!

So, yesterday, after showering and leaving my hotel room just in the nick of time (before noon check-out, that is), I decided to explore Tallahassee. There were two stops on my list: a museum with good web recommendations and a historic home tour. My handy iPhone told me these things were 10 minutes away “with traffic”. This blatant lie is when I began to distrust my pocket copilot. Perhaps 10 minutes “with traffic and suave expertise navigating downtown Tallahassee” would have worked. Tallahassee’s downtown was very busy, and to make things more interesting, they were driving a parade of light-poles of some sort through downtown all afternoon. Up and back, with police blocking off angry streams of angry cars. I finally managed to park for the museum (not ten minutes later… more like 40). Then I turned around and left, because the entire museum was infested with screaming kids from an elementary school. Of course, I should have realized! It’s time for lame school field trips!

I left the parking garage not 15 minutes after parking, but the attendant insisted I had to pay $2. I pointed to the wall where it said the first 30 minutes were free, but she said that was a falsehood. She called the wall a liar. I gave her $2.

I stopped for gas, where a woman tried to tell me about the Lord. I told her I was not interested in the Lord and she turned away. Then she turned back and said, “But I see your ring finger. You need this!” and she handed me a pamphlet about how to be happy in marriage. I decided that was probably entertaining, and I took it, and she left me alone.

I never read it, however, because when I got a look at the front cover, I realized what their trick was.

Enjoy Family Life With a Parrot

The pictured family used a parrot in order to be happy. Well, duh, of course you can be happy with a parrot! I’ve told Sandra that many times. But Sandra has expressly forbid me from getting a parrot due to their incredible neediness, extreme screaming, and ability to outlive their owners. So this pamphlet was useless to me.

Then I tried to park for this historic house, also downtown. It was 5 minutes away “with traffic”. After 30 minutes of attempting to park, I gave up and said, “Fuck you, Tallahassee!” and drove away.

I had not exactly planned where to go but I figured going North would work. There is a compass built into the rearview mirror of my car, so I used that to tell which ways were North. I figured that if I got lost, I could use the iPhone to get unlost.

Truth be told, I did this because when I asked the iPhone how to get to Atlanta, it provided me with a list of some 23 instructions, which looked really complex and crazy. “Can’t I just take a major highway?” I asked the phone. It said no. So I decided I’d just drive north until I reached a major highway.

“Just driving north” is not an efficient way to get to anywhere, it turns out. I averaged 60 mph, though, and I know that because I used the awesome cruise control in the rental car. My rental car is a lot of fun; it has a lot of gadgets. I ran out of mix CDs at about this point and switched to the car’s Sirius radio. This is when I discovered that all the presets were for country music, which I do not enjoy, and that changing the presets was confusing and difficult. But eventually I got the hang of it and began listening to craptacular comedians for the next umpteen hours.

Sandra hates comedians, because they are not funny. It is hard to argue with this logic. But I like comedians because they are talking, and that engages a portion of my brain that lets me not fret. So I can listen to a comedian and zone out, or listen to a comedian and think about my book’s plot, or whatever. It is very useful. It would be better if the comedians were funnier, but beggars can’t be choosers. Sometimes they were funny though.

I drove through many cotton fields, and I took pictures but they didn’t come out to anything so I can’t post them here. It was at this point that I realized the central flaw in my brilliant plan, and people with more common sense than me have seen this coming: once I was well and truly lost in the backwoods of Georgia, I could not use my iPhone to become un-lost, because there was no phone signal of any sort. AT&T does not cover Nowhereville, GA, it turns out. I was lost, in the dark, on a two-lane highway somewhere in Georgia.

This went on for a long time, with me always going North whenever the option presented itself. I finally came out in some small town and was able to find a toilet (by the way, McDonald’s toilets have really gone downhill apparently… for this road trip I’ve been resorting to Burger King toilets. I think of BK as having the better food but nasty toilets, but so far they’ve beaten the crap out of McDonald’s toilets. No pun intended, I guess.)

I then asked my iPhone where a good place in Georgia was, and it said Savannah, GA. So I asked it to plot me a course. It came up with a list of like 600 steps, plotting through secret byways, underground tunnels, poorly-maintained dirt roads, down a well, into a tree house, everything. I begged it to let me use a regular route, but it said that if I wanted a regular route, maybe I should grow a sense of direction. That shut me up.

I proceeded to follow the crazy course the phone gave me, averaging about 40 mph for several hours, which really sucked. Then I hit I-75 and it was moderate fastness time! About 120 miles out of Savannah, I stopped for dinner at a Subway. I asked my iPhone what the weather was like in Savannah, just, you know, to make conversation. It said that it was going to rain like Noah times. Great. Just great.

So I decided to go the other way on I-75, until I reached the first sizable town. That turned out to be Macon, GA. I pulled into a nice-looking hotel that was really cheap, and I slept.

Need New Server Names

We’re setting up new servers and want to run with “incompetent sidekicks from old cartoons” theme. That gives us “Snarf” from ThunderCats and “Orko” from He-Man. Are there more classic whiny/unhelpful sidekicks that I’ve forgotten?

Reminiscing about Early Programming: OOP and Bits

When I was a high school kid in the late 80s and early 90s, OOP was new. It wasn’t taught in the programming class curriculum yet. (I was lucky to have programming classes at my high school at all, actually.)

Turbo Pascal 5.5 came with a thin 100-page book explaining OOP concepts. It was our de facto textbook on the topic. After reading it, Mike Kujawa and I had long arguments about the utility of OOP. It was easy to prove that you could code any OOP program without using OOP, and it seemed that the resulting program would always be smaller. The notion of polymorphism was neat, but you could fake that with pointers. It was hard to see the benefits of Objects right away, because of our intense awareness of the machine’s RAM.

The biggest problem with Objects was that they required you to add a pointer to every single object that you allocated. When you have 640k of RAM for the entire computer, those extra bytes add up, and you’re always conscious of exactly how big everything is. By writing your own pseudo-OOP, you could get the code tighter and more compact. If this sounds like the difference between C and C++, it pretty much is the exact same thing. 

Although the specific Turbo Pascal implementation of OOP was of debatable usefulness at the time, I have always kept that little 100-page book about OOP. Understanding the OOP concepts helped me understand code architecting, which I dearly loved, and practiced constantly throughout high school.

Although I had many things to architect, the most common project was the BBS program Mike and I were writing. It was going to run my personal BBS, replacing the crappy software I was already using. To this end, I filled dozens of spiral-bound notebooks with architecture diagrams. I used every notebook I had just for architecting and system design. It was no wonder I failed most classes, I suppose.

I found one of those old notebooks… most of them were thrown away, but one survived. It’s junk, but it struck me that this is essentially creative writing, the way I would take a concept, abstract it, then refine it over and over until it was elegant.

Because of the RAM restrictions, “elegant” usually meant “uses impressively small amounts of RAM”. Bit-packing is an inherently pleasurable sensation (at least for me). Seeing a complex concept expressed as a few bytes is like reading a tiny poem.

I don’t have need to bit-pack things much these days. I write less poetry, more prose.

Pac Man CE Strategies and Advice

I was really good at Pac Man CE, but then I took a year off. When I was playing it before, I could hit about 375,000 points. At the time, this was really good, and my score regularly got me onto the weekly leaderboards and in the top 150 overall. But times change, and I didn’t stick with it. Now, it looks like 600k is the top. Holy crap!

So I spent the afternoon trying to get my Pac Man chops back. Of course I visited Youtube, where you can see some masters doing their thing. This is incredibly helpful. But I was surprised and sad that there aren’t more people talking about the game. Sure, it’s been out a while now, but obviously people are still playing it, and getting really high scores now, so what gives? Well, let me help remedy the situation.

Find a pattern for your first 45 seconds. There are several patterns you can find at the beginning of the game — patterns of movement that will net you a whole bunch of ghosts reliably. Don’t try to memorize somebody else’s pattern; it’ll be a LOT more useful if you find one yourself. It’s not too hard: just practice chaining the power pellets together without letting them run out. When you can eat at least six power pellets without interruption, then start practicing moving in such a way that you also grab a bunch of ghosts while you do it. You’ll know you’re on the right track when your pattern earns you at least 50,000 points in the first 45 seconds!

Dying Is Not a Scaleable Strategy. When I went googling for strategy tips, I found some very old advice that suggests you kill yourself at strategic moments in order to eat more ghosts. This is good advice early on: use it when you get to the “key” levels, where you have six power pellets on screen all near the ghost house. That will help you get over the 250k hump quickly. But if you want to get really high scores, you can’t afford to die: you lose precious seconds, plus your pellet score multiplier, plus part of your speed boost. It doesn’t pay off. So you’ll need to start practicing getting the ghosts to come to you without getting killed. It’ll take some time, and it’s a lot less reliable than killing yourself, but it’s a necessary thing to learn.

You Don’t Have Time To Parlay With Ghosts. Avoiding death is really important, but you have to go even further: you have to avoid spending a lot of time avoiding ghosts, too! If ghosts corral you and force you to evade for ten seconds, you’re not a whole lot better off than if they had just killed you. You lost the most precious commodity: time.

This is why you shouldn’t try to eat ghosts with every power pellet. Instead, use most power pellets as a way to safely and quickly clear out big chunks of the board without being hampered by ghosts.

By the same token, don’t go out of your way to eat ghosts, unless you’re going to be able to eat a LOT of ghosts (at least eight, preferably 16). It’s satisfying to chomp the buggers, but they are just distracting you from getting to the higher levels of the game where things move faster and getting a high score is easier. Remember that the goal of the first several minutes is to get to the Key level as fast as you can with as few deaths as possible.

Use Extra Mode 1 To Practice High Speed Movement. When I came back to the game I found that my ability to control Pac Man at very high speeds was gone. I needed a way to practice high-speed movement, without waiting for the regular game to speed up. Extra Mode 1 to the rescue! This mode will also train you to watch the whole board for ghosts coming in from the sides. Two very useful skills in one!

I’m headed back to practice some more. I hope that helps someone!

“Evasive Maneuvers!”

Every sci fi TV show eventually has people yelling this phrase. I was just watching some Stargate SG1 episodes where this phrase was especially unhelpful.

But it’s always unhelpful: they’re trillion-ton battleships in space. They’re being attacked by laser beams that were precision-aimed via computer. So how about moving on a slightly different course than you were before? Is that gonna stop the energy beams and light-speed missiles from hitting? No? Weird!

Have you ever seen someone yell “Evasive Maneuvers!” and then “Woo! Thank god that worked!” No. It’s always “Evasive Maneuvers!” and then the whole set shakes because some indeterminate area of the ship blew off. Why doesn’t that guy do something useful instead of micro-managing the pilot?

The secret is that this phrase doesn’t mean what you think it does. In the far future, people don’t say “fuck”. Really! Nobody ever says this on TV. What they say instead is “Evasive Maneuvers!” This is high-fallutin’ captain speak for “fuck”.

Try it out in your daily life. I think you’ll find it works exceptionally well. Stuck in traffic? Some driver cut you off? “Ahh! Evasive Maneuvers!”

Off-topic: Gilgamesh

I’ve been reading Stephen Mitchell’s translation of Gilgamesh for maybe a month. Well, it’s actually pretty short, and I read it all the night I got it, but I left it on my nightstand near my bed and I keep popping it open and reading snippets. It’s pretty good.

But it’s good by modern standards. It’s freaky that the oldest story we have, the epic of Gilgamesh, is as complex as it is. It has all the regular mythical beast slayings and chest beating, plus a nice big helping of homo-eroticism, but the latter half of the book is not something you’d see in any regular myth.

When Gilgamesh’s soulmate Enkidu dies, Gilgamesh, a super hero who is “two-thirds divine and one third mortal”, suddenly realizes he isn’t going to live forever either. He can’t defeat death the way he’s defeated monsters… he is not immortal.

It terrifies him and wrecks him. He becomes a pale shadow of himself and leaves his castle (for he is the king of the greatest city in the world) so that he can wander the world in search of a way to avoid death. 

Eventually, after much effort, he finds the one man whom the gods made immortal, a man named Utnapishtim. He tracks him down in the lands of the gods and learns his story. It turns out that Utnapishtim is the pre-historic version of Noah — that is, his story will be retold as the Noah’s Ark tale in the bible, much later. Utnapishtim was made immortal after the gods realized how foolish it was to have tried to kill off all humanity. This road to immortality isn’t going to help Gilgamesh.

After he explains all he did in order to earn immortality, Utnapishtim says, “Now then, Gilgamesh, who will assemble the gods for your sake? Who will convince them to grant you the eternal life that you seek? How would they know that you deserve it?” So Gilgamesh attempts to prove that he is deserving of immortality, but cannot. He cannot even pass the first test, to stay awake for seven days. He’s so tired that he can’t stay awake for 15 minutes.

When he realizes he’s already failed the test, Gilgamesh cries, “What shall I do, where shall I go now? Death has caught me, it lurks in my bedroom, and everywhere I look, everywhere I turn, there is only death.” But Utnapishtim is not sympathetic. All men (besides him) must die. And so Gilgamesh returns home a broken and ruined man. He is left to rule his kingdom the best he can and make his city the most glorious place possible, until he inevitably dies. The end.

It’s a nuanced and rather complex tale, especially compared to tales that I’ve read from later periods. In Norse myths, for instance, death isn’t so big a deal. But even though Gilgamesh’s world has many gods, the land of the dead is an unhappy, miserable place where people “squat in the darkness, dirt is their food, their drink is clay, they are dressed in feathered garments like birds, they never see light, and on door and bolt the dust lies thick.” Not exactly Valhalla.

To me the most touching scenes are the ones where Gilgamesh tries to come to terms with his friend’s death. “For six days I would not let him be buried, thinking, ‘If my grief is violent enough, perhaps he will come back to life again.’ For six days and seven nights I mourned him, until a maggot fell out of his nose. Then I was frightened. I was terrified of death…”

This is in the same story where Gilgamesh rebuffs and then beats up a goddess, kills a horrific monster, and sleeps with everything that has legs. It’s… really odd. And really unsettling, like a good story should be. You can probably have your library deliver it right to your doorstep for free, so why don’t you google your library and get that set up right now?

PS – if anybody has any more info about the “roller bird” referenced in the myth (one of the many doomed lovers of the goddess Ishtar), please let me know. From what I can tell, the roller bird’s myth is completely lost, which is sad.

AS3 Literal Syntax for XML

ActionScript 3 has all sorts of cool things. One of them is support for “E4X”, which is “ECMAScript for XML”. In other words, it’s got built-in XML primitives. Poorly documented primitives.

One of these primitives is the ability to insert literal XML code right in your app, and have it magically compile into XML objects at runtime. This has lots of handy uses. I’m using XML as a simple communication protocol between two apps, so I don’t need to load XML files… I just want to send small blobs of prefabricated XML back and forth. But of course I don’t want it to be entirely prefabricated… I want to insert variables and such into it. In my case, I wanted to have a prefabricated blob that also had dynamically-generated children.

Insert Dynamic Values Into Nodes: If you look in the help for this, you are directed to the friggin’ E4X specification, in PDF format! There is no documentation other than that. If you google around, you can find that embedding stuff in curly braces {} lets you insert literal symbols. This blob will insert the literal value of “foo” into the XML nodes stored in “cmd”:

var cmd:XML =<cmd><id>{foo}</id></cmd>;

Great! So far, so good. But now, I want to embed several CHILDREN in there, not just the literal value of one node. How do I do it? I tried setting “foo” to a string like “<child>5</child><child>6</child>” etc., but the <> symbols in my string were helpfully turned into &lt and &gt so it was still just the textual value of a single node.

Insert Dynamic NODES into your static structure: So how do you do this? I can’t find a way to magically do this directly in the literal XML. Instead, I left the dynamic part of the data out of the literal, and after it was constructed, I tacked the missing parts into the XML structure. To dynamically create nodes, you can explicitly construct an XML object with a string of text, and it will make that into XML node thingies. Then you can use the += operator to insert those nodes into your literal XML. Let me show you an actual small code snippet:

 

public function sendCmdSetDeckList(deckIdx:uint, ids:Array):void {
    var idxml:String = “<abilities>”;
    for (var loop:int = 0; loop < ids.length; ++loop) {
        idxml += “<ability><id>” + ids[loop].toString() + “</id></ability>”;
    }
    idxml += “</abilities>”;

    var msg:XML =<cmd>
                               <id>{ID_SEND_SETDECKLIST}</id>
                               <deckIdx>{deckIdx}</deckIdx>
                          </cmd>;
    msg.cmd += new XML(idxml);
    send(msg); // casts “msg” into a String and sends it out on a network socket
}

In this bit of code, I create a string of dynamic XML and stick it in the variable “idxml”. Then I create some static XML in “msg”, and then tack my literal XML code into msg, under the “cmd” tag, which is the top-level tag. After that, the “msg” xml structure has a node named <ability>, which has all of my ability IDs in it.
 
Note that the literal string must be “valid” xml, which means it must have only a single top-level node. Thus, I had to put all the <ability> nodes inside an <abilities> tag. If I didn’t do this, I would get a runtime error when I try to stick the string into a new XML object later in the function.
 
Forgive the mediocre example but I wanted to throw something up about this before I forgot about it (but I can’t spare too much time right this second). It’s very frustrating that there’s so little documentation for this. This reference was pretty useful, as far as it goes.

A neat trick in Windows XP

If you’re a developer, try going into the Sounds control panel and assigning sound effects to “Open Program” and “Close Program” events. These actually fire whenever a process starts or stops. It can be very informative. You’ll hear a cacophany of noise when you boot up, but more than that, you can watch various programs doing sneaky things. For instance, if you’re playing WoW with these set, you’ll hear the open/close sounds go off every time you alt-tab away from the game. It’s WoW’s anti-cheat software going off.

You’ll also hear this go off when a screen saver starts or ends, or when a program decides to check for updates, or many other times. It’s pretty interesting.

My little black programming book

I admit it. It came from watching the cheesy TV show “Supernatural.” They have a tattered old notebook and it always has just the right clues needed to solve whatever problem. It’s awesome and I want one.

When I was a teenager I made one, actually. I spent hundreds of hours in classes. I still have it. Every 386 assembly opcode, all the VT102 terminal emulator codes, Pascal references, the works. However, unlike the book in Supernatural, my original programming book is never, ever useful. I have never needed to refer to it in at least 15 years. Programming stuff goes obsolete a lot faster than notes about demons, apparently.

So I made a new one. I found an old leather-bound 3-ring binder my dad used to use before he retired. It has that “hand me down” sort of feel. And I started making my programming book. I create the pages in Word and then print them out and hole-punch them. There’s stuff on PHP, SQL, the C++ STL, a cheatsheet on CSS, and so on. I do actually refer to it occasionally. It sits right here so sometimes it’s faster to find a needed diagram than to look it up on Google.

It isn’t sexy enough, though. It doesn’t have that “here is all my knowledge” sort of feel. So I bought a pencil and paper notebook at the store, with a nice cover and stuff. And I started writing in the stuff by hand. But I got two pages in and realized how stupid that was. So now I have a vaguely unsatisfying Programming Notebook that isn’t quite cool enough. And a mostly-empty journal book with just two pages written on it.

I could go into ghost hunting…