Part 1 | Part 2 | Part 3 | Part 4
Finished Robot Minefield assembly conversion. Total time to do the conversion, remembering I had other things going on, was one week. Very positive experience. I had a couple issues to work out.
You can find the BASIC and C version, or the Assebmly version on github.
Most issues were in the computer AI, and most of the time spent coding was working on the computer AI. No real surprise since there is a lot of logic there, compared to the rest of the code.
The big issue I had was only one robot was being updated when playing the game. Turns out the issue was that not all the robots where being initialized correctly. I initialized 4 robots, but only the first robotxy array was being populated. I had not incremented the index. Using leay -1,y would have been fine, but never actually initializing Y to anything was a no no.
Then there was the fact the robots kept thinking the player was in the opposite direction. That was a matter of confusing the BNE instructions usage of the Z flag. I kept thinking if it branches, Z should be 1.
I had to solve these issues by creating small programs in EDTASM6309, which is a modified version if EDTASM. EDTASM6309 runs on the Coco3 using 80x24 mode, instead of the regular 32x16 mode. Big difference when writing source. But it was still painful using the line editor. I almost couldn't imagine anyone being able to sit down and write a huge program without writing it out on paper first!
Final size information. Source total was 26K. Assembled binary 1654 bytes. Not too bad. I wasn't targeting any particular size. 26K down to 1.6K is pretty neat to see.
$ ls -l robot2.asm random.asm text.asm robot2.bin
17067 Mar 19 01:01 robot2.asm
3027 Mar 15 14:17 random.asm
5991 Mar 18 00:53 text.asm
1654 Mar 19 01:02 robot2.bin
Screen shot of final below shows I took the liberty of increasing the size of the minefield to the entire width of the screen. The reason the BASIC version had such a small minefield was for speed. BASIC was just not fast enough to draw a large field.
Playing it feels a little like Rogue. The way the robots will not move until you do is just like how monsters in Rogue did. Also, quite by accident, the
What's next? This was a great exercise learning assembly, and learn a lot I did. I may convert this game to C next, just to go full circle. I'd also like to play around with a graphics screen. Maybe the 256x192 2 color or 128x96 4 color (would be neat to have it run on the MC-10). Not quite ready to jump into the 320x192 16 color mode of the Coco3 yet. There's some bank switching to deal with, and I'd really want to spend some time on creating some graphics for a good game.
Assembly and C This experience has reaffirmed the need to have better integration with C and assembly. You should write your low level code in assembly for speed, but the main game logic can be written in C. The logic is so much easier to write in a higher level language like C. Consider this code block in C:
for(i=0; i<robotsMax; i++)
{
xpos = robotxy[i];
ypos = robotxy[i+1];
minefield[ypos*FIELD_WIDTH+xpos] = EMPTY;
if(xpos != 0xFF)
{
if(pos<humanx)
--xpos;
else if(pos>humanx)
++ypos;
}
}
That takes all of 10 seconds to write. It is also easy to understand. The same block looks a little like this in assembly.
robotloop
ldx #robotxy ;robot coord array
ldb robot_index
aslb ;array is 2 bytes per coord
leax b,x ;point to location in array
ldd ,x ;grab robot x&y
cmpa #$ff ;is this robot inactive?
beq nextrobot ;nope, skip this one
std xpos ;xpos&ypos now contain robots location
std oldx ;remember old location
;Remove robot from current position in the minefield
jsr calcfieldpos ;find position in minefield
lda #empty
sta ,u ;erase robot from minefield
;check which way human is, and move towards him
;
;assumptions:
; 1 human will never be out of bounds, so we can safely move towards them no matter what
; 2 we first check if we are lined up with human, otherwise #1 is out the window
checkhorz lda xpos ;load the robots position again
cmpa humanx ;first check where human is on horz line
beq checkvert ;we are on the same line, check the vert now
bgt towest ;human is to the left
toeast
inc xpos ;move bot to the right
bra checkvert
towest
dec xpos ;move bot to the left
ldb robot_index ;current index
incb ;next index
stb robot_index
cmpb #robots_max ;at the end?
lbne robotloop ;nope, continue loop. B reg used in top of loop
To that end, I'm going explore the latest changes in CMOC and LWASM to see if I can figure something out. If they still don't play nice, I'll figure out the call stack in C, and figure out how to fake the C program into thinking it's calling a C routine, but it will actually call an assembly routine instead.
One could argue that you could just use inline assembly instead. I actually did this in Bouncy Ball successfully. But what if I wrote inline routines for manipulating the 320x192 graphics screen in C, then wanted to write an assembly program that used those routines? Awkward!
Copyright © 2025, Lee Patterson