public void DestroyBlight (Location location, Blight blight, GameState gameState)
		{
			if (location.Blights.Contains (blight)) {
				location.Blights.Remove (blight);
				gameState.BlightPool.Add (blight);
			}
		}
		/// <summary>
		/// Activate the necromancer. First he detects and then moves.
		/// </summary>
		/// <param name="gameState">Game state.</param>
		/// <param name="detectedHero">Force this hero to be detected.</param>
		/// <param name="roll">Force the necromancer roll.</param>
		/// <param name="heroesToIgnore">Heroes that are ignored due to Elusive Spirit or Blinding Black</param>
		public NecromancerActivationResult Activate (GameState gameState, 
		                                             Hero detectedHero = null,
		                                             int? roll = null, 
		                                             int[] heroesToIgnore = null)
		{
			var result = new NecromancerActivationResult ();
			result.NecromancerRoll = roll.HasValue ? roll.Value : _d6GeneratorService.RollDemBones ();
			result.OldLocationId = gameState.Necromancer.LocationId;

			result.DarknessIncrease = 1 + gameState.Locations.SelectMany (x => x.Blights).Count (x => x.Name == "Desecration");
			if (gameState.Heroes.ShieldOfRadianceActive && result.NecromancerRoll == 6) {
				result.DarknessIncrease--;
				result.Notes += "Shield of Radiance triggered" + Environment.NewLine;
			}

			gameState.Darkness += result.DarknessIncrease;
				
			//detect
			if (detectedHero == null)
				result.DetectedHero = Detect (gameState, result.NecromancerRoll, heroesToIgnore);
			else
				result.DetectedHero = detectedHero;

			//move
			var newLocation = Move (gameState, detectedHero, result.NecromancerRoll);
			result.NewLocationId = newLocation.Id;

			//spawn
			var spawnResult = Spawn(gameState, newLocation, result.NecromancerRoll);
			result.NewBlights = spawnResult.NewBlights;
			result.SpawnQuest = spawnResult.SpawnQuest;

			return result;
		}
		public void Initialise (Hero detectedHero, int necromancerRoll, int [] heroesToIgnore = null)
		{
			Task.Run (() => {
				_pendingGameState = Application.CurrentGame.Clone ();
				SetResult (_necromancerService.Activate (_pendingGameState, detectedHero, necromancerRoll, heroesToIgnore));
				IsLoading = false;
			});
		}
		/// <summary>
		/// Spawns a blight at the specified locaiton. 
		/// If the location is already at capacity then it spawns a blight at the monastery instead.
		/// </summary>
		/// <returns>A typle containting the blight spawned and the locaiton spawned at.</returns>
		/// <param name="location">Location.</param>
		/// <param name="gameState">Game state.</param>
		public Tuple<Location, Blight> SpawnBlight (Location location, GameState gameState)
		{
			if (location.BlightCount >= 4)
				location = gameState.Locations.Single (l => l.Id == (int)LocationIds.Monastery);
			
			var card = gameState.MapCards.Draw ();
			var blightName = card.Rows.Single (r => r.LocationId == location.Id).BlightName;
			var blight = gameState.BlightPool.FirstOrDefault (x => x.Name == blightName);
			gameState.MapCards.Discard (card);

			if (blight != null) {
				location.Blights.Add (blight);
				gameState.BlightPool.Remove (blight);
			} else //if there are no blights of that type left to spawn try the next card
				return SpawnBlight (location, gameState);

			return new Tuple<Location, Blight>(location, blight);
		}
		/// <summary>
		/// Returns a hero visible to the necromancer
		/// </summary>
		/// <param name="gameState">Game state.</param>
		/// <param name="roll">The necromancer's roll.</param>
		/// <param name="heroesToIgnore">Heroes to ignore even if they can be detected (from powers like Blinding Black for example)</param>
		public Hero Detect (GameState gameState, int roll, int[] heroesToIgnore)
		{			
			var detectionRoll = gameState.GatesActive ? roll + 1 : roll;
			//first check if any heroes can be detected
			var exposedHeroes = gameState.Heroes.Active.Where (x => x.LocationId != (int)LocationIds.Monastery && x.Secrecy < detectionRoll && (heroesToIgnore == null || !heroesToIgnore.Contains (x.Id)));

			//special hero effects
			var ranger = gameState.Heroes.Active.SingleOrDefault (x => x is Ranger) as Ranger;
			if (gameState.Heroes.HermitActive && ranger.LocationId == (int)LocationIds.Swamp)
				exposedHeroes = exposedHeroes.Where (h => h != ranger);

			var paragon = gameState.Heroes.Active.SingleOrDefault (h => h is Paragon) as Paragon;
			if (gameState.Heroes.AuraOfHumilityActive)
				exposedHeroes = exposedHeroes.Where (x => x.LocationId != paragon.LocationId);

			if (exposedHeroes.Any ()) {
				//figure out which hero the necromancer is pursuing

				if (gameState.GatesActive) { 
					//if gates are active pick a random hero from those detectd
					var index = new Random ().Next (0, exposedHeroes.Count () - 1);
					return exposedHeroes.ToArray () [index];
				} else if (exposedHeroes.Any (x => x.LocationId == gameState.Necromancer.LocationId)) {
					return exposedHeroes.First (x => x.LocationId == gameState.Necromancer.LocationId);
				} else {
					//TODO: this needs work. not exactly readable at the moment
					var necromancerLocation = gameState.Locations.First (x => x.Id == gameState.Necromancer.LocationId);

					var heroesOneLocationAway = exposedHeroes.Where (x => necromancerLocation.Pathways.Any (y => y == x.LocationId));
					if (heroesOneLocationAway.Any ())
						exposedHeroes = heroesOneLocationAway;

					var index = new Random ().Next (0, exposedHeroes.Count () - 1);
					return exposedHeroes.ToArray () [index];
				}
			} else
				return null;
		}
		public void SpawnStartingBlights(int numberOfBlights, GameState gameState)
		{
			foreach (var location in gameState.Locations)
				location.Blights.Clear();


			for (int i = 0; i < numberOfBlights; i++)
			{
				var mapCard = gameState.MapCards.Draw();

				foreach (var row in mapCard.Rows)
				{
					if (row.LocationId == (int)LocationIds.Monastery)
						continue;

					var blight = gameState.BlightPool.FirstOrDefault(x => x.Name == row.BlightName);
					gameState.Locations.Single(l => l.Id == row.LocationId).Blights.Add(blight);
					gameState.BlightPool.Remove(blight);
				}

				gameState.MapCards.Discard(mapCard);
			}
		}
		public GameState CreateGameState (int numberOfPlayers, int startingDarkness, int startingBlights, bool useQuests, DarknessCardsMode mode)//DifficultyLevelSettings difficultyLevelSettings)
		{
			var gameState = new GameState ();

			gameState.NumberOfPlayers = numberOfPlayers;
			//gameState.DifficultyLevel = difficultyLevelSettings.DifficultyLevel;
			gameState.Darkness = startingDarkness;
			gameState.UseQuests = useQuests;
			//gameState.SpawnExtraQuests = difficultyLevelSettings.SpawnExtraQuests;
			gameState.Mode = mode;

			gameState.Necromancer.LocationId = (int)LocationIds.Ruins;

			gameState.MapCards = new Deck<MapCard> ();
			gameState.MapCards.Initialise (_dataService.GetMapCards ());

			gameState.BlightPool = _dataService.GetBlights ();

			gameState.Locations = _dataService.GetLocations();

			_blightService.SpawnStartingBlights (startingBlights, gameState);

			return gameState;
		}
		public NecromancerSpawnResult Spawn (GameState gameState, Location newLocation, int necromancerRoll)
		{
			var result = new NecromancerSpawnResult() { NewBlights = new List<Tuple<Location, Blight>>()};

			//check if a quest needs to be spawned
			if (gameState.UseQuests && (necromancerRoll == 3 || necromancerRoll == 4))
				result.SpawnQuest = true;

			var initialBlightCount = newLocation.BlightCount;
			var monastery = gameState.Locations.Single (l => l.Id == (int)LocationIds.Monastery);

			//spawn blight at necromancer's new location
			result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));		

			//standard darkness track effects
			if (gameState.DarknessTrackEffectsActive) {
				if (gameState.Darkness >= 10 && newLocation.BlightCount == 0)
					result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));

				if (gameState.Darkness >= 20 && (necromancerRoll == 1 || necromancerRoll == 2))
					result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));
			}

			//darkness card effects
			//if (gameState.Mode != DarknessCardsMode.None) {
				if (gameState.Necromancer.FocusedRituals
					&& !gameState.Heroes.Active.Any (x => x.LocationId == newLocation.Id))
					result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));

				if (gameState.Necromancer.CreepingShadows && (necromancerRoll == 5 || necromancerRoll == 6))
					result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));

				if (gameState.Necromancer.DyingLand) {
					if (gameState.DarknessTrackEffectsActive
						&& gameState.Darkness >= 10
					&& initialBlightCount == 1)
						result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));
					else if ((!gameState.DarknessTrackEffectsActive
						|| gameState.Darkness < 10)
					&& initialBlightCount == 0)
						result.NewBlights.Add (_blightService.SpawnBlight (newLocation, gameState));
				}

				if (gameState.Necromancer.EncroachingShadows && necromancerRoll == 6)
					result.NewBlights.Add (_blightService.SpawnBlight (monastery, gameState));

				if (gameState.Necromancer.Overwhelm && initialBlightCount < 4 && newLocation.BlightCount >= 4)
					result.NewBlights.Add (_blightService.SpawnBlight (monastery, gameState));

			//}

			//darkness tipping over 30
			if (gameState.Darkness > 30) {
				var overflowCount = gameState.Darkness - 30;

				for (int i = 0; i < overflowCount; i++)
					result.NewBlights.Add (_blightService.SpawnBlight (monastery, gameState));

				gameState.Darkness = 30;
			}

			return result;
		}
		/// <summary>
		/// Moves the necromancer in the detected hero's direction or via the die roll if no hero passed in.
		/// Return the Location that the necromancer moved to.
		/// </summary>
		/// <param name="gameState">Game state.</param>
		/// <param name="detectedHero">Detected hero.</param>
		/// <param name="roll">Roll.</param>
		public Location Move (GameState gameState, Hero detectedHero, int roll)
		{
			var currentLocation = gameState.Locations.Single (x => x.Id == gameState.Necromancer.LocationId);
			Location newLocation = null;

			if (detectedHero != null) {
				var heroLocation = gameState.Locations.Single (x => x.Id == detectedHero.LocationId);
				var necromancerLocation = gameState.Locations.First (x => x.Id == gameState.Necromancer.LocationId);
				//if the necromancer can reach the hero go directly to them
				if (necromancerLocation.Pathways.Contains (heroLocation.Id) || gameState.GatesActive)
					newLocation = heroLocation;
				else {
					//the common locations between the hero and necromancer are the ones that the necro should move along
					var commonLocationIds = necromancerLocation.Pathways.Intersect (heroLocation.Pathways).ToArray ();
					var index = new Random ().Next (0, commonLocationIds.Length - 1);
					newLocation = gameState.Locations.Single (x => x.Id == commonLocationIds [index]);
				}
			} else
				newLocation = gameState.Locations.Single (x => x.Id == currentLocation.Pathways [roll - 1]);

			if (gameState.Heroes.InvisibleBarrierLocationId.HasValue
				&& gameState.Heroes.InvisibleBarrierLocationId == newLocation.Id) 
			{
				newLocation = currentLocation;
				gameState.Heroes.InvisibleBarrierLocationId = null;
				//result.Notes += string.Format ("Invisible Barrier deactivated and cancelled the Necromancer's movement. {0}", Environment.NewLine);
			}

			gameState.Necromancer.LocationId = newLocation.Id;

			return newLocation;
		}