public Tuple<double, int> _Evaluate(Unit unit) { // Уничтожаемые линии это хорошо var dropped = DroppedLines(unit); double scoreDropped = Math.Pow(dropped.Count(isDrop => isDrop)-1, 2) + dropped.Select((isDrop, i) => isDrop ? 1.0 + ((double)i)/map.Height : 0.0).Sum(); var droppedLines = dropped.Count(isDrop => isDrop); // Занимаем полезные клетки - это хорошо var usabilities = unit.members.Select(m => UsabilityForCells[m]).ToArray(); double scoreOccupied = unit.members.Sum(m => UsabilityForCells[m]); // Ухудшаем возможность занять полезные клетки - это плохо var freeSurroundingCells = GetFreeSurroundingCells(unit); Dictionary<Cell, int> newFreeInputCells = freeSurroundingCells.ToDictionary(c => c, c => CountFreeInputs(c, unit)); double scoreClosed = freeSurroundingCells.Select(c => (newFreeInputCells[c] - freeInputsForCells[c])*UsabilityForCells[c]).Sum(); // Некомпактность - слишком много свободных клеток вокруг - это плохо double scoreCompact = ((double)-freeSurroundingCells.Length)/unit.GetSurroundingCells().Length; // Чем ниже тем лучше double scorePosHeigh = unit.members.Average(m =>((double)m.y)/map.Height); var score = 0.1*scoreDropped + scoreOccupied + 0.5*scoreClosed + 0.2*scoreCompact + 0.1*scorePosHeigh+ 0; return Tuple.Create(score, droppedLines); }
public void Test(HashSet<Cell> unitCells, HashSet<Cell> surround) { Unit unit = new Unit(){members = unitCells, pivot = new Cell(){x=0,y=0}}; var surrounding = unit.GetSurroundingCells(); Assert.IsTrue(surround.Count == surrounding.Length); foreach (var surroundCell in surrounding) Assert.IsTrue(surround.Contains(surroundCell)); }
public double Evaluate(Unit unit) { //Ценность занимаемых ячеек //Чем меньше остается пустых ячеек в строке - тем лучше //Чем меньше в данной стороке "глухих ячек" - тем лучше int score = 0; int nLinesDropped = 0; int[] occupied = new int[map.Height]; foreach (var occupiedCellsInLine in unit.members.GroupBy(m => m.y)) { var y = occupiedCellsInLine.Key; occupied[y] = occupiedCellsInLine.Count(); var newEmptyCells = emptyCells[y].Except(occupiedCellsInLine); int nEmpty = 0, nBlocked = 0; foreach (var c in newEmptyCells) if (CountFreeInputs(c, unit) == 0) nBlocked++; else nEmpty++; int lineScore = (int) (map.Width - nEmpty - nBlocked)*occupied[y]; if (nEmpty + nBlocked == 0) nLinesDropped++; if (lineScore > 0) score += lineScore; } score += map.Width*nLinesDropped*(nLinesDropped+1); // Насколько хорошая позиция юнита // Если рядом стена или заполненная ячейка - отлично // Если рядом пустая ячейка, то ее ценность - сколько у нее входов int surroundingScore = 0; foreach (var surroundingCellsInLine in unit.GetSurroundingCells().GroupBy(c => c.y)) { foreach (var cell in surroundingCellsInLine) { var cellScore = 0; if (!IsCorrect(cell) || map[cell].filled) cellScore= 10; else cellScore = 4*CountFreeInputs(cell, unit); if (cellScore == 0) cellScore= -(map.Width - emptyCells[cell.y].Length + occupied[cell.y] + (map.Width - emptyCells[cell.y].Length - blockedCells[cell.y] + occupied[cell.y] > map.Width*3/4 ? 10 : 0)); surroundingScore += cellScore; } } // Не находится ли юнит рядом с входом int posScore = 0; if (unit.members.Any(cell => (Math.Abs(cell.x - map.Width/2) < 3 && cell.y < 3))) if (nLinesDropped == 0) posScore = -2*map.Width; score = score + surroundingScore + posScore; return score; }
private int[] CountFreeInputsForSurroundingPoints(Unit unit) { List<int> countOfInputs = new List<int>(); foreach (var cell in unit.GetSurroundingCells()) if (cell.x < 0 || cell.y < 0 || cell.x >= map.Width || cell.y >= map.Height) continue; else if (map[cell].filled) continue; else { int nfree = 0; foreach (var move in up) { var c = cell.Move(move); if (c.x < 0 || c.y < 0 || c.x >= map.Width || c.y >= map.Height) continue; if (!map[c].filled && !unit.members.Contains(c)) nfree++; } countOfInputs.Add(nfree); } return countOfInputs.ToArray(); }
private Cell[] GetFreeSurroundingCells(Unit unit) { return unit.GetSurroundingCells().Where(c => freeInputsForCells.ContainsKey(c)).ToArray(); }