+ // Everything in objects built from this class represent the critical game state\r
+ public class GameState\r
+ {\r
+ public long frameNumber;\r
+\r
+ private long checksum;\r
+ public long Checksum { get { return checksum; } }\r
+\r
+ public bool[] isGameOver;\r
+ public bool[] isTerminated;\r
+\r
+ // Since this is not a game, I'll just keep track of the user inputs as the game state.\r
+\r
+ public int[] mouseLocationX;\r
+ public int[] mouseLocationY;\r
+ public bool[] mouseButton;\r
+ public List<Keys>[] keysDown;\r
+ public int[] keypressCount;\r
+\r
+ public long elapsedTime;\r
+\r
+ /* Constructor */\r
+ public GameState()\r
+ {\r
+ frameNumber = 0;\r
+ checksum = 0;\r
+\r
+ isGameOver = new bool[4];\r
+ isTerminated = new bool[4];\r
+\r
+ mouseLocationX = new int[4];\r
+ mouseLocationY = new int[4];\r
+ mouseButton = new bool[4];\r
+ keysDown = new List<Keys>[4];\r
+ for (int i = 0; i < 4; i++)\r
+ keysDown[i] = new List<Keys>();\r
+ keypressCount = new int[4];\r
+\r
+ elapsedTime = 0;\r
+\r
+ checksum = 0;\r
+ }\r
+\r
+ /* The game engine! */\r
+ public void advanceFrame(NextInputs inputs, long milliseconds)\r
+ {\r
+ // Advance frame number\r
+ frameNumber++;\r
+\r
+ // Advance game - for the test harness, just record statistics and input states.\r
+\r
+ elapsedTime += milliseconds;\r
+\r
+ for (int player = 0; player < 4; player++)\r
+ {\r
+\r
+ //if (isGameOver[player])\r
+ // continue;\r
+\r
+ if (inputs.mousePressedChanged[player])\r
+ mouseButton[player] = inputs.mousePressed[player];\r
+\r
+ if (inputs.mouseLocationChanged[player])\r
+ {\r
+ mouseLocationX[player] = inputs.mouseLocationX[player];\r
+ mouseLocationY[player] = inputs.mouseLocationY[player];\r
+ }\r
+\r
+ foreach (Keys k in inputs.keysPressed[player])\r
+ if (!keysDown[player].Contains(k))\r
+ {\r
+ keysDown[player].Add(k);\r
+ keypressCount[player]++;\r
+ }\r
+\r
+ foreach (Keys k in inputs.keysReleased[player])\r
+ keysDown[player].Remove(k);\r
+\r
+ // If the mouse was pressed for a certain player, activate game over or terminated states as appropriate\r
+\r
+ if (inputs.mousePressed[player])\r
+ for (int p = 0; p < 4; p++)\r
+ {\r
+ int x = 200 * p + 10;\r
+ int y = 220;\r
+\r
+ if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&\r
+ mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)\r
+ {\r
+ isGameOver[p] = true;\r
+ }\r
+ y += 25;\r
+ if (mouseLocationX[player] >= x && mouseLocationY[player] >= y &&\r
+ mouseLocationX[player] < x + 25 && mouseLocationY[player] < y + 25)\r
+ {\r
+ isGameOver[p] = true;\r
+ isTerminated[p] = true;\r
+ }\r
+ }\r
+ \r
+\r
+ }\r
+\r
+ // Advance the checksum.\r
+\r
+ computeChecksum();\r
+\r
+ }\r
+\r
+ /* Just hash the values */\r
+ private long computeChecksum()\r
+ {\r
+ checksum += frameNumber;\r
+ for (int i = 0; i < 4; i++)\r
+ {\r
+ checksum = checksum + keypressCount[i];\r
+ checksum = checksum * 3 + (isGameOver[i] ? 1 : 2);\r
+ checksum = checksum * 3 + (isTerminated[i] ? 1 : 2);\r
+ foreach (Keys k in keysDown[i])\r
+ checksum = checksum * 257 + (int)k;\r
+ checksum = checksum * 25789 + mouseLocationX[i] * 259 + mouseLocationY[i] + 375;\r
+ checksum = checksum * 3 + (mouseButton[i] ? 1 : 2);\r
+\r
+ }\r
+ checksum += elapsedTime;\r
+\r
+ return checksum;\r
+ }\r
+ }\r