/* * RoadCarrier.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.Collections.Generic; using ColonySim.Structures; using Microsoft.Xna.Framework; using Microsoft.Xna.Framework.Content; namespace ColonySim { class RoadCarrier : Carrier { private int mCurrentDistance; bool mTowardsResidential; bool mInitialTowardsResidential; public bool TowardsResidential { get { return mTowardsResidential; } set { mTowardsResidential = value; } } public bool InitialTowardsResidential { get { return mInitialTowardsResidential; } set { mInitialTowardsResidential = value; } } public RoadCarrier(bool GotoResidential, ContentManager pContent, string pModelName, string pTextureName, Grid pGridReference) :base(pContent, pModelName, pTextureName, pGridReference) { mInitialTowardsResidential = GotoResidential; mTowardsResidential = mInitialTowardsResidential; } public void UpdateDirection() { // If we've moved outside the bounds of the grid, destroy us Structure contents = GridReference.GridContents(GridPosition); if (GridPosition.X < GridReference.GridBounds.Left || GridPosition.X > GridReference.GridBounds.Right || GridPosition.Y < GridReference.GridBounds.Top || GridPosition.Y > GridReference.GridBounds.Bottom) { // Purge this carrier Destroy(); return; } else { Dictionary neighbors = GridReference.GetNeighborsForRoad(GridPosition); if (mInitialTowardsResidential) { if (contents != null && contents.mDistanceFromResidential == 1 && Util.Random.Bool()) { Destroy(); return; } } else { foreach (Structure v in neighbors.Values) { if (!(v is Residential || v is Tube || v is Road) && Util.Random.NextDouble() <= .2) { Destroy(); return; } } } if (contents is RoadTubeCrossing) { neighbors = GridReference.GetNeighborsForIntersection(GridPosition, typeof(Road)); } else { neighbors = GridReference.GetNeighborsForRoad(GridPosition, typeof(Road)); Dictionary temp = GridReference.GetNeighborsForRoad(GridPosition, typeof(RoadTubeCrossing)); foreach (Directions d in temp.Keys) { if (GridReference.GetNeighborsForIntersection(temp[d].GridPosition, typeof(Road)).ContainsValue(contents)) { neighbors.Add(d, temp[d]); } } } if (neighbors.Count == 0) { Destroy(); } else { mTowardsResidential = mInitialTowardsResidential; List possibleDirections = new List(); foreach (Directions d in neighbors.Keys) { if (mTowardsResidential && neighbors[d].mDistanceFromResidential < mCurrentDistance) { possibleDirections.Add(d); } else if (!mTowardsResidential && neighbors[d].mDistanceFromResidential > mCurrentDistance) { possibleDirections.Add(d); } } if (possibleDirections.Count == 0) { foreach (Directions d in neighbors.Keys) { possibleDirections.Add(d); } } Direction = possibleDirections[Util.Random.Next(0, possibleDirections.Count)]; } } } public override bool UpdatePosition() { if (!base.UpdatePosition()) { return false; } Structure contents = GridReference.GridContents(GridPosition); // If we've moved outside the bounds of the grid, destroy us if (GridPosition.X < GridReference.GridBounds.Left || GridPosition.X > GridReference.GridBounds.Right || GridPosition.Y < GridReference.GridBounds.Top || GridPosition.Y > GridReference.GridBounds.Bottom) { // Purge this carrier Destroy(); } else { Dictionary neighbors = GridReference.GetNeighborsForRoad(GridPosition); if (mInitialTowardsResidential) { if (contents.mDistanceFromResidential == 1 && Util.Random.Bool()) { Destroy(); return false; } } else { foreach (Structure s in neighbors.Values) { if (!(s is Residential || s is TransportStructure) && Util.Random.NextDouble() <= .2) { Destroy(); return false; } } } if (contents is RoadTubeCrossing) { neighbors = GridReference.GetNeighborsForIntersection(GridPosition, typeof(Road)); } else { neighbors = GridReference.GetNeighborsForRoad(GridPosition, typeof(Road)); Dictionary temp = GridReference.GetNeighborsForRoad(GridPosition, typeof(RoadTubeCrossing)); foreach (Directions d in temp.Keys) { if (GridReference.GetNeighborsForIntersection(temp[d].GridPosition, typeof(Road)).ContainsValue(contents)) { neighbors.Add(d, temp[d]); } } } if (neighbors.Count == 0) { Destroy(); return false; } else if (neighbors.Count == 1) { Dictionary.KeyCollection.Enumerator temp = neighbors.Keys.GetEnumerator(); temp.MoveNext(); Direction = temp.Current; mTowardsResidential = !mTowardsResidential; if (bumps >= 4) { Destroy(); return false; } bumps++; } else if (neighbors.Count == 2) { foreach (Directions d in neighbors.Keys) { if (d != Opposite(Direction)) { Direction = d; break; } } } else { mTowardsResidential = mInitialTowardsResidential; List possibleDirections = new List(); foreach (Directions d in neighbors.Keys) { if (mTowardsResidential && neighbors[d].mDistanceFromResidential < mCurrentDistance) { possibleDirections.Add(d); } else if (!mTowardsResidential && neighbors[d].mDistanceFromResidential > mCurrentDistance) { possibleDirections.Add(d); } } if (possibleDirections.Count == 0) { foreach (Directions d in neighbors.Keys) { if(d != Opposite(Direction)) possibleDirections.Add(d); } } Direction = possibleDirections[Util.Random.Next(0, possibleDirections.Count)]; } } return true; } } }