Even with warp mode enabled the SuperPET ran a bit slow. Maybe that's why the dog developer was not able to catch those quail in the park. Even so, I managed to finish a game. Since the game-play was notably different than the Basic code, I'll include another tedious turn by turn account with commentary.
The SuperPET went first and was quite lucky. On turn 1 it managed to hit my battleship twice and the cruiser once. My return salvo was a miss.
On turn 2 the SuperPET sank my battleship. The Fortran algorithm counts all possible places the ships could be and then launches a salvo to cover the most likely positions as best as possible. Unlike some real-world examples, the missiles actually hit the locations targeted.
Since the results from the first salvo narrowed the locations for the battleship to nine possibilities, the second salvo was chosen in a way guaranteed to sink my battleship in three of the nine possibilities and at least hit it in eight of them. There was only one possibility in the lower right corner where the battleship could have escaped being hit.
On turn 3 the number of available missiles I had for the counter strike was reduced to four. An early loss like this is why the side which goes first has an advantage.
On turn 4 the SuperPET scores another hit on my cruiser. That was expected as the algorithm automatically focuses on ships whose location is better known by having been hit before.
Not surprisingly my cruiser was sunk in the next round as there were very few possible locations where a ship of length three could be hiding that had already been hit in the first and fourth rounds. This reduced my counter attack to only two missiles, but I got lucky and hit the battleship twice.
There were three places the battleship could be. I chose positions that were as likely as possible but hit only once.
I was able to sink the battleship on turn 7 and felt I might even have a chance to win since the SuperPET had not hit either of my destroyers.
Since the SuperPET has twice as many missiles in each salvo it is able to search faster. Otherwise, nothing happened.
On turn 9 my luck ran out and one destroyer was hit. Worse luck was my second destroyer was close to one of the strikes in that salvo and would likely receive a collateral hit when the SuperPET attempts to sink the first destroyer.
On turn 10 that's exactly what happened. The second destroyer was hit while the SuperPET was searching for the first.
By turn 11 I'm down to only one missile. As no friendly country has donated any additional weapons to my defense (even though the SuperPET went first), the end seems near.
The game ends on the next turn with a victory in which the enemy lost only the battleship. Even so, I had the last laugh by shutting down the emulated SuperPET with alt-Q and taking the real super pet to the park.
Code: Select all
*
* BATTLESHIP V2.1
* BY ERIC OLSON
* JUNE 6, 1983
*
* APRIL 2022 UPDATED FOR SUPERPET MICROFORTRAN
*
PROGRAM BATTLE
REAL CHANCE(10,10),PERCNT,RND,D
INTEGER US(10,10),THEM(10,10),LENGTH(5),RECORD(5,5)
INTEGER X,Y,Z,X1,Y1,DIRECT(8,2),COUNT,SHOTS(5),ROUND
INTEGER SHOOT,USREC(5),THINK(10,10),FIND(5),POSSIB
INTEGER FIRE(2,20),HIT(5),MISS,TURN,IABS
INTEGER H,V,B,L1,L2,L3,I,J,K
INTEGER USHIPS(5),THIPS(5),REV,DEBUG,NOHITS
*
* NO DATA STATEMENTS ON THE SUPERPET.
*
DIRECT(1,1)=0
DIRECT(1,2)=1
DIRECT(2,1)=-1
DIRECT(2,2)=1
DIRECT(3,1)=-1
DIRECT(3,2)=0
DIRECT(4,1)=-1
DIRECT(4,2)=-1
DIRECT(5,1)=0
DIRECT(5,2)=-1
DIRECT(6,1)=1
DIRECT(6,2)=-1
DIRECT(7,1)=1
DIRECT(7,2)=0
DIRECT(8,1)=1
DIRECT(8,2)=1
LENGTH(1)=5
LENGTH(2)=3
LENGTH(3)=2
LENGTH(4)=2
LENGTH(5)=0
SHOTS(1)=3
SHOTS(2)=2
SHOTS(3)=1
SHOTS(4)=1
SHOTS(5)=0
DO 91 X=1,10
DO 91 Y=1,10
US(X,Y)=0
91 THEM(X,Y)=0
DO 92 X=1,5
DO 92 Y=1,5
92 RECORD(X,Y)=0
*
* SET RUN OPTIONS.
*
NOHITS=1
DEBUG=0
ROUND=0
*
* DISPLAY WELCOME MESSAGE.
*
WRITE(6,1000)
*
* SET UP SHIPS.
*
DO 10 I=1,5
USREC(I)=LENGTH(I)
USHIPS(I)=1
THIPS(I)=1
IF(LENGTH(I).EQ.0) USHIPS(I)=0
IF(LENGTH(I).EQ.0) THIPS(I)=0
10 CONTINUE
*
* COMPUTER POSITION BOATS.
*
DO 50 I=1,5
IF(LENGTH(I).EQ.0) GOTO 50
45 X=IFIX(RND(0.0)*10.0)+1
Y=IFIX(RND(0.0)*10.0)+1
Z=IFIX(RND(0.0)*4.0)+1
X1=X
Y1=Y
COUNT=LENGTH(I)
*
* FIND A LOCTION AND TEST TO SEE IF IT FITS.
*
47 IF(US(X1,Y1).NE.0) GOTO 45
X1=X1+DIRECT(Z,1)
Y1=Y1+DIRECT(Z,2)
COUNT=COUNT-1
IF(COUNT.LE.0) GOTO 9301
IF(Y1.GT.10.OR.X1.GT.10.OR.Y1.LT.1.OR.X1.LT.1) GOTO 45
GOTO 47
9301 X1=X
Y1=Y
COUNT=LENGTH(I)
*
* PUT THE BOAT THERE.
*
48 US(X1,Y1)=-I
X1=X1+DIRECT(Z,1)
Y1=Y1+DIRECT(Z,2)
COUNT=COUNT-1
IF(COUNT.GT.0) GOTO 48
50 CONTINUE
*
* WHO GOES FIRST?
*
51 WRITE(6,1200)
100 READ(5,1090) I
REV=0
IF(I.NE.0) GOTO 101
CALL BOARD(US)
GOTO 51
101 IF(I.EQ.2) REV=1
IF(I.EQ.1.OR.I.EQ.2) GOTO 111
110 WRITE(6,1220)
GOTO 100
111 CONTINUE
*
* HUMAN POSITION BOATS.
*
DO 90 I=1,5
IF(LENGTH(I).EQ.0) GOTO 90
WRITE(6,1020) LENGTH(I)
*
* ENTER STARTING LOCATION.
*
55 READ(5,1070) X,Y
IF(X.GE.0.AND.X.LT.10.AND.Y.GE.0.AND.Y.LT.10) GOTO 65
60 WRITE(6,1030)
GOTO 55
65 X1=X+1
Y1=Y+1
COUNT=LENGTH(I)
WRITE(6,1040)
*
* ENTER DIRECTION.
*
66 READ(5,1090) Z
IF(Z.GT.0.AND.Z.LE.8) GOTO 68
67 WRITE(6,1050)
GOTO 66
*
* TEST TO SEE IF IT FITS.
*
68 IF(THEM(X1,Y1).NE.0) GOTO 69
X1=X1+DIRECT(Z,1)
Y1=Y1+DIRECT(Z,2)
COUNT=COUNT-1
IF(COUNT.LE.0) GOTO 9302
IF(Y1.GT.10.OR.X1.GT.10.OR.Y1.LT.1.OR.X1.LT.1) GOTO 69
GOTO 68
9302 X1=X+1
Y1=Y+1
COUNT=LENGTH(I)
GOTO 70
*
* IT DOESN'T FIT!
*
69 WRITE(6,1080)
GOTO 60
*
* PUT THE BOAT THERE.
*
70 THEM(X1,Y1)=-I
X1=X1+DIRECT(Z,1)
Y1=Y1+DIRECT(Z,2)
COUNT=COUNT-1
IF(COUNT.GT.0) GOTO 70
90 CONTINUE
*
* COUNT SHOTS AND HAVE THE HUMAN ENTER THEM.
*
IF(REV.EQ.1) GOTO 3000
2000 CONTINUE
2 MISS=0
DO 14 L1=1,5
14 HIT(L1)=0
IF(REV.EQ.0) ROUND=ROUND+1
I=SHOOT(THIPS,SHOTS)
WRITE(6,1230) ROUND,I
IF(I.GT.0) GOTO 124
WRITE(6,1310)
STOP
124 DO 160 J=1,I
WRITE(6,1240) J
125 READ(5,1070) X,Y
IF(X.GE.0.AND.Y.GE.0.AND.X.LE.9.AND.Y.LE.9) GOTO 130
127 WRITE(6,1030)
GOTO 125
130 IF(US(X+1,Y+1).EQ.0) GOTO 140
K=IABS(US(X+1,Y+1))
HIT(K)=HIT(K)+1
USREC(K)=USREC(K)-1
US(X+1,Y+1)=0
IF(USREC(K).GT.0) GOTO 160
USHIPS(K)=0
HIT(K)=-IABS(HIT(K))
GOTO 160
140 MISS=MISS+1
160 CONTINUE
*
* TELL HIM WHAT HE HIT!
*
WRITE(6,1520) MISS
DO 161 L1=1,5
IF(HIT(L1).EQ.0) GOTO 161
L2=IABS(HIT(L1))
WRITE(6,1500) L1,L2
IF(HIT(L1).LT.0) WRITE(6,1510)
161 CONTINUE
GOTO 3000
*
* COMPUTER TAKES HIS TURN.
*
3000 CONTINUE
3 MISS=0
DO 162 L1=1,5
162 HIT(L1)=0
IF(REV.EQ.1) ROUND=ROUND+1
I=SHOOT(USHIPS,SHOTS)
WRITE(6,1280) ROUND,I
IF(I.GT.0) GOTO 163
WRITE(6,1320)
STOP
*
* RANDOM IF FIRST OR SECOND ROUND AND NOTHING HIT.
*
163 IF(NOHITS.EQ.0) GOTO 199
IF(ROUND.GT.2) GOTO 199
DO 198 X=1,10
DO 198 Y=1,10
198 CHANCE(X,Y)=1E0
GOTO 1811
*
* INITIALIZE THINK.
*
199 DO 200 J=1,10
DO 200 K=1,10
200 CHANCE(J,K)=0E0
*
* EXAMINE ALL POSSIBLE SHIPS.
*
DO 4000 B=1,5
IF(THIPS(B).EQ.0) GOTO 4000
POSSIB=0
DO 1812 J=1,10
DO 1812 K=1,10
1812 THINK(J,K)=0
*
* EXAMINE ALL PLACES.
*
DO 4002 H=1,10
DO 4002 V=1,10
*
* POSSIB IS FOR NORMALIZATION OF PERCENTAGES.
*
DO 3900 L1=1,4
X=H
Y=V
DO 3800 L2=1,LENGTH(B)
IF(X.LT.1.OR.X.GT.10.OR.Y.LT.1.OR.Y.GT.10) GOTO 3900
FIND(L2)=THEM(X,Y)
X=X+DIRECT(L1,1)
Y=Y+DIRECT(L1,2)
3800 CONTINUE
*
* SET UP FIND.
*
DO 3100 L2=1,LENGTH(B)
3100 IF(FIND(L2).LT.0) FIND(L2)=0
*
* SORT FIND.
*
DO 3200 L2=1,LENGTH(B)-1
DO 3200 L3=L2+1,LENGTH(B)
IF(FIND(L2).LE.FIND(L3)) GOTO 3200
J=FIND(L2)
FIND(L2)=FIND(L3)
FIND(L3)=J
3200 CONTINUE
*
* SEE IF IT IS A POSSIBILITY.
*
DO 3300 L2=LENGTH(B),1,-1
IF(FIND(L2).NE.RECORD(B,L2)) GOTO 3900
3300 CONTINUE
*
* IT FITS! SO TALLY IT UP!
*
X=H
Y=V
POSSIB=POSSIB+1
DO 3400 L2=1,LENGTH(B)
THINK(X,Y)=THINK(X,Y)+1
X=X+DIRECT(L1,1)
3400 Y=Y+DIRECT(L1,2)
3900 CONTINUE
4002 CONTINUE
*
* ADD IT TO THE CHANCE TABLE.
*
IF(DEBUG.EQ.1) CALL BOARD(THINK)
DO 3950 L1=1,10
DO 3950 L2=1,10
IF(POSSIB.GT.0) GOTO 3950
WRITE(6,1300) 4
STOP
3950 CHANCE(L1,L2)=CHANCE(L1,L2)+FLOAT(THINK(L1,L2))/FLOAT(POSSIB)
4000 CONTINUE
*
* MAKE SURE IT HAS NOT BEEN DONE BEFORE.
*
1811 DO 6 X1=1,10
DO 6 Y1=1,10
IF(THEM(X1,Y1).GT.0) CHANCE(X1,Y1)=0E0
6 CONTINUE
*
* FIND THE I MOST POPULAR SHOTS.
*
J=1
4001 IF(J.GT.I) GOTO 5000
X=1
Y=1
COUNT=0
DO 4100 H=1,10
DO 4100 V=1,10
IF(CHANCE(H,V).LT.CHANCE(X,Y)) GOTO 4100
IF(CHANCE(H,V).NE.CHANCE(X,Y)) GOTO 4050
COUNT=COUNT+1
GOTO 4100
4050 X=H
Y=V
COUNT=1
4100 CONTINUE
*
* GET THEM!
*
PERCNT=CHANCE(X,Y)
IF(PERCNT.GT.0E0) GOTO 4110
WRITE(6,1530) J-1
I=J-1
GOTO 5000
4110 K=IFIX(RND(0.0)*FLOAT(COUNT))+1
DO 4150 H=1,10
DO 4150 V=1,10
IF(CHANCE(H,V).NE.PERCNT) GOTO 4150
K=K-1
IF(K.GT.0) GOTO 4150
FIRE(1,J)=H
FIRE(2,J)=V
J=J+1
CHANCE(H,V)=0E0
GOTO 4160
4150 CONTINUE
WRITE(6,1300) 1
CALL BOARD(THEM)
STOP
4160 COUNT=COUNT-1
IF(J.GT.I) GOTO 5000
IF(COUNT.GT.0) GOTO 4110
GOTO 4001
5000 CONTINUE
*
* SCORE THE SHOTS.
*
DO 5300 J=1,I
X=FIRE(1,J)-1
Y=FIRE(2,J)-1
WRITE(6,1290) J,X,Y
IF(THEM(X+1,Y+1).EQ.0) GOTO 5020
IF(THEM(X+1,Y+1).LT.0) GOTO 5100
WRITE(6,1300) 2
STOP
5020 MISS=MISS+1
THEM(X+1,Y+1)=ROUND
GOTO 5300
5100 CONTINUE
*
* RECORD THE HITS!
*
NOHITS=0
K=IABS(THEM(X+1,Y+1))
HIT(K)=HIT(K)+1
RECORD(K,1)=ROUND
THEM(X+1,Y+1)=ROUND
*
* SORT THE RECORD.
*
DO 5200 L2=1,LENGTH(K)-1
DO 5200 L3=L2+1,LENGTH(K)
IF(RECORD(K,L2).LE.RECORD(K,L3)) GOTO 5200
Z=RECORD(K,L2)
RECORD(K,L2)=RECORD(K,L3)
RECORD(K,L3)=Z
5200 CONTINUE
*
* DID IT SINK?
*
IF(RECORD(K,1).EQ.0) GOTO 5300
HIT(K)=-IABS(HIT(K))
THIPS(K)=0
5300 CONTINUE
*
* TELL HIM WHAT I HIT!
*
WRITE(6,1521) MISS
DO 5301 L2=1,5
IF(HIT(L2).EQ.0) GOTO 5301
L3=IABS(HIT(L2))
WRITE(6,1501) L2,L3
IF(HIT(L2).LT.0) WRITE(6,1510)
5301 CONTINUE
GOTO 2000
*
* FORMAT STATEMENTS.
*
1000 FORMAT(' WELCOME TO BATTLESHIP',40X,'VERSION 2.0')
1020 FORMAT(/,' YOU HAVE A BOAT',I2,' LONG.',/,
& ' ENTER COORDINATES: ')
1030 FORMAT(' ENTER THE COORDINATES IN THE FORM: XY',/,
& ' ENTER COORDINATES: ')
1040 FORMAT(' ENTER DIRECTION OF BOAT: ')
1050 FORMAT(' THE DIRECTION IS A NUMBER FROM 1 TO 8.',/,
& ' ENTER DIRECTION: ')
1060 FORMAT(I3)
1070 FORMAT(2I1)
1080 FORMAT(' YOUR SHIP DOES NOT FIT THERE. TRY AGAIN...',/)
1090 FORMAT(I1)
1200 FORMAT(/,' DO YOU WANT TO GO FIRST?',/,
& 6X,'1) FIRST',/,
& 6X,'2) SECOND',/,
& ' CHOICE: ')
1220 FORMAT(' ENTER EITHER 1 OR 2.',/,
& ' CHOICE: ')
1230 FORMAT(/,' IT IS ROUND',I3,', AND YOU HAVE',I2,' SHOT(S).',/)
1240 FORMAT(5X,'SHOT',I2,': ')
1280 FORMAT(/,' IT IS ROUND',I3,', AND I HAVE',I2,' SHOT(S).',/)
1290 FORMAT(5X,'SHOT',I2,': ',2I1)
1300 FORMAT(/,' BATTLESHIP ERROR:',I2)
1310 FORMAT(' YOU LOSE!')
1320 FORMAT(' YOU WIN!')
1500 FORMAT(' YOU HIT SHIP',I2,',',I2,' TIME(S).')
1501 FORMAT(' I HIT SHIP',I2,',',I2,' TIME(S).')
1510 FORMAT(' IT SUNK!')
1520 FORMAT(/,' YOU MISSED',I2,' TIME(S).')
1521 FORMAT(/,' I MISSED',I2,' TIME(S).')
1530 FORMAT(' I ONLY NEED ',I2,' SHOTS(S).',/)
STOP
END
*
* FUNCTION SHOOT DETERMINES HOW MANY SHOTS ARE LEFT.
*
INTEGER FUNCTION SHOOT(A,B)
INTEGER A(5)
INTEGER B(5),COUNT,I
COUNT=0
DO 10 I=1,5
IF(A(I).EQ.1) COUNT=COUNT+B(I)
10 CONTINUE
SHOOT=COUNT
RETURN
END
*
* SUBROUTINE TO PRINT BOARD.
*
SUBROUTINE BOARD(OUT)
INTEGER OUT(10,10)
WRITE(6,10) OUT
10 FORMAT(/,1X,32('-'),/,10(1X,10I3,/),1X,32('-'))
RETURN
END
The only thing which prevents this program from compiling natively on the Pi with gfortran is the fact that the line continuation characters are in the 1st column rather than the 6th and the need for a suitable random number generator.
Do you think the New York Times would buy an online implementation of Salvo for US$ 1 million? I wonder if gfortran can produce Wasm output.