diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java index a6bf39142a82b9a8f07e507e3acb7540398aac60..4e5c65a0b2f97634f6b851f69af48c13eec3e490 100644 --- a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/LennonSimulationProgram.java @@ -11,9 +11,13 @@ import edu.nps.moves.dis7.enumerations.*; import edu.nps.moves.dis7.pdus.*; import edu.nps.moves.dis7.utilities.DisChannel; import edu.nps.moves.dis7.utilities.PduFactory; +import static java.lang.Math.max; +import static java.lang.Math.min; import java.time.LocalDateTime; import java.util.ArrayList; import java.util.List; +import java.util.Random; +import java.util.Scanner; import java.util.logging.Level; import java.util.logging.Logger; @@ -137,7 +141,7 @@ public class LennonSimulationProgram disChannel.getDisNetworkInterface().setVerbose(true); // sending and receipt disChannel.printlnTRACE ("just checking: hasVerboseSending()=" + disChannel.getDisNetworkInterface().hasVerboseSending() + ", hasVerboseReceipt()=" + disChannel.getDisNetworkInterface().hasVerboseReceipt()); - disChannel.getPduRecorder().setVerbose(true); + disChannel.getPduRecorder().setVerbose(false); // TODO confirm whether recorder is explicitly started by programmer (or not) @@ -205,10 +209,10 @@ public class LennonSimulationProgram { try { - final int SIMULATION_MAX_LOOP_COUNT = 10; // set number of turns in the game also avoid infinite loops. + final int SIMULATION_MAX_LOOP_COUNT = 20; // set number of turns in the game; also avoid infinite loops. int simulationLoopCount = 0; // variable, initialized at 0 boolean simulationComplete = false; // sentinel variable as termination condition, are we done yet? - final int NUMBER_MINES = 5; // preset number of mines to be placed + final int NUMBER_MINES = 30; // preset number of mines to be placed // TODO reset Clock Time for today's date and timestamp to zero, providing consistent outputs for each simulation run String timeMessage = "Simulation time " + simulationTimeSeconds + " at LocalDateTime " + LocalDateTime.now(); disChannel.sendCommentPdu(simulationTimeSeconds, DisChannel.COMMENTPDU_TIME, timeMessage); @@ -217,12 +221,36 @@ public class LennonSimulationProgram // =================================================================================================== // loop the simulation while allowed, programmer can set additional conditions to break out and finish + Random random = new Random(); + Scanner scanner = new Scanner(System.in); List<double[]> minefield = new ArrayList<>(); + //set start point at (0,0) + entityStatePdu_1.getEntityLocation().setX(0.0); + entityStatePdu_1.getEntityLocation().setY(0.0); + double[] start = {entityStatePdu_1.getEntityLocation().getX(), entityStatePdu_1.getEntityLocation().getY()}; + + //exit square is somewhere on the middle third of the far right edge of the minefield (space 3-6) + double exitY = random.nextInt(4)+3; + double[] exit = {9, exitY}; + for (int i = 0; i < NUMBER_MINES; i++){ - //double x = Random.nextInt(); - //double[] mine = [] + //random placement of the mines within the 10x10 grid + double x = random.nextInt(10); + double y = random.nextInt(10) ; + double[] mine = {x,y}; + //No mine placed at the start position or on the exit space + if ((mine[0] == start[0] && mine[1] == start[1]) || (mine[0] == exit[0] && mine[1] == exit[1])){ + continue; + } + //add mines to the minefield list + minefield.add(mine); } + + System.out.println("\nYou are in a minefield. The exit is at (" + exit[0] + ", " + exit[1] + + "). \nWhen prompted, use the WASD keys to pick a move. \nCareful, you only have so many moves, and there are plenty of mines!"); + System.out.flush(); + while (simulationLoopCount < SIMULATION_MAX_LOOP_COUNT) // are we done yet? { simulationLoopCount++; // good practice: increment loop counter as first action in that loop @@ -230,35 +258,77 @@ public class LennonSimulationProgram // ============================================================================================= // * your own simulation code starts here! ***************************************************** // ============================================================================================= - + System.out.println("=========================================================================="); + System.out.println("\nMove "+ simulationLoopCount+ " of " + SIMULATION_MAX_LOOP_COUNT); + System.out.println("Current Location: (" + entityStatePdu_1.getEntityLocation().getX()+","+ entityStatePdu_1.getEntityLocation().getY() + "); Exit: (" + exit[0] + ", " + exit[1] + ")."); + System.out.println("Where would you like to move now?" ); // are there any other variables to modify at the beginning of your loop? - - // are your reading any DIS PDUs from the network? check for them here + boolean validMove = false; + String move = null; + while (!validMove){ + move = scanner.nextLine().toUpperCase(); + switch(move){ + case("W") -> { + entityStatePdu_1.getEntityLocation().setY(min(9.0, entityStatePdu_1.getEntityLocation().getY() + 1.0)); + validMove = true; + } + case("A") -> { + entityStatePdu_1.getEntityLocation().setX(max(0.0, entityStatePdu_1.getEntityLocation().getX() - 1.0)); + validMove = true; + } + case("S") -> { + entityStatePdu_1.getEntityLocation().setY(max(0.0, entityStatePdu_1.getEntityLocation().getY() - 1.0)); + validMove = true; + } + case("D") -> { + entityStatePdu_1.getEntityLocation().setX(min(9.0, entityStatePdu_1.getEntityLocation().getX() + 1.0)); + validMove = true; + } + default -> System.out.println("Not a valid move. Try again"); + } + } // compute a track, update an ESPDU, whatever it is that your model is doing... - // Where is my entity? Insert changes in position; this sample only changes X position. - entityStatePdu_1.getEntityLocation().setX(entityStatePdu_1.getEntityLocation().getX() + 1.0); // 1m per timestep + // decide whether to fire, and then update the firePdu. Hmmm, you might want a target to shoot at! // etc. etc. your code goes here for your simulation of interest - // something happens between my simulation entities, la de da de da... - System.out.println ("... My simulation just did something, no really..."); System.out.flush(); // make sure this arrives to user even if other threads somehow become deadlocked // make your reports: narrative code for CommentPdu here (set all to empty strings to avoid sending) - narrativeMessage1 = "MV3500 ExampleSimulationProgram"; + narrativeMessage1 = "MV3500 LennonSimulationProgram"; narrativeMessage2 = "runSimulation() loop " + simulationLoopCount; narrativeMessage3 = ""; // intentionally blank for testing // your loop termination condition goes here - if (simulationLoopCount > MAX_LOOP_COUNT) // for example + + //Check for entity to reach exit + if (entityStatePdu_1.getEntityLocation().getX() == exit[0] && entityStatePdu_1.getEntityLocation().getY() == exit[1]){ + System.out.println("You've escaped the minefield. Good job."); + narrativeMessage3 = "Entity escaped successfully."; + simulationComplete = true; + } + //Check for turn limit reached + else if (simulationLoopCount >= SIMULATION_MAX_LOOP_COUNT) { + System.out.println("You've run out of time. You lose."); + narrativeMessage3 = "Entity ran out of time."; simulationComplete = true; - } + } + + //Check for entity to hit mine + for (double[] mine : minefield){ + if (entityStatePdu_1.getEntityLocation().getX() == mine[0]&& entityStatePdu_1.getEntityLocation().getY() == mine[1]){ + System.out.println("BOOM! you hit a mine. You're dead."); + narrativeMessage3 = "Entity hit a mine and was destroyed."; + simulationComplete = true; + } + } + System.out.println(""); // ============================================================================================= // * your own simulation code is finished here! ************************************************ // ============================================================================================= @@ -266,7 +336,7 @@ public class LennonSimulationProgram // staying synchronized with timestep: wait duration for elapsed time in this loop // Thread.sleep needs a (long) parameter for milliseconds, which are clumsy to use sometimes Thread.sleep((long)(getSimulationTimeStepDuration() * 1000)); // units of seconds * (1000 msec/sec) = milliseconds - System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]"); + //System.out.println ("... [Pausing for " + getSimulationTimeStepDuration() + " seconds]"); // OK now send the status PDUs for this loop, and then continue System.out.println ("... sending PDUs of interest for simulation step " + simulationLoopCount + ", monitor loopback to confirm sent"); diff --git a/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/README.md b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/README.md new file mode 100644 index 0000000000000000000000000000000000000000..c5aadebfdcbc089649b153eb705bb84c6286336b --- /dev/null +++ b/assignments/src/MV3500Cohort2024JulySeptember/homework3/Lennon/README.md @@ -0,0 +1,38 @@ +## Homework 3: Example Simulation Recording using OpenDIS Network Streams + +<!-- Viewable at https://gitlab.nps.edu/Savage/NetworkedGraphicsMV3500/-/blob/master/assignments/src/MV3500Cohort2024JulySeptember/homework3/README.md --> + +### Assignment + +1. Adapt the functionality for [OpenDIS ExampleSimulationProgram](../../../../examples/src/OpenDis7Examples/ExampleSimulationProgram.java), modifying provided code +2. Experiment with the enumeration values that set up each entity and PDU. What works for you? What makes sense for your future work? +3. Adapt or replace the UML diagrams to describe what you have going on. +4. Record, save and replay your result stream using [PduRecorder](https://savage.nps.edu/opendis7-java/javadoc/edu/nps/moves/dis7/utilities/stream/PduRecorder.html) or [Wireshark](https://www.wireshark.org) + * see local [assignments/src/pduLog](../../../pduLog) subdirectory for latest opendis log files + * Coming soon, we will also (again have) [X3D-Edit](https://savage.nps.edu/X3D-Edit) for DIS stream recording/replay +5. Observe good-practice conventions in the [assignments README](../../../README.md) and [current-course README](../README.md) instructions. + +This assignment presents a Problem Prototyping opportunity. +While some minimal functionality is expected, the general outline of +a networking problem and proposed solution holds great interest. +Think of it as warmup preparation for your future work. + +This is also a freeplay opportunity. +You have the option to pick one or more of the provided course example programs +and adapt the source to demonstrate a new client-server handshake protocol of interest. + +Be sure to provide a rationale that justifies why the networking choices you made +(TCP/UDP, unicast/multicast, etc.) are the best for the problem you are addressing. + +You may find that the prior [homework2 README](../homework2/README.md) still provides +helpful details on what specific deliverables are expected in each homework assignment. + +Team efforts are encouraged, though if you choose a team approach be sure to justify why. +This is a good warmup prior to final projects. Have fun with Java networking! + +### Prior Assignment, August 2019 + +In 2019, students worked together on a single project to check wireless multicast connectivity recently deployed on NPS campus. + +See their experimental results in the [NPS Multicast Connectivity Report](../../MV3500Cohort2019JulySeptember/homework3). +