Jump to content
  • entries
    41
  • comments
    373
  • views
    63,961

Tank war


batari

2,005 views

Djmips mention of an old Apple II game called RobotWar got me wondering if something similar could be done for Combat tanks. Of course with the 2600, a tank language would have to be really minimal. So I've come up with a 4-bit machine code that might work. You would enter the machine code into the 2600 via the joystick. Each tank might feasibly get 64 units (nybbles) of memory. Although I'm not sure if that much is even needed.

mnemon  opcode  nybbles  description
ROTL	0	   1	   Rotate left (latched register, enables rotation once every 16 frames)
ROTR	1	   1	   Rotate right (see above)
FWD	 2	   1	   Move forward (latched, but has immediate effect)
STOP	3	   1	   Stop all motion (immediate effect)
FIRE	4	   1	   Fire gun (Immediate, but only fires if a projectile isn't being fired)
IFFIR   5	   2	   IF my projectile is in flight
IFAGE   6	   2	   IF my angle > enemy angle then branch
IFANE   7	   2	   IF my angle <> enemy angle then branch
IFNRF   8	   2	   IF enemy is within firing range then branch
IFHIT   9	   2	   IF hit obstacle then branch
IFXGX   A	   4	   IF value1>value2 then branch
IFXEX   B	   4	   IF value1=value2 then branch
GOTO	C-F	 2

IF branches are relative, -7 to +7 in memory (not including branch instruction or the following inst) and 0 means END

GOTO can go to any location 0-63. The last two bits in the opcode nybble contain the first two bits in the destination address

 

Tank registers, contain 0-15. Written indirectly, and read with IFXGX or IFXEX. Use lower 3 bits of nybble:

value   name	description
0	   X	   my X pos
1	   Y	   my Y pos
2	   ANG	 my rot angle
3	   EDST	enemy distance (firing range=8)
4	   EANG	enemy angle relative to me
5	   PDST	enemy's projectile distance
6	   PANG	enemy's projectile angle relative to me
7	   TIME	time left in game

If you are comparing two registers, leave the high bit of each nybble clear. If you want to use a constant in value2, set the high bit of value1's nybble.

 

While it is possible to hand-assemble the above code, it could get tedious.

There could be a simple compiler that could build the machine code to enter into the 2600, though it would run on a computer. I have no desire to write one for the 2600 itself...

 

Example (spin and fire)

1 ROTR

2 IFANE END

3 FIRE

 

coded as:

1704 (the rest would be F. FF indicates GOTO END)

 

 

Slightly better example (track enemy, fire if in range)

1 ROTR

2 IFAGE +1

3 ROTL

4 IFNRF +1

5 FIRE

Coded as:

1610814

 

If one can have 64 memory units, it may be possible to get some decent AI in there. I'm sure a simple Combat clone could be written from scratch, and would have 64 bytes of RAM free for AI code for two tanks that can play each other.

 

I suppose it would also be possible to pit a computer tank against a human player, if nothing else, for testing.

 

Infinite loops would not crash the game, as INTIM could be monitored in the interpreter.

 

I'm not sure how effective the AI will be with such a limited language, and I'm sure there are ways to improve it. For instance, some of the 2-nybble specialized branches could be eliminated to add extra instructions, and maybe "TIME" could be a user variable. Who knows?

8 Comments


Recommended Comments

I would suggest that a "turn-based" game where objects move on grid cells might be more practical than a smooth-motion one. Probably do something like allow each player to run 60 instructions per gametick (3 per frame), and end each gametick when either 60 instructions have been executed or a "move", "turn", "fire", or "wait" instruction is executed. Some instructions could take multiple instruction cycles (counted against the 60 limit).

 

Using grid-cell-based motion (and 90-degree rotations) would make it practical for an AI to have some sense of its surroundings. For example, something like:

0 if enemy_ahead
1 fire_cannon
2 elseif space_to_right
3 rotate_right
4 elseif space_ahead
5 move_forward
6 else
7 rotate_left
8 endif
9 goto 0

I'd figure on using one byte per instruction; each line above would be a byte, and there could be maybe 32 instructions per person max. Note, btw, that the "if_enemy_ahead" would indicate whether the enemy was straight ahead during the current game step; the enemy could very well move at the same time as the shot is fired, causing the shot to miss.

 

Maybe that would be enough to be interesting, or maybe the game would be better as a single-player challenge: given a maze with certain objects to be collected and others to be avoided, write a program of a specified size to perform the required task within a specified time.

Link to comment

I would suggest that a "turn-based" game where objects move on grid cells might be more practical than a smooth-motion one. Probably do something like allow each player to run 60 instructions per gametick (3 per frame), and end each gametick when either 60 instructions have been executed or a "move", "turn", "fire", or "wait" instruction is executed. Some instructions could take multiple instruction cycles (counted against the 60 limit).

That's an interesting idea for a game. It becomes more of a puzzle game. It's still a "zero-player" game like RobotWar and it might have a wider appeal than what I'm proposing.

 

But widening the appeal is not necessarily the point. The turn-based approach is getting further from what RobotWar was all about. RobotWar was a real-time, smooth motion game, and you had even less information about other robots than I proposed.

 

Here's a page about RobotWar that has a downloadable manual to get an idea of what the "players" had to deal with.

 

The better robot programs used "interesting" methods to find more information about the other robots. I proposed more information by default because of the limitations of the 2600, though I'm sure I left off some key element. I'm thinking now that the following instruction:

IFNRF   8	   2	   IF enemy is within firing range then branch

Should be replaced with:

INCU   8	   1	   USER=USER+1

And the "TIME" register should then become "USER"

 

This would allow one to get more information about other robots with creative programming. Yeah, I know that just giving INCU don't seem useful, but you can assign USER to any value you want with a loop.

Link to comment

Could you connect two 2600s and have them fight each other? I know there have been ideas tossed around that you could connect them via the player 2 joystick port.

 

Have different programmers come up with their own AI schemes, but make them compatible so they could each take their cart, plug it into a console, and have the two consoles connect and the AI battles it out.

 

Not that this would be useful as a game or anything, but just kind of a fun experiment.

Link to comment

Could you connect two 2600s and have them fight each other? I know there have been ideas tossed around that you could connect them via the player 2 joystick port.

 

Have different programmers come up with their own AI schemes, but make them compatible so they could each take their cart, plug it into a console, and have the two consoles connect and the AI battles it out.

 

Not that this would be useful as a game or anything, but just kind of a fun experiment.

In theory, yes. I've talked about this in the past. The problem is always that I need two consoles and two programmable carts to actually test everything, which significantly slows the development process.

 

But Tank war would be different, in that players wouldn't need to connect two consoles - just post their tank programs and you could set up your own game to battle it out.

 

E.g., one player posts the following tank program:

 

DFF43398983988919818989DE898F9898FD9D8E

 

You enter it in the console and battle it out.

Link to comment

I don't know why I didn't think of this before, but this might be a good application for the SaveKey/AtariVox. The biggest limitation would be that the player would only be able to use one keypad instead of two.

Link to comment

I don't know why I didn't think of this before, but this might be a good application for the SaveKey/AtariVox. The biggest limitation would be that the player would only be able to use one keypad instead of two.

Good point. I'm hesitant to write anything that requires the Avox, but it would be handy to be able to save a tank's data without having to manually enter it every time.

 

Also, a keyboard controller is a good idea as an option, though it's too bad they only have 12 keys - not ideal for hexadecimal code. I suppose one could be given the option to enter octal code. It would be 25% longer but easier than trying to make the keyboard keys multi-purpose.

Link to comment
I suppose one could be given the option to enter octal code. It would be 25% longer but easier than trying to make the keyboard keys multi-purpose.

 

Octal's kinda messy. Moreso in many ways than hex. If things were mapped sensibly, decimal might actually not be so bad (e.g. if there was one opcode that took an operand 0-99, fourteen that took an operand 0-9, and sixteen that didn't take any operand). Note that because the first digit of each byte would have to be a "0", "1", or "2", the other keys could be used for navigation when not typing in a new opcode.

Link to comment
I suppose one could be given the option to enter octal code. It would be 25% longer but easier than trying to make the keyboard keys multi-purpose.

 

Octal's kinda messy. Moreso in many ways than hex. If things were mapped sensibly, decimal might actually not be so bad (e.g. if there was one opcode that took an operand 0-99, fourteen that took an operand 0-9, and sixteen that didn't take any operand). Note that because the first digit of each byte would have to be a "0", "1", or "2", the other keys could be used for navigation when not typing in a new opcode.

Well, if you convert each byte to 3 octal digits, yes, it is messy. But I was thinking more of converting to octal at the bit level so all characters could be 0-7. Anything but hex would, of course, make it impossible for those to hand-assemble their code on the fly, though it seems unlikely that anyone's going to do that. If I assume nobody's going to hand-assemble any code, I can have an assembler slip in a CRC at the end.

 

It seems to me now that the 12 keys could be based on 10-key with 8 and 9 given practical uses:

7	←	→
4	5	6
1	2	3
0	Del  End

End would check CRC, which would most likely prevent accidental ending.

Link to comment
Guest
Add a comment...

×   Pasted as rich text.   Paste as plain text instead

  Only 75 emoji are allowed.

×   Your link has been automatically embedded.   Display as a link instead

×   Your previous content has been restored.   Clear editor

×   You cannot paste images directly. Upload or insert images from URL.

Loading...
  • Recently Browsing   0 members

    • No registered users viewing this page.
×
×
  • Create New...