Files
robot_intelligence_final_pr…/ConsoleApp/SimRunner.cs
2020-12-16 17:19:25 -07:00

253 lines
9.0 KiB
C#

using System;
using System.Collections.Generic;
using System.Linq;
using ConsoleApp.Maps;
using ConsoleApp.PathPlanners;
using ConsoleApp.Sim;
using HexCore;
namespace ConsoleApp
{
public class SimRunner : ISimRunner
{
private IMapFactory _mapFactory;
private IVehicle _vehicle;
private IPathPlanner _pathPlanner;
private IMineMap _mineMap;
private IReactivePathPlanner _reactivePathPlanner;
private HashSet<Coordinate2D> hexBombsFound = new HashSet<Coordinate2D>();
private ISimulationResults _simulationResults;
private HashSet<ICell> squareBombsFound = new HashSet<ICell>();
public SimRunner(IMapFactory mapFactory, IVehicle vehicle, IPathPlanner pathPlanner, IReactivePathPlanner reactivePathPlanner, ISimulationResults simulationResults)
{
_mapFactory = mapFactory;
_vehicle = vehicle;
_pathPlanner = pathPlanner;
_reactivePathPlanner = reactivePathPlanner;
_simulationResults = simulationResults;
}
public void Run()
{
_mineMap = _mapFactory.GetMineMap();
_simulationResults.Mines = _mineMap.PlacedMines;
_simulationResults.TotalBombs = _mineMap.TotalBombs;
SquareSimulation();
HexSimulation();
// while(!squareTask.IsCompleted && !hexTask.IsCompleted){Thread.Sleep(500);}
}
#region HexSimulation
private void HexSimulation()
{
var hexMap = _mapFactory.GetHexMap();
_vehicle.CurrentHexCell = new Coordinate2D(0, 0, OffsetTypes.OddRowsRight);
var optimalPath = _pathPlanner.GenerateOptimalHexPath(hexMap, _vehicle);
var finished = false;
var totalMoves = 0;
while (!finished)
{
totalMoves += 1;
_simulationResults.HexPath.Add(_vehicle.CurrentHexCell);
var detectionCells = DetectionHead.GetCoveredCells(hexMap.Graph, _vehicle.CurrentHexCell, _vehicle.DetectorRadius, _vehicle.TurnRadius);
//Check Cells for mine
var detection = CheckCells(detectionCells);
//mark as cleared
hexMap.Graph.SetCellsTerrainType(detectionCells, hexMap.ClearedTerrain);
//Handle any detections
if (detection)
{
_reactivePathPlanner.GenerateReactiveHexPath(hexMap, optimalPath, _vehicle.CurrentHexCell);
}
//If the reactive Planner is not empty, empty it before the optimal.
if (_reactivePathPlanner.ReactiveHexPath.TryDequeue(out var next))
_vehicle.CurrentHexCell = next;
//Else we will work off of the optimal path
else
{
//If the optimal path is empty we are done otherwise pop.
if (!optimalPath.TryDequeue(out var nextOptimal))
{
finished = true;
continue;
}
if (hexMap.Graph.IsCellBlocked(nextOptimal))
{
_reactivePathPlanner.GenerateReactiveHexPath(hexMap, optimalPath, _vehicle.CurrentHexCell);
}
else
_vehicle.CurrentHexCell = nextOptimal;
}
}
//Debugging information
var (cleared, uncleared) = CoveredCells();
_simulationResults.HexClearedCells = cleared;
_simulationResults.HexUnClearedCells = uncleared;
_simulationResults.HexTotalMoves = totalMoves;
_simulationResults.HexBombsFound = hexBombsFound.Count;
_simulationResults.HexMappedBombs = hexBombsFound.ToList();
foreach (var cell in hexMap.Graph.GetAllCells())
{
if(cell.TerrainType.Id == hexMap.ClearedTerrain.Id)
_simulationResults.HexCoveredCells.Add(cell.Coordinate3.To2D(hexMap.OffsetType));
}
}
private (int, int) CoveredCells()
{
var cleared = 0;
var uncleared = 0;
var hexMap = _mapFactory.GetHexMap();
foreach (var cellState in hexMap.Graph.GetAllCells())
{
if (cellState.TerrainType.Id == hexMap.ClearedTerrain.Id)
cleared++;
if (cellState.TerrainType.Id == hexMap.UnclearedTerrain.Id)
uncleared++;
}
return (cleared, uncleared);
}
private bool CheckCells(List<Coordinate2D> detectionCells)
{
var found = false;
foreach (var cell in detectionCells.Where(cell => _mineMap.GetCell(cell.X, cell.Y)))
{
if (!hexBombsFound.Add(cell)) continue;
BlockCells(cell);
found = true;
}
return found;
}
private void BlockCells(Coordinate2D cell)
{
var hexMap = _mapFactory.GetHexMap();
var cellsToBlock = hexMap.Graph.GetRange(cell, _vehicle.Width / 2);
hexMap.Graph.BlockCells(cellsToBlock);
}
#endregion
#region SquareSimulation
private void SquareSimulation()
{
var squareMap = _mapFactory.GetSquareMap();
_vehicle.CurrentSquareCell = squareMap.StartingCell;
var optimalPath = _pathPlanner.GenerateOptimalSquarePath(squareMap, _vehicle);
var finished = false;
while (!finished)
{
_simulationResults.SquareTotalMoves++;
_simulationResults.SquarePath.Add(_vehicle.CurrentSquareCell);
var detector = squareMap.GetRange(_vehicle.CurrentSquareCell, _vehicle.DetectorRadius);
var detection = CheckForMines(detector);
//Mark cells as covered.
foreach (var cell in detector)
{
cell.Coverage = Coverage.Covered;
}
if (detection)
_reactivePathPlanner.GenerateReactiveSquarePath(squareMap, optimalPath, _vehicle.CurrentSquareCell);
if (_reactivePathPlanner.ReactiveSquarePath.TryDequeue(out var next))
{
_vehicle.CurrentSquareCell = (Cell) next;
}
else
{
if (!optimalPath.TryDequeue(out var current))
{
finished = true;
continue;
}
if (current.Blocked)
{
_reactivePathPlanner.GenerateReactiveSquarePath(squareMap, optimalPath, current);
}
else
_vehicle.CurrentSquareCell = (Cell) current;
}
}
//Debugging information
var (cleared, uncleared) = CoveredSquareCells();
_simulationResults.SquareCellsCleared = cleared;
_simulationResults.SquareCellsUncleared = uncleared;
_simulationResults.SquareBombsFound = squareBombsFound.Count;
_simulationResults.SquareMappedBombs = squareBombsFound.ToList();
foreach (var cell in squareMap.Map)
{
if (cell.Coverage == Coverage.Covered)
{
_simulationResults.SquareCoveredCells.Add(cell);
}
}
}
private (int, int) CoveredSquareCells()
{
var cleared = 0;
var uncleared = 0;
var map = _mapFactory.GetSquareMap();
foreach (var cellState in map.Map)
{
switch (cellState.Coverage)
{
case Coverage.Covered:
cleared++;
break;
case Coverage.Uncovered:
uncleared++;
break;
default:
throw new ArgumentOutOfRangeException();
}
}
return (cleared, uncleared);
}
private bool CheckForMines(List<Cell> detector)
{
var found = false;
foreach (var cell in detector.Where(cell => _mineMap.GetCell(cell.X, cell.Y)))
{
if(!squareBombsFound.Add(cell)) continue;
found = true;
BlockSquareCells(cell);
}
return found;
}
private void BlockSquareCells(Cell cell)
{
var map = _mapFactory.GetSquareMap();
var cellsToBlock = map.GetRange(cell, _vehicle.DetectorRadius);
foreach (var blockCell in cellsToBlock)
{
blockCell.Blocked = true;
}
}
#endregion
}
}