public Location ChooseDestinationAndPower(GameState game, out Power power) { Location destination; if ((game.Dracula.AdvanceMoveLocation != Location.Nowhere && !game.LocationIsBlocked(game.Dracula.AdvanceMoveLocation)) || game.Dracula.AdvanceMovePower != Power.None) { power = game.Dracula.AdvanceMovePower; destination = game.Dracula.AdvanceMoveLocation; game.Dracula.AdvanceMoveLocation = Location.Nowhere; game.Dracula.AdvanceMovePower = Power.None; return destination; } var currentNumberOfPossibleCurrentLocations = NumberOfPossibleCurrentLocations; var currentActualTrail = GetActualTrail(game); var possibleMoves = GetPossibleMovesFromTrail(game, currentActualTrail); var possibleCurrentOrangeBackedLocations = new List<Location>(); foreach (var trail in PossibilityTree) { possibleCurrentOrangeBackedLocations.AddRange(GetPossibleCurrentLocationsFromPossibilityTree(AddOrangeBackedCardToTrail(game, trail))); } var possibleCurrentBlueBackedLocations = new List<Location>(); foreach (var trail in PossibilityTree) { possibleCurrentBlueBackedLocations.AddRange(GetPossibleCurrentLocationsFromPossibilityTree(AddBlueBackedCardToTrail(game, trail))); } var possibleWolfFormLocations = new List<Location>(); foreach (var trail in PossibilityTree) { possibleCurrentBlueBackedLocations.AddRange(GetPossibleCurrentLocationsFromPossibilityTree(AddWolfFormCardToTrail(game, trail))); } var uniquePossibleCurrentOrangeBackedLocations = new List<Location>(); var uniquePossibleCurrentBlueBackedLocations = new List<Location>(); var uniquePossibleWolfFormLocations = new List<Location>(); foreach (var location in possibleCurrentOrangeBackedLocations) { if (!uniquePossibleCurrentOrangeBackedLocations.Contains(location)) { uniquePossibleCurrentOrangeBackedLocations.Add(location); } } foreach (var location in possibleCurrentBlueBackedLocations) { if (!uniquePossibleCurrentBlueBackedLocations.Contains(location)) { uniquePossibleCurrentBlueBackedLocations.Add(location); } } foreach (var location in possibleWolfFormLocations) { if (!uniquePossibleWolfFormLocations.Contains(location)) { uniquePossibleWolfFormLocations.Add(location); } } var numberOfPossibleOrangeBackedLocationsThatWouldBeRevealed = uniquePossibleCurrentOrangeBackedLocations.Count(loc => game.HuntersAt(loc).Any()); var numberOfPossibleLocationsAfterMove = new List<int>(); foreach (var move in possibleMoves) { if ((game.HuntersAt(move.Location).Any() && game.Map.TypeOfLocation(move.Location) != LocationType.Sea) || move.Location == Location.CastleDracula) { numberOfPossibleLocationsAfterMove.Add(1); } else { if (move.Power == Power.None || move.Power == Power.Hide) { if (move.CardBack == CardBack.Orange) { numberOfPossibleLocationsAfterMove.Add(uniquePossibleCurrentOrangeBackedLocations.Count() - numberOfPossibleOrangeBackedLocationsThatWouldBeRevealed); } else if (move.CardBack == CardBack.Blue) { numberOfPossibleLocationsAfterMove.Add(uniquePossibleCurrentBlueBackedLocations.Count()); } } else if (move.Power == Power.Feed || move.Power == Power.DarkCall) { numberOfPossibleLocationsAfterMove.Add(currentNumberOfPossibleCurrentLocations); } else if (move.Power == Power.DoubleBack) { var doubleBackSlot = GetIndexOfLocationInTrail(move.Location, currentActualTrail); var uniquePossibleDoubleBackLocations = new List<Location>(); foreach (var trail in PossibilityTree) { if (DoubleBackToPositionIsValidForTrail(game, trail, doubleBackSlot) && !uniquePossibleDoubleBackLocations.Contains(trail[doubleBackSlot].Location)) { uniquePossibleDoubleBackLocations.Add(trail[doubleBackSlot].Location); } } numberOfPossibleLocationsAfterMove.Add(uniquePossibleDoubleBackLocations.Count() - uniquePossibleDoubleBackLocations.Count(loc => game.HuntersAt(loc).Any())); } else if (move.Power == Power.WolfForm) { numberOfPossibleLocationsAfterMove.Add(uniquePossibleWolfFormLocations.Count() - uniquePossibleWolfFormLocations.Count(loc => game.HuntersAt(loc).Any())); } } } var numberOfMovesUntilDeadEnd = new List<int>(); var deadEndMoves = GetPossibleMovesThatLeadToDeadEnds(game, currentActualTrail, possibleMoves, numberOfMovesUntilDeadEnd); int turnsUntilTrailCleared = GetNumberOfTurnsUntilTrailCleared(game); int index; int randomNumber; List<PossibleTrailSlot> shortList; switch (Strategy) { case Strategy.Sneaky: var distancesFromNearestHunter = new List<int>(); var currentDistanceFromHunters = game.GetDistanceToClosestHunter(game.Dracula.CurrentLocation, true); foreach (var move in possibleMoves) { if (move.Location != Location.Nowhere) { distancesFromNearestHunter.Add(game.GetDistanceToClosestHunter(move.Location, true)); GC.Collect(); } else { distancesFromNearestHunter.Add(currentDistanceFromHunters); } } var chancesToSelectMove = new List<int>(); index = -1; foreach (var move in possibleMoves) { index++; var deadEndIndex = deadEndMoves.FindIndex(m => m.Location == move.Location && m.Power == move.Power); if (deadEndIndex > -1 && turnsUntilTrailCleared > numberOfMovesUntilDeadEnd[deadEndIndex]) { chancesToSelectMove.Add(1); } else { chancesToSelectMove.Add((int)(Math.Pow(numberOfPossibleLocationsAfterMove[index] * distancesFromNearestHunter[index], CHANCETOSELECTSCALAR) * PercentageDifferenceInLikelihoodOfDraculaDeath(game.Dracula.Blood, move.Power))); } } int totalCombinations = 0; foreach (int i in chancesToSelectMove) { totalCombinations += i; } randomNumber = new Random().Next(0, totalCombinations); index = -1; int count = 0; foreach (int i in chancesToSelectMove) { index++; count += i; if (count > randomNumber) { power = possibleMoves[index].Power; return possibleMoves[index].Location; } } power = possibleMoves[0].Power; return possibleMoves[0].Location; case Strategy.Aggressive: var distancesFromVictim = new List<int>(); var currentDistanceFromVictim = game.GetDistanceToHunter(victim); foreach (var move in possibleMoves) { if (move.Location != Location.Nowhere) { distancesFromVictim.Add(game.GetDistanceToHunter(victim)); GC.Collect(); } else { distancesFromVictim.Add(currentDistanceFromVictim); } } int shortestDistanceToVictim = distancesFromVictim.First(); foreach (var i in distancesFromVictim) { if (i < shortestDistanceToVictim) { shortestDistanceToVictim = i; } } shortList = new List<PossibleTrailSlot>(); index = -1; foreach (PossibleTrailSlot move in possibleMoves) { index++; if (distancesFromVictim[index] == shortestDistanceToVictim) { shortList.Add(move); } } randomNumber = new Random().Next(0, shortList.Count()); power = shortList[randomNumber].Power; return shortList[randomNumber].Location; case Strategy.FleeToCastleDracula: var distancesToCastleDracula = new List<int>(); var currentDistanceFromCastleDracula = game.DistanceByRoadOrSeaBetween(game.Dracula.CurrentLocation, Location.CastleDracula, false); foreach (var move in possibleMoves) { if (move.Location != Location.Nowhere) { distancesToCastleDracula.Add(game.DistanceByRoadOrSeaBetween(move.Location, Location.CastleDracula, false)); GC.Collect(); } else { distancesToCastleDracula.Add(currentDistanceFromCastleDracula); } } int shortestDistanceToCastleDracula = distancesToCastleDracula.First(); foreach (int i in distancesToCastleDracula) { if (i < shortestDistanceToCastleDracula) { shortestDistanceToVictim = i; } } shortList = new List<PossibleTrailSlot>(); index = -1; foreach (PossibleTrailSlot move in possibleMoves) { index++; if (distancesToCastleDracula[index] == shortestDistanceToCastleDracula) { shortList.Add(move); } } randomNumber = new Random().Next(0, shortList.Count()); power = shortList[randomNumber].Power; return shortList[randomNumber].Location; } int rand = new Random().Next(0, possibleMoves.Count()); power = possibleMoves[rand].Power; return possibleMoves[rand].Location; }