UQ Students should read the Disclaimer & Warning

Note: This page dates from 2005, and is kept for historical purposes.

<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.1//EN"
    "http://www.w3.org/TR/xhtml11/DTD/xhtml11.dtd">
<html xmlns="http://www.w3.org/1999/xhtml">
<head>
<title>COMP2301 - Assignment 5 - Basic Network Programming in Visual Basic</title>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8" />
<style type="text/css">
<!--
.wrong {
    background: #FF9999;
}
body {
    background: url(_img/DSC04989.jpg) fixed center;
    font-family: "Arial Unicode MS", Arial, Helvetica, sans-serif;
}
th, td, textarea {
    border: 1px solid #000000;
    padding: 0 1ex;
    background: transparent;
    overflow: hidden;
}
table {
    border: none;
}
.changing-vars {
    color: #0000FF;
}
-->
</style>
</head>
<body> 
<h1>COMP2301 &ndash; Assignment Five &ndash; Basic Network Programming in Visual
    Basic</h1> 
<p> This assignment is a pass/fail assignment. I achieved a pass.</p> 
<p>The goal of this assignment is to gain experience using Visual Basic by implementing
    a simple network enabled application. </p> 
<p>In this assignment, you should become familiar with: </p> 
<ul> 
    <li>Network programming under Visual Studio 6 </li> 
    <li>IP addresses, Ports and Sockets </li> 
</ul> 
<h2>Specification </h2> 
<p>Develop a network enabled version of Tick Tack Toe with the following features:</p> 
<ul> 
    <li>Auto Discovery for all active work stations within a set IP range </li> 
    <li>Display Network Gaming traffic in a text window </li> 
    <li>Display game local status on screen (Playing, Win, Lose, Draw, Abort) </li> 
    <li>Display game network status on screen (Off Line, Ready, Busy) </li> 
    <li>Publish game network status via a network port (Off Line, Ready, Busy) </li> 
    <li>Randomly select the player who makes the first move </li> 
</ul> 
<p>Each player must be able to:</p> 
<ul> 
    <li>Invite other players to game by selecting a remote player from the auto
        discovery list </li> 
    <li>Accept or reject an invitation from another player </li> 
    <li>Perform all functions via mouse clicks </li> 
    <li>Manually set the games network status at any time. (Off Line, Ready, Busy) </li> 
    <li>Abort &amp; Reset the game at any time. </li> 
    <li>Change the Auto Discovery Range to any continuous sub range between 130.102.73.32
        and 130.102.73.64 </li> 
</ul> 
<h2>General operation </h2> 
<p>The applications will communicate over a number of fixed ports via simple
    text messages to transfer gaming status and commands. </p> 
<p>Individual ports are specified for sending and receiving gaming traffic. It
    is assumed that a small number of games will be active at any one time and that
    all network requests will be services without delay. </p> 
<p>Each game will format and display the content of all gaming traffic it has
    generated or received in a text window. The gaming commands, auto discovery
    requests and any other application specific messages will be presented at the
    bottom of the screen in a scrolling window. The last 100 gaming command and
    control messages should be buffered and accessible. At the top of the screen
    all status information must be displayed with buttons for all the gaming functions. </p> 
<p>After launching the application the user will select Auto Discovery to generate
    a listing of all the active workstations. </p> 
<p>The user may click on any one of the listed active gaming work stations and
    invite them to play. On the remote gaming work station a dialog box containing
    a detailed invitation will be displayed. The remote user may now accept or reject
    the invitation. If the remote user accepts the invitation the inviting system
    will randomly assign a player to go first. The first player must select Naught
    (green) or Cross (red) and click to indicate where to place their selection.
    The other system will automatically assign the remaining token. After this each
    player will make a selection in turn until the game is over. (out of turn plays
    are illegal) </p> 
<p>Each end will maintain error checking and highlight any remote illegal moves
    in blue on the local system. If an illegal move is made the originator must
    display the move (O=green, X=red) and send the move to the remote player. The
    remote player must detect the invalid move, display the move in blue and send
    an illegal move message back. The originator of the illegal move must respond
    to the illegal move information and automatically change the colour of the illegal
    item on their local system. If the originator of an illegal move clicks that
    item (now blue) it will be removed from the game. Only after all illegal items
    are removed can the game proceed. </p> 
<p>When a winning token is placed the remote system must detect the condition
    and notify the originator of the win. After this the winning line of X/O will
    be identified as a local event by colour change on both systems. The game is
    now over. The players will be shown a dialogue box congratulating the winner.
    At any time either player may Abort / Reset or Manually change the games network
    status. Connected players should react to all events logically. </p> 
<h2>Port definitions </h2> 
<ul> 
    <li>All port definitions and functions are symmetric for local and remote systems </li> 
    <li>No dynamic ports are used by the application. (all fixed) </li> 
    <li>Port 6000 : Discovery Request. Listening only. This port must be monitored
        by the application at all times. All traffic must be processed immediately. </li> 
    <li>Port 6001 : Discovery Request. Transmit only. This port is used to send
        a local system’s Discovery Request to port 6000 of a remote system. </li> 
    <li>Port 6010 : Discovery Status. Listening only. This port accepts status information
        from a remote systems. </li> 
    <li>Port 6011 : Discovery Status. Transmit only. This port is used to send local
        system status information to port 6010 in response to a remote request. </li> 
    <li>Port 6020 : Game commands. Listening only. This port accepts gaming commands
        from the remote system. </li> 
    <li>Port 6021 : Game commands. Transmit only. This port sends gaming commands
        to the remote system. </li> 
</ul> 
<h2>Commands &amp; Messages</h2> 
<p> (examples: Local system John Smith IP 130.102.73.53. Remote system Fred Nirk
    IP 130.102.73.33) </p> 
<ul> 
    <li>Port <span class="changing-vars">6000</span>: This port accepts one command
        only from a remote system. &lt;Auto Discovery Request, For:<span class="changing-vars">IP</span>&gt; <br /> 
        ie Auto Discovery Request, For:<span class="changing-vars">130.102.73.53</span>. </li> 
    <li>Port <span class="changing-vars">6001</span>: This port sends one command
        only to a remote system. &lt;Auto Discovery Request, For:<span class="changing-vars">IP</span>&gt;<br /> 
        ie Auto Discovery Request, For:<span class="changing-vars">130.102.73.32</span> </li> 
    <li>Port <span class="changing-vars">6010</span>: This port accepts status information
        from a remote systems. <br /> 
        ie Auto Discovery Reply, Status: <span class="changing-vars">Off Line</span> From:<span class="changing-vars">130.102.73.33</span> Players
        Name: <span class="changing-vars">Fred Nirk </span></li> 
    <li>Port <span class="changing-vars">6011</span>: This port sends local status
        information to a remote systems. &lt;Auto Discovery Reply, Status: <span class="changing-vars">Status</span> From:<span class="changing-vars">IP</span> Players
        Name: <span class="changing-vars">name</span>&gt; <br /> 
        Auto Discovery Reply, Status: <span class="changing-vars">Ready</span> From:<span class="changing-vars">130.102.73.53</span> Players
        Name: <span class="changing-vars">John Smith</span> <br /> 
        <span class="changing-vars">Status</span> = [Off Line, Ready, Busy] </li> 
    <li>Port <span class="changing-vars">6020</span>: This port accepts gaming messages
        and commands from a remote system </li> 
    <li>Port <span class="changing-vars">6021</span>: This port sends gaming messages
        and commands to a remote system </li> 
</ul> 
<h2>Gaming Commands</h2>
<p> Port 6020 &amp; Port 6021 </p>
<p>&lt;Invitation, From:<span class="changing-vars">IP</span> Players Name: <span class="changing-vars">Inviting
        player’s name</span>&gt; <em>Invite a remote player to play the game.<br /> 
    </em>&lt;Acceptance, From:<span class="changing-vars">IP</span> Players Name: <span class="changing-vars">Accepting
    player’s name</span>&gt; <em>Accept an invitation to play the game. <br /> 
    </em>&lt;Assign First Player, From:<span class="changing-vars">IP</span> First
    Players Name: <span class="changing-vars">First players name</span>&gt; <em>Inviting
    system must select and assign the first player status. <br /> 
    </em>&lt;Select, Token: <span class="changing-vars">x</span> From:<span class="changing-vars">IP</span> Players
    Name: <span class="changing-vars">name</span>&gt; <em>Each player selects X
    or O which is displayed on the remote screen. Token: [<span class="changing-vars">X</span>|<span class="changing-vars">O</span>] <br /> 
    </em>&lt;Place , Token: <span class="changing-vars">x</span> Colour: <span class="changing-vars">x</span> Position: <span class="changing-vars">xx</span> From:<span class="changing-vars">IP</span> Players
    Name: <span class="changing-vars">name</span> &gt; <em>Player places a token
    on the grid A1 to C3 with Colour [R|G|B] <br /> 
    </em>&lt;Delete, Token: <span class="changing-vars">x</span> Colour: <span class="changing-vars">x</span> Position: <span class="changing-vars">xx</span> From:<span class="changing-vars">IP</span> Players
    Name: <span class="changing-vars">name</span> &gt; <em>Reports the removal of
    an illegal token from a system. <br /> 
    </em>&lt;Illegal, Token: <span class="changing-vars">x</span> Colour: <span class="changing-vars">x</span> Position: <span class="changing-vars">xx</span> From:IP
    Players Name: <span class="changing-vars">name</span> &gt; <em>Identifies an
    illegal token to the remote system. <br /> 
    </em>&lt;Winner, From:<span class="changing-vars">IP</span> Winners Name: <span class="changing-vars">winner’s
    name</span>&gt; <em>Notifies the remote system of game completion. <br /> 
    </em></p> 
<h2>Example</h2> 
<p> Text from Network Gaming traffic window on the local system </p> 
<ul> 
    <li> This traffic should be presented as a sequence of text strings one per
        line in time order. <br /> 
        <em>..................User selects Auto Discovery function from GUI ..................... <br /> 
        </em> Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote
        Port <span class="changing-vars">6000</span> Auto Discovery Request, For: <span class="changing-vars">130.102.73.32</span> <br /> 
        Local Port <span class="changing-vars">6010</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6011</span> Auto
        Discovery Reply, Status: <span class="changing-vars">Ready</span> From: <span class="changing-vars">130.102.73.32</span> Players
        Name: <span class="changing-vars">David Jones</span> <br /> 
        Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6000</span> Auto
        Discovery Request, For: <span class="changing-vars">130.102.73.33</span> <br /> 
        Local Port <span class="changing-vars">6010</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6011</span> Auto
        Discovery Reply, Status: <span class="changing-vars">Ready</span> From: <span class="changing-vars">130.102.73.33</span> Players
        Name: <span class="changing-vars">Fred Nirk</span> <br /> 
        Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6000</span> Auto
        Discovery Request, For: <span class="changing-vars">130.102.73.34</span> <br /> 
        Local Port <span class="changing-vars">6010</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6011</span> Auto
        Discovery Reply, Status: <span class="changing-vars">Busy</span> From: <span class="changing-vars">130.102.73.34</span> Players
        Name: <span class="changing-vars">Max Mouse</span> <br /> 
        Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6000</span> Auto
        Discovery Request, For: <span class="changing-vars">130.102.73.35</span> <em>(No
        response from system.........) </em><br /> 
        Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6000</span> Auto
        Discovery Request, For: <span class="changing-vars">130.102.73.36</span> <em>(No
        response from system........) </em><br /> 
        Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6000</span> Auto
        Discovery Request, For: <span class="changing-vars">130.102.73.37</span> <em>(No
        response from system........) </em><br /> 
        Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6000</span> Auto
        Discovery Request, For: <span class="changing-vars">130.102.73.38</span> <em>(No
        response from system........) </em><br /> 
        Local Port <span class="changing-vars">6010</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6011</span> Auto
        Discovery Reply, Status: <span class="changing-vars">Off Line</span> From: <span class="changing-vars">130.102.73.38</span> Players
        Name: <span class="changing-vars">Donald Duck</span> <br /> 
        <em>..................Auto Discovery continues.......... <br /> 
        </em> Local Port <span class="changing-vars">6001</span> &gt;&gt;&gt; Remote
        Port <span class="changing-vars">6000</span> Auto Discovery Request, For: <span class="changing-vars">130.102.73.64</span> <br /> 
        Local Port <span class="changing-vars">6010</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6011</span> Auto
        Discovery Reply, Status: <span class="changing-vars">Ready</span> From: <span class="changing-vars">130.102.73.64</span> Players
        Name: <span class="changing-vars">Another Player</span> <br /> 
        <em>. .................User selects Second Player from list Fred Nirk.......................... </em><br /> 
        Local Port <span class="changing-vars">6021</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6020</span> Invitation,
        From: <span class="changing-vars">130.102.73.53</span> Players Name: <span class="changing-vars">John
        Smith</span> <br /> 
        Local Port <span class="changing-vars">6020</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6021</span> Acceptance,
        From: <span class="changing-vars">130.102.73.33</span> Players Name: <span class="changing-vars">Fred
        Nirk</span> <br /> 
        Local Port <span class="changing-vars">6021</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6020</span> Assign
        First Player, From: <span class="changing-vars">130.102.73.53</span> First
        Players Name: <span class="changing-vars">John Smith</span> <em>(Randomly select
        the first player) </em><br /> 
        Local Port <span class="changing-vars">6021</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6020</span> Select,
        Token: <span class="changing-vars">O</span> From: <span class="changing-vars">130.102.73.53</span> Players
        Name: <span class="changing-vars">John Smith</span> <em>(Second player’s system
        displays remaining token X ) </em><br /> 
        Local Port <span class="changing-vars">6021</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6020</span> Place
        , Token: <span class="changing-vars">O</span> Colour: <span class="changing-vars">G</span> Position: <span class="changing-vars">B2</span> From: <span class="changing-vars">130.102.73.53</span> Players
        Name: <span class="changing-vars">John Smith</span> <br /> 
        Local Port <span class="changing-vars">6020</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6021</span> Place
        , Token: <span class="changing-vars">X</span> Colour: <span class="changing-vars">R</span> Position: <span class="changing-vars">B1</span> From: <span class="changing-vars">130.102.73.33</span> Players
        Name: <span class="changing-vars">Fred Nirk</span> <br /> 
        Local Port <span class="changing-vars">6021</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6020</span> Place
        , Token: <span class="changing-vars">O</span> Colour: <span class="changing-vars">G</span> Position: <span class="changing-vars">A3</span> From: <span class="changing-vars">130.102.73.53</span> Players
        Name: <span class="changing-vars">John Smith</span> <br /> 
        <em>.................Play continues until John’s system detects Fred placing
        a token at C2 out of turn......................... </em><br /> 
        Local Port <span class="changing-vars">6021</span> &gt;&gt;&gt; Remote Port <span class="changing-vars">6020</span> Illegal,
        Token: <span class="changing-vars">X</span> Colour: <span class="changing-vars">B</span> Position: <span class="changing-vars">C2</span> From: <span class="changing-vars">130.102.73.53</span> Players
        Name: <span class="changing-vars">John Smith</span> <em>(Fred’s system must
        redisplay C2) <br /> 
        </em>Local Port <span class="changing-vars">6020</span> &lt;&lt;&lt; Remote
        Port <span class="changing-vars">6021</span> Delete, Token: <span class="changing-vars">X</span> Colour: <span class="changing-vars">B</span> Position: <span class="changing-vars">C2</span> From: <span class="changing-vars">130.102.73.33</span> Players
        Name: <span class="changing-vars">Fred Nirk</span> ( <em>Fred removed the illegal
        token) </em><br /> 
        <em>.................Play continues until Fred’s system detects the last token
        placed by John was the winning move......................... </em><br /> 
        Local Port <span class="changing-vars">6020</span> &lt;&lt;&lt; Remote Port <span class="changing-vars">6021</span> Winner,
        From: <span class="changing-vars">130.102.73.33</span> Winners Name: <span class="changing-vars">John
        Smith</span> <br /> 
    </li> 
</ul> 
<h2>General </h2> 
<ul> 
    <li>Auto Discovery IP range must be displayed on screen and show both upper
        and lower values. Maximum range must be hard coded. </li> 
    <li>Players may place X or O at any time and in any order. All plays must be
        displayed on the local system in Red and Green. </li> 
    <li>Reasonable error detection and handling is required. </li> 
    <li>The application must be well behaved and terminate gracefully. </li> 
    <li>Care must be taken during the development and testing of this application
        to avoid excessive network traffic. </li> 
</ul> 
<p>No IP traffic should be generated outside of the specified IP / Port range. </p>
<p><em>Note: This application was coded as fast as possible, and as such does
        not conform exactly to the specification, and may not be stable or fit for
        use. The IP range is hard-coded, so without modification this application will
        only work in environments with a similar IP range.</em></p>
<p><a href=".//COMP2301-assignment-5-TicTacToe.exe" title="Downloadable application - TicTacToe">Compiled
    (WIN32) binary</a> (64 KB)</p> 
<p>frmTicTacToe.frm<br /> 
    <textarea name="vb" cols="82" rows="1180" readonly="readonly" title="Visual Basic 6 Code">VERSION 5.00
Object = &quot;{248DD890-BB45-11CF-9ABC-0080C7E7B78D}#1.0#0&quot;; &quot;MSWINSCK.OCX&quot;
Begin VB.Form frmTicTacToe 
   Caption         =   &quot;Naughts and Crosses&quot;
   ClientHeight    =   6240
   ClientLeft      =   165
   ClientTop       =   735
   ClientWidth     =   5415
   LinkTopic       =   &quot;Form1&quot;
   ScaleHeight     =   6240
   ScaleWidth      =   5415
   StartUpPosition =   3  'Windows Default
   Begin VB.ListBox lstStatus 
      Height          =   1230
      Left            =   0
      TabIndex        =   10
      Top             =   4920
      Width           =   5415
   End
   Begin MSWinsockLib.Winsock udpGameOUT 
      Left            =   7440
      Top             =   0
      _ExtentX        =   741
      _ExtentY        =   741
      _Version        =   393216
      Protocol        =   1
   End
   Begin MSWinsockLib.Winsock udpGameIN 
      Left            =   6840
      Top             =   0
      _ExtentX        =   741
      _ExtentY        =   741
      _Version        =   393216
      Protocol        =   1
   End
   Begin MSWinsockLib.Winsock udpStatusOUT 
      Left            =   6240
      Top             =   0
      _ExtentX        =   741
      _ExtentY        =   741
      _Version        =   393216
      Protocol        =   1
   End
   Begin MSWinsockLib.Winsock udpStatusIN 
      Left            =   5640
      Top             =   0
      _ExtentX        =   741
      _ExtentY        =   741
      _Version        =   393216
      Protocol        =   1
   End
   Begin MSWinsockLib.Winsock udpAutoRecOUT 
      Left            =   5040
      Top             =   0
      _ExtentX        =   741
      _ExtentY        =   741
      _Version        =   393216
      Protocol        =   1
   End
   Begin MSWinsockLib.Winsock udpAutoRecIN 
      Left            =   4440
      Top             =   0
      _ExtentX        =   741
      _ExtentY        =   741
      _Version        =   393216
      Protocol        =   1
   End
   Begin VB.Frame frmAutoFind 
      Caption         =   &quot;Naughts and Crosses (Auto Find)&quot;
      Height          =   4815
      Left            =   0
      TabIndex        =   15
      Top             =   0
      Width           =   5415
      Begin VB.CommandButton btnAutoDiscover 
         Caption         =   &quot;&amp;AutoDiscover&quot;
         Height          =   375
         Left            =   120
         TabIndex        =   18
         Top             =   4320
         Width           =   2055
      End
      Begin VB.CommandButton btnInvite 
         Caption         =   &quot;&amp;Invite&quot;
         Enabled         =   0   'False
         Height          =   375
         Left            =   2280
         TabIndex        =   17
         Top             =   4320
         Width           =   1095
      End
      Begin VB.ListBox lstUsers 
         Height          =   3960
         Left            =   120
         TabIndex        =   16
         Top             =   240
         Width           =   5055
      End
   End
   Begin VB.Frame frmConfig 
      Caption         =   &quot;Configuration&quot;
      Enabled         =   0   'False
      Height          =   4815
      Left            =   0
      TabIndex        =   11
      Top             =   0
      Visible         =   0   'False
      Width           =   5415
      Begin VB.ComboBox cmbIPLower 
         Height          =   315
         Left            =   2160
         TabIndex        =   21
         Text            =   &quot;Combo2&quot;
         Top             =   2760
         Width           =   855
      End
      Begin VB.ComboBox cmbIPUpper 
         Height          =   315
         Left            =   480
         TabIndex        =   20
         Text            =   &quot;Combo1&quot;
         Top             =   2760
         Width           =   855
      End
      Begin VB.CommandButton btnSave 
         Caption         =   &quot;&amp;Save Settings&quot;
         Height          =   375
         Left            =   3480
         TabIndex        =   13
         Top             =   4200
         Width           =   1575
      End
      Begin VB.TextBox txtName 
         Height          =   285
         Left            =   480
         TabIndex        =   12
         Text            =   &quot;Text1&quot;
         Top             =   1440
         Width           =   2175
      End
      Begin VB.Label lblIPRange 
         Caption         =   &quot;(Upper) Select IP Range (Lower)&quot;
         Height          =   255
         Left            =   480
         TabIndex        =   19
         Top             =   2280
         Width           =   3135
      End
      Begin VB.Label lblName 
         Caption         =   &quot;Name:&quot;
         Height          =   255
         Left            =   480
         TabIndex        =   14
         Top             =   1200
         Width           =   2175
      End
   End
   Begin VB.Frame frmGameFrame 
      Caption         =   &quot;Naughts and Crosses (Starting Up...)&quot;
      Enabled         =   0   'False
      Height          =   4815
      Left            =   0
      TabIndex        =   0
      Top             =   0
      Visible         =   0   'False
      Width           =   5415
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   8
         Left            =   3600
         Style           =   1  'Graphical
         TabIndex        =   9
         Top             =   3240
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   7
         Left            =   1920
         Style           =   1  'Graphical
         TabIndex        =   8
         Top             =   3240
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   6
         Left            =   240
         Style           =   1  'Graphical
         TabIndex        =   7
         Top             =   3240
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   5
         Left            =   3600
         Style           =   1  'Graphical
         TabIndex        =   6
         Top             =   1800
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   4
         Left            =   1920
         Style           =   1  'Graphical
         TabIndex        =   5
         Top             =   1800
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   3
         Left            =   240
         Style           =   1  'Graphical
         TabIndex        =   4
         Top             =   1800
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   2
         Left            =   3600
         Style           =   1  'Graphical
         TabIndex        =   3
         Top             =   360
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   1
         Left            =   1920
         Style           =   1  'Graphical
         TabIndex        =   2
         Top             =   360
         Width           =   1575
      End
      Begin VB.CommandButton btnXO 
         Caption         =   &quot; &quot;
         Enabled         =   0   'False
         Height          =   1335
         Index           =   0
         Left            =   240
         Style           =   1  'Graphical
         TabIndex        =   1
         Top             =   360
         Width           =   1575
      End
   End
   Begin VB.Menu mnuGame 
      Caption         =   &quot;Game&quot;
      Begin VB.Menu mnuStatus 
         Caption         =   &quot;Status&quot;
         Begin VB.Menu mnuReady 
            Caption         =   &quot;&amp;Ready&quot;
         End
         Begin VB.Menu mnuOffline 
            Caption         =   &quot;&amp;Offline&quot;
            Checked         =   -1  'True
         End
         Begin VB.Menu mnuBusy 
            Caption         =   &quot;&amp;Busy&quot;
         End
      End
      Begin VB.Menu mnuConfig 
         Caption         =   &quot;&amp;Configure...&quot;
      End
      Begin VB.Menu mnuReset 
         Caption         =   &quot;&amp;Reset/Abort&quot;
      End
      Begin VB.Menu mnuExit 
         Caption         =   &quot;E&amp;xit&quot;
      End
   End
   Begin VB.Menu mnuHelp 
      Caption         =   &quot;&amp;Help&quot;
      Begin VB.Menu mnuAbout 
         Caption         =   &quot;Abo&amp;ut&quot;
      End
   End
End
Attribute VB_Name = &quot;frmTicTacToe&quot;
Attribute VB_GlobalNameSpace = False
Attribute VB_Creatable = False
Attribute VB_PredeclaredId = True
Attribute VB_Exposed = False
Option Explicit

' Naughts and Crosses
' Copyright (C) 2004 Ned Martin www.nedmartin.org
' #40529927
' Coded for a University of Queensland COMP2301 Assignment 5

' global variables
Dim myStatus As String
Dim myName As String
Dim myToken As String
Dim remoteName As String
Dim remoteIP As String
Dim remotePlaysFirst As Boolean
Dim remoteToken As String
Dim myTurn As Boolean
Dim IPUpper As Integer
Dim IPLower As Integer

' holds array of square positions
Dim gamePositions(8) As String

' auto discover
Private Sub btnAutoDiscover_Click()
    ' 130.102.73.32 and 130.102.73.64
    ' clear user list
    lstUsers.Clear
    
    ' send requests to everyone
    Dim IP As Integer
    For IP = IPLower To IPUpper
        sendAutoRecData (&quot;130.102.73.&quot; &amp; IP)
    Next
End Sub

' save settings
Private Sub btnSave_Click()
    ' save settings
    myName = txtName.Text
    
    ' hide the config frame
    frmConfig.Visible = False
    frmConfig.Enabled = False
    
    ' show the autofind frame
    frmAutoFind.Enabled = True
    frmAutoFind.Visible = True
End Sub

' when user list is clicked
Private Sub lstUsers_Click()
    Dim Status As String
    Dim pos As Integer
    
    Status = lstUsers.Text
    
    ' parse item for IP etc.
    'name (status) [IP]
    pos = InStrRev(Status, &quot;(&quot;)
    Status = Mid(Status, pos + 1, 1)
    
    ' enable invite button if status R, else disable on O or B
    If Status = &quot;R&quot; Then
        btnInvite.Enabled = True
    Else
        btnInvite.Enabled = False
    End If
    
End Sub

' invite a player
Private Sub btnInvite_Click()
    ' only if player is ready
    Dim Item As String
    Dim Status As String
    Dim remoteIP As String
    Dim pos As Integer
    
    Item = lstUsers.Text
    
    ' parse item for IP etc.
    'name (status) [IP]
    pos = InStrRev(Item, &quot;(&quot;)
    Status = Mid(Item, pos + 1, 1)
    
    pos = InStrRev(Item, &quot;[&quot;)
    remoteIP = Mid(Item, pos + 1, Len(Item) - pos - 1)
    addStatus (Status &amp; &quot;_&quot; &amp; remoteIP)
    ' invite the user
    If Status = &quot;R&quot; Then
        Call sendGameData(remoteIP, 0, &quot;X&quot;, &quot;R&quot;, 0, &quot;&quot;)
    End If
    'Call sendGameData(&quot;remoteIP&quot;, 0, &quot;X&quot;, &quot;R&quot;, 0, &quot;None&quot;)
End Sub

Private Sub btnXO_Click(Index As Integer)
    Dim Colour As String
    ' if it's my turn
    If myTurn Then
        ' button is unused
        If btnXO(Index).Caption = &quot; &quot; Then
            ' need to only allow clicking valid buttons
            
            ' set button to my token (X or O)
            btnXO(Index).Caption = myToken
        
            'Call sendGameData(&quot;localhost&quot;, &quot;Place&quot;, &quot;X&quot;, &quot;R&quot;, Index, &quot;localhost&quot;, &quot;ned&quot;)
            ' set colours
            If myToken = &quot;X&quot; Then
                Colour = &quot;R&quot;
                btnXO(Index).BackColor = vbRed
            Else
                Colour = &quot;G&quot;
                btnXO(Index).BackColor = vbGreen
            End If
            
            Call addStatus(gamePositions(Index) &amp; &quot; Clicked&quot; &amp; &quot; my token:&quot; &amp; myToken)
            Call sendGameData(remoteIP, 4, myToken, Colour, Index, &quot;&quot;)
        
            ' not my turn anymore
            Call disableButtons
            
            ' check for win
            ' we only check for win when receiving place msg
            ' we also call checkWin if we receive a winning msg
            'Call checkWin
        Else
            addStatus (&quot;Attempt to click used button&quot;)
        End If
    Else
        addStatus (&quot;Attempt to click out of turn&quot;)
    End If
End Sub

' check for win
Private Sub checkWin()
    Dim Counter As Integer
    Dim Button As Integer
    Dim Token As String
    Dim Won As String
    
    Token = myToken
    ' loop twice, first for X, second for O
    For Counter = 0 To 1
        ' check
        ' 0 1 2
        ' 3 4 5
        ' 6 7 8
        For Button = 0 To 8 Step 3
            If btnXO(Button).Caption = Token And btnXO(Button + 1).Caption = Token And btnXO(Button + 2).Caption = Token Then
                btnXO(Button).BackColor = vbYellow
                btnXO(Button + 1).BackColor = vbYellow
                btnXO(Button + 2).BackColor = vbYellow
                ' winner
                Won = Token
            End If
        Next
        ' 0 3 6
        ' 1 4 7
        ' 2 5 8
        For Button = 0 To 2
            If btnXO(Button).Caption = Token And btnXO(Button + 3).Caption = Token And btnXO(Button + 6).Caption = Token Then
                btnXO(Button).BackColor = vbYellow
                btnXO(Button + 3).BackColor = vbYellow
                btnXO(Button + 6).BackColor = vbYellow
                Won = Token
            End If
        Next
        ' 0 4 8
        ' 2 4 6
        If btnXO(0).Caption = Token And btnXO(4).Caption = Token And btnXO(8).Caption = Token Then
            btnXO(0).BackColor = vbYellow
            btnXO(4).BackColor = vbYellow
            btnXO(8).BackColor = vbYellow
            Won = Token
        End If
        ' 2 4 6
        If btnXO(2).Caption = Token And btnXO(4).Caption = Token And btnXO(6).Caption = Token Then
            btnXO(2).BackColor = vbYellow
            btnXO(4).BackColor = vbYellow
            btnXO(6).BackColor = vbYellow
            Won = Token
        End If
        Token = remoteToken
    Next
    If Won = myToken Then
        ' I have won
        ' this means remote sent winning msg
        ' we highlight winning row and pop up msg
        If MsgBox(&quot;Game Over.&quot; &amp; vbCrLf &amp; myName &amp; &quot; was the winner. Click OK to reset&quot;, vbOKOnly) = vbOK Then
            Call reset
        End If
    ElseIf Won = remoteToken Then
        ' remote has won
        ' send winning msg
        '&lt;Winner, From:IP  Winners Name: winner's name>
        Call sendGameData(remoteIP, 7, &quot;&quot;, &quot;&quot;, 0, remoteName)
                
        If MsgBox(&quot;Game Over.&quot; &amp; vbCrLf &amp; remoteName &amp; &quot; was the winner. Click OK to reset&quot;, vbOKOnly) = vbOK Then
            Call reset
        End If

    End If
End Sub

' Form Load
' Set inital state here
Private Sub Form_Load()
    
    ' init winsocks, bind to ports, etc
    'udpAutoRecIN.LocalPort = 6000
    udpAutoRecIN.Bind 6000
    
    ' note we are not setting local port for this udp?
    'udpAutoRecOUT.LocalPort = 6001
    udpAutoRecOUT.RemotePort = 6000
    
    'udpStatusIN.LocalPort = 6010
    udpStatusIN.Bind 6010
    
    'udpStatusOUT.LocalPort = 6011
    udpStatusOUT.RemotePort = 6010
    
    'udpGameIN.LocalPort = 6020
    udpGameIN.Bind 6020
    
    'udpGameOUT.LocalPort = 6021
    udpGameOUT.LocalPort = 6021
    udpGameOUT.RemotePort = 6020
    
    ' populate gamePositions
    gamePositions(0) = &quot;A1&quot;
    gamePositions(1) = &quot;A2&quot;
    gamePositions(2) = &quot;A3&quot;
    gamePositions(3) = &quot;B1&quot;
    gamePositions(4) = &quot;B2&quot;
    gamePositions(5) = &quot;B3&quot;
    gamePositions(6) = &quot;C1&quot;
    gamePositions(7) = &quot;C2&quot;
    gamePositions(8) = &quot;C3&quot;
    
    ' set status to offline and name to default
    myStatus = &quot;Off Line&quot;
    myName = &quot;Ned@&quot; &amp; udpAutoRecIN.LocalIP
    txtName = myName
    
    Call addGameMsg(myName &amp; &quot; Off Line&quot;)
    Call reset
    
    ' make random number
    Randomize
    
    ' fill IP boxes
    IPUpper = 64
    IPLower = 32
    Dim IP As Integer
    For IP = 32 To 64
        cmbIPUpper.AddItem (IP)
        cmbIPLower.AddItem (IP)
    Next
    
End Sub

' show about form
Private Sub mnuAbout_Click()
    frmAbout.Show
End Sub

' enter config mode
Private Sub mnuConfig_Click()
    ' hide the gameframe
    ' cannot call config during a game
    'frmGameFrame.Visible = False
    'frmGameFrame.Enabled = False
    ' hide the autofind frame
    frmAutoFind.Visible = False
    frmAutoFind.Enabled = False
    
    ' show the config frame
    frmConfig.Enabled = True
    frmConfig.Visible = True
End Sub

' set status to Busy
Private Sub mnuBusy_Click()
    myStatus = &quot;Busy&quot;
    mnuBusy.Checked = True
    mnuReady.Checked = False
    mnuOffline.Checked = False
    addGameMsg (myName &amp; &quot; Busy&quot;)
End Sub

' set status to Off Line
Private Sub mnuOffline_Click()
    myStatus = &quot;Off Line&quot;
    mnuOffline.Checked = True
    mnuBusy.Checked = False
    mnuReady.Checked = False
    addGameMsg (myName &amp; &quot; Off Line&quot;)
End Sub

' set status to ready
Private Sub mnuReady_Click()
    myStatus = &quot;Ready&quot;
    mnuReady.Checked = True
    mnuOffline.Checked = False
    mnuBusy.Checked = False
    addGameMsg (myName &amp; &quot; Ready&quot;)
End Sub

' place a token
Private Sub placeToken(Colour As String, Position As String)
    ' place a token of Colour at position tokenPosition
    ' must check if move is valid
    ' if it is not my turn
    If Not myTurn Then
        ' if position is not already taken
        If btnXO(convertPosition(Position)).Caption = &quot; &quot; Then
            Dim BackColour As ColorConstants
            Select Case (Colour)
            Case &quot;R&quot;
                BackColour = vbRed
            Case &quot;G&quot;
                BackColour = vbGreen
            Case &quot;B&quot;
                BackColour = vbBlue
            End Select
            btnXO(convertPosition(Position)).Caption = remoteToken
            btnXO(convertPosition(Position)).BackColor = BackColour
            
            ' it is now my turn so enable buttons
            Call enableButtons
            
            ' check for win
            ' if won then remote host has won
            Call checkWin
        
        Else
        ' attempt to place token in used position
        ' set to blue
            btnXO(convertPosition(Position)).Caption = &quot; &quot;
            btnXO(convertPosition(Position)).BackColor = vbBlue
            ' send illegal move msg
            addStatus (&quot;Attempt to place token in used position&quot;)
            Call sendGameData(remoteIP, 6, remoteToken, Colour, convertPosition(Position), &quot;&quot;)
       End If
    Else
        ' it is my turn
        ' this move is illegal
        ' set to blue
        btnXO(convertPosition(Position)).Caption = &quot; &quot;
        btnXO(convertPosition(Position)).BackColor = vbBlue
        ' sent illegal move msg
        '&lt;Illegal, Token: x Colour: x Position: xx From:IP  Players Name: name >
        Call sendGameData(remoteIP, 6, remoteToken, Colour, convertPosition(Position), &quot;&quot;)
        addStatus (&quot;Attempt by remote to place token out of turn&quot;)
    End If
End Sub

' delete a token
Private Sub deleteToken(Position As String)
    ' delete a token
    btnXO(convertPosition(Position)).Caption = &quot; &quot;
    btnXO(convertPosition(Position)).BackColor = &amp;H8000000F
    
    addStatus (&quot;Delete:&quot; &amp; Position)
    
End Sub

' enable buttons
' called when it is my turn
Private Sub enableButtons()
    ' check what buttons we should enable
    ' currently enabling all buttons
    Dim buttons As Integer
    For buttons = 0 To 8
        If btnXO(buttons).Caption = &quot; &quot; Then
            btnXO(buttons).Enabled = True
        End If
    Next
    myTurn = True
    addGameMsg (&quot;Your Turn - Playing &quot; &amp; remoteName)
End Sub

' disable buttons
' called when it is not my turn
Private Sub disableButtons()
    Dim buttons As Integer
    For buttons = 0 To 8
        btnXO(buttons).Enabled = False
    Next
    myTurn = False
    addGameMsg (&quot;Remote Turn - Playing &quot; &amp; remoteName)
End Sub

' reset
Private Sub reset()
    ' we need to re-enable the finding people stuff etc
    ' hide gameframe
    frmGameFrame.Visible = False
    frmGameFrame.Enabled = False
    ' show autofind frame
    frmAutoFind.Enabled = True
    frmAutoFind.Visible = True
    ' enable config
    mnuConfig.Enabled = True
    
    Dim Button As Integer
    ' init remote as default values
    remoteIP = &quot;localhost&quot;
    remoteName = &quot;remote&quot;
    
    ' disable buttons and reset them
    For Button = 0 To 8
        btnXO(Button).Enabled = False
        btnXO(Button).Caption = &quot; &quot;
        btnXO(Button).BackColor = &amp;H8000000F
    Next
End Sub

' start the game
Private Sub startGame()
    ' we need to disable stuff here
    ' hide autofind frame
    frmAutoFind.Visible = False
    frmAutoFind.Enabled = False
    ' disable config
    mnuConfig.Enabled = False
    ' show gameframe
    frmGameFrame.Enabled = True
    frmGameFrame.Visible = True
    ' set status to busy
    Call mnuBusy_Click
    ' set frame msg
    addGameMsg (&quot;Playing &quot; &amp; remoteName)
    
    If remotePlaysFirst Then
        ' remote player goes first
        myTurn = False
    Else
        ' we go
        ' enable buttons
        Call enableButtons
    End If
End Sub

' reset the game
Private Sub mnuReset_Click()
    Call reset
End Sub

' get data from udpAutoRecIN
Private Sub udpAutoRecIN_DataArrival(ByVal bytesTotal As Long)
    ' &lt;Auto Discovery Request, For:IP>
    Dim msg As String
    udpAutoRecIN.GetData msg
    
    ' add to status
    Call addStatus(&quot;AutoRecIN &lt; &quot; &amp; msg)
    
    ' reply to auto recovery request
    Call sendStatusData(udpAutoRecIN.RemoteHostIP, myStatus, myName)
End Sub

' handle invitation
Private Sub handleInvitation(IP As String, Name As String)
    
    If MsgBox(&quot;Invitation from &quot; &amp; Name &amp; &quot; [&quot; &amp; IP &amp; &quot;]&quot;, vbYesNo) = vbYes Then
        ' we have accepted a game
        ' set IPs
        remoteIP = IP
        remoteName = Name
            
        ' other player assigns a player to go first
            
        ' other player assigns O or X
        ' I assign the other token (in case &quot;As&quot;)
            
        ' send acceptance
        '&lt;Acceptance, From:IP  Players Name: Accepting player's name>  Accept an invitation to play the game.
        Call sendGameData(remoteIP, 1, &quot;&quot;, &quot;&quot;, 0, &quot;&quot;)
    End If
End Sub

' select X or O
Private Sub selectXorO()
    ' must select X or O and send select below
    If MsgBox(&quot;Yes for X, No for O&quot;, vbYesNo) = vbYes Then
        ' we are X
        Call sendGameData(remoteIP, 3, &quot;X&quot;, &quot;&quot;, 0, &quot;&quot;)
        Call addStatus(&quot;Assign: We are X&quot;)
        myToken = &quot;X&quot;
        remoteToken = &quot;O&quot;
    Else
        ' we are O
        Call sendGameData(remoteIP, 3, &quot;O&quot;, &quot;&quot;, 0, &quot;&quot;)
        Call addStatus(&quot;Assign: We are O&quot;)
        myToken = &quot;O&quot;
        remoteToken = &quot;X&quot;
    End If
    Call startGame
End Sub
' get data from udpGameIN
Private Sub udpGameIN_DataArrival(ByVal bytesTotal As Long)
    Dim msg As String
    Dim msgType As String
    
    Dim Colour As String
    Dim Position As String
    Dim Name As String
    Dim IP As String
    
    Dim pos As Integer
    
    ' get game data
    udpGameIN.GetData msg
    
    ' parse commands

    ' get first two chars
    msgType = Left(msg, 2)
    
    Select Case (msgType)
    Case &quot;In&quot;
    ' only listen for invitations if status is ready
        If mnuReady.Checked = True Then
            'In&lt;Invitation, From:IP  Players Name: Inviting player's name>   Invite a remote player to play the game.
            ' accept invitation somehow
            ' pop up a box asking if I want to accept this or not
            ' set remoteIP to this IP
            IP = udpGameIN.RemoteHostIP
            'Call addStatus(&quot;In | remIP = &quot; &amp; remoteIP)
            
            ' set remote name to this name
            pos = InStrRev(msg, &quot;:&quot;)
            Name = Mid(msg, pos + 1, Len(msg) - pos)
            'Call addStatus(&quot;In | remName = &quot; &amp; remoteName)
            
            Call handleInvitation(IP, Name)
        End If
    Case &quot;Ac&quot;
    'Ac&lt;Acceptance, From:IP  Players Name: Accepting player's name>  Accept an invitation to play the game.
        ' set remoteIP to this IP
        remoteIP = udpGameIN.RemoteHostIP
        'Call addStatus(&quot;Ac | remIP = &quot; &amp; remoteIP)
        pos = InStrRev(msg, &quot;:&quot;)
        remoteName = Mid(msg, pos + 2, Len(msg) - pos)
        'Call addStatus(&quot;Ac | remName =&quot; &amp; remoteName &amp; &quot;X&quot;)
        
        ' game is accepted, randomly assign a player to go first
        If Rnd &lt; 0.5 Then
            ' first player is me
            Call sendGameData(remoteIP, 2, &quot;&quot;, &quot;&quot;, 0, &quot;&quot;)
            addStatus (&quot;first player me&quot;)
            ' must now select X or O
            remotePlaysFirst = False
            Call selectXorO
            
        Else
            ' first player is remote
            Call sendGameData(remoteIP, 2, &quot;&quot;, &quot;&quot;, 1, &quot;&quot;)
            addStatus (&quot;first player remote&quot;)
            remotePlaysFirst = True
        End If

    Case &quot;As&quot;
    'As&lt;Assign First Player, From:IP  First Players Name: First players name>  Inviting system must select and assign the first player status.
    ' if I invited, then do this
        ' if this name is my name, then I play first otherwise remote plays first
        pos = InStrRev(msg, &quot;:&quot;)
        Name = Mid(msg, pos + 2, Len(msg) - pos)
        Call addStatus(&quot;Assign called=&quot; &amp; Name &amp; &quot;=&quot; &amp; myName &amp; &quot;=&quot;)
        ' if my name is the assigned name then I play first
        If myName = Name Then
            ' I play first
            remotePlaysFirst = False
            
            Call selectXorO
            
        Else
            remotePlaysFirst = True
            addStatus (&quot;remote plays first&quot;)
        End If
        ' we are now playing a game

    Case &quot;Se&quot;
    'Se&lt;Select, Token: x From:IP  Players Name: name>  Each player selects X or O which is displayed on the remote screen. Token: [X|O]
        If Mid(msg, 16, 1) = &quot;X&quot; Then
            remoteToken = &quot;X&quot;
            myToken = &quot;O&quot;
        Else
            remoteToken = &quot;O&quot;
            myToken = &quot;X&quot;
        End If
        Call addStatus(&quot;My Token:&quot; &amp; myToken &amp; &quot;, Remote Token:&quot; &amp; remoteToken)
        ' game begins
        Call startGame
    Case &quot;Pl&quot;
    'Pl&lt;Place , Token: x Colour: x Position: xx From:IP  Players Name: name > Player places a token on the grid A1 to C3 with Colour [R|G|B]
    ' NOTE space after place
        pos = InStr(msg, &quot;Colour:&quot;)
        Colour = Mid(msg, pos + 8, 1)
        Position = Mid(msg, pos + 20, 2)
        addStatus (&quot;T:&quot; &amp; Colour &amp; &quot;=&quot; &amp; Position)
        Call placeToken(Colour, Position)
        ' Remote has played
    Case &quot;De&quot;
    'De&lt;Delete, Token: x Colour: x Position: xx From:IP  Players Name: name > Reports the removal of an illegal token from a system.
        Colour = Mid(msg, 26, 1)
        Position = Mid(msg, 38, 2)
        addStatus (&quot;T:&quot; &amp; Position &amp; &quot;=&quot; &amp; Colour)
        Call deleteToken(Position)
    Case &quot;Il&quot;
    'Il&lt;Illegal, Token: x Colour: x Position: xx From:IP  Players Name: name > Identifies an illegal token to the remote system.
        Colour = Mid(msg, 27, 1)
        Position = Mid(msg, 39, 2)
        ' place a blue token in this position
        Call placeToken(&quot;B&quot;, Position)
    Case &quot;Wi&quot;
    'Wi&lt;Winner, From:IP  Winners Name: winner's name> Notifies the remote system of game completion.
        pos = InStrRev(msg, &quot;:&quot;)
        Name = Mid(msg, pos + 2, Len(msg) - pos)
        ' remote sends win msg, this means I have won
        ' call checkWin to pop up msg and highlight
        ' not currently using name here, we determine it ourself
        Call checkWin
    End Select
        
    ' add to status
    Call addStatus(&quot;GameIN &lt; &quot; &amp; msg)
End Sub

' get data from udpStatusIN
Private Sub udpStatusIN_DataArrival(ByVal bytesTotal As Long)
' Auto Discovery Reply, Status: Off Line From:130.102.73.33 Players Name: Fred Nirk
' &lt;Auto Discovery Reply, Status: Status From:IP  Players Name: name>
    Dim msg As String
    Dim Status As String
    Dim remoteIP As String
    Dim Name As String
    Dim pos As Integer
    Dim pos2 As Integer
    
    udpStatusIN.GetData msg
    
    ' add to status
    addStatus (&quot;StatusIN &lt; &quot; &amp; msg)
    
    ' parse msg
    'pos = InStr(msg, &quot;:&quot;)
    Status = Mid(msg, 31, 1)
    ' Off Line or Ready or Busy
    
    ' find IP
    pos = InStr(msg, &quot;m:&quot;)
    pos2 = InStrRev(msg, &quot;:&quot;)
    
    remoteIP = Mid(msg, pos + 2, (pos2 - 15) - pos)
    
    Name = Mid(msg, pos2 + 2, Len(msg) - pos2)
    ' add to users list
    
    Call addUser(Status, remoteIP, Name)

End Sub

' send game data
'remoteIP, 0, &quot;X&quot;, &quot;R&quot;, 0, &quot;&quot;
Private Sub sendGameData(remoteHost As String, msgType As Integer, Token As String, Colour As String, Position As Integer, Winner As String)
    Dim data As String
    Dim myIP As String
    myIP = udpGameOUT.LocalIP
    ' &lt;Place , Token: x Colour: x Position: xx From:IP  Players Name: name > Player places a token on the grid A1 to C3 with Colour [R|G|B]

' x, from:myIP, playersName, myName
Select Case (msgType)
Case 0
    '0&lt;Invitation, From:myIP  Players Name: Inviting player's myname>   Invite a remote player to play the game.
    data = &quot;Invitation, From:&quot; &amp; myIP &amp; &quot; Players Name: &quot; &amp; myName
    addStatus (data &amp; &quot; RH:&quot; &amp; remoteHost &amp; &quot; MyIP:&quot; &amp; myIP)
Case 1
    '1&lt;Acceptance, From:myIP  Players Name: Accepting player's myname>  Accept an invitation to play the game.
    data = &quot;Acceptance, From:&quot; &amp; myIP &amp; &quot; Players Name: &quot; &amp; myName
Case 2
    '2&lt;Assign First Player, From:myIP  First Players Name: First players myname?>  Inviting system must select and assign the first player status.
    If Position = 0 Then
        ' first player is me
        data = &quot;Assign First Player, From:&quot; &amp; myIP &amp; &quot; First Players Name: &quot; &amp; myName
        addStatus (&quot;Assign:&quot; &amp; myName)
    Else
        ' first player is remote
        data = &quot;Assign First Player, From:&quot; &amp; myIP &amp; &quot; First Players Name: &quot; &amp; remoteName
        addStatus (&quot;Assign:&quot; &amp; remoteName)
    End If
Case 3
    '3&lt;Select, Token: x From:myIP  Players Name: name>  Each player selects X or O which is displayed on the remote screen. Token: [X|O]
    data = &quot;Select, Token: &quot; &amp; Token &amp; &quot; From: &quot; &amp; myIP &amp; &quot; Players Name: &quot; &amp; myName
Case 4
    '4&lt;Place , Token: x Colour: x Position: xx From:myIP  Players Name: myname > Player places a token on the grid A1 to C3 with Colour [R|G|B]
    addStatus (&quot;P:&quot; &amp; Token &amp; &quot;=&quot; &amp; Colour)
    data = &quot;Place , Token: &quot; &amp; Token &amp; &quot; Colour: &quot; &amp; Colour &amp; &quot; Position: &quot; &amp; gamePositions(Position) &amp; &quot; From:&quot; &amp; myIP &amp; &quot;  Players Name: &quot; &amp; myName
Case 5
    '5&lt;Delete, Token: x Colour: x Position: xx From:myIP  Players Name: myname > Reports the removal of an illegal token from a system.
    data = &quot;Delete, Token: &quot; &amp; Token &amp; &quot; Colour: &quot; &amp; Colour &amp; &quot; Position: &quot; &amp; gamePositions(Position) &amp; &quot; From:&quot; &amp; myIP &amp; &quot;  Players Name: &quot; &amp; myName
Case 6
    '6&lt;Illegal, Token: x Colour: x Position: xx From:myIP  Players Name: myname > Identifies an illegal token to the remote system.
    data = &quot;Illegal, Token: &quot; &amp; Token &amp; &quot; Colour: &quot; &amp; Colour &amp; &quot; Position: &quot; &amp; gamePositions(Position) &amp; &quot; From:&quot; &amp; myIP &amp; &quot;  Players Name: &quot; &amp; myName
Case 7
    '7&lt;Winner, From:IP  Winners Name: winner's name> Notifies the remote system of game completion.
    data = &quot;Winner, From:&quot; &amp; myIP &amp; &quot; Winners Name: &quot; &amp; Winner
End Select

    ' add to status
    ' send data
    udpGameOUT.remoteHost = remoteHost
    'udpGameOUT.remoteHost = &quot;130.102.73.57&quot;
    udpGameOUT.SendData data
    
    Call addStatus(&quot;GameOUT > &quot; &amp; data &amp; &quot; RH:&quot; &amp; remoteHost &amp; &quot;RP:&quot; &amp; udpGameOUT.RemotePort)
 
End Sub

' send autoRec data
Private Sub sendAutoRecData(remoteHost As String)
    Dim data As String
    ' IP range: 130.102.73.32 and 130.102.73.64, ie 32 to 64
    data = &quot;Auto Discovery Request, For:&quot; &amp; udpAutoRecOUT.LocalIP
    ' &lt;Auto Discovery Request, For:IP>
    udpAutoRecOUT.remoteHost = remoteHost
    'udpAutoRecOUT.RemotePort = 6000
    udpAutoRecOUT.SendData data
    
    addStatus (&quot;AutoRecOUT > &quot; &amp; data)
End Sub

' send status data
Private Sub sendStatusData(remoteHost As String, Status As String, Name As String)
    Dim data As String
    
    data = &quot;Auto Discovery Reply, Status: &quot; &amp; Status &amp; &quot; From:&quot; &amp; udpStatusOUT.LocalIP &amp; &quot; Players Name: &quot; &amp; Name
    ' &lt;Auto Discovery Reply, Status: Status From:IP  Players Name: name>
    'Auto Discovery Reply, Status: Ready From:130.102.73.53  Players Name: John Smith

    udpStatusOUT.remoteHost = remoteHost
    udpStatusOUT.SendData data
    
    Call addStatus(&quot;StatusOUT > &quot; &amp; data)
End Sub

' convert token position to array position
Private Function convertPosition(Position As String) As Integer
    Dim Multiple As Integer
    Select Case (Left(Position, 1))
    Case &quot;A&quot;
        Multiple = 0
    Case &quot;B&quot;
        Multiple = 3
    Case &quot;C&quot;
        Multiple = 6
    End Select
    
    Select Case (Right(Position, 1))
    Case &quot;1&quot;
        convertPosition = 0 + Multiple
    Case &quot;2&quot;
        convertPosition = 1 + Multiple
    Case &quot;3&quot;
        convertPosition = 2 + Multiple
    
    End Select
    ' A1 A2 A3
    ' 0  1  2
    ' B1 B2 B3
    ' 3  4  5
    ' C1 C2 C3
    ' 6  7  8
End Function

' form unload
Private Sub Form_Unload(Cancel As Integer)
    ' close ports
    udpAutoRecIN.Close
    udpAutoRecOUT.Close
    udpStatusIN.Close
    udpStatusOUT.Close
    udpGameIN.Close
    udpGameOUT.Close
End Sub

' add item to status
Private Sub addStatus(Item As String)
    ' add item to status list
    lstStatus.AddItem Item
    ' select last item in status list (for scrolling)
    lstStatus.Selected(lstStatus.ListCount - 1) = True
End Sub

' add item to users list
Private Sub addUser(Status As String, remoteIP As String, Name As String)
    ' add item to status list
    Dim userStatus As String
    
    Select Case (Status)
    Case &quot;R&quot;
        userStatus = &quot;Ready&quot;
    Case &quot;O&quot;
        userStatus = &quot;Off Line&quot;
    Case &quot;B&quot;
        userStatus = &quot;Busy&quot;
    End Select
    
    ' this does not currently work
    If Name &lt;> myName Then
        lstUsers.AddItem Name &amp; &quot; (&quot; &amp; userStatus &amp; &quot;) [&quot; &amp; remoteIP &amp; &quot;]&quot;
    End If
    ' select last item in status list (for scrolling)
    'lstStatus.Selected(lstStatus.ListCount - 1) = True
End Sub

' add msg to all frames
Private Sub addGameMsg(Item As String)
    frmGameFrame.Caption = &quot;Naughts and Crosses (&quot; &amp; Item &amp; &quot;)&quot;
    frmAutoFind.Caption = &quot;Naughts and Crosses (&quot; &amp; Item &amp; &quot;)&quot;
    frmConfig.Caption = &quot;Naughts and Crosses (&quot; &amp; Item &amp; &quot;)&quot;
End Sub

' game is won
Private Sub gameWon(Name As String)
    MsgBox (&quot;Winner is&quot; &amp; Name)
End Sub

' exit
Private Sub mnuExit_Click()
    End
End Sub
    </textarea> 
    <br /> 
    Code &copy; Copyright 2004 Ned Martin</p> 
<p>04-Jun-2004</p> 
</body>
</html>