As I continue working on the combat engine, finishing up other portions of “temporary” code has come up. One particular one is the use of battlemaps.
Most of the 2D CRPG tactical combat games feature some kind of varied terrain to conduct battles on. Ultima’s III-V all had them, one for each different terrain type. So obviously I intended to follow suit here.
But, since I have the disk space for it, I intended to go much further than any of those games. Ultima V only features 16 unique battle maps. My CRPG? Oh, probably around 300+.
I started battlemap design several years ago, when I was still working in the MESS emulator. I actually had to port my work off an old work disk to continue it, and update the tiles, which had changed a few times since I made the original file. Now I’ve gone one step further and made a separate battlemap set for each tile set. That way I can have as many as I need to make combats always potentially interesting.
One complication I had to correct was the loading of different tile sets. Originally I had only a single set for combat. Now I’ve expanded it so that there’s a tied-in tile set for each of the major travel types. That lets me have maximum character space to do interesting features. If you’re in a town battle, lamp posts, crates, barrels, may show up on the map. A dungeon has manacles, skeletons, and other macabre items. All fun!
An added bonus with my approach is that battlemaps will be alterable by player action. Spells exist that let you create barriers, area effects of damage spells can destroy the landscape, and so forth. I don’t think any classic CRPG offered this kind of feature, keeping most of the terrain fairly static.
Battlemaps are stored in two 128 byte records. The first 8 bytes are a compressed mini-map that indicates if the spaces are empty or occupied. The rest of the space stores the maps in RLE compression, using values lower than 128 to indicate a count of the next tile. My battlemap editor warns me if I exceed the record size. This usually happens if I get overzealous with spreading unique tiles around. (I don’t use RLE for the travel maps, because the high-byte is used to indicate lit/unlit squares on dark maps. No real need to compress those files anyway.)
One particular problem to solve is the placement of units on the battle map. I considered at first an array of common positions to just iterate through, but it was quickly adding up to a lot of bytes of data to store. So then I realized I could do this algorithmically with tools the code already has: the trigonometric functions.
Using that code, all I have to supply for the map is two things: a set of coordinates and a radius. Because I want units to spread out a bit, I actually supply two sets. The number of units is divided in half, and then each half is placed in a circle around that coordinate, with the angle being based on the number of units. (4 = 90 degrees, 3=120 degrees, and so forth.) For an ambush scenario, a single set of coordinates is used for both sides, with different radius’s, so one is surrounding the other.
What to do if the chosen space is occupied? Well, first it will check all adjacent squares to that square for any open spots. If it finds one it takes it. If all four cardinal directions have nothing, then I just default to selecting completely random coordinates until an empty space is found. This means there’s a potential for a stray unit to end up in some bizarre place, but hey, that’s the fog of war…
I wrote up the necessary code to do the positioning this afternoon on paper, now I just need to get it written in code and incorporated into the source. I may also need to refactor my trigonometric functions a bit; they were assuming whole word values and I’m pretty much exclusively in bytes, for sprites and coordinates.
Oh yeah, the trigonometric functions. No, I’m not using the ROM routines. They’re difficult to implement and use, plus I’d have to convert everything to Radix 100 floating point. Instead I use whole integers, with a base of 256, and stored the main 90 degree set as values 0-255 in a data table. Ratios are then calculated by multiplying the angle by the data table value and dividing by 256. It’s obviously nowhere near as accurate as a floating-point method, but for what I’m using it for, it works pretty well.
When I get battlemaps loading and positioning of units working, I will probably move on to getting combat ending debugged and sorted out. I’d like to have the end-to-end of it mostly done before I get into the long arduous process of spell FX.
I’ve been following your blog since…ever. Well, I mean I’ve ready your entire blog and I check back several times a week. I’m 41 this year and grew up playing Wizardry, Ultima I-V, etc. on the Apple II+/gs so there’s a lot of nostalgia involved for games like the one you’re working on.
But I cannot help but simultaneously wonder and get frustrated. Why oh why are you limiting yourself to an ancient platform for your game? Things would be sooooooo much easier for you development wise if you were working with say win32/c++.
I can partially understand your reasoning. I really think I can. But it doesn’t help me get past the frustration I feel when I read your blog and the difficulties you encounter solely because of choice of platform. Heh. Or I read about the limitations you’re suffering again, solely because of choice of platform.
Please make me a believer! Lol. When I saw some of your battle maps I got a small thrill. Your large map at the top of your website begs me to study it every time I load your webpage (speaking of which: I could’ve sworn I was able to download a huge overland map a long time ago from your website – what happened to that and is it still available?)
So all that to say this: keep up the good work man. You’re an inspiration and I really look forward to your next blog. Also is there any chance you’d ever port development over to, well, win32/c++ for example? Just curious.
Take care!
Thanks for keeping up with me! This eight years is really going on too long for it…
Part of the reason I’m developing on a vintage platform is, well, it’s a hobby and I like it. Plus I always wanted to write a game of this caliber when I was a teenager. And there’s a distinct lack of good CRPG’s on the TI-99/4a as well.
There was an overland giant map, I believe it’s on my older website at http://www.adamantyr.com/crpg/images/WorldMap.png I redesigned the game to remove large maps like this because they were inefficient in both space and loading time.
Porting over to a modern development platform isn’t impossible, but I’d probably do that after the game is done on the TI-99/4a. I’d really be interested at working on a modern touch platform like the Surface or iPad for that… Obviously it would still be a classic CRPG, just running on a modern platform.
Ahh, that was the one. Awesome. Just something cool about zooming in and scrolling around maps like that. I think it’s the nostalgia thing again heh.
But can’t you just load whatever’s around the player from disk, like U4 did? If you don’t have a big map for the game what are you doing?
If you don’t mind my asking….
I had a big map implementation initially. I didn’t do it quite the same way that Ultima IV and V do; I recently discovered some great wiki pages describing the internals of those games in detail.
The problem is these techniques involve a lot of disk access. ESPECIALLY for the edges. I noticed even Ultima IV isn’t very efficient with this; the Commodore 64 version is particularly bad, having a long 3-5 second disk access every time new chunks are loaded.
Another problem was how the map design was happening with a large blank. I found myself drawing a lot of mountains to box in areas to focus creativity on. I felt like I was repeating myself a lot in different places.
I decided to go with a zone-based system instead. There’s still a “world map” it’s just broken down into chunks up to 4096 bytes in size. They’re all self-contained and it doesn’t have to deal with border/edge loading, so no more disk accesses as long as you don’t move into a new zone. I have to get creatively clever to mask boundaries between zones… mountains or impassible cliffs border each zone… but I think it will still make for a great game.
This brings back memories I had of dealing with my maps and the edge of the world using the segement system I did, worked out quite well in the end..
How DID you solve that problem with segments, out of curiosity?
“Plus I always wanted to write a game of this caliber when I was a teenager. And there’s a distinct lack of good CRPG’s on the TI-99/4a as well.”
I can relate. I wish I had the technical knowledge that I have now back when I had the imagination and passion as a teenager. Making the “Great CRPG game for X retro platform” that was never made for that machine is a topic of discussion that comes up on retrocomputing forums from time to time.
Since I am a much better programmer than I was in high school, along with cross development platforms (cross-assemblers and compilers that run on modern computers but they can generate 8-bit machine code) I can do those games I always wanted to do, but couldn’t because of the limitations that were evident back in the day. But being older, I’m creatively burned out compared to when I was a 13 year old kid. So I mine the recesses of my past life as a teenager for ideas, or I look at my halfway-completed 8-bit games that were saved on disk, and then I actually finish them. I won’t ever achieve commercial success with my hobby, but I certainly have a much larger audience today by providing a link to download my latest retro game on the appropriate internet forums compared to when I would show my games to my parents and they’d nod “Oh, that’s nice.”
I often think about hunkering down and learning how to program iOS. But real life gets in the way (mortgage payments, and all that).
I apparently cant reply any deeper, so I solved my segment problems. trying to remember, My maps are all cut into 32×32 chunks, and I’d load all 9 segments, the one the player is in, and the surrounding ones, so when you moved, it just loaded whatever segments it needed, and the compressed segments were so tiny that disk accesses were really short. you could only move horizontal/vertical so moving SE didnt require a load of 5 segments of the map.
also, I’ve since scrapped it to just load the entire map, as one problem I did run into was I have entities on the map outside those segments, and it was too much management to know, can they move onto square X when its not in memory, it was a problem for scripted NPC’s, ie: shopkeepers who move around behind the counter trying to get to the player, and I didnt like freezing everyone when you moved off the map segment or just making them disappear… then I got rid of the PSP (psp homebrew is dead dead dead) so plenty of ram to just load any sized map I needed into one segment now. no more 32×32..
9 segments? That could be optimized down to 4 I think… You wouldn’t need any more than a corner and two edges, so long as your viewing window isn’t so large.
My original world map algorithm loaded a 48×48 size map, about 2.25k. I didn’t have the map divided in chunks, it was one long horizontal line per record, so it was 48 accesses every time you moved. This was slow enough and annoying enough I decided to re-engineer the whole system to zone-based, and I don’t plan on going back.
I recently found the various wiki’s that detail the internals of the Ultima IV and V engine, and it seems they actually stored the map in 1k chunks of 32×32, rather than in a long linear format. That makes me reconsider a bit, but loading 4 32-x32 chunks would still be around 16 record loads, and I’d probably have to write it to be a direct sector access, slightly more complicated.
Another interesting factoid is that the Ultima V map went further and started storing the chunks in smaller sizes (16×16) and also omitted chunks that were pure water. Ultima VI and VII have an actual map array and a tile array so many areas are replicated.
From the Ultima V Internal Formats link you provided:
“4) Chunk cache:
Britannia and the Underworld are divided into chunks of 16×16 tiles.
Four of these chunks are cached in at any time; you see them when you view a gem.”
I remember playing it on my Apple IIgs off a 5 1/4 drive. When you moved far enough (16 tiles?) you could hear the floppy whirring for a split second. It was super quick even on that old platform.
Too bad the Britannia Overview map link is not working. I love loading huge world maps in PSP and scrolling around. 😛
Do you by chance have a link to those U4/5 wikis you mentioned?
TIA
http://ultima.wikia.com/wiki/Ultima_IV_Internal_Formats
http://wiki.ultimacodex.com/wiki/Ultima_V_Internal_Formats
I read about Ultima 6 and 7 elsewhere, I don’t recall the links… the Exult team published some stuff about how the U7 map is put together though as part of their editor.
Thanks!
Reminds me of the thoroughness of the Wasteland deconstruction project (or what it was called).