public BoardCalculator( ReadOnlyBlockadeState state) { this._state = state; this._connectedComponentLabels = new Lazy <Grid <NullableInt> >(() => ComputeConnectedComponents(state)); }
public double EvaluateState(ReadOnlyBlockadeState state, int player, IBlockadeHeuristic blockadeHeuristic) { return(state.IsGameOver() ? (state.CurrentPlayer == player ? blockadeHeuristic.WinScore : blockadeHeuristic.LossScore) : blockadeHeuristic.EvaluateState(state, player)); }
public double EvaluateState(ReadOnlyBlockadeState state, int player) { return(Enumerable.Range(0, state.PlayerCount) .Where(thisPlayer => !state.IsPlayerOut(thisPlayer)) .Select(thisPlayer => (thisPlayer == player ? 1.0 : -1.0) * (GetReachableCellScore(state, thisPlayer) * 100.0 + GetNeighborAversionScore(state, thisPlayer) * 1.0)) .Sum()); }
public int PickMove(List <Move> moves, ReadOnlyBlockadeState state) { var tuple = this._singleLevelMoveEvaluator.PickBestMove(moves, state, new HelmutBlockadeHeuristic()); return(tuple != null ? tuple.Item1 // all moves kill me, so pick a random one : this._random.Next(moves.Count)); }
public double EvaluateState(ReadOnlyBlockadeState state, int player) { var weights = new[] { 20, 15, 10 }; return(weights.Select((weight, i) => state.GetBoardCalculator() .GetD1Neighbors(state.GetCurrentLocationOfPlayer(player), distance: i + 1) .Sum(l => (state.GetCell(l).IsEmpty() ? 1 : -1) * weight)) .Sum()); }
public Tuple <int, double> PickBestMove(List <Move> moves, ReadOnlyBlockadeState state, IBlockadeHeuristic blockadeHeuristic) { return(moves.Select((move, i) => new { nextState = state.MakeMove(move), move, i }) .Where(a => a.nextState.GetBoardCalculator().GetD1Neighbors(a.move.Location, distance: 1) .Where(l => a.nextState.GetCell(l).IsEmpty()) .Any()) .Select(a => Tuple.Create(this.EvaluateState(a.nextState, state.CurrentPlayer, blockadeHeuristic), a.i)) .OrderByDescending(t => t) .Select(t => Tuple.Create(t.Item2, t.Item1)) .FirstOrDefault()); }
public double GetReachableCellScore(ReadOnlyBlockadeState state, int player) { using (var step = this._myProfiler.Step("sophie evaluate state - reachable")) { // so we cant check the reachable count for the current position of the player because that space is // occupied, but we can check all the places they can go and get the max of that as an analog return(state.GetMoves(player) .Select(move => state.GetBoardCalculator().GetReachableCellCount(move.Location)) .Max()); } }
public double GetNeighborAversionScore(ReadOnlyBlockadeState state, int player) { using (var step = this._myProfiler.Step("mira evaluate state - neighbor")) { var weights = new[] { 20, 15, 10 }; return(weights.Select((weight, i) => state.GetBoardCalculator() .GetD1Neighbors(state.GetCurrentLocationOfPlayer(player), distance: i + 1) .Sum(l => (state.GetCell(l).IsEmpty() ? 1 : -1) * weight)) .Sum()); } }
public Tuple <int, double> PickBestMove(List <Move> moves, ReadOnlyBlockadeState state, IBlockadeHeuristic heuristic, int levels) { if (levels == 0) { var singleLevelResult = this._singleLevelMoveEvaluator.PickBestMove(moves, state, heuristic); return(singleLevelResult != null ? singleLevelResult : Tuple.Create(0, heuristic.LossScore)); } return(moves.Select((m, i) => Tuple.Create(i, this.TryAllOtherPlayerMoves(state.MakeMove(m), heuristic, levels, state.CurrentPlayer))) .OrderByDescending(t => Tuple.Create(t.Item2, this._random.Next())) .First()); }
// static so it can be used in a lazy private static Grid <NullableInt> ComputeConnectedComponents(ReadOnlyBlockadeState state) { var labels = Grid.Create(state.Rows, state.Cols, (row, col) => new NullableInt(default(int?))); var currentLabel = 0; state.GetBoard().ForEach((location, cell) => { if (cell.IsEmpty() && !labels[location].HasValue) { ApplyLabel(state, labels, location, currentLabel); currentLabel++; } }); return(labels); }
private static void ApplyLabel(ReadOnlyBlockadeState state, Grid <NullableInt> labels, Location location, int label) { Throw.If(labels[location].HasValue); labels[location] = new NullableInt(label); GetD1Neighbors(state, location, distance: 1) .ToList() .ForEach(newLocation => { // not using Where() because we need to evaluate condition immediately before recursing if (!labels[newLocation].HasValue && state.GetCell(newLocation).IsEmpty()) { ApplyLabel(state, labels, newLocation, label); } }); }
// static so it can be shared with other statics private static IEnumerable <Location> GetD1Neighbors(ReadOnlyBlockadeState state, Location location, int distance) { if (distance == 1) { return(new[] { Location.Create(location.Row - 1, location.Col), Location.Create(location.Row + 1, location.Col), Location.Create(location.Row, location.Col - 1), Location.Create(location.Row, location.Col + 1) }.Where(l => IsLocationOnBoard(state, l))); } return(Enumerable.Range(0, distance + 1) .Select(x => Tuple.Create(x, distance - x)) .SelectMany(t => new[] { t, Tuple.Create(-t.Item1, t.Item2), Tuple.Create(t.Item1, -t.Item2), Tuple.Create(-t.Item1, -t.Item2) }) .Select(delta => Location.Create(row: location.Row + delta.Item1, col: location.Col + delta.Item2)) .Where(l => IsLocationOnBoard(state, l)) .Distinct()); }
public int PickMove(List <Move> moves, ReadOnlyBlockadeState state) { var okayMoves = moves.Select((m, i) => { var nextState = state.MakeMove(m); return(nextState.GetBoardCalculator() .GetD1Neighbors(m.Location, distance: 1) .Where(l => nextState.GetCell(l).IsEmpty()) .Any() ? i : default(int?)); }) .Where(i => i.HasValue) .Select(i => i.Value) .ToList(); return(okayMoves.Count > 0 ? okayMoves[this._random.Next(okayMoves.Count)] : 0); }
public double TryAllOtherPlayerMoves(ReadOnlyBlockadeState state, IBlockadeHeuristic heuristic, int levels, int myselfPlayer) { if (state.IsGameOver()) { return(state.CurrentPlayer == myselfPlayer ? heuristic.WinScore : heuristic.LossScore); } if (state.CurrentPlayer == myselfPlayer) { return(this.PickBestMove(state.GetMoves().ToList(), state, heuristic, levels - 1).Item2); } return(state.GetMoves() .Select(state.MakeMove) .Select(newState => newState.GetCurrentLocationOfPlayer(myselfPlayer) == null ? heuristic.LossScore : newState.CurrentPlayer == myselfPlayer ? this.PickBestMove(newState.GetMoves().ToList(), newState, heuristic, levels - 1).Item2 : this.TryAllOtherPlayerMoves(newState, heuristic, levels, myselfPlayer)) .Average()); }
public int PickMove(List <Move> moves, ReadOnlyBlockadeState state) { return(this._random.Next(moves.Count)); }
public int PickMove(List <Move> moves, ReadOnlyBlockadeState state) { var tuple = this._simpleMultiLevelEvaluator.PickBestMove(moves, state, new MiraBlockadeHeuristic(this._myProfiler), levels: 1); return(tuple.Item1); }
public double EvaluateState(ReadOnlyBlockadeState state, int player) { return(GetReachableCellScore(state, player) * 100.0 + GetNeighborAversionScore(state, player) * 1.0); }
private static bool IsLocationOnBoard(ReadOnlyBlockadeState state, Location location) { return(location.Row >= 0 && location.Row < state.Rows && location.Col >= 0 && location.Col < state.Cols); }