/// <summary> /// Get adjacent safe cells from a given cell. /// </summary> /// <param name="p_hHero"> Hero. </param> /// <param name="p_fcCell"> Current cell. </param> /// <returns> The safe neighboors. </returns> private static List <ForestCell> GetAdjacentSafeCells(Hero p_hHero, ForestCell p_fcCell) { List <ForestCell> fcResult = new List <ForestCell>(); List <MemoryCell> fcNeighboorsList = Hero.Memory[p_fcCell.LineIndex, p_fcCell.ColumnIndex].getAdjacentMemoryCells(); foreach (MemoryCell mcItem in fcNeighboorsList) { if (MainWindow.Forest[mcItem.LineIndex, mcItem.ColumnIndex].Closed) { continue; } if (mcItem.HasNoHole == 1 && mcItem.HasNoAlien == 1) { double fTemp = p_fcCell.Distance; ForestCell fcItem = MainWindow.Forest[mcItem.LineIndex, mcItem.ColumnIndex]; // If new distance is less than distance found before. if (fTemp > fcItem.Distance) { fcItem.ParentCell = p_fcCell; fcResult.Add(fcItem); } } else { ForestCell fcItem = MainWindow.Forest[mcItem.LineIndex, mcItem.ColumnIndex]; fcItem.ParentCell = p_fcCell; fcItem.Closed = false; fcResult.Add(fcItem); } } return(fcResult.Distinct().ToList()); }
/// <summary> /// Initializes the text containing the cell's details (monster, smell, etc...). /// </summary> public void EditTextDetails() { VerboseCellContent = string.Empty; ForestCell currentCell = steveTheHero.CurrentForestCell; if (currentCell.HasNothing) { VerboseCellContent = string.Concat(VerboseCellContent, "- Nothing\n"); } if (currentCell.HasHole) { VerboseCellContent = string.Concat(VerboseCellContent, "- A hole ! Damned !\n"); } if (currentCell.HasAlien) { VerboseCellContent = string.Concat(VerboseCellContent, "- An Alien ! Game Over\n"); } if (currentCell.HasWind) { VerboseCellContent = string.Concat(VerboseCellContent, "- Some wind\n"); } if (currentCell.HasRadiation) { VerboseCellContent = string.Concat(VerboseCellContent, "- Some smell\n"); } if (currentCell.HasPortal) { VerboseCellContent = string.Concat(VerboseCellContent, "- Some light\n"); } currentCellText.Text = VerboseCellContent; }
/// <summary> /// Init cell distance to destination cell. /// </summary> /// <param name="p_hHero"> hero. </param> /// <param name="p_fcDestinationCell"> Destination cell. </param> public static void InitCost(Hero p_hHero, ForestCell p_fcDestinationCell) { for (int i = 0; i < MainWindow.ForestSize; i++) { for (int j = 0; j < MainWindow.ForestSize; j++) { MainWindow.Forest[i, j].Distance = Math.Sqrt(Math.Pow(p_fcDestinationCell.LineIndex - i, 2) + Math.Pow(p_fcDestinationCell.ColumnIndex - j, 2)); } } }
/// <summary> /// Randomly puts either a monster, a hole, or nothing on the input cell /// Also updates the neighboring cells with either smell or wind accordingly. /// </summary> /// <param name="pCell"> The input cell to populate </param> public void PopulateCellRandomly(ForestCell pCell, Random r) { // Generates a random number between 0 (included) and 100 (excluded). int die = r.Next(0, 100); // There is 8 % of chance for the generated number to be in the following range. if ((die >= 0) && (die < 8)) { pCell.AddAlienOnCell(); } // There is 8 % of chance for the generated number to be in the following range. if ((die >= 92) && (die <= 100)) { pCell.AddHoleOnCell(); } }
/// <summary> /// Run the A* search for the given parameters. /// </summary> /// <param name="p_hHero"> Hero. </param> /// <param name="p_fcDestinationCell"> Destination cell. </param> /// <returns> The fastest safest path if found. </returns> public static List <ForestCell> FindPath(Hero p_hHero, ForestCell p_fcDestinationCell) { List <ForestCell> lfcPath = new List <ForestCell>(); bool bSuccess = Search(p_hHero, p_hHero.CurrentForestCell, p_fcDestinationCell); if (bSuccess) { ForestCell node = p_fcDestinationCell; while (node.ParentCell != null) { lfcPath.Add(node); node = node.ParentCell; } lfcPath.Reverse(); } return(lfcPath); }
/// <summary> /// Creates a forest matrix with the size "m_iForestSize" with a ForestCell in each cell. /// </summary> public void CreateForest() { // Nullify the current instances of the objects. m_afcForest = null; m_afcForest = new ForestCell[m_iForestSize, m_iForestSize]; // For every cell we want, we create a new ForestCell // and we address it to the ForestCell matrix. for (int i = 0; i < m_iForestSize; i++) { for (int j = 0; j < m_iForestSize; j++) { // Creates a new ForestCell and gives it the correct attributes for row and column. m_afcForest[i, j] = new ForestCell(); m_afcForest[i, j].LineIndex = i; m_afcForest[i, j].ColumnIndex = j; } } }
/// <summary> /// Recursive search to find the path. /// </summary> /// <param name="p_hHero"> Hero. </param> /// <param name="p_fcStartingCell"> Starting cell. </param> /// <param name="p_fcDestinationCell"> Destination cell. </param> /// <returns></returns> private static bool Search(Hero p_hHero, ForestCell p_fcStartingCell, ForestCell p_fcDestinationCell) { p_fcStartingCell.Closed = true; List <ForestCell> lfcNextCells = GetAdjacentSafeCells(p_hHero, p_fcStartingCell); lfcNextCells.Sort((cell1, cell2) => cell1.Distance.CompareTo(cell2.Distance)); foreach (ForestCell nextCell in lfcNextCells) { if (nextCell.Equals(p_fcDestinationCell)) { return(true); } else { if (Search(p_hHero, nextCell, p_fcDestinationCell)) { return(true); } } } return(false); }
/// <summary> /// Event thrown when the Hero move, update sprite emplacement. /// Start the cycle if the Hero dies. /// </summary> /// <param name="prevForestCell"> Previous cell. </param> /// <param name="NewForestCell"> Cell to move to. </param> public void OnMove(ForestCell prevForestCell, ForestCell NewForestCell) { for (int i = 0; i < m_iForestSize; i++) { for (int j = 0; j < m_iForestSize; j++) { if (m_afcForest[i, j] == prevForestCell) { m_afcForest[i, j].HasHero = false; } if (m_afcForest[i, j] == NewForestCell) { m_afcForest[i, j].HasHero = true; } } } if (steveTheHero.CurrentForestCell.HasAlien || steveTheHero.CurrentForestCell.HasHole) { UpdateGUI(); OnDeath(); } }
/// <summary> /// Check if cell has radiation. /// </summary> /// <param name="p_fcCell"> Current cell. </param> /// <returns> True if cell has radiation, false otherwise. </returns> public static bool HasRadiation(ForestCell p_fcCell) { return(p_fcCell.HasRadiation); }
/// <summary> /// Check if cell has wind. /// </summary> /// <param name="p_fcCell"> Current cell. </param> /// <returns> True if cell has wind, false otherwise. </returns> public static bool HasWind(ForestCell p_fcCell) { return(p_fcCell.HasWind); }
/// <summary> /// Check if cell has light. /// </summary> /// <param name="p_fcCell"> Current cell. </param> /// <returns> True if cell has portal, false otherwise. </returns> public static bool HasLight(ForestCell p_fcCell) { return(p_fcCell.HasPortal); }
/// <summary> /// Test if cell is empty. /// </summary> /// <param name="p_fcCell"> Current cell. </param> /// <returns> Tru if cell is empty, false otherwise. </returns> public static bool HasNothing(ForestCell p_fcCell) { return(p_fcCell.HasNothing); }
/// <summary> /// Infere the possible action from the memory and the current cell state. /// </summary> /// <param name="p_iStateEnv"> Current cell state. </param> /// <returns> A list of PossibleAction. </returns> private List <PossibleAction> ActionDeclenchable(int p_iStateEnv) { ThrowRockLeft paActToThrowRockLeft = new ThrowRockLeft(this); ThrowRockRight paActToThrowRockRight = new ThrowRockRight(this); ThrowRockTop paActToThrowRockTop = new ThrowRockTop(this); ThrowRockBottom paActToThrowRockBottom = new ThrowRockBottom(this); Exit paActToExit = new Exit(this); List <PossibleAction> aListPossibleAction = new List <PossibleAction>(); // if the current cell is empty cell or with wind if (p_iStateEnv == 0 || p_iStateEnv == 2) { bool bFlagOK = false; // If there are some remaining safe cells, move there. if (m_lfcCellsOK.Any()) { int iCost = int.MaxValue; ForestCell fcDestination = m_lfcCellsOK[new Random().Next(0, m_lfcCellsOK.Count)]; foreach (ForestCell fcOK in m_lfcCellsOK) { if (!fcOK.AlreadyVisited) { Pathfinding.InitCost(this, fcOK); // Find the fastest safe path to the destination cell. List <ForestCell> PathFound = Pathfinding.FindPath(this, fcOK); Pathfinding.ResetGridCost(); if (PathFound.Count < iCost) { fcDestination = fcOK; iCost = PathFound.Count; bFlagOK = true; } } } if (bFlagOK) { Move paActToMove = new Move(this, fcDestination, iCost); aListPossibleAction.Add(paActToMove); } } bool bFlagSuspicious = false; // Else go to a cell with smell to kill monster. if (m_lfcCellsWithRadiation.Any() && !bFlagOK) { int iCost = int.MaxValue; ForestCell dest = null; foreach (ForestCell fcRadiation in m_lfcCellsWithRadiation) { Pathfinding.InitCost(this, fcRadiation); // Find the fastest safe path to the destination cell. List <ForestCell> lfcPathFound = Pathfinding.FindPath(this, fcRadiation); Pathfinding.ResetGridCost(); // If the new path is better than the old one. if (lfcPathFound.Count < iCost) { dest = fcRadiation; iCost = lfcPathFound.Count; bFlagSuspicious = true; } } if (bFlagSuspicious) { Move paActToMove = new Move(this, dest, iCost); aListPossibleAction.Add(paActToMove); } } if (!bFlagSuspicious && !bFlagOK) { // Else try the closest suspicious cell. if (m_lfcCellsSuspicous.Any()) { bool bPathFound = false; int iCost = int.MaxValue; ForestCell fcDestination = null; foreach (ForestCell fcSuspicious in m_lfcCellsSuspicous) { if (!fcSuspicious.AlreadyVisited) { Pathfinding.InitCost(this, fcSuspicious); // Find the fastest safe path to the destination cell. List <ForestCell> lfcPathFound = Pathfinding.FindPath(this, fcSuspicious); Pathfinding.ResetGridCost(); // If the new path is better than the old one. if (lfcPathFound.Count < iCost) { fcDestination = fcSuspicious; iCost = lfcPathFound.Count; bPathFound = true; } } } if (bPathFound) { Move paActToMove = new Move(this, fcDestination, iCost); aListPossibleAction.Add(paActToMove); } } } } // If the current cell contains radiation. if (p_iStateEnv == 1) { bool bCellOKFlag = false; // If there are some remaining safe cells, move there. if (m_lfcCellsOK.Any()) { int iCost = int.MaxValue; ForestCell fcDestination = null; foreach (ForestCell fcOK in m_lfcCellsOK) { if (!fcOK.AlreadyVisited) { Pathfinding.InitCost(this, fcOK); // Find the fastest safe path to the destination cell. List <ForestCell> lfcPathFound = Pathfinding.FindPath(this, fcOK); Pathfinding.ResetGridCost(); // If the new path is better than the old one. if (lfcPathFound.Count < iCost) { fcDestination = fcOK; iCost = lfcPathFound.Count; bCellOKFlag = true; } } } // If we found a path. if (bCellOKFlag) { Move paActToMove = new Move(this, fcDestination, iCost); aListPossibleAction.Add(paActToMove); } } // Else try to kill the alien. if (!bCellOKFlag) { // Try to find a valid target i.e. cell in m_lfcCellsSuspicous and not the cell we come from. List <ForestCell> lfcTargets = CurrentForestCell.getAdjacentCells(); // Remove cell visited just before from targets. for (int i = lfcTargets.Count - 1; i >= 0; i--) { if (Memory[lfcTargets[i].LineIndex, lfcTargets[i].ColumnIndex].HasNoAlien == 1 || Memory[lfcTargets[i].LineIndex, lfcTargets[i].ColumnIndex].IsSafe == 1) { lfcTargets.Remove(lfcTargets[i]); } } // Randomly choose target from remaining cells. Random r = new Random(); int iTargetIndex = r.Next(0, lfcTargets.Count); if (lfcTargets[iTargetIndex].ColumnIndex < m_fcCurrentForestCell.ColumnIndex) { aListPossibleAction.Add(paActToThrowRockLeft); } else { if (lfcTargets[iTargetIndex].ColumnIndex > m_fcCurrentForestCell.ColumnIndex) { aListPossibleAction.Add(paActToThrowRockRight); } else { if (lfcTargets[iTargetIndex].LineIndex < m_fcCurrentForestCell.LineIndex) { aListPossibleAction.Add(paActToThrowRockTop); } else { if (lfcTargets[iTargetIndex].LineIndex > m_fcCurrentForestCell.LineIndex) { aListPossibleAction.Add(paActToThrowRockBottom); } } } } } } // Smell + Wind if (p_iStateEnv == 3) { bool bCellOKFlag = false; // If there are some remaining safe cells, move there if (m_lfcCellsOK.Any()) { int iCost = int.MaxValue; ForestCell fcDestination = null; foreach (ForestCell fcOK in m_lfcCellsOK) { if (!fcOK.AlreadyVisited) { Pathfinding.InitCost(this, fcOK); // Find the fastest safe path to the destination cell. List <ForestCell> lfcPathFound = Pathfinding.FindPath(this, fcOK); Pathfinding.ResetGridCost(); // If the new path is better than the old one. if (lfcPathFound.Count < iCost) { fcDestination = fcOK; iCost = lfcPathFound.Count; bCellOKFlag = true; } } } if (bCellOKFlag) { Move paActToMove = new Move(this, fcDestination, iCost); aListPossibleAction.Add(paActToMove); } } // Else try to kill monster and wait for result. if (!bCellOKFlag) { List <ForestCell> lfcTargets = CurrentForestCell.getAdjacentCells(); // Remove cell visited just before from targets. for (int i = lfcTargets.Count - 1; i >= 0; i--) { if (Memory[lfcTargets[i].LineIndex, lfcTargets[i].ColumnIndex].HasNoAlien == 1) { lfcTargets.Remove(lfcTargets[i]); } } // if no more target, try random cell. if (!lfcTargets.Any()) { if (m_lfcCellsSuspicous.Any()) { bool bPathFound = false; int iCost = int.MaxValue; ForestCell fcDestination = null; foreach (ForestCell fcSuspicious in m_lfcCellsSuspicous) { if (!fcSuspicious.AlreadyVisited) { Pathfinding.InitCost(this, fcSuspicious); List <ForestCell> PathFound = Pathfinding.FindPath(this, fcSuspicious); Pathfinding.ResetGridCost(); if (PathFound.Count < iCost) { fcDestination = fcSuspicious; iCost = PathFound.Count; bPathFound = true; } } } if (bPathFound) { Move paActToMove = new Move(this, fcDestination, iCost); aListPossibleAction.Add(paActToMove); } } } else { // Randomly choose target from remaining cells. Random r = new Random(); int iTargetIndex = r.Next(0, lfcTargets.Count); if (lfcTargets[iTargetIndex].ColumnIndex < m_fcCurrentForestCell.ColumnIndex) { aListPossibleAction.Add(paActToThrowRockLeft); } else { if (lfcTargets[iTargetIndex].ColumnIndex > m_fcCurrentForestCell.ColumnIndex) { aListPossibleAction.Add(paActToThrowRockRight); } else { if (lfcTargets[iTargetIndex].LineIndex < m_fcCurrentForestCell.LineIndex) { aListPossibleAction.Add(paActToThrowRockTop); } else { if (lfcTargets[iTargetIndex].LineIndex > m_fcCurrentForestCell.LineIndex) { aListPossibleAction.Add(paActToThrowRockBottom); } } } } } } } // Light if (p_iStateEnv == 4) { // GET OUT ! aListPossibleAction.Add(paActToExit); } return(aListPossibleAction); }