private static Helper.Way CreateWay(ICell[,] occupy, UsefulRegionDestination destination) { List <Point> points = new List <Point>(); points.Add(destination.Point); Helper.FieldUtils.Fill(occupy, destination.Point, (c2, p2) => { if (c2 != null) { if (!points.Contains(p2)) { points.Add(p2); } return(true); } return(false); }, Direction.All.ParseFlags(true)); return(new Helper.Way(destination.Agent, points.ToArray())); }
/// <summary> /// 得点能率を計算する関数。エージェントからの移動距離は計算されますが、得点能率には加算しません /// </summary> /// <param name="field"></param> /// <param name="map"></param> /// <returns></returns> private List <UsefulRegionEfficiency> CalculateScoreEfficiencies(Field field, bool[][] map) { List <ICell[, ]> occups = new List <ICell[, ]>(); List <ICell[, ]> regions = new List <ICell[, ]>(); List <UsefulRegionDestination> destinations = new List <UsefulRegionDestination>(); var directions8 = Direction.All.ParseFlags(true).ToArray(); var conv = map.Convert(); map.ForEach((p, b) => { ICell[,] regionCells = null; if (b) { /*領域の作成*/ var cell = field.GetCell(p); //このとき領域セルの上下左右は少なくとも領域内となるのでチェックは省略する regionCells = new ICell[field.Height, field.Width]; //領域となるセルをコピーする map.ForEach((p2, b2) => { if (b2) { map[p2.Y][p2.X] = false; regionCells[p2.Y, p2.X] = field.Map[p2.Y, p2.X]; } }); regions.Add(regionCells); /*占有セルの作成*/ //エージェントからの最短地点を格納する UsefulRegionDestination dest = null; //領域セルの外側を塗りつぶす var nonRegion = Helper.FieldUtils.Fill(field.Map, new Point(0, 0), (_, p2) => regionCells[p2.Y, p2.X] == null, directions8); //領域と隣接するセルのみを取り出して占有セルとする ICell[,] occup = new ICell[field.Height, field.Width]; //独立した領域となっているセルを格納する List <ICell[, ]> smallOccups = new List <ICell[, ]>(); nonRegion.ForEach((p2, c) => { if (occup[p2.Y, p2.X] == null && nonRegion[p2.Y, p2.X] != null && OnRegion(field.GetPoints(p2, SearchableDirections))) { var cells = Helper.FieldUtils.Fill(nonRegion, p2, (_, p3) => OnRegion(field.GetPoints(p3, SearchableDirections)), directions8); smallOccups.Add(cells); cells.ForEach((p3, c2) => { if (c2 != null) { occup[p3.Y, p3.X] = c2; //ついでにその位置から各エージェントの距離を調べて短ければ記録 var len = p3.Length(Agent.Position); if (dest == null || dest.Length < len) { if (dest == null) { dest = new UsefulRegionDestination(); dest.Agent = Team.Agent1; } dest.Length = len; dest.Point = p3; dest.Cell = c2; } } }); } }); //独立した領域を最短距離で接続 for (int i = 0; smallOccups.Count > i; i++) { var oc = smallOccups[i]; for (int j = 0; smallOccups.Count > j; j++) { if (i != j) { var points = GetMinimumPoints(oc, smallOccups[j]); var way = points.Item1.Way(points.Item2); foreach (var point in way) { occup[point.Item1.Y, point.Item1.X] = field.GetCell(point.Item1); } occup[points.Item1.Y, points.Item1.X] = field.GetCell(points.Item1); smallOccups.RemoveAt(j--); } } } occups.Add(occup); destinations.Add(dest); } bool OnRegion(IEnumerable <Point> points) { var cells = points.Select(p3 => regionCells[p3.Y, p3.X]); var onRegion = cells.Where(c => c != null).Count() > 0; return(onRegion); } }); //得点能率の大きいものを格納 List <UsefulRegionEfficiency> effics = new List <UsefulRegionEfficiency>(); foreach (var pair in regions.Zip(occups, (r, o) => (r, o)).Zip(destinations, (r, d) => (r, d))) { var e = new UsefulRegionEfficiency(); var region = pair.r.r.Cast <ICell>().Where(c => c != null).Sum(c => Math.Abs(c.Score)); var occup = pair.r.o.Cast <ICell>().Where(c => c != null).Sum(c => c.Score); e.Occupy = pair.r.o; e.Region = pair.r.r; e.Destination = pair.d; e.Way = CreateWay(e.Occupy, e.Destination); var f = Game.Field.Clone(false, true, true); e.Occupy.ForEach((p, c) => { if (c != null) { f.GetCell(p).SetState(TeamEnum, CellState.Occupied); } }); e.Efficiency = new ScoringEfficiency(f, TeamEnum, e.Way.MovePoints.Count); effics.Add(e); } return(effics); }