ULarn (Ultra-Larn) for Win32, built on Cygwin but runs natively
Ularn that runs on Windows 7!
Table of Contents
Background
Larn is one of the many “Roguelike” games, using ASCII (letters and symbols), before graphical computer games were common.
Unlike Rogue and Hack, Larn was one of the first Roguelike games to employ a top-level “town”, with a bank, a store, trading post, and other buildings.
Rather than a food-based timer, where you have to eat periodically, your character is on a quest, where a special potion must be acquired, to cure your character’s daughter’s illness, which if not cured within a specified time period, will result in failure (her death). This gives the game a global timer, where the player must accumulate wealth, special items, explore, and kill monsters, all within the time limit.
I wasted many of my prime teen hours playing Larn, and it has a special place in my heart to this day.
A newer version, called “Ultra-Larn”, or “Ularn” for short, emerged in 1992, offering more dungeon levels, more monsters, more items, better game play, etc…
YEARS LATER, maybe 2006-ish, I downloaded a bunch of classic games, including the original Larn and Ularn, but these only run in *nix or DOS – there really isn’t (wasn’t) a good Win32 version available.
Although you could run the DOS versions in DosBox (A DOS emulator), it wasn’t an easy, clean, or pure experience.
After scouring the Internet, I finally found a distribution called Ularn Win TTY (1.6.3). This version had been updated with color, directional walls, and a few other enhancements.
Since then, Ularn Win TTY has ceased to exist, or at least, I can’t find a valid link to it.
Moreover, there doesn’t appear to be a stable Windows release of Ularn, so I decided to download the latest official version, 1.5pt4, and compile one.
Download
This is a Cygwin build of Ularn 1.5pt4, modified to run “as is” without having to install Cygwin. The included cygwin1.dll is all that’s required.
Simply extract all the files from the zip file, in the folder CygUlarn_1_5_pt4\Binaries, to an empty folder, and launch “Ularn.exe”.
You can download the zip file here:
Movement:
y k u \ | / h - - l / | \ b j n Keyboard layout: ul ur y u h j k l lf dn up rt b n dl dr ? - Help file - this is your friend!
More Details
In case you are interested in the process, and my thoughts at the time, here is some additional info.
Problem 1: MinGW isn’t going to work
My first thought was to build this using Eclipse and MinGW. I found out very quickly that MinGW doesn’t support “curses”, and there are a bunch of other “GNU” dependencies, that were simply impractical to re-write to use the WinAPI, or compile and cobble together all of the pieces I needed.
Configuring for Cygwin
Looking to Cygwin, all of the parts were there, but Ularn is REALLY OLD CODE! The last time it was “built” in Cygwin was apparently in 2002!
I set up a Cygwin environment, got everything up to date, installed automake and autoconfig, gcc, and make, and went to town.
Within a shell, I ran the ‘autogen.sh’ script, which ran just fine, and created the ‘configure’ script.
I ran ‘configure’, which completed successfully, but there were a few hidden problems that I was about to discover.
The main purpose of configure is to create the Makefile and config.h — a collection of constants that defines various compile options for various platforms.
Problem 2: ‘configure’ Had Some Issues
The configure script failed to detect Cygwin, so I had to dig around in the source code, and figure out that a bunch of the compile errors were related to a “CYGWIN” constant that should have been created during the configure process, but wasn’t. I added the following line at the top of config.h:
#define CYGWIN 1
That fixed many of the signal errors I was getting during compile time.
Problem 3: ncurses / termcap
Next, I fought with ncurses, which I didn’t know at the time was related to termcap. Not sure if this is part of the “official” GNU distribution, or specific to Cygwin, but termcap has been swallowed by ncurses.
Everything I read said, “Eh, download ncurses, compile with -lncurses, and you should be fine!”, or the typical internet response, “RTFM you n00b!” <– I love these people. I learned so much from some jerk posting, “RTFM”.
Whenever I’m trying to google for something obscure, I always end up on a message board which feels like that scene from MST3K:
Tom Servo: No, wait! We’re trapped in space! Can we use this thing to get back to Earth?
[or, maybe compile this application that uses termcap???]
Benkitnorf: I don’t know. Geez… let’s see, maybe this does something…
[pushes button, zapping Servo]Benkitnorf: Crap. That’s not it. Hang on…
[gets manual]Benkitnorf: Okay. Did you use the Intensifier Disc?
All: Yes.
Benkitnorf: Turn the controls 18 degrees to the left?
All: Did that.
Benkitnorf: Are you in Europe? Do you need an adapter?
All: No.
Benkitnorf: Well, look. I don’t know anything about this thing. Maybe this does something…
[pushes button, zapping Servo again]Benkitnorf: Oops. That didn’t work. Okay, well I’ll be sure to tell Exeter to give you a call! Bye!
I finally found a really old distribution of Cygwin with its own termcap, and I just blatantly statically included the termcap sources :-)
Everything I read said, “keep your code the same, just compile with -lncurses”. Yeah…. that doesn’t work.
Everything else I read said, “You should bring the code up to date to use a newer library.” OK, someone can do that, but someone isn’t me. Have fun with that. If I have to “bring the code up to date”, I’d rather just write my own, like the Nlarn guy did, rather than waste the time having to learn someone else’s code.
I copied *.c and *.h from the termcap sources to the Ularn/src folder. I had to make a couple of modifications to extern.h, and I had to modify the Makefile to include the new .c, .h, and object (*.o) files.
Problem 4: Issues with ZLib
Can’t find ‘compress’ and ‘uncompress’.
A little googling (and much more name-calling) later, and I determined that these symbols were tied to zlib, as I’d expected.
“Benkitnorf: Did you compile with -lz?”
“All: yes, we compiled with -lz”.
After some more digging, I found a constant in config.h to turn off zlib support, so I just did that, instead. Again, if someone else wants to mess with this, go right ahead!
I remmed out the following line in config.h:
#define HAVE_LIBZ 1
This is referred to as “libz” rather than “zlib”, so there is probably some rare, obscure, outdated reference that I’m missing somewhere. The easier answer is just to turn it off — so we have a slightly larger save file? WHO CARES.
Clean Compile / Build!
So at this point, I had a compiled, working version of Ularn.exe, built on Cygwin!
Still a few more bugs to work out…
Problem 5: Hard Coded Location
I launched Ularn from a Cygwin shell, only to get the following message:
Can’t create scoreboard file in /usr/local/shared/Ularn
Check permissions and try again
The shared files, including the scoreboard, were assumed to be in /usr/local/shared/Ularn, which simply doesn’t exist in my local Cyg environment.
I think this was being read from a macro in the Makefile, assigned to LIBDIR.
:DEFS= -DLIBDIR='"${datarootdir}/Ularn"'
Then, in data.c, “libdir” is assigned:
char *libdir = LIBDIR;
The easier thing to do is hard code the “libdir” path to the current folder from the environment:
char *libdir = ".";
NOW, I had a Ularn.exe that actually runs.
Now What?
My next goal was to liberate “CygUlarn” from the Cygwin environment.
There are many so-called Win32 apps that were really ported, compiled, and built on Cygwin, and similarly liberated. For example, if you download RSync for Windows, it has the same cygwin1.dll within the package….
Step 1: I copied everything to an isolated folder
Step 2: I launched a command prompt, and wiped out the path
Problem 6: Suss out DLL Dependencies
The first thing to do was to figure out the DLL dependencies. The only one was cygwin1.dll – this is because everything else is statically-compiled in to the quite-chunky 500K executable! The original Ularn was probably 50K! But the original Ularn won’t run in Windows 7, and doesn’t have to contend with the Windows API.
Problem 7: Determine User Name
Once I got the DLL dependency resolved, the next issue was to correctly capture the user name. Ularn is intended for a multi-user environment, just like its Larn predecessor, so it tries to go scrape the system’s user info to figure out who is logged in. In a Cygwin shell, this works just fine, but in a Windows shell, there is no such construct.
My solution was to make a couple of modifications in main.c, to just simply prompt for the user name at startup. I remmed out all the code dealing with finding the user name or UID, ending in a fatal error if you can’t find the user name.
Old Code:
/* * first task is to identify the player */ if ((ptr = getlogin()) == (char *)NULL) { if (pwe=getpwuid(geteuid())) ptr = pwe->pw_name; else if ((ptr = getenv("LOGNAME")) == (char *)NULL) if ((ptr = getenv("USER")) == (char *)NULL) { noone: fprintf(stderr,"Who *are* you?\n"); exit(1); } }
I added the following:
noone: fprintf(stdout,"Who are you? "); fgets(defaultplayer,sizeof(defaultplayer),stdin); defaultplayer[strlen(defaultplayer)-1]=0; ptr=defaultplayer;
“fgets” is a better method, since it protects against the buffer length, but it has the quirky behavior of including the carriage return. ??? Stupid behavior. Thus assigning “0” (end of string) to the position at the string length minus one, effectively wiping out the carriage return.
Problem 8: Path Assumptions
One more run, and everything seemed OK, until….
Can’t write to save file /home/Justin/Ularn.sav
Some files, like help and scoreboard, are “global”, and I had addressed that by fixing ‘libdir’ (see above), but others were tied to the user profile.
In the DOS version, it just saves everything to the Larn folder, so I opted for that solution instead.
Old code:
/* this will be overwritten with the players name */ if ((ptr = getenv("HOME")) == (char *)NULL) if ((ptr = pwe->pw_dir) == (char *)NULL) ptr = "."; /* save file name in home directory */ sprintf(savefilename, "%s/Ularn.sav", ptr); sprintf(buf, "%s/%s",ptr, optsfile); /* the .Ularnopts filename */ strcpy(optsfile, buf); sprintf(buf, "%s/%s", ptr, ckpfile); /* the checkpoint file */ strcpy(ckpfile, buf);
New code:
sprintf(savefilename, "%s.sav", ptr); sprintf(buf, "%s%s",ptr, optsfile); /* the .Ularnopts filename */ strcpy(optsfile, buf); sprintf(buf, "%s.chk", ptr); /* the checkpoint file */ strcpy(ckpfile, buf);
Assuming you type “NewGuy” as your name, this will create or use the three following “local” user files in the Ularn folder:
- NewGuy.sav — Save file
- NewGuy.Ularnopts — Optional options file
- NewGuy.chk — If Ularn or the whole system crashes, this restores your game from a “checkpoint” taken every 400 moves
Again – my goal is to play it, not support a highly-multi-user environment. If there are two “Bob’s”, you know what? Bob1 and Bob2 are just going to have to work it out.
Aaannd…. It works!
Sources
All of the modified sources, including Makefiles, termcap files, and modified source files are included in the “Sources” folder of the zip file in the ‘Download’ section above.
If you want the original, go download it, here:
Screen Shots Running on Windows 7
Launch, showing Firefox browser, Win7 desktop. The window is a Windows shell not a Cygwin shell (note the icon)
Choose your class:
The town:
Dungeon crawling — being attacked by Gnomes!
Isn’t that kind of small?
Glad you asked!
In 32-bit Windows, “ALT+ENTER”, holding ALT and pressing ENTER, brings you to a full-screen command prompt.
In 64-bit versions of Windows, including most machines running Windows 7, “full screen command prompt” is not available.
Here is what you can do instead:
- Right-click on “Ularn.exe” (or simply “Ularn” if you have file extensions turned off)
- Right-click on “Ularn.exe – Shortcut” or “Ularn – Shortcut”, then select “Properties”, which will allow you to modify the shortcut.
- Click the “Font” tab, at the top. Here are the default settings:
- Select these settings instead, “Lucida Console” for the Font, and “24” for the size:
From now on, launch “Ularn.exe – Shortcut” or “Ularn – Shortcut”
Here is what the screen looks like:
Much easier to read!
Next Steps
I’m kind of a purist, so I want to maintain the Ularn version “as-is”, meaning, as close to the original source as possible. I think people should have access to the original experience, either for nostalgia or just to maintain an historical record.
However, there are some things I’d like to do, and if I end up doing them, I will bundle that as a separate version:
- Ularn Win TTY, bless it, added color. This is one of the biggest drawbacks to Larn and Ularn — NO COLOR! I think there’s room to add an option to conditionally enable color. If you’re a purist, disable it, if you want something easier on the eyes, enable it.
- Get rid of 80 x 25. There is plenty of room for larger dungeons by going to 80 x 40 or 80 x 50. In the source code, it alludes to all of the maximum game board dimensions, so it may be as simple as expanding the defaults. In theory, “ncurses” or “termcap” or whatever should handle the back end.
- Bring back the dots! Original Larn had “dots” like Rogue and Hack, indicating areas that you have explored. Ularn can get quite confusing, because your awareness is a 3 x 3 grid — sometimes you don’t know if you’ve explored something or not, because a dark hallway in the center of two other dark hallways looks exactly the same as the ones you have explored. If you love something, let it go. If you’ve explored something, put a dot on it!
- Branch Trading Post and DND Store. Ularn adds a “branch bank of Larn” several levels in to the dungeon. This is convenient, since the dungeon is 15 levels deep, and you quickly find yourself loaded down with a bunch of belts, rings, and unique items, leaving only a few inventory slots available for gems and other items. Easy access to a “Branch trading post” or “Branch DND store” would allow you to liquidate uneeded assets, or procure much-needed supplies without having to constantly run back and forth to the town.
- True ANSI terminal support. I WANT TO USE THE DARN ARROW KEYS.
I’m not trying to reinvent the wheel, with yet another Roguelike… my intent is to bring back a classic, so that people on modern operating systems can run it and enjoy it.
If you want a modern take on Larn, check out Nlarn. I think the guy who wrote this did a spectacular job! However, his take on it is the same as mine — rather than hack around with 30-year-old code, he wrote a simulacrum from the ground up. It’s far superior to Larn or Ularn, but it’s not “pure Larn”. For folks who want Ularn, here it is.
For what it’s worth, I downloaded ULarn 1.6.3 TTY and ULarn 1.6.3a, both for Windows, a little over 8 years ago, and I have uploaded them to MEGA for the benefit of you and anyone else who reads this site; I found this page by looking for an update to that program after reading the recent Ars Technica history of Roguelikes.
ULarn 1.6.3 TTY: https://mega.nz/file/g0gikIyI#i8FPhZ-4IAwcFLnZegbyzRlT18FrUu9KYulIEucrAfI
ULarn 1.6.3a: https://mega.nz/file/hxwWiYwQ#V23IYKAzzrEMzzy4P09cVbr0W2YfU_4sQ_Ozd-k8biM
Thanks!!