-
Porting UNIX Programs to Mac OS X
This is a short list of problems that I frequently encountered when porting applications to Mac OS X. As any veteran Linux hacker will predict, most of them involve libtool :-)
libtool problems
- Can’t dlopen/dlsym a file properly? Make sure that you have
-module
parameter in the plugin’splugin_LDFLAGS
entry in itsMakefile.am
. - libtool doesn’t write the proper information to its
.la
files if you compile a library as--enable-static --disable-shared
. You’ll have to edit the .la file and change thelibrary_names
parameter there to belibname.a
.
C++ problems
- g++’s support for templates is pretty good now, but if you’re having problems, have a look at GCC’s documentation on templates. In particular, note the
-frepo
flag: using that solved a few template problems for me.
- Can’t dlopen/dlsym a file properly? Make sure that you have
-
ABC CMWeb Installation Overview
S. Pfeiffer, C. Parker, A. Pang, “ABC CMWeb Installation Overview”, Technical Report, CSIRO Mathematical and Information Sciences No. 03/177, September 2003.
-
Playing iTunes's M4A files in XMMS on Debian GNU/Linux
This took way too much futzing around to get working (or perhaps I’m just too used to Mac OS X now), so here’s a no-frills guide to get it working:
- Add the lines
deb http://marillat.free.fr/ unstable main
and
deb http://pessoal.onda.com.br/rjamorim/debian/ ./
to your/etc/apt/sources.list
file. apt-get update; apt-get install libfaad2-dev
apt-get -t unstable install libstdc++5
- If you’re on x86, download the i386 .deb of my patched version of Frederic Fondriest’s xmms-mp4plugin XMMS input plugin.
- If you’re exotic enough to not have an x86, download the debian source, and run
fakeroot debian/rules binary
to build the .deb for you. You need the g++-3.3 and automake1.7 packages installed to compile this thing. - Execute
sudo dpkg -i xmms-mp4plugin_0.2-1.andrep_*.deb
to install the package. - Run XMMS and enjoy.
Useful links:
- http://rarewares.hydrogenaudio.org/debian.html: RareWares Debian repository for faad2, faac, aac/mp4, lame, lame-ha, lamip, cue2toc, shntool
- http://www.xmms.org/comments.php?show=P211: Original sources for Frederic Fondriest’s MP4 XMMS input plugin
(Random keywords to be more search-engine friendly: Debian, Linux, XMMS, iTunes, MPEG-4, MP4, AAC, M4A.)
- Add the lines
-
Emacs for Mac OS X
Emacsen
There are a few ‘native’ versions of Emacs for Mac OS X: by ‘native’, I mean they have an Aqua interface, and don’t require an X11 server. Here are the full names of the ones that I know of, so you know what to google for if you’re ever that interested :).
- Emacs on Aqua. Works with Panther, but seems quite unstable.
- Carbon Emacs. Sources and binaries are available on that page, although I don’t know if the binaries available there work with Panther. However, recent binaries (built from the CVS repository) which do work with Panther can also be obtained from Mindlube’s Emacs page. This is the Emacs version I currently use with Panther.
- Enhanced Carbon Emacs. Same as the above, but has a couple more packages, in particular ones which support LaTeX/AucTeX/etc. Binaries only, and the author has now updated Enhanced Carbon Emacs to work with Panther. Recommended.
- Emacs 21 for Mac OS X — Source only. Ovidiu Predescu has put together a binary package of it. Ovidiu’s page also has some nice key bindings you can add to your
~/.emacs
file to get Cmd-X/C/V, Cmd-S, Cmd-L etc. working, if you’re a veteran classic MacOS user. - XEmacs 19.14 for Macintosh (and also XEmacs 21.5.9 for Macintosh, which is considered alpha right now). I haven’t tested to see whether this works with Panther.
I’m fairly sure that all of them are based on GNU Emacs (except the XEmacs port, obviously).
The version I used in Jaguar is Enhanced Carbon Emacs: it’s been very stable and comes with lots of useful packages. Mind you, I haven’t used it that much—I use vim for most of my Unix editing—but Emacs works when I need it. Now Enhanced Carbon Emacs is available for Panther, but I haven’t tried it yet since I don’t use Emacs too often.
When you install any of those Emacs packages, it’ll stick an Emacs application in the
/Applications
directory like any other Mac app. If you’re using it from the terminal a lot, here’s a shell script I wrote which will open the GUI version of Emacs (and leave the console window “frozen” while the GUI is running, just like a normal X11 app):#!/bin/sh if [ -x '/Applications/Emacs.app/Contents/MacOS/Emacs' ]; then exec /Applications/Emacs.app/Contents/MacOS/Emacs "$@" else exec /usr/bin/emacs "$@" fi
Emacs in text fields?
If you haven’t found out by accident yet, you can actually press C-a and C-e inside a text field in Cocoa application to go to the beginning and end of the line. It turns out that key bindings for Cocoa applications are completely customisable, which is just way cool. The default key bindings are in a property list file at
/System/Library/Frameworks/AppKit.framework/Resources/StandardKeyBinding.dict
, and you can override those key bindings with a file in~/Library/KeyBindings/DefaultKeyBinding.dict
. You’ll never look at the humble TextEdit application in the same way again.If you’re an Emacs guy, I highly recommend getting TextExtras , which allows you to do things like pipe the contents of the text field through filters (run your word processing document through
sed -e s/foo/bar/
, sweet), and also adds the can’t-live-without dynamic abbreviation and abbreviations features.See gnufoo’s Mac OS X page for a slightly more in-depth look at how to bind keys to Emacs commands. After that, you can grab my DefaultKeyBinding.dict file, which has things like
M-/
bound to dynamic abbreviation already. -
MochΛ: A Haskell to Objective-C Binding
MochΛ is a Haskell to Objective-C language binding for Mac OS X. Using Mocha, Haskell code can send messages to Objective-C objects, and Objective-C class declarations can be written in Haskell. Haskell API definitions are provided for the entire Mac OS X Cocoa framework, and automated interface generation can be performed for any user-supplied frameworks.
Update: Mocha has been officially discontinued—but never fear, Wolfgang Thaller and I have been working on HOC, which fulfils much of the same goals that Mocha strived for, and furthermore, it’s actually released and working! See the HOC release announcement for more details.
-
Look out mutants!
You are Professor X!
You are a very effective teacher, and you are very
committed to those who learn from you. You put your all into everything you do, to some extent because you fear failure more than anything else. You are always seeking self-improvement, even in areas where there is nothing you can do to improve.Which X-Men character are you most like?
brought to you by Quizilla -
Geek Code
-----BEGIN GEEK CODE BLOCK----- Version: 3.12 GCS/SS d?>! s+: a-->---@ C++(++++) UB++++ UL++++ P+++ L++++ E(-) W++(--) N o-- K w(---) O+++ M++ V PS PE(+) Y+>++ PGP>++ t+ 5 X+ R++(*) tv-- b+>++++ DI++ D+++>$ G(-) e*>++++ h r++ y**>+++++ ------END GEEK CODE BLOCK------
If you’re not e-1337 e-nuff to know what this means, run it through the Geek Code Decoder by Bradley Kuhn. Enjoy!
-
Session 2 Summary
Babylon Campaign Summary for Session 2 (18/3/2003)
by André Pang
The last session ended with our five
valiant heroesmercenaries fighting to earn a place in the Thel’s Warriors, and they greatly impressed Thel and XXX by ripping their opponents to shreds whilst also smelling like minty freshness.Thel Achila congratulated Amber and the party after the fight, and told them more about the Thel’s Warriors. She informed them that wounds suffered by any of the stable’s fighters are tended to by their healer named Papparasmus, a man not particularly known for his social skills, but was nevertheless good at what he does. Thel also mentioned that she was now in retirement because of the “Ankheg incident” —- several of her fighters were gored to death in an unpleasant manner in an ankheg pit during one of the fights. In fact, apart from the Ankheg incident, many of her warriors were dying during the middle of a fight in the veins; they would mysteriously keel over with no signs of warning. In particular, her greatest gladiator, a shambling mound who went by the name “The Golden Shambler”, died in this fashion. Thel wants the party to find out who or what is responsible for killing all her gladiators, and is offering a 1000 gp bounty to solve this puzzle. Thel suspects that a rival stable, the Sandnets, may have something to do with the deaths. Led by Vulpone Sandnet, a hulking minotaur who savagely cuts down almost all opposition, the Sandnets have never been on the best of terms with Thel’s Warriors. However, our heroes’ first intuition was to follow up on the strange minty smell that Torr picked up in the battle to prove themselves to Thel. Thel mentioned that Flug, the arena janitor, uses some cleaning fluid which may have been a bit minty.
After their conversation with Thel, the crew of five descended beneath the gladiatorial arena: the Underveins. The Underveins, featured on a very cool Dragon® map, was home to Papparasmus the healer. Papparasmus was about as pleasant to deal with as everybody suggested: that is, not very. He did do his job though, and healed everybody back up to their optimal health. One thing that our heroes managed to get out of Papparasmus was a name: Tiberius, apparently a master healer and cleric who was responsible for raising the dead.
The heroes then went to visit Thel again; upon asking Thel about Tiberius, Thel became defensive and refused to talk to the heroes about “her father”. Instead, she laid down the rules of gladiatorial combat in the Veins:
- No magical “buffs” before a match; e.g. no Mage Armour, no Protection From Normal Missiles and Other Pointy Things. It’s perfectly okay to cast those spells once you’ve started combat, though.
- There’s a 50gp entrance fee for each fight, and the 1st such fee is paid for by Thel. This fee can also be waived if you’re particularly (in)famous.
- One can take “raise dead insurance”, which costs (50gp + 10 * your fame score). Once you’ve taken the insurance, if you fall in combat, you will be raised for the mere price paid for the insurance.
- If you have no “raise dead insurance”, it costs 200gp to raise you lest you be decapitated, arrowed, sworded, or otherwise burninated (to the countryside).
- Winning a gladiatorial battle nets (50gp + 2 * your fame score). XXX: This doesn’t seem like much, given that the entrance fee takes 50gp out of that. Andrew?
- Good performance in battle and/or good crowd entertainment nets a gladiator more fame.
- A gladiator may appeal to the crowd with either a Charisma check or a skill check (DM determines difficulty), at their choice.
- Inflicting massive damage, such as one would expect from a critical hit from a scythe, increases a gladiator’s fame.
- Performing a Fatality to kill your foe(s) increases your fame.
- Having “spice” in a battle (and presumably winning that battle) increases your fame. “Spice” can be a number of things, such as having an ankheg pit present, a random basilisk peacefully wandering around the arena, or random landmines.
- Doing “cool things” in combat increases your fame, where “cool things” is subject to interpretation by Mr. Dungeon Master.
- To perform a Fatality, a gladiator must kill an opponent with a critical hit, or must kill an opponent with a -6 penalty to their attack roll.
- Once you hit 0 hitpoints in the arena, you’re gone. Dead. Burninated.
Armed with this valuable information, our astute heroes then took a one week break, with 45gp spending money courtesy of Thel, to prepare themselves before their first battle. The group separated for the week, and each mercenary had their own story to tell.
Kane and Arjanne were visited by the PsiCore: darkly-dressed people with scary-looking hoods. Fascinatingly, neither of the two could tell whether the PsiCore members were actually male or female. In fact, the PsiCore look quite … inhuman. They were taken to some sort of temple where they met the PsiCore leader, another average-looking PsiCore members who told the two psions to “side with them when the time comes”. After agreeing because they didn’t see much choice (being surrounded by about 50 PsiCore members at the time), they were escorted out of the temple and were immediately met in by other mysterious men, dressed in white, claiming to be part of a group called the “Freeminders”. The Freeminders, like the PsiCore tempted the two champions to join their side when the time came, and also said that the PsiCore were “corrupters”. Of course, since they were wearing white, Arjanne and Kane dismissed them as being pansies.
Mind flayersThe PsiCore are obviously much more fun to be allies with.Amber couldn’t sleep for the week. Her sleep was being haunted with nightmares of ghosts, who kept telling her to “open the door”. When confused little Amber asked what-the-hell-door they were talking about, the “Earthbound” ghosts simply stated “There is only one door. Don’t you understand?” Obviously, Amber didn’t —- at least, not for now …
Our favourite drunken monk, Grasshopper, decided to talk to Rifius, the little boy with the large golden belt. Rifius ran an errand for Grasshopper and managed to get a jar of the cleaning fluid that Flug used to clean the arena; unfortunately, Grasshopper’s keen sense of vapours didn’t detect any minty freshness in the fluid. Grasshopper also met another girl in Thel’s Warriors named Stiletto, who at the moment seemed to be
what meta-gamers call a “standard NPC”, but will no doubt turn out to be significant later on in the campaigna nice young lass. Grasshopper gained a fame point from saying Hi to the ladies, and also learnt that the commons hold a “Blood Bowl League” —- this week’s game was between Super Nashwan (of Xenon II fame) and Brutal Deluxe (of Speedball II fame), and it was looking like a good one. Bets are welcome!Torr met a fellow named Mountain Musso who had some kind of “angry potion”, fought him in a wrestling match for it, and promptly lost. Stupid Torr.
After the one-week break taken by the heroes, they were approached by none other than Tiberius Achila. He looked like a very streetwise old man, and claimed that Thel was a criminal, and “stolen from Nathaniel” (whatever that means). Tiberius also warned the heroes that he’d be coming to take half of their arena winnings, and if the heroes refused, they’d be in for all sorts of trouble.
The leaderless heroes now needed a leader for their combat group, named “The Jackson Bitches” (with a 3-2 majority vote, thank you, drive through). In order to determine who would be their fearless leader, they diplomatically beat each other senseless until one was left standing. Of course, the Cleric won that fight (thanks in no small part to a small glowing celestial doggy); Amber now leads Torr, Grasshopper, Kane and Arjanne in their search for monsters to kill and stuff to take. Each of the heroes earned 200 XP in the gladiatorial challenge.
At this stage, the heroes relaxed for one more day before their first fight. In the day, they could visit the markets to buy some new equipment, or speak to Thel, Papparasmus or Flug about their investigation. At the end of the day, the heroes could then go to the Bloodbowl match to watch lots of humies beat the living crap out of each other. Hooray!
Most of the heroes decided to go to the markets, except for The Monk (XXX: is this correct?) Grasshopper talked to Thel and told her that the cleaning fluid wasn’t minty. Thel basically said “ahuh” in response to this. Upon asking Thel about her father Tiberius, Thel claimed that Tiberius and her were no longer blood relatives.
At the Bloodbowl stadium, our heroes learnt that the Orcland Raiders won last year, and in this match, the odds were 3 to 1 for Super Nashwan vs Brutal Deluxe. Brutal Deluxe ended up winning (XXX: is this right?); as a result, Kane lost 7gp, Arjanne lost 10gp, Amber won 12gp, Torr lost 10gp (stupid Torr), and Grasshopper lost 66.6666 silver pieces.
At this stage, life was suspended in the Babylon universe, and mundane daily life returned.
-
Character Sheets
Here are some character record sheets for use with the Babylon campaign:
- AndrÈ’s character sheet in Excel or Acrobat/PDF format.
-
Fixing Corrupted Modules
Introduction
One of the very irritating downsides to the Aurora Toolkit is that it has a nasty habit of corrupting modules:
Uh oh.
Virtually none of us have the discipline to keep backups of the last 10 saves of the module in case the latest one becomes corrupted, which means that we can lose hours of work. (Some unfortunates have probably lost hundreds of hours of work thanks to these corruption bugs.)
There was a “sticky” thread on the BioWare boards about how to recover these corrupted modules, which involved messing around with the temporary directories that the Toolset creates, but that was a bit too hacky for my liking. So here’s another method to recover them.
Recovering Corrupted Modules with NWNViewer and NWNPacker
You’ll need Zoligato’s NWNViewer, an invaluable program for NWN hackers. The NWNViewer application actually has the NWNPacker program inside it, so there’s no separate download for NWNPacker.
Here’s the procedure:
- Use the “File menu -> MOD HAK ERF Open” command to open your corrupted module
- Right-click on any name inside the “File List” pane (the left-hand-side of the NWNViewer application) and pick “Extract ALL” from the context menu
- Extract all files to a Directory Of Your Choice
- Start NWNPacker by going to the “File menu -> NWN Packer”
Here’s the fun bit: the “File” menu is completely irrelevant to the NWNPacker application. Everything in NWNPacker is controlled by the icons in the NWNPacker window. So …
- Click on the “New Document” icon (the piece of paper with the folded corner) inside the NWNPacker window, and select the “New MOD” menu entry. (You can’t go to “File menu -> New -> New MOD” to create a new MOD file, because there is no “File menu -> New” menu entry!) The directory browser inside the NWNPacker window should now allow you to navigate directories and add files to the left pane.
- Add all the files which you previously extracted to your new module, by dragging them from the file selection window in the bottom-right to the list of files in the module in the bottom-left.
- Use the disk icon in the NWNPacker window to save your new module.
At this point, your module should be openable (is that a word?) in the toolset.
- Open your new module up in the toolset, and delete any invalid resources in it. If you’re lucky, the Toolset won’t give you those fun “invalid pointer” error messages as you’re doing this. Save this new module as your final module, and you should be able to continue work from there.
Optionally:
- If you’re paranoid (like moi), you may want to then open up your final module and repeat the process with NWNViewer/NWNPacker, to make 100% sure that the module file is packed properly.
I’d add screenshots to this to make it more understandable, but hey, I’m lazy. If you care enough about recovering your corrupted module to email me about it but can’t understand this procedure, email me so I can put up some screenshots for you.
Possible Explanations for Corruption
If you try to open up your corrupted module in NWNPacker (instead of NWNViewer), it will complain about insufficient memory. My intuitive guess is that one of the length fields for the resources inside the module is wrong, which would also explain the invalid pointer operations performed by the toolkit.
NWNViewer appears to be more robust than NWNPacker and the toolkit, and seems to deal with such corruption better.
Have the appropriate amount of fun.
-
Barkskin VFX Removal
The Barkskin, Stoneskin and Greater Stoneskin spells are all great, except that they make your character look like a brown or stone-like object. I dunno about you, but I prefer staring at a character which doesn’t look like a tree.
So, I modified the “skin” spells to use the visual effect used by the “Premonition” spell. The actual spell effects don’t change, of course, just the visual effect that appears on your character.
Download:
Extract this file to the directory where you installed Neverwinter Nights, and you should end up with a few new files in your
override
directory. Have fun oogling at your character.Note: This is for NWN HoTU 1.61. Untested on other versions.
-
Subraces and ECLs
Neverwinter Nights has all the standard 3E races: Humans, Dwarves, Elves, Half-Elves, Gnomes, Halflings, and Half-Orcs. (I do wonder who at WoTC decided that half-orcs should be a core race; whether this is a good or bad thing is left as an exercise to the reader.)
However, NWN doesn’t implement any of the additional races found in the Forgotten Realms sourcebook, which you might’ve expected, since Icewind Dale (II) does. In case you have no idea what I’m talking about, the Forgotten Realms sourcebook adds quite a number of player character (PC) races, including Sun Elves, Gold Dwarves, Tieflings, Genasi, and the infamous Drow.
So, here’s to extending NWN to support those new races.
Download
(n.b. These files aren’t really meant for public consumption yet. Do. Not. Expect. Them. To. Work!)
Grab the above file and unzip it to your modules directory. This module allows you to pick a non-standard race.
Unzip all the files in the ECLs.zip archive to your override directory. This will implement proper ECL support.
-
Neverwinter Nights First Impressions
The one-word summary? Wow.
I’ve read many reviews on this game, and I was in slight disbelief as review after review refused to rate this game at any less than 90%. Now that I’ve got my hands on it though, I know why.
Keep in mind that this is a first impression. It’s not an extensive review, and no doubt my opinion of the game will go down as I encounter bugs, or realise that the single-player plot is about as boring as Baldur’s Gate. However, BioWare looks like they really have done what no other company has ever done before: taken the D&D concepts (not just the rules), and faithfully implemented them as a computer RPG.
They got 3E right
For hardcore D&D players, NWN is everything that you’ve been waiting for in a computerised version of D&D. It’s not perfect, but it’s so good that you just won’t care about the insignificant shortcomings.
Part of the reason that it’s so good is simply because it’s the very first game to use the 3E mechanics: it’s the same D&D that we know and love (or hate), and it’s a huge improvement over the 2nd edition rules that previous D&D games used. Yes, you can multi-class in this. Yes, every feat that’s in the Player’s Handbook is in the game, and they’re all implemented perfectly.
Sure, some bits were changed around to suit the nature of CRPGs better; for instance, the Rogue’s “Disable Device” skill has been split up into “Disable Trap” and “Set Trap”. But those changes are small, and they’re Done Right.
But really, for all intents and purposes, this game is 3rd edition Dungeons & Dragons. Perhaps this won’t dawn on you until you see all the skills and feats that you can choose at your character generation, but this in itself makes the game worthy of buying. The amount of attention paid by Bioware to implementing every single last detail in 3E is truly staggering; if they got nothing else right about this game, I wouldn’t care. The 3E implementation is just so good that any hardcore D&D fan would be impressed with it. (Hey, if Ryan Dancey’s happy with it, it has to be That Good).
So what didn’t they quite get right with the 3E rules? It’s not extensible enough. You can’t add new feats, for instance. If you want to create a new weapon model, you’re going to need 3DSmax. But before you sneer, the Aurora engine which Neverwinter Nights uses is extensible enough that you can simulate everything that you’d ever want in a computer RPG just by using various types of items.
And on that note, let’s talk a bit about the Aurora toolkit.
The Aurora Toolkit
Forget everything you know about level editors, map editors, and anything else related to modding games. The Aurora thing is so usable and so friendly that it makes creating basic modules fun, and not a chore.
There’s a little bit to learn, but considering the worlds that you can craft with this thing, there’s very little to learn. Put it this way: the section on the toolkit in the manual is less than 20 pages long. The toolkit’s interface is so good that it just makes creating modules trivial.
For instance, take the conversation editor. You can add new dialogues for NPCs by using this tool. You click the ‘Add’ button and type in “Greetings! What’s two plus two?”; the toolkit automatically tags that message as being spoken by the NPC. You click ‘Add’ again and type in “1” as a possible response, and the toolkit immediately tags that as being spoken by the player’s character.
If you want to add more things that the player character can say, just click on the “Greetings” message, click ‘Add’ again, and type in “2”. This can send the player down a completely new conversation path, which implies that it might be complex to handle. Not at all; the conversation’s represented as a simple tree, which makes it trivial to insert new conversation items.
As I said before, the core engine doesn’t let you expand feats or races. Is that a big oversight? No. You can simulate almost of these things by using items which grant the characters whatever abilities you wish.
For example, I was disappointed that I couldn’t play an Aasimar, one of the standard Forgotten Realms races. So, using the half-elf template, you can give the character an invisible, intangible item called a “skin” which grants her those Aasimar qualities. Change your subrace name to “Aasimar”, and bingo, you’re an Aasimar. You just added a new race.
So while the game engine doesn’t allow the extension of some core 3E ideas such as classes and feats, you can do a lot with the toolkit. I imagine that implementing prestige classes and new feat-like things won’t be out of the question at all. Of course, you can create new items, weapons, armour, magical staves, rods and spoons with ease.
So, the toolkit makes doing all the standard things easy. Of course, if you want to do wacky stuff, the Aurora engine is driven by a programming language called NWScript which you can write stuff in. Don’t be mistaken —- this isn’t a play-language. From what I understand, it’s fully OO, and gives you full access to the internals of the game engine.
What’s even better than that is that Bioware realised how powerful NWScript is, and provide you with a script editor right in the toolkit. No more whipping out that sorry-ass excuse for a text editor (notepad.exe) to change things around; all your development tools are in the toolkit. Effectively, it’s a small IDE (integrated development environment): the toolkit can edit scripts, debug them and compile them. This makes things so much more accessible than fooling around with two dozen text files. (Civilisation, anyone?)
If you’re a DM and have never done programming before, well, now’s a good time to learn. The toolkit is so good that you could use it as a basis to build a module that you wanted to play in table-top RPGs. That’s really cool.
The network effect
Now we get into romantic territory. Fasten your seatbelts!
By itself, the flawless implementation of the rules doesn’t mean all that much. By itself, an easy-to-use toolkit doesn’t imply that much. By itself, the DM client, which allows you to dungeon master a module that you’ve created, isn’t a big deal.
However, combine these three things, and the effect is exponential: I kid you not, this thing is a truly viable alternative to tabletop RPGing.
Read that again, just in case it hasn’t hit you yet. NWN could drain away as much of your time as regular D&D does, or perhaps even more. (Although in the case of our current gaming group, draining more time than our D&D sessions isn’t all that hard :).
I’m not saying that it should replace tabletop RPGing, or dethrone it as the RPG method of choice. I’m saying that’s NWN is an alternative to tabletop RPGs; it’s an alternative because it offers a completely different experience to tabletop RPGing.
Computer RPGs vs tabletop RPGs
Let’s get something straight, first: computer RPGs will never be able to compete with tabletop RPGs. They never have, they never will.
However, now that NWN has been released, something has emerged which I thought never happen: computer RPGs now offer something which table-top RPGs don’t, and never will be able to: the feeling of being immersed in a computer game created by friends. The graphics detail in NWN is good enough that just seeing the environment makes for a completely different experience from conventional RPGs; the fact that you will play your DM’s module just like any other computer game also makes for something different.
If you’re a DM, you can prep the entire module before the session starts, watch your players walk through the world, talk to them as you would over a table, and then watch with glee as that pretty NPC they picked up is actually a succubus and teleports them to hell. You get to see all that in vivid graphical detail, in a campaign you wrote, on a computer game that your players are playing, and you’re watching them do this as they’re playing*.
Think about that for a second. Come back and read the rest of this when you’re done.
Thought about it? Good. Now imagine that you can have multiple DMs controlling a session. This is unfeasible in real-life RPGs, but it’s actually recommended for NWN. You can have a DM/PC ratio of 1:1; for every PC, there’s a DM. DMs can control NPCs to say exactly what they want, and the human players on the other end will just think it’s all part of a computer game.
That staggers me.
So, first impressions of NWN? Awesome. If you’re a D&D player, buy this thing. Right freaking now! (And I mean buy, not pirate.) If you’ve got the computer to run it, it will provide you with as much joy as any D&D book does, and at least from my point of view, that’s possibly the highest accolade that I could ever award to a computer game.
-
Chiba
Chiba is a markup language I’m currently working on, which is inspired by many other markup languages, including the syntax used by HTML, SDF, POD, lout, AFT, APT, Wiki, DocBook, and of course, LaTeX. It’s written in Haskell.
It’s nowhere near finished (and don’t hold your breath), but the framework is currently there. Some very simple functions have been written, so it’s currently possible to convert a Chiba DOM to HTML markup.
Here, you can find all the source code for my presentation in the chiba-20020603.tar.gz file, or you can browse the contents of the tarball . The actual presentation can be downloaded in two formats:
-
Hicki
Hicki was the working name for my thesis project, which is a case study of writing a WikiEngine in Haskell, before I decided to change thesis topics.
Here are the slides and handouts which I used in my Thesis Part A presentation (22/10/02), if you’re interested:
- Slides: hicki.ps
- One-page summary in Acrobat or PostScript format.
- A tarball with all the files. You can also browse the directory with all the files; all the original LaTeX files are there too.
-
zsh
What’s zsh?
This is a talk I gave on zsh (the Z shell) at SLUG, the Sydney Linux Users’ Group. You can find more information on this great shell on the zsh homepage, which is at (drumroll) www.zsh.org . Briefly, zsh combines all of the (in)famous interactive power of tcsh and bash’s standard Bourne shell syntax, with its own most utterly crazy and useful word completion, globbing, redirection, and editing features. Once you start using it, everything else seems annoyingly … useless.
You can find a copy of my current zsh configuration files at
My zsh presentation
Feel free to take a peek at the slides that I used for my presentation, in html or MagicPoint format.
Other zsh tutorials and advocacy documents I used for my talk include:
- Paul Falstad and Bas de Bakker’s “An Introduction to the Z shell” (intro.ps). This is also on the zsh homepage.
- The FEATURES document that comes with zsh (taken from 4.0.1prerelease). This is actually a superb quick reference to all of the useful features in the Z shell.
However, you really want to drop by www.zsh.org and see the documentation, FAQs and scripts there.
-
Download CV
You can find the online version of my cirriculum vitae here, if you’re curious: it’s accurate and updated as of February, 2006.
It’s currently available in Adobe Acrobat (PDF) and PostScript (ps) formats; the Acrobat version contains hyperlinks.
- Acrobat version: andrep.pdf
- Postscript version: andrep.ps
-
Vimacs
What is Vimacs?
- Conrad Parker: “Dude, I gotta get you doing some serious hacking projects”
- Erik de Castro Lopo: “Oh, so you’re the insane guy that K was talking about”
- Wichert Akkerman: “Gross. Horror. Vim abuse. Mind if I include this as an example in the Debian vim packages? :)”
Yep, it’s Emacs in Vim:
http://www.algorithm.com.au/vimacs/
-
GHC Runtime Loading
Note: Since I wrote this dynamic loader for Haskell a long time ago, quite a few advancements have been made, so I’m no longer supporting this package. See the end of the page for discussion on the state-of-the-art in Haskell dynamic loading.
Introduction to Dynamic Loading & Plugins
Dynamic Loading is an important feature for building extensible programs and larger applications. It allows the program to load in code contained in a file, at runtime, and execute it. It’s a simple concept, but it leads to applications which can be very easily extended, sometimes in ways the original author never imagined.
If you’re still not convinced of the power of dynamic loading, think of WinAmp (a.k.a. XMMS :), which uses plugins to read files and perform device-specific output (not to mention all of its fantastic visualisation plugins). Each file type (MP3, WAV, OGG, XM, etc) is handled by a separate plugin, which means that it’s incredibly easy to extend WinAmp to play different types of media files.
Other notable projects which extensively use plugins are the Linux kernel (think kernel modules), Emacs, the Windows device driver model, the entire DirectX/gstreamer media framework, and the Apache web server. These projects would not be what they are today without their modular, extensible design.
Plugins in Haskell
The good news is: GHC has had, for quite a while now, the capability to load in Haskell modules at runtime. (If you use GHCI, that’s exactly what it does!) The bad news is: you can’t normally get at the functions which will do this for you. The better news is: thanks to some handiwork, you now can get at the functions which perform runtime (un)loading of modules; you’ll need to download a special RuntimeLoader module which allows you to do this.
To use it,
import RuntimeLoader ... -- Load the plugin file plugin <- loadObject "MyPlugin.so" -- Load the function inside the plugin adder <- loadFunction plugin "addFunction" :: IO (Int -> Int -> Int) -- Execute the function let i = adder 2 3
That’s all you need to do to load a plugin. (Okay, not quite, you have to add a few flags to the ghc commandline too ;-).
If you’re interested, I’ve packaged up a small, example program called “TextFilter” which includes the RuntimeLoader module and demonstrates how to use it. Download it and get hacking!
Sorry, there’s no separate package for just the RuntimeLoader by itself: I think the TextFilter example is small enough that packaging it separately from the RuntimeLoader isn’t worth the hassle for you or me.
RuntimeLoader Redux
Since the release of RuntimeLoader in 2002, a few other people have taken up the challenge to make Haskell a more dynamic language. If you’re interested in this, have a look at:
- HWS-WP, a.k.a “Haskell Web Server With Plugins”. Martin Sjöaut;ren took the original Haskell Web Server written by Simon Marlow many moons ago, and extended it to have Apache-style modules.
- Hampus Ram’s DynamicLoader, which provides a higher-level API than my RuntimeLoader module.
- I worked with Don Stewart, Sean Seefried and Manuel Chakravarty on a paper named Plugging Haskell In, which is complemented by an implementation of a far more complete dynamic framework for Haskell named hs-plugins. Thanks to the incredible work of Crazy Don, hs-plugins has become mature enough to write an interactive Haskell shell in less than 100 lines of code, and even lets you call Haskell functions from C far too easily. Check it out, dude.
-
Implementing Subraces and ECLs
There are two big problems with putting new PC races into NWN: implementing the racial traits, and implementing Effective Character Levels (ECLs). At first glance, it seems that implementing racial traits can’t be too hard (hey, BioWare even provided a custom “subrace” option for your PC!), and ECLs are much harder. Experience has shown, however, that it’s the other way around.
Racial Traits
Each race has a bunch of unique traits; for example, Aasimars have a 2 ability modifier to both Wisdom and Charisma. They can also cast the Light spell once per day, and have a few energy resistances (e.g. 5/- for electrical). How do you implement these?
The method done by all the modules I’ve seen give the character a skin. Skins are normally only given to monsters, but there’s no reason you can give them to a player. Think of a skin as an invisible, intangible item which the player possesses, but can’t access in her inventory (so she can’t drop it or trade it to other players). The skin can then have the properties usually associated with magical items, to simulate the racial traits: e.g. an Aasimar Skin would grant them 2 to Wisdom and Charisma.
However, there is one large problem with this: ability modifications are not part of the character herself. Some things in NWN, such as feat prerequisites, are based solely on the character’s real, permanent ability score, and do not take into account the ability modifier given by the skin. The full list of things which use the character’s unmodified ability scores are:
- Feat prerequisites. e.g. if you have a Str of 12 and a skin which gives you a 2 Str adjustment, you should be able to access the Cleave feat, which requires a minimum of 12 Str. You can’t.
- Spellcaster levels. A Druid or Cleric with 17 Wis and a skin which grants a 2 Wis adjustment will still only be able to access level 7 spells. The same applies for Sorcerers and Bards with the Charisma ability, and for Wizards with Intelligence.
- Intelligence modifier for bonus skills. A character with an Int score of 10 and a skin which grants a 2 Int adjustment should receive 1 bonus skill point per level, but instead receives no bonus.
You can sorta overcome this restriction by giving the character a specially tailored-skin and picking an ability to adjust which doesn’t affect your character, but that solution’s not very satisfactory.
So far, there doesn’t seem to be a way to modify the permanent statistics of a character via NWScript, which means that even if you find another way to give ability adjustments instead of skins, it won’t make a difference.
NWN also seems to have some protection against character editing: changing the ability scores of the various .BIC files in the localvault directory will make your character invalid if the total ability points don’t add up to 30. So you can’t use a character editor to adjust your character’s ability scores (yet). This makes sense, otherwise it would be very easy to use a super-character to cheat on multiplayer servers.
So, unless there’s a way to permanently adjust ability scores, using skins is a hack which works, but doesn’t really work well enough. The other solution would be for Bioware to patch NWN so that it uses the adjusted ability scores, rather than the permanent ability scores. Unfortunately, doing it either way has its share of implementation issues.
ECLs
Effective Character Levels, or ECLs, are a way to compensate for the traits of the more powerful races. The average drow, for example, has a whole bunch of fun abilities that make them far more powerful than the average human. To compensate for this, some dude came up with the concept of an ECL.
Drows have an ECL of 2, which basically means that they’re two levels lower than other races at the same amount of XP. For example, a human with 11000 XP would normally be level 5; a drow with 11000 XP is level 3. ECLs “lag” your character behind by a certain number of levels, to compensate for your more powerful racial capabilities.
I’ve managed to implement ECLs in NWN. The solution is quite elegant in some ways and pretty ugly in other ways, but as far as I know, it’s the first complete ECL implementation done to date.
You can always have a look at the NWScript code to figure out what’s going on, but since all programmers are lazy, here’s a rough idea of how it works, and why it’s been written that way.
A first attempt at an ECL implementation
(Warning: deep knowledge of NWScript and 3E/ECL rules (or serious crack) will be required to understand what the hell I’m talking about here.)
Conceptually, an ECL changes the XP progression table. The PC is treated as if she’s some number of levels higher than she actually is, only for the purpose of determining the XP required to level up. If you try to translate that concept directly into code, though, you’re doomed.
Initially, the most obvious way to implement ECLs is to use a module’s OnPlayerLevelUp event. Every time the player gets enough XP to level up, take some amount of XP away, so that she has to earn more XP to go up that level. Yeah, that will work, but it presents two nasty problems:
- The OnPlayerLevelUp event is triggered after the player actually levels up. It’s not triggered when you hit the amount of XP required to level up. That means that if you decide to take away some XP, it will be done after the player has picked all their classes, skills, etc., only to have that level immediately taken away. Raaather annoying. This first problem isn’t solvable, but if you’re really intent on having ECLs, but you can live with it if you really want to.
- If you take away XP when the player levels up, how do you know whether you’ve done this before? This is easily solvable by storing local variables on the PC object.
- Since you cannot store any persistent information on a PC object, you don’t know whether you’ve taken away the XP before. What if the character has had her XP taken away before, then exports her character for use on another server, only to find that when she levels up, her XP has been taken away again? Unfortunately, this problem is unsolvable, and it’s a showstopper: users will not accept XP being taken away from them unnecessarily.
Statefulness and persistence
The core issue with the third problem is that it relies on state. (Functional programmers, don’t you all feel good now?) It relies on being able to store information with the character that can be used at a much later time; if the character is exported before that event occurs, things go completely screwy. So, any ECL solution that is done must be stateless, or at least executed quickly enough that there is no practical chance for such a race condition to occur in practice.
Another view on ECLs
There’s no chance of implementing ECLs if we don’t alter our concept of how to implement them. i.e. we have to think outside the box.
We know that an ECLed character requires more XP to go up one level than a non-ECLed character. One way to think of this is that the PC requires, say, 25% more XP than usual to go up a level. As an example:
- a non-ECL character requires 2000 XP to advance from level 2 to level 3: you need 1000 XP to get to level 2, and 3000 XP to get to level 3. However,
- a ECL 1 character requires 3000 XP to advance from level 2 to level 3: you need 3000 XP to get to level 2, and 6000 XP to level 3.
So a ECL 1 character requires 50% more XP than a non-ECL character to advance from level 2 to level 3. While we can’t change NWN’s XP progression table to support this (at least not without evil hacking of 2DA files), what we can do is penalise the XP that the PC earns to make it equivalent to the progression table used by the ECL character. This is similar to the XP penalty that is introduced when you multiclass and you don’t keep your non-favoured classes within one level of each other.
So, if we require 3000 XP to advance a level instead of 2000 XP, our ECL implementation will work if we penalise all the XP earnt by the character by a factor of 1/3. Instead of earning 90 XP for killing a monster, the character earns 60 XP. Where she’d normally get 300 XP, she gets 200 XP instead.
While NWScript doesn’t allow you to say “give a PC n% of the XP that she’d normally get”, what you can do is subtract an amount from the XP that the character has earnt. So, when the PC gets 900 XP, subtract 300 XP. When she gets 60 XP, subtract 20 XP. If you do this at a frequent enough interval (e.g. every second), then you have an algorithm which executes fast enough that it’s effectively stateless.
This is the way that the ECL script works. We replace the nw_c2_default1 script, which is called whenever an animation update occurs, so that the XP check is done very often (on average, probably once every three seconds). Previous attempts tried to trigger the script so that it ran once every second, but that can’t be done unless there’s a way to set a variable which only lasts for the duration of the current play session. (See the Scripting page for more information.) As long as players aren’t cheating dramatically and exporting their character within time between animations are updated, it’s all good.
There are a few downsides to the current approach:
- Do all players need to put the new nw_c2_default1 file in their override directory, or does it only need to reside on the server?
- The nw_c2_default1 file may need to be updated whenever a new patch is released.
- There should be a stronger link between the thingy that grants the character the racial abilities, and ECLs, so that if you don’t have ECLs active, you should not receive the racial abilities. (That’s only fair!)
- It would be better to have a consistent, short time interval between XP checks. It’s good enough right now, but it’s always better to be perfect …
I’ll treat these problems as a TODO list: they may go away as I find workarounds. The ECL scripts, however, work, and work well.