Part 41: Hex Wars: An autopsy (Part 5)
Whoops! Look like I put this update off a bit too long. Hopefully this post and the next will revive things.Hex War: An Autopsy: Part 5
When we left off, we had just defined a bunch of variables we're going to be using later. We haven't actually put any values into them yet, though. That's been kind of the theme, actually: not just preparing things, but preparing to prepare things.
So let's change that.
code:
60 A = RND(-TI / 97): P0$ = "{blue}{rvrs off}{$af:2}{down}{left:2}{lt. green}
{$df}{ctrl pound}": P1$ = "{yellow}{rvrs on}{ctrl pound}{$df}{rvrs off}
{down}{left:2}{purple}{$b7:2}"
70 PN = 1: ME = 31
80 MM = 3: REM MAX MOVES
90 KA = 1 / 48: KB = 1 / 48: KC = 1 / 32
110 FOR J = 1 TO 4: READ A
120 FOR K = A TO A + 7: READ B: POKE K, B: NEXTK, J
130 DATA 12936, 240, 240, 63, 15, 3, 3, 3, 3
140 DATA 12984, 15, 15, 252, 240, 192, 192, 192, 192
150 DATA 12840, 3, 3, 3, 3, 15, 63, 240, 240
160 DATA 12944, 192, 192, 192, 192, 240, 252, 15, 15
170 FOR J = 0 TO 63: READ K: POKE 832 + J, K: NEXT
180 DATA 0, 255, 0, 15, 195, 240, 63, 0
190 DATA 252, 48, 0, 12, 48, 0, 12, 48
200 DATA 0, 12, 48, 0, 12, 48, 0, 12
210 DATA 48, 0, 12, 48, 0, 12, 48, 0
220 DATA 12, 48, 0, 12, 48, 0, 12, 48
230 DATA 0, 12, 48, 0, 12, 48, 0, 12
240 DATA 48, 0, 12, 48, 0, 12, 63, 0
250 DATA 252, 15, 195, 240, 0, 255, 0, 0
260 FOR J = 1 TO CN: FOR K = 0 TO 1: READ CIT(J, K): NEXT K:
MAP(CIT(J, 0), CIT(J, 1), 2) = 1: NEXT J
270 DATA 8, 4, 0, 4, 8, 0, 0, 8, 4, 0, 4, 8
280 DATA 5, 5, 3, 3, 6, 3, 2, 5, 5, 2, 3, 6
The RND function returns a pseudo-random value from 0 to just shy of 1. I say pseudo-random because, like most computers even today, the numbers aren't truly random. You'd need some kind of source of natural randomness, like radioactive decay or atmospheric noise, to do that. Instead they use more or less complicated formulas whose values bounce around seemingly randomly, but actually following a sequence.
The C64 implementation of RND in particular can take three possible inputs. Any positive number returns the next random number in the sequence. However, any negative number sets the computer's place in the sequence and returns the first value from there. Keep putting the same negative number in, and you'll get the same value out. Finally, putting zero in uses the internal clock to generate a random number. Unfortunately, this isn't as useful as you might think, as it only uses a small part of the internal clock and therefore can only return a small variety of pseudo-random numbers.
TI, as I said in my coverage of 'Pests', is a variable that lets us access the timer. A = RND(-TI / 97) takes that variable, divides it by 97 (why 97? I dunno), and negates it, then feeds it to RND, which causes the pseudo-random generator to get set somewhere in the sequence based on the current internal clock. Unlike RND(0), this uses the whole internal clock, so we wind up with a huge number of possible starting places in the random list. (Folks who have used Microsoft BASIC may recognize this as being like RANDOMIZE TIMER.) We don't actually care about the value assigned to A, and from here on out we'll use RND(1) to generate random numbers. We just needed to get the random number generator to as truly random a place as we're capable of.
The next two statements on line 60 initialize P0$ and P1$ to the shapes of the player pieces for players 0 and 1, respectively. Player 0 has a blue underline on top of a light green triangle pointing downward, while player 1 has a purple overline (i.e., a line at the top of the character) underneath a yellow triangle pointing upward. (Each string contains codes for cursor movement and color changing, so you only have to print the string in the correct screen location to get both lines' worth of symbols.) For actual armies, as opposed to territory claiming markers, the strength of the army will be printed over the line characters in blue or purple, respectively.
Line 70 sets two constants. PN is used to keep track of the number of the current player; setting it to 1 here means that player 1 always goes first. ME is the value of the first dimension of the ARMY array; while it isn't used in the definition of the array (sloppy programming), it is used to make sure that array doesn't get overfilled.
Line 80, as commented, sets 'max moves', or the number of movement points each army has. It takes one point to move into friendly territory and two points to move into neutral or enemy territory (though if you only have one movement point left, you can use it to move into any cell). In practice, that means you can move each army two cells in a turn, or three if you stick to friendly territory. One of the suggested game customizations is changing this number.
Line 90 sets three constants which are used to determine the fraction of an army that could be vaporized, injured, or dazed in a turn, respectively. Battles will go faster and be more deadly if these numbers are raised.
Lines 110-160 contain data that's inserted into our custom character set. The first number on each DATA is the first address of eight into which the following numbers will be written. This replaces the graphics characters from shifted Q, W, E, and R with the four symbols used to make up the playing field: upper-right, upper-left, lower-right, and lower-left corner shapes, respectively, angled to make the hexes. A single hex is represented by this:
ER
W Q
R E
QW
As you might guess, though, there's some overlap, so the board looks more like this:
ER ER
W QW Q
ER ER ER
W QW QW Q
R ER ER E
QW QW QW
R ER E
QW QW
Lines 170-250 define the shape of the sprite we'll be using for a cursor. You may remember us setting up the sprite to use specific memory for its shape back in part 2; now we're actually loading the shape into that memory. You can see the cursor shape, a black vaguely hexagonal thing, in one of my previous screenshots. (One potential improvement for the program would be to make the sprite more closely conform to the actual cell shape. This isn't as simple as changing these numbers, though, as a sprite is 24 pixels wide and a cell is 32.)
Finally, lines 260-280 initialize the CIT array, which contains the B and T coordinates for each of the 12 (CN) cities in the game. It also marks each corresponding location in the MAP array as containing a city.
That went rather painlessly, didn't it? Just a quick one to get back on the horse. Next time, drawing the board and choosing a game type!