/*
* 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
}
}