|
Post by tsh73 on Jul 20, 2024 9:30:45 GMT
It started from this thread justbasiccom.proboards.com/thread/1121/naval-battle-2-playersI wanted to roll my own arrays (in one big one) to be able to reuse code for different arrays I had something working but end with conclusion what it does not worth it ;) but as a second try, I made something like Battleship engine (still on a single big array) Now it fiercely plays against itself ;) in a mainwin. I probably make it into playable mainwin game (now it miss big chunk - code for user placing ships) Idea was that character arrays could be easily transferred to GUI (just draw certain sprite for certain letter ), but placing ships calls for drag'n'drop so this part should be completely new. Now it asks for field size (10x10 or 8x8) and ships set Ships set for 8x8 was googled picture. It plays faster (but it looks like player 1 wins most of the time). Ships are horisontal or vertical, no turns Ships could not touch each other Player who hit a ship gets next shot (with this, game plays faster. But it is possible one lucky player to quickly finish other one!) few screeenshots (it is actually text from a mainwin!) ----====**** BATTLESHIP ****====----
Select field size (0-10x10, 1=8x8): Field set to 10x10 Select ship set Milton/Hasbro (5 4 3 3 2) USSR (4 3 3 2 2 2 1 1 1 1) Select ship set (0-Milton, 1=USSR): Ship set is Milton/Hasbro
Generating ships for player 1 aaaaa bbbb ccc ddd ee
A B C D E F G H I J --------------------- 1| . . d d d . . . c . 2| . . . . . . . . c . 3| . . . . . . . . c . 4| . . b b b b . . . . 5| . . . . . . . . . e 6| . . . . . . . . . e 7| . . . . . . . . . . 8| . . . . . . . . . . 9| . . . a a a a a . . 10| . . . . . . . . . . --------------------- A B C D E F G H I J
press ENTER to start auto-game
While autoplaying, program shows radar for player1(left) and player2 (right) Current shot shows in a caps lock. oO miss, xX hit. (+) is "shadow" cells where ship could not be placed - it's mark for the AI not to shoot there. Player scoring a hit gets next move. B1 miss . O o . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . J6 hit . . . . . . . . . . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . + . . . . . . . . . . X . . . . . . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . I6 miss . . . . . . . . . . . . . . . . . . . . . . o . . . . . . . . . . . . . . . . . . . . . . . . . + . . . . . . . . . O x . . . . . . . . + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
When ship is killed, program says "kill" and finish encircling ship with (+) E6 kill . o o . . . . . . . . . . + + + . . . . . . . + x + . . . . . . . + x + . . . . . . . + x + . . . . . . . + X + . . . . . . o + + + . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . . .
Eventually, one player runs out of ships so game register "win" J1 win . o o o . o + x x X o o o + + + o + + o + + + + x + o . o . + x + + x + . . + o + x + + x + . . + x + o + + x + o . + x . o o + + + . . + x . o . . . . . . + x . . o + + o + + + x . . . + x x x + + o
Player 1 wins! turns:41
In the end it shows ships of both players. Obviously, one who got nothing but "x" left loses A B C D E F G H I J --------------------- 1| . . d d d . . . X . 2| . . . . . . . . X . 3| . . . . . . . . X . 4| . . X X X X . . . . 5| . . . . . . . . . X 6| . . . . . . . . . X 7| . . . . . . . . . . 8| . . . . . . . . . . 9| . . . X X X X X . . 10| . . . . . . . . . . --------------------- A B C D E F G H I J
A B C D E F G H I J --------------------- 1| . . . . . . . X X X 2| . . . . . . . . . . 3| . . . . X . . . . . 4| . X . . X . . . . . 5| . X . . X . . . . X 6| . . . . X . . . . X 7| . . . . . . . . . X 8| . . . . . . . . . X 9| . . . . . . . . . X 10| . . . . X X X . . . --------------------- A B C D E F G H I J
press ENTER to quit
AI remembers "last hit", and continues to hunt that ship, even after miss. (actually until ship is killed, it remembers all its hit points. So you hardly can escape) Example setup for 8x8 field ----====**** BATTLESHIP ****====----
Select field size (0-10x10, 1=8x8):1 Field set to 8x8 Ship set (5 4 3 2 2 1 1)
Generating ships for player 1 aaaaa bbbb ccc dd ee f g
A B C D E F G H ----------------- 1| e e . . f . . . 2| . . . . . . . . 3| . . . a . b . . 4| . . . a . b . . 5| . g . a . b . c 6| . . . a . b . c 7| . . . a . . . c 8| d d . . . . . . ----------------- A B C D E F G H
Example setup for 10x10 field, USSR ship set ----====**** BATTLESHIP ****====----
Select field size (0-10x10, 1=8x8): Field set to 10x10 Select ship set Milton/Hasbro (5 4 3 3 2) USSR (4 3 3 2 2 2 1 1 1 1) Select ship set (0-Milton, 1=USSR):1 Ship set is USSR
Generating ships for player 1 aaaa bbb ccc dd ee ff g h i j
A B C D E F G H I J --------------------- 1| . . . . . . g . . . 2| . a a a a . . . . . 3| . . . . . . . . . . 4| j . c c c . e . . . 5| . . . . . . e . . h 6| . . . . . . . . . . 7| . . . f f . . . d d 8| . . . . . . . . . . 9| i . . . . b b b . . 10| . . . . . . . . . . --------------------- A B C D E F G H I J
|
|
|
Post by tsh73 on Jul 20, 2024 9:36:03 GMT
Current code (v.14)
'sea battle 01 ' array management, now console 'v.14
global N, player1, player2, shadow, radar global shipList$
print "----====**** BATTLESHIP ****====----" print input "Select field size (0-10x10, 1=8x8):";n1 if n1=0 then N=10 else N=8 print " Field set to ";N;"x";N if N=10 then print "Select ship set" print " Milton/Hasbro (5 4 3 3 2)" print " USSR (4 3 3 2 2 2 1 1 1 1)" input "Select ship set (0-Milton, 1=USSR):";n2 if n2=0 then print " Ship set is Milton/Hasbro" shipList$="a5 b4 c3 d3 e2" 'classic else print " Ship set is USSR" shipList$="a4 b3 c3 d2 e2 f2 g1 h1 i1 j1" 'Russian traditional end if else print " Ship set (5 4 3 2 2 1 1)" shipList$="a5 b4 c3 d2 e2 f1 g1" '8x8 ships end if
' input "press ENTER to quit"; d$ ' end
'N=10 'N=8 player1=0 player2=100 'enough space to store all player1 data shadow=20 radar=40
dim a$(2*player2,N+1) 'row, col. row+ displacement gives player2 etc dim prevHit$(player2) 'actually need 2 cells, but I'll use 0 and 100
'letter, number of cells 'shipList$="a4 b3 c3 d2 e2 f2 g1 h1 i1 j1" 'Russian traditional 'shipList$="a5 b4 c3 d3 e2" 'classic 'shipList$="a5 b4 c3 d2 e2 f1 g1" '8x8 ships 'shipList$="a1 b1 c1 d1 e1 f1 g1 h1 i1 j1" 'test for kill
print call generate2 player1 call showArr1 player1
print call generate2 player2 call showArr1 player2
print input "press ENTER to start auto-game"; d$
player=player1 prevHit$="" for i = 1 to 200 do res$= shoot5$(player) if player>=player2 then print space$(5+N*2); print res$ call showArr player+radar call toLower player+radar if res$="win" then print print "Player "; (player=player2)+1;" wins!" print " turns:";i call showArr1 player1 print call showArr1 player2 print input "press ENTER to quit"; d$ end end if loop until res$="miss" 'if not miss, extra move! player=player2-player next
input "press ENTER to quit"; d$ end
sub showArr offset for r = 1 to N if offset>=player2 then print space$(5+N*2); for c = 1 to N c$="." if a$(offset+r, c)<>"" and a$(offset+r, c)<>" " then c$=a$(offset+r, c) print " ";c$; next print next end sub
sub showArr1 offset ln$=left$("-----------------------------------------------------",N*2+1) ltr$=left$(" A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ",N*2) if offset>=player2 then off$ = space$(5+N*2) print off$;" ";ltr$ print off$;" ";ln$ for r = 1 to N print off$;using("##",r);"|"; for c = 1 to N c$="." if a$(offset+r, c)<>"" and a$(offset+r, c)<>" " then c$=a$(offset+r, c) print " ";c$; next print next print off$;" ";ln$ print off$;" ";ltr$ end sub
sub clearArr offset for r = 1 to N for c = 1 to N a$(offset+r, c)="" next next end sub
sub generate2 player 'with check 'clear player call clearArr player call clearArr player+shadow
if player>=player2 then off$ = space$(5+N*2) print "Generating ships for player ";(player=player2)+1 i=0 while 1 i=i+1 w$=word$(shipList$,i) if w$="" then exit while c$=left$(w$,1) n=val(mid$(w$,2)) print off$;:for j = 1 to n:print c$;:next:print k=0 while 1 k=k+1 if k>500 then 'if we cannot do it that long, just start over print "*start over*" call generate2 player exit sub end if isVert=rnd(1)>.5 isHor=1-isVert r=int(rnd(0)*(N-isVert*(n-1))+1) c=int(rnd(0)*(N-isHor*(n-1))+1) 'have to check first forbidden=0 for j = 0 to n-1 forbidden=forbidden+( a$(player+shadow+r+j*isVert, c+j*isHor)="#" ) next if not (forbidden) then for j = 0 to n-1 a$(player+r+j*isVert, c+j*isHor)=c$ next call mkShadow player exit while end if wend 'print k;" "; wend print end sub
sub mkShadow player for r = 1 to N for c = 1 to N if a$(player+r, c)<>"" and a$(player+r, c)<>" " then for i = -1 to 1 for j = -1 to 1 a$(player+shadow+r+i, c+j)="#" next next end if next next end sub
sub mkRadarShadow2.1 player for r = 1 to N for c = 1 to N if a$(player+radar+r, c)="#" then for i = -1 to 1 for j = -1 to 1 if a$(player+radar+r+i, c+j)="" or a$(player+radar+r+i, c+j)=" " then a$(player+radar+r+i, c+j)="+" end if next next end if next next end sub
sub mkRadarShadow2 player, r,c 'paint-like from shoot$ 'notice "TBD! "+chr$(13)+"sub mkRadarShadow2 player, shoot$" 'input "press Ener to quit"; d$ 'end call paintKilled player+radar,r,c 'mark fresh kill call mkRadarShadow2.1 player 'hide fresh kill mark for r = 1 to N for c = 1 to N if a$(player+radar+r, c)="#" then a$(player+radar+r, c)="x" next next end sub
sub paintKilled offset,r,c a$(offset+r,c)="#" if a$(offset+r-1,c)="x" then call paintKilled offset,r-1,c if a$(offset+r+1,c)="x" then call paintKilled offset,r+1,c if a$(offset+r,c-1)="x" then call paintKilled offset,r,c-1 if a$(offset+r,c+1)="x" then call paintKilled offset,r,c+1 end sub
function shoot5$(player) if prevHit$(player)<>"" then list$="" while 1 k=k+1 w$=word$(prevHit$(player),k) if w$="" then exit while ' r0=val(word$(w$,1,",")) c0=val(word$(w$,2,",")) list$=addNeighbourFreeList$(player+radar,r0,c0, list$) wend end if if list$="" then list$=mkFreeList$(player+radar) end if if list$="" then 'or cource should not happen, but... print "ERROR! player ";((player=player2)+1);" have no unchecked cells on radar!" input "press ENTER to quit";d$ end end if shoot$=randomSelect$(list$) r=val(word$(shoot$,1,",")) c=val(word$(shoot$,2,",")) if player>=player2 then print space$(5+N*2); print chr$(asc("A")-1+c);r enemy=player2-player 'if rnd(1)>.8 then if a$(enemy+r, c)<>" " and a$(enemy+r, c)<>"" then marker$=a$(enemy+r, c) a$(player+radar+r, c)="X" 'current shot - hit a$(enemy+r, c)="X" 'current shot - hit if countMarker(enemy, marker$) then res$="hit" prevHit$(player)=prevHit$(player);" ";shoot$ 'a list call mkRadarDiagShadow player, r,c else res$="kill" call mkRadarShadow2 player, r,c 'TBD ''call mkRadarDiagShadow player, r,c 'instead a$(player+radar+r, c)="X" 'restore last shot prevHit$(player)="" 'release only on kill! if countLeft(enemy)=0 then res$="win" end if else a$(player+radar+r, c)="O" 'current shot - miss res$="miss" 'but prevHit$ stays end if shoot5$=res$ end function
sub toLower offset for r = 1 to N for c = 1 to N a$(offset+r, c)=lower$(a$(offset+r, c)) next next end sub
function countMarker(enemy, marker$) countMarker=0 'should count for r = 1 to N for c = 1 to N if a$(enemy+r, c)=marker$ then countMarker=countMarker+1 next next end function
function countLeft(enemy) countLeft=0 'should count for r = 1 to N for c = 1 to N if a$(enemy+r, c)<>"" and instr(" xXoO", a$(enemy+r, c))=0 then countLeft=countLeft+1 next next end function
function mkFreeList$(offset) for r = 1 to N for c = 1 to N if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=list$;" ";r;",";c next next mkFreeList$=list$ end function
sub mkRadarDiagShadow player,r0,c0 offset=player+radar r=r0-1:c=c0-1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if r=r0-1:c=c0+1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if r=r0+1:c=c0-1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if r=r0+1:c=c0+1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if end sub
function addNeighbourFreeList$(offset,r0,c0, list$) r=r0:c=c0-1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if r=r0:c=c0+1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if r=r0-1:c=c0 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if r=r0+1:c=c0 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if addNeighbourFreeList$=list$ end function
function addUniq$(list$, item$) if instr(" ";list$;" ", " ";item$;" ")=0 then addUniq$=list$;" ";item$ else addUniq$=list$ end if end function
function countItems(list$) do i=i+1 w$=word$(list$,i) loop until w$="" countItems=i-1 end function
function randomSelect$(list$) r=randInt1(countItems(list$)) randomSelect$=word$(list$,r) end function
function randInt(n) '0..n-1 randInt=int(rnd(1)*n) end function
function randInt1(n) '1..n randInt1=int(rnd(1)*n)+1 end function
|
|
|
Post by tsh73 on Jul 20, 2024 20:23:37 GMT
Ok, game is playable now - all but ship placing. Looks working - I even winned it over once! ;) It flips coin to determine is human Player1 (first) or Player2 Computer move shows result on player map with ships Player move shows only player radar (I could probably remove AI '+' marks from it. But you have it in mind then playing anyway, aren't you?) (autoplay is retained as an option. Autoplay shows radars for both computer players)
EDIT: just made my kid play it. Human wins! ;)
'sea battle 01 ' array management, now console 'v.15
global N, player1, player2, human, shadow, radar global shipList$, autoplay
'N=10 'N=8 player1=0 player2=100 'offset - enough space to store all player1 data shadow=20 'point was storing 0..N+1 lines for actual ship map, shadow used to place ships, radar radar=40 '0 and N+1 is unused but prevenst out of array errors
print "----====**** BATTLESHIP ****====----" print input "Select field size (0-10x10, 1=8x8):";n1 if n1=0 then N=10 else N=8 print " Field set to ";N;"x";N if N=10 then print "Select ship set" print " Milton/Hasbro (5 4 3 3 2)" print " USSR (4 3 3 2 2 2 1 1 1 1)" input "Select ship set (0-Milton, 1=USSR):";n2 if n2=0 then print " Ship set is Milton/Hasbro" shipList$="a5 b4 c3 d3 e2" 'classic else print " Ship set is USSR" shipList$="a4 b3 c3 d2 e2 f2 g1 h1 i1 j1" 'Russian traditional end if else print " Ship set (5 4 3 2 2 1 1)" shipList$="a5 b4 c3 d2 e2 f1 g1" '8x8 ships end if
print input "Press Enter to flip the coin, 1 for autoplay";n3 if n3=0 then Print Print "Flipping the coin..." if rnd(0)<.5 then human=player1 Print " You are Player1."' Your turn!" else human=player2 Print " You are Player2."' Computer turn!" end if else autoplay=1 print " Preparing autoplay..." end if 'input "press ENTER to quit"; d$' end
dim a$(2*player2,N+1) 'row, col. row+ displacement gives player2 etc dim prevHit$(player2) 'actually need 2 cells, but I'll use 0 and 100
'letter, number of cells 'shipList$="a4 b3 c3 d2 e2 f2 g1 h1 i1 j1" 'Russian traditional 'shipList$="a5 b4 c3 d3 e2" 'classic 'shipList$="a5 b4 c3 d2 e2 f1 g1" '8x8 ships 'shipList$="a1 b1 c1 d1 e1 f1 g1 h1 i1 j1" 'test for kill
if autoplay then print call generate2 player1 call showArr1 player1
print call generate2 player2 call showArr1 player2
print input "press ENTER to start auto-game"; d$ else if human=player2 then call generate2 player1 print print "Player2, please place your ships" print " wait, not ready yet. Let me place it for you..." call generate2 player2 call showArr1 player2 else print "Player1, please place your ships" print " wait, not ready yet. Let me place it for you..." call generate2 player1 call showArr1 player1 print call generate2 player2 end if print input "press ENTER to start game"; d$ if human=player1 then Print " You are Player1. Your turn!" else Print " You are Player2. Computer turn!" end if end if
player=player1 prevHit$="" for i = 1 to 200 do res$= shoot5$(player) if player>=player2 then print space$(5+N*2); print res$ if not(autoplay) and (player<>human) then call showArr1 human call toLower human else call showArr1 player+radar end if call toLower player+radar if res$="win" then print print "Player "; (player=player2)+1;" wins!" print " turns:";i call showArr1 player1 print call showArr1 player2 print input "press ENTER to quit"; d$ end end if loop until res$="miss" 'if not miss, extra move! player=player2-player next
input "press ENTER to quit"; d$ end
sub showArr offset for r = 1 to N if offset>=player2 then print space$(5+N*2); for c = 1 to N c$="." if a$(offset+r, c)<>"" and a$(offset+r, c)<>" " then c$=a$(offset+r, c) print " ";c$; next print next end sub
sub showArr1 offset ln$=left$("-----------------------------------------------------",N*2+1) ltr$=left$(" A B C D E F G H I J K L M N O P Q R S T U V W X Y Z ",N*2) if not(autoplay) and (offset=human) then 'offset reversed if offset<player2 then off$ = space$(5+N*2) else if offset>=player2 then off$ = space$(5+N*2) end if print off$;" ";ltr$ print off$;" ";ln$ for r = 1 to N print off$;using("##",r);"|"; for c = 1 to N c$="." if a$(offset+r, c)<>"" and a$(offset+r, c)<>" " then c$=a$(offset+r, c) print " ";c$; next print next print off$;" ";ln$ print off$;" ";ltr$ end sub
sub clearArr offset for r = 1 to N for c = 1 to N a$(offset+r, c)="" next next end sub
sub generate2 player 'with check 'clear player call clearArr player call clearArr player+shadow
if player>=player2 then off$ = space$(5+N*2) print "Generating ships for player ";(player=player2)+1 i=0 while 1 i=i+1 w$=word$(shipList$,i) if w$="" then exit while c$=left$(w$,1) n=val(mid$(w$,2)) print off$;:for j = 1 to n:print c$;:next:print k=0 while 1 k=k+1 if k>500 then 'if we cannot do it that long, just start over print "*start over*" call generate2 player exit sub end if isVert=rnd(1)>.5 isHor=1-isVert r=int(rnd(0)*(N-isVert*(n-1))+1) c=int(rnd(0)*(N-isHor*(n-1))+1) 'have to check first forbidden=0 for j = 0 to n-1 forbidden=forbidden+( a$(player+shadow+r+j*isVert, c+j*isHor)="#" ) next if not (forbidden) then for j = 0 to n-1 a$(player+r+j*isVert, c+j*isHor)=c$ next call mkShadow player exit while end if wend 'print k;" "; wend print end sub
sub mkShadow player for r = 1 to N for c = 1 to N if a$(player+r, c)<>"" and a$(player+r, c)<>" " then for i = -1 to 1 for j = -1 to 1 a$(player+shadow+r+i, c+j)="#" next next end if next next end sub
sub mkRadarShadow2.1 player for r = 1 to N for c = 1 to N if a$(player+radar+r, c)="#" then for i = -1 to 1 for j = -1 to 1 if a$(player+radar+r+i, c+j)="" or a$(player+radar+r+i, c+j)=" " then a$(player+radar+r+i, c+j)="+" end if next next end if next next end sub
sub mkRadarShadow2 player, r,c 'paint-like from shoot$ 'notice "TBD! "+chr$(13)+"sub mkRadarShadow2 player, shoot$" 'input "press Ener to quit"; d$ 'end call paintKilled player+radar,r,c 'mark fresh kill call mkRadarShadow2.1 player 'hide fresh kill mark for r = 1 to N for c = 1 to N if a$(player+radar+r, c)="#" then a$(player+radar+r, c)="x" next next end sub
sub paintKilled offset,r,c a$(offset+r,c)="#" if a$(offset+r-1,c)="x" then call paintKilled offset,r-1,c if a$(offset+r+1,c)="x" then call paintKilled offset,r+1,c if a$(offset+r,c-1)="x" then call paintKilled offset,r,c-1 if a$(offset+r,c+1)="x" then call paintKilled offset,r,c+1 end sub
function shoot5$(player) 'AI part enemy=player2-player if autoplay or (player<>human) then if prevHit$(player)<>"" then list$="" while 1 k=k+1 w$=word$(prevHit$(player),k) if w$="" then exit while ' r0=val(word$(w$,1,",")) c0=val(word$(w$,2,",")) list$=addNeighbourFreeList$(player+radar,r0,c0, list$) wend end if if list$="" then list$=mkFreeList$(player+radar) end if if list$="" then 'or cource should not happen, but... print "ERROR! player ";((player=player2)+1);" have no unchecked cells on radar!" input "press ENTER to quit";d$ end end if shoot$=randomSelect$(list$) r=val(word$(shoot$,1,",")) c=val(word$(shoot$,2,",")) else 'ask player while 1 input "Enter coords to fire, like a1: ";shoot0$ shoot0$=trim$(lower$(shoot0$)) r=val(mid$(shoot0$,2)) c=instr("abcdefghij", left$(shoot0$,1)) if (c>0) and (c <11) and (r>0) and (r <11) then exit while Print "Got row=";r;" col=";c;". Not valid!" wend shoot$=r;",";c if a$(enemy+r, c)="x" or a$(enemy+r, c)="o" then print " Already fired at - your wasted your turn!" res$="miss" shoot5$=res$ exit function end if end if if player>=player2 then print space$(5+N*2); print "Player";((player=player2)+1);" "; print chr$(asc("A")-1+c);r 'if rnd(1)>.8 then if a$(enemy+r, c)<>" " and a$(enemy+r, c)<>"" then marker$=a$(enemy+r, c) a$(player+radar+r, c)="X" 'current shot - hit a$(enemy+r, c)="X" 'current shot - hit if countMarker(enemy, marker$) then res$="hit" prevHit$(player)=prevHit$(player);" ";shoot$ 'a list call mkRadarDiagShadow player, r,c else res$="kill" call mkRadarShadow2 player, r,c 'TBD ''call mkRadarDiagShadow player, r,c 'instead a$(player+radar+r, c)="X" 'restore last shot prevHit$(player)="" 'release only on kill! if countLeft(enemy)=0 then res$="win" end if else a$(player+radar+r, c)="O" 'current shot - miss a$(enemy+r, c)="O" res$="miss" 'but prevHit$ stays end if shoot5$=res$ end function
sub toLower offset for r = 1 to N for c = 1 to N a$(offset+r, c)=lower$(a$(offset+r, c)) next next end sub
function countMarker(enemy, marker$) countMarker=0 'should count for r = 1 to N for c = 1 to N if a$(enemy+r, c)=marker$ then countMarker=countMarker+1 next next end function
function countLeft(enemy) countLeft=0 'should count for r = 1 to N for c = 1 to N if a$(enemy+r, c)<>"" and instr(" xXoO", a$(enemy+r, c))=0 then countLeft=countLeft+1 next next end function
function mkFreeList$(offset) for r = 1 to N for c = 1 to N if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=list$;" ";r;",";c next next mkFreeList$=list$ end function
sub mkRadarDiagShadow player,r0,c0 offset=player+radar r=r0-1:c=c0-1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if r=r0-1:c=c0+1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if r=r0+1:c=c0-1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if r=r0+1:c=c0+1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then a$(offset+r, c)="+" end if end sub
function addNeighbourFreeList$(offset,r0,c0, list$) r=r0:c=c0-1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if r=r0:c=c0+1 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if r=r0-1:c=c0 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if r=r0+1:c=c0 if r>0 and r<=N and c>0 and c<=N then if a$(offset+r, c)="" or a$(offset+r, c)=" " then list$=addUniq$(list$, r;",";c) end if addNeighbourFreeList$=list$ end function
function addUniq$(list$, item$) if instr(" ";list$;" ", " ";item$;" ")=0 then addUniq$=list$;" ";item$ else addUniq$=list$ end if end function
function countItems(list$) do i=i+1 w$=word$(list$,i) loop until w$="" countItems=i-1 end function
function randomSelect$(list$) r=randInt1(countItems(list$)) randomSelect$=word$(list$,r) end function
function randInt(n) '0..n-1 randInt=int(rnd(1)*n) end function
function randInt1(n) '1..n randInt1=int(rnd(1)*n)+1 end function
|
|
|
Post by plus on Jul 21, 2024 22:04:06 GMT
This game is definitely played differently than what I am use to. 1. players alternate turns hit or miss 2. you can put ships right next to each other to fool the enemy into wrong thinking but I never played with radar??? 3. for positioning ships I suggest va1 or ha1 for v's it's the top and ship goes vertically downward for h's its the leftmost cell the ships runs horizontal for it's length 4. really would like to see my board before shooting instead of scrolling up to remind myself. But this is tsh73 version so, thumbs up! ![:)](//storage.proboards.com/forum/images/smiley/smiley.png) b = b + ...
|
|
|
Post by plus on Jul 28, 2024 18:39:36 GMT
OK tsh73 you've shown me yours and I've shown you mine. Now it's time to compare, no? I am particularly interested in how you are going about sinking a ship after you get a hit on it. I started reviewing your subroutines and OMG we are light years different! What is all that? Helpful would be a quick description of what each routine is supposed to do. Isn't it obvious? no, some are but radar stuff??? Maybe, if you don't mind, a verbal description of what you are doing after a hit is detected maybe I need to know how hits are detected too. Just some more translation into words if you please. (What coder minds talking about their creations, I don't think I know a single one!) Of course, if I asked, I have to be prepared to do same for you. Honestly I forgot half the stuff I did when I first created those AI routines. But I am committed to properly comment the code to make it clearer to others and myself, dang it!, because someone at another forum was complaining about that and I thought it a proper thing to request in earnest motivation. But I asked you first! ![:)](//storage.proboards.com/forum/images/smiley/smiley.png) b = b + ...
|
|
|
Post by tsh73 on Jul 28, 2024 20:41:54 GMT
Ok first is data structure Wikipedia says
Let us say N=10 in games I used to play cells numbered from 1, so cells would be a1...j10
So for player 1, "one grid the player arranges ships and records the shots by the opponent" is actually a$(1..N,1..N) Since Basic allocates from 0, I added extra row\column to a$(0..N+1, 0..N+1) so neighbour of valid cell did not end in "out of array" error.
But we need "other grid, the player records their own shots" , and two more grids for player 2.
I chose to make array longer, like dim a$(200,N+1) and use first N rows for player1 N rows after some offset (actually radar=40) to "other grid, the player records their own shots" (that I call "radar", but it really only memory device for remembering own shots, hits and misses) and the same for player2, but after own offset (player2=100)
So I have it all in single array, distinguished by row offset offset 0 . player1=0, no offset - player 1 ships offset 20 . shadow=20 - rather important in this version that ships could not touch each other. It could be thought of each ship cast "shadow" one cell any direction, so no other ships could occupy that shadowed area. This part of array used then placing the ships for player 1, only. offset 40 . radar=40 place for the player1 records their own shots. Also AI marks shadowed cells there (with +). offset 100 . player2=100, player 2 ships offset 120 . player2+shadow This part of array used then placing the ships for player 2, only. offset 140 . player2+radar place for the player2 records their own shots. (same for AI, if player 2 is AI)
For my troubles I could use same code for player 1 and player 2 (and actually for diplaying ships map and hits/misses (radar) map).
BTW is player1 is 0 and player2 is 100, then "enemy" is (player2-player) ;)
Now, on with ships it's interesting but I code ship with repeated symbols, one ship - one symbol (as you did) But you use digits, and different for player and computer while I use letters, same letters for player 1 and player 2 Enpty cells are not initialised ("")
Then "player" shoot at (row, col), . function shoot5$(player) program checks a$(enemy+row, col) If it holds "x" or "o" then we already shoot that point (and hit, or miss) if it empty, program puts "O" on that place at player radar . a$(player+radar+r, c)="O" and at enemy ships map . a$(enemy+r, c)="O" Else it remembers letter at that place . marker$=a$(enemy+r, c) and puts "X" for hit. After hit it searches for other accurences of letter . if countMarker(enemy, marker$) If there is no more of this letter, it means "kill" That means we know eaxactly there killed ship is so we could mark ajacent cells with "+" I had it rather convoluted - call mkRadarShadow2 player, r,c .it calls recursive fill .. sub paintKilled offset,r,c 'painting "x" with "#" .Then .. sub mkRadarShadow2.1 player .marks all empty neghbours of (#) with (+) .then it converts all (#) back to (x) .and restores lat shot big (X)
Now for AI part. (ha. Most of it is "not shoot twice at place you alreaduy shot" ;)) ) So AI has that "radar" map and I have this . dim prevHit$(player2) actually each player uses single string prevHit$(player1) and prevHit$(player2) If it is empty, AI have no idea where to shoot So it just creates a list of all empty cells (not hit, not shadowed by killed ship) on radar
if list$="" then list$=mkFreeList$(player+radar) end if and then just take random one
shoot$=randomSelect$(list$) r=val(word$(shoot$,1,",")) c=val(word$(shoot$,2,",")) Now if we endeed have a hit then prevHit$(player) added that hit point (so it stores all hit points of a ship) (prevHit$(player) gets cleared after kill)
If prevHit$(player) is not empty, AI creates list of possible (empty) nighbours for all cells from prevHit$(player) . list$=addNeighbourFreeList$(player+radar,r0,c0, list$) (non-repeating, with .. ist$=addUniq$(list$, r;",";c)) and then just take random one (with same piece of code as before!)
A would confess, all that list stuff definitely Python influence ;) But seems working.
Last interesting thing Then it gets first hit, it has no idea where to shoot next but it knows for sure that there no ship is possible diagonally, so . call mkRadarDiagShadow player, r,c marks radar as this
+ + X + +
So it randomly fires at empty nighbour cell, NESW direction
But after second hit we got something like this
++++ Xx ++++
You see? It gets automatically restricted to a line!
|
|
|
Post by plus on Jul 28, 2024 23:28:58 GMT
yes, and if a miss you have one end closed by "radar" OK Well the rule of no ships touching makes "the problem' which ship are you hitting with the 2nd hit NOT (a problem at all!) tsh73 thank you very much for your time in explaining, that clears things up very nicely! b = b + ...
|
|