--- /dev/null
+//#define DisplayRegions\r
+#define DisplayFinalRegions\r
+\r
+using System;\r
+using System.Collections.Generic;\r
+using System.Linq;\r
+using System.Text;\r
+using Microsoft.Xna.Framework;\r
+\r
+namespace CarFire\r
+{\r
+ /// <summary>\r
+ /// AI infomation to be used by monsters. The map is split into deferent regions, \r
+ /// each region is then linked to other regions that it can see. \r
+ /// </summary>\r
+ public class AI\r
+ {\r
+ Game game;\r
+ int[,] regions;\r
+ List<Region> regionList;\r
+ int regionCnt;\r
+\r
+ public AI(Game _game)\r
+ {\r
+ game = _game;\r
+ regions = new int[game.State.Map.Width, game.State.Map.Height];\r
+ regionList = new List<Region>();\r
+ regionCnt = 0;\r
+\r
+ //set all square to -1 to show they have not been assigned to a region yet.\r
+ for (int y = 0; y < regions.GetLength(1); y++)\r
+ {\r
+ for (int x = 0; x < regions.GetLength(0); x++)\r
+ {\r
+ regions[x, y] = -1;\r
+ }\r
+ }\r
+ regionList.Add(new Region(0)); //region 0 will represent all walls and things like it.\r
+ \r
+ #if DisplayRegions\r
+ printRegions();\r
+ #endif\r
+\r
+ setUpRegions();\r
+ foreach (Region r in regionList)\r
+ r.CalcCenter();\r
+ \r
+\r
+ #if (DisplayRegions || DisplayFinalRegions)\r
+ printRegions();\r
+ #endif\r
+ linkRegions();\r
+ }\r
+\r
+ /// <summary>\r
+ /// check to see if a spot on the map is visible from another spot\r
+ /// </summary>\r
+ /// <param name="curX">Current X position</param>\r
+ /// <param name="curY">Current Y position</param>\r
+ /// <param name="testX">X location to test</param>\r
+ /// <param name="testY">Y location to test</param>\r
+ public bool spaceVisible(int curX, int curY, int testX, int testY)\r
+ {\r
+ return regionList[regions[curX, curY]].VisibleRegions.Contains(regions[testX, testY]);\r
+ }\r
+\r
+ //find regions in map. these regions will be large groups of connected grid squares.\r
+ public int setUpRegions()\r
+ {\r
+ \r
+ //find open space that has not been assigned yet\r
+ for (int y = 0; y < regions.GetLength(1); y++)\r
+ {\r
+ for (int x = 0; x < regions.GetLength(0); x++)\r
+ {\r
+ if (regions[x, y] == -1 && spaceOpen(x, y))\r
+ {\r
+ regionCnt++;\r
+ regionList.Add(new Region(regionCnt));\r
+ createRegion(x, y);\r
+ }\r
+ else if (regions[x, y] == -1) //grid square is a wall\r
+ {\r
+ regions[x, y] = 0;\r
+ }\r
+ else //grid already assigned to region, do nothing\r
+ {\r
+ }\r
+ }\r
+ }\r
+\r
+ return regionList.Count;\r
+ }\r
+\r
+ #region Private Methods\r
+ private void createRegion(int x, int y)\r
+ {\r
+ regionList[regionCnt].Left = x;\r
+ regionList[regionCnt].Top = y;\r
+\r
+ for (int rY = 0; rY < 5 && y + rY < regions.GetLength(1); rY++) // creates a region as large as possible up to 5x5\r
+ {\r
+ for (int rX = 0; rX < 5 && x + rX < regions.GetLength(0); rX++)\r
+ {\r
+ if (regions[x + rX, y + rY] == -1 && spaceOpen(x + rX, y + rY))\r
+ {\r
+ regions[x + rX, y + rY] = regionCnt;\r
+ }\r
+ else if (regions[x + rX, y + rY] == -1) //grid square is a wall\r
+ {\r
+ regions[x + rX, y + rY] = 0;\r
+ regionList[regionCnt].Right = x + rX;\r
+ regionList[regionCnt].Bottom = y + rY;\r
+ #if DisplayRegions\r
+ printRegions();\r
+ #endif\r
+ if (!spaceOpen(x + rX + 1, y + rY)) // hit horizontal wall end region\r
+ if(x + rX >= regions.GetLength(0)-1)\r
+ break;\r
+ else\r
+ return;\r
+ else\r
+ break;\r
+\r
+ //todo: figure out how to get region to stop being created when \r
+ }\r
+ else //grid already assigned to region, do nothing\r
+ {\r
+ }\r
+ regionList[regionCnt].Right = x + rX;\r
+ }\r
+ \r
+ regionList[regionCnt].Bottom = y + rY;\r
+ }\r
+ #if DisplayRegions\r
+ printRegions();\r
+ #endif\r
+ return;\r
+ }\r
+ private bool spaceOpen(int x, int y)\r
+ {\r
+ if (x >= regions.GetLength(0)) return false;\r
+ if (y >= regions.GetLength(1)) return false;\r
+ return !game.State.Map.IsWall(x, y);\r
+ }\r
+ //TODO: scans out from each corner, some areas are still missed\r
+ private void linkRegions()\r
+ {\r
+ foreach (Region r in regionList)\r
+ {\r
+ if (r.Label == 0)\r
+ continue;\r
+ //scan from center\r
+\r
+ //scan from corners\r
+ //top Left\r
+ int x = r.Left;\r
+ int y = r.Top;\r
+ //scan up\r
+ for (int t = 1; spaceOpen(x, y - t); t++)\r
+ {\r
+ if ( regions[x, y] != regions[x, y - t] )\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x, y - t]);\r
+ }\r
+ }\r
+ //scan left\r
+ for (int t = 1; spaceOpen(x - t, y); t++)\r
+ {\r
+ if ( regions[x, y] != regions[x - t, y] )\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x - t, y]);\r
+ }\r
+ }\r
+ //scan diag\r
+ for (int t = 1; spaceOpen(x - t, y - t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x - t, y - t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x - t, y - t]);\r
+ }\r
+ }\r
+\r
+ //top Right\r
+ x = r.Right;\r
+ y = r.Top;\r
+ //scan up\r
+ for (int t = 1; spaceOpen(x, y - t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x, y - t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x, y - t]);\r
+ }\r
+ }\r
+ //scan Right\r
+ for (int t = 1; spaceOpen(x + t, y); t++)\r
+ {\r
+ if (regions[x, y] != regions[x + t, y])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x + t, y]);\r
+ }\r
+ }\r
+ //scan diag\r
+ for (int t = 1; spaceOpen(x + t, y - t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x + t, y - t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x + t, y - t]);\r
+ }\r
+ }\r
+\r
+ //bottom Right\r
+ x = r.Right;\r
+ y = r.Bottom;\r
+ //scan down\r
+ for (int t = 1; spaceOpen(x, y + t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x, y + t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x, y + t]);\r
+ }\r
+ }\r
+ //scan Right\r
+ for (int t = 1; spaceOpen(x + t, y); t++)\r
+ {\r
+ if (regions[x, y] != regions[x + t, y])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x + t, y]);\r
+ }\r
+ }\r
+ //scan diag\r
+ for (int t = 1; spaceOpen(x + t, y + t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x + t, y + t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x + t, y + t]);\r
+ }\r
+ }\r
+\r
+ //bottom left\r
+ x = r.Left;\r
+ y = r.Bottom;\r
+ //scan down\r
+ for (int t = 1; spaceOpen(x, y + t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x, y + t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x, y + t]);\r
+ }\r
+ }\r
+ //scan Left\r
+ for (int t = 1; spaceOpen(x - t, y); t++)\r
+ {\r
+ if (regions[x, y] != regions[x - t, y])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x - t, y]);\r
+ }\r
+ }\r
+ //scan diag\r
+ for (int t = 1; spaceOpen(x - t, y + t); t++)\r
+ {\r
+ if (regions[x, y] != regions[x - t, y + t])\r
+ {\r
+ regionList[regions[x, y]].AddVisible(regions[x - t, y + t]);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ #endregion\r
+ //for testing print the region grid to the console\r
+ public void printRegions()\r
+ {\r
+ Console.WriteLine("--Printing Regions--");\r
+ for (int y = 0; y < regions.GetLength(1); y++)\r
+ {\r
+ for (int x = 0; x < regions.GetLength(0); x++)\r
+ {\r
+ Console.Write(regions[x, y]);\r
+ }\r
+ Console.WriteLine("");\r
+ }\r
+ }\r
+ }\r
+\r
+ /// <summary>\r
+ /// a chuck of the map that is at most 5x5 used to determine line of sight\r
+ /// </summary>\r
+ public class Region\r
+ {\r
+ List<int> visibleRegions; //other regions that are in this regions sight\r
+ int label;\r
+ int centerX;\r
+ int centerY;\r
+\r
+ //edges\r
+ int left, right, top, bottom; \r
+\r
+ public Region(int _label)\r
+ {\r
+ label = _label;\r
+ visibleRegions = new List<int>();\r
+ }\r
+\r
+ public void AddVisible(int region)\r
+ {\r
+ if(!visibleRegions.Contains(region))\r
+ visibleRegions.Add(region);\r
+ }\r
+\r
+ public void CalcCenter()\r
+ {\r
+ if (right != left) centerX = right + (right - left) / 2;\r
+ else centerX = right;\r
+ if (top != bottom) centerY = top + (bottom - top) / 2;\r
+ else centerY = top;\r
+ }\r
+\r
+ public int Left \r
+ { \r
+ get { return left; } \r
+ set { left = value; }\r
+ }\r
+ public int Right\r
+ {\r
+ get { return right; }\r
+ set { right = value; }\r
+ }\r
+ public int Top\r
+ {\r
+ get { return top; }\r
+ set { top = value; }\r
+ }\r
+ public int Bottom\r
+ {\r
+ get { return bottom; }\r
+ set { bottom = value; }\r
+ }\r
+\r
+ public Point Center { get { return new Point(centerX, centerY); } }\r
+ public int Label { get { return label; } }\r
+\r
+ public List<int> VisibleRegions { get { return visibleRegions; } }\r
+\r
+\r
+ }\r
+}\r