Author Topic: Simple example of LAN game with 2-4 PCs?  (Read 3838 times)

0 Members and 1 Guest are viewing this topic.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Simple example of LAN game with 2-4 PCs?
« on: July 02, 2021, 04:21:03 pm »
Hi all,
I'm interested in writing a simple local network game for 2-4 PCs.
I have no idea how to approach it, and am not too knowledgable about networking, so would like to keep it as simple as possible while still following whatever the standard practices are. It should not require the users to know much about networking or mess with the networking/firewall settings on their computer (if possible?)
Can anyone either post some code or maybe a link to a simple & minimal example of a game for 2-4 computers (preferably connected together via a wired hub)?
Any info would be much appreciated...

PS If it makes any difference, this would be for lower bandwidth games, stuff like Battleship, Spacewar, Pong, Roguelikes - not any kind of super fast MMO 3D game sending/receiving a ton of data.
« Last Edit: July 02, 2021, 04:29:47 pm by madscijr »

Offline SpriggsySpriggs

  • Forum Resident
  • Posts: 1145
  • Larger than life
    • View Profile
    • GitHub
Re: Simple example of LAN game with 2-4 PCs?
« Reply #1 on: July 02, 2021, 04:23:29 pm »
@FellippeHeitor Sounds like a job for Amongst
Shuwatch!

FellippeHeitor

  • Guest
Re: Simple example of LAN game with 2-4 PCs?
« Reply #2 on: July 02, 2021, 06:32:29 pm »
Hehe 🤩

https://github.com/FellippeHeitor/amongst <-- run the server once, up to 10 clients can connect

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #3 on: July 02, 2021, 08:30:26 pm »
Hehe 🤩

https://github.com/FellippeHeitor/amongst <-- run the server once, up to 10 clients can connect

That looks really neat, I will give it a look. Thanks!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #4 on: July 03, 2021, 11:22:14 am »
Can always check out my BattleShip game, it has LAN options.
https://www.qb64.org/forum/index.php?topic=826.msg100326
Granted after becoming radioactive I only have a half-life!

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #5 on: July 12, 2021, 09:05:20 am »
Can always check out my BattleShip game, it has LAN options.
https://www.qb64.org/forum/index.php?topic=826.msg100326

Thanks I will do that. The week turned out to be a little busy but I will get back to this in the next couple of days and post an update. Thanks again everybody.

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #6 on: July 12, 2021, 10:32:49 am »
Can always check out my BattleShip game, it has LAN options.
https://www.qb64.org/forum/index.php?topic=826.msg100326

Question, what format file is "battleship.gfx", and how would you edit it?
Thanks...

Offline madscijr

  • Seasoned Forum Regular
  • Posts: 295
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #7 on: July 13, 2021, 01:13:35 pm »
Can always check out my BattleShip game, it has LAN options.
https://www.qb64.org/forum/index.php?topic=826.msg100326

I was looking at your code, and got the genius idea (I hope you are picking up on the sarcasm here)
to rename the variables a little less ambiguously to help me follow what the code is doing,
and I seem to have introduced a little bug where when you place a ship on the board, it disappears.
If you have any bandwidth, and could quickly zero in on the line that might be making that happen,
that would be very much appreciated... No pressure or anything, LoL

Code: QB64: [Select]
  1. ' ################################################################################################################################################################
  2. ' Battle Ship 64 by Cobalt
  3. ' ################################################################################################################################################################
  4.  
  5. ' =============================================================================
  6. ' CHANGE LOG
  7.  
  8. ' WHEN         WHO            WHAT
  9. ' 11/23/2018   Cobalt David   Started (30 mins)
  10. ' 11/23/2018   Cobalt David   V0.0a inital build (45 mins)
  11. '                             inital types and diminsions in place
  12. ' 11/24/2018   Cobalt David   V0.0b build (30 mins)
  13. '                             added Title screen
  14. '                             loaded sprite sheet
  15. ' 11/27/2018   Cobalt David   V0.1a First Run Build (300 mins)
  16. '                             Added\Finished ship deployment
  17. '                             added auto deployment for computer opponent
  18. '                             added yellow selection color for ship placement and shot selection
  19. '                             started shot taking routine
  20. '                             added Who goes first test
  21. '                             (made audio files for posible add-in later)
  22. '                             (ripped video files for posible add-in later)
  23. ' 11/28/2018   Cobalt David   V0.1b Build (240 mins)
  24. '                             Added Hit and Miss images
  25. '                             added player shot routines
  26. '                             added ship sunk routines
  27. '                             added Gameover state
  28. '                             added Computer shooting routine
  29. ' 11/29/2018   Cobalt David   V0.1C Build (150 mins)
  30. '                             fixed Computer Shooting routine, computer can now hit players ships.
  31. '                             fixed message timing, so its a hit shows before ship sunk message
  32. '                             set randomize to TIMER
  33. '                             game level Easy, Computer AI: STUPID(always random shots)
  34. '                             added graphics loading rountine
  35. '                             public release
  36. ' 11/29/2018   Cobalt David   V0.1D Build (10 mins)
  37. '                             fixed oversight found by Bplus were autoplace doesn't clear board first
  38. '                             adding extra 'ghost' ships to the layout.
  39. '                             Added Title bar info.
  40. ' 11/30/2018   Cobalt David   V0.2A Build (540 mins)
  41. '                             Added Menu and options
  42. '                             Added ChangeColor routine
  43. '                             added fonts
  44. '                             added instruction page 1
  45. '                             fixed bug if player pressed Reset with ship selected ship stayed selected as a phantom ship.
  46. '                             Updated GFX file
  47. '                             Began networking routines
  48. '                             first successful log in of clients
  49. ' 12/01/2018   Cobalt David   V0.5A Build (300 mins)
  50. '                             Ripped Functions\Subs for network retooling.
  51. '                             Added Networking types\variables\arrays\consts
  52. '                             added\fixed host startup and client startup
  53. '                             added communication decodeing
  54. '                             added Opponent shot for multiplayer games
  55. ' 12/02/2018   Cobalt David   V0.7A build (210 mins)
  56. '                             fixed networking protocol
  57. '                             fixed minor bugs related to network game communication
  58. '                             added IP address entry to join network screen
  59. '                             reconsistuted routines into main BAS file
  60. '                             First successful LAN game at 19:55 EST
  61. ' 07/12/2021   madscijr       Prettified code a little, renamed variables with Hungarian notation
  62. '                             to easily identify which ones are shared, constants, arrays, UDTs, etc.
  63. '                             Broke something so now when you place a ship, it disappears! DOH!
  64.  
  65. ' =============================================================================
  66. ' NOTES:
  67. ' fonts:Vecteezy.com/free-fonts.com/Geronimo Font Studios[dafont.com]
  68.  
  69. ' QB64 variable types:
  70. ' a$  = string
  71. ' i%  = integer
  72. ' L&  = long
  73. ' s!  = single
  74. ' d#  = double
  75. ' b%% = byte
  76.  
  77. ' -----------------------------------------------------------------------------
  78. ' A Short Course in Hungarian Notation
  79. ' http://www.imm.dtu.dk/~alan/hungarian.html
  80.  
  81. ' In general, Hungarian notation names a variable with a lower-case prefix
  82. ' to identify the class or usage of the variable. There is no such thing as
  83. ' standard HN, so the point here is to create a consistent notation system.
  84. ' In this class, we'll use the following standards.
  85. '       c: signed character <- *** NOT USED IN THIS PROGRAM c SPECIFIES CONSTANTS ***
  86. '      uc: unsigned character
  87. '       i: integer
  88. '      ui: unsigned integer
  89. '      si: short integer
  90. '      li: long integer
  91. '       n: an integer number where the actual size is irrelevant
  92. '       f: float
  93. '       d: double
  94. '       s: string of characters
  95. '      sz: string of characters, terminated by a null character
  96. '       b: an integer or character being used as a boolean value
  97. '      by: single byte
  98. '      ct: an integer being used as a counter or tally
  99. '       p: pointer to a structure or general void pointer
  100. '     pfs: file stream pointer
  101. '     pfn: pointer to a function
  102. '      px: pointer to a variable of class x, e.g. pi, pf, pli
  103. '
  104. ' Other prefixes:
  105. '       c: constant
  106. '       m: shared (module-level) variable
  107. '      st: static variable
  108. '     arr: array
  109.  
  110. ' Suffixes:
  111. '     {name}_Type: user-defined types (UDTs) end with "_Type"
  112.  
  113. ' =============================================================================
  114. ' USER-DEFINED TYPES (UDTs)
  115.  
  116. Type Pos_Hits_Type
  117.     Xpos As _Byte
  118.     Ypos As _Byte
  119.     Orent As _Byte
  120.     Hits As _Byte
  121.     sunk As _Byte
  122.     placed As _Byte
  123. End Type ' Pos_Hits_Type
  124.  
  125. Type Ships_Type
  126.     Carrier As Pos_Hits_Type
  127.     Battle As Pos_Hits_Type
  128.     Destroyer As Pos_Hits_Type
  129.     Submarine As Pos_Hits_Type
  130.     Patrol As Pos_Hits_Type
  131. End Type ' Ships_Type
  132.  
  133. Type Ship_Board_Offsets_Type
  134.     Board_VX As _Byte
  135.     Board_VY As _Byte
  136.     Board_HX As _Byte
  137.     Board_HY As _Byte
  138.     RedBoard_VX As Integer
  139.     RedBoard_VY As Integer
  140.     RedBoard_HX As Integer
  141.     RedBoard_HY As Integer
  142.     ShipYard_X As Integer
  143.     ShipYard_Y As Integer
  144. End Type ' Ship_Board_Offsets_Type
  145.  
  146. Type Networking_Type
  147.     Host As Long ' host ID
  148.     Client As Long ' Client ID
  149.     Users As _Byte ' Clients Connected, 2 max
  150.     Ready As _Byte ' Opponent has placed ships
  151.     X As _Byte ' Opponents shot X location
  152.     Y As _Byte ' Opponents shot Y location
  153. End Type ' Networking_Type
  154.  
  155. Type Client_Type
  156.     PingTime As Long
  157.     Id As Long
  158. End Type ' Client_Type
  159.  
  160. Type Game_Data_Type
  161.     PlayerDead As _Byte
  162.     OpponentDead As _Byte
  163.     GameOver As _Byte
  164.     WhoIsUp As _Byte
  165.     NetWork As Networking_Type
  166.     Mode As _Byte
  167.     Debug As _Byte
  168. End Type ' Game_Data_Type
  169.  
  170. ' =============================================================================
  171. ' GLOBAL DECLARATIONS
  172.  
  173. Dim Shared m_arrBoard(10, 10, 2) As _Byte ' 1-player layout\OPPONENT shots 2-player shots
  174. Dim Shared m_arrFleet(2) As Ships_Type ' *** IS THIS USED?
  175. Dim Shared m_arrOffs(5) As Ship_Board_Offsets_Type
  176. Dim Shared m_GameData As Game_Data_Type
  177. Dim Shared m_arrShip(10) As Pos_Hits_Type ' 1-5 player 6-10 OPPONENT
  178. Dim Shared m_arrShipName$(5) ' names of ship types
  179. Dim Shared m_arrLayer(10) As _Unsigned Long
  180. Dim Shared m_byStarts As _Byte ' *** IS THIS USED?
  181. Dim Shared m_arrFFX(12) As _Unsigned Long
  182. Dim Shared m_arrUser(2) As Client_Type
  183. Dim Shared m_Message$
  184. Dim Shared m_Listen&
  185. Dim Shared m_Cancel%%
  186.  
  187. Const c_CARRIER = 1, c_BATTLESHIP = 2, c_DESTROYER = 3, c_SUBMARINE = 4, c_PTBOAT = 5
  188. Const TRUE = -1, FALSE = Not TRUE
  189. Const c_HORZ = 11, c_VERT = 12
  190. Const c_MIX = 1, c_TITLE = 2, c_SHEET = 3, c_SHIPS = 4, c_SHOTS = 5, c_BOARD = 6, c_PEGS = 7, c_MENU = 8, c_LAN = 9
  191. Const c_PLAYER = 1, c_OPPONENT = 2, c_LANCLIENT = 3
  192. Const c_BlueBoard~& = _RGBA32(7, 15, 212, 48)
  193. Const c_RedBoard~& = _RGBA32(212, 15, 7, 48)
  194. Const c_YellowSelect~& = _RGBA32(212, 192, 7, 80)
  195. Const c_HIT = -1, c_MISS = -2, c_BAD = 4
  196.  
  197. ' ship yard horzontal offsets
  198. ShipYardOffsetsData:
  199. Data 68,316,68,343,68,367,68,393,66,416
  200.  
  201. ShipBoardOffsetsData:
  202. Data 57,55,58,57,55,58,56,60,55,58
  203. Data 54,58,56,57,57,55,59,57,58,55
  204.  
  205. ShipBoardOffsetsRedData:
  206. Data 347,55,347,57,343,58,345,60,343,58
  207. Data 343,58,344,57,345,55,347,57,346,55
  208.  
  209. ShipNamesData:
  210. Data "Carrier","Battle Ship","Destroyer","Submarine","PT Boat"
  211.  
  212. m_Listen& = _FreeTimer
  213. On Timer(m_Listen&, .1) MessageCheck ' timer for Host status.
  214.  
  215. Screen _NewImage(640, 480, 32)
  216. INIT ' load screens, load data, set randomizer
  217.  
  218. ' Title Screen
  219. _PutImage , m_arrLayer(c_TITLE), LayerD&
  220. _Delay 5.5
  221.  
  222. ' *****************************************************************************
  223. m_GameData.Debug = FALSE
  224. ' *****************************************************************************
  225.  
  226. SetUpGameBoard
  227. MainMenu
  228.  
  229. ' /////////////////////////////////////////////////////////////////////////////
  230. ' Game Menu
  231.  
  232. Sub MainMenu
  233.     _Font m_arrFFX(2), m_arrLayer(c_MIX)
  234.     ExitFlag%% = FALSE
  235.  
  236.     Do
  237.         _PutImage , m_arrLayer(c_MENU), m_arrLayer(c_MIX)
  238.         If m_GameData.Mode = c_LAN Then
  239.             ChangeColor _RGB32(248, 48, 64), m_arrLayer(c_MIX)
  240.             _PrintString (0, 450), "CONNECTED", m_arrLayer(c_MIX)
  241.         End If
  242.         ChangeColor _RGB32(48, 48, 64), m_arrLayer(c_MIX) ' BASE COLOR
  243.         _PrintString (280, 150), "PLAY GAME", m_arrLayer(c_MIX)
  244.         If m_GameData.Mode <> c_LAN Then
  245.             _PrintString (280, 180), "START NETWORK GAME", m_arrLayer(c_MIX)
  246.         Else
  247.             _PrintString (280, 180), "STOP NETWORK GAME", m_arrLayer(c_MIX)
  248.         End If
  249.         _PrintString (280, 210), "JOIN NETWORK GAME", m_arrLayer(c_MIX)
  250.         _PrintString (280, 240), "INSTRUCTION!", m_arrLayer(c_MIX)
  251.         _PrintString (280, 270), "QUIT GAME", m_arrLayer(c_MIX)
  252.  
  253.         If over%% Then ' hi-lite option mouse is over
  254.             ChangeColor _RGB32(248, 248, 48), m_arrLayer(c_MIX) ' Hover color
  255.             Select Case over%%
  256.                 Case 1
  257.                     _PrintString (280, 150), "PLAY GAME", m_arrLayer(c_MIX)
  258.                 Case 2
  259.                     If m_GameData.Mode <> c_LAN Then
  260.                         _PrintString (280, 180), "START NETWORK GAME", m_arrLayer(c_MIX)
  261.                     Else
  262.                         _PrintString (280, 180), "STOP NETWORK GAME", m_arrLayer(c_MIX)
  263.                     End If
  264.                 Case 3
  265.                     _PrintString (280, 210), "JOIN NETWORK GAME", m_arrLayer(c_MIX)
  266.                 Case 4
  267.                     _PrintString (280, 240), "INSTRUCTION!", m_arrLayer(c_MIX)
  268.                 Case 5
  269.                     _PrintString (280, 270), "QUIT GAME", m_arrLayer(c_MIX)
  270.             End Select
  271.         End If
  272.  
  273.         If _MouseButton(1) Then ' player clicked on option
  274.             Select Case over%%
  275.                 Case 1 ' play the game
  276.                     DeployFleet
  277.                     AutoPlaceShips c_OPPONENT
  278.                     ClearArea
  279.                     GamePlay
  280.                     _Font m_arrFFX(2), m_arrLayer(c_MIX)
  281.                 Case 2 ' start host for network game
  282.                     If m_GameData.Mode = c_LAN Then
  283.                         ' close down host and host's client reset game to normal mode
  284.                         ' turn off network listening timer
  285.                         Close #6
  286.                         Timer(m_Listen&) Off
  287.                         Close #m_GameData.NetWork.Client
  288.                         Close #m_GameData.NetWork.Host
  289.                         m_GameData.Mode = FALSE
  290.                     Else
  291.                         'IF m_GameData.Debug THEN OPEN "Debughost.txt" FOR OUTPUT AS #6
  292.                         CreateNetworkGame
  293.                     End If
  294.                     UpDate%% = TRUE
  295.                 Case 3 ' find network game on server list and join
  296.                     'IF m_GameData.Debug THEN OPEN "debugclient.txt" FOR OUTPUT AS #6
  297.                     JoinNetworkGame
  298.                     If Not m_Cancel%% Then
  299.                         ' -----------------------------------------------------------------------------
  300.                         ' game is now in network mode
  301.  
  302.                         ' start game directly
  303.                         DeployFleet
  304.                         ClearArea
  305.                         GamePlay
  306.                     Else
  307.                         m_Cancel%% = FALSE ' player hit ESC
  308.                     End If
  309.                     Timer(m_Listen&) Off
  310.                     Close #m_GameData.NetWork.Client
  311.                     _Font m_arrFFX(2), m_arrLayer(c_MIX)
  312.                 Case 4 ' instructions! heck its point and click ppl!
  313.                     Instruction
  314.                 Case 5 ' quit game
  315.                     ExitFlag%% = TRUE
  316.             End Select
  317.             ' trap mouse button down
  318.             Do: null = _MouseInput: _Delay .025: Loop While _MouseButton(1)
  319.         End If
  320.  
  321.         _PutImage , m_arrLayer(c_MIX), m_arrLayer(0)
  322.  
  323.         Do
  324.             _Delay .025
  325.             If InKey$ = Chr$(27) Then ExitFlag%% = TRUE
  326.         Loop Until _MouseInput Or ExitFlag%% Or UpDate%%
  327.  
  328.         UpDate%% = FALSE
  329.         x% = _MouseX: y% = _MouseY
  330.         If x% > 280 And x% < 630 Then ' if mouse is in correct X region
  331.             If y% > 150 And y% < 300 Then ' if mouse is in correct Y region
  332.                 over%% = (y% - 150) \ 30 + 1
  333.             End If
  334.         Else ' off menu region
  335.             over%% = 0
  336.         End If
  337.         Do: Loop While _MouseInput
  338.     Loop Until ExitFlag%%
  339.  
  340.     ExitFlag%% = FALSE ' reset flag
  341.     ChangeColor &HFFFFFFFF, m_arrLayer(c_MIX)
  342.     _Font 16
  343.     ' ----------------------------------
  344. End Sub ' MainMenu
  345.  
  346. ' /////////////////////////////////////////////////////////////////////////////
  347.  
  348. Function StartHost (port%)
  349.     If port% = 0 Then default% = 1979 Else default% = port%
  350.     ID$ = "TCP/IP:" + LTrim$(Str$(default%))
  351.     HostID& = _OpenHost(ID$) ' begin new host
  352.     Result = HostID&
  353.     StartHost = Result
  354. End Function ' StartHost
  355.  
  356. ' /////////////////////////////////////////////////////////////////////////////
  357. ' catch user connection
  358.  
  359. Sub MessageCheck
  360.     ' -----------------------------------------------------------------------------
  361.     ' only if HOST
  362.     If m_GameData.Mode = c_LAN Then
  363.         newclient = _OpenConnection(m_GameData.NetWork.Host) ' receive any new connection
  364.         If newclient Then
  365.             m_GameData.NetWork.Users = m_GameData.NetWork.Users + 1
  366.             m_arrUser(m_GameData.NetWork.Users).Id = newclient
  367.             If m_GameData.Debug Then Print #6, "add:" + Str$(newclient)
  368.         End If
  369.     End If
  370.  
  371.     ' -----------------------------------------------------------------------------
  372.     ' Listen for communication from Players-
  373.     If m_GameData.Mode = c_LAN Then ' host game only listens for player 2
  374.         If m_GameData.NetWork.Users = 2 Then ' only listen once hosts has both users
  375.             Get #m_arrUser(2).Id, , m_Message$
  376.             If m_GameData.Debug And m_Message$ <> "" Then Print #6, "REC:" + Str$(m_arrUser(I%%).Id) + ":" + m_Message$
  377.         End If
  378.     Else ' while player two just listens
  379.         Get #m_GameData.NetWork.Client, , m_Message$
  380.         If m_GameData.Debug And m_Message$ <> "" Then Print #6, "REC:" + Str$(m_arrUser(I%%).Id) + ":" + m_Message$
  381.     End If
  382.  
  383.     ' -----------------------------------------------------------------------------
  384.     If m_Message$ <> "" Then ProcessMessage
  385. End Sub ' MessageCheck
  386.  
  387. ' /////////////////////////////////////////////////////////////////////////////
  388.  
  389. Sub ProcessMessage
  390.     Select Case Left$(m_Message$, 5)
  391.         Case "[SHP]" ' ship xy and orentation data
  392.             txt$ = Mid$(m_Message$, 6, 30)
  393.             For i%% = 6 To 10
  394.                 x%% = Val(Mid$(txt$, 1, 2))
  395.                 y%% = Val(Mid$(txt$, 3, 2))
  396.                 o%% = Val(Mid$(txt$, 5, 2))
  397.                 txt$ = Mid$(txt$, 7)
  398.                 m_arrShip(i%%).Xpos = x%%
  399.                 m_arrShip(i%%).Ypos = y%%
  400.                 m_arrShip(i%%).Orent = o%%
  401.                 PlaceShipOnBoard i%%
  402.             Next i%%
  403.             m_GameData.NetWork.Ready = TRUE
  404.         Case "[SHT]" ' players Shot xy data
  405.             txt$ = Mid$(m_Message$, 6, 4)
  406.             x%% = Val(Mid$(txt$, 1, 2))
  407.             y%% = Val(Mid$(txt$, 3, 2))
  408.             m_GameData.NetWork.X = x%%
  409.             m_GameData.NetWork.Y = y%%
  410.         Case "[FST]" ' who goes first number chance
  411.             ' go ahead and use x value for this.
  412.             m_GameData.NetWork.X = Val(Mid$(m_Message$, 6, 2))
  413.         Case "[PKN]" ' who goes first number
  414.             m_GameData.NetWork.Y = Val(Mid$(m_Message$, 6, 2))
  415.     End Select
  416. End Sub ' ProcessMessage
  417.  
  418. ' /////////////////////////////////////////////////////////////////////////////
  419.  
  420. Function ConnectClient (port%, IPA$)
  421.     If port% = 0 Then default% = 1979 Else default% = port%
  422.     If IPA$ = "0" Then IP$ = ":localhost" Else IP$ = ":" + IPA$
  423.     ID$ = "TCP/IP:" + LTrim$(Str$(default%)) + IP$
  424.     connection& = _OpenClient(ID$) ' Attempt to connect to local host as a client
  425.     Result = connection&
  426.     If m_GameData.Debug Then Print #6, ID$ + " " + Str$(Result)
  427.     ConnectClient = Result
  428. End Function ' ConnectClient
  429.  
  430. ' /////////////////////////////////////////////////////////////////////////////
  431.  
  432. Sub SendMessage
  433.     If m_GameData.Debug Then Print #6, "SND:" + Str$(m_arrUser(2).Id) + ":" + Str$(m_GameData.Mode)
  434.     If m_GameData.Mode = c_LAN Then
  435.         If m_GameData.Debug Then Print #6, "SND:" + Str$(m_arrUser(2).Id) + ":" + m_Message$
  436.         Put #m_arrUser(2).Id, , m_Message$
  437.     Else
  438.         If m_GameData.Debug Then Print #6, "SND:" + Str$(m_GameData.NetWork.Client) + ":" + m_Message$
  439.         Put #m_GameData.NetWork.Client, , m_Message$
  440.     End If
  441.     m_Message$ = ""
  442. End Sub ' SendMessage
  443.  
  444. ' /////////////////////////////////////////////////////////////////////////////
  445.  
  446. Sub AutoPlaceShips (Who%%)
  447.     If Who%% = c_PLAYER Then A%% = 0 Else A%% = 5
  448.     For i%% = 1 + A%% To 5 + A%% ' take each ship starting with Carrier
  449.         limit! = Timer
  450.         Do: Good%% = FALSE
  451.             x%% = Int(Rnd * 10) + 1 ' pick a spot and orentation
  452.             y%% = Int(Rnd * 10) + 1
  453.             If Int(Rnd * 100) + 1 > 50 Then o%% = c_HORZ Else o%% = c_VERT
  454.             If CheckShipPos(x%%, y%%, o%%, i%%) Then Good%% = TRUE ' check that it fits and doesn't overlap
  455.             If Timer > limit! + .5 Then Print "AUTO PLACE ERROR, TIME EXCEEDED!": End
  456.         Loop Until Good%%
  457.         m_arrShip(i%%).Xpos = x%%
  458.         m_arrShip(i%%).Ypos = y%%
  459.         m_arrShip(i%%).Orent = o%%
  460.         PlaceShipOnBoard (i%%)
  461.     Next i%%
  462. End Sub ' AutoPlaceShips
  463.  
  464. ' /////////////////////////////////////////////////////////////////////////////
  465. ' change text color(value~&) on specified m_arrLayer(id~&)
  466.  
  467. Sub ChangeColor (value~&, id~&)
  468.     old~& = _Dest
  469.     _Dest id~&
  470.     Color value~&
  471.     _Dest old~&
  472. End Sub ' ChangeColor
  473.  
  474. ' /////////////////////////////////////////////////////////////////////////////
  475.  
  476. Function CheckShipPos (xt%%, yt%%, ot%%, tt%%)
  477.     ' copy values to local variables
  478.     ' lets not change a variable by accident
  479.     x%% = xt%%
  480.     y%% = yt%%
  481.     o%% = ot%%
  482.     t%% = tt%%
  483.  
  484.     If t%% > 5 Then w%% = 2: t%% = t%% - 5 Else w%% = 1 ' >5 OPPONENT ships
  485.     result%% = TRUE
  486.  
  487.     Select Case t%% ' first check to see if ship will fit on board
  488.         Case c_CARRIER
  489.             If o%% = c_HORZ And x%% > 6 Then result%% = FALSE
  490.             If o%% = c_VERT And y%% > 6 Then result%% = FALSE
  491.         Case c_BATTLESHIP
  492.             If o%% = c_HORZ And x%% > 7 Then result%% = FALSE
  493.             If o%% = c_VERT And y%% > 7 Then result%% = FALSE
  494.         Case c_DESTROYER, c_SUBMARINE
  495.             If o%% = c_HORZ And x%% > 8 Then result%% = FALSE
  496.             If o%% = c_VERT And y%% > 8 Then result%% = FALSE
  497.         Case c_PTBOAT
  498.             If o%% = c_HORZ And x%% > 9 Then result%% = FALSE
  499.             If o%% = c_VERT And y%% > 9 Then result%% = FALSE
  500.     End Select
  501.  
  502.     If result%% Then ' if fit test passed make sure no ships in way
  503.         Select Case t%%
  504.             Case c_CARRIER
  505.                 If o%% = c_HORZ Then
  506.                     For i%% = 0 To 4
  507.                         If m_arrBoard(x%% + i%%, y%%, w%%) Then result%% = FALSE: i%% = 5
  508.                     Next i%%
  509.                 End If
  510.                 If o%% = c_VERT Then
  511.                     For i%% = 0 To 4
  512.                         If m_arrBoard(x%%, y%% + i%%, w%%) Then result%% = FALSE: i%% = 5
  513.                     Next i%%
  514.                 End If
  515.             Case c_BATTLESHIP
  516.                 If o%% = c_HORZ Then
  517.                     For i%% = 0 To 3
  518.                         If m_arrBoard(x%% + i%%, y%%, w%%) Then result%% = FALSE: i%% = 5
  519.                     Next i%%
  520.                 End If
  521.                 If o%% = c_VERT Then
  522.                     For i%% = 0 To 3
  523.                         If m_arrBoard(x%%, y%% + i%%, w%%) Then result%% = FALSE: i%% = 5
  524.                     Next i%%
  525.                 End If
  526.             Case c_DESTROYER, c_SUBMARINE
  527.                 If o%% = c_HORZ Then
  528.                     For i%% = 0 To 2
  529.                         If m_arrBoard(x%% + i%%, y%%, w%%) Then result%% = FALSE: i%% = 5
  530.                     Next i%%
  531.                 End If
  532.                 If o%% = c_VERT Then
  533.                     For i%% = 0 To 2
  534.                         If m_arrBoard(x%%, y%% + i%%, w%%) Then result%% = FALSE: i%% = 5
  535.                     Next i%%
  536.                 End If
  537.             Case c_PTBOAT
  538.                 If o%% = c_HORZ Then
  539.                     For i%% = 0 To 1
  540.                         If m_arrBoard(x%% + i%%, y%%, w%%) Then result%% = FALSE: i%% = 5
  541.                     Next i%%
  542.                 End If
  543.                 If o%% = c_VERT Then
  544.                     For i%% = 0 To 1
  545.                         If m_arrBoard(x%%, y%% + i%%, w%%) Then result%% = FALSE: i%% = 5
  546.                     Next i%%
  547.                 End If
  548.         End Select
  549.     End If
  550.     CheckShipPos = result%%
  551. End Function ' CheckShipPos
  552.  
  553. ' /////////////////////////////////////////////////////////////////////////////
  554.  
  555. Sub CheckShips
  556.     Static st_arrKnown(10) As _Byte
  557.  
  558.     ' check for sunk ship on player
  559.     m_GameData.PlayerDead = TRUE
  560.     For i%% = 1 To 5
  561.         If m_arrShip(i%%).sunk And (Not st_arrKnown(i%%)) Then
  562.             MessageHandler "Opponent Sunk players " + m_arrShipName$(i%%) + " !"
  563.             _Delay .75
  564.             st_arrKnown(i%%) = TRUE
  565.         End If
  566.         If m_arrShip(i%%).sunk = FALSE Then m_GameData.PlayerDead = FALSE
  567.     Next i%%
  568.  
  569.     ' check for sunk ship on opponent
  570.     m_GameData.OpponentDead = TRUE
  571.     For i%% = 6 To 10
  572.         If m_arrShip(i%%).sunk And (Not st_arrKnown(i%%)) Then
  573.             MessageHandler "Player Sunk Opponents " + m_arrShipName$(i%% - 5) + " !"
  574.             _Delay .75
  575.             st_arrKnown(i%%) = TRUE
  576.         End If
  577.         If m_arrShip(i%%).sunk = FALSE Then m_GameData.OpponentDead = FALSE
  578.     Next i%%
  579.  
  580.     If m_GameData.PlayerDead Or m_GameData.OpponentDead Then m_GameData.GameOver = TRUE
  581. End Sub ' CheckShips
  582.  
  583. ' /////////////////////////////////////////////////////////////////////////////
  584. ' Clear deploy information area
  585.  
  586. Sub ClearArea
  587.     _Dest m_arrLayer(c_BOARD)
  588.     Line (0, 300)-(639, 479), _RGB32(0, 0, 0), BF
  589.     _Dest m_arrLayer(0)
  590.     _Dest m_arrLayer(c_SHIPS)
  591.     Line (0, 300)-(639, 479), _RGB32(0, 0, 0), BF
  592.     _Dest m_arrLayer(0)
  593.     _PutImage , m_arrLayer(c_BOARD), m_arrLayer(c_MIX)
  594.     _PutImage , m_arrLayer(c_SHIPS), m_arrLayer(c_MIX)
  595.     _PutImage , m_arrLayer(c_MIX), m_arrLayer(0)
  596. End Sub ' ClearArea
  597.  
  598. ' /////////////////////////////////////////////////////////////////////////////
  599.  
  600. Sub ClearLayer (id%%)
  601.     old& = _Dest
  602.     _Dest m_arrLayer(id%%)
  603.     Cls
  604.     _Dest old&
  605. End Sub ' ClearLayer
  606.  
  607. ' /////////////////////////////////////////////////////////////////////////////
  608.  
  609. Sub ComputerShot
  610.     Do: Good%% = FALSE ' run until an unfired upon area is found
  611.         x%% = Int(Rnd * 10) + 1
  612.         y%% = Int(Rnd * 10) + 1
  613.         If m_arrBoard(x%%, y%%, 1) >= 0 Then Good%% = TRUE
  614.     Loop Until Good%%
  615.  
  616.     MessageHandler "Computer fires at " + Chr$(64 + y%%) + Str$(x%%)
  617.     _Delay .5
  618.  
  619.     Select Case SendShot(x%%, y%%, c_OPPONENT)
  620.         Case c_HIT ' Computer hits players ship
  621.             MessageHandler "Computer Hits!"
  622.             CheckShips
  623.         Case c_MISS ' Computer missed players ship
  624.             MessageHandler "Computer Misses"
  625.         Case c_BAD ' Computer already fired upon this space ERROR
  626.             MessageHandler "Computer has been Hitting the juice again, fired an error"
  627.     End Select
  628.  
  629.     _Delay .5
  630. End Sub ' ComputerShot
  631.  
  632. ' /////////////////////////////////////////////////////////////////////////////
  633.  
  634. Sub DisplayShip (X%, Y%, ID%%, Orentation%%, LayerD&)
  635.     Select Case ID%%
  636.         Case c_CARRIER
  637.             If Orentation%% = c_HORZ Then _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (500, 277)-(611, 299) Else _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (592, 165)-(614, 276)
  638.         Case c_BATTLESHIP
  639.             If Orentation%% = c_HORZ Then _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (500, 303)-(588, 321) Else _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (570, 165)-(589, 253)
  640.         Case c_DESTROYER
  641.             If Orentation%% = c_HORZ Then _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (500, 324)-(570, 341) Else _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (551, 165)-(568, 235)
  642.         Case c_SUBMARINE
  643.             If Orentation%% = c_HORZ Then _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (500, 344)-(568, 357) Else _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (534, 165)-(548, 233)
  644.         Case c_PTBOAT
  645.             If Orentation%% = c_HORZ Then _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (500, 360)-(546, 375) Else _PutImage (X%, Y%), m_arrLayer(c_SHEET), LayerD&, (516, 165)-(531, 211)
  646.     End Select
  647. End Sub ' DisplayShip
  648.  
  649. ' /////////////////////////////////////////////////////////////////////////////
  650. ' start game
  651.  
  652. Sub GamePlay
  653.     WhoIsFirst ' find who gets to shoot first!
  654.  
  655.     Do
  656.         If m_GameData.WhoIsUp = c_PLAYER Then
  657.  
  658.             ' shooting routine PLAYER
  659.             Do: ShotFired%% = FALSE
  660.                 ' mix layers and display
  661.                 _PutImage , m_arrLayer(c_BOARD), m_arrLayer(c_MIX)
  662.                 _PutImage , m_arrLayer(c_SHIPS), m_arrLayer(c_MIX)
  663.                 _PutImage , m_arrLayer(c_PEGS), m_arrLayer(c_MIX)
  664.                 _PutImage (0, 0), m_arrLayer(c_MIX), m_arrLayer(0), (0, 0)-(639, 300)
  665.  
  666.                 x% = _MouseX: y% = _MouseY ' get mouse location
  667.  
  668.                 If x% > 344 And y% > 54 And x% < 582 And y% < 294 Then ' mouse over enemy board
  669.                     ' highlite grid block that mouse is over(grid blocks are 22x22[24x24WL])
  670.                     hx%% = ((x% - 344) \ 24) + 1: hy%% = ((y% - 54) \ 24) + 1
  671.                     Line (344 + ((hx%% - 1) * 24), 54 + ((hy%% - 1) * 24))-(367 + ((hx%% - 1) * 24), 77 + ((hy%% - 1) * 24)), c_YellowSelect~&, BF
  672.                 End If
  673.  
  674.                 ' *****************************************************************************
  675.                 ' debug information
  676.                 Locate 1, 1: Print Chr$(64 + hy%%); hx%%
  677.                 ' *****************************************************************************
  678.  
  679.                 If m_GameData.GameOver = FALSE Then
  680.                     ' Main input loop
  681.                     Do: _Delay .025
  682.                         KBD$ = InKey$
  683.                         Select Case KBD$
  684.                             Case Chr$(27)
  685.                                 ExitFlag%% = TRUE
  686.                                 m_GameData.GameOver = TRUE
  687.                         End Select
  688.                     Loop Until _MouseInput Or ExitFlag%%
  689.  
  690.                     ' Player shoots
  691.                     If _MouseButton(1) Then
  692.                         If x% > 344 And y% > 54 And x% < 582 And y% < 294 Then ' only shoot if player is over shot board.
  693.                             MessageHandler "Player Fires at: " + Chr$(64 + hy%%) + Str$(hx%%)
  694.                             _Delay .5
  695.                             If m_GameData.Mode Then
  696.                                 If hx%% < 10 Then m$ = "0" + LTrim$(Str$(hx%%)) Else m$ = LTrim$(Str$(hx%%))
  697.                                 m_Message$ = "[SHT]" + m$
  698.                                 If hy%% < 10 Then m$ = "0" + LTrim$(Str$(hy%%)) Else m$ = LTrim$(Str$(hy%%))
  699.                                 m_Message$ = m_Message$ + m$
  700.                                 SendMessage
  701.                             End If
  702.                             Select Case SendShot(hx%%, hy%%, c_PLAYER)
  703.                                 'Case HIT%% ' player hit enemy  ship
  704.                                 Case c_HIT%% ' player hit enemy  ship
  705.                                     MessageHandler "Player Hits!"
  706.                                     ShotFired%% = TRUE
  707.                                     CheckShips
  708.                                     'Case MISS%% ' player missed enemy ship
  709.                                 Case c_MISS%% ' player missed enemy ship
  710.                                     MessageHandler "Player Misses"
  711.                                     ShotFired%% = TRUE
  712.                                     'Case BAD%% ' player already fired upon this space
  713.                                 Case c_BAD%% ' player already fired upon this space
  714.                                     MessageHandler "Space Already Fired at, pick again"
  715.                             End Select
  716.                         End If
  717.                         _Delay 1.5
  718.                     End If
  719.  
  720.                 Else
  721.                     ExitFlag%% = TRUE
  722.                     m_GameData.GameOver = TRUE
  723.                 End If
  724.                 Do: Loop While _MouseInput
  725.             Loop Until ShotFired%% Or m_GameData.GameOver
  726.  
  727.         ElseIf m_GameData.WhoIsUp = c_OPPONENT Then ' opponents turn to shoot!
  728.             ' mix layers and display
  729.             _PutImage , m_arrLayer(c_BOARD), m_arrLayer(c_MIX)
  730.             _PutImage , m_arrLayer(c_SHIPS), m_arrLayer(c_MIX)
  731.             _PutImage , m_arrLayer(c_PEGS), m_arrLayer(c_MIX)
  732.             _PutImage (0, 0), m_arrLayer(c_MIX), m_arrLayer(0), (0, 0)-(639, 300)
  733.  
  734.             If m_GameData.Mode Then OpponentShot Else ComputerShot
  735.             If m_GameData.GameOver Then ExitFlag%% = TRUE
  736.         End If
  737.  
  738.         ' whos turn is it now?
  739.         If m_GameData.WhoIsUp = c_PLAYER Then m_GameData.WhoIsUp = c_OPPONENT Else m_GameData.WhoIsUp = c_PLAYER
  740.     Loop Until ExitFlag%%
  741.  
  742.     ' dumpboard
  743.     If m_GameData.PlayerDead Then MessageHandler "You have lost this round."
  744.     If m_GameData.OpponentDead Then MessageHandler "Congratulations You are Victorious!"
  745.     If Not m_GameData.PlayerDead And Not m_GameData.OpponentDead Then MessageHandler "Game quit..."
  746.  
  747.     MessageHandler "Press any key to return to menu"
  748.     Do: Loop While InKey$ = ""
  749. End Sub ' GamePlay
  750.  
  751. ' /////////////////////////////////////////////////////////////////////////////
  752.  
  753. Sub HitShip (id%%)
  754.     ' ID%%-number of the ship, 1-5 player 6-10 opponent
  755.     m_arrShip(id%%).Hits = m_arrShip(id%%).Hits + 1
  756.     Select Case id%%
  757.         Case c_CARRIER, c_CARRIER + 5
  758.             If m_arrShip(id%%).Hits = 5 Then m_arrShip(id%%).sunk = TRUE
  759.         Case c_BATTLESHIP, c_BATTLESHIP + 5
  760.             If m_arrShip(id%%).Hits = 4 Then m_arrShip(id%%).sunk = TRUE
  761.         Case c_DESTROYER, c_DESTROYER + 5
  762.             If m_arrShip(id%%).Hits = 3 Then m_arrShip(id%%).sunk = TRUE
  763.         Case c_SUBMARINE, c_SUBMARINE + 5
  764.             If m_arrShip(id%%).Hits = 3 Then m_arrShip(id%%).sunk = TRUE
  765.         Case c_PTBOAT, c_PTBOAT + 5
  766.             If m_arrShip(id%%).Hits = 2 Then m_arrShip(id%%).sunk = TRUE
  767.     End Select
  768. End Sub ' HitShip
  769.  
  770. ' /////////////////////////////////////////////////////////////////////////////
  771.  
  772. Sub INIT
  773.     Dim arrSize(64) As Long
  774.     Dim arrFOffset&(64)
  775.  
  776.     Open "battleship.gfx" For Binary As #1
  777.     Get #1, , c~%% ' number of records
  778.     For w% = 1 To c~%%
  779.         Get #1, , arrFOffset&(w%)
  780.         Get #1, , arrSize(w%)
  781.         arrFOffset&(w%) = arrFOffset&(w%) + 1
  782.     Next w%
  783.  
  784.     m_arrLayer(0) = _Display
  785.     m_arrLayer(c_MIX) = _NewImage(640, 480, 32) ' composite layer
  786.     m_arrLayer(c_TITLE) = LoadGFX&(arrFOffset&(1), arrSize(1))
  787.     m_arrLayer(c_SHEET) = LoadGFX&(arrFOffset&(2), arrSize(2))
  788.     m_arrLayer(c_SHIPS) = _NewImage(640, 480, 32)
  789.     m_arrLayer(c_SHOTS) = _NewImage(640, 480, 32)
  790.     m_arrLayer(c_BOARD) = _NewImage(640, 480, 32)
  791.     m_arrLayer(c_PEGS) = _NewImage(640, 480, 32)
  792.     m_arrLayer(c_MENU) = LoadGFX&(arrFOffset&(3), arrSize(3))
  793.     m_arrLayer(c_LAN) = LoadGFX&(arrFOffset&(4), arrSize(4)) ' _LOADIMAGE("Networking.bmp", 32)
  794.  
  795.     m_arrFFX(1) = LoadFFX&(arrFOffset&(5), arrSize(5), 30) ' _LOADFONT("gunmetl.ttf", 30, "monospace")
  796.     m_arrFFX(2) = LoadFFX&(arrFOffset&(6), arrSize(6), 18) ' _LOADFONT("ARGEBL.ttf", 18, "monospace")
  797.     m_arrFFX(3) = LoadFFX&(arrFOffset&(7), arrSize(7), 18) ' _LOADFONT("TechnoLCD.ttf", 18, "monospace")
  798.     m_arrFFX(4) = LoadFFX&(arrFOffset&(8), arrSize(8), 24) ' _LOADFONT("TechnicznaPomocR.ttf", 24, "monospace")
  799.     m_arrFFX(5) = LoadFFX&(arrFOffset&(5), arrSize(5), 48) ' _LOADFONT("gunmetl.ttf", 30, "monospace")
  800.     m_arrFFX(6) = LoadFFX&(arrFOffset&(5), arrSize(5), 24) ' _LOADFONT("gunmetl.ttf", 30, "monospace")
  801.  
  802.     _PrintMode _KeepBackground , m_arrLayer(c_MIX)
  803.     _PrintMode _KeepBackground , m_arrLayer(c_LAN)
  804.  
  805.     ClearLayer c_BOARD
  806.     _ClearColor _RGB32(0, 0, 0), m_arrLayer(c_SHEET)
  807.     _ClearColor _RGB32(0, 0, 0), m_arrLayer(c_SHIPS)
  808.     _ClearColor _RGB32(0, 0, 0), m_arrLayer(c_SHOTS)
  809.     _ClearColor _RGB32(0, 0, 0), m_arrLayer(c_PEGS)
  810.  
  811.     LoadData
  812.  
  813.     Close #1
  814.  
  815.     If _FileExists("temp.dat") Then Kill "temp.dat" ' make sure we clean up temp files.
  816.  
  817.     _ScreenMove 25, 25
  818.     _Title "BattleShip 64 V0.7A"
  819. End Sub ' INIT
  820.  
  821. ' /////////////////////////////////////////////////////////////////////////////
  822. ' who%%- which player board to add hit 1-PLAYER, 2-OPPONENT
  823. ' put red peg in board and tally hits to ships
  824.  
  825. Sub ItsAHit (x%%, y%%, Who%%)
  826.     HitShip m_arrBoard(x%%, y%%, Who%%) + ((Who%% - 1) * 5)
  827.     m_arrBoard(x%%, y%%, Who%%) = c_HIT
  828. End Sub ' ItsAHit
  829.  
  830. ' /////////////////////////////////////////////////////////////////////////////
  831. ' who%%- which player board to add hit 1-PLAYER, 2-OPPONENT
  832. ' put white peg in board
  833.  
  834. Sub ItsAMiss (x%%, y%%, Who%%)
  835.     m_arrBoard(x%%, y%%, Who%%) = c_MISS
  836. End Sub ' ItsAMiss
  837.  
  838. ' /////////////////////////////////////////////////////////////////////////////
  839.  
  840. Sub LoadData
  841.     Restore ShipYardOffsetsData
  842.     For i%% = 1 To 5
  843.         Read m_arrOffs(i%%).ShipYard_X
  844.         Read m_arrOffs(i%%).ShipYard_Y
  845.     Next i%%
  846.  
  847.     Restore ShipBoardOffsetsData
  848.     For i%% = 1 To 5
  849.         Read m_arrOffs(i%%).Board_HX
  850.         Read m_arrOffs(i%%).Board_HY
  851.     Next i%%
  852.     For i%% = 1 To 5
  853.         Read m_arrOffs(i%%).Board_VX
  854.         Read m_arrOffs(i%%).Board_VY
  855.     Next i%%
  856.  
  857.     Restore ShipBoardOffsetsRedData
  858.     For i%% = 1 To 5
  859.         Read m_arrOffs(i%%).RedBoard_HX
  860.         Read m_arrOffs(i%%).RedBoard_HY
  861.     Next i%%
  862.     For i%% = 1 To 5
  863.         Read m_arrOffs(i%%).RedBoard_VX
  864.         Read m_arrOffs(i%%).RedBoard_VY
  865.     Next i%%
  866.  
  867.     Restore ShipNamesData
  868.     For i%% = 1 To 5
  869.         Read m_arrShipName$(i%%)
  870.     Next i%%
  871. End Sub ' LoadData
  872.  
  873. ' /////////////////////////////////////////////////////////////////////////////
  874.  
  875. Function LoadGFX& (Foff&, Size&)
  876.     If _FileExists("temp.dat") Then Kill "temp.dat"
  877.     Open "temp.dat" For Binary As #3
  878.     dat$ = Space$(Size&)
  879.     Get #1, Foff&, dat$
  880.     Put #3, , dat$
  881.     Close #3
  882.     LoadGFX& = _LoadImage("temp.dat", 32)
  883. End Function ' LoadGFX&
  884.  
  885. ' /////////////////////////////////////////////////////////////////////////////
  886.  
  887. Function LoadFFX& (Foff&, Size&, Fize%%)
  888.     If _FileExists("temp.dat") Then Kill "temp.dat"
  889.     Open "temp.dat" For Binary As #3
  890.     dat$ = Space$(Size&)
  891.     Get #1, Foff&, dat$
  892.     Put #3, , dat$
  893.     Close #3
  894.     LoadFFX& = _LoadFont("temp.dat", Fize%%, "monospace")
  895. End Function ' LoadFFX&
  896.  
  897. ' /////////////////////////////////////////////////////////////////////////////
  898.  
  899. Sub MessageHandler (txt$)
  900.     ' define message area
  901.     View Print 20 To 25
  902.  
  903.     ' display message
  904.     Locate 25, 1: Print txt$
  905.  
  906.     ' restore screen area
  907.     View Print
  908. End Sub ' MessageHandler
  909.  
  910. ' /////////////////////////////////////////////////////////////////////////////
  911. ' w%%- Which board to place ship 1-player 2-Opponent
  912. ' o%%= ships Orentation c_VERT or c_HORZ
  913. ' idx%%- Ident of ship to place c_CARRIER to c_PTBOAT
  914.  
  915. Sub PlaceShipOnBoard (id%%)
  916.     If id%% <= 5 Then ' players ships
  917.         w%% = 1: idx%% = id%%
  918.     Else ' OPPONENT ships
  919.         w%% = 2: idx%% = id%% - 5 ' correction for Enemy ships 6-10
  920.     End If
  921.     o%% = m_arrShip(id%%).Orent
  922.  
  923.     Select Case idx%%
  924.         Case c_CARRIER
  925.             If o%% = c_HORZ Then For i%% = 0 To 4: m_arrBoard(m_arrShip(id%%).Xpos + i%%, m_arrShip(id%%).Ypos, w%%) = c_CARRIER: Next i%%
  926.             If o%% = c_VERT Then For i%% = 0 To 4: m_arrBoard(m_arrShip(id%%).Xpos, m_arrShip(id%%).Ypos + i%%, w%%) = c_CARRIER: Next i%%
  927.         Case c_BATTLESHIP
  928.             If o%% = c_HORZ Then For i%% = 0 To 3: m_arrBoard(m_arrShip(id%%).Xpos + i%%, m_arrShip(id%%).Ypos, w%%) = c_BATTLESHIP: Next i%%
  929.             If o%% = c_VERT Then For i%% = 0 To 3: m_arrBoard(m_arrShip(id%%).Xpos, m_arrShip(id%%).Ypos + i%%, w%%) = c_BATTLESHIP: Next i%%
  930.         Case c_DESTROYER
  931.             If o%% = c_HORZ Then For i%% = 0 To 2: m_arrBoard(m_arrShip(id%%).Xpos + i%%, m_arrShip(id%%).Ypos, w%%) = c_DESTROYER: Next i%%
  932.             If o%% = c_VERT Then For i%% = 0 To 2: m_arrBoard(m_arrShip(id%%).Xpos, m_arrShip(id%%).Ypos + i%%, w%%) = c_DESTROYER: Next i%%
  933.         Case c_SUBMARINE
  934.             If o%% = c_HORZ Then For i%% = 0 To 2: m_arrBoard(m_arrShip(id%%).Xpos + i%%, m_arrShip(id%%).Ypos, w%%) = c_SUBMARINE: Next i%%
  935.             If o%% = c_VERT Then For i%% = 0 To 2: m_arrBoard(m_arrShip(id%%).Xpos, m_arrShip(id%%).Ypos + i%%, w%%) = c_SUBMARINE: Next i%%
  936.         Case c_PTBOAT
  937.             If o%% = c_HORZ Then For i%% = 0 To 1: m_arrBoard(m_arrShip(id%%).Xpos + i%%, m_arrShip(id%%).Ypos, w%%) = c_PTBOAT: Next i%%
  938.             If o%% = c_VERT Then For i%% = 0 To 1: m_arrBoard(m_arrShip(id%%).Xpos, m_arrShip(id%%).Ypos + i%%, w%%) = c_PTBOAT: Next i%%
  939.     End Select
  940. End Sub ' PlaceShipOnBoard
  941.  
  942. ' /////////////////////////////////////////////////////////////////////////////
  943.  
  944. Sub ResetBoard
  945.     For iz%% = 0 To 2
  946.         For ix%% = 0 To 10
  947.             For iy%% = 0 To 10
  948.                 m_arrBoard(ix%%, iy%%, iz%%) = FALSE
  949.             Next iy%%
  950.         Next ix%%
  951.     Next iz%%
  952. End Sub ' ResetBoard
  953.  
  954. ' /////////////////////////////////////////////////////////////////////////////
  955.  
  956. Function SendShot (x%%, y%%, Who%%)
  957.     If Who%% = c_PLAYER Then
  958.         ' Player shooting, check enemy board
  959.         If m_arrBoard(x%%, y%%, c_OPPONENT) > 0 Then
  960.             ItsAHit x%%, y%%, c_OPPONENT
  961.             Result%% = c_HIT
  962.         ElseIf m_arrBoard(x%%, y%%, c_OPPONENT) < 0 Then ' already hit or miss
  963.             Result%% = c_BAD
  964.         Else ' space is empty so its a miss
  965.             ItsAMiss x%%, y%%, c_OPPONENT
  966.             Result%% = c_MISS
  967.         End If
  968.     Else
  969.         ' Opponent shooting, check player board
  970.         If m_arrBoard(x%%, y%%, c_PLAYER) > 0 Then
  971.             ItsAHit x%%, y%%, c_PLAYER
  972.             Result%% = c_HIT
  973.         ElseIf m_arrBoard(x%%, y%%, c_PLAYER) < 0 Then ' already hit or miss
  974.             Result%% = c_BAD
  975.         Else ' space is empty so its a miss
  976.             ItsAMiss x%%, y%%, c_PLAYER
  977.             Result%% = c_MISS
  978.         End If
  979.     End If
  980.  
  981.     UpdatePegLayer
  982.     SendShot = Result%%
  983. End Function ' SendShot
  984.  
  985. ' /////////////////////////////////////////////////////////////////////////////
  986.  
  987. Sub SetUpGameBoard
  988.     _Dest m_arrLayer(c_BOARD)
  989.     _PutImage (32, 32), m_arrLayer(c_SHEET), m_arrLayer(c_BOARD), (0, 0)-(262, 262)
  990.     _PutImage (320, 32), m_arrLayer(c_SHEET), m_arrLayer(c_BOARD), (0, 0)-(262, 262)
  991.     Line (32, 32)-(294, 294), c_BlueBoard~&, BF
  992.     Line (320, 32)-(582, 294), c_RedBoard~&, BF
  993.     _PutImage , m_arrLayer(c_BOARD), _Display
  994.  
  995.     _PrintString (64, 16), "Your fleet"
  996.     _PrintString (352, 16), "Enemy fleet"
  997.     _Dest m_arrLayer(0)
  998. End Sub ' SetUpGameBoard
  999.  
  1000. ' /////////////////////////////////////////////////////////////////////////////
  1001.  
  1002. Sub ShowShips (Who%%)
  1003.     If Who%% = c_PLAYER Then
  1004.         For i%% = 1 To 5
  1005.             If m_arrShip(i%%).Orent = c_HORZ Then
  1006.                 DisplayShip m_arrOffs(i%%).Board_HX + (m_arrShip(i%%).Xpos - 1) * 24, m_arrOffs(i%%).Board_HY + (m_arrShip(i%%).Ypos - 1) * 24, i%%, m_arrShip(i%%).Orent, m_arrLayer(c_SHIPS) ' display ships in Board area
  1007.             Else
  1008.                 DisplayShip m_arrOffs(i%%).Board_VX + (m_arrShip(i%%).Xpos - 1) * 24, m_arrOffs(i%%).Board_VY + (m_arrShip(i%%).Ypos - 1) * 24, i%%, m_arrShip(i%%).Orent, m_arrLayer(c_SHIPS) ' display ships in Board area
  1009.             End If
  1010.         Next i%%
  1011.     Else
  1012.         For i%% = 6 To 10
  1013.             If m_arrShip(i%%).Orent = c_VERT Then
  1014.                 DisplayShip m_arrOffs(i%% - 5).RedBoard_VX + (m_arrShip(i%%).Xpos - 1) * 24, m_arrOffs(i%% - 5).RedBoard_VY + (m_arrShip(i%%).Ypos - 1) * 24, i%% - 5, m_arrShip(i%%).Orent, m_arrLayer(c_SHIPS) ' display ships in Board area
  1015.             Else
  1016.                 DisplayShip m_arrOffs(i%% - 5).RedBoard_HX + (m_arrShip(i%%).Xpos - 1) * 24, m_arrOffs(i%% - 5).RedBoard_HY + (m_arrShip(i%%).Ypos - 1) * 24, i%% - 5, m_arrShip(i%%).Orent, m_arrLayer(c_SHIPS) ' display ships in Board area
  1017.             End If
  1018.         Next i%%
  1019.     End If
  1020. End Sub ' ShowShips
  1021.  
  1022. ' /////////////////////////////////////////////////////////////////////////////
  1023.  
  1024. Sub UpdatePegLayer
  1025.     For z%% = 1 To 2
  1026.         If z%% = 1 Then ofx% = 55: ofy% = 55 Else ofx% = 343: ofy% = 55
  1027.         For y%% = 1 To 10
  1028.             For x%% = 1 To 10
  1029.                 Select Case m_arrBoard(x%%, y%%, z%%)
  1030.                     Case c_HIT
  1031.                         _PutImage (ofx% + (x%% - 1) * 24, ofy% + (y%% - 1) * 24), m_arrLayer(c_SHEET), m_arrLayer(c_PEGS), (305, 144)-(327, 166)
  1032.                     Case c_MISS
  1033.                         _PutImage (ofx% + (x%% - 1) * 24, ofy% + (y%% - 1) * 24), m_arrLayer(c_SHEET), m_arrLayer(c_PEGS), (329, 144)-(350, 166)
  1034.                 End Select
  1035.             Next x%%
  1036.         Next y%%
  1037.     Next z%%
  1038. End Sub ' UpdatePegLayer
  1039.  
  1040. ' /////////////////////////////////////////////////////////////////////////////
  1041. ' Pick Who Goes first
  1042.  
  1043. Sub WhoIsFirst
  1044.     starter%% = Int(Rnd * 100) + 1
  1045.     Locate 20, 1: Input "Pick Number 1-100"; P%%
  1046.  
  1047.     If m_GameData.Mode = FALSE Then ' if not a network game
  1048.         computer%% = Int(Rnd * 100) + 1
  1049.  
  1050.     Else
  1051.         ' if game is network then
  1052.         If m_GameData.Mode = c_LAN Then ' if this program is host game then send pick to player2
  1053.             If starter%% < 10 Then m$ = "0" + LTrim$(Str$(starter%%)) Else m$ = LTrim$(Str$(starter%%))
  1054.             m_Message$ = "[PKN]" + m$
  1055.             SendMessage
  1056.  
  1057.         ElseIf m_GameData.Mode = c_LANCLIENT Then ' if this program is player 2 then wait for number
  1058.             Print "Awaiting Pick Number..."
  1059.             Do
  1060.                 _Delay .005
  1061.             Loop Until m_GameData.NetWork.Y
  1062.             starter%% = m_GameData.NetWork.Y
  1063.             m_GameData.NetWork.Y = 0
  1064.         End If
  1065.  
  1066.         ' client sends number first then waits.
  1067.         ' host waits first then sends number.
  1068.         If m_GameData.Mode = c_LANCLIENT Then
  1069.             If P%% < 10 Then m$ = "0" + LTrim$(Str$(P%%)) Else m$ = LTrim$(Str$(P%%))
  1070.             m_Message$ = "[FST]" + m$
  1071.             SendMessage
  1072.             _Delay .025
  1073.         End If
  1074.  
  1075.         Locate 21, 1: Print "Waiting for Opponents pick..."
  1076.         Do
  1077.             _Delay .005
  1078.         Loop Until m_GameData.NetWork.X
  1079.  
  1080.         computer%% = m_GameData.NetWork.X ' set player 2's number
  1081.         m_GameData.NetWork.X = 0
  1082.  
  1083.         If m_GameData.Mode = c_LAN Then ' send player 1's number to player 2
  1084.             If P%% < 10 Then m$ = "0" + LTrim$(Str$(P%%)) Else m$ = LTrim$(Str$(P%%))
  1085.             m_Message$ = "[FST]" + m$
  1086.             SendMessage
  1087.         End If
  1088.     End If
  1089.  
  1090.     If P%% < 1 Or P%% > 100 Then ' player auto lose
  1091.         Print "Opponent wins because you can not follow instructions."
  1092.         computer%% = starter%%
  1093.     Else ' player entered correct ranged value
  1094.         Print "Opponent picks:"; computer%%
  1095.     End If
  1096.  
  1097.     testp%% = Abs(starter%% - P%%) ' find how far off player is.
  1098.     testc%% = Abs(starter%% - computer%%) ' find how far off computer is.
  1099.     If testp%% = testc%% Then winner%% = c_PLAYER ' in a tie player wins
  1100.     If testp%% < testc%% Then winner%% = c_PLAYER ' player closer wins
  1101.     If testp%% > testc%% Then winner%% = c_OPPONENT ' computer closer wins
  1102.     _Delay 1.25
  1103.  
  1104.     Print "Control number was:";
  1105.     _Delay .75
  1106.  
  1107.     Print starter%%
  1108.     _Delay .75
  1109.  
  1110.     If winner%% = c_PLAYER Then Print "You Win the chance to shoot first" Else Print "Opponent shoots first"
  1111.  
  1112.     m_GameData.WhoIsUp = winner%% ' store who starts for later
  1113.     _Delay 1.5
  1114.     ' ---------------------------------------------
  1115. End Sub ' WhoIsFirst
  1116.  
  1117. ' /////////////////////////////////////////////////////////////////////////////
  1118.  
  1119. Sub DeployFleet
  1120.     Static st_arrPicked(5)
  1121.  
  1122.     _PutImage , m_arrLayer(c_BOARD), m_arrLayer(0)
  1123.     _PutImage (64, 300), m_arrLayer(c_SHEET), m_arrLayer(c_BOARD), (304, 6)-(499, 142)
  1124.  
  1125.     _PrintString (304, 320), "Place Your fleet.", m_arrLayer(c_BOARD)
  1126.     _PrintString (304, 336), "Space to rotate ship.", m_arrLayer(c_BOARD)
  1127.     _PrintString (304, 352), "Left Click to select and place ship.", m_arrLayer(c_BOARD)
  1128.     _PrintString (304, 368), "Right Click to abort Placement.", m_arrLayer(c_BOARD)
  1129.  
  1130.     If m_GameData.Mode = c_LAN Or m_GameData.Mode = c_LANCLIENT Then _PrintString (304, 384), "Game is in Network Mode.", m_arrLayer(c_BOARD)
  1131.  
  1132.     _PutImage (304, 400), m_arrLayer(c_SHEET), m_arrLayer(c_BOARD), (24, 279)-(180, 322) ' accept button
  1133.     _PutImage (480, 400), m_arrLayer(c_SHEET), m_arrLayer(c_BOARD), (182, 279)-(338, 322) ' Reset button
  1134.     _Font 16, m_arrLayer(c_MIX)
  1135.  
  1136.     Do
  1137.         AllPlaced%% = TRUE
  1138.         For i%% = 1 To 5
  1139.             If Not st_arrPicked(i%%) Then ' is ship 'in hand' or placed on board already?
  1140.                 DisplayShip m_arrOffs(i%%).ShipYard_X, m_arrOffs(i%%).ShipYard_Y, i%%, c_HORZ, m_arrLayer(c_SHIPS) ' display ships in ShipYard area
  1141.                 AllPlaced%% = FALSE
  1142.             Else
  1143.                 _PutImage (64, 316 + (i%% - 1) * 24), m_arrLayer(c_SHEET), m_arrLayer(c_SHIPS), (304, 22)-(424, 46) ' Erase ships from ShipYard area
  1144.                 ' display ships placed on board
  1145.                 If m_arrShip(i%%).Xpos <> 0 Then ' if ship has valid xpos then place on board
  1146.                     If m_arrShip(i%%).Orent = c_HORZ Then
  1147.                         DisplayShip m_arrOffs(i%%).Board_HX + (m_arrShip(i%%).Xpos - 1) * 24, m_arrOffs(i%%).Board_HY + (m_arrShip(i%%).Ypos - 1) * 24, i%%, m_arrShip(i%%).Orent, m_arrLayer(SHIPS) ' display ships in Board area
  1148.                     Else
  1149.                         DisplayShip m_arrOffs(i%%).Board_VX + (m_arrShip(i%%).Xpos - 1) * 24, m_arrOffs(i%%).Board_VY + (m_arrShip(i%%).Ypos - 1) * 24, i%%, m_arrShip(i%%).Orent, m_arrLayer(SHIPS) ' display ships in Board area
  1150.                     End If
  1151.                 End If ' otherwise ship must still be 'in-hand'
  1152.             End If
  1153.         Next i%%
  1154.  
  1155.         ' move image to screen
  1156.         ' avoids flicker for the most part.
  1157.         _PutImage , m_arrLayer(c_BOARD), m_arrLayer(c_MIX)
  1158.         _PutImage , m_arrLayer(c_SHIPS), m_arrLayer(c_MIX)
  1159.         If ShipSelection%% Then DisplayShip x% - 6, y% - 6, ShipSelection%%, ShipOrentation%%, m_arrLayer(c_MIX)
  1160.  
  1161.         If m_GameData.Mode = c_LAN Then
  1162.             If m_GameData.NetWork.Ready Then
  1163.                 _PrintString (304, 454), "Opponent is ready", m_arrLayer(c_MIX)
  1164.             Else
  1165.                 _PrintString (304, 454), "Awaiting Opponent ship placement", m_arrLayer(c_MIX)
  1166.             End If
  1167.         End If
  1168.  
  1169.         _PutImage , m_arrLayer(c_MIX), m_arrLayer(0)
  1170.  
  1171.         ' *****************************************************************************
  1172.         ' debug information
  1173.         Locate 1, 1: Print Chr$(64 + hy%%); hx%%
  1174.         ' *****************************************************************************
  1175.  
  1176.         x% = _MouseX: y% = _MouseY ' get mouse location
  1177.         If x% > 54 And y% > 54 And x% < 294 And y% < 294 Then ' mouse over player board
  1178.             ' highlite grid block that mouse is over(grid blocks are 22x22[24x24WL])
  1179.             hx%% = ((x% - 54) \ 24) + 1: hy%% = ((y% - 54) \ 24) + 1
  1180.             Line (54 + ((hx%% - 1) * 24), 54 + ((hy%% - 1) * 24))-(77 + ((hx%% - 1) * 24), 77 + ((hy%% - 1) * 24)), c_YellowSelect~&, BF
  1181.  
  1182.             ' place ship on player board
  1183.             If _MouseButton(1) And ShipSelection%% <> 0 Then
  1184.                 If CheckShipPos(hx%%, hy%%, ShipOrentation%%, ShipSelection%%) Then ' make sure ship fits
  1185.                     m_arrShip(ShipSelection%%).Xpos = hx%%
  1186.                     m_arrShip(ShipSelection%%).Ypos = hy%%
  1187.                     m_arrShip(ShipSelection%%).Orent = ShipOrentation%%
  1188.                     PlaceShipOnBoard ShipSelection%%
  1189.                     held%% = 0
  1190.                     ShipSelection%% = 0
  1191.                     _MouseShow
  1192.                 End If
  1193.             End If
  1194.         End If
  1195.  
  1196.         ' -----------------------------------------------------------------------------
  1197.         ' Main input loop
  1198.         Do: _Delay .025
  1199.             KBD$ = InKey$
  1200.             Select Case KBD$
  1201.                 Case Chr$(13)
  1202.                     If AllPlaced%% And (held%% = FALSE) Then exitflag%% = TRUE
  1203.                 Case Chr$(27)
  1204.                     'exitflag%% = TRUE
  1205.                 Case Chr$(32)
  1206.                     If ShipOrentation%% = c_HORZ Then ShipOrentation%% = c_VERT Else ShipOrentation%% = c_HORZ
  1207.                     UpDateFlag%% = TRUE
  1208.                 Case Chr$(65)
  1209.                     If Not AutoFlag%% Then
  1210.                         For i%% = 1 To 5
  1211.                             st_arrPicked(i%%) = TRUE ' set true before using autopick
  1212.                             m_arrShip(i%%).Xpos = 0
  1213.                             m_arrShip(i%%).Ypos = 0
  1214.                             m_arrShip(i%).Orent = 0
  1215.                         Next i%%
  1216.                         ResetBoard
  1217.                         ClearLayer c_SHIPS
  1218.                         _ClearColor _RGB32(0, 0, 0), m_arrLayer(c_SHIPS)
  1219.                         AutoPlaceShips c_PLAYER
  1220.                         UpDateFlag%% = TRUE
  1221.                         AutoFlag%% = TRUE
  1222.                     End If
  1223.             End Select
  1224.         Loop Until _MouseInput Or exitflag%% Or UpDateFlag%%
  1225.         UpDateFlag%% = FALSE
  1226.  
  1227.         ' -----------------------------------------------------------------------------
  1228.         ' Ship Selection to place
  1229.         If x% > 64 And y% > 316 And x% < 245 And y% < 432 Then ' player over ship yard
  1230.             If _MouseButton(1) Then
  1231.                 If ShipSelection%% = 0 Then
  1232.                     hy2%% = ((y% - 316) \ 24) + 1
  1233.                     If Not st_arrPicked(hy2%%) Then ' make sure ship is still in the yard.
  1234.                         Select Case hy2%%
  1235.                             Case c_CARRIER
  1236.                                 ShipSelection%% = c_CARRIER: ShipOrentation%% = c_HORZ: st_arrPicked(1) = TRUE: held%% = 1
  1237.                             Case c_BATTLESHIP
  1238.                                 ShipSelection%% = c_BATTLESHIP: ShipOrentation%% = c_HORZ: st_arrPicked(2) = TRUE: held%% = 2
  1239.                             Case c_DESTROYER
  1240.                                 ShipSelection%% = c_DESTROYER: ShipOrentation%% = c_HORZ: st_arrPicked(3) = TRUE: held%% = 3
  1241.                             Case c_SUBMARINE
  1242.                                 ShipSelection%% = c_SUBMARINE: ShipOrentation%% = c_HORZ: st_arrPicked(4) = TRUE: held%% = 4
  1243.                             Case c_PTBOAT
  1244.                                 ShipSelection%% = c_PTBOAT: ShipOrentation%% = c_HORZ: st_arrPicked(5) = TRUE: held%% = 5
  1245.                         End Select
  1246.                     End If
  1247.                     If ShipSelection%% <> 0 Then _MouseHide
  1248.                 End If
  1249.             End If
  1250.         End If
  1251.  
  1252.         ' -----------------------------------------------------------------------------
  1253.         If x% > 304 And y% > 400 And x% < 460 And y% < 443 Then ' accept button
  1254.             If _MouseButton(1) And AllPlaced%% And (held%% = FALSE) Then
  1255.                 exitflag%% = TRUE
  1256.                 _PutImage (304, 400), m_arrLayer(c_SHEET), m_arrLayer(0), (24, 324)-(180, 367) ' accept button down
  1257.             End If
  1258.         End If
  1259.  
  1260.         If x% > 480 And y% > 400 And x% < 636 And y% < 443 Then ' reset button
  1261.             If _MouseButton(1) Then
  1262.                 _PutImage (480, 400), m_arrLayer(c_SHEET), m_arrLayer(0), (182, 324)-(338, 367) ' Reset button down
  1263.                 For i%% = 1 To 5
  1264.                     st_arrPicked(i%%) = FALSE
  1265.                     m_arrShip(i%%).Xpos = 0
  1266.                     m_arrShip(i%%).Ypos = 0
  1267.                     m_arrShip(i%).Orent = 0
  1268.                 Next i%%
  1269.                 held%% = 0: ShipSelection%% = 0
  1270.                 _MouseShow
  1271.                 ResetBoard
  1272.                 If AutoFlag%% Then AutoFlag%% = FALSE
  1273.                 ClearLayer c_SHIPS
  1274.                 _ClearColor _RGB32(0, 0, 0), m_arrLayer(c_SHIPS)
  1275.             End If
  1276.         End If
  1277.  
  1278.         If _MouseButton(2) Then ShipSelection%% = 0: st_arrPicked(held%%) = FALSE: held%% = 0: _MouseShow ' Deselect ship for placement
  1279.  
  1280.         Do: Loop While _MouseInput
  1281.     Loop Until exitflag%%
  1282.  
  1283.     ' player is done but if network game pause here until Opponent is ready
  1284.  
  1285.     ClearArea
  1286.  
  1287.     If Not m_GameData.NetWork.Ready Then
  1288.         _PrintString (304, 320), "Awaiting Opponent ship placement...", m_arrLayer(0)
  1289.         _PrintString (304, 336), "You are Ready...", m_arrLayer(0)
  1290.     End If
  1291.  
  1292.     If m_GameData.Mode = c_LAN Then
  1293.         Do
  1294.             _Delay .05
  1295.         Loop Until m_GameData.NetWork.Ready
  1296.  
  1297.         ' once client has given ship locations send hosts
  1298.         m_Message$ = "[SHP]"
  1299.         For i%% = 1 To 5
  1300.             If m_arrShip(i%%).Xpos < 10 Then m$ = "0" + LTrim$(Str$(m_arrShip(i%%).Xpos)) Else m$ = LTrim$(Str$(m_arrShip(i%%).Xpos))
  1301.             m_Message$ = m_Message$ + m$
  1302.             If m_arrShip(i%%).Ypos < 10 Then m$ = "0" + LTrim$(Str$(m_arrShip(i%%).Ypos)) Else m$ = LTrim$(Str$(m_arrShip(i%%).Ypos))
  1303.             m_Message$ = m_Message$ + m$
  1304.             m_Message$ = m_Message$ + LTrim$(Str$(m_arrShip(i%%).Orent))
  1305.         Next i%%
  1306.         SendMessage
  1307.     End If
  1308.  
  1309.     If m_GameData.Mode = c_LANCLIENT Then
  1310.         ' send host ship placement
  1311.         m_Message$ = "[SHP]"
  1312.         For i%% = 1 To 5
  1313.             If m_arrShip(i%%).Xpos < 10 Then m$ = "0" + LTrim$(Str$(m_arrShip(i%%).Xpos)) Else m$ = LTrim$(Str$(m_arrShip(i%%).Xpos))
  1314.             m_Message$ = m_Message$ + m$
  1315.             If m_arrShip(i%%).Ypos < 10 Then m$ = "0" + LTrim$(Str$(m_arrShip(i%%).Ypos)) Else m$ = LTrim$(Str$(m_arrShip(i%%).Ypos))
  1316.             m_Message$ = m_Message$ + m$
  1317.             m_Message$ = m_Message$ + LTrim$(Str$(m_arrShip(i%%).Orent))
  1318.         Next i%%
  1319.         SendMessage
  1320.         Do
  1321.             _Delay .05
  1322.         Loop Until m_GameData.NetWork.Ready
  1323.     End If
  1324.     If m_GameData.Debug Then dumpboard
  1325. End Sub ' DeployFleet
  1326.  
  1327. ' /////////////////////////////////////////////////////////////////////////////
  1328.  
  1329. Sub OpponentShot
  1330.     Do ' wait until opponent sends shot packet
  1331.         _Delay .01
  1332.         ' if something happens to Opponent
  1333.         If InKey$ = Chr$(27) Then m_GameData.NetWork.X = 1: m_GameData.NetWork.Y = 1: m_GameData.GameOver = TRUE
  1334.     Loop Until m_GameData.NetWork.X
  1335.  
  1336.     x%% = m_GameData.NetWork.X
  1337.     y%% = m_GameData.NetWork.Y
  1338.     m_GameData.NetWork.X = 0
  1339.     m_GameData.NetWork.Y = 0
  1340.  
  1341.     MessageHandler "Opponent fires at " + Chr$(64 + y%%) + Str$(x%%)
  1342.     _Delay .5
  1343.  
  1344.     Select Case SendShot(x%%, y%%, c_OPPONENT)
  1345.         Case c_HIT ' Hits players ship
  1346.             MessageHandler "Opponent Hits!"
  1347.             CheckShips
  1348.         Case c_MISS ' Missed players ship
  1349.             MessageHandler "Opponent Misses"
  1350.         Case c_BAD ' Already fired upon this space ERROR
  1351.             MessageHandler "Opponent has been Hitting the juice again, fired an error"
  1352.     End Select
  1353.     _Delay .5
  1354. End Sub ' OpponentShot
  1355.  
  1356. ' /////////////////////////////////////////////////////////////////////////////
  1357.  
  1358. Sub CreateNetworkGame
  1359.     Cls
  1360.     ClearLayer c_MIX
  1361.  
  1362.     _Font m_arrFFX(1), m_arrLayer(c_LAN)
  1363.     _PrintString (128, 32), "PORT ADDRESS FOR HOST", m_arrLayer(c_LAN)
  1364.     _Font m_arrFFX(6), m_arrLayer(c_LAN)
  1365.     _PrintString (96, 64), "VALUE MUST BE GREATER THAN 1000", m_arrLayer(c_LAN)
  1366.     _PrintString (200, 84), "0 FOR DEFUALT PORT", m_arrLayer(c_LAN)
  1367.     _Font m_arrFFX(5), m_arrLayer(c_MIX)
  1368.     ChangeColor _RGB32(63, 208, 63), m_arrLayer(c_MIX)
  1369.  
  1370.     port$ = "1945" ' defualt WWII port address
  1371.     Do
  1372.         Port% = Val(port$)
  1373.         _PutImage , m_arrLayer(c_LAN), m_arrLayer(c_MIX)
  1374.         _PrintString (268, 117), LTrim$(Str$(Port%)), m_arrLayer(c_MIX)
  1375.         _PutImage , m_arrLayer(c_MIX), m_arrLayer(0)
  1376.         x% = _FontWidth(m_arrFFX(5)) * Len(port$)
  1377.         Line (268 + x%, 158)-(292 + x%, 162), _RGB32(255, 255, 0), BF
  1378.         Do
  1379.             KBD$ = InKey$
  1380.             Select Case KBD$
  1381.                 Case Chr$(8) ' backspace
  1382.                     If port$ <> "" Then port$ = Mid$(port$, 1, Len(port$) - 1)
  1383.                     UpDate%% = TRUE
  1384.                 Case Chr$(13)
  1385.                     If Len(port$) = 4 Then
  1386.                         Port% = Val(port$): ExitFlag%% = TRUE
  1387.                     ElseIf port$ = "" Or port$ = "0" Then
  1388.                         Port% = 0: ExitFlag%% = TRUE
  1389.                     End If
  1390.                 Case Chr$(27)
  1391.                     ExitFlag%% = TRUE
  1392.                 Case Chr$(48) TO Chr$(57) ' numbers
  1393.                     If Len(port$) < 4 Then port$ = port$ + KBD$
  1394.                     UpDate%% = TRUE
  1395.             End Select
  1396.             _Delay .025
  1397.         Loop Until _MouseInput Or ExitFlag%% Or UpDate%%
  1398.         UpDate%% = FALSE
  1399.     Loop Until ExitFlag%%
  1400.  
  1401.     ExitFlag%% = FALSE
  1402.  
  1403.     _Font 16, m_arrLayer(c_LAN)
  1404.     _PrintString (8, 464), "Starting up host...", m_arrLayer(0)
  1405.  
  1406.     m_GameData.NetWork.Host = StartHost(Port%)
  1407.     If m_GameData.NetWork.Host Then _Delay 1.5 ' give host a few secs to start up
  1408.     m_GameData.Mode = c_LAN
  1409.  
  1410.     Timer(m_Listen&) On ' turn on the timer to listen for opponent chatter
  1411.  
  1412.     ' connect host user
  1413.     _PrintString (256, 464), "Connecting to host...", m_arrLayer(0)
  1414.     _Delay .5
  1415.  
  1416.     m_GameData.NetWork.Client = ConnectClient(Port%, "0")
  1417.     ' game is now in network mode
  1418.  
  1419.     _Font m_arrFFX(2), m_arrLayer(c_MIX)
  1420. End Sub ' CreateNetworkGame
  1421.  
  1422. ' /////////////////////////////////////////////////////////////////////////////
  1423.  
  1424. Sub JoinNetworkGame
  1425.     Cls
  1426.     ClearLayer c_MIX
  1427.  
  1428.     _Font m_arrFFX(1), m_arrLayer(c_LAN)
  1429.     _PrintString (128, 32), "PORT ADDRESS CONNECT TO", m_arrLayer(c_LAN)
  1430.     _PrintString (144, 168), "IP ADDRESS CONNECT TO", m_arrLayer(c_LAN)
  1431.     _Font m_arrFFX(6), m_arrLayer(c_LAN)
  1432.     _PrintString (200, 84), "0 FOR DEFUALT PORT", m_arrLayer(c_LAN)
  1433.     _PutImage (32, 200), m_arrLayer(c_SHEET), m_arrLayer(c_LAN), (0, 376)-(575, 430)
  1434.  
  1435.     _Font m_arrFFX(5), m_arrLayer(c_MIX)
  1436.     ChangeColor _RGB32(63, 208, 63), m_arrLayer(c_MIX)
  1437.     port$ = "1945" ' defualt WWII port address
  1438.     If IPA$ = "" Then IPA$ = "LOCALHOST"
  1439.     selection%% = 2
  1440.     Do
  1441.         Port% = Val(port$)
  1442.         _PutImage , m_arrLayer(c_LAN), m_arrLayer(c_MIX)
  1443.         _PrintString (268, 117), LTrim$(Str$(Port%)), m_arrLayer(c_MIX)
  1444.  
  1445.         _PrintString (320 - ((Len(IPA$) \ 2) * _FontWidth(m_arrFFX(5))), 208), IPA$, m_arrLayer(c_MIX)
  1446.         _PutImage , m_arrLayer(c_MIX), m_arrLayer(0)
  1447.  
  1448.         x% = _MouseX: y% = _MouseY ' get mouse location
  1449.  
  1450.         If _MouseButton(1) Then
  1451.             If x% > 220 And x% < 450 And y% > 112 And y% < 162 Then selection%% = 1 ' port address
  1452.             If x% > 40 And x% < 600 And y% > 200 And y% < 250 Then selection%% = 2 ' IP address
  1453.             update%% = TRUE
  1454.         End If
  1455.  
  1456.         If selection%% = 1 Then
  1457.             x% = _FontWidth(m_arrFFX(5)) * Len(port$)
  1458.             Line (268 + x%, 158)-(292 + x%, 162), _RGB32(255, 255, 0), BF
  1459.         ElseIf selection%% = 2 Then
  1460.             x% = 320 - ((Len(IPA$) \ 2) * _FontWidth(m_arrFFX(5))) + (Len(IPA$) * _FontWidth(m_arrFFX(5)))
  1461.             Line (x%, 249)-(x% + 24, 253), _RGB32(255, 255, 0), BF
  1462.         End If
  1463.         Do
  1464.             KBD$ = InKey$
  1465.             Select Case KBD$
  1466.                 Case Chr$(8) ' backspace
  1467.                     If selection%% = 1 Then
  1468.                         If port$ <> "" Then port$ = Mid$(port$, 1, Len(port$) - 1)
  1469.                     ElseIf selection%% = 2 Then
  1470.                         If IPA$ <> "" Then IPA$ = Mid$(IPA$, 1, Len(IPA$) - 1)
  1471.                     End If
  1472.                     update%% = TRUE
  1473.                 Case Chr$(13)
  1474.                     If Len(port$) = 4 Then
  1475.                         If IPA$ = "" Or UCase$(IPA$) = "LOCALHOST" Then IPA$ = "0"
  1476.                         Port% = Val(port$): ExitFlag%% = TRUE
  1477.                     ElseIf port$ = "" Or port$ = "0" Then
  1478.                         Port% = 0: ExitFlag%% = TRUE
  1479.                     End If
  1480.                 Case Chr$(27)
  1481.                     ExitFlag%% = TRUE: m_Cancel%% = TRUE
  1482.                 Case Chr$(48) TO Chr$(57), Chr$(46) ' numbers and .
  1483.                     If selection%% = 1 Then
  1484.                         If Len(port$) < 4 Then port$ = port$ + KBD$
  1485.                     ElseIf selection%% = 2 Then
  1486.                         If Len(IPA$) < 15 Then IPA$ = IPA$ + KBD$
  1487.                     End If
  1488.                     update%% = TRUE
  1489.             End Select
  1490.             _Delay .025
  1491.         Loop Until _MouseInput Or ExitFlag%% Or update%%
  1492.         update%% = FALSE
  1493.         Do: Loop While _MouseInput
  1494.  
  1495.     Loop Until ExitFlag%%
  1496.     ExitFlag%% = FALSE
  1497.  
  1498.     _Font 16, m_arrLayer(c_LAN)
  1499.  
  1500.     ' connect host user
  1501.     If Not m_Cancel%% Then
  1502.         _PrintString (256, 464), "Connecting to host...", m_arrLayer(0)
  1503.         _Delay .5
  1504.         m_GameData.NetWork.Client = ConnectClient(Port%, IPA$)
  1505.         If m_GameData.NetWork.Client Then m_GameData.Mode = c_LANCLIENT
  1506.         Timer(m_Listen&) On ' turn on the timer to listen for opponent chatter
  1507.     End If
  1508. End Sub ' JoinNetworkGame
  1509.  
  1510. ' /////////////////////////////////////////////////////////////////////////////
  1511. ' Instructions
  1512.  
  1513. Sub Instruction
  1514.     _Font m_arrFFX(1), m_arrLayer(c_MIX)
  1515.     ChangeColor _RGB32(212, 212, 212), m_arrLayer(c_MIX) ' Hover color
  1516.     ClearLayer c_MIX
  1517.  
  1518.     _PrintString (200, 16), "BATTLESHIP 64", m_arrLayer(c_MIX)
  1519.     _PrintString (64, 48), "SHIP STATS:", m_arrLayer(c_MIX)
  1520.  
  1521.     For i%% = 1 To 5
  1522.         DisplayShip 32, 64 + (32 * i%%), i%%, c_HORZ, m_arrLayer(c_MIX)
  1523.     Next i%%
  1524.  
  1525.     _PrintString (160, 96), "CARRIER TAKES 5 HITS", m_arrLayer(c_MIX)
  1526.     _PrintString (160, 128), "BATTLESHIP TAKES 4 HITS", m_arrLayer(c_MIX)
  1527.     _PrintString (160, 160), "DESTROYER TAKES 3 HITS", m_arrLayer(c_MIX)
  1528.     _PrintString (160, 192), "SUBMARINE TAKES 3 HITS", m_arrLayer(c_MIX)
  1529.     _PrintString (160, 224), "PT BOAT TAKES 2 HITS", m_arrLayer(c_MIX)
  1530.  
  1531.     _Font m_arrFFX(4), m_arrLayer(c_MIX)
  1532.     _PrintString (32, 256), "Ships can be palced vertically", m_arrLayer(c_MIX)
  1533.     _PrintString (32, 288), "on the game board by pressing", m_arrLayer(c_MIX)
  1534.     _PrintString (32, 320), "the space bar while the ship", m_arrLayer(c_MIX)
  1535.     _PrintString (32, 352), "is selected.", m_arrLayer(c_MIX)
  1536.  
  1537.     _PutImage (32, 400), m_arrLayer(c_SHEET), m_arrLayer(c_MIX), (305, 144)-(327, 166)
  1538.     _PutImage (32, 432), m_arrLayer(c_SHEET), m_arrLayer(c_MIX), (329, 144)-(350, 166)
  1539.  
  1540.     _PrintString (64, 400), "-Denotes a hit.", m_arrLayer(c_MIX)
  1541.     _PrintString (64, 432), "-Denotes a miss.", m_arrLayer(c_MIX)
  1542.  
  1543.     _Font 16, m_arrLayer(c_MIX)
  1544.     _PrintString (8, 464), "Press any key to return to menu", m_arrLayer(c_MIX)
  1545.  
  1546.     _PutImage , m_arrLayer(c_MIX), m_arrLayer(0)
  1547.  
  1548.     _Font m_arrFFX(2), m_arrLayer(c_MIX)
  1549.  
  1550.     Do: Loop While InKey$ = ""
  1551.     _KeyClear
  1552. End Sub ' Instruction
  1553.  
  1554. ' ****************************************************************************************************************************************************************
  1555. ' BEGIN DEBUGGING ROUTINES
  1556. ' Routines Beyond are not Game nessesary
  1557. ' ****************************************************************************************************************************************************************
  1558.  
  1559. ' /////////////////////////////////////////////////////////////////////////////
  1560. ' debugging
  1561.  
  1562. Sub dumpboard
  1563.     For z%% = 1 To 2
  1564.         For y%% = 1 To 10
  1565.             For x%% = 1 To 10
  1566.                 Print #6, m_arrBoard(x%%, y%%, z%%);
  1567.             Next x%%
  1568.             Print #6,
  1569.         Next y%%
  1570.         Print #6,: Print #6,
  1571.     Next z%%
  1572. End Sub ' dumpboard
  1573.  
  1574. ' /////////////////////////////////////////////////////////////////////////////
  1575.  
  1576. ' ****************************************************************************************************************************************************************
  1577. ' END DEBUGGING ROUTINES
  1578. ' ****************************************************************************************************************************************************************
  1579.  
« Last Edit: July 13, 2021, 01:24:25 pm by madscijr »

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #8 on: July 13, 2021, 11:29:22 pm »
Question, what format file is "battleship.gfx", and how would you edit it?
Thanks...

Its an outdated version of my MFI proprietary packing format. Not really editable in the easy sense.
I've never had to "de-compile" a resource file before so I have never developed a program to unpack one.

I think I still have all the resource material floating around somewhere though.
Granted after becoming radioactive I only have a half-life!

Offline Cobalt

  • QB64 Developer
  • Forum Resident
  • Posts: 878
  • At 60 I become highly radioactive!
    • View Profile
Re: Simple example of LAN game with 2-4 PCs?
« Reply #9 on: July 14, 2021, 12:47:10 am »
I was looking at your code, and got the genius idea (I hope you are picking up on the sarcasm here)
to rename the variables a little less ambiguously to help me follow what the code is doing,
and I seem to have introduced a little bug where when you place a ship on the board, it disappears.
If you have any bandwidth, and could quickly zero in on the line that might be making that happen,
that would be very much appreciated... No pressure or anything, LoL

Besides obfuscating my code, you apparently changed something that must not be changed. What that is I have no clue, but the ships don't actually disappear, they now flicker(faintly) on my machine. So by changing names you have changed the order of operations somewhere and the board now gets drawn over the ships instead of the ships getting drawn over the board. Believe it or not sometimes names matter, when it comes to variables and what not. (no sarcasm, just a grain of salt. take it how you will XD)

Guessing you used the CHANGE ALL command and just bulk changed things? If so, that is certainly what did it. (I have accidentally done similar things) I would suggest you pull a clean copy and if you really, REALLY, REALLY! need to change variable names then use the FIND AND VERIFY option and confirm that each change is in fact the exact variable you are trying to rename. I would highly advise against messing with the LAYER array name. or any names pertaining to Graphics layers (ie variables in _putimage lines, _loadimage lines, or _newimage lines) as they tend to be important.

but reviewing this code, man! there are things which I would never do anymore. to think in only like 2 1\2 years I have found so many better ways to do things. And I never did add sound... :(
but that would be why there is no SFX file.  May have just given me a reason to revisit this project an maybe get it up to Ver 1.0(or at least 0.9)
Granted after becoming radioactive I only have a half-life!