|
Post by bplus on Jul 30, 2024 1:17:25 GMT
I got out some old Battleship code wrote up a mod of the AI and did in screen 0 without assets of sound effects or images, all Basic screen 0 text. _Title "BattleShip Mod842 View Print 2024-07-29" ' b+ 2024-07-26 port from JB ' Battleship Mod842 b+ 2024-07-25 uses a garanteed AI to find Destroyer in 50 shots ' unlike Battleship 2 which AI uses mod 3 it is screwed if fails to find Destroyer when mod 3 ' shooting covers the ocean taking something like up to 66 shots to garantee finding Destroyer. ' This code starts from my first Battleship coded for JB: ' Battleship based on Hasbro Game b+ 2024-07-23 allot of code ported out of old QB64 version ' 2024-07-26 besides port trans back to QB64, fix the showing of computer ships so only the ones ' or parts not hit with ship number. Add Sound when ship is hit.
' 2024-07-29 Oh I forgot, MessageBox does not work for older versions of QB64. ' Actually that turns out to be no problem at all!!! ' I think I can use View Print and not need my Message and Message Clear subroutines. ' This might be a very cool fix! Also I am going to work on my organization and commenting. ' OK View Print did not scroll inside the view text port so I had to cls before turning off ' View Print. I was thinking scrolling would be cool, no cls needed but no.
' Fix a bug that has been here from beginning, check player's bomb site to see if already done ' if so BEEP him, definitely don't want to sink a ship twice which is what has been happening. ' So we should use computer c() to track players shots. -1 for miss but what about when ship ' is hit??? c(x, y) = c(x, y) + 10 so if c(x, y) is > 5 and < 11 then good hit. ' if c(x,y) > 10 then already hit. BEEPing now for places already bombed plus give player another ' chance to shoot.
' Need to check place$ to see if player screwed up placement instructions, done.
' Offsets for the Game board print at top of screen P is for Player, C is for Computer ' S is for Ships Sunk tally on far right of screen (x,y) offsets: Dim Shared As Long PXO, PYO, CXO, CYO, SXO, SYO
Dim Shared As Long PTurn, GameOn ' TF players turn or not and GameOn if still running game
' internal tracking of P() Players ships, C() Computer ships Dim Shared As Long P(9, 9), C(9, 9), Hits(9, 9) ' player board, computer board and hits tracking for AI
Dim Shared As Long ShipLen(10), ShipHor(10), ShipX(10), ShipY(10), ShipSunk(10) Dim Shared ShipName$(10), ShipHits$(10) ' Ship arrays are 0 based but are really numbered 1 to 10, 0 is ignored ' ShipName$() are names of ships according to length in character cells see approx line 38 ' ShipLen() is the length or how many character cells a ship is long, 5 down to 2 according to index ' ShipHor() is a T/F value (0|-1) if it is Setup horizontal see SetUp where ships are positioned ' ShipX() and ShipY() locate the top of a ship if vertically set or the left start of ship if horizontal ' ShipHits$() tracks which cell on each ship was hit ' ShipSunk() T/F if ship has been sunk
' this stuff is for the AI for computer's turn to play Dim Shared AiShots$(50) ' AiShots sequence pattern coverage of board when c not working a hit Dim Shared As Long AiI ' index for AiShots$() Dim Shared As Long Dir ' for AI bombing testing 4 directions from last hit for more of ship hit Dim Shared As Long CurrentHits ' tracks how many hits have been made ' when ship is sunk subtract it's length Dim Shared As Long X1, Y1, BombX, BombY, Hit2 ' tracking bombs and hits for AI to sink ship ' X1, Y1 is the location of the latest hit on ship ' Bombx, Bomby is next bomb location when working a first hit ' hit2 indicates the direction we are going was success on last hit
Color 15, 9 Randomize Timer ' set one time only stuff PXO = 8: PYO = 6 ' offsets for player grid display, tracks players ships and computers shots CXO = 35: CYO = 6 ' offsets for computer grid display, player shots hit= X miss= o SXO = 68: SYO = 10 ' offsets ships sunk tally For i = 1 To 10 Select Case i Case 1: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 2: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 3: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 4: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 5: ShipLen(i) = 2: ShipName$(i) = "Destroyer" Case 6: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 7: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 8: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 9: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 10: ShipLen(i) = 2: ShipName$(i) = "Destroyer" End Select Next
While 1 'run game loop until player quits Setup Shoot Wend
Sub Setup ' get a game ready to play ' clear shared arrays and variables Erase ShipX, ShipY, ShipHor, ShipHits$, ShipSunk, P, C, Hits PTurn = 0: GameOn = 0: Dir = 0: AiI = 0: CurrentHits = 0 ' globals
'setup 2 bombing patterns to cover sea in checkerboard pattern one is chosen in each game s1$ = "A0B1C2D3E4F5G6H7I8J9I0J1A8B9E0F1G2H3I4J5A4B5C6D7E8F9C0D1E2F3G4H5I6J7A6B7C8D9G0H1I2J3A2B3C4D5E6F7G8H9" s2$ = "A9B8C7D6E5F4G3H2I1J0B0A1I9J8A5B4C3D2E1F0E9F8G7H6I5J4A3B2C1D0A7B6C5D4E3F2G1H0C9D8E7F6G5H4I3J2G9H8I7J6" If Rnd < .5 Then shots$ = s1$ Else shots$ = s2$ ' don't be predictable with bombing patterns ' shuffle sections: priority diagonal then sub diagonals, Mod 8 then mod 4 then mod 2 ReDim As Long T(50), i For i = 1 To 50: T(i) = i: Next start = 1: stp = 10: Shuffle T(), start, stp start = 11: stp = 14: Shuffle T(), start, stp start = 15: stp = 26: Shuffle T(), start, stp start = 27: stp = 50: Shuffle T(), start, stp For i = 1 To 50 ' stow into an array AiShots$(i) = Mid$(shots$, 2 * T(i) - 1, 2) Next Cls ' Game Board draw once per game Print "" Print " Player Computer" Print "" Print " A B C D E F G H I J A B C D E F G H I J" Print " ------------------- -------------------" Print " 0| . . . . . . . . . . 0| . . . . . . . . . ." Print " 1| . . . . . . . . . . 1| . . . . . . . . . ." Print " 2| . . . . . . . . . . 2| . . . . . . . . . ." Print " 3| . . . . . . . . . . 3| . . . . . . . . . . Ships: P C" Print " 4| . . . . . . . . . . 4| . . . . . . . . . . Carrier . ." Print " 5| . . . . . . . . . . 5| . . . . . . . . . . Battleship . ." Print " 6| . . . . . . . . . . 6| . . . . . . . . . . Cruiser . ." Print " 7| . . . . . . . . . . 7| . . . . . . . . . . Submarine . ." Print " 8| . . . . . . . . . . 8| . . . . . . . . . . Destroyer . ." Print " 9| . . . . . . . . . . 9| . . . . . . . . . ." Print " ------------------- -------------------" Print " A B C D E F G H I J A B C D E F G H I J"
'locate 6, 5: print "X" ' check offsets
' debugg check AIshots$((aiI) OK 'For i = 1 To 50 'double check checker board coverage 50 cells in priority order ' x = InStr("ABCDEFGHIJ", Left$(AiShots$(i), 1)) - 1 ' y = Val(Mid$(AiShots$(i), 2, 1)) ' LP x, y, "p", "O" ' _Delay 1 'Next
For i = 1 To 10 ' restring ship hits to all clear no hits ShipHits$(i) = String$(ShipLen(i), "o") Next Autosetup 1 'setup the Computers ships offer to that for player View Print 20 To 25 Print " Let computer setup your ships? press y for yes, n for no..." k$ = UCase$(Input$(1)) Cls View Print
If k$ = "Y" Then Autosetup 0 Else For s = 1 To 5 ' do it yourself ship placement OK = 0 While OK = 0 placeAgain: View Print 20 To 25 Print " Setting up the " + ShipName$(s) + " with length" + Str$(ShipLen(s)) Print " To place ship:" Print " Enter v for vertical, h for horizontal, letter and digit for top, left of ship" Input " Placement "; place$ Cls View Print ' turn off view place$ = UCase$(place$) ' check place If Left$(place$, 1) <> "V" And Left$(place$, 1) <> "H" Then Beep: GoTo placeAgain sx = InStr("ABCDEFGHIJ", Mid$(place$, 2, 1)) If sx < 1 Or sx > 10 Then Beep: GoTo placeAgain Else sx = sx - 1 sy = InStr("0123456789", Mid$(place$, 3, 1)) If sy < 1 Or sy > 10 Then Beep: GoTo placeAgain Else sy = sy - 1
If Left$(place$, 1) = "V" Then ShipHor(s) = 0 Else ShipHor(s) = 1 If ShipHor(s) Then ' layout ship horiz If sx <= 10 - ShipLen(s) Then OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If End If Else ' layout vertical If sy <= 10 - ShipLen(s) Then OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If End If Wend Next End If End Sub
Sub Autosetup (AItf As Long) If AItf Then 'setup Computer's ships 'setup a board with ships, Computer or AI's setup For s = 6 To 10 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If C(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 C(sx + xx, sy) = s 'LP sx + xx, sy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If C(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 C(sx, sy + yy) = s 'LP sx, sy + yy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If End If Wend Next Else 'setup Player's ships For s = 1 To 5 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If Wend Next End If End Sub
Sub FYI (Info$) ' in place of a MessageBox Sound 3000, 4 Color 10, 1 View Print 20 To 25 Print Space$(3); Info$ + " ...zzz" Sleep 3 Cls View Print Color 15, 1 End Sub
Sub LP (x As Long, y As Long, pcGrid$, s$) If pcGrid$ = "p" Then Locate PYO + y, PXO + 2 * x Else Locate CYO + y, CXO + 2 * x Print s$; End Sub
Function Rand& (low As Long, high As Long) ' Random integer from low to high inclusive Rand& = Int(Rnd * (high - low + 1)) + low End Function
Sub Shoot GameOn = 1 While GameOn If PTurn Then PTurn = 0 Else PTurn = 1 If PTurn Then ' player playerAgain: View Print 20 To 25 Input " Enter your next bomb site letter digit "; place$ Cls View Print If place$ = "" Then GameOn = 0 place$ = UCase$(place$) bx = InStr("ABCDEFGHIJ", Left$(place$, 1)) - 1 by = Val(Mid$(place$, 2, 1)) If bx >= 0 And bx < 10 Then ' better check If by >= 0 And by < 10 Then If C(bx, by) = 0 Then 'miss LP bx, by, "c", "o" C(bx, by) = -1 ElseIf C(bx, by) > 5 And C(bx, by) < 11 Then 'hit LP bx, by, "c", "X" Sound 200, 2 HitEval "c", bx, by 'game could end here C(bx, by) = C(bx, by) + 10 ' signal we hit this spot already! ElseIf C(bx, by) = -1 Or C(bx, by) > 10 Then Beep: GoTo playerAgain End If End If End If Else 'AI's turn if it gets a hit it will bomb around the ship until it is finished 'could be trouble if 2 ships are next to each other. Some effort to work it, 'still might get confused. 'hits() array tracks red = 1 and white pegs = -1 like a human player for AI
If Dir Then 'we are working around the latest hit with bombx, bomby to test If P(BombX, BombY) <> 0 Then 'hit! Hit2 = 1 ' found 2nd hit neighbor of first hi could be another ship Hits(BombX, BombY) = 1: CurrentHits = CurrentHits + 1 LP BombX, BombY, "p", "X" 'when hitEval announces a ship sunk we can reduce the currentHits count 'by that ships amount if still have more current hits, continue bombing ' area as another ship is there Sound 2000, 2 ' wakeup player! HitEval "p", BombX, BombY ' this will reduce currentHits by the amount ' a ship would take when sunk If CurrentHits = 0 Then ' clear our checklist we sank all ships we hit, ' call off bombing of area X1 = 0: Y1 = 0: Dir = 0 Else DecideWhereToBombNext End If Else 'no hit from checklist scratch off one item Hit2 = 0 Hits(BombX, BombY) = -1 LP BombX, BombY, "p", "o" DecideWhereToBombNext End If ' are we still working on hit Else 'not working on any hits x1, y1 = 0, dir = 0, currentHits might be = 0 'random but systematic shooting, bring up next good shooting location alreadyHit: AiI = AiI + 1 ' next random shoot If AiI > 50 Then ' we should never get this far but just in case x = Rand(0, 9) y = Rand(0, 9) Else ' normal shooting pattern by diagonals to form checker board coverage x = InStr("ABCDEFGHIJ", Left$(AiShots$(AiI), 1)) - 1 y = Val(Mid$(AiShots$(AiI), 2, 1)) End If If Hits(x, y) <> 0 Then GoTo alreadyHit
' was that shot just fired a hit or miss If P(x, y) <> 0 Then ' test our shot just fired is hit! X1 = x: Y1 = y 'save first hit to come back to Hits(X1, Y1) = 1: CurrentHits = CurrentHits + 1 LP X1, Y1, "p", "X" Sound 2000, 2 ' wakeup player! HitEval "p", X1, Y1 'did we just happen to finish off a ship? current hits = 0 If CurrentHits = 0 Then 'must of finished off an ship X1 = 0: Y1 = 0: Dir = 0 'we are done Else Dir = -1 ' this signals we are working on a hit DecideWhereToBombNext End If Else 'no hit Hits(x, y) = -1 LP x, y, "p", "o" End If End If 'rI was hit or not End If 'whose turn is it _Delay 1.5 ' a sec pause to allow us to see computers move Wend View Print 20 To 25 Print " Play Again? press y for yes, n for no..." k$ = Input$(1) Cls View Print If k$ = "n" Then End End Sub
Sub HitEval (board$, bbx, bby) 'this is like a referee for both players to announce a ship sunk and a game won? If board$ <> "p" Then s = C(bbx, bby) ' which ship number you$ = "Player": my$ = "Computer's" istart = 6: istop = 10 Else s = P(bbx, bby) you$ = "Computer": my$ = "Player's" istart = 1: istop = 5 End If If ShipHor(s) Then D = bbx - ShipX(s) + 1 Else D = bby - ShipY(s) + 1 Mid$(ShipHits$(s), D, 1) = "X" If ShipHits$(s) = String$(ShipLen(s), "X") Then ShipSunk(s) = 1 If board$ = "p" Then CurrentHits = CurrentHits - ShipLen(s) UpdateStatus FYI "Congrats: " + you$ + " sank " + my$ + " " + ShipName$(s) + "!" tot = 0 For i = istart To istop If ShipSunk(i) = 1 Then tot = tot + 1 Next If tot = 5 Then UpdateStatus If you$ = "Computer" Then ShowComputersShips FYI "Congrats: " + you$ + ", you sank all " + my$ + " ships! Game Over" GameOn = 0 End If End If End Sub
Sub DecideWhereToBombNext 'find next good location, mark the direction we took If Dir = -1 Then ' new hit Hit2 = 0 'when direction = 0 reset 2nd hit signal to 0 If X1 + 1 <= 9 Then If Hits(X1 + 1, Y1) = 0 Then BombX = X1 + 1: BombY = Y1: Dir = 1: Exit Sub End If End If 'still here? If Y1 + 1 <= 9 Then If Hits(X1, Y1 + 1) = 0 Then BombX = X1: BombY = Y1 + 1: Dir = 2: Exit Sub End If End If 'still here? If X1 - 1 >= 0 Then If Hits(X1 - 1, Y1) = 0 Then BombX = X1 - 1: BombY = Y1: Dir = 3: Exit Sub End If End If 'still here OK this has to do it! If Y1 - 1 >= 0 Then If Hits(X1, Y1 - 1) = 0 Then BombX = X1: BombY = Y1 - 1: Dir = 4: Exit Sub End If End If 'still here ???? damn! give up and go back to random shots Dir = 0: Exit Sub ' < this signals that End If
'setup next bombx, bomby If Hit2 Then 'whatever direction we are taking, continue if we can Select Case Dir Case 1 If BombX + 1 <= 9 Then If Hits(BombX + 1, BombY) = 0 Then BombX = BombX + 1: Exit Sub End If End If Case 2 If BombY + 1 <= 9 Then If Hits(BombX, BombY + 1) = 0 Then BombY = BombY + 1: Exit Sub End If End If Case 3 If BombX - 1 >= 0 Then If Hits(BombX - 1, BombY) = 0 Then BombX = BombX - 1: Exit Sub End If End If Case 4 If BombY - 1 >= 0 Then If Hits(BombX, BombY - 1) = 0 Then BombY = BombY - 1: Dir = 4: Exit Sub End If End If End Select End If
'still here? then we have to change direction and go back to x1, y1 the first hit Hit2 = 0 'reset this for the new direction check While Dir < 4 Dir = Dir + 1 Select Case Dir Case 2 If Y1 + 1 <= 9 Then If Hits(X1, Y1 + 1) = 0 Then BombX = X1: BombY = Y1 + 1: Exit Sub End If End If Case 3 If X1 - 1 >= 0 Then If Hits(X1 - 1, Y1) = 0 Then BombX = X1 - 1: BombY = Y1: Exit Sub End If End If Case 4 If Y1 - 1 >= 0 Then If Hits(X1, Y1 - 1) = 0 Then BombX = X1: BombY = Y1 - 1: Exit Sub End If End If End Select Wend 'still here, well we've run out of directions Dir = 0 'back to random bombing End Sub
Sub UpdateStatus ' ships area For i = 1 To 5 ' row 10 carrier player colum 66 computer column 68 If ShipSunk(i) Then Locate i + 9, 68,: Print "X"; If ShipSunk(i + 5) Then Locate i + 9, 70: Print "X" Next End Sub
Sub ShowComputersShips ' fixed this so only empty spaces not bombed are displayed For s = 6 To 10 If ShipHor(s) Then sx = ShipX(s): sy = ShipY(s) For xx = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), xx + 1, 1) = "o" Then LP sx + xx, sy, "c", _Trim$(Str$(s Mod 10)) End If Next Else sx = ShipX(s): sy = ShipY(s) For yy = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), yy + 1, 1) = "o" Then LP sx, sy + yy, "c", _Trim$(Str$(s Mod 10)) End If Next End If Next End Sub
Sub Shuffle (a() As Long, start, stp) ' used to randomize shooting pattern a bit For i = stp To start + 1 Step -1 Swap a(i), a(Rand(start, i)) Next End Sub
The AI is pretty good but beatable:
|
|
|
Post by bplus on Jul 30, 2024 19:05:47 GMT
Computer AI: The Movie Watch the drama unfold as the computer AI hunts down and sinks your ships! _Title "BS Mod842 AI Movie 2024-07-30" ' b+ 2024-07-26 port from JB ' Battleship Mod842 b+ 2024-07-25 uses a garanteed AI to find Destroyer in 50 shots ' unlike Battleship 2 which AI uses mod 3 it is screwed if fails to find Destroyer when mod 3 ' shooting covers the ocean taking something like up to 66 shots to garantee finding Destroyer. ' This code starts from my first Battleship coded for JB: ' Battleship based on Hasbro Game b+ 2024-07-23 allot of code ported out of old QB64 version ' 2024-07-26 besides port trans back to QB64, fix the showing of computer ships so only the ones ' or parts not hit with ship number. Add Sound when ship is hit.
' 2024-07-29 Oh I forgot, MessageBox does not work for older versions of QB64. ' Actually that turns out to be no problem at all!!! ' I think I can use View Print and not need my Message and Message Clear subroutines. ' This might be a very cool fix! Also I am going to work on my organization and commenting. ' OK View Print did not scroll inside the view text port so I had to cls before turning off ' View Print. I was thinking scrolling would be cool, no cls needed but no.
' Fix a bug that has been here from beginning, check player's bomb site to see if already done ' if so BEEP him, definitely don't want to sink a ship twice which is what has been happening. ' So we should use computer c() to track players shots. -1 for miss but what about when ship ' is hit??? c(x, y) = c(x, y) + 10 so if c(x, y) is > 5 and < 11 then good hit. ' if c(x,y) > 10 then already hit. BEEPing now for places already bombed plus give player another ' chance to shoot.
' Need to check place$ to see if player screwed up placement instructions, done.
' 2024-07-30 BS Mod842 AI Movie - last night I got this great idea and want to share it. ' This Movie shows The Computer AI in action finding and sinking ships, it does so with ' minimum interruption from viewer/Player. I do want to set it so the Player can setup ' tricky ship placements to test how well the AI handles them, also excellent tool to ' improve the AI because just watching a number of these I see AI failures clearly some ' holes left in coverage...
' Offsets for the Game board print at top of screen P is for Player, C is for Computer ' S is for Ships Sunk tally on far right of screen (x,y) offsets: Dim Shared As Long PXO, PYO, CXO, CYO, SXO, SYO
Dim Shared As Long PTurn, GameOn ' TF players turn or not and GameOn if still running game
' internal tracking of P() Players ships, C() Computer ships Dim Shared As Long P(9, 9), C(9, 9), Hits(9, 9) ' player board, computer board and hits tracking for AI
Dim Shared As Long ShipLen(10), ShipHor(10), ShipX(10), ShipY(10), ShipSunk(10) Dim Shared ShipName$(10), ShipHits$(10) ' Ship arrays are 0 based but are really numbered 1 to 10, 0 is ignored ' ShipName$() are names of ships according to length in character cells see approx line 38 ' ShipLen() is the length or how many character cells a ship is long, 5 down to 2 according to index ' ShipHor() is a T/F value (0|-1) if it is Setup horizontal see SetUp where ships are positioned ' ShipX() and ShipY() locate the top of a ship if vertically set or the left start of ship if horizontal ' ShipHits$() tracks which cell on each ship was hit ' ShipSunk() T/F if ship has been sunk
' this stuff is for the AI for computer's turn to play Dim Shared AiShots$(50) ' AiShots sequence pattern coverage of board when c not working a hit Dim Shared As Long AiI ' index for AiShots$() Dim Shared As Long Dir ' for AI bombing testing 4 directions from last hit for more of ship hit Dim Shared As Long CurrentHits ' tracks how many hits have been made ' when ship is sunk subtract it's length Dim Shared As Long X1, Y1, BombX, BombY, Hit2 ' tracking bombs and hits for AI to sink ship ' X1, Y1 is the location of the latest hit on ship ' Bombx, Bomby is next bomb location when working a first hit ' hit2 indicates the direction we are going was success on last hit
Color 15, 9 Randomize Timer ' set one time only stuff PXO = 8: PYO = 6 ' offsets for player grid display, tracks players ships and computers shots CXO = 35: CYO = 6 ' offsets for computer grid display, player shots hit= X miss= o SXO = 68: SYO = 10 ' offsets ships sunk tally For i = 1 To 10 Select Case i Case 1: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 2: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 3: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 4: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 5: ShipLen(i) = 2: ShipName$(i) = "Destroyer" Case 6: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 7: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 8: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 9: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 10: ShipLen(i) = 2: ShipName$(i) = "Destroyer" End Select Next
While 1 'run game loop until player quits Setup Shoot Wend
Sub Setup ' get a game ready to play ' clear shared arrays and variables Erase ShipX, ShipY, ShipHor, ShipHits$, ShipSunk, P, C, Hits PTurn = 0: GameOn = 0: Dir = 0: AiI = 0: CurrentHits = 0 ' globals
'setup 2 bombing patterns to cover sea in checkerboard pattern one is chosen in each game s1$ = "A0B1C2D3E4F5G6H7I8J9I0J1A8B9E0F1G2H3I4J5A4B5C6D7E8F9C0D1E2F3G4H5I6J7A6B7C8D9G0H1I2J3A2B3C4D5E6F7G8H9" s2$ = "A9B8C7D6E5F4G3H2I1J0B0A1I9J8A5B4C3D2E1F0E9F8G7H6I5J4A3B2C1D0A7B6C5D4E3F2G1H0C9D8E7F6G5H4I3J2G9H8I7J6" 'If Rnd < .5 Then shots$ = s1$ Else shots$ = s2$ ' don't be predictable with bombing patterns shots$ = s1$ ' shuffle sections: priority diagonal then sub diagonals, Mod 8 then mod 4 then mod 2 ReDim As Long T(50), i For i = 1 To 50: T(i) = i: Next ' don't shuffle want to test with predictable bombing 'start = 1: stp = 10: Shuffle T(), start, stp 'start = 11: stp = 14: Shuffle T(), start, stp 'start = 15: stp = 26: Shuffle T(), start, stp 'start = 27: stp = 50: Shuffle T(), start, stp For i = 1 To 50 ' stow into an array AiShots$(i) = Mid$(shots$, 2 * T(i) - 1, 2) Next Cls ' Game Board draw once per game Print "" Print " Player Computer" Print "" Print " A B C D E F G H I J A B C D E F G H I J" Print " ------------------- -------------------" Print " 0| . . . . . . . . . . 0| . . . . . . . . . ." Print " 1| . . . . . . . . . . 1| . . . . . . . . . ." Print " 2| . . . . . . . . . . 2| . . . . . . . . . ." Print " 3| . . . . . . . . . . 3| . . . . . . . . . . Ships: P C" Print " 4| . . . . . . . . . . 4| . . . . . . . . . . Carrier . ." Print " 5| . . . . . . . . . . 5| . . . . . . . . . . Battleship . ." Print " 6| . . . . . . . . . . 6| . . . . . . . . . . Cruiser . ." Print " 7| . . . . . . . . . . 7| . . . . . . . . . . Submarine . ." Print " 8| . . . . . . . . . . 8| . . . . . . . . . . Destroyer . ." Print " 9| . . . . . . . . . . 9| . . . . . . . . . ." Print " ------------------- -------------------" Print " A B C D E F G H I J A B C D E F G H I J"
'locate 6, 5: print "X" ' check offsets
' debugg check AIshots$((aiI) OK 'For i = 1 To 50 'double check checker board coverage 50 cells in priority order ' x = InStr("ABCDEFGHIJ", Left$(AiShots$(i), 1)) - 1 ' y = Val(Mid$(AiShots$(i), 2, 1)) ' LP x, y, "p", "O" ' _Delay 1 'Next
For i = 1 To 10 ' restring ship hits to all clear no hits ShipHits$(i) = String$(ShipLen(i), "o") Next Autosetup 1 'setup the Computers ships offer to that for player View Print 20 To 25 Print " Let computer setup your ships? press y for yes, n for no..." k$ = UCase$(Input$(1)) Cls View Print
If k$ = "Y" Then Autosetup 0 Else For s = 1 To 5 ' do it yourself ship placement OK = 0 While OK = 0 placeAgain: View Print 20 To 25 Print " Setting up the " + ShipName$(s) + " with length" + Str$(ShipLen(s)) Print " To place ship:" Print " Enter v for vertical, h for horizontal, letter and digit for top, left of ship" Input " Placement "; place$ Cls View Print ' turn off view place$ = UCase$(place$) ' check place If Left$(place$, 1) <> "V" And Left$(place$, 1) <> "H" Then Beep: GoTo placeAgain sx = InStr("ABCDEFGHIJ", Mid$(place$, 2, 1)) If sx < 1 Or sx > 10 Then Beep: GoTo placeAgain Else sx = sx - 1 sy = InStr("0123456789", Mid$(place$, 3, 1)) If sy < 1 Or sy > 10 Then Beep: GoTo placeAgain Else sy = sy - 1
If Left$(place$, 1) = "V" Then ShipHor(s) = 0 Else ShipHor(s) = 1 If ShipHor(s) Then ' layout ship horiz If sx <= 10 - ShipLen(s) Then OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If End If Else ' layout vertical If sy <= 10 - ShipLen(s) Then OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If End If Wend Next End If End Sub
Sub Autosetup (AItf As Long) If AItf Then 'setup Computer's ships 'setup a board with ships, Computer or AI's setup For s = 6 To 10 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If C(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 C(sx + xx, sy) = s 'LP sx + xx, sy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If C(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 C(sx, sy + yy) = s 'LP sx, sy + yy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If End If Wend Next Else 'setup Player's ships For s = 1 To 5 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If Wend Next End If End Sub
Sub FYI (Info$) ' in place of a MessageBox Sound 3000, 4 Color 10, 1 View Print 20 To 25 Print Space$(3); Info$ + " ...zzz" Sleep 3 Cls View Print Color 15, 1 End Sub
Sub LP (x As Long, y As Long, pcGrid$, s$) If pcGrid$ = "p" Then Locate PYO + y, PXO + 2 * x Else Locate CYO + y, CXO + 2 * x Print s$; End Sub
Function Rand& (low As Long, high As Long) ' Random integer from low to high inclusive Rand& = Int(Rnd * (high - low + 1)) + low End Function
Sub Shoot GameOn = 1 While GameOn 'If PTurn Then PTurn = 0 Else PTurn = 1 PTurn = 0 ' for the AI Movie If PTurn Then ' player playerAgain: View Print 20 To 25 Input " Enter your next bomb site letter digit "; place$ Cls View Print If place$ = "" Then GameOn = 0 place$ = UCase$(place$) bx = InStr("ABCDEFGHIJ", Left$(place$, 1)) - 1 by = Val(Mid$(place$, 2, 1)) If bx >= 0 And bx < 10 Then ' better check If by >= 0 And by < 10 Then If C(bx, by) = 0 Then 'miss LP bx, by, "c", "o" C(bx, by) = -1 ElseIf C(bx, by) > 5 And C(bx, by) < 11 Then 'hit LP bx, by, "c", "X" Sound 200, 2 HitEval "c", bx, by 'game could end here C(bx, by) = C(bx, by) + 10 ' signal we hit this spot already! ElseIf C(bx, by) = -1 Or C(bx, by) > 10 Then Beep: GoTo playerAgain End If End If End If Else 'AI's turn if it gets a hit it will bomb around the ship until it is finished 'could be trouble if 2 ships are next to each other. Some effort to work it, 'still might get confused. 'hits() array tracks red = 1 and white pegs = -1 like a human player for AI
If Dir Then 'we are working around the latest hit with bombx, bomby to test If P(BombX, BombY) <> 0 Then 'hit! Hit2 = 1 ' found 2nd hit neighbor of first hi could be another ship Hits(BombX, BombY) = 1: CurrentHits = CurrentHits + 1 LP BombX, BombY, "p", "X" 'when hitEval announces a ship sunk we can reduce the currentHits count 'by that ships amount if still have more current hits, continue bombing ' area as another ship is there Sound 2000, 2 ' wakeup player! HitEval "p", BombX, BombY ' this will reduce currentHits by the amount ' a ship would take when sunk If CurrentHits = 0 Then ' clear our checklist we sank all ships we hit, ' call off bombing of area X1 = 0: Y1 = 0: Dir = 0 Else DecideWhereToBombNext End If Else 'no hit from checklist scratch off one item Hit2 = 0 Hits(BombX, BombY) = -1 LP BombX, BombY, "p", "o" DecideWhereToBombNext End If ' are we still working on hit Else 'not working on any hits x1, y1 = 0, dir = 0, currentHits might be = 0 'random but systematic shooting, bring up next good shooting location alreadyHit: AiI = AiI + 1 ' next random shoot If AiI > 50 Then ' we should never get this far but just in case x = Rand(0, 9) y = Rand(0, 9) Else ' normal shooting pattern by diagonals to form checker board coverage x = InStr("ABCDEFGHIJ", Left$(AiShots$(AiI), 1)) - 1 y = Val(Mid$(AiShots$(AiI), 2, 1)) End If If Hits(x, y) <> 0 Then GoTo alreadyHit
' was that shot just fired a hit or miss If P(x, y) <> 0 Then ' test our shot just fired is hit! X1 = x: Y1 = y 'save first hit to come back to Hits(X1, Y1) = 1: CurrentHits = CurrentHits + 1 LP X1, Y1, "p", "X" Sound 2000, 2 ' wakeup player! HitEval "p", X1, Y1 'did we just happen to finish off a ship? current hits = 0 If CurrentHits = 0 Then 'must of finished off an ship X1 = 0: Y1 = 0: Dir = 0 'we are done Else Dir = -1 ' this signals we are working on a hit DecideWhereToBombNext End If Else 'no hit Hits(x, y) = -1 LP x, y, "p", "o" End If End If 'rI was hit or not End If 'whose turn is it _Delay 1 ' a sec pause to allow us to see computers move Wend View Print 20 To 25 Print " Play Again? press y for yes, n for no..." k$ = Input$(1) Cls View Print If k$ = "n" Then End End Sub
Sub HitEval (board$, bbx, bby) 'this is like a referee for both players to announce a ship sunk and a game won? If board$ <> "p" Then s = C(bbx, bby) ' which ship number you$ = "Player": my$ = "Computer's" istart = 6: istop = 10 Else s = P(bbx, bby) you$ = "Computer": my$ = "Player's" istart = 1: istop = 5 End If If ShipHor(s) Then D = bbx - ShipX(s) + 1 Else D = bby - ShipY(s) + 1 Mid$(ShipHits$(s), D, 1) = "X" If ShipHits$(s) = String$(ShipLen(s), "X") Then ShipSunk(s) = 1 If board$ = "p" Then CurrentHits = CurrentHits - ShipLen(s) UpdateStatus FYI "Congrats: " + you$ + " sank " + my$ + " " + ShipName$(s) + "!" tot = 0 For i = istart To istop If ShipSunk(i) = 1 Then tot = tot + 1 Next If tot = 5 Then UpdateStatus If you$ = "Computer" Then ShowComputersShips FYI "Congrats: " + you$ + ", you sank all " + my$ + " ships! Game Over" GameOn = 0 End If End If End Sub
Sub DecideWhereToBombNext 'find next good location, mark the direction we took If Dir = -1 Then ' new hit Hit2 = 0 'when direction = 0 reset 2nd hit signal to 0 If X1 + 1 <= 9 Then If Hits(X1 + 1, Y1) = 0 Then BombX = X1 + 1: BombY = Y1: Dir = 1: Exit Sub End If End If 'still here? If Y1 + 1 <= 9 Then If Hits(X1, Y1 + 1) = 0 Then BombX = X1: BombY = Y1 + 1: Dir = 2: Exit Sub End If End If 'still here? If X1 - 1 >= 0 Then If Hits(X1 - 1, Y1) = 0 Then BombX = X1 - 1: BombY = Y1: Dir = 3: Exit Sub End If End If 'still here OK this has to do it! If Y1 - 1 >= 0 Then If Hits(X1, Y1 - 1) = 0 Then BombX = X1: BombY = Y1 - 1: Dir = 4: Exit Sub End If End If 'still here ???? damn! give up and go back to random shots Dir = 0: Exit Sub ' < this signals that End If
'setup next bombx, bomby If Hit2 Then 'whatever direction we are taking, continue if we can Select Case Dir Case 1 If BombX + 1 <= 9 Then If Hits(BombX + 1, BombY) = 0 Then BombX = BombX + 1: Exit Sub End If End If Case 2 If BombY + 1 <= 9 Then If Hits(BombX, BombY + 1) = 0 Then BombY = BombY + 1: Exit Sub End If End If Case 3 If BombX - 1 >= 0 Then If Hits(BombX - 1, BombY) = 0 Then BombX = BombX - 1: Exit Sub End If End If Case 4 If BombY - 1 >= 0 Then If Hits(BombX, BombY - 1) = 0 Then BombY = BombY - 1: Dir = 4: Exit Sub End If End If End Select End If
'still here? then we have to change direction and go back to x1, y1 the first hit Hit2 = 0 'reset this for the new direction check While Dir < 4 Dir = Dir + 1 Select Case Dir Case 2 If Y1 + 1 <= 9 Then If Hits(X1, Y1 + 1) = 0 Then BombX = X1: BombY = Y1 + 1: Exit Sub End If End If Case 3 If X1 - 1 >= 0 Then If Hits(X1 - 1, Y1) = 0 Then BombX = X1 - 1: BombY = Y1: Exit Sub End If End If Case 4 If Y1 - 1 >= 0 Then If Hits(X1, Y1 - 1) = 0 Then BombX = X1: BombY = Y1 - 1: Exit Sub End If End If End Select Wend 'still here, well we've run out of directions Dir = 0 'back to random bombing End Sub
Sub UpdateStatus ' ships area For i = 1 To 5 ' row 10 carrier player colum 66 computer column 68 If ShipSunk(i) Then Locate i + 9, 68,: Print "X"; If ShipSunk(i + 5) Then Locate i + 9, 70: Print "X" Next End Sub
Sub ShowComputersShips ' fixed this so only empty spaces not bombed are displayed For s = 6 To 10 If ShipHor(s) Then sx = ShipX(s): sy = ShipY(s) For xx = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), xx + 1, 1) = "o" Then LP sx + xx, sy, "c", _Trim$(Str$(s Mod 10)) End If Next Else sx = ShipX(s): sy = ShipY(s) For yy = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), yy + 1, 1) = "o" Then LP sx, sy + yy, "c", _Trim$(Str$(s Mod 10)) End If Next End If Next End Sub
Sub Shuffle (a() As Long, start, stp) ' used to randomize shooting pattern a bit For i = stp To start + 1 Step -1 Swap a(i), a(Rand(start, i)) Next End Sub Also makes a great tool to test and improve the AI with tricky ship positioning in attempts to befuddle the AI.
|
|
|
Post by bplus on Aug 2, 2024 9:09:46 GMT
Ultimate Computer AI Using hints from problems found in certain setups from Computer AI: The Movie, I have perfected the AI so that if while sinking a ship it gets part of another, it will pursue the other until finished and if another ship is hit as well then it will pursue it too... before resuming search for ships with random wave patterns of bombs. Here is the movie, not much different in action to previous but try out these setups on both versions: vj5 hd9 vd2 va2 ha2 vg2 hg8 ve6 vb7 hi9 _Title "BS Mod842 Counting Hits 1 2024-08-01" ' b+ 2024-07-26 port from JB ' Battleship Mod842 b+ 2024-07-25 uses a garanteed AI to find Destroyer in 50 shots ' unlike Battleship 2 which AI uses mod 3 it is screwed if fails to find Destroyer when mod 3 ' shooting covers the ocean taking something like up to 66 shots to garantee finding Destroyer. ' This code starts from my first Battleship coded for JB: ' Battleship based on Hasbro Game b+ 2024-07-23 allot of code ported out of old QB64 version ' 2024-07-26 besides port trans back to QB64, fix the showing of computer ships so only the ones ' or parts not hit with ship number. Add Sound when ship is hit.
' 2024-07-29 Oh I forgot, MessageBox does not work for older versions of QB64. ' Actually that turns out to be no problem at all!!! ' I think I can use View Print and not need my Message and Message Clear subroutines. ' This might be a very cool fix! Also I am going to work on my organization and commenting. ' OK View Print did not scroll inside the view text port so I had to cls before turning off ' View Print. I was thinking scrolling would be cool, no cls needed but no.
' Fix a bug that has been here from beginning, check player's bomb site to see if already done ' if so BEEP him, definitely don't want to sink a ship twice which is what has been happening. ' So we should use computer c() to track players shots. -1 for miss but what about when ship ' is hit??? c(x, y) = c(x, y) + 10 so if c(x, y) is > 5 and < 11 then good hit. ' if c(x,y) > 10 then already hit. BEEPing now for places already bombed plus give player another ' chance to shoot.
' Need to check place$ to see if player screwed up placement instructions, done.
' 2024-07-30 BS Mod842 AI Movie - last night I got this great idea and want to share it. ' This Movie shows The Computer AI in action finding and sinking ships, it does so with ' minimum interruption from viewer/Player. I do want to set it so the Player can setup ' tricky ship placements to test how well the AI handles them, also excellent tool to ' improve the AI because just watching a number of these I see AI failures clearly some ' holes left in coverage...
' 2024-07-30 BS Mod842 AI Movie 2 tsh suggest if running successfully one way and stop ' the reverse direction and go opposite ie heading dir 1 right then go left if stopped.
' 2024-07-31 still with Movie 2 - Take out View Print with Locate and ClearPartial sub ' to clear only bottom part of screen. Now I have code portable to all Basics.
' 2024-08-01 BS Mod 842 Counting Hits as posted at JB today: ' ========================================================================================================= ' I am studying cases when/where AI fails to sustain an attack when current hits > 0 after a ship is sunk. ' The attack needs to persist for the original hit area until currentHits is zero, = no ships left in ' area of first hit in sequence after random fire gets a first hit. ' ' Towards that end I need to restructure: ' Add HitX(), HitY() track where we have hits 1, 0 for untested ' yet I suppose we have to track if missed at that spot too, -1 ' that would replace X1, Y1 with the array ordered by hitIndex ' kinda of confused at moment to include misses or not. ' BTW 17 is max amount of hits possible if you hit everything on Board, could have a cluster convoy. ' ' Dir() = 0 1 2 3 4 test all 4 directions for each hit, 0 no direction tested, ' 5 = all directions tested and so hitIndex for that place is played out ' ' the 3 (new arrays) above are indexed with hitIndex (global) ' ' When currentHits does go to 0 after all ships sunk then call new ZeroOutHits sub ' ' Maybe need a tryThisIndexNext global also when deciding where to bomb next, ' set to 1 in ZeroOut This would track where we are in the hit List. ' ' Well that sketches out my next mods and experiment towards a more intelligent AI. ' There, you 'all have it in my words before the code is written! :) ' ========================================================================================================= ' note: previous version had Dir2 that never got used
' oh I need 4 arrays for 4 directions possible because can't depend on directions going in order from ' 1 to 4.
' Offsets for the Game board print at top of screen P is for Player, C is for Computer ' S is for Ships Sunk tally on far right of screen (x,y) offsets: Dim Shared As Long PXO, PYO, CXO, CYO, SXO, SYO
Dim Shared As Long PTurn, GameOn ' TF players turn or not and GameOn if still running game
' internal tracking of P() Players ships, C() Computer ships Dim Shared As Long P(9, 9), C(9, 9), Hits(9, 9) ' player board, computer board and hits tracking for AI
Dim Shared As Long ShipLen(10), ShipHor(10), ShipX(10), ShipY(10), ShipSunk(10) Dim Shared ShipName$(10), ShipHits$(10) ' Ship arrays are 0 based but are really numbered 1 to 10, 0 is ignored ' ShipName$() are names of ships according to length in character cells see approx line 38 ' ShipLen() is the length or how many character cells a ship is long, 5 down to 2 according to index ' ShipHor() is a T/F value (0|-1) if it is Setup horizontal see SetUp where ships are positioned ' ShipX() and ShipY() locate the top of a ship if vertically set or the left start of ship if horizontal ' ShipHits$() tracks which cell on each ship was hit ' ShipSunk() T/F if ship has been sunk
' this stuff is for the AI for computer's turn to play Dim Shared AiShots$(50) ' AiShots sequence pattern coverage of board when c not working a hit Dim Shared As Long AiI ' index for AiShots$() Dim Shared As Long Dir ' for AI bombing testing 4 directions from last hit for more of ship hit
Dim Shared As Long CurrentHits ' tracks how many hits have been made ' when ship is sunk subtract it's length Dim Shared As Long BombX, BombY, Hit2 ' tracking bombs and hits for AI to sink ship ' Bombx, Bomby is next bomb location when working a first hit area ' Hit2 indicates the direction we are going was success on last hit, keep going!
' new for Counting Hits D1 east right, D2, west left, D3 down south, D4 up North ReDim Shared As Long HitX(17), HitY(17), D1(17), D2(17), D3(17), D4(17), HitI, tryNextI ' HitI is HitIndex tryNextI tracks open slots of left of currentHits to shoot around
Color 15, 9 Randomize Timer ' set one time only stuff PXO = 8: PYO = 6 ' offsets for player grid display, tracks players ships and computers shots CXO = 35: CYO = 6 ' offsets for computer grid display, player shots hit= X miss= o SXO = 68: SYO = 10 ' offsets ships sunk tally For i = 1 To 10 Select Case i Case 1: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 2: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 3: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 4: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 5: ShipLen(i) = 2: ShipName$(i) = "Destroyer" Case 6: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 7: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 8: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 9: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 10: ShipLen(i) = 2: ShipName$(i) = "Destroyer" End Select Next
While 1 'run game loop until player quits Setup Shoot Wend
Sub Setup ' get a game ready to play ' clear shared arrays and variables Erase ShipX, ShipY, ShipHor, ShipHits$, ShipSunk, P, C, Hits PTurn = 0: GameOn = 0: AiI = 0: CurrentHits = 0 ' globals
'setup 2 bombing patterns to cover sea in checkerboard pattern one is chosen in each game s1$ = "A0B1C2D3E4F5G6H7I8J9I0J1A8B9E0F1G2H3I4J5A4B5C6D7E8F9C0D1E2F3G4H5I6J7A6B7C8D9G0H1I2J3A2B3C4D5E6F7G8H9" s2$ = "A9B8C7D6E5F4G3H2I1J0B0A1I9J8A5B4C3D2E1F0E9F8G7H6I5J4A3B2C1D0A7B6C5D4E3F2G1H0C9D8E7F6G5H4I3J2G9H8I7J6" 'If Rnd < .5 Then shots$ = s1$ Else shots$ = s2$ ' don't be predictable with bombing patterns shots$ = s1$ ' shuffle sections: priority diagonal then sub diagonals, Mod 8 then mod 4 then mod 2 ReDim As Long T(50), i For i = 1 To 50: T(i) = i: Next ' don't shuffle want to test with predictable bombing 'start = 1: stp = 10: Shuffle T(), start, stp 'start = 11: stp = 14: Shuffle T(), start, stp 'start = 15: stp = 26: Shuffle T(), start, stp 'start = 27: stp = 50: Shuffle T(), start, stp For i = 1 To 50 ' stow into an array AiShots$(i) = Mid$(shots$, 2 * T(i) - 1, 2) Next ZeroOutHits Cls ' Game Board draw once per game Print "" Print " Player Computer" Print "" Print " A B C D E F G H I J A B C D E F G H I J" Print " ------------------- -------------------" Print " 0| . . . . . . . . . . 0| . . . . . . . . . ." Print " 1| . . . . . . . . . . 1| . . . . . . . . . ." Print " 2| . . . . . . . . . . 2| . . . . . . . . . ." Print " 3| . . . . . . . . . . 3| . . . . . . . . . . Ships: P C" Print " 4| . . . . . . . . . . 4| . . . . . . . . . . Carrier . ." Print " 5| . . . . . . . . . . 5| . . . . . . . . . . Battleship . ." Print " 6| . . . . . . . . . . 6| . . . . . . . . . . Cruiser . ." Print " 7| . . . . . . . . . . 7| . . . . . . . . . . Submarine . ." Print " 8| . . . . . . . . . . 8| . . . . . . . . . . Destroyer . ." Print " 9| . . . . . . . . . . 9| . . . . . . . . . ." Print " ------------------- -------------------" Print " A B C D E F G H I J A B C D E F G H I J"
'locate 6, 5: print "X" ' check offsets
' debugg check AIshots$((aiI) OK 'For i = 1 To 50 'double check checker board coverage 50 cells in priority order ' x = InStr("ABCDEFGHIJ", Left$(AiShots$(i), 1)) - 1 ' y = Val(Mid$(AiShots$(i), 2, 1)) ' LP x, y, "p", "O" ' _Delay 1 'Next
For i = 1 To 10 ' restring ship hits to all clear no hits ShipHits$(i) = String$(ShipLen(i), "o") Next Autosetup 1 'setup the Computers ships offer to that for player Locate 20, 1 Print " Let computer setup your ships? press y for yes, n for no..." k$ = UCase$(Input$(1)) CLSpart
If k$ = "Y" Then Autosetup 0 Else For s = 1 To 5 ' do it yourself ship placement OK = 0 While OK = 0 placeAgain: Locate 20, 1 Print " Setting up the " + ShipName$(s) + " with length" + Str$(ShipLen(s)) Print " To place ship:" Print " Enter v for vertical, h for horizontal, letter and digit for top, left of ship" Input " Placement "; place$ CLSpart place$ = UCase$(place$) ' check place If Left$(place$, 1) <> "V" And Left$(place$, 1) <> "H" Then Beep: GoTo placeAgain sx = InStr("ABCDEFGHIJ", Mid$(place$, 2, 1)) If sx < 1 Or sx > 10 Then Beep: GoTo placeAgain Else sx = sx - 1 sy = InStr("0123456789", Mid$(place$, 3, 1)) If sy < 1 Or sy > 10 Then Beep: GoTo placeAgain Else sy = sy - 1
If Left$(place$, 1) = "V" Then ShipHor(s) = 0 Else ShipHor(s) = 1 If ShipHor(s) Then ' layout ship horiz If sx <= 10 - ShipLen(s) Then OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If End If Else ' layout vertical If sy <= 10 - ShipLen(s) Then OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If End If Wend Next End If End Sub
Sub Autosetup (AItf As Long) If AItf Then 'setup Computer's ships 'setup a board with ships, Computer or AI's setup For s = 6 To 10 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If C(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 C(sx + xx, sy) = s 'LP sx + xx, sy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If C(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 C(sx, sy + yy) = s 'LP sx, sy + yy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If End If Wend Next Else 'setup Player's ships For s = 1 To 5 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If Wend Next End If End Sub
Sub FYI (Info$) ' in place of a MessageBox Sound 3000, 4 Locate 20, 1 Print Space$(3); Info$ + " (3 secs)" _Delay 3 CLSpart End Sub
Sub LP (x As Long, y As Long, pcGrid$, s$) If pcGrid$ = "p" Then Locate PYO + y, PXO + 2 * x Else Locate CYO + y, CXO + 2 * x Print s$; End Sub
Function Rand& (low As Long, high As Long) ' Random integer from low to high inclusive Rand& = Int(Rnd * (high - low + 1)) + low End Function
Sub Shoot GameOn = 1 While GameOn 'If PTurn Then PTurn = 0 Else PTurn = 1 PTurn = 0 ' for the AI Movie If PTurn Then ' player playerAgain: Locate 20, 1 Input " Enter your next bomb site letter digit "; place$ CLSpart If place$ = "" Then GameOn = 0 place$ = UCase$(place$) bx = InStr("ABCDEFGHIJ", Left$(place$, 1)) - 1 by = Val(Mid$(place$, 2, 1)) If bx >= 0 And bx < 10 Then ' better check If by >= 0 And by < 10 Then If C(bx, by) = 0 Then 'miss LP bx, by, "c", "o" C(bx, by) = -1 ElseIf C(bx, by) > 5 And C(bx, by) < 11 Then 'hit LP bx, by, "c", "X" Sound 200, 2 HitEval "c", bx, by 'game could end here C(bx, by) = C(bx, by) + 10 ' signal we hit this spot already! ElseIf C(bx, by) = -1 Or C(bx, by) > 10 Then Beep: GoTo playerAgain End If End If End If Else 'AI's turn if it gets a hit it will bomb around the ship until it is finished 'could be trouble if 2 ships are next to each other. Some effort to work it, 'still might get confused. 'hits() array tracks red = 1 and white pegs = -1 like a human player for AI
If CurrentHits > 0 Then 'we are working around the latest hit with bombx, bomby to test ' BombX, Bomby already deided in decide... sub If P(BombX, BombY) <> 0 Then 'hit! Hit2 = 1 ' signal AI that bomb x, y was a success, keep that direction going Hits(BombX, BombY) = 1 ' update hits board CurrentHits = CurrentHits + 1 ' update AI hit count Counting Hits!!!! LP BombX, BombY, "p", "X" ' update display 'new stuff 2024-08-01 mod HitI = HitI + 1 ' increase index HitX(HitI) = BombX ' save location HitY(HitI) = BombY
' when hitEval announces a ship sunk we can reduce the currentHits count ' by that ships amount if still have more current hits, continue bombing ' area as another ship is there Sound 2000, 2 ' wakeup player! HitEval "p", BombX, BombY ' this will reduce currentHits by ship sank If CurrentHits = 0 Then ' clear our checklist we sank all ships we hit, Call ZeroOutHits ' call off bombing of area Else DecideWhereToBombNext End If Else 'no hit from checklist scratch off one item Hit2 = 0 ' signal ai that direction was not successful move on to next Hits(BombX, BombY) = -1 ' update ALL the hits on board LP BombX, BombY, "p", "o" ' update board display DecideWhereToBombNext End If ' are we still working on hit Else 'not working on any hits x1, y1 = 0, dir = 0, currentHits might be = 0 'random but systematic shooting, bring up next good shooting location
alreadyHit: AiI = AiI + 1 ' next random shoot If AiI > 50 Then ' we should never get this far but just in case x = Rand(0, 9) y = Rand(0, 9) Else ' normal shooting pattern by diagonals to form checker board coverage x = InStr("ABCDEFGHIJ", Left$(AiShots$(AiI), 1)) - 1 y = Val(Mid$(AiShots$(AiI), 2, 1)) End If If Hits(x, y) <> 0 Then GoTo alreadyHit
' was that shot just fired a hit or miss If P(x, y) <> 0 Then ' test our shot just fired is hit! CurrentHits = CurrentHits + 1 ' counting hits!! HitI = HitI + 1 HitX(HitI) = x HitY(HitI) = y Hits(x, y) = 1 ' update board LP HitX(HitI), HitY(HitI), "p", "X" ' update display of board Sound 2000, 2 ' wakeup player! HitEval "p", HitX(HitI), HitY(HitI) ' see if ship sunk 'did we just happen to finish off a ship? If CurrentHits = 0 Then ' finished off all ships in area of hit ZeroOutHits Else DecideWhereToBombNext ' still working the hit area End If Else 'no hit Hits(x, y) = -1 ' record in board LP x, y, "p", "o" ' update display End If End If 'rI was hit or not End If 'whose turn is it _Delay 1 ' a sec pause to allow us to see computers move Wend Locate 20, 1 Print " Play Again? press y for yes, n for no..." k$ = Input$(1) CLSpart If k$ = "n" Then End End Sub
Sub HitEval (board$, bbx, bby) 'a referee for both players to announce a ship sunk and a game won? If board$ <> "p" Then s = C(bbx, bby) ' which ship number you$ = "Player": my$ = "Computer's" istart = 6: istop = 10 Else s = P(bbx, bby) you$ = "Computer": my$ = "Player's" istart = 1: istop = 5 End If If ShipHor(s) Then D = bbx - ShipX(s) + 1 Else D = bby - ShipY(s) + 1 Mid$(ShipHits$(s), D, 1) = "X" If ShipHits$(s) = String$(ShipLen(s), "X") Then ShipSunk(s) = 1 ' this is only thing ref does to help Computer AI If board$ = "p" Then CurrentHits = CurrentHits - ShipLen(s) UpdateStatus FYI "Congrats: " + you$ + " sank " + my$ + " " + ShipName$(s) + "!" tot = 0 For i = istart To istop If ShipSunk(i) = 1 Then tot = tot + 1 Next If tot = 5 Then UpdateStatus If you$ = "Computer" Then ShowComputersShips FYI "Congrats: " + you$ + ", you sank all " + my$ + " ships! Game Over" GameOn = 0 End If End If End Sub
Sub DecideWhereToBombNext ' this sets the next place to try with bombX, bombY If Hit2 Then 'whatever direction we are taking, continue if we can Select Case Dir Case 1 If BombX + 1 <= 9 Then If Hits(BombX + 1, BombY) = 0 Then BombX = BombX + 1: Exit Sub End If End If Case 2 If BombX - 1 >= 0 Then If Hits(BombX - 1, BombY) = 0 Then BombX = BombX - 1: Exit Sub End If End If Case 3 If BombY + 1 <= 9 Then If Hits(BombX, BombY + 1) = 0 Then BombY = BombY + 1: Exit Sub End If End If Case 4 If BombY - 1 >= 0 Then If Hits(BombX, BombY - 1) = 0 Then BombY = BombY - 1: Exit Sub End If End If End Select ' still here then the direction is no longer good to try Hit2 = 0 ' turn off signal End If
tryNextI = 1 'vsearch next open hit location not tested While tryNextI <= HitI ' Not CurrentHits !!! If D1(tryNextI) = 0 Then D1(tryNextI) = 1 If HitX(tryNextI) + 1 <= 9 Then If Hits(HitX(tryNextI) + 1, HitY(tryNextI)) = 0 Then BombX = HitX(tryNextI) + 1: BombY = HitY(tryNextI): Dir = 1: Exit Sub End If End If End If If D2(tryNextI) = 0 Then D2(tryNextI) = 1 If HitX(tryNextI) - 1 >= 0 Then If Hits(HitX(tryNextI) - 1, HitY(tryNextI)) = 0 Then BombX = HitX(tryNextI) - 1: BombY = HitY(tryNextI): Dir = 2: Exit Sub End If End If End If If D3(tryNextI) = 0 Then D3(tryNextI) = 1 If HitY(tryNextI) + 1 <= 9 Then If Hits(HitX(tryNextI), HitY(tryNextI) + 1) = 0 Then BombX = HitX(tryNextI): BombY = HitY(tryNextI) + 1: Dir = 3: Exit Sub End If End If End If If D4(tryNextI) = 0 Then D4(tryNextI) = 1 If HitY(tryNextI) - 1 >= 0 Then If Hits(HitX(tryNextI), HitY(tryNextI) - 1) = 0 Then BombX = HitX(tryNextI): BombY = HitY(tryNextI) - 1: Dir = 4: Exit Sub End If End If End If tryNextI = tryNextI + 1 Wend ' exhausted all hit locations hit1 area played out!!! CurrentHits = 0 ' abandon hit area ZeroOutHits End Sub
Sub UpdateStatus ' ships sunk area of the display For i = 1 To 5 ' row 10 carrier player colum 66 computer column 68 If ShipSunk(i) Then Locate i + 9, 68,: Print "X"; If ShipSunk(i + 5) Then Locate i + 9, 70: Print "X" Next End Sub
Sub ShowComputersShips ' fixed this so only empty spaces not bombed are displayed For s = 6 To 10 If ShipHor(s) Then sx = ShipX(s): sy = ShipY(s) For xx = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), xx + 1, 1) = "o" Then LP sx + xx, sy, "c", _Trim$(Str$(s Mod 10)) End If Next Else sx = ShipX(s): sy = ShipY(s) For yy = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), yy + 1, 1) = "o" Then LP sx, sy + yy, "c", _Trim$(Str$(s Mod 10)) End If Next End If Next End Sub
Sub Shuffle (a() As Long, start, stp) ' used to randomize shooting pattern a bit For i = stp To start + 1 Step -1 Swap a(i), a(Rand(start, i)) Next End Sub
Sub CLSpart ' clear lower part of screen For i = 20 To 25 Locate i, 1: Print Space$(80); Next Locate 20, 1 End Sub
Sub ZeroOutHits ' at setup and everytime CurrentHits is set back to zero ReDim As Long HitX(17), HitY(17), D1(17), D2(17), D3(17), D4(17) HitI = 0: Dir = 0: Hit2 = 0: tryNextI = 0 End Sub
|
|
|
Post by bplus on Aug 2, 2024 9:12:59 GMT
Battleship Mod842 Counting Hits 2 Player back Now bring the player back in, happy hunting! _Title "BS Mod842 Counting Hits 2 Player back 2024-08-01" ' b+ 2024-07-26 port from JB ' Battleship Mod842 b+ 2024-07-25 uses a garanteed AI to find Destroyer in 50 shots ' unlike Battleship 2 which AI uses mod 3 it is screwed if fails to find Destroyer when mod 3 ' shooting covers the ocean taking something like up to 66 shots to garantee finding Destroyer. ' This code starts from my first Battleship coded for JB: ' Battleship based on Hasbro Game b+ 2024-07-23 allot of code ported out of old QB64 version ' 2024-07-26 besides port trans back to QB64, fix the showing of computer ships so only the ones ' or parts not hit with ship number. Add Sound when ship is hit.
' 2024-07-29 Oh I forgot, MessageBox does not work for older versions of QB64. ' Actually that turns out to be no problem at all!!! ' I think I can use View Print and not need my Message and Message Clear subroutines. ' This might be a very cool fix! Also I am going to work on my organization and commenting. ' OK View Print did not scroll inside the view text port so I had to cls before turning off ' View Print. I was thinking scrolling would be cool, no cls needed but no.
' Fix a bug that has been here from beginning, check player's bomb site to see if already done ' if so BEEP him, definitely don't want to sink a ship twice which is what has been happening. ' So we should use computer c() to track players shots. -1 for miss but what about when ship ' is hit??? c(x, y) = c(x, y) + 10 so if c(x, y) is > 5 and < 11 then good hit. ' if c(x,y) > 10 then already hit. BEEPing now for places already bombed plus give player another ' chance to shoot.
' Need to check place$ to see if player screwed up placement instructions, done.
' 2024-07-30 BS Mod842 AI Movie - last night I got this great idea and want to share it. ' This Movie shows The Computer AI in action finding and sinking ships, it does so with ' minimum interruption from viewer/Player. I do want to set it so the Player can setup ' tricky ship placements to test how well the AI handles them, also excellent tool to ' improve the AI because just watching a number of these I see AI failures clearly some ' holes left in coverage...
' 2024-07-30 BS Mod842 AI Movie 2 tsh suggest if running successfully one way and stop ' the reverse direction and go opposite ie heading dir 1 right then go left if stopped.
' 2024-07-31 still with Movie 2 - Take out View Print with Locate and ClearPartial sub ' to clear only bottom part of screen. Now I have code portable to all Basics.
' 2024-08-01 BS Mod 842 Counting Hits 1, as posted at JB today: ' ========================================================================================================= ' I am studying cases when/where AI fails to sustain an attack when current hits > 0 after a ship is sunk. ' The attack needs to persist for the original hit area until currentHits is zero, = no ships left in ' area of first hit in sequence after random fire gets a first hit. ' ' Towards that end I need to restructure: ' Add HitX(), HitY() track where we have hits 1, 0 for untested ' yet I suppose we have to track if missed at that spot too, -1 ' that would replace X1, Y1 with the array ordered by hitIndex ' kinda of confused at moment to include misses or not. ' BTW 17 is max amount of hits possible if you hit everything on Board, could have a cluster convoy. ' ' Dir() = 0 1 2 3 4 test all 4 directions for each hit, 0 no direction tested, ' 5 = all directions tested and so hitIndex for that place is played out ' ' the 3 (new arrays) above are indexed with hitIndex (global) ' ' When currentHits does go to 0 after all ships sunk then call new ZeroOutHits sub ' ' Maybe need a tryThisIndexNext global also when deciding where to bomb next, ' set to 1 in ZeroOut This would track where we are in the hit List. ' ' Well that sketches out my next mods and experiment towards a more intelligent AI. ' There, you 'all have it in my words before the code is written! :) ' ========================================================================================================= ' note: previous version had Dir2 that never got used
' oh I need 4 arrays for 4 directions possible because can't depend on directions going in order from ' 1 to 4.
' 2024-08-01 BS Mod 842 Counting Hits 2 Player back - yeah so now that AI is playing so well ' bring back the player!
' Offsets for the Game board print at top of screen P is for Player, C is for Computer ' S is for Ships Sunk tally on far right of screen (x,y) offsets: Dim Shared As Long PXO, PYO, CXO, CYO, SXO, SYO
Dim Shared As Long PTurn, GameOn ' TF players turn or not and GameOn if still running game
' internal tracking of P() Players ships, C() Computer ships Dim Shared As Long P(9, 9), C(9, 9), Hits(9, 9) ' player board, computer board and hits tracking for AI
Dim Shared As Long ShipLen(10), ShipHor(10), ShipX(10), ShipY(10), ShipSunk(10) Dim Shared ShipName$(10), ShipHits$(10) ' Ship arrays are 0 based but are really numbered 1 to 10, 0 is ignored ' ShipName$() are names of ships according to length in character cells see approx line 38 ' ShipLen() is the length or how many character cells a ship is long, 5 down to 2 according to index ' ShipHor() is a T/F value (0|-1) if it is Setup horizontal see SetUp where ships are positioned ' ShipX() and ShipY() locate the top of a ship if vertically set or the left start of ship if horizontal ' ShipHits$() tracks which cell on each ship was hit ' ShipSunk() T/F if ship has been sunk
' this stuff is for the AI for computer's turn to play Dim Shared AiShots$(50) ' AiShots sequence pattern coverage of board when c not working a hit Dim Shared As Long AiI ' index for AiShots$() Dim Shared As Long Dir ' for AI bombing testing 4 directions from last hit for more of ship hit
Dim Shared As Long CurrentHits ' tracks how many hits have been made ' when ship is sunk subtract it's length Dim Shared As Long BombX, BombY, Hit2 ' tracking bombs and hits for AI to sink ship ' Bombx, Bomby is next bomb location when working a first hit area ' Hit2 indicates the direction we are going was success on last hit, keep going!
' new for Counting Hits D1 east right, D2, west left, D3 down south, D4 up North ReDim Shared As Long HitX(17), HitY(17), D1(17), D2(17), D3(17), D4(17), HitI, tryNextI ' HitI is HitIndex tryNextI tracks open slots of left of currentHits to shoot around
Color 15, 9 Randomize Timer ' set one time only stuff PXO = 8: PYO = 6 ' offsets for player grid display, tracks players ships and computers shots CXO = 35: CYO = 6 ' offsets for computer grid display, player shots hit= X miss= o SXO = 68: SYO = 10 ' offsets ships sunk tally For i = 1 To 10 Select Case i Case 1: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 2: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 3: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 4: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 5: ShipLen(i) = 2: ShipName$(i) = "Destroyer" Case 6: ShipLen(i) = 5: ShipName$(i) = "Carrier" Case 7: ShipLen(i) = 4: ShipName$(i) = "Battleship" Case 8: ShipLen(i) = 3: ShipName$(i) = "Cruiser" Case 9: ShipLen(i) = 3: ShipName$(i) = "Submarine" Case 10: ShipLen(i) = 2: ShipName$(i) = "Destroyer" End Select Next
While 1 'run game loop until player quits Setup Shoot Wend
Sub Setup ' get a game ready to play ' clear shared arrays and variables Erase ShipX, ShipY, ShipHor, ShipHits$, ShipSunk, P, C, Hits PTurn = 0: GameOn = 0: AiI = 0: CurrentHits = 0 ' globals
'setup 2 bombing patterns to cover sea in checkerboard pattern one is chosen in each game s1$ = "A0B1C2D3E4F5G6H7I8J9I0J1A8B9E0F1G2H3I4J5A4B5C6D7E8F9C0D1E2F3G4H5I6J7A6B7C8D9G0H1I2J3A2B3C4D5E6F7G8H9" s2$ = "A9B8C7D6E5F4G3H2I1J0B0A1I9J8A5B4C3D2E1F0E9F8G7H6I5J4A3B2C1D0A7B6C5D4E3F2G1H0C9D8E7F6G5H4I3J2G9H8I7J6" If Rnd < .5 Then shots$ = s1$ Else shots$ = s2$ ' don't be predictable with bombing patterns ' shuffle sections: priority diagonal then sub diagonals, Mod 8 then mod 4 then mod 2 ReDim As Long T(50), i For i = 1 To 50: T(i) = i: Next ' don't shuffle want to test with predictable bombing start = 1: stp = 10: Shuffle T(), start, stp start = 11: stp = 14: Shuffle T(), start, stp start = 15: stp = 26: Shuffle T(), start, stp start = 27: stp = 50: Shuffle T(), start, stp For i = 1 To 50 ' stow into an array AiShots$(i) = Mid$(shots$, 2 * T(i) - 1, 2) Next ZeroOutHits Cls ' Game Board draw once per game Print "" Print " Player Computer" Print "" Print " A B C D E F G H I J A B C D E F G H I J" Print " ------------------- -------------------" Print " 0| . . . . . . . . . . 0| . . . . . . . . . ." Print " 1| . . . . . . . . . . 1| . . . . . . . . . ." Print " 2| . . . . . . . . . . 2| . . . . . . . . . ." Print " 3| . . . . . . . . . . 3| . . . . . . . . . . Ships: P C" Print " 4| . . . . . . . . . . 4| . . . . . . . . . . Carrier . ." Print " 5| . . . . . . . . . . 5| . . . . . . . . . . Battleship . ." Print " 6| . . . . . . . . . . 6| . . . . . . . . . . Cruiser . ." Print " 7| . . . . . . . . . . 7| . . . . . . . . . . Submarine . ." Print " 8| . . . . . . . . . . 8| . . . . . . . . . . Destroyer . ." Print " 9| . . . . . . . . . . 9| . . . . . . . . . ." Print " ------------------- -------------------" Print " A B C D E F G H I J A B C D E F G H I J"
'locate 6, 5: print "X" ' check offsets
' debugg check AIshots$((aiI) OK 'For i = 1 To 50 'double check checker board coverage 50 cells in priority order ' x = InStr("ABCDEFGHIJ", Left$(AiShots$(i), 1)) - 1 ' y = Val(Mid$(AiShots$(i), 2, 1)) ' LP x, y, "p", "O" ' _Delay 1 'Next
For i = 1 To 10 ' restring ship hits to all clear no hits ShipHits$(i) = String$(ShipLen(i), "o") Next Autosetup 1 'setup the Computers ships offer to that for player Locate 20, 1 Print " Let computer setup your ships? press y for yes, n for no..." k$ = UCase$(Input$(1)) CLSpart
If k$ = "Y" Then Autosetup 0 Else For s = 1 To 5 ' do it yourself ship placement OK = 0 While OK = 0 placeAgain: Locate 20, 1 Print " Setting up the " + ShipName$(s) + " with length" + Str$(ShipLen(s)) Print " To place ship:" Print " Enter v for vertical, h for horizontal, letter and digit for top, left of ship" Input " Placement "; place$ CLSpart place$ = UCase$(place$) ' check place If Left$(place$, 1) <> "V" And Left$(place$, 1) <> "H" Then Beep: GoTo placeAgain sx = InStr("ABCDEFGHIJ", Mid$(place$, 2, 1)) If sx < 1 Or sx > 10 Then Beep: GoTo placeAgain Else sx = sx - 1 sy = InStr("0123456789", Mid$(place$, 3, 1)) If sy < 1 Or sy > 10 Then Beep: GoTo placeAgain Else sy = sy - 1
If Left$(place$, 1) = "V" Then ShipHor(s) = 0 Else ShipHor(s) = 1 If ShipHor(s) Then ' layout ship horiz If sx <= 10 - ShipLen(s) Then OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If End If Else ' layout vertical If sy <= 10 - ShipLen(s) Then OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If End If Wend Next End If End Sub
Sub Autosetup (AItf As Long) If AItf Then 'setup Computer's ships 'setup a board with ships, Computer or AI's setup For s = 6 To 10 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If C(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 C(sx + xx, sy) = s 'LP sx + xx, sy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If C(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 C(sx, sy + yy) = s 'LP sx, sy + yy, "c", _Trim$(Str$(S Mod 10)) ' for debugg Next End If End If Wend Next Else 'setup Player's ships For s = 1 To 5 OK = 0 While OK = 0 ShipHor(s) = Rand(0, 1) If ShipHor(s) Then sy = Rand(0, 9) sx = Rand(0, 10 - ShipLen(s)) OK = 1 For xx = 0 To ShipLen(s) - 1 If P(sx + xx, sy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For xx = 0 To ShipLen(s) - 1 P(sx + xx, sy) = s LP sx + xx, sy, "p", _Trim$(Str$(s)) Next End If Else sx = Rand(0, 9) sy = Rand(0, 10 - ShipLen(s)) OK = 1 For yy = 0 To ShipLen(s) - 1 If P(sx, sy + yy) <> 0 Then OK = 0: Exit For Next If OK Then ShipX(s) = sx: ShipY(s) = sy For yy = 0 To ShipLen(s) - 1 P(sx, sy + yy) = s LP sx, sy + yy, "p", _Trim$(Str$(s)) Next End If End If Wend Next End If End Sub
Sub FYI (Info$) ' in place of a MessageBox Sound 3000, 4 Locate 20, 1 Print Space$(3); Info$ + " (3 secs)" _Delay 3 CLSpart End Sub
Sub LP (x As Long, y As Long, pcGrid$, s$) If pcGrid$ = "p" Then Locate PYO + y, PXO + 2 * x Else Locate CYO + y, CXO + 2 * x Print s$; End Sub
Function Rand& (low As Long, high As Long) ' Random integer from low to high inclusive Rand& = Int(Rnd * (high - low + 1)) + low End Function
Sub Shoot GameOn = 1 While GameOn If PTurn Then PTurn = 0 Else PTurn = 1 ' PTurn = 0 ' for the AI Movie If PTurn Then ' player playerAgain: Locate 20, 1 Input " Enter your next bomb site letter digit "; place$ CLSpart If place$ = "" Then GameOn = 0 place$ = UCase$(place$) bx = InStr("ABCDEFGHIJ", Left$(place$, 1)) - 1 by = Val(Mid$(place$, 2, 1)) If bx >= 0 And bx < 10 Then ' better check If by >= 0 And by < 10 Then If C(bx, by) = 0 Then 'miss LP bx, by, "c", "o" C(bx, by) = -1 ElseIf C(bx, by) > 5 And C(bx, by) < 11 Then 'hit LP bx, by, "c", "X" Sound 200, 2 HitEval "c", bx, by 'game could end here C(bx, by) = C(bx, by) + 10 ' signal we hit this spot already! ElseIf C(bx, by) = -1 Or C(bx, by) > 10 Then Beep: GoTo playerAgain End If End If End If Else 'AI's turn if it gets a hit it will bomb around the ship until it is finished 'could be trouble if 2 ships are next to each other. Some effort to work it, 'still might get confused. 'hits() array tracks red = 1 and white pegs = -1 like a human player for AI
If CurrentHits > 0 Then 'we are working around the latest hit with bombx, bomby to test ' BombX, Bomby already deided in decide... sub If P(BombX, BombY) <> 0 Then 'hit! Hit2 = 1 ' signal AI that bomb x, y was a success, keep that direction going Hits(BombX, BombY) = 1 ' update hits board CurrentHits = CurrentHits + 1 ' update AI hit count Counting Hits!!!! LP BombX, BombY, "p", "X" ' update display 'new stuff 2024-08-01 mod HitI = HitI + 1 ' increase index HitX(HitI) = BombX ' save location HitY(HitI) = BombY
' when hitEval announces a ship sunk we can reduce the currentHits count ' by that ships amount if still have more current hits, continue bombing ' area as another ship is there Sound 2000, 2 ' wakeup player! HitEval "p", BombX, BombY ' this will reduce currentHits by ship sank If CurrentHits = 0 Then ' clear our checklist we sank all ships we hit, Call ZeroOutHits ' call off bombing of area Else DecideWhereToBombNext End If Else 'no hit from checklist scratch off one item Hit2 = 0 ' signal ai that direction was not successful move on to next Hits(BombX, BombY) = -1 ' update ALL the hits on board LP BombX, BombY, "p", "o" ' update board display DecideWhereToBombNext End If ' are we still working on hit Else 'not working on any hits x1, y1 = 0, dir = 0, currentHits might be = 0 'random but systematic shooting, bring up next good shooting location
alreadyHit: AiI = AiI + 1 ' next random shoot If AiI > 50 Then ' we should never get this far but just in case x = Rand(0, 9) y = Rand(0, 9) Else ' normal shooting pattern by diagonals to form checker board coverage x = InStr("ABCDEFGHIJ", Left$(AiShots$(AiI), 1)) - 1 y = Val(Mid$(AiShots$(AiI), 2, 1)) End If If Hits(x, y) <> 0 Then GoTo alreadyHit
' was that shot just fired a hit or miss If P(x, y) <> 0 Then ' test our shot just fired is hit! CurrentHits = CurrentHits + 1 ' counting hits!! HitI = HitI + 1 HitX(HitI) = x HitY(HitI) = y Hits(x, y) = 1 ' update board LP HitX(HitI), HitY(HitI), "p", "X" ' update display of board Sound 2000, 2 ' wakeup player! HitEval "p", HitX(HitI), HitY(HitI) ' see if ship sunk 'did we just happen to finish off a ship? If CurrentHits = 0 Then ' finished off all ships in area of hit ZeroOutHits Else DecideWhereToBombNext ' still working the hit area End If Else 'no hit Hits(x, y) = -1 ' record in board LP x, y, "p", "o" ' update display End If End If 'rI was hit or not End If 'whose turn is it _Delay 1 ' a sec pause to allow us to see computers move Wend Locate 20, 1 Print " Play Again? press y for yes, n for no..." k$ = Input$(1) CLSpart If k$ = "n" Then End End Sub
Sub HitEval (board$, bbx, bby) 'a referee for both players to announce a ship sunk and a game won? If board$ <> "p" Then s = C(bbx, bby) ' which ship number you$ = "Player": my$ = "Computer's" istart = 6: istop = 10 Else s = P(bbx, bby) you$ = "Computer": my$ = "Player's" istart = 1: istop = 5 End If If ShipHor(s) Then D = bbx - ShipX(s) + 1 Else D = bby - ShipY(s) + 1 Mid$(ShipHits$(s), D, 1) = "X" If ShipHits$(s) = String$(ShipLen(s), "X") Then ShipSunk(s) = 1 ' this is only thing ref does to help Computer AI If board$ = "p" Then CurrentHits = CurrentHits - ShipLen(s) UpdateStatus FYI "Congrats: " + you$ + " sank " + my$ + " " + ShipName$(s) + "!" tot = 0 For i = istart To istop If ShipSunk(i) = 1 Then tot = tot + 1 Next If tot = 5 Then UpdateStatus If you$ = "Computer" Then ShowComputersShips FYI "Congrats: " + you$ + ", you sank all " + my$ + " ships! Game Over" GameOn = 0 End If End If End Sub
Sub DecideWhereToBombNext ' this sets the next place to try with bombX, bombY If Hit2 Then 'whatever direction we are taking, continue if we can Select Case Dir Case 1 If BombX + 1 <= 9 Then If Hits(BombX + 1, BombY) = 0 Then BombX = BombX + 1: Exit Sub End If End If Case 2 If BombX - 1 >= 0 Then If Hits(BombX - 1, BombY) = 0 Then BombX = BombX - 1: Exit Sub End If End If Case 3 If BombY + 1 <= 9 Then If Hits(BombX, BombY + 1) = 0 Then BombY = BombY + 1: Exit Sub End If End If Case 4 If BombY - 1 >= 0 Then If Hits(BombX, BombY - 1) = 0 Then BombY = BombY - 1: Exit Sub End If End If End Select ' still here then the direction is no longer good to try Hit2 = 0 ' turn off signal End If
tryNextI = 1 'vsearch next open hit location not tested While tryNextI <= HitI ' Not CurrentHits !!! If D1(tryNextI) = 0 Then D1(tryNextI) = 1 If HitX(tryNextI) + 1 <= 9 Then If Hits(HitX(tryNextI) + 1, HitY(tryNextI)) = 0 Then BombX = HitX(tryNextI) + 1: BombY = HitY(tryNextI): Dir = 1: Exit Sub End If End If End If If D2(tryNextI) = 0 Then D2(tryNextI) = 1 If HitX(tryNextI) - 1 >= 0 Then If Hits(HitX(tryNextI) - 1, HitY(tryNextI)) = 0 Then BombX = HitX(tryNextI) - 1: BombY = HitY(tryNextI): Dir = 2: Exit Sub End If End If End If If D3(tryNextI) = 0 Then D3(tryNextI) = 1 If HitY(tryNextI) + 1 <= 9 Then If Hits(HitX(tryNextI), HitY(tryNextI) + 1) = 0 Then BombX = HitX(tryNextI): BombY = HitY(tryNextI) + 1: Dir = 3: Exit Sub End If End If End If If D4(tryNextI) = 0 Then D4(tryNextI) = 1 If HitY(tryNextI) - 1 >= 0 Then If Hits(HitX(tryNextI), HitY(tryNextI) - 1) = 0 Then BombX = HitX(tryNextI): BombY = HitY(tryNextI) - 1: Dir = 4: Exit Sub End If End If End If tryNextI = tryNextI + 1 Wend ' exhausted all hit locations hit1 area played out!!! CurrentHits = 0 ' abandon hit area ZeroOutHits End Sub
Sub UpdateStatus ' ships sunk area of the display For i = 1 To 5 ' row 10 carrier player colum 66 computer column 68 If ShipSunk(i) Then Locate i + 9, 68,: Print "X"; If ShipSunk(i + 5) Then Locate i + 9, 70: Print "X" Next End Sub
Sub ShowComputersShips ' fixed this so only empty spaces not bombed are displayed For s = 6 To 10 If ShipHor(s) Then sx = ShipX(s): sy = ShipY(s) For xx = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), xx + 1, 1) = "o" Then LP sx + xx, sy, "c", _Trim$(Str$(s Mod 10)) End If Next Else sx = ShipX(s): sy = ShipY(s) For yy = 0 To ShipLen(s) - 1 If Mid$(ShipHits$(s), yy + 1, 1) = "o" Then LP sx, sy + yy, "c", _Trim$(Str$(s Mod 10)) End If Next End If Next End Sub
Sub Shuffle (a() As Long, start, stp) ' used to randomize shooting pattern a bit For i = stp To start + 1 Step -1 Swap a(i), a(Rand(start, i)) Next End Sub
Sub CLSpart ' clear lower part of screen For i = 20 To 25 Locate i, 1: Print Space$(80); Next Locate 20, 1 End Sub
Sub ZeroOutHits ' at setup and everytime CurrentHits is set back to zero ReDim As Long HitX(17), HitY(17), D1(17), D2(17), D3(17), D4(17) HitI = 0: Dir = 0: Hit2 = 0: tryNextI = 0 End Sub This is probably my final version of Battleship unless someone finds a pattern of problems.
|
|
ubi44
Junior Member
Posts: 52
|
Post by ubi44 on Aug 4, 2024 9:02:59 GMT
Nice work ! I made a probability-based AI that gives results that range from worst to best.. I tried to make sure that she didn't always play the same way! The big difficulty is when the boats touch.. sometimes the AI gets completely lost! However, it allows you to beat her from time to time! There are three grids on the screen: in yellow on a blue background is the objective, in red on a blue background is the game in progress and in grayscale it is the probabilities... I have displayed the statistics: minimum, maximum and average... it goes very fast!(comment line 84 to speed up)
I wrote this in 2022 and it can be improved for example by forcing AI to play on a checkerboard: only the black squares or the white squares!
Type bateau tx As Integer ty As Integer str As String * 20 type As Integer coule As Integer End Type ReDim Shared B(4) As bateau B(0).str = "PORTE-AVION" B(1).str = "CROISEUR" B(2).str = "CONTRE-TORPILLEUR" B(3).str = "SOUS-MARIN" B(4).str = "TORPILLEUR" B(0).type = 0 B(1).type = 1 B(2).type = 1 B(3).type = 0 B(4).type = 1 B(0).tx = 1: B(0).ty = 5 B(1).tx = 1: B(1).ty = 4 B(2).tx = 1: B(2).ty = 3 B(3).tx = 1: B(3).ty = 3 B(4).tx = 1: B(4).ty = 2 B(0).coule = 5 B(1).coule = 4 B(2).coule = 3 B(3).coule = 3 B(4).coule = 2 ReDim Shared NBCELL, NBBATEAUX NBCELL = 10 Randomize Timer NBBATEAUX = 5 - 1 Screen _NewImage(800, 600, 32) minimum = NBCELL * NBCELL
'initialisation AI 36
ReDim Shared GrilleAI(NBCELL - 1, NBCELL - 1) ReDim Shared GrilleProb(NBCELL - 1, NBCELL - 1) ReDim Shared GrilleJoueur(NBCELL - 1, NBCELL - 1) ReDim Shared GrilleJouBAT(NBCELL - 1, NBCELL - 1) ReDim Shared Btestjoue(NBBATEAUX) ReDim Shared memX(NBCELL - 1), memY(NBCELL - 1) ReDim Shared AI, Boat, DIRECTION, CUR, passATAC, mxCUR, sauvX, sauvY Boat = 0 NTO = 0 For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 GrilleJouBAT(x, y) = -1 Next y, x placebateau nombredecoup = 0 AI = 0 Cls , _RGB(12, 30, 26)
45
choix x, y If GrilleAI(x, y) = 1 And AI <> 0 Then AI = 0: choix x, y GrilleAI(x, y) = 1 nombredecoup = nombredecoup + 1
rep = envoi(x, y) ' 0=water 1=touche 2=coule IA rep, x, y
trace x, y, rep Circle (450 + x * 10 + 5, y * 10 + 5), 2, _RGB(255, 255, 255) For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 If GrilleJoueur(x, y) = 1 Then r = 255: g = 255: b = 0 Line (450 + x * 10, y * 10)-(450 + x * 10 + 10, y * 10 + 10), _RGB(r, g, b), B Else r = 0: g = 0: b = 255 Circle (450 + x * 10 + 5, y * 10 + 5), 2, _RGB(r, g, b) End If Next y, x
Locate 1, 1: Print "MIN:"; minimum; "MAX:"; maximum; "MOY"; Int(moyenne) Print nombredecoup
_Display ktim = Timer + .1 'slowdown the show! Do Loop Until ktim < Timer
If Boat = NBBATEAUX + 1 Then total = total + nombredecoup partie = partie + 1 moyenne = total / partie If minimum > nombredecoup Then minimum = nombredecoup If maximum < nombredecoup Then maximum = nombredecoup GoTo 36 End If If InKey$ = Chr$(27) Then End
GoTo 45 Sub choix (x, y) 45 Select Case AI Case 0 stat m, x, y Case 1 HBGD x, y passATAC = 0 Case 2 attac0 x, y If AI = 3 Then passATAC = 0 Select Case DIRECTION Case 0 DIRECTION = 2 Case 1 DIRECTION = 3 Case 2 DIRECTION = 0 Case 3 DIRECTION = 1 End Select sauvX = memX(mxCUR) sauvY = memY(mxCUR) GoTo 45 End If
Case 3 attac1 sauvX, sauvY, x, y End Select End Sub Sub IA (rep, x, y)
Select Case rep Case 0 Select Case AI Case 0 AI = 0 Case 1 AI = 1 Case 2 If passATAC = 0 Then Select Case DIRECTION Case 0 DIRECTION = 1 CUR = 0 Case 1 DIRECTION = 0 CUR = 0 Case 2 DIRECTION = 3 CUR = 0 Case 3 DIRECTION = 2 CUR = 0 End Select passATAC = 1 Else AI = 0 CUR = 0 End If Case 3 If passATAC = 0 Then Select Case DIRECTION Case 0 DIRECTION = 1 Case 1 DIRECTION = 0 Case 2 DIRECTION = 3 Case 3 DIRECTION = 2 End Select passATAC = 1 sauvX = memX(mxCUR) sauvY = memY(mxCUR)
Else mxCUR = mxCUR - 1 If mxCUR < 0 Then AI = 0: mxCUR = 0 End If End Select Case 1 GrilleAI(x, y) = 2 Select Case AI Case 0 ReDim memX(NBCELL - 1), memY(NBCELL - 1) CUR = 0 memX(CUR) = x: memY(CUR) = y AI = 1 Case 1 CUR = CUR + 1 mxCUR = CUR memX(CUR) = x: memY(CUR) = y AI = 2 Case 2 CUR = CUR + 1 mxCUR = CUR memX(CUR) = x: memY(CUR) = y AI = 2 Case 3 sauvX = x sauvY = y AI = 3 End Select Case 2
Select Case AI Case 0, 1, 2 CUR = 0 AI = 0 Case 3 mxCUR = mxCUR - 1 If mxCUR < 0 Then AI = 0 mxCUR = 0 CUR = 0 Else sauvX = memX(mxCUR) sauvY = memY(mxCUR) passATAC = 0 End If End Select 'ox = x: oy = y 'For x = 0 To NBCELL - 1 ' For y = 0 To NBCELL - 1 ' If GrilleJouBAT(ox, oy) = GrilleJouBAT(x, y) And GrilleAI(x, y) = 2 Then GrilleAI(x, y) = 1 'Next y, x 'x = ox: y = oy End Select End Sub Sub stat (kop, pox, poy) For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 GrilleProb(x, y) = .1 Next y, x For i = 0 To 4 ' If Btestjoue(i) Then xa = B(i).tx ya = B(i).ty For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 TESTbateau x, y, xa, ya TESTbateau x, y, ya, xa Next y, x ' End If Next i kop = 0 For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 cl = GrilleProb(x, y) * 10 Line (350 + x * 10 + 2.5, 150 + y * 10)-(350 + x * 10 + 10 - 2.5, 150 + y * 10 + 10), _RGB(cl, cl, cl), BF If cl > kop And GrilleAI(x, y) = 0 Then pox = x poy = y kop = cl End If Next y, x End Sub Sub HBGD (pox, poy) 'ai=1 x = memX(CUR): y = memY(CUR) esp = 1 1111 i = Int(Rnd * 4) If i = 4 Then GoTo 1111 340 fait = 0 For i = 0 To 3 Select Case i Case 0 'n If y - esp >= 0 Then If GrilleAI(x, y - esp) = 0 Then px = x: py = y - esp mix0 = GrilleProb(x, y - esp)
fait = 1 Else tente0 = GrilleAI(x, y - esp)
End If Else tente0 = 1 End If Case 1 's If y + esp <= NBCELL - 1 Then If GrilleAI(x, y + esp) = 0 Then px = x: py = y + esp mix1 = GrilleProb(x, y + esp) fait = 1 Else tente1 = GrilleAI(x, y + esp) End If Else tente1 = 1 End If Case 2 'e If x - esp >= 0 Then If GrilleAI(x - esp, y) = 0 Then px = x - esp: py = y mix2 = GrilleProb(x - esp, y) fait = 1 Else tente2 = GrilleAI(x - esp, y) End If Else tente2 = 1 End If Case 3 'o If x + esp <= NBCELL - 1 Then If GrilleAI(x + esp, y) = 0 Then px = x + esp: py = y mix3 = GrilleProb(x + esp, y) fait = 1 Else tente3 = GrilleAI(x + esp, y) End If Else tente3 = 1 End If End Select Next i If tente1 >= 1 And tente0 >= 1 And tente2 >= 1 And tente3 >= 1 Then ttt = 0 af = 0 If tente0 = 2 Then i = 0: af = mix0: ttt = 0 If tente1 = 2 Then i = 1: If mix1 > af Then af = mix1: ttt = 1 If tente2 = 2 Then i = 2: If mix2 > af Then af = mix2: ttt = 2 If tente3 = 2 Then i = 3: If mix3 > af Then af = mix3: ttt = 3 tente1 = 0: tente0 = 0: tente2 = 0: tente3 = 0 mix0 = 0: mix1 = 0: mix2 = 0: mix3 = 0: esp = esp + 1 i = ttt GoTo 340 End If If tente0 = 0 Then af = mix0: ttt = 0 If tente1 = 0 Then If mix1 > af Then af = mix1: ttt = 1 If tente2 = 0 Then If mix2 > af Then af = mix2: ttt = 2 If tente3 = 0 Then If mix3 > af Then af = mix3: ttt = 3 Select Case ttt Case 0 pox = x: poy = y - esp Case 1 pox = x: poy = y + esp Case 2 pox = x - esp: poy = y Case 3 pox = x + esp: poy = y End Select
DIRECTION = ttt End Sub
Sub attac0 (pox, poy) 'ai=2 memDIRECTION = DIRECTION 1011 x = memX(CUR) y = memY(CUR) 1012 fait = 0 Select Case DIRECTION Case 0 If y - 1 >= 0 Then Select Case GrilleAI(x, y - 1) Case 0 px = x: py = y - 1 fait = 1 Case 1 DIRECTION = 1 Case 2 y = y - 1: GoTo 1012 End Select Else DIRECTION = 1 End If Case 1 's If y + 1 <= NBCELL - 1 Then Select Case GrilleAI(x, y + 1) Case 0 px = x: py = y + 1 fait = 1 Case 1 DIRECTION = 0 Case 2 y = y + 1: GoTo 1012 End Select Else DIRECTION = 0 End If Case 2 'e If x - 1 >= 0 Then Select Case GrilleAI(x - 1, y) Case 0 px = x - 1: py = y fait = 1 Case 1 DIRECTION = 3 Case 2 x = x - 1: GoTo 1012 End Select Else DIRECTION = 3 End If Case 3 'o If x + 1 <= NBCELL - 1 Then Select Case GrilleAI(x + 1, y) Case 0 px = x + 1: py = y fait = 1 Case 1 DIRECTION = 2 Case 2 x = x + 1: GoTo 1012 End Select Else DIRECTION = 2 End If End Select If memDIRECTION <> DIRECTION And passATAC = 0 Then CUR = 0 passATAC = 1 GoTo 1011 End If If passATAC = 1 And fait = 0 Then AI = 3 If fait = 1 Then pox = px poy = py End If End Sub Sub attac1 (svx, svy, pox, poy) memDIRECTION = DIRECTION 1011 x = svx y = svy 1012 fait = 0 Select Case DIRECTION Case 0 If y - 1 >= 0 Then Select Case GrilleAI(x, y - 1) Case 0 px = x: py = y - 1 fait = 1 Case 1 DIRECTION = 1 Case 2 y = y - 1: GoTo 1012 End Select Else DIRECTION = 1 End If Case 1 's If y + 1 <= NBCELL - 1 Then Select Case GrilleAI(x, y + 1) Case 0 px = x: py = y + 1 fait = 1 Case 1 DIRECTION = 0 Case 2 y = y + 1: GoTo 1012 End Select Else DIRECTION = 0 End If Case 2 'e If x - 1 >= 0 Then Select Case GrilleAI(x - 1, y) Case 0 px = x - 1: py = y fait = 1 Case 1 DIRECTION = 3 Case 2 x = x - 1: GoTo 1012 End Select Else DIRECTION = 3 End If Case 3 'o If x + 1 <= NBCELL - 1 Then Select Case GrilleAI(x + 1, y) Case 0 px = x + 1: py = y fait = 1 Case 1 DIRECTION = 2 Case 2 x = x + 1: GoTo 1012 End Select Else DIRECTION = 2 End If End Select If memDIRECTION <> DIRECTION And passATAC = 0 Then x = svx y = svy passATAC = 1 GoTo 1012 End If If fait = 1 Then pox = px poy = py End If End Sub
Function envoi (x, y) If GrilleJoueur(x, y) = 1 Then Select Case GrilleJouBAT(x, y) Case 0 Btestjoue(0) = Btestjoue(0) - 1 Case 1 Btestjoue(1) = Btestjoue(1) - 1 Case 2 Btestjoue(2) = Btestjoue(2) - 1 Case 3 Btestjoue(3) = Btestjoue(3) - 1 Case 4 Btestjoue(4) = Btestjoue(4) - 1 End Select envoi = 1 nto = 0 For dfi = 0 To NBBATEAUX If Btestjoue(dfi) = 0 Then nto = nto + 1 Next dfi If nto <> Boat Then Boat = nto: envoi = 2 Else envoi = 0 End If End Function
Sub placebateau For encour = 0 To 4
hazard: If Rnd < .5 Then Swap B(encour).tx, B(encour).ty x = Int(Rnd * (NBCELL - 1)) y = Int(Rnd * (NBCELL - 1)) fait = 0 If poss(x, y, B(encour).tx, B(encour).ty) Then If B(encour).tx < B(encour).ty Then For by = y To y + B(encour).ty - 1 GrilleJoueur(x, by) = 1 GrilleJouBAT(x, by) = encour Next by Btestjoue(encour) = B(encour).ty fait = 1 Else For bx = x To x + B(encour).tx - 1 GrilleJoueur(bx, y) = 1 GrilleJouBAT(bx, y) = encour Next bx Btestjoue(encour) = B(encour).tx fait = 1 End If End If If fait = 0 Then GoTo hazard Next encour End Sub Function poss (x, y, tx, ty) If tx < ty Then For uy = y To y + ty - 1 If uy < NBCELL Then If GrilleJoueur(x, uy) = 1 Then poss = 0: Exit Function Else poss = 0 Exit Function End If Next uy Else For ux = x To x + tx - 1 If ux < NBCELL Then If GrilleJoueur(ux, y) = 1 Then poss = 0: Exit Function Else poss = 0 Exit Function End If Next ux End If poss = 1 End Function Sub trace (x, y, reponse) Select Case reponse Case 0 'water r = 0: g = 50: b = 128 Case 1 'touche r = 255: g = 0: b = 0 Case 2 'coule r = 255: g = 0: b = 0 End Select If reponse > 0 Then Line (350 + x * 10, y * 10)-(350 + x * 10 + 10, y * 10 + 10), _RGB(r, g, b), B Else Circle (350 + x * 10 + 5, y * 10 + 5), 2, _RGB(r, g, b) End If End Sub
Sub TESTbateau (x, y, xa, ya) If possAI(x, y, xa, ya) Then plus = testAI(x, y, xa, ya) If xa < ya Then For by = y To y + ya - 1 If GrilleAI(x, by) = 0 Then GrilleProb(x, by) = GrilleProb(x, by) + 1 + plus ' If GrilleAI(x, by) = 1 Then GrilleProb(x, by) = GrilleProb(x, by) - (by - y) Next by Else For bx = x To x + xa - 1 If GrilleAI(bx, y) = 0 Then GrilleProb(bx, y) = GrilleProb(bx, y) + 1 + plus ' If GrilleAI(bx, y) = 1 Then GrilleProb(bx, y) = GrilleProb(bx, y) - (bx - x) Next bx End If End If End Sub Function testAI (x, y, tx, ty) If tx < ty Then For uy = y To y + ty - 1
If GrilleAI(x, uy) = 2 Then testAIk = testAIk + 2
Next uy Else For ux = x To x + tx - 1
If GrilleAI(ux, y) = 2 Then testAIk = testAIk + 2
Next ux End If testAI = testAIk End Function Function possAI (x, y, tx, ty) If tx < ty Then For uy = y To y + ty - 1 If uy < NBCELL Then If GrilleAI(x, uy) = 1 Then possAI = 0: Exit Function Else possAI = 0 Exit Function End If Next uy Else For ux = x To x + tx - 1 If ux < NBCELL Then If GrilleAI(ux, y) = 1 Then possAI = 0: Exit Function Else possAI = 0 Exit Function End If Next ux End If possAI = 1 End Function
|
|
|
Post by bplus on Aug 4, 2024 11:11:21 GMT
ubi44 cool! It does play fast alright! A couple of times your AI looks like it tries wave patterns of bombing to find a ship, is that true? I have been wondering about trying something based on probabilities. The more open the area of sea, the more likely a ship might in there? I suppose along the edges, less probably a ship would be there because more restrictions in placement to stay in board boundaries. Also the order you place your ships in sea might effect the random placement ie starting by smallest ships first will make placement of larger ships more difficult and effect probabilities compared with placement starting with largest ships first. Just an idea to test... We might try a given set of setups and see how many shots it takes our AI's to sink ships? BTW do you check your PM's here? I sent you a message some time ago, did you see it?
|
|
ubi44
Junior Member
Posts: 52
|
Post by ubi44 on Aug 5, 2024 10:00:04 GMT
Okay to test the AI on a set of 5 boats.. 1 aircraft carrier length 5 1 cruiser length 4 1 destroyer length 3 1 submarine length 3 1 torpedo boat length 2
To place them, we have to choose the starting point in X, Y and the alignment if vertical it goes down, if horizontal it goes to the right ... e.g. aircraft carrier in 2; 2 horizontal starts at 2; 2 and finished in 6; 2 All right? I'll leave the choice in the positions! __________________________
The following program has a variable 'knowboat'(line 40) which makes when it is 1 that when a boat is sunk the AI knows which boat is sunk (it's a bit cheated) this allows to have less maximum stroke. if 'knowboat' is 0 the AI gets sunk but doesn't know what type of boat is sunk! It's really hard to know what kind of boat is sunk and I couldn't do it...
Type bateau tx As Integer ty As Integer str As String * 20 type As Integer coule As Integer End Type ReDim Shared B(4) As bateau B(0).str = "PORTE-AVION" B(1).str = "CROISEUR" B(2).str = "CONTRE-TORPILLEUR" B(3).str = "SOUS-MARIN" B(4).str = "TORPILLEUR" B(0).type = 0 B(1).type = 1 B(2).type = 1 B(3).type = 0 B(4).type = 1 B(0).tx = 1: B(0).ty = 5 B(1).tx = 1: B(1).ty = 4 B(2).tx = 1: B(2).ty = 3 B(3).tx = 1: B(3).ty = 3 B(4).tx = 1: B(4).ty = 2 B(0).coule = 5 B(1).coule = 4 B(2).coule = 3 B(3).coule = 3 B(4).coule = 2 ReDim Shared NBCELL, NBBATEAUX NBCELL = 10 Randomize Timer NBBATEAUX = 5 - 1 Screen _NewImage(800, 600, 32) minimum = NBCELL * NBCELL
'initialisation AI 36 ReDim Shared KNOWBOAT KNOWBOAT = 0 ReDim Shared GrilleAI(NBCELL - 1, NBCELL - 1) ReDim Shared GrilleProb(NBCELL - 1, NBCELL - 1) ReDim Shared GrilleJoueur(NBCELL - 1, NBCELL - 1) ReDim Shared GrilleJouBAT(NBCELL - 1, NBCELL - 1) ReDim Shared Btestjoue(NBBATEAUX) ReDim Shared memX(NBCELL - 1), memY(NBCELL - 1) ReDim Shared AI, Boat, DIRECTION, CUR, passATAC, mxCUR, sauvX, sauvY ReDim Shared MemB(NBBATEAUX) Boat = 0 NTO = 0 For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 GrilleJouBAT(x, y) = -1 Next y, x placebateau nombredecoup = 0 AI = 0 Cls , _RGB(12, 30, 26)
45
choix x, y
If GrilleAI(x, y) = 1 And AI <> 0 Then AI = 0: choix x, y
GrilleAI(x, y) = 1 nombredecoup = nombredecoup + 1
rep = envoi(x, y) ' 0=water 1=touche 2=coule 'soVai = AI 'If rep >= 1 Then BUF = BUF + 1
IA rep, x, y 'If KNOWBOAT = 0 Then
' If rep = 2 Then ' If soVai = 1 Then ' For i = 0 To NBBATEAUX ' If MemB(i) = 2 Then MemB(i) = 7: Exit For ' Next i
' End If ' End If
' If rep = 2 And soVai > 1 And BUF <= 5 Then ' For i = 0 To NBBATEAUX ' If MemB(i) = BUF Then ' MemB(i) = 7 ' Exit For ' End If ' Next i ' BUF = 0 ' End If ' If rep = 2 Then BUF = 0 'End If
trace x, y, rep Circle (450 + x * 10 + 5, y * 10 + 5), 2, _RGB(255, 255, 255) For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 If GrilleJoueur(x, y) = 1 Then r = 255: g = 255: b = 0 Line (450 + x * 10, y * 10)-(450 + x * 10 + 10, y * 10 + 10), _RGB(r, g, b), B Else r = 0: g = 0: b = 255 Circle (450 + x * 10 + 5, y * 10 + 5), 2, _RGB(r, g, b) End If Next y, x
Locate 1, 1: Print "MIN:"; minimum; "MAX:"; maximum; "MOY"; Int(moyenne) Print nombredecoup
_Display 'ktim = Timer + .01 'slowdown the show! Do Loop Until ktim < Timer
If Boat = NBBATEAUX + 1 Then total = total + nombredecoup partie = partie + 1 moyenne = total / partie If minimum > nombredecoup Then minimum = nombredecoup If maximum < nombredecoup Then maximum = nombredecoup If nombredecoup = 17 Then End End If
GoTo 36 End If
If InKey$ = Chr$(27) Then End
GoTo 45 Sub choix (x, y) 145 Select Case AI Case 0 stat x, y Case 1 HBGD x, y passATAC = 0 Case 2 attac0 x, y If AI = 3 Then passATAC = 0 Select Case DIRECTION Case 0 If Rnd < .5 Then DIRECTION = 2 Else DIRECTION = 3 Case 1 If Rnd < .5 Then DIRECTION = 3 Else DIRECTION = 2 Case 2 If Rnd < .5 Then DIRECTION = 0 Else DIRECTION = 1 Case 3 If Rnd < .5 Then DIRECTION = 1 Else DIRECTION = 0 End Select sauvX = memX(mxCUR) sauvY = memY(mxCUR) GoTo 145 End If Case 3 attac1 sauvX, sauvY, x, y End Select End Sub Sub IA (rep, x, y) Select Case rep Case 0 Select Case AI Case 0 AI = 0 Case 1 AI = 1 Case 2 If passATAC = 0 Then Select Case DIRECTION Case 0 DIRECTION = 1 CUR = 0 Case 1 DIRECTION = 0 CUR = 0 Case 2 DIRECTION = 3 CUR = 0 Case 3 DIRECTION = 2 CUR = 0 End Select passATAC = 1 Else AI = 3 Select Case DIRECTION Case 0 DIRECTION = 2 Case 1 DIRECTION = 3 Case 2 DIRECTION = 0 Case 3 DIRECTION = 1 End Select passATAC = 0 sauvX = memX(mxCUR) 'CUR = 0 sauvY = memY(mxCUR) End If Case 3 If passATAC = 0 Then Select Case DIRECTION Case 0 DIRECTION = 1 Case 1 DIRECTION = 0 Case 2 DIRECTION = 3 Case 3 DIRECTION = 2 End Select passATAC = 1 sauvX = memX(mxCUR) sauvY = memY(mxCUR)
End If End Select Case 1 GrilleAI(x, y) = 2 Select Case AI Case 0 ReDim memX(NBCELL - 1), memY(NBCELL - 1) CUR = 0 memX(CUR) = x: memY(CUR) = y AI = 1 Case 1 CUR = CUR + 1 mxCUR = CUR memX(CUR) = x: memY(CUR) = y AI = 2 Case 2 CUR = CUR + 1 mxCUR = CUR memX(CUR) = x: memY(CUR) = y AI = 2 Case 3 sauvX = x sauvY = y AI = 3 End Select Case 2 GrilleAI(x, y) = 2 Select Case AI Case 0, 1, 2 CUR = 0 AI = 0 Case 3 mxCUR = mxCUR - 1 If mxCUR < 0 Then AI = 0 mxCUR = 0 CUR = 0 Else Select Case DIRECTION Case 0 If Rnd < .5 Then DIRECTION = 1 Case 1 If Rnd < .5 Then DIRECTION = 0 Case 2 If Rnd < .5 Then DIRECTION = 3 Case 3 If Rnd < .5 Then DIRECTION = 2 End Select sauvX = memX(mxCUR) sauvY = memY(mxCUR) passATAC = 0 End If End Select If KNOWBOAT = 1 Then ox = x: oy = y For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 If GrilleJouBAT(ox, oy) = GrilleJouBAT(x, y) And GrilleAI(x, y) = 2 Then GrilleAI(x, y) = 1 Next y, x MemB(GrilleJouBAT(ox, oy)) = 0 x = ox: y = oy End If End Select End Sub Sub stat (pox, poy) For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 If GrilleAI(x, y) = 0 Then GrilleProb(x, y) = .1 Else GrilleProb(x, y) = 0 '+ (2 - GrilleAI(x, y)) 'If GrilleAI(x, y) = 2 Then pull = pull + 1 Next y, x For i = 0 To NBBATEAUX If plusorb < MemB(i) And MemB(i) < 7 Then plusorb = MemB(i) Next i If KNOWBOAT = 1 Then For g = 0 To NBBATEAUX If MemB(g) > 0 And MemB(g) < 7 Then xa = MemB(g) ya = 1 For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 TESTbateau x, y, xa, ya, plusorb TESTbateau x, y, ya, xa, plusorb Next y, x End If Next g Else ' Sleep For g = 0 To NBBATEAUX If MemB(g) < 7 Then xa = MemB(g) ya = 1 For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 TESTbateau x, y, xa, ya, plusorb TESTbateau x, y, ya, xa, plusorb Next y, x End If Next g End If bob = 0 ReDim cvX((NBCELL * NBCELL * .5) + .5), cvY((NBCELL * NBCELL * .5) + .5) For x = 0 To NBCELL - 1 If sty = 0 Then sty = 1 Else sty = 0 For y = sty To NBCELL - 1 Step 2 cvX(bob) = x cvY(bob) = y bob = bob + 1 Next y, x Randomize Timer(.00001) 444 lim = Int((NBCELL - 1) / 5)
kop = 0 For x = 0 To NBCELL - 1 For y = 0 To NBCELL - 1 cl = GrilleProb(x, y) * (2) Line (350 + x * 10 + 2.5, 150 + y * 10)-(350 + x * 10 + 10 - 2.5, 150 + y * 10 + 10), _RGB(cl, cl, cl), BF If cl > kop And GrilleAI(x, y) = 0 Then For i = 0 To bob - 1 If x = cvX(i) And y = cvY(i) Then pox = x poy = y kop = cl doit = 1
End If Next i End If
Next y, x If boot > 10 And doit = 0 Then sty = 1: bob = 0 ReDim cvX(NBCELL * NBCELL * .5 + .5), cvY(NBCELL * NBCELL * .5 + .5) For x = 0 To NBCELL - 1 If sty = 0 Then sty = 1 Else sty = 0 For y = sty To NBCELL - 1 Step 2 cvX(bob) = x cvY(bob) = y bob = bob + 1 Next y, x GoTo 444 End If If doit = 0 Then boot = boot + 1: GoTo 444
End Sub Sub HBGD (pox, poy) 'ai=1 x = memX(CUR): y = memY(CUR) esp = 1 i = -1 pxl = x: pyl = y stat pxl, pyl tente0 = -1: tente1 = -1: tente2 = -1: tente3 = -1 340 fait = 0 For i = 0 To 3 Select Case i Case 0 'n If y - esp >= 0 Then If GrilleAI(x, y - esp) = 0 Then px = x: py = y - esp mix0 = GrilleProb(x, y - esp)
fait = 1 Else tente0 = GrilleAI(x, y - esp)
End If Else tente0 = 1 End If Case 1 's If y + esp <= NBCELL - 1 Then If GrilleAI(x, y + esp) = 0 Then px = x: py = y + esp mix1 = GrilleProb(x, y + esp) fait = 1 Else tente1 = GrilleAI(x, y + esp) End If Else tente1 = 1 End If Case 2 'e If x - esp >= 0 Then If GrilleAI(x - esp, y) = 0 Then px = x - esp: py = y mix2 = GrilleProb(x - esp, y) fait = 1 Else tente2 = GrilleAI(x - esp, y) End If Else tente2 = 1 End If Case 3 'o If x + esp <= NBCELL - 1 Then If GrilleAI(x + esp, y) = 0 Then px = x + esp: py = y mix3 = GrilleProb(x + esp, y) fait = 1 Else tente3 = GrilleAI(x + esp, y) End If Else tente3 = 1 End If End Select Next i If tente1 >= 1 And tente0 >= 1 And tente2 >= 1 And tente3 >= 1 Then ttt = 0 af = 0 If tente0 = 2 Then i = 0 If tente1 = 2 Then i = 1 If tente2 = 2 Then i = 2 If tente3 = 2 Then i = 3 tente1 = -1: tente0 = -1: tente2 = -1: tente3 = -1 mix0 = 0: mix1 = 0: mix2 = 0: mix3 = 0: esp = esp + 1 ' i = ttt GoTo 340 End If If tente0 = -1 Then af = mix0: ttt = 0 If tente1 = -1 Then If mix1 > af Then af = mix1: ttt = 1 If tente2 = -1 Then If mix2 > af Then af = mix2: ttt = 2 If tente3 = -1 Then If mix3 > af Then af = mix3: ttt = 3 Select Case ttt Case 0 pox = x: poy = y - esp Case 1 pox = x: poy = y + esp Case 2 pox = x - esp: poy = y Case 3 pox = x + esp: poy = y End Select DIRECTION = ttt End Sub
Sub attac0 (pox, poy) memDIRECTION = DIRECTION x = memX(CUR) y = memY(CUR) 1012 fait = 0 Select Case DIRECTION Case 0 If y - 1 >= 0 Then Select Case GrilleAI(x, y - 1) Case 0 px = x: py = y - 1 fait = 1 Case 1 DIRECTION = 1 Case 2 y = y - 1: GoTo 1012 End Select Else DIRECTION = 1 End If Case 1 's If y + 1 <= NBCELL - 1 Then Select Case GrilleAI(x, y + 1) Case 0 px = x: py = y + 1 fait = 1 Case 1 DIRECTION = 0 Case 2 y = y + 1: GoTo 1012 End Select Else DIRECTION = 0 End If Case 2 'e If x - 1 >= 0 Then Select Case GrilleAI(x - 1, y) Case 0 px = x - 1: py = y fait = 1 Case 1 DIRECTION = 3 Case 2 x = x - 1: GoTo 1012 End Select Else DIRECTION = 3 End If Case 3 'o If x + 1 <= NBCELL - 1 Then Select Case GrilleAI(x + 1, y) Case 0 px = x + 1: py = y fait = 1 Case 1 DIRECTION = 2 Case 2 x = x + 1: GoTo 1012 End Select Else DIRECTION = 2 End If End Select If memDIRECTION <> DIRECTION And passATAC = 0 Then x = memX(0) y = memY(0) passATAC = 1 GoTo 1012 End If If passATAC = 1 And fait = 0 Then AI = 3 ': Sleep If fait = 1 Then pox = px poy = py End If End Sub Sub attac1 (svx, svy, pox, poy) memDIRECTION = DIRECTION 1011 x = svx y = svy 1012 fait = 0 Select Case DIRECTION Case 0 If y - 1 >= 0 Then Select Case GrilleAI(x, y - 1) Case 0 px = x: py = y - 1 fait = 1 Case 1 DIRECTION = 1 Case 2 y = y - 1: GoTo 1012 End Select Else DIRECTION = 1 End If Case 1 's If y + 1 <= NBCELL - 1 Then Select Case GrilleAI(x, y + 1) Case 0 px = x: py = y + 1 fait = 1 Case 1 DIRECTION = 0 Case 2 y = y + 1: GoTo 1012 End Select Else DIRECTION = 0 End If Case 2 'e If x - 1 >= 0 Then Select Case GrilleAI(x - 1, y) Case 0 px = x - 1: py = y fait = 1 Case 1 DIRECTION = 3 Case 2 x = x - 1: GoTo 1012 End Select Else DIRECTION = 3 End If Case 3 'o If x + 1 <= NBCELL - 1 Then Select Case GrilleAI(x + 1, y) Case 0 px = x + 1: py = y fait = 1 Case 1 DIRECTION = 2 Case 2 x = x + 1: GoTo 1012 End Select Else DIRECTION = 2 End If End Select If memDIRECTION <> DIRECTION And passATAC = 0 Then x = svx y = svy passATAC = 1 memDIRECTION = DIRECTION GoTo 1012 End If If fait = 1 Then pox = px poy = py End If End Sub Function envoi (x, y) If GrilleJoueur(x, y) = 1 Then Btestjoue(GrilleJouBAT(x, y)) = Btestjoue(GrilleJouBAT(x, y)) - 1 envoi = 1 nto = 0 For dfi = 0 To NBBATEAUX If Btestjoue(dfi) = 0 Then nto = nto + 1 Next dfi If nto <> Boat Then Boat = nto: envoi = 2 Else envoi = 0 End If End Function
Sub placebateau For encour = 0 To 4
hazard: If Rnd < .5 Then Swap B(encour).tx, B(encour).ty x = Int(Rnd * (NBCELL - 1)) y = Int(Rnd * (NBCELL - 1)) fait = 0 If poss(x, y, B(encour).tx, B(encour).ty) Then If B(encour).tx < B(encour).ty Then For by = y To y + B(encour).ty - 1 GrilleJoueur(x, by) = 1 GrilleJouBAT(x, by) = encour Next by Btestjoue(encour) = B(encour).ty fait = 1 Else For bx = x To x + B(encour).tx - 1 GrilleJoueur(bx, y) = 1 GrilleJouBAT(bx, y) = encour Next bx Btestjoue(encour) = B(encour).tx fait = 1 End If End If If fait = 0 Then GoTo hazard MemB(encour) = B(encour).coule Next encour End Sub Function poss (x, y, tx, ty) If tx < ty Then For uy = y To y + ty - 1 If uy < NBCELL Then If GrilleJoueur(x, uy) = 1 Then poss = 0: Exit Function Else poss = 0 Exit Function End If Next uy Else For ux = x To x + tx - 1 If ux < NBCELL Then If GrilleJoueur(ux, y) = 1 Then poss = 0: Exit Function Else poss = 0 Exit Function End If Next ux End If poss = 1 End Function Sub trace (x, y, reponse) Select Case reponse Case 0 'water r = 0: g = 50: b = 128 Case 1 'touche r = 255: g = 0: b = 0 Case 2 'coule r = 255: g = 0: b = 0 End Select If reponse > 0 Then Line (350 + x * 10, y * 10)-(350 + x * 10 + 10, y * 10 + 10), _RGB(r, g, b), B Else Circle (350 + x * 10 + 5, y * 10 + 5), 2, _RGB(r, g, b) End If End Sub
Sub TESTbateau (x, y, xa, ya, u) tp = (Int((Abs((NBCELL - 1) * .5 - x) + Abs((NBCELL - 1) * .5 - y)) * .5) / NBCELL) * 10 If possAI(x, y, xa, ya) Then If xa < ya Then If ya = u Then plus = 1 + u For by = y To y + ya - 1 If GrilleAI(x, by) = 0 Then GrilleProb(x, by) = GrilleProb(x, by) + (ya + plus + tp) Next by Else If xa = u Then plus = 1 + u For bx = x To x + xa - 1 If GrilleAI(bx, y) = 0 Then GrilleProb(bx, y) = GrilleProb(bx, y) + (xa + plus + tp) Next bx End If End If End Sub Function testAI (x, y, tx, ty) If tx < ty Then For uy = y To y + ty - 1
If GrilleAI(x, uy) = 2 Then testAIk = testAIk + 2
Next uy Else For ux = x To x + tx - 1
If GrilleAI(ux, y) = 2 Then testAIk = testAIk + 2
Next ux End If testAI = testAIk End Function Function possAI (x, y, tx, ty) If tx < ty Then For uy = y To y + ty - 1 If uy < NBCELL Then If GrilleAI(x, uy) = 1 Then possAI = 0: Exit Function Else possAI = 0 Exit Function End If Next uy Else For ux = x To x + tx - 1 If ux < NBCELL Then If GrilleAI(ux, y) = 1 Then possAI = 0: Exit Function Else possAI = 0 Exit Function End If Next ux End If possAI = 1 End Function
|
|
|
Post by bplus on Aug 5, 2024 13:54:43 GMT
Yes I agree, the AI is allowed to know the length of the ship sunk 5, 4, 3, 3, 2 could know ship name too doesn't make a differnce.. BUT! the AI is NOT allowed to know if the ship was horizontal or vertical nor is the AI allowed to know which shots it made sank the ship. The AI must track it's shots and deduce what it needs from only being allowed to know a ship (by name or by length) was sunk on it's last shot. That is my HitEval subroutine, it is like a referee in announcing ships sunk AI's or Player's and it does one thing for AI reduces the CurrentHits count by the length of the ship because the AI could do that anyway (from the name of the ship) same as the Player. I think that fair and not a cheat. What I was proposing was a CONTEST between AI's, your's ubi44, and mine, and anyone else who might want to give it a try as well. We need a Common Set of ship positions to test each AI with to see how many, on average say of 100?, it takes each AI to sink all the ships (while the Player just sits out the game). This is just an idea, I offer because I know I can program my game to do this fairly easily. read in a set of ship positions setup the simulation run the sim and count the number of shots to sink all the ships. Just wondering if you are also up for the Challenge? Might be fun friendly competition. If disagreement arises, we just quit or let 3rd party decide, our relationship here at forum is more important than silly game. Battleship Olympics? We could start that in Discussion board (Rules regulations the Common set of ship setups...) and particpants show their coded versions in Programs Board so everyone can test for themself the other persons code.
|
|
ubi44
Junior Member
Posts: 52
|
Post by ubi44 on Aug 5, 2024 14:36:17 GMT
I'm ok for this "Battleship Olympics" It's fun and I'm going to work on modifying the program so that we can easily enter the coordinates of the ships (it must be simple). My AI doesn't know the position or orientation of the ships, it can just know which boats it sank and therefore what it has to do! My program also allows you to increase the size of the grid (10 basic) and the number of boats !(This may be interesting) I'll post the modified program here, as soon as it's ready, and then we can start the "Battleship Olympics".(I love this title... )
|
|
|
Post by bplus on Aug 5, 2024 15:09:20 GMT
Hi ubi44 You can post in this thread if you prefer but I think each partricipant post in their own Thread (Under you name, Battleship Olympics their code) I will start "bplus, Battleship Olympics" when I get a start on accepting Board positions from forum to test run and count shots to sink ships. Also so that everyone plays under same set of rules keep your "official" versions to 10 x 10, of course you can do anything you please, just saying to keep everyone under the same conditions.
|
|
ubi44
Junior Member
Posts: 52
|
Post by ubi44 on Aug 5, 2024 19:01:04 GMT
Hi bplus My program is ready! the boats are to be placed from the largest (5) to the smallest (2) by entering a letter for the abscissa and a number for the ordinate as in your program (a - j) (0-9) then h or v for horizontal or vertical. I think we should do the same at this level to easily enter data... I suggest you create a Battleship Olympics thread yourself and tell me in which section it is and I will post the program there. (I won't be able to do it myself) sorry bplus i just see your thread in >Discussion !
|
|
|
Post by bplus on Aug 5, 2024 19:17:25 GMT
Wow! that was fast! My hint was to post your code for battleship Olympics in your own separate Thread in the Programs Board. For you ubi44, you would post your new Thread under Programs "ubi44, Battleship Olympics" For me I will post in Programs Board: "bplus, Battleship Olympics" We post our own code updates in separate Threads, others may comment but post their own code ideas in their own thread titled: "avatar name, Battleship Olympics" I like assumed ship list ordered from biggest to smallest, yeah we could put the h | v at the right end instead of at the start, left end or maybe our code could look instr for h or v, look instr for a letter and look for a digit, since all 3 symbols come from mutually exclusive groups, we don't have to demand h or v first or last or even middle. It would just be easier if we agreed on same thing before we got started.
|
|
|
Post by bplus on Aug 5, 2024 19:19:31 GMT
LOL luv your enthusiasm ubi!
|
|
|
Post by bplus on Aug 5, 2024 19:35:33 GMT
|
|