Robot Minefield Assembly done

Date: 2018-03-19 06:21:39

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 to dismiss a message is how it is done in Rogue. I kinda gives me an idea to try to make a Rogue like. I'll have to think about it a little.

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) 
        else if(pos>humanx)

That takes all of 10 seconds to write. It is also easy to understand. The same block looks a little like this in assembly.

                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
                ;       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
                inc     xpos                    ;move bot to the right
                bra     checkvert
                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 © 2019, Lee Patterson