Garbage Time

Despite the lack of posts, I have not been idle…

After a lot of testing, I’m satisfied with my battlemap generator. I’ve populated the data table with some entries that are undefined (graphics sets in later parts of the game) but all the core graphic work is done. I still have other portions of the encounter engine to test, but I can do that in live running rather than in a test program.

The next step? Running the full game and getting into a fight. Then putting a breakpoint in the debugger to try and figure out where it crashed and why. Repeat repeat repeat… 🙂

Playing World of Warcraft, while a bit of a time-consumer, is also useful for thinking about game mechanics. A bit of a side bar on that…

Since I haven’t played since the Pandaria expansion, I’m enjoying a lot of the new ideas they’ve introduced, like garrison campaigns. The stat/level squishing that occurred shortly after Pandaria and more recently before Battle for Azeroth also helped to make the game stats less crazy; before your hit points were up in the 500k range! They actually ran into integer overflow problems with raid bosses; because the base code was still using 32-bit integers and the raid bosses hit points were set high enough to exceed the max positive. I’m noticing though in Azeroth that item levels and stat bonuses are getting out of control again…

I was worried about the level scaling at first, but it works pretty well. You can now do either Northrend or the Outlands from 60-80, and Pandaria or Cataclysm areas from 80-90. I’m certain they’ll be doing something similar for Draenor and Legion soon so you can play either area from 90-110, there’s more than enough content to do it and stick to one. Funny how Draenor suffers the same issues that Burning Crusade did; it’s a bit of a “side trek” to visit and players get bored and resentful having to play through the content with their alts. Legion content is VERY desirable to play through, as it’s the only way to unlock the new races to play.

However, I do NOT like the dungeons, and I haven’t for awhile. The original classic game tried to introduce some interesting story points and offered very non-linear designs. Modern dungeons (pretty much since the first expansion) are extremely linear and dull. Contrast the original Blackrock Depths instance, with a colorful and huge dwarven city, to the dull linear design of Grim Batol and you can see the difference. My favorite thing is to out-level the dungeons so I can go in and just solo them if I need to. Otherwise, I have to just run the dungeons with a bunch of strangers using the finder who are ONLY interested in clearing it as quick as possible and getting gear.

Anyway, back to my CRPG…

I originally had my experience levels going up exponentially; I decided to relax that a bit and try and make it less step at the higher levels. Time and play-testing will also help adjust these values.

The most important often-overlooked aspect of CRPG design is pacing. You want to make sure your world is not just large but also rich in content. You want to avoid the following:

  • Having a big map that has only one town and a bunch of monsters, nothing interesting to explore in various corners
  • Your characters have the most powerful weapons in the game before the halfway mark
  • You’ve reached maximum level long before the endgame
  • Towns that are simply repeats of other towns offering basic services
  • Completing quests changes nothing other than your party; the game world seems unaffected, peasants still complain about the evil thing you defeated, etc.

I’ve no doubt that my present material for the game will go through some serious revisions as I go along. I’ve already noticed places where I’ve repeated myself a bit, and I want to make sure I make everything fresh and interesting.

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

Random Thoughts

And now a side-trek on random number generation…

Pseudo-random numbers have been a part of software design for awhile. It’s a field that is still very heavy in the mathematics area, because a large part of it is about trying to design an algorithm to create a random value quickly but also predictably.

However, if you started with BASIC in the old days, all that was hidden from you. You just called a RAND or RND function and got a number. The better BASIC languages offered a way to change or update the random seed, but otherwise you just used what they gave you and didn’t know what it did under the hood.

For most 99’ers, the earliest best example of an assembly random number generator came from the source code for Tombstone City, a cartridge game from Texas Instruments. The source code was provided with the Editor/Assembler package as a learning tool. (Sadly, as a teenager, I wasn’t aware of this. Studying source code may have made my early frustrations with assembly programming easier. Ah well…)

Here is the routine from it:

RANDNO LI   R4,28645
       MPY  @RAND16,R4
       AI   R5,31417
       MOV  R5,@RAND16
       RT

As you can see, not a lot to this one. Let’s say you started with a random seed of 0 and went a few cycles:

  • 0 * 28645 = 0 + 31417 = 31417
  • 31417 * 28645 = 65149 (low word) + 31417 = 31030
  • 31030 * 28645 = 55118 (low word) + 31417 = 20999
  • 20999 * 28645 = 26947 (low word) + 31417 = 58364

This is pretty much what every pseudo-random algorithm does. It generates a sequence of values using the prior value as a key to generate the new value. It also creates a predictable sequence, which can be useful in situations where you want the randomness to be more controlled. It also produces an exact sequence of 65536 different values; changing the seed value just changes where you start in the sequence.

However, it consistently produces an even/odd pattern. In some cases, this may be desirable! But for most random routines you want the even/oddness to be variant.

A simple fix, which is what I introduced and it did the trick at the time, was to throw in a bit shift of an odd value on the random seed, as follows:

RANDNO LI   R4,28645
       MPY  @RAND16,R4
       AI   R5,31417
       SRC  R5,5
       MOV  R5,@RAND16
       RT

By shifting the bits an odd number of times it broke up the even/odd cycle. It however still creates a predictable sequence since you are always shifting by a predictable amount.

So my next solution was to have the bit shift be determined by an outside factor.

The TI-99/4a has a vertical sync clock which ticks at 1/60 of a second. By using that value to determine the bit shift, I was able to have it shift to a completely different place in the sequence in an unpredictable fashion:

RANDNO LI   R4,28645
       MPY  @RAND16,R4
       AI   R5,31417
       MOV  @CLOCK,R0
       ANDI R0,>000F
       SRC  R5,0
       MOV  R5,@RAND16
       RT

@CLOCK in this instance is a word that I increment every time there is a vertical sync.

But even THIS one is not perfect… because when I tried to use it to generate random map content, which involved consecutive calls to the random function in a tight time frame when the vertical clock did not actually change, it created strange symmetric patterns every 4th or 5th iteration.

So I decided to change the routine, for the map generation at least, to a different approach:

MASK   DATA >B400
RANDNO MOV  @RAND16,R0
       SRL  R0,1
       JNC  NOCARR
       XOR  @MASK,R0
NOCARR MOV  R0,@RAND16

This rather clever routine avoids the use of multiplication (which is unavailable in many assembly languages of the era, and is cycle-costly) and uses XOR instead to invert the bits when there is no carry. This creates a predictable sequence that varies high and low.

Let’s step through it a bit, starting with 0:

  • 0 >> 1 = 0, No carry, XOR >B400 = 46080
  • 46080 >> 1 = 23040, No carry, XOR >B400 = 60928
  • 60928 >> 1 = 30464, No carry, XOR >B400 = 49920
  • 49920 >> 1 = 24960, No carry, XOR >B400 = 54656

So this one worked better, since it wasn’t relying upon the clock value. Until I reached a particular map where I was placing random tiles in a smaller area. Suddenly every single map produced the EXACT SAME pattern of tiles in an odd diagonal line. I realized then that I had to go back to the drawing board.

The solution (at present anyway) is to use a different clock. I needed one that counted faster than 1/60 of a second, and wasn’t reliant upon the vertical sync, which requires you to have interrupts enabled to update the value.

I found one in the interface chip the TMS9901, which has a 14-bit counter value you can set. It decrements it at clock-cycle speed so it’s VERY fast. It requires a bit of setup in your program to initialize with a value, but after that it’s readily accessible. After I put this in, my random values are EXTREMELY random and satisfying.

* Somewhere at program start
* Set up 9901 counter
       CLR  R12             * CRU base of the TMS9901
       SBO  0               * Enter timer mode
       LI   R1,>000F        * Set counter to 15
       INCT R12             * Address of bit 1
       LDCR R1,14           * Load value
       DECT R12
       SBZ  0               * Exit clock mode, start decrementer
* Random function
RANDNO LI   R4,23729        * Load with 15-bit value
       MPY  @RSEED,R4       * Multiply by the random seed
       AI   R5,31871        * Add a 15-bit value to the lower word
       CLR  R12             * CRU base of the TMS9901
       SBO  0               * Enter timer mode
       STCR R0,15           * Read current value (plus mode bit)
       SRL  R0,1            * Get rid of mode bit
       SBZ  0               * Exit clock mode, decrementer continues
       SRC  R5,0            * Rotate seed based on clock value
       MOV  R5,@RSEED       * Copy back to RSEED
       RT

Alternatively, if I was coding in a system that lacked such a handy counter, I would try and create some kind of clock that is incremented by other parts of my program that I could use in it’s place. The most important aspect of it is that it can’t be in the random function itself!

One other option, that occurred to me afterwards, is that I could have opened the interrupts on the TI during the random function so that the clock value would get incremented. I’m reluctant to do this, though, because in many places I’m doing more during interrupts than just a clock, and they would steal resources away from map generation.

So for now, I seem to have enough randomness to use everywhere in the CRPG. 🙂

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

Battling Bugs

Okay, a couple new things…

One, after all the excitement and talk of the latest expansion for World of Warcraft, I decided to renew my subscription after over four years just to play a bit. I have two and a half expansions of material to enjoy before I even buy the latest one, so it’s slow going but fun! You can criticize Blizzard on a lot of things, but they are damn good at making a fun game.

All of that doesn’t mean the CRPG has dropped off, far from it! I needed something to get through the myriad of frustrating bugs in my battlemap generator system. I decided I didn’t want to risk testing the code in the game itself, but instead write a prototype to create the maps so I could observe how they looked. After a LOT of assembler debugging to find video over-writes and other problems, it’s done and working well! This will allow me to test different graphics combinations, and add new ones as needed, to keep the maps looking fresh and interesting. Here’s a small sampling of some:

Lastly, I had a very unexpected and welcome gift come my way…

When I was at Fest West 18′ a few months back, we had a contest and the prize I won was a TIPI sidecar controller. I graciously turned it down and took an alternate gift because I am using my Peripheral expansion system and the sidecar isn’t advantageous for it.

So the creator of the TIPI system contacted me a week ago to say he’d finished the PEB card version of it, and he was going to send me the card! I had to purchase my own Raspberry PI unit and associated components (power supply, Micro SDHC card) but that was not expensive or difficult on Amazon.

After figuring out how to put it together and get it in, I discovered it’s a fantastic device. I am able to access the “file system” from my local PC laptop and can quickly and easily copy TI files from there right to the drive. This allows for VERY fast turn-around in testing the game on the hardware, and it’s a perfect replacement for the drive system, given that the disk controllers are getting scarce, and these days, you WANT some compatibility with modern devices.

You can find all the information on TIPI you need right here!

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

Trades and Revisions

Churning onward…

As part of my work coding up traps for the encounter module, I realized I had to make my damage approach consistent. There’s effectively two kinds of damage reduction, one for wounding effects and one for every other kind of effect such as poison, charm, and so forth. So I centralized damage determination in the various modules to make it so the same rules apply everywhere.

I also realized my statistic screens for players need some serious revisions. To make it similar to the monster stat screens, I’m restructuring one so you are told explicitly your stats for melee, ranged, and defense. I won’t throw away the work I did designing the item stat generation with the little blocks indicating special qualities and such. Instead I’ll move it into the examine option for inventory.

I also need to write up trading code for the encounter module. Items in combat are randomly determined and can’t be recovered later if you turn them down. So I need to make sure you can trade off items to different players and, if need be, discard an item from your backpack to make room. (No, I can’t have chests of items generate in travel mode where the combat occurred. There’s a multitude of technical reasons why that’s impossible.)

I may need to go back to the travel module and make some changes there too. My original design was built around the idea of an “active” player. Whoever was active would be the one who picked up items, used his skills for trap detection, locks, and other things. But I’m wondering if this is going to cause trouble and confusion later. I originally extended it into the manager module but I’m going to change that so it prompts you to select a player for given operations instead.

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

Combat Complete

The combat module is finished! I ended up moving combat end determinations into the Encounter module, so that work will be completed there.

Now that I got some code space to spare, I may have a complex “You found a chest, open it?” event at the end of combat. Another opportunity to throw in some traps… 😉

 

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

Now serving Monster #43…

Made a nice push and got a LOT of code work done. All that’s really left in the Combat module is alteration spells (which requires retooling them for the new data design, as well as adding some new stuff like summoned creatures) and updating the combat end to include experience.

I side-stepped this weekend and worked on updating the monster data so that I could encode it from a text file instead of using a spreadsheet with DEC2HEX conversions. I’ve found this is a much easier way to update data because I can use my tool binaries to directly copy data into the files for very quick turn-around. This will be very important when I get into play-testing the combat engine, because I need to make sure monster statistics are easy to change. Right now, I’m pretty sure their health values across the board are going to be too low to make combat interesting, but we’ll see.

I had such success with my monster encoder tool, in fact, that I decided to also write one for map data as well. This has been a bit of a pain for awhile, so it was a relief to be able to write one so I didn’t have to hand-edit files with a hex editor in order to update small items. The only part of map files that’s still hand-edited is elevation data, because it’s RLE-encoded and with only a few maps having elevation, it’s easier to manage those directly than try and write an engine to do it. (I calculate the length of a map’s elevation then arbitrarily decide what sector it goes into in order to pack the data as efficiently as possible.)

Both these changes accomplished something else, the ability to refer to monsters and mob blocks in an abstract way. My mob and map data had to include monsters as fixed numbers originally, but when I renamed one and reshuffled the list they all ended up out of order. So by referring to a monster as “Ogre” instead of monster #53, it’s a HUGE reduction in time to add, subtract, or update monsters. Being able to refer to monsters that spawn by name is great because at a glance I know what monsters are assigned to a map and can make tweaks quickly and easily.

After I move some graphics around, I’ll be back on the combat module to wrap it up so I can focus on the encounter module. After that it’s a nice long debugging cycle of getting the game to run properly (fixing many bugs I’ve no doubt introduced with new code) in all it’s phases.

UPDATE:

Some mock screenshots of monster statistic screens. They can only be viewed when a particular spell is used.

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

Do the Split

So it turns out that 12k was NOT enough for both combat encounter generation and management. I had 1K left and still a ton of things to write. So I’m splitting the encounter portion into a separate module.

Fortunately, this is easy to do. The “encounter” module will do the following:

  • Load monster data from disk
  • Load monster graphics from disk
  • Load player graphic data from extended memory
  • Determine how many monster types are present and how many of each type
  • Populate the data arrays for monsters with their randomly determined health and stamina
  • Determine the terrain type of the battle map and set it up
  • Load all graphic data from extended memory to support battlemap
  • Place all units on battlemap
  • Populate all necessary maps with unit and obstruction data
  • Create encounter text to display

It then immediately shifts to the Combat module.

Doing so has already freed up nearly 4K which should be enough to get the job done. It also nicely separates the encounter work (which has a large amount of influence from content) from the actual battle management.

This means I have to increase the base size of my program file to accommodate another module. I may add another 24K just so I have a little extra data space; I already load in 8K segments from disk so it doesn’t hurt to add extra for graphics space, sound data, or other data needs that may come up.

I had to restructure some basic models for how player data was stored as well, as it turned out it was better for combat determination to have the system treat players and monsters as agnostic entities. This required moving some data around, which will probably create some fun regression errors for me to fix elsewhere. 😛

Funny enough, I found myself nearly repeating the same mistake that Richard Garriott did in Ultima III, which was to forget to include weapon/armor values in attack/damage calculations! 😀 A big change from the prior design is now it adds in all the calculations dynamically rather than trying to store them in arrays ahead of time.

I’ve updated my Progress page to reflect the new module as well.

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

Halfway Point

So, now that it is July, the year is more than half over. My intention was to have the game complete by the end of the year. Will I make it? We will see…

I changed tactics and stopped working on the encounter engine, which was devolving into creating graphics and other more content-related work. Instead, I went back to trying to convert existing combat code. This turned out to be a good idea; a lot of elements need to be figured out in the new design, plus I need to find out if my 12k segment for combat will be large enough for everything.

I had to make a few changes to the FX engine code to support boss monsters, as well as convert it to read FX data from CPU memory pages instead of loading them from disk. Fortunately the code beyond this is largely unchanged.

I also need to add support for new concepts, like summoned creatures by players. I realized I could just have them be new monsters added to the unit list, but with the “charm” effect enabled. One the charm clock runs out they turn hostile on the player.

On the subject of units, I redesigned my arrays to store the unit type (including if they are “dead” or not, a player or monster, etc.), unit graphics (A zero means they’re invisible, don’t render them on screen), and unit coordinates. (A -1 means they’re “off map”, which only players can do, fleeing the combat.) Hopefully the combination of these three will cover all my bases!

I may do one extra thing, which is have player data copied from their normal arrays into a block adjacent to the monster state blocks. I’m having to write a lot of “specialty” code to do considerations between player vs. monster, and it’s getting annoying.

I’m hoping by the end of this month I’ll have the bulk of the code converted and can return to encounter design/generation.

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

Working On It

Another quick update…

It’s been a busy couple of weeks, and at the end of this week I’m going to ACE Comic Con in Seattle, so it’s going to stay that way!

I’ve been working on the dynamic battlemap generation. The work is going slowly because I’m designing the algorithms to create the maps in tandem with graphics updates to support them. I think the end result is going to be VERY cool but right now there’s just nothing to show off.

The combat engine is going to be a bigger job than I anticipated, because I’m also re-designing the main screen from my original code, and there’s a lot of new additions and changes from the pre-AMS code. (Multiple monster types, big monsters, and so forth.)

Update: Here’s are some mock screens of combat just for fun!

Posted in CRPG, Design, Personal, Screenshots, TI-99/4a | 1 Comment

Crickets…

Sorry for the lack of updates recently. Work has been brutal and the weather (sunny and VERY warm) has necessitated spending more time outdoors mowing and doing basic yard maintenance.

I did a little testing and found some bugs in various places. I’ve written up some encounter code for combat to have the display tell you things like “You face a raging bear!” or “You face an acidic slime and 2 giant rats!” I encoded pluralizing monsters as a single code so that I could still have unique cases like “wolves” verses “wolf” and the typical “just add an s on the end” case.

Despite being distracted by the idea of writing a more complete version of Donkey Kong for the TI, pushing on with the CRPG work!

 

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