/* * Grid.cs * Authors: Mike Dapiran * Copyright (c) 2007-2008 Cornell University This program is free software; you can redistribute it and/or modify it under the terms of the GNU General Public License as published by the Free Software Foundation; either version 2 of the License, or (at your option) any later version. This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for more details. You should have received a copy of the GNU General Public License along with this program; if not, write to the Free Software Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA. */ using System; using System.Collections.Generic; using ColonySim.Structures; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; using Microsoft.Xna.Framework.Graphics; using Util; using tAC_Engine.Graphics.Entities; namespace ColonySim { /// /// Represents a Grid that maps structures to two dimensional coordinates /// in space. /// class Grid { #region Constants // The base chance for a carrier to spawn from a structure private const double CHANCE_CARRIER_SPAWN = 1; #endregion #region Pools // The maximum number of road carriers private const int MAX_ROAD_CARRIERS = 100; // The maximum number of tube carriers private const int MAX_TUBE_CARRIERS = 100; // The number of road carriers to add per residential structure private const int ROAD_CARRIERS_PER_RES = 2; // The number of tube carriers to add per commercial structure private const int TUBE_CARRIERS_PER_COM = 2; /// /// The pool of road carriers to have access to /// private readonly Stack mRoadCarrierPool = new Stack(); /// /// The pool of tube carriers to have access to /// private readonly Stack mTubeCarrierPool = new Stack(); #endregion #region Fields // Structure array for the grid private readonly Structure[,] mReferenceGrid; private Resource[,] mResourceGrid; private readonly bool[,] mBuildAreaGrid; // List of the carriers that the grid has private readonly List mCarrierList; private readonly List mNewCarriers; // The internal status value for the Colony, used by the Grid private ColonySimStatusInformation mGridStatus = new ColonySimStatusInformation(); // The content manager used for loading in content private readonly ContentManager mContent; // The model used for representing the grid private EntityModel mGridModel; // Whether or not the build area should be drawn private bool mDrawBuildArea; /// /// The number of polygons being drawn /// internal int numPolygons; /// /// The lists of structures by type in the grid. /// List mMiningPlants = new List(); List mResidentials = new List(); List mFactories = new List(); List mCommercials = new List(); List mEntertainments = new List(); List mCommandCenters = new List(); #endregion #region Properties /// /// Gets/Sets the grid model /// public EntityModel GridModel { get { return mGridModel; } set { mGridModel = value; mGridModel.Model.Meshes[0].Effects[0].Parameters["GridDimensions"].SetValue(new Vector2(mReferenceGrid.GetLength(0), mReferenceGrid.GetLength(1))); } } /// /// Gets/Sets the draw build area /// public bool DrawBuildArea { get { return mDrawBuildArea; } set { mDrawBuildArea = value; } } /// /// Gets/Sets the status information for the grid, which is /// exposed to be exploited by the ColonySim. /// public ColonySimStatusInformation StatusInfo { get { return mGridStatus; } set { mGridStatus = value; } } /// /// Gets the bounds of the grid. /// public Rectangle GridBounds { get { return new Rectangle( 0, 0, mReferenceGrid.GetLength(0), mReferenceGrid.GetLength(1)); } } /// /// Gets the Vector position at the grid's center. /// public Vector2 GridCenter { get { return new Vector2(mReferenceGrid.GetLength(0) / 2f, mReferenceGrid.GetLength(1) / 2f); } } /// /// Gets a list of the current structures in the Grid. /// public List GridStructures { get { List returnList = new List(); foreach (Structure s in mReferenceGrid) { if (s != null && !returnList.Contains(s)) returnList.Add(s); } return returnList; } } /// /// Gets a copy of the list of carriers that the Grid has. /// public List GridCarriers { get { return mCarrierList; } } /// /// Gets only the carriers which are the new list. When it returns, /// it clears the list of the current carriers available. /// public Carrier[] NewCarriers { get { Carrier[] retVal = mNewCarriers.ToArray(); mNewCarriers.Clear(); return retVal; } } /// /// Gets the number of player placed structures. /// public int PlayerStructures { get { // Set the return value int retVal = 0; // Go through all of the structures foreach (Structure s in mReferenceGrid) { // If it's a tube or hub if (s is Tube /*|| s is Hub*/) { // Increment the counter retVal++; } } // Return return retVal; } } /// /// Access to the grid at the given grid location. /// public Structure this[Point p] { get { return GridContents(p); } set { if (value != null) { AddStructure(value, p); } else { RemoveStructure(p); } } } /// /// Access to the grid at the given grid location. /// public Structure this[int x, int y] { get { return GridContents(new Point(x, y)); } set { if (value != null) { AddStructure(value, new Point(x, y)); } else { RemoveStructure(new Point(x, y)); } } } #endregion #region Lighting Modifiers /// /// Raises the specular lighting intensity /// public void RaiseSpecularIntensity() { foreach (Structure s in mReferenceGrid) { if (s is TransportStructure) { s.SpecularIntensity += .05f; s.ReloadModel(); } } } /// /// Lowers the specular lighting intensity /// public void LowerSpecularIntensity() { foreach (Structure s in mReferenceGrid) { if (s is TransportStructure) { s.SpecularIntensity -= .05f; s.ReloadModel(); } } } /// /// Raises the specular lighting power /// public void RaiseSpecularPower() { foreach (Structure s in mReferenceGrid) { if (s is TransportStructure) { s.SpecularPower += .05f; s.ReloadModel(); } } } /// /// Lowers the specular lighting power /// public void LowerSpecularPower() { foreach (Structure s in mReferenceGrid) { if (s is TransportStructure) { s.SpecularPower -= .05f; s.ReloadModel(); } } } #endregion #region Constructs /// /// Base constructor /// /// The width of the grid. /// The height of the grid. /// The content manager to use. /// The respource grid spawner public Grid(int pWidth, int pHeight, ContentManager pContent, ResourceSpawnNumbers pResSpawnNumbers) { // Initialize the grid and list mReferenceGrid = new Structure[pWidth, pHeight]; mResourceGrid = pResSpawnNumbers.GenerateResourceGrid(pWidth, pHeight); mBuildAreaGrid = new bool[pWidth, pHeight]; mCarrierList = new List(); mNewCarriers = new List(); mContent = pContent; //// Generate the carrier pools //for (int i = 0; i < MAX_ROAD_CARRIERS; i++) //{ // mRoadCarrierPool.Push(new RoadCarrier(false, mContent, // @"Models\Vehicle_No_Guns_Mod", @"Textures\BluePixel", this)); //} //for (int i = 0; i < MAX_TUBE_CARRIERS; i++) //{ // mTubeCarrierPool.Push(new TubeCarrier(false, ResourceCode.A0, // mContent, @"Models\Vehicle_No_Guns_Mod", @"Textures\GreenPixel", this)); //} } /// /// Base constructor /// /// The width of the grid. /// The height of the grid. /// The content manager to use. public Grid(int pWidth, int pHeight, ContentManager pContent) : this(pWidth, pHeight, pContent, new ResourceSpawnNumbers()) { } #endregion #region Getters /// /// Gets the list of resource models /// /// Reference to the current content manager /// The list of resource models public List GetResourceModels(ContentManager pContent) { List returnList = new List(); for (int i = 0; i < mResourceGrid.GetLength(0); i++) { for (int j = 0; j < mResourceGrid.GetLength(1); j++) { if (mResourceGrid[i, j] != null) { switch (mResourceGrid[i, j].ResourceCode) { case ResourceCode.A1: { Asteroid tempAst = new Asteroid(new Vector2(i + .5f, j + .5f), pContent); tempAst.ColorToAdd = Color.Red; returnList.Add(tempAst); } break; case ResourceCode.B1: returnList.Add(new Asteroid(new Vector2(i + .5f, j + .5f), pContent)); break; case ResourceCode.B0: { Asteroid tempAst = new Asteroid(new Vector2(i + .5f, j + .5f), pContent); tempAst.ColorToAdd = Color.Blue; returnList.Add(tempAst); } break; case ResourceCode.C0: { Asteroid tempAst = new Asteroid(new Vector2(i + .5f, j + .5f), pContent); tempAst.ColorToAdd = Color.Green; returnList.Add(tempAst); } break; case ResourceCode.A0: { Asteroid tempAst = new Asteroid(new Vector2(i + .5f, j + .5f), pContent); tempAst.ColorToAdd = Color.Yellow; returnList.Add(tempAst); } break; } } } } return returnList; } /// /// Gets all the structures within the current game grid /// /// The list of structures within the current game grid public List GetAllStructures() { List returnList = new List(); foreach (Structure s in mReferenceGrid) { if (s != null && !returnList.Contains(s)) { returnList.Add(s); } } return returnList; } ///// ///// Get a list of all structures directly adjacent to the given structure. ///// //[Obsolete("Only correct for 1x1 buildings")] //private List Neighbors(GridComponent pStruct) //{ // Point pLocation = pStruct.GridPosition; // Point newPoint; // Structure neighbor; // List ret = new List(); // newPoint = new Point(pLocation.X + 1, pLocation.Y); // neighbor = this[newPoint]; // if (neighbor != null) // { // ret.Add(neighbor); // } // newPoint = new Point(pLocation.X - 1, pLocation.Y); // neighbor = this[newPoint]; // if (neighbor != null) // { // ret.Add(neighbor); // } // newPoint = new Point(pLocation.X, pLocation.Y + 1); // neighbor = this[newPoint]; // if (neighbor != null) // { // ret.Add(neighbor); // } // newPoint = new Point(pLocation.X, pLocation.Y - 1); // neighbor = this[newPoint]; // if (neighbor != null) // { // ret.Add(neighbor); // } // return ret; //} /// /// Returns a list of the specific type of structures. /// /// The type of structure we want. public List GetSpecificStructures(Type pType) { // The return value List retVal = new List(); // Switch on the type if (pType == typeof(MiningPlant)) { retVal = mMiningPlants; } else if (pType == typeof(Residential)) { retVal = mResidentials; } else if (pType == typeof(Commercial)) { retVal = mCommercials; } else if (pType == typeof(Factory)) { retVal = mFactories; } else if (pType == typeof(Entertainment)) { retVal = mEntertainments; } else if (pType == typeof(CommandPost)) { retVal = mCommandCenters; } // Return the list return retVal; } /// /// Gets the neighbors of the specified point that are of the given structure type /// /// The specified point in the grid /// The type of stucture to look for /// The neighbors of the specified point that are of the given structure type public Dictionary GetNeighborsForRoad(Point position, Type structureType) { Dictionary neighborList = new Dictionary(); if (position.X + 1 < mReferenceGrid.GetLength(0) && structureType.IsInstanceOfType(mReferenceGrid[position.X + 1, position.Y])) neighborList.Add(Carrier.Directions.Positive_X, mReferenceGrid[position.X + 1, position.Y]); if (position.Y + 1 < mReferenceGrid.GetLength(1) && structureType.IsInstanceOfType(mReferenceGrid[position.X, position.Y + 1])) neighborList.Add(Carrier.Directions.Positive_Y, mReferenceGrid[position.X, position.Y + 1]); if (position.X - 1 >= 0 && structureType.IsInstanceOfType(mReferenceGrid[position.X - 1, position.Y])) neighborList.Add(Carrier.Directions.Negative_X, mReferenceGrid[position.X - 1, position.Y]); if (position.Y - 1 >= 0 && structureType.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1])) neighborList.Add(Carrier.Directions.Negative_Y, mReferenceGrid[position.X, position.Y - 1]); return neighborList; } public Dictionary GetNeighborsForIntersection(Point position, Type structureType) { RoadTubeCrossing current = mReferenceGrid[position.X, position.Y] as RoadTubeCrossing; if (current == null) return null; Dictionary returnDic = new Dictionary(); if (structureType == typeof(Road)) { if (current.RoadAlongX) { if (position.X + 1 < mReferenceGrid.GetLength(0) && mReferenceGrid[position.X + 1, position.Y] is Road) { returnDic.Add(Carrier.Directions.Positive_X, mReferenceGrid[position.X + 1, position.Y]); } if (position.X - 1 >= 0 && mReferenceGrid[position.X - 1, position.Y] is Road) { returnDic.Add(Carrier.Directions.Negative_X, mReferenceGrid[position.X - 1, position.Y]); } } else { if (position.Y + 1 < mReferenceGrid.GetLength(1) && mReferenceGrid[position.X, position.Y + 1] is Road) { returnDic.Add(Carrier.Directions.Positive_Y, mReferenceGrid[position.X, position.Y + 1]); } if (position.Y - 1 >= 0 && mReferenceGrid[position.X, position.Y - 1] is Road) { returnDic.Add(Carrier.Directions.Negative_Y, mReferenceGrid[position.X, position.Y - 1]); } } } else if (structureType == typeof(Tube)) { if (!current.RoadAlongX) { if (position.X + 1 < mReferenceGrid.GetLength(0) && mReferenceGrid[position.X + 1, position.Y] is Tube) { returnDic.Add(Carrier.Directions.Positive_X, mReferenceGrid[position.X + 1, position.Y]); } if (position.X - 1 >= 0 && mReferenceGrid[position.X - 1, position.Y] is Tube) { returnDic.Add(Carrier.Directions.Negative_X, mReferenceGrid[position.X - 1, position.Y]); } } else { if (position.Y + 1 < mReferenceGrid.GetLength(1) && mReferenceGrid[position.X, position.Y + 1] is Tube) { returnDic.Add(Carrier.Directions.Positive_Y, mReferenceGrid[position.X, position.Y + 1]); } if (position.Y - 1 >= 0 && mReferenceGrid[position.X, position.Y - 1] is Tube) { returnDic.Add(Carrier.Directions.Negative_Y, mReferenceGrid[position.X, position.Y - 1]); } } } return returnDic; } /// /// Gets the neighbors of the specified point /// /// The specified point in the grid /// The neighbors of the specified point public Dictionary GetNeighborsForRoad(Point position) { Dictionary neighborList = new Dictionary(); if (position.X + 1 < mReferenceGrid.GetLength(0) && mReferenceGrid[position.X + 1, position.Y] != null) neighborList.Add(Carrier.Directions.Positive_X, mReferenceGrid[position.X + 1, position.Y]); if (position.Y + 1 < mReferenceGrid.GetLength(1) && mReferenceGrid[position.X, position.Y + 1] != null) neighborList.Add(Carrier.Directions.Positive_Y, mReferenceGrid[position.X, position.Y + 1]); if (position.X - 1 >= 0 && mReferenceGrid[position.X - 1, position.Y] != null) neighborList.Add(Carrier.Directions.Negative_X, mReferenceGrid[position.X - 1, position.Y]); if (position.Y - 1 >= 0 && mReferenceGrid[position.X, position.Y - 1] != null) neighborList.Add(Carrier.Directions.Negative_Y, mReferenceGrid[position.X, position.Y - 1]); return neighborList; } public List GetNeighbors(Structure structure) { List returnList = new List(); int structureWidth = (int)structure.FootPrintSize.X; int structureHeight = (int)structure.FootPrintSize.Y; int gridWidth = mReferenceGrid.GetLength(0); int gridHeight = mReferenceGrid.GetLength(1); for (int i = structure.GridPosition.X; i < structure.GridPosition.X + structureWidth && i < gridWidth; i++) { if (structure.GridPosition.Y - 1 >= 0) { int yPosition = structure.GridPosition.Y - 1; if (mReferenceGrid[i, yPosition] != null) { returnList.Add(mReferenceGrid[i, yPosition]); } } if (structure.GridPosition.Y + structureHeight < gridHeight) { int yPosition = structure.GridPosition.Y + structureHeight; if (mReferenceGrid[i, yPosition] != null) { returnList.Add(mReferenceGrid[i, yPosition]); } } } for (int i = structure.GridPosition.Y; i < structure.GridPosition.Y + structureHeight && i < gridHeight; i++) { if (structure.GridPosition.X - 1 >= 0) { int xPosition = structure.GridPosition.X - 1; if (mReferenceGrid[xPosition, i] != null) { returnList.Add(mReferenceGrid[xPosition, i]); } } if (structure.GridPosition.X + structureWidth < gridWidth) { int xPosition = structure.GridPosition.X + structureWidth; if (mReferenceGrid[xPosition, i] != null) { returnList.Add(mReferenceGrid[xPosition, i]); } } } return returnList; } public List GetNeighbors(Structure structure, Type structureToLookFor) { List returnList = new List(); int structureWidth = (int)structure.FootPrintSize.X; int structureHeight = (int)structure.FootPrintSize.Y; int gridWidth = mReferenceGrid.GetLength(0); int gridHeight = mReferenceGrid.GetLength(1); for (int i = structure.GridPosition.X; i < structure.GridPosition.X + structureWidth && i < gridWidth; i++) { if (structure.GridPosition.Y - 1 >= 0) { int yPosition = structure.GridPosition.Y - 1; if (mReferenceGrid[i, yPosition] != null && structureToLookFor.IsInstanceOfType(mReferenceGrid[i, yPosition])) { returnList.Add(mReferenceGrid[i, yPosition]); } } if(structure.GridPosition.Y + structureHeight < gridHeight) { int yPosition = structure.GridPosition.Y + structureHeight; if(mReferenceGrid[i, yPosition] != null && structureToLookFor.IsInstanceOfType(mReferenceGrid[i, yPosition])) { returnList.Add(mReferenceGrid[i, yPosition]); } } } for (int i = structure.GridPosition.Y; i < structure.GridPosition.Y + structureHeight && i < gridHeight; i++) { if (structure.GridPosition.X - 1 >= 0) { int xPosition = structure.GridPosition.X - 1; if (mReferenceGrid[xPosition, i] != null && structureToLookFor.IsInstanceOfType(mReferenceGrid[xPosition, i])) { returnList.Add(mReferenceGrid[xPosition, i]); } } if(structure.GridPosition.X + structureWidth < gridWidth) { int xPosition = structure.GridPosition.X + structureWidth; if (mReferenceGrid[xPosition, i] != null && structureToLookFor.IsInstanceOfType(mReferenceGrid[xPosition, i])) { returnList.Add(mReferenceGrid[xPosition,i]); } } } return returnList; } /// /// Gets the worldspace coordinates of the center of the grid square. /// /// The ray striking position on the plane. /// The center of the grid square. public Vector3 CenterOfGridSquare(Vector3 mWorldSpace) { return new Vector3( (float)Math.Floor(mWorldSpace.X) + .5f, 0, (float)Math.Floor(mWorldSpace.Z) + .5f); } /// /// Gets the center of the model, based on a given position in /// worldspace and a given structure. /// /// The position in worldspace /// The structure /// The location of the model's center in worldspace public Vector3 CenterOfModel(Vector3 mWorldSpace, Structure pStructure) { Vector3 returnVect = Vector3.Zero; //if (pStructure.FootPrintSize.X % 2 == 0) //{ returnVect.X = (float)Math.Floor(mWorldSpace.X) + (pStructure.FootPrintSize.X/2); //} //else //{ // returnVect.X = (float)(Math.Floor(mWorldSpace.X) + (pStructure.FootPrintSize.X/2.0)); //} //if (pStructure.FootPrintSize.Y % 2 == 0) //{ returnVect.Z = (float)(Math.Floor(mWorldSpace.Z) + (pStructure.FootPrintSize.Y/2)); //} //else //{ // returnVect.Z = (float)(Math.Floor(mWorldSpace.Z) + (pStructure.FootPrintSize.Y/2) + 0.5f); //} returnVect.Y = 0; return returnVect; } /// /// Returns the contents of the grid at the given grid location. /// /// The current location on the grid. public Structure GridContents(Point pLocation) { try { return mReferenceGrid[pLocation.X, pLocation.Y]; } catch { #if DEBUG Console.WriteLine("Outside of Grid"); #endif return null; } } /// /// Returns the direction in which the transport structure running /// /// Position in the current game grid /// Reference to teh transport structure /// The direction in which the transport structure running internal TransportStructure.Runnings getProperRunningForTransportStructure(Point position, Type transportStructure) { List connectableBuildings = new List(); if(transportStructure == typeof(Road)) { connectableBuildings.Add(typeof(Residential)); connectableBuildings.Add(typeof(Commercial)); connectableBuildings.Add(typeof(Entertainment)); } else if (transportStructure == typeof(Tube)) { connectableBuildings.Add(typeof(MiningPlant)); } connectableBuildings.Add(typeof(Factory)); Structure posXRef = null; Structure negXRef = null; Structure posYRef = null; Structure negYRef = null; if(position.X + 1 < mReferenceGrid.GetLength(0)) { posXRef = mReferenceGrid[position.X + 1, position.Y]; } if(position.X - 1 > 0) { negXRef = mReferenceGrid[position.X - 1, position.Y]; } if(position.Y + 1 < mReferenceGrid.GetLength(1)) { posYRef = mReferenceGrid[position.X, position.Y + 1]; } if(position.Y - 1 > 0) { negYRef = mReferenceGrid[position.X, position.Y - 1]; } if (position.X + 1 < mReferenceGrid.GetLength(0) && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X + 1, position.Y]) || ( posXRef != null && connectableBuildings.Contains(posXRef.GetType())) || (mReferenceGrid[position.X + 1, position.Y] is RoadTubeCrossing && ((transportStructure == typeof(Road) && (mReferenceGrid[position.X + 1, position.Y] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && !(mReferenceGrid[position.X + 1, position.Y] as RoadTubeCrossing).RoadAlongX))))) { if (position.Y + 1 < mReferenceGrid.GetLength(1) && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y + 1]) || ( posYRef != null &&connectableBuildings.Contains(posYRef.GetType())) || (mReferenceGrid[position.X, position.Y + 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y + 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y + 1] as RoadTubeCrossing).RoadAlongX))))) { if (position.X - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X - 1, position.Y]) || ( negXRef != null && connectableBuildings.Contains(negXRef.GetType())) || (mReferenceGrid[position.X - 1, position.Y] is RoadTubeCrossing && ((transportStructure == typeof(Road) && (mReferenceGrid[position.X - 1, position.Y] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && !(mReferenceGrid[position.X -1, position.Y] as RoadTubeCrossing).RoadAlongX))))) { if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.Four_Way; } return TransportStructure.Runnings.Positive_Y; } if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.Positive_X; } return TransportStructure.Runnings.PXPY; } if (position.X - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X - 1, position.Y]) || ( negXRef != null && connectableBuildings.Contains(negXRef.GetType())) || mReferenceGrid[position.X - 1, position.Y] is RoadTubeCrossing && ((transportStructure == typeof(Road) && (mReferenceGrid[position.X - 1, position.Y] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && !(mReferenceGrid[position.X - 1, position.Y] as RoadTubeCrossing).RoadAlongX)))) { if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.Negative_Y; } return TransportStructure.Runnings.X; } if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.PXNY; } // only one connection return TransportStructure.Runnings.X; } if (position.Y + 1 < mReferenceGrid.GetLength(1) && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y + 1]) || ( posYRef != null && connectableBuildings.Contains(posYRef.GetType())) || mReferenceGrid[position.X, position.Y + 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y + 1] as RoadTubeCrossing).RoadAlongX || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y + 1] as RoadTubeCrossing).RoadAlongX))))) { if (position.X - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X - 1, position.Y]) || ( negXRef != null && connectableBuildings.Contains(negXRef.GetType())) || mReferenceGrid[position.X - 1, position.Y] is RoadTubeCrossing && ((transportStructure == typeof(Road) && (mReferenceGrid[position.X - 1, position.Y]as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && !(mReferenceGrid[position.X - 1, position.Y] as RoadTubeCrossing).RoadAlongX)))) { if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.Negative_X; } return TransportStructure.Runnings.NXPY; } if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.Y; } // only one connection return TransportStructure.Runnings.Y; } if (position.X - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X - 1, position.Y]) || ( negXRef != null && connectableBuildings.Contains(negXRef.GetType())) || mReferenceGrid[position.X - 1, position.Y] is RoadTubeCrossing && ((transportStructure == typeof(Road) && (mReferenceGrid[position.X - 1, position.Y] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && !(mReferenceGrid[position.X - 1, position.Y] as RoadTubeCrossing).RoadAlongX)))) { if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { return TransportStructure.Runnings.NXNY; } // only on connection return TransportStructure.Runnings.X; } if (position.Y - 1 >= 0 && (transportStructure.IsInstanceOfType(mReferenceGrid[position.X, position.Y - 1]) || ( negYRef != null && connectableBuildings.Contains(negYRef.GetType())) || mReferenceGrid[position.X, position.Y - 1] is RoadTubeCrossing && ((transportStructure == typeof(Road) && !(mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX) || (transportStructure == typeof(Tube) && (mReferenceGrid[position.X, position.Y - 1] as RoadTubeCrossing).RoadAlongX)))) { // only one connection return TransportStructure.Runnings.Y; } return TransportStructure.Runnings.Four_Way; } #endregion #region Setters /// /// Sets the build area's texture /// /// Reference to the current graphics device /// The build area's new texture public Texture2D SetBuildAreaTexture(GraphicsDevice mDevice) { Texture2D returnText = new Texture2D(mDevice, mReferenceGrid.GetLength(0), mReferenceGrid.GetLength(1), 0, TextureUsage.None, SurfaceFormat.Color); List temp = new List(); for (int i = 0; i < mBuildAreaGrid.GetLength(0); i++) { for (int j = 0; j < mBuildAreaGrid.GetLength(1); j++) { if (mBuildAreaGrid[j, i]) temp.Add(Color.White); else temp.Add(Color.TransparentBlack); } } returnText.SetData(temp.ToArray(), 0, temp.Count, SetDataOptions.Discard); mGridModel.Model.Meshes[0].Effects[0].Parameters["buildArea"].SetValue(returnText); return returnText; } #endregion #region Adders /// /// Place the carrier back into the carrier pools. /// /// The carrier to add back. public void AddToCarrierPool(Carrier pCarrier) { // If it's not disposed if (!pCarrier.IsDisposed) { // Add the carrier if (pCarrier is RoadCarrier) { // Add it back mRoadCarrierPool.Push(pCarrier as RoadCarrier); } else if (pCarrier is TubeCarrier) { // Add it back mTubeCarrierPool.Push(pCarrier as TubeCarrier); } } } /// /// Adds the given structure to the given point on the grid /// /// The stucture to add to the grid /// The point in the grid to add the structure to /// Whether or not the structure could be added public bool AddStructure(Structure pStructureToAdd, Point pLocation) { // Get the return value bool retVal = AddStructure(pStructureToAdd, pLocation, mReferenceGrid, mResourceGrid); // If we did it if (retVal) { // Switch on the type if (pStructureToAdd is MiningPlant) { mMiningPlants.Add(pStructureToAdd); } else if (pStructureToAdd is Factory) { mFactories.Add(pStructureToAdd); } else if (pStructureToAdd is Residential) { mResidentials.Add(pStructureToAdd); } else if (pStructureToAdd is Commercial) { mCommercials.Add(pStructureToAdd); } else if (pStructureToAdd is Entertainment) { mEntertainments.Add(pStructureToAdd); } else if (pStructureToAdd is CommandPost) { mCommandCenters.Add(pStructureToAdd); } } // Return return retVal; } /// /// Add the given structure to the Grid /// /// The structure to add /// The location to add the structure /// Reference to the current game grid /// Reference to the resource grid /// Whether or not the structure could be added public bool AddStructure(Structure pStructureToAdd, Point pLocation, Structure[,] pReferenceGrid, Resource[,] pResourceGrid) { // If we're not on the grid if (pLocation.X + pStructureToAdd.FootPrintSize.X >= pReferenceGrid.GetLength(0) || pLocation.X < 0 || pLocation.Y + pStructureToAdd.FootPrintSize.Y >= pReferenceGrid.GetLength(1) || pLocation.Y < 0) { // Abort return false; } // Check to see if we have enough space to be placed at the current location for (int i = pLocation.X; i < pLocation.X + pStructureToAdd.FootPrintSize.X; i++) { for (int j = pLocation.Y; j < pLocation.Y + pStructureToAdd.FootPrintSize.Y; j++) { // Something blocking a tile if (pReferenceGrid[i, j] != null || (pStructureToAdd.RequiresBuildArea && !mBuildAreaGrid[i, j])) { // So abort return false; } } } // Check to see if we're a mining plant MiningPlant miningPlant = pStructureToAdd as MiningPlant; if (miningPlant != null) { // If there's no resource here if (pResourceGrid[pLocation.X, pLocation.Y] == null) { // Mining planets can only be placed directly on resources. return false; } // Set our resource miningPlant.OutputResource = pResourceGrid[pLocation.X, pLocation.Y].ResourceCode; } // For each tile this building takes up. for (int i = pLocation.X ; i < pLocation.X + pStructureToAdd.FootPrintSize.X; i++) { for (int j = pLocation.Y; j < pLocation.Y + pStructureToAdd.FootPrintSize.Y; j++) { // Set it to be occupying those tiles. pReferenceGrid[i, j] = pStructureToAdd; } } // Set its reference position pStructureToAdd.GridPosition = pLocation; pStructureToAdd.Register(this); // Set the build area flags in the radius around the building. int maxBuildAreaX = mBuildAreaGrid.GetLength(0); Point centerOfBuilding = new Point(pLocation.X + (int)(pStructureToAdd.FootPrintSize.X/2), pLocation.Y + (int)(pStructureToAdd.FootPrintSize.Y/2)); for (int i = (centerOfBuilding.X - pStructureToAdd.BuildRadius < 0 ? 0 : centerOfBuilding.X - pStructureToAdd.BuildRadius); i <= centerOfBuilding.X + pStructureToAdd.BuildRadius && i < maxBuildAreaX; i++) { int maxBuildAreaY = mBuildAreaGrid.GetLength(1); for (int j = (centerOfBuilding.Y - pStructureToAdd.BuildRadius < 0 ? 0 : centerOfBuilding.Y - pStructureToAdd.BuildRadius); j <= centerOfBuilding.Y + pStructureToAdd.BuildRadius && j < maxBuildAreaY; j++) { mBuildAreaGrid[i, j] = true; } } pStructureToAdd.TransformationMatrix *= Matrix.CreateTranslation(new Vector3(pLocation.X + pStructureToAdd.FootPrintSize.X * 0.5f, 0, pLocation.Y + pStructureToAdd.FootPrintSize.Y * 0.5f)); UpdateRoadmapFromNeighbors(pStructureToAdd); SetBuildAreaTexture(mGridModel.GraphicsDevice); // If it's residential or commercial if(pStructureToAdd is Residential) { // Generate the carrier pools for (int i = 0; i < ROAD_CARRIERS_PER_RES; i++) { mRoadCarrierPool.Push(new RoadCarrier(false, mContent, @"Models\transport02_FBX\transport02_FBX\transport_02", null, this)); //mRoadCarrierPool.Peek().ColorToAdd = Color.LightBlue; } } else if (pStructureToAdd is MiningPlant) { // Generate the carrier pools for (int i = 0; i < TUBE_CARRIERS_PER_COM; i++) { mTubeCarrierPool.Push(new TubeCarrier(false, ResourceCode.A0, mContent, @"Models\transport02_FBX\transport02_FBX\transport_02", null, this)); //mTubeCarrierPool.Peek().ColorToAdd = Color.Green; } } return true; } /// /// Adds the given Carrier to our list of carriers. /// /// The carrier to add public void AddCarrier(Carrier pCarrier) { // Add the carrier to the list, if it doesn't contain it if (!mCarrierList.Contains(pCarrier)) { // Add it to the list mCarrierList.Add(pCarrier); mNewCarriers.Add(pCarrier); pCarrier.Register(this); } // Set it's values pCarrier.Enabled = true; pCarrier.Visible = true; //pCarrier.UpdatePosition(); } /// /// Adds a new random carrier somewhere in one of the legal spots in the current game grid /// /// Reference to the current content manager private void SpawnRandomCarriers(ContentManager Content) { foreach (Structure s in mReferenceGrid) { if (s is TransportStructure && Util.Random.NextDouble() <= CHANCE_CARRIER_SPAWN) { if (s is Road && s.DistanceFromResidential == 1) { // If it's not null if (mRoadCarrierPool.Count > 0) { RoadCarrier temp = mRoadCarrierPool.Pop(); temp.GridPosition = s.GridPosition; temp.TowardsResidential = false; temp.InitialTowardsResidential = false; temp.TransformationMatrix = Matrix.CreateTranslation(s.TransformationMatrix.Translation); temp.DrawOrder = s.DrawOrder - 1; temp.RealignDirection(); temp.UpdateDirection(); AddCarrier(temp); } } if (s is Tube) { Array resources = Enum.GetValues(typeof(ResourceCode)); for (int i = 0; i < resources.Length && mTubeCarrierPool.Count > 0; i++) { if (s.GetDistanceFromResource((int)resources.GetValue(i)) == 1) { TubeCarrier temp = mTubeCarrierPool.Pop(); temp.AssociatedResource = (ResourceCode)resources.GetValue(i); temp.TowardsResource = false; temp.InitialTowardsResource = false; temp.GridPosition = s.GridPosition; temp.TransformationMatrix = Matrix.CreateTranslation(s.TransformationMatrix.Translation); temp.DrawOrder = s.DrawOrder - 1; temp.RealignDirection(); temp.UpdateDirection(); AddCarrier(temp); } } } } } } #endregion #region Removers /// /// Removes the structure at the given point. /// /// The location to remove the structure public void RemoveStructure(Point pLocation) { // Get the value Structure structure = mReferenceGrid[pLocation.X, pLocation.Y]; // Go through the grid's rows for (int i = 0; i < mReferenceGrid.GetLength(0); i++) { // And columns for (int j = 0; j < mReferenceGrid.GetLength(1); j++) { // If the structure is this one if (mReferenceGrid[i, j] == structure) { // Then remove it from the grid mReferenceGrid[i, j] = null; } } } // Update the structure for removal UpdateForRemoval(structure); // If the structure is a residential if (structure is Residential) { // If we can if (mRoadCarrierPool.Count > 0) { // Remove the value mRoadCarrierPool.Pop().Dispose(); } } else if (structure is MiningPlant) { // If we can if (mTubeCarrierPool.Count > 0) { // Remove the value mTubeCarrierPool.Pop().Dispose(); } } // Switch on the type if (structure is MiningPlant) { mMiningPlants.Remove(structure); } else if (structure is Factory) { mFactories.Remove(structure); } else if (structure is Residential) { mResidentials.Remove(structure); } else if (structure is Commercial) { mCommercials.Remove(structure); } else if (structure is Entertainment) { mEntertainments.Remove(structure); } else if (structure is CommandPost) { mCommandCenters.Remove(structure); } // Dispose of the structure structure.Dispose(); // Update the build areas UpdateBuildArea(); } #endregion #region Update /// /// Tick the Grid along. /// /// Reference to the current content manager public void Tick(ContentManager Content) { // Reset the current money and population mGridStatus.Population = 0; mGridStatus.Happiness = 0.0f; // For loop approach for (int i = mCarrierList.Count - 1; i >= 0; i--) { // Get the carrier Carrier carrier = mCarrierList[i]; // If the carrier is disposed if (carrier.IsDisposed) { // Remove it mCarrierList.RemoveAt(i); } } // Get the mean happiness of the colony List ress = GetSpecificStructures(typeof(Residential)); // If the count is greater than or equal to one if (ress.Count >= 1) { // Go through each of the residential structures foreach (Residential res in ress) { // Get the happiness StatusInfo.Happiness += res.Happiness; StatusInfo.Population += res.CurrentPopulation; } // Divide up by the number of structures mGridStatus.Happiness /= ress.Count; } // Now adjust that happiness int industryCount = GetSpecificStructures(typeof(MiningPlant)).Count + GetSpecificStructures(typeof(Factory)).Count; mGridStatus.Happiness -= industryCount * 0.01f; mGridStatus.Happiness = MathHelper.Max(0.0f, mGridStatus.Happiness); // Now tick all of the structures foreach (Structure structure in GridStructures) { // If the structure is not null if (structure != null) { // Tick the structure structure.Tick(); } } SpawnRandomCarriers(Content); // Tell us we ticked #if DEBUG Console.WriteLine("Tick"); Console.WriteLine("Total Number of Carriers: " + mCarrierList.Count); #endif } /// /// Updates the building area /// internal void UpdateBuildArea() { int maxBuildAreaX = mBuildAreaGrid.GetLength(0); int maxBuildAreaY = mBuildAreaGrid.GetLength(1); for (int i = 0; i < maxBuildAreaX; i++) { for (int j = 0; j < maxBuildAreaY; j++) { mBuildAreaGrid[i, j] = false; } } for (int k = 0; k < maxBuildAreaX; k++) { for (int l = 0; l < maxBuildAreaY; l++) { if (mReferenceGrid[k, l] != null) { Point centerOfBuilding = new Point(mReferenceGrid[k, l].GridPosition.X + (int)(mReferenceGrid[k, l].FootPrintSize.X / 2), mReferenceGrid[k, l].GridPosition.Y + (int)(mReferenceGrid[k, l].FootPrintSize.Y / 2)); for (int i = (centerOfBuilding.X - mReferenceGrid[k, l].BuildRadius < 0 ? 0 : centerOfBuilding.X - mReferenceGrid[k, l].BuildRadius); i <= centerOfBuilding.X + mReferenceGrid[k, l].BuildRadius && i < maxBuildAreaX; i++) { for (int j = (centerOfBuilding.Y - mReferenceGrid[k, l].BuildRadius < 0 ? 0 : centerOfBuilding.Y - mReferenceGrid[k, l].BuildRadius); j <= centerOfBuilding.Y + mReferenceGrid[k, l].BuildRadius && j < maxBuildAreaY; j++) { if (!mBuildAreaGrid[i, j]) { mBuildAreaGrid[i, j] = true; } } } } } } SetBuildAreaTexture(mGridModel.GraphicsDevice); } /// /// Update the road status of a newly-placed building based on it's surroundings. /// /// The newly added structure private void UpdateRoadmapFromNeighbors(Structure self) { if (self is Residential) { UpdateRoadmapForAllNeighbors(self); } else if (self is MiningPlant) { UpdateResourceMapForAllNeighbors(self); } else { int dist = self.DistanceFromResidential; int[] dists = (int[])self.mDistanceFromResource.Clone(); foreach (Structure neighbor in GetNeighbors(self)) { if ((neighbor is Road || neighbor is RoadTubeCrossing) || (neighbor is Residential && (self is Road || self is RoadTubeCrossing))) { dist = Math.Min(dist, neighbor.DistanceFromResidential); } if ((neighbor is Tube || neighbor is RoadTubeCrossing) || (neighbor is MiningPlant && (self is Tube || self is RoadTubeCrossing)) || (neighbor is Factory && (self is Tube || self is RoadTubeCrossing))) { for(int i = 0; i< dists.Length; ++i) { dists[i] = Math.Min(dists[i], neighbor.mDistanceFromResource[i]); } } } if (dist != int.MaxValue) { dist += 1; } for (int i = 0; i < dists.Length; ++i) { if (dists[i] != int.MaxValue) { dists[i] += 1; } } self.DistanceFromResidential = dist; self.SetDistanceFromResource(dists); #if DEBUG // NOTE Debug: //Console.WriteLine(self + " distance is " + dist); //for (int i = 0; i < dists.Length; ++i) //{ // Console.WriteLine("Resource " + i + " " + self + " distance is " + dists[i]); //} #endif if (self is Road || self is RoadTubeCrossing) { UpdateRoadmapForAllNeighbors(self); } if (self is Tube || self is RoadTubeCrossing) { UpdateResourceMapForAllNeighbors(self); } } } /// /// Update the road status of all surrounding buildings due to a change. /// /// The newly added structure private void UpdateRoadmapForAllNeighbors(Structure self) { int dist = self.mDistanceFromResidential; if (dist != int.MaxValue) { dist += 1; foreach (Structure neighbor in GetNeighbors(self)) { if (!(neighbor is Road || neighbor is RoadTubeCrossing) && !(self is Road || self is RoadTubeCrossing)) { continue; } if (neighbor.mDistanceFromResidential <= dist) { continue; } neighbor.DistanceFromResidential = dist; #if DEBUG // NOTE Debug: //Console.WriteLine(neighbor + " distance is " + neighbor.mDistanceFromResidential); #endif if (neighbor is Road || neighbor is RoadTubeCrossing) { UpdateRoadmapForAllNeighbors(neighbor); } } } } /// /// Updates the resource status of all surrounding buildings due to a change. /// /// The newly added structure private void UpdateResourceMapForAllNeighbors(Structure self) { int[] dists = (int[])self.mDistanceFromResource.Clone(); for (int i = 0; i < dists.Length; ++i) { if (dists[i] != int.MaxValue) { dists[i] += 1; } } foreach (Structure neighbor in GetNeighbors(self)) { if (!(neighbor is Tube || neighbor is RoadTubeCrossing) && !(self is Tube || self is RoadTubeCrossing)) { continue; } bool change = false; for (int i = 0; i < dists.Length; ++i) { if (neighbor.mDistanceFromResource[i] > dists[i]) { neighbor.SetDistanceFromResource(i,dists[i]); change = true; } } if (change) { if (neighbor is Tube || neighbor is RoadTubeCrossing) { UpdateResourceMapForAllNeighbors(neighbor); } } } } /// /// Updates grid information due to the removal of a structure /// /// The structure that has been removed private void UpdateForRemoval(Structure self) { int dist = self.mDistanceFromResidential; if (dist != int.MaxValue) { dist += 1; self.DistanceFromResidential = int.MaxValue; foreach (Structure neighbor in GetNeighbors(self)) { if (neighbor.mDistanceFromResidential == dist) { UpdateRoadmapRemovalChange(neighbor); } } } for (int i = 0; i < self.mDistanceFromResource.Length; i++) { if (self.mDistanceFromResource[i] != int.MaxValue) { dist = self.mDistanceFromResource[i]; self.SetDistanceFromResource(i, int.MaxValue); List neighbors = GetNeighbors(self); foreach (Structure neighbor in GetNeighbors(self)) { if (neighbor.mDistanceFromResource[i] > dist) { UpdateResourceMapRemovalChange(neighbor, i); } } } } } /// /// /// /// private void UpdateRoadmapRemovalChange(Structure self) { int dist = self.mDistanceFromResidential; if (dist == int.MaxValue) { return; } bool disconnected = true; foreach (Structure neighbor in GetNeighbors(self)) { if (neighbor.mDistanceFromResidential <= dist) { disconnected = false; break; } } if (disconnected) { self.DistanceFromResidential = int.MaxValue; foreach (Structure neighbor in GetNeighbors(self)) { UpdateRoadmapRemovalChange(neighbor); } } else { UpdateRoadmapFromNeighbors(self); } } /// /// /// /// /// private void UpdateResourceMapRemovalChange(Structure self, int iResource) { int dist = self.mDistanceFromResource[iResource]; if (dist == int.MaxValue) { return; } bool disconnected = true; foreach (Structure neighbor in GetNeighbors(self)) { if (neighbor.mDistanceFromResource[iResource] <= dist) { disconnected = false; break; } } if (disconnected) { self.SetDistanceFromResource(iResource, int.MaxValue); foreach (Structure neighbor in GetNeighbors(self)) { if (neighbor.mDistanceFromResource[iResource] > dist) { UpdateResourceMapRemovalChange(neighbor, iResource); } } } else { UpdateRoadmapFromNeighbors(self); } } #endregion #region File I/O /// /// Saves the current game state to a file /// /// The name of the file to save to /// Whether or not the game successfully saved public bool Save(string pSaveString) { GameState gameState = new GameState(); gameState.ResourceGrid = mResourceGrid; gameState.StructureGrid = mReferenceGrid; gameState.PlayerStatusInfo = StatusInfo; return SaverLoader.Save(GameScreen.GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + UserProfileUtility.SaveDirectory, pSaveString + ".csg", gameState); } /// /// Loads in the current game grid information from the given file /// /// The current content manager /// The name of the file to load /// All the need game information loaded from the file public ColonySimStatusInformation Load(ContentManager Content, string pGameName) { for (int i = 0; i < mReferenceGrid.GetLength(0); i++) { for (int j = 0; j < mReferenceGrid.GetLength(1); j++) { if (mReferenceGrid[i, j] != null) { mReferenceGrid[i, j].Dispose(); mReferenceGrid[i, j] = null; } } } for (int i = 0; i < mResourceGrid.GetLength(0); i++) { for (int j = 0; j < mResourceGrid.GetLength(1); j++) { if (mResourceGrid[i, j] != null) { mResourceGrid[i, j] = null; } } } string path = GameScreen.GlobalRootStorageDirectory + UserProfileUtility.OutputDirectory + UserProfileUtility.SaveDirectory; GameState returnState = SaverLoader.Load(path + pGameName, AddStructure, mReferenceGrid, mContent); if (returnState == null) { // No save file found, so create one SaverLoader.Save(path, pGameName, new GameState()); // And try to load it again returnState = SaverLoader.Load(path + pGameName, AddStructure, mReferenceGrid, mContent); } mResourceGrid = returnState.ResourceGrid; UpdateBuildArea(); return returnState.PlayerStatusInfo; } #endregion #region Management /// /// Clears out the entire reference grid and resource grid /// /// Reference to the current graphics device public void Clear(GraphicsDevice pDevice) { for (int i = 0; i < mReferenceGrid.GetLength(0); i++) { for (int j = 0; j < mReferenceGrid.GetLength(1); j++) { if (mReferenceGrid[i, j] != null) { mReferenceGrid[i, j].Dispose(); mReferenceGrid[i, j] = null; } if(mResourceGrid[i,j] != null) mResourceGrid[i, j] = null; } } UpdateBuildArea(); SetBuildAreaTexture(pDevice); } #endregion } /// /// Represents the resource names and codes that are available in the /// Colony Simulation. /// public enum ResourceCode { /// /// Represents that there is no resource /// None = 0, /// /// Represents that there is a level 0 A resource /// A0 = 1, /// /// Represents that there is a level 0 B resource /// B0 = 2, /// /// Represents that there is a level 0 C resource /// C0 = 3, /// /// Represents that there is a level 1 A resource /// A1 = 4, /// /// Represents that there is a level 1 B resource /// B1 = 5, /// /// Represents that there is a level 1 C resource /// C1 = 6, /// /// Represents that there is a level 2 A resource /// A2 = 7, /// /// Represents that there is a level 2 B resource /// B2 = 8, /// /// Represents that there is a level 2 C resource /// C2 = 9, /// /// Represents that there is a level 3 A resource /// A3 = 10, /// /// Represents that there is a level 3 B resource /// B3 = 11, /// /// Represents that there is a level 3 C resource /// C3 = 12 } /// /// Class that defines the amount of certain resources that exist in the grid /// class ResourceSpawnNumbers { #region Fields // The number of oxygen resources in the grid private int mOxygen = Util.Random.Next(5, 20); // The number of helium resources in the grid private int mHelium = Util.Random.Next(5, 20); // The number of hydrogen resources in the grid private int mHydrogen = Util.Random.Next(5, 20); // The number of iron resources in the grid private int mIron = Util.Random.Next(5, 20); // The number of carbon resources in the grid private int mCarbon = Util.Random.Next(5, 20); #endregion #region Properties /// /// Gets/Sets the number of oxygen resources in the grid /// public int Oxygen { get { return mOxygen; } set { mOxygen = value; } } /// /// Gets/Sets the number of helium resources in the grid /// public int Helium { get { return mHelium; } set { mHelium = value; } } /// /// Gets/Sets the number of hydrogen resources in the grid /// public int Hydrogen { get { return mHydrogen; } set { mHydrogen = value; } } /// /// Gets/Sets the number of iron resources in the grid /// public int Iron { get { return mIron; } set { mIron = value; } } /// /// Gets/Sets the number of carbon resources in the grid /// public int Carbon { get { return mCarbon; } set { mCarbon = value; } } #endregion #region Generate Resources /// /// Generates the grid of resources of specified height and width /// /// The width of the grid /// The height of the grid /// The grid of resources of specified height and width public Resource[,] GenerateResourceGrid(int width, int height) { Resource[,] returnGrid = new Resource[width, height]; for (int i = 0; i < mOxygen; i++) { Point currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); while (returnGrid[currentLocation.X, currentLocation.Y] != null) { currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); } returnGrid[currentLocation.X, currentLocation.Y] = new Resource(); returnGrid[currentLocation.X, currentLocation.Y].ResourceCode = ResourceCode.A0; } //for (int i = 0; i < mCarbon; i++) //{ // Point currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); // while (returnGrid[currentLocation.X, currentLocation.Y] != null) // { // currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); // } // returnGrid[currentLocation.X, currentLocation.Y] = new Resource(); // returnGrid[currentLocation.X, currentLocation.Y].ResourceCode = ResourceCode.B1; //} for (int i = 0; i < mHelium; i++) { Point currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); while (returnGrid[currentLocation.X, currentLocation.Y] != null) { currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); } returnGrid[currentLocation.X, currentLocation.Y] = new Resource(); returnGrid[currentLocation.X, currentLocation.Y].ResourceCode = ResourceCode.B0; } for (int i = 0; i < mHydrogen; i++) { Point currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); while (returnGrid[currentLocation.X, currentLocation.Y] != null) { currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); } returnGrid[currentLocation.X, currentLocation.Y] = new Resource(); returnGrid[currentLocation.X, currentLocation.Y].ResourceCode = ResourceCode.C0; } //for (int i = 0; i < mIron; i++) //{ // Point currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); // while (returnGrid[currentLocation.X, currentLocation.Y] != null) // { // currentLocation = new Point(Util.Random.Next(0, width), Util.Random.Next(0, height)); // } // returnGrid[currentLocation.X, currentLocation.Y] = new Resource(); // returnGrid[currentLocation.X, currentLocation.Y].ResourceCode = ResourceCode.A1; //} return returnGrid; } #endregion } /// /// Class that defines the amount of certain buildings exist in the grid /// class BuildingSpawnNumbers { #region Fields // The number of obstacles in the grid private int mObstacles = Util.Random.Next(100, 500); // The number of planets in the grid private int mPlanets = Util.Random.Next(10, 30); // The number of outposts in the grid private int mOutposts = Util.Random.Next(20, 60); #endregion #region Properties /// /// Gets/Sets the number of obstacles in the grid /// public int Obstacles { get { return mObstacles; } set { mObstacles = value; } } /// /// Gets/Sets the number of planets in the grid /// public int Planets { get { return mPlanets; } set { mPlanets = value; } } /// /// Gets/Sets then number of outposts in the grid /// public int Outposts { get { return mOutposts; } set { mOutposts = value; } } #endregion #region Genereate Structures /// /// Generates the grid with the given number of each structure object /// /// Reference to the current content manager /// Reference to the grid to fill /// The list of structures in the grid public List GenerateStructures(ContentManager pContent, Grid pGridReference) { List returnList = new List(); for (int i = 0; i < mPlanets; i++) { Residential tempPlanet = new Residential(pContent, @"Models\Industrial Plant_JPx", null); tempPlanet.Register(pGridReference); tempPlanet.FootPrintSize = new Vector2(3, 3); returnList.Add(tempPlanet); } for (int i = 0; i < mOutposts; i++) { Factory tempOutpost = new Factory(pContent, @"Models\spacestation", null); tempOutpost.Register(pGridReference); tempOutpost.FootPrintSize = new Vector2(2, 2); returnList.Add(tempOutpost); } for (int i = 0; i < mObstacles; i++) { Obstacle tempObstacle = new Obstacle(pContent, @"Models\testcube", @"Textures\singlePixel"); tempObstacle.Register(pGridReference); returnList.Add(tempObstacle); } return returnList; } #endregion } }