Recently I’ve been distracted by one of my other hobby, wargaming. There has been a discussion on USENET about freeware space combat games. Having designed one a few years back, I quickly did an ASCII version and posted it. This then lead to further distractions in that hobby. Feeling guilty about “abandoning” the QL, I wanted to come up with some program that would tie the two hobbies together.
Most wargames are based on hex maps. One of the difficulties in putting wargames on a computer is the hex map system. A square map system is nothing more than a 2D array. But a hex map system, with each cell having 6 neighbors is takes some work. It’s workable with a square map, by extending the rules for what squares are “next” to the current square.
After pondering over this, and pursuing how I would represent a hex map in an array, I discovered that I really don’t need to store the hex map, just a way of determining what hex was next to the current hex. Anything relating to what is in a hex can be stored in an array, looked up by the hex number.
These routines will determine two things, what hex is next to the current hex (given any direction), and the distance (in hexes) between two hexes. Determining what hex is next to another hex was fairly easy. Finding the proper distance was a more challenging task. I first tried the distance formula used in square coordinate system. This had some flaws.
I then tried a different approach based on simple common sense about hexes. This worked until I got back to the program the next day and THEN saw that it did not work. Back to the distance formula. After much plugging and chugging, plus some tinking with the distance formula, I found an algorithm that worked (at least in the cases that I tested). I found the general case that failed in the plain distance formula and found a fix for these cases. I’m pretty sure that it all works fine, but I have not tested all cases.
The hex number system that I used came from my favorite wargame, OGRE. I have not played with other numbering systems. Each hex number is two numbers combined, a column number and a row number. 0102 is column 01 and row 02. Below is a quick drawing of the numbering system.
__
/ \
__/ Y \__
/ \ / \ /|\ Hex X = 0102
/ X \__/ Z \ | Hex Y = 0201
\ / \ / Hex Z = 0302
\__/ A \__/ N Hex A = 0202
\ /
\__/
100 DEFine FuNction even(num)
110 true = 1 : false = 0
120 IF (num MOD 2) = 0 THEN
130 RETurn true
140 ELSE
150 RETurn false
160 END IF
170 END DEFine
190 DEFine FuNction odd(num)
200 true = 1 : false = 0
210 IF (num MOD 2) > 0 THEN
220 RETurn true
230 ELSE
240 RETurn false
250 END IF
260 END DEFine
270 DEFine FuNction hex_north$(hex_num$)
280 LOCal column$, row, temp$
290 column$ = hex_num$(1 TO 2)
300 row = hex_num$(3 TO 4)
310 row = row - 1
320 temp$ = row
330 IF LEN(temp$) = 1 THEN temp$="0"&temp$
340 RETurn column$&temp$
350 END DEFine
360 DEFine FuNction hex_south$(hex_num$)
370 LOCal column$, row, temp$
380 column$ = hex_num$(1 TO 2)
390 row = hex_num$(3 TO 4)
400 row = row + 1
410 temp$ = row
420 IF LEN(temp$) = 1 THEN temp$="0"&temp$
430 RETurn column$&temp$
440 END DEFine
450 DEFine FuNction hex_ne$(hex_num$)
460 LOCal temp1$,temp2$,column,row
470 column = hex_num$(1 TO 2)
480 row = hex_num$(3 TO 4)
490 IF odd(column) THEN row=row-1
500 column=column+1
510 temp1$ = row
520 IF LEN(temp1$) = 1 THEN temp1$ = "0"&temp1$
530 temp2$ = column
540 IF LEN(temp2$) = 1 THEN temp2$ = "0"&temp2$
550 RETurn temp2$&temp1$
560 END DEFine
570 DEFine FuNction hex_se$(hex_num$)
580 LOCal temp1$,temp2$,column,row
590 column = hex_num$(1 TO 2)
600 row = hex_num$(3 TO 4)
610 IF even(column) THEN row=row+1
620 column=column+1
630 temp1$ = row
640 IF LEN(temp1$) = 1 THEN temp1$ = "0"&temp1$
650 temp2$ = column
660 IF LEN(temp2$) = 1 THEN temp2$ = "0"&temp2$
670 RETurn temp2$&temp1$
680 END DEFine
690 DEFine FuNction hex_nw$(hex_num$)
700 LOCal temp1$,temp2$,column,row
710 column = hex_num$(1 TO 2)
720 row = hex_num$(3 TO 4)
730 IF odd(column) THEN row=row-1
740 column=column-1
750 temp1$ = row
760 IF LEN(temp1$) = 1 THEN temp1$ = "0"&temp1$
770 temp2$ = column
780 IF LEN(temp2$) = 1 THEN temp2$ = "0"&temp2$
790 RETurn temp2$&temp1$
800 END DEFine
810 DEFine FuNction hex_sw$(hex_num$)
820 LOCal temp1$,temp2$,column,row
830 column = hex_num$(1 TO 2)
840 row = hex_num$(3 TO 4)
850 IF even(column) THEN row=row+1
860 column=column-1
870 temp1$ = row
880 IF LEN(temp1$) = 1 THEN temp1$ = "0"&temp1$
890 temp2$ = column
900 IF LEN(temp2$) = 1 THEN temp2$ = "0"&temp2$
910 RETurn temp2$&temp1$
920 END DEFine
930 DEFine FuNction hex_dist(hex1$,hex2$)
940 LOCal temp1, temp2, col1, col2, row1, row2, dist
950 col1 = hex1$(1 TO 2)
960 row1 = hex1$(3 TO 4)
970 col2 = hex2$(1 TO 2)
980 row2 = hex2$(3 TO 4)
990 temp1 = col2 - col1
1000 temp2 = row2 - row1
1010 dist = temp1^2 + temp2^2
1020 dist = SQRT(dist)
1030 IF INT(dist) < dist THEN
1040 IF row2 = row1-1 THEN
1050 dist = INT(dist)
1060 ELSE
1070 dist = INT(dist)+1
1080 END IF
1090 END IF
1100 RETurn dist
1110 END DEFine
As a side note, if there are any QLer’s out there that are interested in Wargaming, I’ve got a few Freeware wargames that I have designed and a few that I have picked up off the Internet. I’ve designed one tactical space combat and one tank combat game. I have all of these as Quill documents. If any are interested, please contact me.