WarWorld (part I)

WarWorld was the most popular BBS door game I ever made. Not so popular as anyone I’ve ever met has even heard of it - not talking about a L.O.R.D. or a Trade Wars here - but it was more frequently registered than any other thing I wrote. Once or twice a week for about a year, I’d get a check for $15 from a SysOp seeking a registration code.

WarWorld

This last good version used the same basic screen and keyboard I/O functions as the BASIC language offered at the time. I wrote wrappers for things like Print and Input. Actually one for every screen and keyboard I/O function that the language supported, plus Beep. These were ZPrint, ZInput, ZLocate, ZBeep, ZClr, and so on.

When using my Zfunctions, if a modem connection existed, then along with the local display, a mix of ANSI and ASCII would ensure the remote user’s screen displayed the exact same thing. When waiting for input, keys from local or remote would be accepted.

I even implemented local ANSI emulation, sort of the reverse of zFuntions. An ANSI file could be sent to a remote user character-by-character and their modem program would display it correctly. But locally, the ANSI codes had to be interpreted so that Locate, Color, Print, and such would display the file as it was being seen remotely. This was so infinitely harder, the only reason I succeeded at all was by finding someone else’s ANSI-display code which didn’t work, and then fixing their bugs.

Version 1.23 was the last good one because the next update, version 2.x, was a major rewrite, with tons of new features, even a name change (though registrations of the old game worked on the new version, too). It contained many features players and SysOps had long been asking for… and a Windows-style interface no one had.

Though still a DOS application, it looked like a Windows Application from Bizarro World or an alternate universe where World War II had been won by Nazis and also they only liked ASCII text [and maybe what they called ANZI garaphics --Nov.].

It had a menu bar with pull down menus, pop-up textboxes, windowed input boxes, and so on…

Wonderful in local mode, this was entirely too much data transmission for anyone creeping along under 9600bps, which was everyone. Throw in a couple of nearly show-stopping, highly annoying bugs, imagine the Windows UI without mouse support… and you’ve got the measure of it.

Not that the ability to have Windows-type interface elements was a bad thing in itself. In many cases it was excellent.

For example, this early version of WarWorld cleared the entire screen for SysOp-to-user chat, which of course required redrawing the entire screen later. Since that was undesirable due to the low connect speeds of the time, only the menu was redrawn.

Acceptable, given they had already seen the map, their next option would display the appropriate part of the map as needed, and if the player just wanted to see it again for some reason, a Display Map option was available.

Acceptable, but ugly. Still, a kindness to the 300 baud user (also 1200, 2400 and 4800).

Before ChatDuring chatAfter Chat

 

By comparison, my eventual windowed chat (shown here in ANT WAR), was much nicer. It would restore the screen to the previous contents, and actually required less of the screen to be redrawn.

Before ChatDuring ChatAfter Chat

The obstacle seemed insurmountable. To get windows that could pop up, display some info or accept some input, then close? I needed the ability to capture and store a portion of the screen, so that when the window closed, it could be redrawn.

I was stuck, because this needed to work both local and remote.

The one time I did use proper VisualBASIC form, created with the VBDOS form editor, was for a configuration UI which could only be seen local. Though it just had to be more efficient (not constantly checking for a remote connection, and written by professional programmers), the executable ballooned in size. I immediately removed it and wrote my own config UI, since tripling the size of the executable for something no player would ever see was no bueno. We had to worry about things like that, in modem-times.

Using VisualBASIC for DOS was of no help. Though it also created forms out of standard ASCII text, they displayed only locally, through magical built-in functions that I couldn’t touch.

VB/DOS Form builder

They would not display to a remote user, and demanded either mouse or alt-key input, neither of which I could detect from the remote user.

So I had to write code to do just what VBDOS was best at doing, in order to have it work local and remote. That meant solving the problem of capturing screen contents.

So. Very. Hard.

Until suddenly, it was easy. It turned out to be a simple thing to do, mostly involving stop being an idiot.

I’d been stymied by an inability to capture the remote user’s screen. Writing all those other zFunctions had gotten me stuck in the paradigm of doing something local, checking for a connection, then using ANSI codes to do it again remote if needed. Some ANSI documentation hinted at the possibility it might be able to query for screen contents. I didn’t really try to get that to work much, but I did spend some lengthy minutes wondering how such a query would be answered. I considered attempting to store a local image of what I thought the remote screen must look like: maybe three arrays of integers: fore-color, back-color and ASCII code. Then I mentally cursed my stupid brain for being so stupid.

‘Cause duh, the remote screen was the same as the local one.

I could easily query the local screen for character and color contents, and that was that.

Then in addition to my standard zPrint, zInput, etc. functions, I was able to add zMsgBox, zInputBox, and so forth to WarWorld. I built the screen save and restore functionality right into the windows open and close functions and never had to think about them again. Forcing them to be closed in the reverse-order they were opened, meant they could even be stacked on top of one another (SysOp-to-user chat opening over a pop-up input box, for example). The screen would be restored correctly.

Check this out:

Context sensitive help

Ok, so I couldn’t put HELP on F1 where belonged (the remote user might not even have an F1 key), but no one had context-sensitive help in a door game back then, on any key!

My baby was feature-rich.

So much so, in fact, that I needed to upgrade from QuickBASIC in order to work on it, even before the desire for windows-style interface elements hit me. There were a handful of features reserved for professional developers which VBDOS 1.0 and BASIC Professional Development System 7.1 had, and QuickBASIC 4.5 did not.

I feared a switch to TurboPascal or PowerBASIC, as either would likely require a rewrite of WarWorld. I wanted to continue development, not redevelop.

But I couldn’t afford anything.

Luckily, the first working version of MS-Windows (the third version) wasn’t out yet, so the world was still playing in DOS. Everyone used MS- or PC-DOS, WordPerfect, Lotus123, dBase or R:BASE, and no email even when they were connected by a Novell network. My department was even running an inter-departmental e-mail program that I had written, since Novell wanted to make the impending ass-kicking they were about to receive from Microsoft as easy as possible. We also ran some applications I’d written for procedures formerly done by hand (and pen and paper). I explained to my boss that I needed either VB/DOS ($200) or PDS7 ($500) for work, and the department ponied-up for a copy of VB/DOS.

Well, I did also use it at work, sometimes even for work-related things.

Eventually, WarWorld was pretty done, and I began thinking of new games to make.

I realized I’d have to re-code tons of features that I’d want the new game to have… and for that matter, that I’d want every game to have.

As I said, everything was added to WarWorld.

I’d begun this adventure [only] knowing how to load a .BAS file and compile it from a menu option. Now I was using LIB, LINK, and BC.

I’d already been forced to break WW into five or so modules and to exit the VBDOS environment and compile it from the command line. Due to the size of the program, I was compiling modules into .OBJ’s, and linking them (and the MS C 6.0 communication-routines) into an executable, with some other funky command line options that I don’t even recall.

This just barely rings a bell.

  • BC.EXE … Basic Compiler: .BAS -> .OBJ
  • LINK.EXE … Linker: .OBJ + .LIB + .QLB -> .EXE or .QLB
  • LIB.EXE … Library utility: .OBJ + .LIB -> .LIB files

Now I had to figure out libraries.

That is not the order in which one learns these things, generally.

All my door routines had started from a set of QuickBASIC functions, a skeletal .BAS file into which I’d inserted a doorgame.

Hey, how’s this for nerdy?

Posting BASIC code to a Star Trek forum: 1 nerd point

So, from a set of functions, I’d built-up WarWorld and added to that core set of functions, and only much later realized how useful the updated and expanded set of functions would be for every other game that I wanted to write. So I extracted the functions to make my library of door game routines. Fearing a tragic blunder, I copied rather than cut, and left WW alone. WarWorld wouldn’t use the library I’d created from its door functions until that rewrite, much later.

In the meantime, Wow!

Subsequent games needed so much less work. I marveled at the ease of programming a game, when you didn’t also need to program UI and IO functions from scratch for every goddamn thing.

It was so easy, I’d browse through lists of BBS utilities, find one that I wanted, then code my own to do whatever it did. I never calculated that the $15 registration fee I’d “saved” put me at an income of maybe $1 to $3 per hour, but I didn’t earn much more than that at the time anyway.

Plus, I just thought it marvelous. Not to have to re-code extremely boring non-game things like monitoring the user’s time left, dealing with dropped connections, sysop-to-user chat, and so on was great. Being able to pass a function a couple of variables, then seeing something polished result? Sweet Lucifer! It felt like cheating.

The only other time I’ve felt like that was when, after playing a monk in EQ for fifty levels, I started playing a druid.

I could make a new card or dice game in a weekend. I added standard deck and dice functions to the card and dice libraries, plus top-ten lists and such to another. All the typical things a card or dice game did, rolling and displaying dice, drawing and shuffling cards, was a snap. Thinking of single-player games was the hardest part, usually.

Moment of idiocy: I didn’t know how to code card-shuffling. I wrote a monstrous, slow, embarrassing piece of code to do it. It didn’t even occur to me to just forget about shuffling and deal them randomly. Eventually I got it, uhdoyeee!. The same thing I’d have seen if I’d read any book of BASIC game programs. For each, SWAP randomly.

This is the penalty of ignorance. I also invented database normalization through third normal form, for example.

I’m not saying that to brag, but to confess: Third normal form had been defined for about 30 years, already. Re-inventing it was stupid.

If you’re going to do something, anything, for work or play: Do yourself a favor and see what others have done in that area. Spend your time inventing new things.

I’m like a guy who invented the wheel again, decades after it’d already been invented and put into wide-spread use.

But apart from and after that, these were so easy that I made them share scores with other BBS’s in the area for city-wide top-ten lists. None of these games were ever popular enough for there to be more than one BBS running them, registered, in the same area code, but it would have worked. I think.

Various BBS utilities were even easier to deliver. They practically designed themselves (to address a need). I rarely even made those shareware: just gave them away, since usually there were already fifty some odd utilities doing the same thing they did (and frequently more).

But all that stuff is gone.

Ant Wars, and the “pre-NGE” WarWorld: all that is left of my work. All that the BBS SysOps deemed worthy of keeping around.

Granted, the things that sucked, I didn’t really expect to survive. Possibly my first door ever, RPGdoor (a forum-based RPG message, character-sheet, notes, mapfile, etc. program), hadn’t even survived in the BBS world.

I had sold my card games to another door game programmer, source code and all. He already had a few dozen dice and card games out there, and I never saw mine again. I assumed that he was just eliminating competition. No shock those are gone now, too.

The ZDOOR library, which was a marvel, only worked with VisualBASIC and maybe BASIC PDS 7.*. These were languages not even BASIC programmers used. They used PowerBASIC if they were serious, QuickBASIC if they were not. The only people using Microsoft’s over-priced, under-powered orphans were the people who’d gotten their employers to buy ‘em. So again, no surprise that zdoor???.zip isn’t anywhere among the old BBS files now hosted on the net.

That not a single one of my utilities was deemed worthy surprises me, especially a FILES.BBS manager that I recall being quite good, though I cannot recall what I named it.

Just WarWorld, which consumed massive hours of development time over a year or more, and Ant Wars… which I wrote in a couple weekends.

I only wish more of that old stuff had made it for selfish reasons. Each .zip is a time-capsule from fifteen years ago. Discovering surprising features (because they were completely forgotten), recalling goofy implementations. Examining wonky datafile structures and the like.

I wish I’d known to keep all of it, so I could read everything I wrote back then.

One Trackback

  1. By WarWorld (part II) (from Jeff Freeman) on November 21, 2007 at 11:34 pm

    [...] Feed 21 Nov 2007WarWorld (part II)[Essays][ Personal][ Gaming]In WarWorld (part I) I wrote about my first real video game. That is, it was the first that I’d designed and [...]