TI-99/4a

Dramatic Presentation

Posted in CRPG, TI-99/4a, Video on July 23rd, 2010 by adamantyr – 1 Comment

Well, a lot of work the last few days…

I had to restructure the monster array into something that was actually useful. I hadn’t taken into account many of the changes made on the player side of things. In particular, to keep the attack system clean and simple, I ended up implementing fatigue for monsters as well… it’s just EASIER, because otherwise I have to special case out monsters, track which units are monsters and which aren’t, etc. Strange how that works.

I also ended up increasing the array size for monster records to… 42 bytes. I’m sure there’s a joke to be had there. :) 32 wasn’t enough, and 64 was too much. 42 bytes makes for 6 records in a sector, with a 4-byte loss. That means overall I would lose 120 bytes on the disk. Bleh, I can live with that.

Lots of spreadsheet work as well. I used one to generate the pattern codes for the monsters. It’s just easier that way than using a program, because I’m currently just using Hex Workshop to cut and paste hexadecimal strings into files. The only thing I do on the TI is generate blank files to populate with data. Sure, I could write an editor or two… and I have… but for development purposes, it’s just easier for me to plop the data in there.

I don’t have any actual combat mechanics in play yet, because I had to do all this prep work BEFORE I could do so. But it’s done now, so I can start trying to implement melee combat. I also implemented my “encounter announcement” system, and set it up to load random monsters so I could see how it looks. A big problem, unfortunately, is that monsters who blend into the background colors of the battlemap may get hard to see… there’s not much I can do about that, unless I want to abandon monster colors entirely and make all units white. How boring.

So, gotta have something to show for my work, right? Okay, here’s another movie:

The one little bug I have to address is that long sentences end up with a space at the start on the next line. This is a trickier thing to fix than you’d think.

Monster Mash

Posted in CRPG, Development, TI-99/4a on July 19th, 2010 by adamantyr – 10 Comments

Right, back on the wagon with the CRPG!

“What about that other game?” – “Shut up!”

I’ve been stuck in a philosophical design rut when it comes to the monster encounters in my CRPG, one reason I faltered for several months. I wanted to have 2D tactical combat, but I felt wretched about the fact that I could not have some things I wanted, like:

  • Monsters with varied attack types, like humanoids who are specialized in melee, ranged, or sorcery, but otherwise look alike
  • Multiple monster types in one encounter

However, after my old school game, and a rather dreary 4th Edition D&D session with too many long drawn-out combats, I think I’m starting to appreciate the idea a bit more. Enough, anyway, to get back to work.

The first thing I had to do was finalize the monster data structure. This particular pattern has undergone several revisions over the years, I originally had a 64-byte record size, but I’ve cut it down to 32 bytes by diversifying the data into other areas. Monster names (and their plurals) are stored in a large Name file with other objects, and special attack data is stored as spells in a single file which contains both effects and FX data.

I also came up with a decent “level” system. My actual monster data is just raw values, so I use a spreadsheet to track what the “average” monster at a level has for attacks, defenses, and health. I also have some type data so that creatures of particular types are immune to spell effects, will or won’t flee combat, and of course, A.I. level. My plan right now for that is as follows:

  • Dumb A.I. – Attacks the closest target, moves towards them if only has melee
  • Low A.I. – As above, but also keeps an aggravation counter for each player so a player who does more damage is singled out
  • Medium A.I. – As above, but considers ranged and spell damage more aggravating than melee damage
  • High A.I. – As above, but considers healing/buffing spells as aggravation

I worked up a list of about 25 monsters for the Demo, using 16 different patterns. (Of course I’m re-using patterns. It’s a tradition!) So far, I’m liking the diversification I’m seeing, it looks like I can do some statistical changes to make each monster a little different from each other. I have to do some infrastructure work to start actually loading this data and setting it up accordingly; I was hand-waving a lot of this before to just design the interface system.

A small feature I want to add that may end up costing a bit is the encounter announcement. Instead of just saying “3 trolls” I’d like to have it be a bit more, well, dramatic. I wrote up descriptive words for 2, 3-4, and 5+ monsters like “a pair of”, “a gang of”, “a swarm of”, and then a list of adjectives like “fearsome”, “horrific”, “repugnant” and my plan is to have it randomly construct a phrase like “A mob of fearsome trolls!” The only problem I can see with this is that the compound sentence construction may burn up some bytes I could use elsewhere… but then again, it just seems more fun. At the least, it’s an easy feature to drop later.

I’m working towards the idea of implementing melee combat effects. That’s the easy one. Then ranged and spell effects can be done, which will push the creation of the spell/special attack file section. From there, hopefully things can move along into FX. Plus I can look at memory left and try and figure out if I can still do this in 32k….

Side Journies

Posted in Adventure, Development, Screenshot, TI-99/4a on June 9th, 2010 by adamantyr – 5 Comments

Been awhile since an update… and yes, it’s update #100! And I do have something to share, although not about the CRPG…

I’ve decided to work on a smaller side project. It’s another game for the TI-99/4a, of course, but it’s a bit smaller scale than my CRPG. I got into playing Legend of Zelda on a NES emulator, and I realized that a lot of the gameplay should be easy to reproduce on the TI. And I figured, why not write my own action/adventure style game that was original, but inspired by games like Zelda and Atari Adventure?

There’s a method to the madness as well. A game like this will make very heavy use of sprites. I may even have to consider designing a sprite rotation system to overcome the 4-sprites-per-line limitation inherent in the TI’s video chip. (That means the system will detect overlap and rotate sprites in and out of the visible positions in order to keep all of them visible for at least a portion of the time. This creates the ‘flicker’ effect often seen on old 8-bit systems.)

My combat engine in the CRPG also has a lot of sprite usage for special effects, but I’ve been hand-waving a lot of that complexity aside. While I could push on and figure it out as I go along, I’d much rather do a more sprite-oriented game where things are in real time. I’d solve a lot of the timing issues and difficulties that way, and then leverage that knowledge into the CRPG design.

My working title for the game is “KnightQuest”. You can see a mocked-up screenshot on the left.

It will be much like Zelda in behavior, with a scrolling chamber map style. I’m going to really try and make the graphics “anime super-deformed” style so it matches an old Konami game in style. The main character is a knight in armor, my plan is to use 2-color sprites with animation for him. Monsters will probably be single-colored; I have to keep in mind that if I use the “half-bitmap” hybrid mode, I’m limited to 8 sprites maximum due to a strange hardware limitation. I really want music in the game as well, but I’ll have to find somebody to help me out with that, given I have the musical ability of a deaf muskrat…

The game will use the disk system of course… the TI cartridge system is incredibly nasty to work in, mostly because you have almost no CPU RAM for buffer space. It’s no wonder a lot of 3rd party developers balked at doing games for Texas Instruments.

This game should take a lot less time to develop than the CRPG. I plan on writing up a prototype map loader/scrolling routine to make sure you can move a sprite around and have it contact stuff on screen and do clean transitions from one map to another. A lot of the work will be in sprite interactions, which is what I really want to focus on. That and generating all the graphical content, of course…

Sound Design (Did I use that one already?)

Posted in CRPG, Development, TI-99/4a on March 25th, 2010 by adamantyr – 5 Comments

Slow work on the CRPG the last week or so. Got some big real life stuff going on… just put an offer down on a very nice townhouse that was accepted. You don’t own it until you close, of course, but it’s looking good so far…

What I have been doing is some re-architecture of files. In particular, I decided to have two sound files, one for travel mode and one for combat. This gives me the whole buffer (2k) I have set up to devote to combat sounds without sharing space. This means splitting the data and also identifying “overlap” sounds that are needed in both modes. I could actually store sound data in records instead of memory-images, but sound data is particularly variable-length in nature, which means I’d end up with a lot of wasted space.

Consider that a “record” would likely be 128 bytes. (Yes, some sounds can easily consume that much.) That means storing 32 sounds would take up 4k on the disk. And some sounds wouldn’t use up the whole record, which is a lot of waste. So far I’ve been able to make 2k stretch pretty well, and it’s always accessible without any disk access.

Another change was to stop storing my “mob” character graphics, the 8×8 patterns for moving units on the travel screen, in CPU memory. There were 32 patterns, for a total of 256 bytes of high memory being used. I have room in the VDP for that, so I’m moving them out there. That means modifying another memory-image file’s base address and size to include the mob graphic data. Should be easy, and the added access time for two VDP accesses (read in from VDP, write back to VDP) should be minimal compared to what it would cost pushing them out to disk. I’ve considered pushing tile data into records, which would let me have as many character sets as I have file space and file count for, but for now I’m just keeping them in a static VDP location for speed.

I also decided to mine a few more classic TI cartridges for sound effects: Parsec, A-Maze-ing, and Alpiner. Sound data is always in the GROM for these old cartridges, but finding the data can be a bit of a hunt. You could use an emulator with a debugger (such as classic99) and check the value of the sound ISR routine’s address to find them, but you’ll still need a hex editor to extract the data out. ISR sound data follows a particular pattern: Searching for >E3 or >E7 values is always good because this is the setting to make the noise generator use the third voice’s frequency as its value. Not all games use these, though, so you also want to look for sound setting patterns and low-byte values for the count of bytes (Which is 1-12) followed by a duration byte (which is usually low). So far, most TI cartridges have been well designed and have kept all their sounds in one place, rather than scattering them about.

A few interesting things I’ve discovered:

  • Parsec’s laser blast noise is nothing more than a single voice, brought from a very high to very low tone rapidly (Only 1/60 duration per change). The volume is a bell curve, louder in the middle and soft at the ends.
  • The third victory tune in Alpiner is the opening of “Promenade” from Mussorgsky’s “Pictures at an Exhibition” suite
  • Most of the sounds effects in Alpiner only use a single voice, probably so they don’t override the background music

After I finish the file changes, and make certain everything still works all right, it’s on with combat! I’ll admit that I’m a bit distracted into some sound crafting; it’s creative work and rather fun. I would rather have a “needs work” sound in place for combat than just a “beep” or nothing at all.

Slow in the Dark

Posted in CRPG, Development, Screenshot, TI-99/4a on March 17th, 2010 by adamantyr – 1 Comment

Been working slowly at the extensive regression changes to accommodate my faster attack routine. After completing it, I was pleased to see it only occupy 602 bytes, including the data arrays. I’ve reworked the stat screen generation as well, so it should display the new data, such as attack fatigue. By this weekend I should have it back up and running, and I can continue my combat engine efforts. You can take a look at the two different attack routines on a post I made at AtariAge.

While I was doing this, I also created an entry for the Short but Sweet Contest on the TI-99/4a boards at AtariAge. The contest rules were quite simple:

  • 30 lines maximum of code, 10 lines of data additional
  • Extended BASIC or BASIC (Although you really don’t want to use BASIC)

Unlike the prior contest, which only in the end had two completed entries, there are now over a dozen completed entries on the board. And they’re all VERY impressive work.

It was interesting programming in Extended BASIC again. Much to my surprise, I remembered the programming style and tricks very quickly, and I was able to put together my game “Dark Maze” in about four hours of work. Refinement and changes took longer, of course, and the game runs VERY slow at native speed, because the GCHAR calls to uncover the map are a huge speed trap. Fortunately, in the emulator of choice, Classic99, you can select “CPU Overdrive” which speeds up the computer considerably while keeping it usable by a player. My game isn’t the only one that requires this.

It’s a good board at AtariAge, with a lot of 99′ers coming out of the wood work and just having fun programming on a computer they love.

Short and Sweet (SSGC) Contest at AtariAge

Dark Maze at AtariAge

Order of Battle

Posted in CRPG, Development, Screenshot, TI-99/4a on February 14th, 2010 by adamantyr – 1 Comment

I’m working on the combat option system. So far, it’s not quite done, but debugging all the code I’ve written over the last week or so hasn’t been as bad as I feared. Generally, writing code is like building a house of cards… one bad one at the bottom causes the whole thing to come tumbling down.

The first bug I ran into was a regression; the statistic screen for player spells caused the VDP to go “wild”, switching modes and going into psychedelic colors. When this happens, it’s usually means you have a runaway video write going on, usually with a totally illegal value. The top two bits of a word are used to indicate VDP write modes, so even a negative value can cause it to go off quite spectacularly. An investigation quickly showed that I was using an archaic method to generate the spell lists, and I was able to leverage some new routines to do the job quicker and faster.

The other problem was the command going back to travel mode while still on the combat screen, among other bugs… this I traced to having subroutine returns in the wrong places. I use a stack tracked by a static register to store return addresses, allowing me to branch and link in multiple layers rather than just one. This works pretty well, but it’s easy to lose track of where you’re at. Then I found a bunch of problems with the sprites, such as them not being in 16×16 size mode. This was occurring because the contents of VDP register 1 are set to the value in the scratchpad at address >83D4. Every time you call the ROM routine to scan the keyboard, it does this replacement. Why I don’t know… fortunately it only needs to be done once.

Enemy unit targeted!

Chosing a target

As you can see on the screenshot, I finally have a working target cursor. You can’t see it, but it is blinking, courtesy of a sprite animation routine I have in the system. Unlike Tunnels of Doom, you do not move the cursor around until you are on an enemy; instead it lets you cycle through the targets. Only area-effect spells allow free targeting anywhere on the screen.

Right now, I’m still debugging each command one at a time until it’s perfect. I added a cancel routine so you could remove the last order given, or all of them. Unfortunately, I can’t provide much in the way of tracking what each order was; I don’t have the icons to really show a complicated command with only one or two letters. Attack or move in a direction, easy. Attacking THIS unit or casting THIS specific spell is quite another. For now, I use single letters, like ‘M’ for move or ‘C’ for cast spell. It will be up to the player to remember what he ordered.

Why so much trouble, tracking actions? Well, my goal here is to not have your actions occur in a sequential order by player. Instead, each individual action will be given a speed, based on the action taken and a bit of randomness. Monsters actions are determined in a similar fashion. This means that you’re not certain most of the time WHEN your actions will occur.

I got the idea for this from a reading of the old AD&D 1st edition books. In that rules system, combat was divided into strict segments. Initiative wasn’t the only determination for when things happened. Weapons speeds were a factor, and spells never went off quickly. This allowed things like interruptions and granted advantages to faster weapons. As far as I know, very few people actually played the rules this stringently… AD&D was notorious for being over-complicated, and most players house-ruled a lot of things in, or ignored what didn’t work well. (For example, critical hits are NOT in the original rules, but most players add them anyway.)

I don’t know yet how fun this system will turn out to be. I’ve reduced the randomness quite a bit from my first design; I realized that since players would be blind to the exact numbers most of the time, too much randomness would make it seem arbitrary and chaotic. Hopefully it makes the tactical system more interesting than frustrating.

A Difference Point

Posted in Code, Development, TI-99/4a on February 9th, 2010 by adamantyr – 3 Comments

Well, didn’t get around to working much on the code this weekend, but I’ll get back on it. Regrettably, I usually find I’m most motivated when I’m at work… at home I just want to relax. I really envy people who can take that work attitude home with them.

I found a new TI forum lately, at AtariAge. I’ve been there a few times in the past, there’s some great retrogamers there from all over the world. Much to my delight, they’ve started a TI-99/4a programming board, and a number of 99′ers hang out there discussing pet projects. There’s even a contest going to write a retro game! I’d join up, but my own project is not likely to make the deadline…

And now a sedge-way into some coding discussion…

An interesting programming issue on vintage systems is the need for complex mathematics, but only using integers. Granted, most old computers did have some form of real number implementation, but it was rarely used. Why? Here are the reasons:

  • Real numbers take up more memory than integers
  • Real number handling requires special routines, either in hardware or self-written
  • Real numbers are rarely needed, and not worth the trouble to implement

The TI-99/4a has a very good floating-point number system, which uses the radix 100 implementation. The numbers are 64-bit; 8 bits for the power,  with 14 significant digits in the mantissa. This particular implementation was usually seen more in accounting and business than science, but is easier to manage than bit-wise implementations that modern processors use. The TI could beat PC’s of the era in floating-point accuracy quite handily.

However, using floating point on the TI is really annoying and expensive in time and resources. All numeric variables in BASIC and Extended BASIC are floating-point, which is one reason it’s so slow. A number of routines for manipulating floating point are present in the ROM and GROM chips of the console, but accessing them requires using the XMLLNK and GPLLNK utilities provided, or writing your own version of them. (Something I have not done myself yet, and am in no hurry to do.)

Generally, what I need floating point for is usually very specific tasks. For example, determining the distance between two points on a coordinate plane. This is easily done using the Pythagorean theorem, which states that the distance is equal to the square root of the added squares of the differences between the two points, or:

 \sqrt{(x_1-x_0)^2 + (y_1-y_0)^2}.

This particular calculation could be done using the GROM routines for both power and square root, but why do that? Why not use integers? (Assuming you don’t care to have accuracy beyond a single whole number…)

Before calculators and clever programmers, there were methods to calculate square roots, as accurate as you needed them. One method is the Babylonian method, described by the greek mathematician Hero of Alexandria in the first century AD. It is a quadratically convergent algorithm, which means it doubles in accuracy with each iteration. Here’s the description:

  1. Start with an arbitrary positive start value x0 (the closer to the root, the better).
  2. Let xn+1 be the average of xn and S / xn (using the arithmetic mean to approximate the geometric mean).
  3. Repeat steps 2 and 3, until the desired accuracy is achieved.

It can also be represented as:

x_0 \approx \sqrt{S}.
x_{n+1} = \frac{1}{2} \left(x_n + \frac{S}{x_n}\right),
\sqrt S = \lim_{n \to \infty} x_n.

So, how to do this in assembly with integers? Well, first you need the deltas between the two coordinates. This is easily done with subtraction. Then you need your arbitrary value, or pseudo-root value. I decided the average between the two deltas would be all right. Technically, any positive value would work. But choosing something closer to the actual value reduces the computation cycles. Then you simply do some division and addition in loops changing the pseudo-root value each time, checking if the new value is equal to the prior value. (Ignoring the division remainder and focusing on the quotient only.) If it is, the cycle is complete and you have your distance!

Here’s the code in TMS9900 assembly. It’s VERY nice that we have multiply and division opcodes in the language; this routine would be more complicated in 6502 assembly:

* Distance calculator
* @XD - X Delta
* @YD - Y Delta
* Returns value in R0
DICCLC MOV  @XD,R0
       MPY  @XD,R0                     * @XD^2 into R1
       MOV  @YD,R2
       MPY  @YD,R2                     * @YD^2 into R3
       A    R1,R3                      * R3 = Seed value
       MOV  @XD,R4
       A    @YD,R4
       SRL  R4,1                       * R4 = (XD+YD)/2 (pseudo-root value)
DC1    MOV  R3,R1
       CLR  R0
       DIV  R4,R0                      * Divide Seed by PRV
       A    R4,R0                      * Add PRV to result
       SRL  R0,1                       * Divide by 2
       C    R0,R4                      * Compare to original PRV
       JEQ  DC2                        * If equal, value found, end routine
       MOV  R0,R4                      * Else, replace PRV and reloop
       JMP  DC1
DC2    RT

Well, that was fun. Let’s look at another…

Another floating-point function I rather wanted to have was sine and cosine. Why? So I could have sprites move in circles and arcs. Trigonometric functions are located in the ROM of the console, but of course, we want to use integers, and on the TI screen, we really don’t need all those digits anyway…

As a quick reminder, in case math class was a long time ago for you:

Sine

The sine of an angle is the ratio of the length of the opposite side to the length of the hypotenuse:

\sin A = \frac {\textrm{opposite}} {\textrm{hypotenuse}} = \frac {a} {h}.

Cosine

The cosine of an angle is the ratio of the length of the adjacent side to the length of the hypotenuse.

\cos A = \frac {\textrm{adjacent}} {\textrm{hypotenuse}} = \frac {b} {h}.

These two functions can be used to determine the exact coordinates around a center point. Radius is used as a multiplier on the ratios. The center position coordinates are just added to the results for each. Where the point for angle 0 starts depends on which one you use on which coordinate, X or Y.

This is a bit more of a difficult implementation, namely because even calculating sine and cosine using integers is a lot of work. Instead, I use a data table. This isn’t a new idea; until dedicated floating-point hardware existed in 3D video cards for the modern PC, most PC games used data tables for their trigonometric values instead of calling functions. And for the same reason we use it here, speed and efficiency!

I only need to have a quarter-circle of ratio values; the other three quadrants can be determined by inverting signs on values. The ratio divisions and angle use the range of a single byte, which is accurate enough for my purposes. By just running angles from 0-255 through the function, I can continually update a point’s position so it does a circle around the point.

The routine below will generate a position change on an X or Y coordinate to move it to the expected point for the radius and angle. Changing the radius along with the angle will make it spiral inward or outward. Increasing the angle differential in the loop will speed it up, making the angle differential negative will move in the opposite direction. Very cool!

* Data block for trigonomic values
TRGDAT BYTE 0,6,12,18,25,31,37,43
       BYTE 49,56,62,68,74,80,86,92
       BYTE 97,103,109,115,120,126,131,136
       BYTE 142,147,152,157,162,167,171,176
       BYTE 181,185,189,193,197,201,205,209
       BYTE 212,216,219,222,225,228,231,234
       BYTE 236,238,241,243,244,246,248,249
       BYTE 251,252,253,254,254,255,255,255

* R0 = Radius
* R1 - Angle (0-255)
* R2 = Position Adjustment
TRIGX  AI   R1,64                      * Add 64 to angle
       ANDI R1,>00FF                   * Keep in 0-255 range
TRIGY  MOV  R1,R3
       SRL  R3,6                       * Divide angle by 64
       JEQ  TG1                        * If 0 (first quadrant) goto TG1
       CI   R3,1
       JEQ  TG2                        * If 1 (second quadrant) goto TG2
       CI   R3,2                       * If 2 (third quadrant) goto TG3
       JEQ  TG3                        * Otherwise is 3 (fourth quadrant)
       MOVB @TRGDAT(R1),R2             * Copy ratio of angle
       SRL  R2,8                       * Adjust for full register
       AI   R2,-256                    * Adjust angle by -256
       ABS  R2                         * Make angle absolute value
       MPY  R0,R2                      * Multiply radius by angle
       DIV  @W256,R2                   * Divide total by 256
       NEG  R2                         * Negate position change value
       JMP  TG4                        * End routine
TG1    MOVB @TRGDAT(R1),R2             * Copy ratio of angle
       SRL  R2,8                       * Adjust for full register
       MPY  R0,R2                      * Multiply radius by angle
       DIV  @W256,R2                   * Divide total by 256
       JMP  TG4                        * End routine
TG2    MOVB @TRGDAT(R1),R2             * Copy ratio of angle
       SRL  R2,8                       * Adjust for full register
       AI   R2,-256                    * Adjust angle by -256
       ABS  R2                         * Make angle absolute value
       MPY  R0,R2                      * Multiply radius by angle
       DIV  @W256,R2                   * Divide total by 256
       JMP  TG4                        * End routine
TG3    MOV  @TRGDAT(R1),R2             * Copy ratio of angle
       SRL  R2,8                       * Adjust for full register
       MPY  R0,R2                      * Multiply radius by angle
       DIV  @W256,R2                   * Divide total by 256
       NEG  R2                         * Negate position change value
TG4    RT                              * End routine

That’s all for now!

AtariAge TI-99/4a Programming Forum

TI-99/4a Tech Pages (Real number section)

Wikipedia: Methods of Computing Square Roots

A Glimpse of Conflict

Posted in CRPG, Development, Screenshot, TI-99/4a on September 1st, 2009 by adamantyr – 7 Comments

I’ve had combat code written for several months, back when I was going to split it off into its own engine for development. So it was quick to port it into the travel engine. I created a stationary “monster” mob that I could tag, and ran it to see how my code worked.

Not surprisingly, I got a screen full of garbage. Going back to the source, I found a multitude of problems:

  • A copy routine I was using to generate a “grass only” battlemap for simplicity wasn’t copying words but bytes, finishing too early.
  • The unit array structure had two different expected structures, one 4 bytes and the other 6 bytes in two different places.
  • Display constants were wrong for several of the right rail elements
  • Monster data files didn’t exist, and the creation source I had for them had flaws that created bad files.

Anyway, you get the idea. The code was totally untested, so I figured I’d have plenty to work out. With most programming, having something work the first time is not celebrated, it’s in fact rather creepy and unsettling…

After a hour or so of work, though I got all the issues sorted or clipped (for now) and it finished building the combat display. Voila!

Combat Screen

There’s a number of small details, like monster colors, battlemap loading, ambush determination, unit placement, that’s being faked with constants. I’m not concerned with that stuff right now because the main focus first is to get the controls for player actions done.

The main reason is player interaction code is by far the most expensive in space and time to write. I have to find out if I’ll have room for special effects and everything left in the other portion of the game, namely, dialogue, shopping, questing, etc.

So, the next step is the basic controls, so the player can move his units about on screen, designate targets, and so forth.

Stepping Along

Posted in CRPG, Development, Screenshot, TI-99/4a on August 31st, 2009 by adamantyr – Be the first to comment

Exploring with the new LOS algorithm

Well, I’ve been working on various things, off and on… here’s a short list:

  • Mob movement. I used a clock value to keep them from moving about too frequently. I still need to add collision with other mobs to this part, as well as a chase algorithm for monsters.
  • Special terrain effects. I have four possible effects: wounding, fatiguing, poison, and slowing. They also have severity and occurrence values. Using a spell can negate all special terrain penalties.
  • Option display. Most commands still need to be fleshed out, but it’s building the display at least.

The option code is also used with the combat engine, so I’m working that into the design now. I have introduced some regressions I’ll have to fix later… boarding a boat causes a status screen to pop up, which signifies a pretty nasty sedge-way in code somewhere…

This isn’t a new problem with assembly programming, really. Regression bugs are really easy to create, unless you pre-plan your code paths to an absolute degree. I haven’t done this, so there’s bound to be some oddball side-effects as I add more functionality. Fortunately, Classic99 is a good platform for quick and dirty programming, and frankly, I make a lot more progress this way.

I really want to have the total engine finished by the end of the year… the actual game contents will take more time, but will be a lot more fun and interesting.

Pellucid Programming

Posted in CRPG, Development, Screenshot, TI-99/4a on August 27th, 2009 by adamantyr – 11 Comments

A new way of not viewing things

I decided to overhaul the LOS (line-of-sight) algorithm in my game. I decided to use the alternate algorithm that was introduced in Ultima IV for the PC.

The results are very pleasing. It’s more permissive (more viewable squares) and it doesn’t have serious slow-downs when you’re close to or near opaque tiles. It also does less calculations overall so it doesn’t drag down the rest of the game engine. You can see in the screenshot that it has some interesting effects, allowing you to see around blocks of opaque areas in some cases.

How does it work? Well, instead of tracing paths from each tile to the center, it traces from the center outward. It first does the cardinals, which are easy, checking for opaque tiles on the way out. Diagonals are a little trickier; here it has to check three squares around the target one, and if any are open it opens that one as well. I suspect I could have a “minimum number of open tiles required” here if I want to make it more demanding, but I think the current effect is fine.

The original algorithm in C is pretty simple, a set of four loops with a bunch of IF conditions. Replicating this in assembly was not so simple, but I managed it… mainly it’s trying to do it in a compact way that recycles code. I also used a data array to indicate direction and vectors.

Now that that’s done, I can move on to the command/control system, which will also be needed for combat, inventory management, and so forth.