Hammer and Screwdriver

What’s that title mean? That while you can drive nails and screw-in screws without tools, it’s a much longer and more exasperating process…

Tools for development are always needed. Besides my map and graphic editors, I have also wrote tools in Windows (in C# .NET) to handle some of the more automatable tasks. My text compression is an easy one; all I had to do recently to it was modify it to process a whole text fine line-by-line so that I could paste an entire block instead of one at a time.

But until I got VERY deep into design on transactions, I hadn’t realized that doing things by hand wasn’t going to cut it.

I’ve made one other decision; all NPC interaction is now tracked through transactions. This includes buying and selling items. As I was writing code, I realized it was just easier to have a single entry point for everything.

My original plan was to just hand-code the transactions myself, storing them in an Excel spreadsheet. I started to write out text files to describe each NPC and what they were doing. But as I did this, I realized how complicated it was getting. Plus, every small change would force me to re-do every single reference that was to an offset position. I would be reduced to gibbering insanity in a VERY short order if I had to do that. :)

The transaction system is a word (2-byte) language that tells the game what each NPC does. For example, the code to display a message on screen is “!MSG” followed by a list of dialogue codes. Dialogue is structured as “0-5″, which means dialogue file 0, message 5. If I have several comma-separated messages, it loads and displays all of them in a block.

Here’s an example of a text file describing a sage in the first town:

#Sage

?LOCAL_FLAG 0,Visited,NotVisited

NotVisited
!MSG 2-26,2-11
!LOCAL_FLAG 0=1
!BRANCH OptBuild

Visited
!PMSG Two,1-14,1-33

OptBuild
!OPTION 0-6,Q1,1-12,Q2
?QUEST_FLAG 1,OptBuild1,Select

OptBuild1
!OPTION 0-7,Q3

Select
!INPUT Select

Q1
!MSG 1-13,2-20
!INPUT AnyKey
!BRANCH Start

Q2
!MSG 2-25,2-18,1-6
!INPUT AnyKey
!BRANCH Start

Q3
!MSG 3-3
!INPUT AnyKey
!BRANCH Start

#Sage end

The # symbol is used to indicate the start and end of a transaction block. This allows me to add commentary in-between blocks if I need to; my intent is to have one large text file containing all of a disk’s transactions for processing.

When in a block, there are two kinds of commands, actions (!) and queries (?). Queries check values and branch to labels inside the transaction based on true/false conditions. Actions do things like display messages, alter data both in memory and on disk, start a battle, etc. Any line that has neither a ? or a ! is considered a label and gets added to a list to note it’s position in the transaction array. (For now I don’t have a “comment” symbol, but I could add one if I need to.)

Let’s go over it, shall we?

?LOCAL_FLAG 0,Visited,NotVisited

So first, we check a local flag. There are eight of them in a byte, so they are referred to by position, 0-7. Every NPC in the game has a local flag store of a byte, for tracking changes and states. #0 on all of them is being treated as the “visited” flag. This indicates whether or not this NPC has been interacted with before. This lets us have an NPC actually remember that the player has interacted with them already and respond as such. The first label after the flag number is the true case, and the second is the false case.

NotVisited
!MSG 2-26,2-11
!LOCAL_FLAG 0=1
!BRANCH OptBuild

If the player has not visited the Sage before, he has a few greeting messages. The visited flag is then set to 1, and we branch to the OptBuild label. After this, the player won’t see those messages again. When the player leaves the map, all the existing mob data is saved, including the new flag states, so returning later won’t restore them to blank.

Visited
!PMSG Two,1-14,1-33

If you have visited him already, he has a follow-up greeting. !PMSG is actually a “plural message” command. Given that the size of the party is entirely determined by the player, I wanted a message system that could deliver multiple messages based on how big the party is. The keyword “Two” indicates there are two variations, a single and a multiple. The first message is the singular party member version, the second message is the multiple party member version. There is also a “Three” version for cases where an NPC may say “You”, “Both of you” or “All of you”.

OptBuild
!OPTION 0-6,Q1,1-12,Q2
?QUEST_FLAG 1,OptBuild1,Select

OptBuild1
!OPTION 0-7,Q3

The !OPTION command specifies a number of dialogues and branches that are choices for the player to make. These are added to a local memory stack for processing later. Two are added for two questions that are always available to ask. Then we check the status of a quest flag (#1) to see if it’s true or false. If a particular quest has been completed, we add a third option.

Select
!INPUT Select

The !INPUT command pauses the dialogue and waits for the player to choose one of the pre-determined options.

Q1
!MSG 1-13,2-20
!INPUT AnyKey
!BRANCH Start

Q2
!MSG 2-25,2-18,1-6
!INPUT AnyKey
!BRANCH Start

Q3
!MSG 3-3
!INPUT AnyKey
!BRANCH Start

So for each option, the Sage has a different set of messages. It then waits for the player to press a key, then branches back to “Start”. This hard-coded label is always the beginning of the transaction.

#Sage end

And that’s the end of the transaction block. So I run my parser on it and I end up with this:

05 00 0E 04 0E 02 20 1A 20 0B 13 00 01 14 0F 00 10 0E 10 21 11 02 00 06 00 2A 10 0C 00 34 06 01 22 28 11 01 00 07 00 40 12 01 0E 02 10 0D 20 14 12 00 01 00 0E 03 20 19 20 12 10 06 12 00 01 00 0E 01 30 03 12 00 01 00

72 bytes, or 36 words, to define the entire transaction!

Transactions are all stored as 2-byte records in one large file per disk. Looking over my initial calculations of size for different things, I will end up with a couple thousand records per disk. If sizes remain at a consistent amount, I may also increase the record size and pad out some of them with zeroes for quicker load times. (I don’t think it should prove to be a particular problem; the TI disk controller loads an entire sector into VDP anyway so as long as transactions don’t cross sector lines it will remain fairly fast.)

Now I just need to write up the code to process the transactions and do all the displays… fun fun!

 

Posted in Coding, CRPG, Design, TI-99/4a | 3 Comments

Dragon Questing…

While working on my transaction stuff I’m also doing some research on the needs of the story that I’ve had on my mind for the last several years and what the engine needs to do to make it happen. But… It’s not all work. There’s some play too!

dw1Recently I got an urge to re-play the old Dragon Warrior games on the classic NES. There were a few CRPG’s on the old Nintendo, but the two most well known were Dragon Warrior and Final Fantasy. I’ve already won the latter on the classic console (I still have the blister scars from buying 99 heal potions OVER AND OVER… stupid interface!) but I never played Dragon Warrior II to conclusion, only the first and third.

dw2Why? Well… these games were NOT easy. The level and XP grinding you had to do was insane. The first game required you to sit and kill slimes, the weakest monster in the game, for around an hour before your character was leveled up enough to explore further than a few steps from the starting castle and town. If you died you lost half your gold, so exploring early was punished harshly. And you NEEDED money because all the best gear was incredibly expensive. Playing the original Dragon Warrior on the NES was more painful than fun.

dw3Dragon Warrior II was a better game overall, offering a party of three characters and a much larger world to explore. You still had to grind hard-core though; many players took advantage of a small bug in the game to obtain a valuable item over and over again and sell it to make the money to buy the best gear. I didn’t win it back in the day primarily because I didn’t own it, I could only play a friend’s copy and I couldn’t borrow it long enough to win.

So I had an itch to play these old games, but at the moment, all my video game console stuff is still packed away… Plus, my general experience with the old games is that it would mean spending a LOT of time in front of the TV, doing the same repetitive things over and over, eventually muting the game so the music wouldn’t give me a headache…

dq1Fortunately for me, there was a solution… the games have been released for the Android mobile platform! (Under their original name “Dragon Quest“) So I was able to purchase them cheaply on Google’s Playstore and download them for my tablet and phone.

Compared to the originals, the games have some differences, all to the good!

One, the graphics are WAY better. When they did the port, they actually used the Super Famicom graphics for a version that was only released in Japan. I don’t mind the original 8-bit graphics of the NES versions, but it’s nice to have an upgrade.

dq3Two, the adaptations retain the the original “Athurian” language and some of the place names. Some of the mobile ports reverted entirely to the original Japanese, where the renowned hero “Erdrick” is named “Loto”. I’m relieved to have familiar names and places, although most of the towns in Dragon Quest II have different names. Spells have completely different names entirely; most of them have sound-effect style names like ‘Sizzle’, ‘Kazing’, and ‘Thwack’. Fortunately the mobile version interface helpfully tells you what each spell does so you know what it is.

The actual in game text is also much more loquacious, with a lot of style and nuance that was absent in the NES versions. This is partly because the old cartridges were very tight on memory, but also because Nintendo stripped out anything with religious overtones. This is very fascinating to me because the games have a VERY religious theme to them.

dq2For example: the enemy in Dragon Quest II, Hargon, is actually a high priest and not a wizard. There’s a lot of discussion about how he has perverted his position against the Goddess, the “god” in the Dragon Quest universe. Instead of “Wizard Rings” to restore magic points, you have “Prayer Rings”. Magical power is directly associated with divine energy. And so forth… I actually find it really enriches the game and makes it much more fantasy-feeling.

Three, playing the games on my tablet is much more comfortable and easy than playing in front of a TV. I can move about, take it with me to different rooms, and I can even leave the game running and not have to save constantly!

Best of all… the games are much easier to play. The interface has been reworked to function very well on a touch-screen interface. The first Dragon Quest game has clearly doubled experience and quadrupled (!) gold so you can level up and advance MUCH faster.

dq4Dragon Quest II is more subtle in the improvements, but they are there. If a targeted monster dies before a character attacks him, he switches his attack to another monster. I’m pretty sure a lot of the under-the-hood mechanics for determining hit chance and damage were tweaked as well, your characters seem much stronger and more capable than the NES version, where you always felt like you were one combat away from a TPK.

Advancement, particularly spells, don’t follow the original game. I was expecting to get the Firebane (or ‘Sizzle’) spell at level 18 with the mage/warrior character, and instead I didn’t get it until level 24 thereabouts! Curiously none of the walk-throughs note this discrepancy… Your priestess character also maxed out at level 35 in the original, but in this version I got her to 36 before I won the game.

The best aspect of these games, though, is that I can finally play ones that were never released in the U.S. I’m playing them through in order; I’m now on Dragon Quest III, and looking forward to moving into the ones that started a new story arc.

Posted in Blog, CRPG, Design, Gaming | 2 Comments

Transacting Scripts

My focus remains on turning out a working and complete demo of the game… I’ve written a bunch of code I haven’t even had a chance to test yet. And I’m currently working on plotting out a long-neglected portion of the game; complex transactions with NPC’s.

I’m doing SOME stuff that isn’t entirely practical. For example, I’m finally working on finishing the title screen. I had always been stymied by the fact I didn’t really want to take the time to plot out the thing in a paint program. (ESPECIALLY in TI-Artist, which is incredibly painful to use for pixel plotting. Multi-color mode, blech!) I finally found a low-tech sneaky way to do it… Transcribe the character graphics myself by the naked eye into the bit patterns and hex-edit them into a Paint N’Print file. (Paint N’Print is my favorite editor; the zoom mode is perfect!) I can then colorize it later in the paint program.

So, about those transactions…

I decided early on not to have a text parser in the game. (Basically, a cursor which would allow you to enter key words.) My decision was based upon two things:

  1. Text parsers are a pain to implement and error check in assembly language
  2. Too much like Ultima

How can being like Ultima be bad? Well, Ultima IV is actually very simplistic; there is a maximum of 32 NPC’s in each town, and each one has a single 288 byte record to store all their conversations. (Except for special NPC’s like Lord British and Hawkwind, of course.) If you look, the actual depth of each character is shallow; each character only has two potential keywords beyond the baselines (name, job, health) and a single question and virtue that is affected by it. Ultima V is slightly more complicated with the day and night cycles and NPC schedules, but conversations are largely the same structure.

Also, there’s a certain degree of “I want this to be MY game, not just a copy of Ultima.” There’s been too poor-man copies of Ultima over the years (Gates of Delirium comes to mind…) and I want my game to stand out as something that is entirely itself.

Another aspect of my design is, I want the game world to CHANGE based on the player’s actions. All too many old CRPG’s have worlds that largely remain the same, even after the player has accomplished things. You save the town and they’re STILL talking about the danger?

So, there are two kinds of NPC’s in the game, simple and complex. The simple ones are much like the NPC’s in Ultima III; they have a single response they say and nothing more. There will also be map flags for each area so that if you have achieved certain goals, they say different things.

Complex NPC’s though, are another matter. For those, I’ve had to create my own little scripting language.

Essentially, each complex NPC has a set of local flags (one byte’s worth, one of which is always the “visited/revisited” flag) and a set of transaction records, each one word (16-bit) long. If the average length of these transactions ends up being a consistent size I may just convert them to longer records and live with a little wasted space.

Each word has a code indicating either an action or a query, with a variant amount of data after it. For example, it may check that a certain flag is set. If so, it moves to the appropriate spot in the transaction string using a positive/negative offset value, and continues transaction processing from there. It can display messages, set up options for the player to select from a list to determine a series of next results. And it can give money (or take it), items, or make changes to the party and player data as needed. A veritable transaction engine!

Here’s an example of how it may look:

TRANSACTION

OPEN:
IF Visited_Flag    (4)
    DISPLAY Intro (4)
    SET Visited_Flag (2)
    BRANCH Options (2)
ELSE
    DISPLAY Revisit (4)
    BRANCH Options (2)
OPTIONS:
    OPTION Question_1, Question_2 (10)
    SELECT Option (2)
    IF Option_1
        DISPLAY Read_1, Read_2 (6)
        BRANCH OPEN (2)
    IF Option_2
        DISPLAY Take_1 (4)
        SET Quest_Item_0 (2)
        CLEAR Mob (12)
        END Transaction (2)

Total: 58 bytes (29 words)

In fact, as I was designing the system, I realized that I could use it to replace some things in game. For example, I originally had fountains as a stock object in game for dungeons and places, that would have variant effects upon you. But I’ve been leaning towards removing them as a more “gamey” object more appropriate to old-school first-person dungeon designs, and I realized that I didn’t even need to HAVE special code for them. I can just make a fountain a transaction if I still want one!

I did briefly consider integrating shopkeepers into the same transaction system, since it’s already going to be doing a lot of heavy lifting. I decided against it in the end, though, because with shopkeepers, I have much more predictable data structures. That will let me write much more streamlined code to handle the transactions for those.

The only pain point with this approach is that coding the actual scripts up is going to be a pain. Since all the offsets are going to be localized and fixed, that means they will need to be updated with any changes. I’m going to initially try and set up an Excel spreadsheet to store this for me so I can (hopefully) just copy out a clean hex string to paste, but we’ll see how it goes…

Posted in Coding, CRPG, Design, TI-99/4a | 4 Comments

Monstrously Complicated

So I decided to switch things up a notch, and move over into monster A.I.

Why? Well, the FX spell system is now definitely working, the only tasks remaining are to implement and test out each spell individually. This won’t actually take too long. The only real complicated bit left is the alteration spells that cause battlefield changes, like creating a wall of fire.

I’m more concerned right now with removing a lot of the short-cuts and implementing the full pipeline for combat. This means actually checking for victory conditions, determining treasure, and returning back to travel mode cleanly. And as part of that… monsters actually doing stuff!

So my original architecture for monsters was, well… very ambitious. I had four different intelligence levels, the highest of which would consider spell casting as a “high threat” and target that character specifically. Every monster would have “aggravation” counters to determine who pissed it off the most. Spells would include at least two offensive and defensive spells: a ranged attack, a close attack, a self defense and an ally defense. And finally every potential action a monster would take would be weighted on priority and the best one selected each turn.

Then I realized how much code space it would take up to implement all this. I currently have around 8k of space left for code, and I still have a LOT of other stuff to implement. Creating the simplest and easiest monster A.I. to start with and then adding to it and updating it later when all the major pieces are done makes a lot more sense.

Plus, on screen, all a player is going to see is a monster take a step towards them. All that cleverness will be invisible and undetectable. Is there really a difference between a monster making a ranged attack on a character because it was the most properly weighed action, or just at random?

Plus, I don’t really want the combats to take a long time. Playing Ultima IV made me realize that when you have an awkward interface and no way to skip a lot of things, the combat can really become a hassle. (Get into a battle with reapers. You’ll see what I mean.)

And finally, it’s very VERY possible to make the monster A.I. just too damn good. If monsters all target the character who just threw a fireball at them with ranged attacks, that character won’t be alive long. It’s a general truth in most computer games that it’s pretty easy to write artificial intelligence that’s TOO good. You want it fun and challenging, not bone-grinding difficult to impossible. (Unless you’re playing Wizardry of course…)

The new simplified A.I. is pretty simple. A monster finds the closest target enemy unit and either moves towards them, targets them with a ranged attack, or targets them (or their location) with a special attack/spell. The one thing I need to add in and figure out is when a monster should use a close attack. A dragon breathing fire, for example, will want to have the player very close, and preferably none of its companions in the way!

I’m in a frame of mind now that before I release another demo, I should have as much of the game implemented as possible. That means not just the A.I. but also all the town services and everything needed to actually play the game. I really want to FINISH the game engine and start focusing in earnest on actually writing the story and designing the game itself.

Posted in Coding, CRPG, Design, TI-99/4a | Leave a comment

Burn baby burn!

And the spell is done!

It’s amazing how much effort went into getting only a few seconds of action on the screen, but wow it’s beautiful!

As part of my efforts, I also am making a few changes to how orientation is determined… I originally was going to have it random, but I realized that would be a disconnection from on screen, where you may move your party into a mob, or get attacked in turn from a particular direction. So I altered things a bit so the direction is determined that way.

Another aspect is the ambush. I realized belatedly that the Ultima mob methodology (where you see them and they move towards you) doesn’t work with ambushes because, well, you SEE them. How can they surprise you? So I’m redesigning it so that at times, hidden monsters are placed on the map and if you trigger them, it’s an ambush situation.

Work continues on the next set of spell effects, which includes a cone effect and a wall effect… I’ll want to test out all 64 spells individually to make sure they’re all satisfactory.

Posted in CRPG, Design, TI-99/4a, Video | 2 Comments

Making Room and Untangling Things

Happy 2015 everyone!

Yeesh… I’ve been working on this project for 10 years now… I seriously need to just get it done!

I’ve been pretty busy since late December moving into the new home, and getting things organized and put away. You accumulate a lot of stuff when you stay in one place awhile… and the fact I’m a bit of a pack rat doesn’t help matters. I found to my surprise that I had seven, SEVEN, TI-99/4a consoles in my garage. I’m not sure how that happened! I don’t need that many, really two is enough, so I’ll be looking to find new homes for some vintage hardware.

On the CRPG side of things, digging back into my code base meant figuring out where I had left off… as part of that, I also started to wonder how much more space I had for the game and when I’d need to start moving code into different areas.

A little hardware background first…

The TI-99/4a has a 16-bit addressing space, so it can address 64k of memory maximum. Most of this isn’t RAM; a lot of the address space is consumed by ROM’s, cartridge drivers, and other system peripherals. The console itself actually only has 256 bytes (!) of actual CPU RAM.

The only other RAM in the system is the 16K used by the video display processor. This RAM is not included in the addressing; there’s a memory-mapped ports in that very small CPU space (nicknamed “the scratchpad”) to read and write bytes to and from VDP memory. Yes, it is an eclectic computer indeed…

A fully upgraded TI-99/4a includes a memory expansion card, which adds 32k to the system. It adds 8k in one spot of memory (called “low memory”) and 24k in another (called “high memory”). When you wrote assembly language programs with the Editor/Assembler, you typically only have the 24k available, because the loaders used to load your program occupy the low memory, along with some other utilities. There IS space there, around 6k worth, but it’s tricky to get into.

Most assembly programmers on the TI write their programs to load as “memory image files”, which are just raw assembly code loaded as 8k segments directly into memory, chained together with a common file name structure. In order to convert your assembled program INTO memory image files, you used a a utility that occupied the low RAM. Which meant you still couldn’t quite use that whole space.

My solution to this problem is to reserve the entire low memory section as pure RAM for the program. I’m actually using that much RAM (or more) for the game; the maps alone consume half of it. After the program finishes loading, the entire space of memory is mine to use as I see fit, and I don’t have to worry about loaders.

But… my program is going to exceed 24k in size. I’ve known this for awhile, so I planned for it by obtaining a handy cartridge called the Super Cart. It’s basically an Editor/Assembler cartridge, but with 8K of RAM at the cartridge port address. This extra space will be enough to finish the game easily, and for those users who want to run on an actual TI, the cartridges aren’t hard to come by.

Figuring out how to create the memory image files for this proved to be a challenge, though. There are compiler directives to redirect code into different addresses, which I used, but I found out that I was unable to use any utility, in the emulator or on the TI itself, to actually create the files!

My final solution is a bit of a hack… literally. I do a memory dump out of the emulator after fully loading the assembled file into memory. I then hand-create the memory image files and copy and paste the data from the dump into files using a hex editor. It’s a bit slower than the old method, but it works, and now I have freed up plenty of space in high memory to finish the job!

On the CRPG code itself, I’m working to get at least ONE spell, fireball, working. The effect on screen should be spectacular, a ball of flame streaking towards a location and exploding, sending clouds of fire and dust in a slow spiral outwards. Implementing this has proven to be trickier than expected though…

Aside from writing the code to achieve the effect, I’ve discovered that my code to determine attack results with melee and ranged weapons got somewhat mixed into my actual effects code. I need to unravel it and clearly separate the effects on screen from the actual logic to determine WHAT effects to show and when… This also means I’ll have to do regression testing of melee and ranged combat when I’m finished…

My latest code effort was rather amusing… instead of a fireball streaking out to the targeted location, a fireball flew towards another party member and struck them causing damage! Not QUITE what I was going for…

 

Posted in Coding, CRPG, Design, Personal, TI-99/4a | 2 Comments

DELETE DSK1.CONDO, OLD DSK1.HOUSE

Hello all! Wow, it’s been a year since I last updated… it’s been a busy one!

I had some major big things happen this year. I left my current job and got a new much better one. I started commuting by bus instead of driving, which proved to be far less of a problem than I thought it would be. This lead to my next move… to buy a house!

I’ve lived in a townhouse condo for nearly 5 years, and the time has come to move on to better accommodations! In particular, a place that is much closer to my girlfriend and that will be much easier for her to move into with me. :) Also, a LOT more storage space for all the things I love, like vintage computers, gaming books, etc.

So, for the rest of this year, I’ll be working hard at packing up stuff, cleaning out things I don’t need, and getting relocated to my new home! Then I have to clean and get my condo in shape to sell, very quickly… the market right now is very good for it, but that’s a bit of anxiety that needs to be quelled as quickly as possible.

After I get settled in, I’ll have time to look at my programming projects anew…

I have worked on the CRPG off and on over this year, but made no significant updates I could share… when I last left off I was trying to get spells working in combat, which will open up a HUGE amount of testing work to do.

I’ve also been lured by the ease of Extended BASIC into other TI projects as well…

I completed a conversion of an old favorite TRS-80 Color Computer game, “Space Trek” to the TI, and have several other small coding projects in the works, including re-creating Aardvark Software’s “Quest” and “Wizard’s Tower” titles on the TI (which were commercially released but copies are impossible to find now) and my own personal project, “Kingdoms”, a turn-based strategy game similar to the titles put out by Not-Polyoptics.

See you next year from our new home!

Posted in Blog, CRPG, Personal | 2 Comments

On the first day of Christmas…

Christmas is in two days, and I wanted to take a moment to reflect on something personal…

I’ve met a very special and awesome girl. She is both a very good friend and the love of my life. I’ve been spending all of my free time with her, and honestly, it’s not enough for me.

Her list of virtues is endless. She’s pretty, sweet, funny, she loves to read, watch movies and TV shows, we have endless fun shopping together, exploring new places, and just being together. Maybe some of you know what I mean… when you have that special someone that just holding their hand and looking into their eyes… you just know.

She also loves that I’m a geek and she thinks my programming hobby is very cool. It goes without saying that she will be in the CRPG…

Everyone needs someone to love and love them, inspire and inspire them, and make them feel good about themselves and the world with all of its possibilities. I’ve found her, and I’m not going to let her go…

I love you Trisha…

Posted in Blog, Personal | 6 Comments

Cast a Deadly Spell

Long long hiatus indeed… Life’s been keeping me busy lately, namely a wonderful awesome girl. :) I’m turning my attention back to the CRPG…

When I last left off, I was doing a lot of prep work for spell casting in combat. I had to redesign the damage system to account for non-damage effects, compress effects code, redo a lot of my spell data, plug in test values for every spell to experiment with… you get the idea.

Now, it’s time to start actually writing the interface! For the record, combat in general has NOT been thoroughly tested in all edge cases… There’s going to be a lot of QA work involved there later.

I first fired up the current code and tried casting a spell. I found several glitches in the interface I had to fix, and I changed my basic spell data so I could validate that it was grabbing the right spells and populating the lists correctly. I have to be careful here because in game, there’s a theoretical maximum of 16 spells in a spellbook… so I don’t want to exceed that because it will overwrite other areas of memory. I still have some interface bugs to fix (Fireball wanted to target party members?) but I’m feeling good about the setup.

Naturally, when I looked at my code for spells actually doing something,I found to my amusement that I had NOTHING written in the action section… no wire-up at all. This actually reminds me of a recent interview that Richard Garriott (a.k.a. “Lord British”, the creator of the Ultima CRPG series) conducted where he admitted that he discovered AFTER he had released Ultima III that he had completely forgotten to write the code to wire up weapon damage to weapons equipped. He didn’t notice (as the ONLY tester) because the characters level also affected hit and damage and it seemed balanced enough. So if you play Ultima III, don’t bother equipping anything but slings or bare hands. :)

My next task will be making sure spell types and the necessary targeting interfaces are correctly wired, and then start writing the code to actually make spells happen and calculate effects AND display the FX. I probably won’t get this done before the end of the year… another New Year’s Resolution uncompleted! Oh well…

Posted in Blog, Coding, CRPG, Design, Gaming, RPG, TI-99/4a | 1 Comment

Cause And Effect

So, I finished up the changes to my effects code… although it remains to plug it in and integrate it with the main code base! I thought I would take this opportunity to show what was done and why…

Effects in the CRPG are, essentially, things that alter the status of a player, a monster, or the party in itself. This includes dealing wound damage, setting a counter for a spell effect, increasing the party’s rations, and so forth. There are around 40 effects in the game in total.

Originally, the code I wrote to process the effects was linear; each effect was a separate routine, and it used a passed register for the “address” to update, as well as values in a few extra registers. (For party effects, no passed register is needed, since there’s only one party ever.) Here’s a sample of how it looked:

* Effects subroutine
* R0 = Variable one
* R3 = Variable two
* R2 = STATE location pointer (player or monster)
* R1 = Effect
EFFCTS MOV  R11,*R10+
       SLA  R1,1
       MOV  @EFCASE(R1),R4
       B    *R4

* Reduces R0 fatigue
EF1    AI   R2,4
* Reduces R0 wounds
EF0    S    R0,*R2
       JGT  EF0A
       CLR  *R2
EF0A   B    @SUBRET

* Inflicts R0 fatigue
EF3    AI   R2,4
* Inflicts R0 wounds
EF2    A    R0,*R2
       B    @SUBRET

* Effects case array
EFCASE DATA EF0,EF1,EF2,EF3,EF4,EF5,EF6,EF7
       DATA EF8,EF9,EF10,EF11,EF12,EF13,EF14,EF15
       DATA EF16,EF17,EF18,EF19,EF20,EF21,EF22,EF23
       DATA EF24,EF25,EF26,EF27,EF28,EF29,EF30,EF31
       DATA EF32,EF33,EF34

So what’s the problem with that? Nothing… except that by the end, after crunching all the routines together along with the large reference array for each function (EFCASE), the routines take up around 426 bytes of space. Not a HUGE amount of space, even in a 32k system, but fairly significant. It also is hard to expand and maintain; I’ve had to revise effects multiple times and every time has been a hassle.

So, my new approach was to create an effects processing method. First, it’s in a separate workspace so that the registers can’t be corrupted by prior called routines. Second, all of the uniqueness of each effects is defined in a data structure, not as logic checks inside linear code. There’s more overhead writing a more “generic” processing system, but if your data is tight enough you eventually get more out of it.

The new code looks like this:

* Effects subroutine
*
* Inputs
* 
* @WORK - Effect #
* @WORK+2 - Array location for player/monster
* @WORK+4 - Value #1
* @WORK+5 = Value #2 (or #1 overflow)
EFFCTS DATA AWS,EFC0
EFC0   LI   R0,EFCDAT                  * Get effects data into R0
       LI   R9,60
EFC1   CB   @WORK,*R0                  * Check if current effect is in record
       JNE  EFC4                       * If not, jump to loop
       INC  R0                         * Increment R0 to type byte
       MOVB *R0+,R1                    * Copy type byte to R1
       MOV  R1,R2                      * Copy type byte to R2
       MOV  R1,R3                      * Copy type byte to R3
       ANDI R2,>1000                   * Get player/party bit
       JNE  EFC2
       MOV  @WORK+2,R4                 * Copy player/monster state to R4
       JMP  EFC3
EFC2   LI   R4,PARTY                   * Copy party state to R4
EFC3   AB   *R0+,@>8389                * Add Offset to R4 low-byte
       ANDI R3,>2000                   * Get byte/word bit
       ANDI R1,>0F00
       SRL  R1,8
       MOV  @EFCASE(R1),R2
       B    *R2
       JMP  EFC5
EFC4   AI   R0,4                       * Move to next record
EFC5   DEC  R9                         * Decrease effect count
       JNE  EFC1
EFC6   RTWP

* Effect "is zero"
EFZERO INC  R0                         * Set R0 to next record
       CB   @ZERO,*R4                  * Check if target value is zero
       JEQ  EFC5                       * If so, go to next record
       JMP  EFC4                       * Otherwise skip next record

* Effects add
EFADD  INC  R0                         * Set R0 to next record
       MOV  R3,R3                      * Word or byte operation?
       JEQ  EFADD1
       A    @WORK+4,*R4                * Add word value
       JMP  EFC5
EFADD1 AB   @WORK+4,*R4                * Add byte value
       JMP  EFC5

* Effects subtract
EFSUB  INC  R0                         * Set R0 to next record
       MOV  R3,R3                      * Word or byte operation?
       JEQ  EFSUB1
       S    @WORK+4,*R4                * Subtract word value
       JLT  EFSUB3                     * If negative, clear to 0
       JMP  EFC5
EFSUB1 SB   @WORK+4,*R4                * Subtract byte value
       JLT  EFSUB2                     * If negative, clear to 0
       JMP  EFC5
EFSUB2 MOVB @ZERO,*R4                  * Set to 0
       JMP  EFC5
EFSUB3 CLR  *R4                        * Set to 0
       JMP  EFC5

* Effect set
EFSET  INC  R0                         * Set R0 to next record
       MOV  R3,R3                      * Word or byte operation?
       JEQ  EFADD1
       MOV  @WORK+4,*R4                * Set word value
       JMP  EFC5
EFSET1 MOVB @WORK+4,*R4                * Set byte value
       JMP  EFC5

* Effect clear
EFCLR  MOVB *R0+,R3
       SRL  R3,8                       * Set R3 to count of bytes to clear
EFCLR1 MOVB @ZERO,*R4+                 * Clear location
       DEC  R3
       JNE  EFCLR1
       JMP  EFC5

* Effects cases
EFCASE DATA EFADD,EFSUB,EFSET,EFCLR,EFZERO

* Effects data
EFCDAT DATA >0022,>0000
       DATA >0122,>0400
       DATA >0220,>0000
       DATA >0320,>0400
       DATA >0424,>0000
       DATA >0522,>0000
       DATA >0522,>0400
       DATA >0632,>1C00
       DATA >0730,>1C00
       DATA >0802,>0F00
       DATA >0902,>1300
       DATA >0902,>1400
       DATA >0902,>1600
       DATA >0A06,>1E01
       DATA >0B06,>1F01
       DATA >0C06,>0816
       DATA >0D14,>0700
       DATA >0D10,>1401
       DATA >0E10,>1500
       DATA >0F10,>1600
       DATA >1010,>1700
       DATA >1100,>0800
       DATA >1106,>0901
       DATA >1200,>0900
       DATA >1206,>0801
       DATA >1300,>0A00
       DATA >1306,>0B01
       DATA >1400,>0B00
       DATA >1406,>0A01
       DATA >1500,>0C00
       DATA >1506,>0D01
       DATA >1600,>0D00
       DATA >1606,>0C01
       DATA >1700,>0E00
       DATA >1706,>0F01
       DATA >1800,>0F00
       DATA >1806,>0E01
       DATA >1900,>1200
       DATA >1906,>1301
       DATA >1A00,>1300
       DATA >1A06,>1201
       DATA >1B00,>1400
       DATA >1C08,>1C00
       DATA >1C00,>1500
       DATA >1D08,>1C00
       DATA >1D00,>1600
       DATA >1E00,>1700
       DATA >1F00,>1800
       DATA >2008,>1C00
       DATA >2000,>1900
       DATA >2100,>1A00
       DATA >2200,>1B00
       DATA >2300,>1C00
       DATA >2408,>1000
       DATA >2400,>1100
       DATA >2508,>1100
       DATA >2500,>1000
       DATA >2600,>1D00
       DATA >2700,>1E00
       DATA >2800,>1F00

Each effect is defined with a one or more 4-byte records. The first byte indicates which effect it applies to. The second is the type (adding, subtracting, checking for zero, etc.), whether to do word or byte operations, and whether it’s a player/monster or party change. The last two bytes are used for values or ranges to change, depending on the type.

The entire effects array is parsed each time a new effect is done. That is so every case is checked and every record potentially ran. In BASIC this would be a terrible waste, but for assembly language this is fairly fast. Given that the most effects calculated at any time is under a dozen, even a human user wouldn’t notice it taking much longer than a split second.

I haven’t crunched the numbers yet, but my initial calculations were very favorable for the size of the new Effects system… The data table is 240 bytes, and the instructions add around another 128 or so… It may not be much smaller than the original, but it’s VERY easy for me to maintain and add new records.

I also need to integrate it better into the combat system itself. My attack routines for melee and ranged are adding wounds directly; they should use the effects system instead. That will allow me to substitute in different effects, such as spells, within the same framework.

Posted in Coding, CRPG, TI-99/4a | 1 Comment