From 07067303b3c95a56f68b7bd14237e40669d932ca Mon Sep 17 00:00:00 2001
From: tjsus <tjsus@172.20.148.137>
Date: Thu, 29 Aug 2024 11:10:05 -0700
Subject: [PATCH] Assignment 3 code added.

---
 .../ExampleSimulationProgramBattleShip.java   | 241 ++++++++++++++++++
 1 file changed, 241 insertions(+)
 create mode 100644 assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java

diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java
new file mode 100644
index 0000000000..dd9344676f
--- /dev/null
+++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Smith/ExampleSimulationProgramBattleShip.java
@@ -0,0 +1,241 @@
+package MV3500Cohort2024JulySeptember.homework3.Smith;
+
+import edu.nps.moves.dis7.pdus.*;
+import edu.nps.moves.dis7.utilities.DisChannel;
+import edu.nps.moves.dis7.utilities.PduFactory;
+import java.util.logging.Level;
+import java.util.logging.Logger;
+
+/** The purpose of this inheritable class is to provide an easily modifiable 
+ *  example simulation program that includes DIS-capable entities performing 
+ *  tasks of interest, and then reporting activity via PDUs to the network.
+ *  Default program initialization includes PDU recording turned on by default.
+ */
+public class ExampleSimulationProgramBattleShip {
+
+    // Constants for the Battleship game
+    private static final int GRID_SIZE = 10; // 10x10 grid for Battleship
+    private static final int MAX_TURNS = 100; // Limit turns to avoid infinite games
+
+    // Grids for each player
+    private char[][] player1Grid = new char[GRID_SIZE][GRID_SIZE];
+    private char[][] player2Grid = new char[GRID_SIZE][GRID_SIZE];
+
+    // To track whose turn it is
+    private boolean isPlayer1Turn = true;
+
+    // Ship positions (simple example positions for each player's ships)
+    private final int[][] player1Ships = {{0, 0}, {0, 1}, {0, 2}}; // Positions for player 1's ships
+    private final int[][] player2Ships = {{5, 5}, {5, 6}, {5, 7}}; // Positions for player 2's ships
+
+    // DIS utilities
+    private String descriptor = this.getClass().getSimpleName();
+    protected DisChannel disChannel;
+    protected PduFactory pduFactory;
+    protected FirePdu firePduPlayer1;
+    protected FirePdu firePduPlayer2;
+    protected MunitionDescriptor munitionDescriptor1 = new MunitionDescriptor();
+
+    // Simulation time settings
+    private double simulationTimeStepDuration = 1.0; // seconds
+    private double simulationTimeSeconds = 0.0;
+
+    // Tracking indices for Player 1's systematic search
+    private int player1SearchRow = 0;
+    private int player1SearchCol = 0;
+
+    /**
+     * Constructor to create an instance of this class.
+     * Design goal: additional built-in initialization conveniences can go here
+     * to keep your efforts focused on the runSimulation() method.
+     */
+    public ExampleSimulationProgramBattleShip() {
+        initialize();
+    }
+
+    /** 
+     * Initialize the simulation program, setting up the DIS channel, 
+     * PDUs, and the Battleship game grids. 
+     */
+    private void initialize() {
+        initializeDisChannel();
+        initializeSimulationEntities();
+        setupGrids();
+        disChannel.join();
+    }
+
+    /** 
+     * Initialize the DIS channel for communication, setting verbose output 
+     * for debugging and creating the PduFactory.
+     */
+    private void initializeDisChannel() {
+        disChannel = new DisChannel();
+        pduFactory = disChannel.getPduFactory();
+        disChannel.setDescriptor(this.getClass().getSimpleName());
+        disChannel.setUpNetworkInterface();
+        disChannel.getDisNetworkInterface().setVerbose(true); // sending and receipt
+        disChannel.getPduRecorder().setVerbose(true);
+    }
+
+    /**
+     * Initialize simulation entities by creating PDUs for firing events.
+     */
+    private void initializeSimulationEntities() {
+        firePduPlayer1 = pduFactory.makeFirePdu();
+        firePduPlayer2 = pduFactory.makeFirePdu();
+    }
+
+    /**
+     * Set up the game grids for each player, marking empty water and ship positions.
+     */
+    private void setupGrids() {
+        // Initialize grids with empty water '~'
+        for (int i = 0; i < GRID_SIZE; i++) {
+            for (int j = 0; j < GRID_SIZE; j++) {
+                player1Grid[i][j] = '~';
+                player2Grid[i][j] = '~';
+            }
+        }
+
+        // Place ships on the grids ('P' denotes a ship)
+        for (int[] ship : player1Ships) {
+            player1Grid[ship[0]][ship[1]] = 'P';
+        }
+        for (int[] ship : player2Ships) {
+            player2Grid[ship[0]][ship[1]] = 'P';
+        }
+    }
+
+    /**
+     * This runSimulationLoops() method is for you, a customizable programmer-modifiable
+     * code block for defining and running a new simulation of interest.
+     */
+    public void runSimulationLoops() {
+        int turnCount = 0;
+        while (turnCount < MAX_TURNS) {
+            if (isPlayer1Turn) {
+                // Player 1 systematically searches Player 2's grid
+                int[] target = selectNextTargetForPlayer1();
+                handleFire(firePduPlayer1, player2Grid, target, "Player 1");
+            } else {
+                // Player 2 fires at Player 1 randomly
+                int[] target = selectRandomTarget();
+                handleFire(firePduPlayer2, player1Grid, target, "Player 2");
+            }
+
+            // Switch turns and increment turn counter
+            isPlayer1Turn = !isPlayer1Turn;
+            turnCount++;
+
+            // Check for win conditions
+            if (checkWinCondition(player1Grid)) {
+                System.out.println("Player 2 wins!");
+                break;
+            } else if (checkWinCondition(player2Grid)) {
+                System.out.println("Player 1 wins!");
+                break;
+            }
+
+            // Wait for the next simulation step
+            try {
+                Thread.sleep((long) (simulationTimeStepDuration * 1000)); // units of seconds * (1000 msec/sec) = milliseconds
+            } catch (InterruptedException iex) {
+                Logger.getLogger(ExampleSimulationProgram.class.getSimpleName()).log(Level.SEVERE, null, iex);
+            }
+
+            // Increment simulation time
+            simulationTimeSeconds += simulationTimeStepDuration;
+        }
+    }
+
+    /**
+     * Systematically select the next target for Player 1 in a row-by-row manner.
+     * @return the coordinates of the next target cell.
+     */
+    private int[] selectNextTargetForPlayer1() {
+        // Systematically select the next target in a row-by-row manner
+        int[] target = {player1SearchRow, player1SearchCol};
+
+        // Move to the next column
+        player1SearchCol++;
+        // If end of row is reached, move to the next row and reset column
+        if (player1SearchCol >= GRID_SIZE) {
+            player1SearchCol = 0;
+            player1SearchRow++;
+        }
+
+        // Ensure search stays within grid bounds
+        if (player1SearchRow >= GRID_SIZE) {
+            player1SearchRow = 0; // Reset search if bounds are exceeded
+        }
+
+        return target;
+    }
+
+    /**
+     * Randomly select a target on the grid for Player 2's turn.
+     * @return the coordinates of the randomly selected target cell.
+     */
+    private int[] selectRandomTarget() {
+        int x = (int) (Math.random() * GRID_SIZE);
+        int y = (int) (Math.random() * GRID_SIZE);
+        return new int[]{x, y};
+    }
+
+    /**
+     * Handles the firing action, checking if the target is a hit or miss, 
+     * updating the grid, and sending the appropriate PDU.
+     * @param firePdu the FirePdu object to use for the shot.
+     * @param grid the grid of the player being fired at.
+     * @param target the coordinates of the target cell.
+     * @param player the name of the player firing the shot.
+     */
+    private void handleFire(FirePdu firePdu, char[][] grid, int[] target, String player) {
+        int x = target[0];
+        int y = target[1];
+
+        // Fire at the target position
+        firePdu.setDescriptor(munitionDescriptor1).setRange(100.0f); // Example fire properties
+
+        if (grid[x][y] == 'P') {
+            grid[x][y] = 'H'; // Hit
+            System.out.println(player + " hits a ship at (" + x + ", " + y + ")!");
+        } else if (grid[x][y] == '~') {
+            grid[x][y] = 'M'; // Miss
+            System.out.println(player + " misses at (" + x + ", " + y + ").");
+        } else {
+            System.out.println(player + " fires at (" + x + ", " + y + ") but it's already hit/missed.");
+        }
+
+        // Send the fire PDU to reflect the shot
+        disChannel.sendSinglePdu(simulationTimeSeconds, firePdu);
+    }
+
+    /**
+     * Checks the win condition by verifying if all ships on the grid have been hit.
+     * @param grid the grid to check.
+     * @return true if all ships are hit; false otherwise.
+     */
+    private boolean checkWinCondition(char[][] grid) {
+        // Check if all ships have been hit
+        for (int i = 0; i < GRID_SIZE; i++) {
+            for (int j = 0; j < GRID_SIZE; j++) {
+                if (grid[i][j] == 'P') {
+                    return false; // There are still ships left
+                }
+            }
+        }
+        return true; // All ships have been hit
+    }
+
+    /**
+     * Main method is first executed when a program instance is loaded.
+     * @param args command-line parameters: network address and port.
+     *    Command-line arguments are an array of optional String parameters that are passed from execution environment during invocation
+     */
+    public static void main(String[] args) {
+        ExampleSimulationProgramBattleShip game = new ExampleSimulationProgramBattleShip();
+        game.runSimulationLoops();
+        System.out.println("Game Over");
+    }
+}
-- 
GitLab