CEDEC AI 2013 の決勝で使用したプログラムのソースコード。
| Revision | 379e3190be21c53fb61f5d0ebcfbc770b4845c86 (tree) |
|---|---|
| Time | 2014-04-21 02:23:51 |
| Author | B_head <b_head@outl...> |
| Commiter | B_head |
A*と建築順序最適化(不完全)を実装。
Signed-off-by: B_head <b_head@users.sourceforge.jp>
| @@ -0,0 +1,2 @@ | ||
| 1 | +*/bin | |
| 2 | +*/obj | |
| \ No newline at end of file |
| @@ -0,0 +1,115 @@ | ||
| 1 | +using System; | |
| 2 | +using System.Collections.Generic; | |
| 3 | +using System.Linq; | |
| 4 | +using System.Text; | |
| 5 | + | |
| 6 | +namespace Common | |
| 7 | +{ | |
| 8 | + static class AStar | |
| 9 | + { | |
| 10 | + public static Direction ApproachPoint(this GameField field, Point from, Point to) | |
| 11 | + { | |
| 12 | + SortedSet<RouteNode> open = new SortedSet<RouteNode>(); | |
| 13 | + RouteNode[,] nodeField = new RouteNode[field.Width, field.Height]; | |
| 14 | + int player = field[from].Player; | |
| 15 | + RouteNode start = new RouteNode(from, to, 0, null); | |
| 16 | + nodeField[from.X, from.Y] = start; | |
| 17 | + open.Add(start); | |
| 18 | + while (open.Count > 0) | |
| 19 | + { | |
| 20 | + RouteNode current = open.Min; | |
| 21 | + open.Remove(current); | |
| 22 | + current.Close = true; | |
| 23 | + if (current.Point == to) | |
| 24 | + { | |
| 25 | + return GetApproachingDirection(current); | |
| 26 | + } | |
| 27 | + if (!field.IsOutMove(current.Point)) continue; | |
| 28 | + int goal = current.Goal + 1; | |
| 29 | + foreach (Point point in field.Adjoin(current.Point)) | |
| 30 | + { | |
| 31 | + if (!field.IsInMove(point, field[point].Player == player)) continue; | |
| 32 | + RouteNode temp = nodeField[point.X, point.Y]; | |
| 33 | + if (temp == null) | |
| 34 | + { | |
| 35 | + temp = new RouteNode(point, to, goal, current); | |
| 36 | + nodeField[point.X, point.Y] = temp; | |
| 37 | + open.Add(temp); | |
| 38 | + continue; | |
| 39 | + } | |
| 40 | + if (temp.Goal <= goal) continue; | |
| 41 | + if (!temp.Close) open.Remove(temp); | |
| 42 | + temp.Update(goal, current); | |
| 43 | + open.Add(temp); | |
| 44 | + } | |
| 45 | + } | |
| 46 | + throw new Exception(); | |
| 47 | + } | |
| 48 | + | |
| 49 | + private static Direction GetApproachingDirection(RouteNode node) | |
| 50 | + { | |
| 51 | + Point prev = node.Point; | |
| 52 | + while (node.Parent != null) | |
| 53 | + { | |
| 54 | + prev = node.Point; | |
| 55 | + node = node.Parent; | |
| 56 | + } | |
| 57 | + for (int i = 0; i < 7; i++) | |
| 58 | + { | |
| 59 | + Point point = GameField.TransformDirection(i, node.Point); | |
| 60 | + if (point == prev) return (Direction)i; | |
| 61 | + } | |
| 62 | + throw new Exception(); | |
| 63 | + } | |
| 64 | + | |
| 65 | + class RouteNode : IComparable<RouteNode> | |
| 66 | + { | |
| 67 | + public readonly Point Point; | |
| 68 | + public readonly int Heuristic; | |
| 69 | + public int Goal; | |
| 70 | + public int Fitness; | |
| 71 | + public RouteNode Parent; | |
| 72 | + public bool Close; | |
| 73 | + | |
| 74 | + public RouteNode(Point from, Point to, int goal, RouteNode parent) | |
| 75 | + { | |
| 76 | + this.Point = from; | |
| 77 | + Heuristic = HeuristicCost(from, to); | |
| 78 | + Update(goal, parent); | |
| 79 | + } | |
| 80 | + | |
| 81 | + private int HeuristicCost(Point from, Point to) | |
| 82 | + { | |
| 83 | + int x = from.X - to.X; | |
| 84 | + int y = from.Y - to.Y; | |
| 85 | + int a = Math.Max(Math.Abs(x), Math.Abs(y)); | |
| 86 | + int b = x + y; | |
| 87 | + if (a > b) | |
| 88 | + { | |
| 89 | + return a; | |
| 90 | + } | |
| 91 | + else | |
| 92 | + { | |
| 93 | + return b; | |
| 94 | + } | |
| 95 | + } | |
| 96 | + | |
| 97 | + public void Update(int goal, RouteNode parent) | |
| 98 | + { | |
| 99 | + Goal = goal; | |
| 100 | + Fitness = Goal + Heuristic; | |
| 101 | + Parent = parent; | |
| 102 | + Close = false; | |
| 103 | + } | |
| 104 | + | |
| 105 | + public int CompareTo(RouteNode other) | |
| 106 | + { | |
| 107 | + int f = Fitness.CompareTo(other.Fitness); | |
| 108 | + if (f != 0) return f; | |
| 109 | + int x = Point.X - other.Point.X; | |
| 110 | + if (x != 0) return x; | |
| 111 | + return Point.Y - other.Point.Y; | |
| 112 | + } | |
| 113 | + } | |
| 114 | + } | |
| 115 | +} |
| @@ -0,0 +1,82 @@ | ||
| 1 | +using System; | |
| 2 | +using System.Collections.Generic; | |
| 3 | +using System.Linq; | |
| 4 | +using System.Text; | |
| 5 | + | |
| 6 | +namespace Common | |
| 7 | +{ | |
| 8 | + public class BuildPriority : Field<byte> | |
| 9 | + { | |
| 10 | + public readonly Point Focus; | |
| 11 | + public readonly int MaxPriority; | |
| 12 | + | |
| 13 | + public BuildPriority(GameField gameField, int player, Point focus, int maxPriority) | |
| 14 | + : base(gameField.Width, gameField.Height) | |
| 15 | + { | |
| 16 | + Focus = focus; | |
| 17 | + MaxPriority = maxPriority; | |
| 18 | + SearchPriority(gameField, player); | |
| 19 | + } | |
| 20 | + | |
| 21 | + private void SearchPriority(GameField gameField, int player) | |
| 22 | + { | |
| 23 | + DistanceMap distance = new DistanceMap(gameField, player, Focus); | |
| 24 | + SortedSet<BuildResource> open = new SortedSet<BuildResource>(); | |
| 25 | + BuildResource[,] resourceField = new BuildResource[gameField.Width, gameField.Height]; | |
| 26 | + foreach (Point point in gameField.Iterator()) | |
| 27 | + { | |
| 28 | + if (gameField[point].Terrain != Terrain.Wasteland && gameField[point].Terrain != Terrain.Hole) continue; | |
| 29 | + BuildResource temp = new BuildResource(point, gameField[point].Terrain == Terrain.Hole, distance[point], gameField.GetPrepareResource(point, player, true)); | |
| 30 | + open.Add(temp); | |
| 31 | + resourceField[point.X, point.Y] = temp; | |
| 32 | + } | |
| 33 | + int nextPriority = MaxPriority; | |
| 34 | + while (open.Count > 0) | |
| 35 | + { | |
| 36 | + BuildResource current = open.Min; | |
| 37 | + open.Remove(current); | |
| 38 | + if (current.Resource < 4) continue; | |
| 39 | + this[current.Point] = (byte)nextPriority--; | |
| 40 | + if(nextPriority <= 0) break; | |
| 41 | + if (current.Hole) continue; | |
| 42 | + foreach (Point point in Adjoin(current.Point)) | |
| 43 | + { | |
| 44 | + BuildResource temp = resourceField[point.X, point.Y]; | |
| 45 | + if (temp == null) continue; | |
| 46 | + if (!open.Remove(temp)) continue; | |
| 47 | + temp.Resource--; | |
| 48 | + open.Add(temp); | |
| 49 | + } | |
| 50 | + } | |
| 51 | + } | |
| 52 | + | |
| 53 | + class BuildResource : IComparable<BuildResource> | |
| 54 | + { | |
| 55 | + public readonly Point Point; | |
| 56 | + public readonly bool Hole; | |
| 57 | + public readonly int Distance; | |
| 58 | + public int Resource; | |
| 59 | + | |
| 60 | + public BuildResource(Point point, bool hole, int distance, int resource) | |
| 61 | + { | |
| 62 | + this.Point = point; | |
| 63 | + Hole = hole; | |
| 64 | + Distance = distance; | |
| 65 | + Resource = resource; | |
| 66 | + } | |
| 67 | + | |
| 68 | + public int CompareTo(BuildResource other) | |
| 69 | + { | |
| 70 | + int r = Resource.CompareTo(other.Resource); | |
| 71 | + if (r != 0) return r; | |
| 72 | + if (!Hole && other.Hole) return 1; | |
| 73 | + if (Hole && !other.Hole) return -1; | |
| 74 | + int d = Distance.CompareTo(other.Distance); | |
| 75 | + if (d != 0) return d; | |
| 76 | + int x = Point.X - other.Point.X; | |
| 77 | + if (x != 0) return x; | |
| 78 | + return Point.Y - other.Point.Y; | |
| 79 | + } | |
| 80 | + } | |
| 81 | + } | |
| 82 | +} |
| @@ -1,4 +1,5 @@ | ||
| 1 | 1 | using System; |
| 2 | +using System.Collections.ObjectModel; | |
| 2 | 3 | using System.Collections.Generic; |
| 3 | 4 | using System.Linq; |
| 4 | 5 | using System.Text; |
| @@ -55,6 +56,22 @@ namespace Common | ||
| 55 | 56 | } |
| 56 | 57 | } |
| 57 | 58 | |
| 59 | + public struct TownPlan | |
| 60 | + { | |
| 61 | + public readonly int VictoryPoint; | |
| 62 | + public readonly int SpendRobot; | |
| 63 | + public readonly Point Excavator; | |
| 64 | + public readonly ReadOnlyCollection<Point> Town; | |
| 65 | + | |
| 66 | + public TownPlan(int victoryPoint, int spendRobot, Point excavator, ReadOnlyCollection<Point> town) | |
| 67 | + { | |
| 68 | + VictoryPoint = victoryPoint; | |
| 69 | + SpendRobot = spendRobot; | |
| 70 | + Excavator = excavator; | |
| 71 | + Town = town; | |
| 72 | + } | |
| 73 | + } | |
| 74 | + | |
| 58 | 75 | public enum Terrain |
| 59 | 76 | { |
| 60 | 77 | Outside = 0, |
| @@ -39,6 +39,8 @@ | ||
| 39 | 39 | <Reference Include="System.Xml" /> |
| 40 | 40 | </ItemGroup> |
| 41 | 41 | <ItemGroup> |
| 42 | + <Compile Include="AStar.cs" /> | |
| 43 | + <Compile Include="BuildPriority.cs" /> | |
| 42 | 44 | <Compile Include="Common.cs" /> |
| 43 | 45 | <Compile Include="DispositionRobot.cs" /> |
| 44 | 46 | <Compile Include="DistanceMap.cs" /> |
| @@ -14,47 +14,53 @@ namespace Common | ||
| 14 | 14 | Player = player; |
| 15 | 15 | } |
| 16 | 16 | |
| 17 | - public void AddMoveOrder(int priority, Point point, int robot, bool once) | |
| 17 | + public void AddMoveOrder(int priority, Point point, int robot) | |
| 18 | 18 | { |
| 19 | - OrderSecure temp = new OrderSecure(priority, once, point, robot); | |
| 19 | + OrderMove temp = new OrderMove(priority, point, robot); | |
| 20 | 20 | Add(temp); |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | - public void AddBuildOrder(int priority, Point point, Terrain building, bool once) | |
| 23 | + public void AddBuildOrder(int priority, Point point, Terrain building) | |
| 24 | 24 | { |
| 25 | - OrderBuild temp = new OrderBuild(priority, once, point, building); | |
| 26 | - Add(temp); | |
| 25 | + OrderBuild b = new OrderBuild(priority, point, building); | |
| 26 | + Add(b); | |
| 27 | 27 | } |
| 28 | 28 | |
| 29 | - public void AddSecureResource(int priority, Point point, GameField field) | |
| 29 | + public void AddSecureResource(int priority, Point point, int player, GameField field) | |
| 30 | 30 | { |
| 31 | 31 | foreach(Point temp in field.Adjoin(point)) |
| 32 | 32 | { |
| 33 | 33 | if (field[temp].Terrain != Terrain.Wasteland) continue; |
| 34 | - AddMoveOrder(priority, temp, field[temp].WaitRobot + 1, true); | |
| 34 | + if (field[temp].Player == player) continue; | |
| 35 | + AddMoveOrder(priority, temp, field[temp].WaitRobot + 1); | |
| 35 | 36 | } |
| 36 | 37 | } |
| 37 | 38 | |
| 38 | - public void AddSecureGround(int priority, int borderRobot, Point initial, GameField field) | |
| 39 | + public void AddSecureGround(int invadePriority, int guardPriority, int player, GameField field) | |
| 39 | 40 | { |
| 40 | - SearchSecureGround(priority, borderRobot, initial, field, new bool[field.Width, field.Height]); | |
| 41 | - } | |
| 42 | - | |
| 43 | - private void SearchSecureGround(int priority, int borderRobot, Point point, GameField field, bool[,] searched) | |
| 44 | - { | |
| 45 | - searched[point.X, point.Y] = true; | |
| 46 | - if (field[point].Player != Player && field[point].Terrain == Terrain.Wasteland) | |
| 41 | + foreach (Point point in field.Iterator()) | |
| 47 | 42 | { |
| 48 | - if (field[point].WaitRobot <= borderRobot) | |
| 43 | + if (field[point].Terrain != Terrain.Wasteland) continue; | |
| 44 | + if (!field.IsBoundary(point, player)) continue; | |
| 45 | + if (field[point].Player == player) | |
| 49 | 46 | { |
| 50 | - AddMoveOrder(priority - field[point].WaitRobot, point, field[point].WaitRobot + 1, true); | |
| 47 | + AddMoveOrder(guardPriority, point, 1); | |
| 48 | + } | |
| 49 | + else | |
| 50 | + { | |
| 51 | + if (field[point].WaitRobot > 0) continue; | |
| 52 | + AddMoveOrder(invadePriority, point, 1); | |
| 51 | 53 | } |
| 52 | - return; | |
| 53 | 54 | } |
| 54 | - foreach (Point temp in field.Adjoin(point)) | |
| 55 | + } | |
| 56 | + | |
| 57 | + public void AddKamikaze(int priority, int player, GameField field) | |
| 58 | + { | |
| 59 | + foreach (Point point in field.Iterator()) | |
| 55 | 60 | { |
| 56 | - if (searched[temp.X, temp.Y]) continue; | |
| 57 | - SearchSecureGround(priority, borderRobot, temp, field, searched); | |
| 61 | + if (field[point].Terrain != Terrain.Wasteland) continue; | |
| 62 | + if (field[point].Player == player)continue; | |
| 63 | + AddMoveOrder(priority - field[point].WaitRobot, point, field[point].WaitRobot + 1); | |
| 58 | 64 | } |
| 59 | 65 | } |
| 60 | 66 |
| @@ -73,15 +79,18 @@ namespace Common | ||
| 73 | 79 | public void Dispose(GameField field, ICommander commander) |
| 74 | 80 | { |
| 75 | 81 | Sort(); |
| 82 | + bool isOrderBuild = false; | |
| 76 | 83 | for (int i = Count - 1; i >= 0; i--) |
| 77 | 84 | { |
| 78 | - if (this[i].Execute(field, commander) || this[i].Once) | |
| 85 | + if (this[i] is OrderBuild) | |
| 79 | 86 | { |
| 80 | - this[i] = null; | |
| 87 | + if (isOrderBuild) continue; | |
| 88 | + isOrderBuild = true; | |
| 81 | 89 | } |
| 90 | + this[i].Execute(field, commander); | |
| 82 | 91 | } |
| 92 | + Clear(); | |
| 83 | 93 | commander.Finish(); |
| 84 | - RemoveAll(o => o == null); | |
| 85 | 94 | } |
| 86 | 95 | } |
| 87 | 96 | } |
| @@ -17,55 +17,30 @@ namespace Common | ||
| 17 | 17 | this.gameField = gameField; |
| 18 | 18 | this.center = center; |
| 19 | 19 | Initalize(); |
| 20 | - Investigate(0, player, center.X, center.Y); | |
| 20 | + Investigate(0, player, center); | |
| 21 | 21 | } |
| 22 | 22 | |
| 23 | 23 | private void Initalize() |
| 24 | 24 | { |
| 25 | - for (int x = 0; x < Width; x++) | |
| 25 | + foreach(Point point in Iterator()) | |
| 26 | 26 | { |
| 27 | - for (int y = 0; y < Height; y++) | |
| 28 | - { | |
| 29 | - field[x, y] = Impossible; | |
| 30 | - } | |
| 27 | + this[point] = Impossible; | |
| 31 | 28 | } |
| 32 | 29 | } |
| 33 | 30 | |
| 34 | - private void Investigate(byte distanse, int player, int x, int y) | |
| 31 | + private void Investigate(byte distanse, int player, Point point) | |
| 35 | 32 | { |
| 36 | - if (!IsInRange(x, y)) return; | |
| 37 | - if (field[x, y] <= distanse) return; | |
| 38 | - if (gameField[x, y].Terrain == Terrain.Outside) return; | |
| 39 | - if (gameField[x, y].Player != player && | |
| 40 | - gameField[x, y].Terrain != Terrain.Wasteland && gameField[x, y].Terrain != Terrain.Hole) return; | |
| 41 | - field[x, y] = distanse; | |
| 42 | - if (gameField[x, y].Terrain == Terrain.Hole && distanse > 0) return; | |
| 43 | - int tx, ty; | |
| 44 | - for (int i = 1; i < 7; i++) | |
| 33 | + if (!IsInRange(point)) return; | |
| 34 | + if (this[point] <= distanse) return; | |
| 35 | + if (gameField[point].Terrain == Terrain.Outside) return; | |
| 36 | + if (gameField[point].Player != player && | |
| 37 | + gameField[point].Terrain != Terrain.Wasteland && gameField[point].Terrain != Terrain.Hole) return; | |
| 38 | + this[point] = distanse; | |
| 39 | + if (gameField[point].Terrain == Terrain.Hole && distanse > 0) return; | |
| 40 | + foreach(Point temp in Adjoin(point)) | |
| 45 | 41 | { |
| 46 | - TransformDirection(i, x, y, out tx, out ty); | |
| 47 | - Investigate((byte)(distanse + 1), player, tx, ty); | |
| 42 | + Investigate((byte)(distanse + 1), player, temp); | |
| 48 | 43 | } |
| 49 | 44 | } |
| 50 | - | |
| 51 | - public Direction ApproachTerget(Point point) | |
| 52 | - { | |
| 53 | - return ApproachTerget(point.X, point.Y); | |
| 54 | - } | |
| 55 | - | |
| 56 | - public Direction ApproachTerget(int x, int y) | |
| 57 | - { | |
| 58 | - int tx, ty; | |
| 59 | - for (int i = 1; i < 7; i++) | |
| 60 | - { | |
| 61 | - if (TransformDirection(i, x, y, out tx, out ty)) continue; | |
| 62 | - if (gameField[tx, ty].Terrain == Terrain.Hole && field[tx, ty] != 0) continue; | |
| 63 | - if (field[x, y] - 1 == field[tx, ty]) | |
| 64 | - { | |
| 65 | - return (Direction)i; | |
| 66 | - } | |
| 67 | - } | |
| 68 | - return Direction.Center; | |
| 69 | - } | |
| 70 | 45 | } |
| 71 | 46 | } |
| @@ -31,6 +31,82 @@ namespace Common | ||
| 31 | 31 | return count >= 7; |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | + public static bool IsAdjoinTerritory(this GameField field, Point point, int player) | |
| 35 | + { | |
| 36 | + foreach (Point temp in field.Adjoin(point)) | |
| 37 | + { | |
| 38 | + if (field[temp].Terrain == Terrain.Hole) continue; | |
| 39 | + if (field[temp].Terrain == Terrain.Outside) continue; | |
| 40 | + if (field[temp].Player == player) return true; | |
| 41 | + } | |
| 42 | + return false; | |
| 43 | + } | |
| 44 | + | |
| 45 | + public static bool IsBoundary(this GameField field, Point point, int player) | |
| 46 | + { | |
| 47 | + if (field[point].Player == player) | |
| 48 | + { | |
| 49 | + foreach (Point temp in field.Adjoin(point)) | |
| 50 | + { | |
| 51 | + if (field[temp].Terrain == Terrain.Hole) continue; | |
| 52 | + if (field[temp].Terrain == Terrain.Outside) continue; | |
| 53 | + if (field[temp].Player != player) return true; | |
| 54 | + } | |
| 55 | + return false; | |
| 56 | + } | |
| 57 | + else | |
| 58 | + { | |
| 59 | + foreach (Point temp in field.Adjoin(point)) | |
| 60 | + { | |
| 61 | + if (field[temp].Terrain == Terrain.Hole) continue; | |
| 62 | + if (field[temp].Terrain == Terrain.Outside) continue; | |
| 63 | + if (field[temp].Player == player) return true; | |
| 64 | + } | |
| 65 | + return false; | |
| 66 | + } | |
| 67 | + } | |
| 68 | + | |
| 69 | + public static Point GetNearComer(this GameField field, Point point) | |
| 70 | + { | |
| 71 | + int com = field.Size - 1; | |
| 72 | + int x = point.X - com, y = point.Y - com; | |
| 73 | + int a = Math.Max(Math.Abs(x), Math.Abs(y)); | |
| 74 | + int b = x + y; | |
| 75 | + if (a > b) | |
| 76 | + { | |
| 77 | + if (x < 0) | |
| 78 | + { | |
| 79 | + return new Point { X = 0, Y = com * 2 }; | |
| 80 | + } | |
| 81 | + else | |
| 82 | + { | |
| 83 | + return new Point { X = com * 2, Y = 0 }; | |
| 84 | + } | |
| 85 | + } | |
| 86 | + else if (Math.Abs(x) > Math.Abs(y)) | |
| 87 | + { | |
| 88 | + if (x < 0) | |
| 89 | + { | |
| 90 | + return new Point { X = 0, Y = com }; | |
| 91 | + } | |
| 92 | + else | |
| 93 | + { | |
| 94 | + return new Point { X = com * 2, Y = com }; | |
| 95 | + } | |
| 96 | + } | |
| 97 | + else | |
| 98 | + { | |
| 99 | + if (x < 0) | |
| 100 | + { | |
| 101 | + return new Point { X = com, Y = 0 }; | |
| 102 | + } | |
| 103 | + else | |
| 104 | + { | |
| 105 | + return new Point { X = com, Y = com * 2 }; | |
| 106 | + } | |
| 107 | + } | |
| 108 | + } | |
| 109 | + | |
| 34 | 110 | public static IEnumerable<Point> NearIterator(this GameField field, Point center, int player) |
| 35 | 111 | { |
| 36 | 112 | bool[,] searched = new bool[field.Width, field.Height]; |
| @@ -6,9 +6,9 @@ using System.Threading.Tasks; | ||
| 6 | 6 | |
| 7 | 7 | namespace Common |
| 8 | 8 | { |
| 9 | - public class Field<TYPE> | |
| 9 | + public class Field<T> | |
| 10 | 10 | { |
| 11 | - protected TYPE[,] field; | |
| 11 | + protected T[,] field; | |
| 12 | 12 | public readonly int Width; |
| 13 | 13 | public readonly int Height; |
| 14 | 14 |
| @@ -16,10 +16,10 @@ namespace Common | ||
| 16 | 16 | { |
| 17 | 17 | Width = width; |
| 18 | 18 | Height = height; |
| 19 | - field = new TYPE[width, height]; | |
| 19 | + field = new T[width, height]; | |
| 20 | 20 | } |
| 21 | 21 | |
| 22 | - public TYPE this[int x, int y] | |
| 22 | + public T this[int x, int y] | |
| 23 | 23 | { |
| 24 | 24 | get |
| 25 | 25 | { |
| @@ -31,7 +31,7 @@ namespace Common | ||
| 31 | 31 | } |
| 32 | 32 | } |
| 33 | 33 | |
| 34 | - public TYPE this[Point point] | |
| 34 | + public T this[Point point] | |
| 35 | 35 | { |
| 36 | 36 | get |
| 37 | 37 | { |
| @@ -43,114 +43,80 @@ namespace Common | ||
| 43 | 43 | } |
| 44 | 44 | } |
| 45 | 45 | |
| 46 | - public void CopyTo(Field<TYPE> other) | |
| 46 | + public void CopyTo(Field<T> other) | |
| 47 | 47 | { |
| 48 | 48 | Array.Copy(field, other.field, Width * Height); |
| 49 | 49 | } |
| 50 | 50 | |
| 51 | 51 | public bool IsInRange(Point point) |
| 52 | 52 | { |
| 53 | - return IsInRange(point.X, point.Y); | |
| 53 | + return point.X >= 0 && point.X < Width && point.Y >= 0 && point.Y < Height; | |
| 54 | 54 | } |
| 55 | 55 | |
| 56 | - public bool IsInRange(int x, int y) | |
| 56 | + public static Point TransformDirection(int dir, Point point) | |
| 57 | 57 | { |
| 58 | - return x >= 0 && x < Width && y >= 0 && y < Height; | |
| 58 | + return TransformDirection((Direction)dir, point); | |
| 59 | 59 | } |
| 60 | 60 | |
| 61 | - public bool TransformDirection(int dir, int x, int y, out int tx, out int ty) | |
| 61 | + public static Point TransformDirection(Direction dir, Point point) | |
| 62 | 62 | { |
| 63 | - return TransformDirection((Direction)dir, x, y, out tx, out ty); | |
| 64 | - } | |
| 65 | - | |
| 66 | - public Point TransformDirection(int dir, Point from) | |
| 67 | - { | |
| 68 | - return TransformDirection((Direction)dir, from); | |
| 69 | - } | |
| 70 | - | |
| 71 | - public Point TransformDirection(Direction dir, Point from) | |
| 72 | - { | |
| 73 | - Point result; | |
| 74 | - TransformDirection((Direction)dir, from.X, from.Y, out result.X, out result.Y); | |
| 75 | - return result; | |
| 76 | - } | |
| 77 | - | |
| 78 | - public bool TransformDirection(Direction dir, int x, int y, out int tx, out int ty) | |
| 79 | - { | |
| 80 | - tx = x; | |
| 81 | - ty = y; | |
| 63 | + Point result = point; | |
| 82 | 64 | switch (dir) |
| 83 | 65 | { |
| 84 | - case Direction.Center: tx += 0; ty += 0; break; | |
| 85 | - case Direction.Right: tx += 1; ty += 0; break; | |
| 86 | - case Direction.UpperRight: tx += 1; ty += -1; break; | |
| 87 | - case Direction.DownerRight: tx += 0; ty += 1; break; | |
| 88 | - case Direction.Left: tx += -1; ty += 0; break; | |
| 89 | - case Direction.DownerLeft: tx += -1; ty += 1; break; | |
| 90 | - case Direction.UpperLeft: tx += 0; ty += -1; break; | |
| 66 | + case Direction.Center: result.X += 0; result.Y += 0; break; | |
| 67 | + case Direction.Right: result.X += 1; result.Y += 0; break; | |
| 68 | + case Direction.UpperRight: result.X += 1; result.Y += -1; break; | |
| 69 | + case Direction.DownerRight: result.X += 0; result.Y += 1; break; | |
| 70 | + case Direction.Left: result.X += -1; result.Y += 0; break; | |
| 71 | + case Direction.DownerLeft: result.X += -1; result.Y += 1; break; | |
| 72 | + case Direction.UpperLeft: result.X += 0; result.Y += -1; break; | |
| 91 | 73 | default: throw new Exception(); |
| 92 | 74 | } |
| 93 | - return !IsInRange(tx, ty); | |
| 94 | - } | |
| 95 | - | |
| 96 | - public Point TransformTowerRange(int i, Point from) | |
| 97 | - { | |
| 98 | - Point result; | |
| 99 | - TransformTowerRange(i, from.X, from.Y, out result.X, out result.Y); | |
| 100 | 75 | return result; |
| 101 | 76 | } |
| 102 | 77 | |
| 103 | - public bool TransformTowerRange(int i, int x, int y, out int tx, out int ty) | |
| 78 | + public static Point TransformTowerRange(int i, Point point) | |
| 104 | 79 | { |
| 105 | - tx = x; | |
| 106 | - ty = y; | |
| 80 | + Point result = point; | |
| 107 | 81 | switch (i) |
| 108 | 82 | { |
| 109 | - case 0: tx += 1; ty += 0; break; | |
| 110 | - case 1: tx += 1; ty += -1; break; | |
| 111 | - case 2: tx += 0; ty += 1; break; | |
| 112 | - case 3: tx += -1; ty += 0; break; | |
| 113 | - case 4: tx += -1; ty += 1; break; | |
| 114 | - case 5: tx += 0; ty += -1; break; | |
| 115 | - case 6: tx += 2; ty += 0; break; | |
| 116 | - case 7: tx += 2; ty += -2; break; | |
| 117 | - case 8: tx += 0; ty += 2; break; | |
| 118 | - case 9: tx += -2; ty += 0; break; | |
| 119 | - case 10: tx += -2; ty += 2; break; | |
| 120 | - case 11: tx += 0; ty += -2; break; | |
| 83 | + case 0: result.X += 1; result.Y += 0; break; | |
| 84 | + case 1: result.X += 1; result.Y += -1; break; | |
| 85 | + case 2: result.X += 0; result.Y += 1; break; | |
| 86 | + case 3: result.X += -1; result.Y += 0; break; | |
| 87 | + case 4: result.X += -1; result.Y += 1; break; | |
| 88 | + case 5: result.X += 0; result.Y += -1; break; | |
| 89 | + case 6: result.X += 2; result.Y += 0; break; | |
| 90 | + case 7: result.X += 2; result.Y += -2; break; | |
| 91 | + case 8: result.X += 0; result.Y += 2; break; | |
| 92 | + case 9: result.X += -2; result.Y += 0; break; | |
| 93 | + case 10: result.X += -2; result.Y += 2; break; | |
| 94 | + case 11: result.X += 0; result.Y += -2; break; | |
| 121 | 95 | default: throw new Exception(); |
| 122 | 96 | } |
| 123 | - return !IsInRange(tx, ty); | |
| 124 | - } | |
| 125 | - | |
| 126 | - public Point TransformSitePropose(int i, Point from) | |
| 127 | - { | |
| 128 | - Point result; | |
| 129 | - TransformSitePropose(i, from.X, from.Y, out result.X, out result.Y); | |
| 130 | 97 | return result; |
| 131 | 98 | } |
| 132 | 99 | |
| 133 | - public bool TransformSitePropose(int i, int x, int y, out int tx, out int ty) | |
| 100 | + public static Point TransformSitePropose(int i, Point point) | |
| 134 | 101 | { |
| 135 | - tx = x; | |
| 136 | - ty = y; | |
| 102 | + Point result = point; | |
| 137 | 103 | switch (i) |
| 138 | 104 | { |
| 139 | - case 0: tx += 1; ty += 0; break; | |
| 140 | - case 1: tx += 1; ty += 1; break; | |
| 141 | - case 2: tx += 0; ty += 1; break; | |
| 142 | - case 3: tx += -1; ty += 2; break; | |
| 143 | - case 4: tx += -1; ty += 1; break; | |
| 144 | - case 5: tx += -2; ty += 1; break; | |
| 145 | - case 6: tx += -1; ty += 0; break; | |
| 146 | - case 7: tx += -1; ty += -1; break; | |
| 147 | - case 8: tx += 0; ty += -1; break; | |
| 148 | - case 9: tx += 1; ty += -2; break; | |
| 149 | - case 10: tx += 1; ty += -1; break; | |
| 150 | - case 11: tx += 2; ty += -1; break; | |
| 105 | + case 0: result.X += 1; result.Y += 0; break; | |
| 106 | + case 1: result.X += 1; result.Y += 1; break; | |
| 107 | + case 2: result.X += 0; result.Y += 1; break; | |
| 108 | + case 3: result.X += -1; result.Y += 2; break; | |
| 109 | + case 4: result.X += -1; result.Y += 1; break; | |
| 110 | + case 5: result.X += -2; result.Y += 1; break; | |
| 111 | + case 6: result.X += -1; result.Y += 0; break; | |
| 112 | + case 7: result.X += -1; result.Y += -1; break; | |
| 113 | + case 8: result.X += 0; result.Y += -1; break; | |
| 114 | + case 9: result.X += 1; result.Y += -2; break; | |
| 115 | + case 10: result.X += 1; result.Y += -1; break; | |
| 116 | + case 11: result.X += 2; result.Y += -1; break; | |
| 151 | 117 | default: throw new Exception(); |
| 152 | 118 | } |
| 153 | - return !IsInRange(tx, ty); | |
| 119 | + return result; | |
| 154 | 120 | } |
| 155 | 121 | |
| 156 | 122 | public IEnumerable<Point> Adjoin(Point point, bool center = false) |
| @@ -23,7 +23,8 @@ namespace Common | ||
| 23 | 23 | disposition = new DispositionRobot(player); |
| 24 | 24 | InitialPoint = field.GetInitialPoint(player); |
| 25 | 25 | planning = new TownPlanning(field); |
| 26 | - int max = planning.Max(p => p.SpendRobot); | |
| 26 | + var forbid = planning.ForbidPoint(new Point { X = 6, Y = 6 }, field); | |
| 27 | + int max = forbid.Max(p => p.SpendRobot); | |
| 27 | 28 | var maxPlans = planning.Where(p => p.SpendRobot == max); |
| 28 | 29 | foreach (Point point in field.NearIterator(InitialPoint, player)) |
| 29 | 30 | { |
| @@ -36,96 +37,44 @@ namespace Common | ||
| 36 | 37 | |
| 37 | 38 | public void Think(int turn, int maxTurn, int player, GameField field, ICommander commander) |
| 38 | 39 | { |
| 39 | - DistanceMap distance = new DistanceMap(field, player, InitialPoint); | |
| 40 | - Point fieldCenter = new Point { X = 6, Y = 6 }; | |
| 41 | - if (field.GetPrepareResource(plan.Excavator, player, true) >= 4 && plan.Excavator != fieldCenter) | |
| 40 | + if (field.GetPrepareResource(plan.Excavator, player, true) >= 4 && field[plan.Excavator].Terrain == Terrain.Wasteland) | |
| 42 | 41 | { |
| 43 | - disposition.AddBuildOrder(200, plan.Excavator, Terrain.Excavator, true); | |
| 42 | + disposition.AddBuildOrder(1000, plan.Excavator, Terrain.Excavator); | |
| 43 | + disposition.AddMoveOrder(100, plan.Excavator, GameField.GetNeedRobot(Terrain.Excavator)); | |
| 44 | 44 | } |
| 45 | 45 | foreach (Point town in plan.Town) |
| 46 | 46 | { |
| 47 | 47 | if (field.GetPrepareResource(town, player, true) < 9) continue; |
| 48 | - if (town == fieldCenter) continue; | |
| 49 | - disposition.AddBuildOrder(200, town, Terrain.Town, true); | |
| 48 | + disposition.AddBuildOrder(1000, town, Terrain.Town); | |
| 49 | + disposition.AddMoveOrder(100, town, GameField.GetNeedRobot(Terrain.Town)); | |
| 50 | 50 | } |
| 51 | - foreach (Point point in field.NearIterator(InitialPoint, player)) | |
| 51 | + DistanceMap distance = new DistanceMap(field, player, InitialPoint); | |
| 52 | + BuildPriority priority = new BuildPriority(field, player, InitialPoint, 99); | |
| 53 | + foreach (Point point in field.Iterator()) | |
| 52 | 54 | { |
| 53 | 55 | if (field.GetPrepareResource(point, player, true) < 4) continue; |
| 54 | - if (field[point].Terrain == Terrain.Hole) | |
| 56 | + if (!field.IsAdjoinTerritory(point, player)) continue; | |
| 57 | + if (point == new Point { X = 6, Y = 6 }) continue; | |
| 58 | + Terrain building; | |
| 59 | + switch(field[point].Terrain) | |
| 55 | 60 | { |
| 56 | - disposition.AddBuildOrder(100 - distance[point], point, Terrain.Bridge, true); | |
| 61 | + case Terrain.Wasteland: building = Terrain.House; break; | |
| 62 | + case Terrain.Hole: building = Terrain.Bridge; break; | |
| 63 | + default: continue; | |
| 57 | 64 | } |
| 58 | - else if (field[point].Terrain == Terrain.Wasteland) | |
| 59 | - { | |
| 60 | - disposition.AddBuildOrder(100 - distance[point], point, Terrain.House, true); | |
| 61 | - } | |
| 62 | - else | |
| 63 | - { | |
| 64 | - continue; | |
| 65 | - } | |
| 66 | - break; | |
| 65 | + disposition.AddBuildOrder(priority[point] * 10, point, building); | |
| 66 | + disposition.AddMoveOrder(priority[point], point, GameField.GetNeedRobot(building)); | |
| 67 | 67 | } |
| 68 | 68 | foreach (OrderBuild build in disposition.EnumerateOrder<OrderBuild>()) |
| 69 | 69 | { |
| 70 | - disposition.AddSecureResource(build.Priority - 1, build.Point, field); | |
| 70 | + disposition.AddSecureResource(build.Priority / 10 - 1, build.Point, player, field); | |
| 71 | 71 | } |
| 72 | - disposition.AddSecureGround(0, 0, InitialPoint, field); | |
| 72 | + disposition.AddSecureGround(150, 100, player, field); | |
| 73 | + disposition.AddKamikaze(0, player, field); | |
| 73 | 74 | disposition.Dispose(field, commander); |
| 74 | 75 | } |
| 75 | 76 | } |
| 76 | 77 | |
| 77 | - public class KamikazeAI : IGameAI | |
| 78 | - { | |
| 79 | - public string Prepare(int player, GameField field) | |
| 80 | - { | |
| 81 | - throw new NotImplementedException(); | |
| 82 | - } | |
| 83 | - | |
| 84 | - public void Think(int turn, int maxTurn, int player, GameField field, ICommander commander) | |
| 85 | - { | |
| 86 | - throw new NotImplementedException(); | |
| 87 | - } | |
| 88 | - } | |
| 89 | - | |
| 90 | - public class InvadeAI : IGameAI | |
| 91 | - { | |
| 92 | - public string Prepare(int player, GameField field) | |
| 93 | - { | |
| 94 | - throw new NotImplementedException(); | |
| 95 | - } | |
| 96 | - | |
| 97 | - public void Think(int turn, int maxTurn, int player, GameField field, ICommander commander) | |
| 98 | - { | |
| 99 | - throw new NotImplementedException(); | |
| 100 | - } | |
| 101 | - } | |
| 102 | - | |
| 103 | - public class GovernAI : IGameAI | |
| 104 | - { | |
| 105 | - public string Prepare(int player, GameField field) | |
| 106 | - { | |
| 107 | - throw new NotImplementedException(); | |
| 108 | - } | |
| 109 | - | |
| 110 | - public void Think(int turn, int maxTurn, int player, GameField field, ICommander commander) | |
| 111 | - { | |
| 112 | - throw new NotImplementedException(); | |
| 113 | - } | |
| 114 | - } | |
| 115 | - | |
| 116 | - public class CompanyAI : IGameAI | |
| 117 | - { | |
| 118 | - public string Prepare(int player, GameField field) | |
| 119 | - { | |
| 120 | - throw new NotImplementedException(); | |
| 121 | - } | |
| 122 | - | |
| 123 | - public void Think(int turn, int maxTurn, int player, GameField field, ICommander commander) | |
| 124 | - { | |
| 125 | - throw new NotImplementedException(); | |
| 126 | - } | |
| 127 | - } | |
| 128 | - | |
| 129 | 78 | public class TestAI : IGameAI |
| 130 | 79 | { |
| 131 | 80 | Random random; |
| @@ -161,7 +161,7 @@ namespace Common | ||
| 161 | 161 | } |
| 162 | 162 | } |
| 163 | 163 | |
| 164 | - public int GetNeedRobot(Terrain ter) | |
| 164 | + public static int GetNeedRobot(Terrain ter) | |
| 165 | 165 | { |
| 166 | 166 | switch (ter) |
| 167 | 167 | { |
| @@ -175,7 +175,7 @@ namespace Common | ||
| 175 | 175 | } |
| 176 | 176 | } |
| 177 | 177 | |
| 178 | - public int GetNeedResource(Terrain ter) | |
| 178 | + public static int GetNeedResource(Terrain ter) | |
| 179 | 179 | { |
| 180 | 180 | switch (ter) |
| 181 | 181 | { |
| @@ -8,17 +8,15 @@ namespace Common | ||
| 8 | 8 | public abstract class Order : IComparable<Order> |
| 9 | 9 | { |
| 10 | 10 | public readonly int Priority; |
| 11 | - public readonly bool Once; | |
| 12 | 11 | public readonly Point Point; |
| 13 | 12 | |
| 14 | - public Order(int priority, bool once, Point point) | |
| 13 | + public Order(int priority, Point point) | |
| 15 | 14 | { |
| 16 | 15 | this.Priority = priority; |
| 17 | - this.Once = once; | |
| 18 | 16 | this.Point = point; |
| 19 | 17 | } |
| 20 | 18 | |
| 21 | - public abstract bool Execute(GameField field, ICommander commander); | |
| 19 | + public abstract void Execute(GameField field, ICommander commander); | |
| 22 | 20 | |
| 23 | 21 | protected bool IsForbidMove(ICommander commander) |
| 24 | 22 | { |
| @@ -30,16 +28,15 @@ namespace Common | ||
| 30 | 28 | return commander.IsMove || commander.IsBuild || commander.IsFinish; |
| 31 | 29 | } |
| 32 | 30 | |
| 33 | - protected bool NearRobotMove(Point point, int robot, GameField field, ICommander commander) | |
| 31 | + protected void NearRobotMove(Point point, int robot, GameField field, ICommander commander) | |
| 34 | 32 | { |
| 35 | 33 | int moveCount = 0; |
| 36 | - DistanceMap distance = new DistanceMap(field, commander.Player, point); | |
| 37 | 34 | foreach (Point temp in field.NearIterator(point, commander.Player)) |
| 38 | 35 | { |
| 39 | 36 | if (field[temp].ActiveRobot <= 0) continue; |
| 40 | 37 | if (field[temp].Terrain == Terrain.Hole && !point.Equals(temp)) continue; |
| 41 | 38 | int moveRobot = Math.Min(field[temp].ActiveRobot, robot - moveCount); |
| 42 | - Direction dir = distance.ApproachTerget(temp); | |
| 39 | + Direction dir = field.ApproachPoint(temp, point); | |
| 43 | 40 | if (!field.Move(temp, dir, moveRobot)) throw new Exception(); |
| 44 | 41 | if (dir != Direction.Center) |
| 45 | 42 | { |
| @@ -48,7 +45,6 @@ namespace Common | ||
| 48 | 45 | moveCount += moveRobot; |
| 49 | 46 | if (moveCount >= robot) break; |
| 50 | 47 | } |
| 51 | - return false; | |
| 52 | 48 | } |
| 53 | 49 | |
| 54 | 50 | public int CompareTo(Order other) |
| @@ -61,22 +57,20 @@ namespace Common | ||
| 61 | 57 | } |
| 62 | 58 | } |
| 63 | 59 | |
| 64 | - public class OrderSecure : Order | |
| 60 | + public class OrderMove : Order | |
| 65 | 61 | { |
| 66 | 62 | public readonly int Robot; |
| 67 | 63 | |
| 68 | - public OrderSecure(int priority, bool once, Point point, int robot) | |
| 69 | - : base(priority, once, point) | |
| 64 | + public OrderMove(int priority, Point point, int robot) | |
| 65 | + : base(priority, point) | |
| 70 | 66 | { |
| 71 | 67 | this.Robot = robot; |
| 72 | 68 | } |
| 73 | 69 | |
| 74 | - public override bool Execute(GameField field, ICommander commander) | |
| 70 | + public override void Execute(GameField field, ICommander commander) | |
| 75 | 71 | { |
| 76 | - if (IsForbidMove(commander)) return false; | |
| 77 | - if (field[this.Point].Terrain != Terrain.Wasteland) return true; | |
| 78 | - if (NearRobotMove(this.Point, Robot, field, commander)) return true; | |
| 79 | - return false; | |
| 72 | + if (IsForbidMove(commander)) return; | |
| 73 | + NearRobotMove(this.Point, Robot, field, commander); | |
| 80 | 74 | } |
| 81 | 75 | } |
| 82 | 76 |
| @@ -84,23 +78,17 @@ namespace Common | ||
| 84 | 78 | { |
| 85 | 79 | public readonly Terrain Building; |
| 86 | 80 | |
| 87 | - public OrderBuild(int priority, bool once, Point point, Terrain building) | |
| 88 | - : base(priority, once, point) | |
| 81 | + public OrderBuild(int priority, Point point, Terrain building) | |
| 82 | + : base(priority, point) | |
| 89 | 83 | { |
| 90 | 84 | this.Building = building; |
| 91 | 85 | } |
| 92 | 86 | |
| 93 | - public override bool Execute(GameField field, ICommander commander) | |
| 87 | + public override void Execute(GameField field, ICommander commander) | |
| 94 | 88 | { |
| 95 | - if (field[this.Point].Terrain != Terrain.Wasteland && field[this.Point].Terrain != Terrain.Hole) return true; | |
| 96 | - if (!IsForbidBuild(commander) && field.IsBuild(this.Point, Building)) | |
| 97 | - { | |
| 98 | - commander.Build(this.Point.X, this.Point.Y, Building); | |
| 99 | - return true; | |
| 100 | - } | |
| 101 | - if (IsForbidMove(commander)) return false; | |
| 102 | - if (NearRobotMove(this.Point, field.GetNeedRobot(Building), field, commander)) return true; | |
| 103 | - return false; | |
| 89 | + if (IsForbidBuild(commander)) return; | |
| 90 | + if (!field.IsBuild(this.Point, Building)) return; | |
| 91 | + commander.Build(this.Point.X, this.Point.Y, Building); | |
| 104 | 92 | } |
| 105 | 93 | } |
| 106 | 94 | } |
| @@ -6,22 +6,6 @@ using System.Text; | ||
| 6 | 6 | |
| 7 | 7 | namespace Common |
| 8 | 8 | { |
| 9 | - public struct TownPlan | |
| 10 | - { | |
| 11 | - public readonly int VictoryPoint; | |
| 12 | - public readonly int SpendRobot; | |
| 13 | - public readonly Point Excavator; | |
| 14 | - public readonly ReadOnlyCollection<Point> Town; | |
| 15 | - | |
| 16 | - public TownPlan(int victoryPoint, int spendRobot, Point excavator, ReadOnlyCollection<Point> town) | |
| 17 | - { | |
| 18 | - VictoryPoint = victoryPoint; | |
| 19 | - SpendRobot = spendRobot; | |
| 20 | - Excavator = excavator; | |
| 21 | - Town = town; | |
| 22 | - } | |
| 23 | - } | |
| 24 | - | |
| 25 | 9 | public class TownPlanning : IEnumerable<TownPlan> |
| 26 | 10 | { |
| 27 | 11 | List<TownPlan> plan; |
| @@ -44,7 +28,7 @@ namespace Common | ||
| 44 | 28 | { |
| 45 | 29 | for (int i = dir; i < 12; i++) |
| 46 | 30 | { |
| 47 | - Point town = field.TransformSitePropose(i, excavator); | |
| 31 | + Point town = GameField.TransformSitePropose(i, excavator); | |
| 48 | 32 | if (!field.IsInRange(town)) continue; |
| 49 | 33 | if (!IsPlanLiberate(i, townDir)) continue; |
| 50 | 34 | if (!field.IsLiberate(town)) continue; |
| @@ -82,7 +66,7 @@ namespace Common | ||
| 82 | 66 | int victory = 3, spend = 25; |
| 83 | 67 | for (int i = 0; i < townDir.Length; i++) |
| 84 | 68 | { |
| 85 | - Point temp = field.TransformSitePropose(townDir[i], excavator); | |
| 69 | + Point temp = GameField.TransformSitePropose(townDir[i], excavator); | |
| 86 | 70 | town[i] = temp; |
| 87 | 71 | spend += 10; |
| 88 | 72 | victory += townDir[i] % 2 == 0 ? 18 : 21; |
| @@ -104,6 +88,30 @@ namespace Common | ||
| 104 | 88 | } |
| 105 | 89 | } |
| 106 | 90 | |
| 91 | + public IEnumerable<TownPlan> ForbidPoint(Point point, GameField field) | |
| 92 | + { | |
| 93 | + List<TownPlan> result = new List<TownPlan>(); | |
| 94 | + foreach (TownPlan p in plan) | |
| 95 | + { | |
| 96 | + if (p.Excavator == point) continue; | |
| 97 | + if (!IsForbidPointInTown(p.Town, point, field)) continue; | |
| 98 | + result.Add(p); | |
| 99 | + } | |
| 100 | + return result; | |
| 101 | + } | |
| 102 | + | |
| 103 | + private bool IsForbidPointInTown(ReadOnlyCollection<Point> towns, Point point, GameField field) | |
| 104 | + { | |
| 105 | + foreach (Point town in towns) | |
| 106 | + { | |
| 107 | + foreach (Point temp in field.Adjoin(town, true)) | |
| 108 | + { | |
| 109 | + if(temp == point) return false; | |
| 110 | + } | |
| 111 | + } | |
| 112 | + return true; | |
| 113 | + } | |
| 114 | + | |
| 107 | 115 | public IEnumerator<TownPlan> GetEnumerator() |
| 108 | 116 | { |
| 109 | 117 | return plan.GetEnumerator(); |
| @@ -0,0 +1,202 @@ | ||
| 1 | + | |
| 2 | + Apache License | |
| 3 | + Version 2.0, January 2004 | |
| 4 | + http://www.apache.org/licenses/ | |
| 5 | + | |
| 6 | + TERMS AND CONDITIONS FOR USE, REPRODUCTION, AND DISTRIBUTION | |
| 7 | + | |
| 8 | + 1. Definitions. | |
| 9 | + | |
| 10 | + "License" shall mean the terms and conditions for use, reproduction, | |
| 11 | + and distribution as defined by Sections 1 through 9 of this document. | |
| 12 | + | |
| 13 | + "Licensor" shall mean the copyright owner or entity authorized by | |
| 14 | + the copyright owner that is granting the License. | |
| 15 | + | |
| 16 | + "Legal Entity" shall mean the union of the acting entity and all | |
| 17 | + other entities that control, are controlled by, or are under common | |
| 18 | + control with that entity. For the purposes of this definition, | |
| 19 | + "control" means (i) the power, direct or indirect, to cause the | |
| 20 | + direction or management of such entity, whether by contract or | |
| 21 | + otherwise, or (ii) ownership of fifty percent (50%) or more of the | |
| 22 | + outstanding shares, or (iii) beneficial ownership of such entity. | |
| 23 | + | |
| 24 | + "You" (or "Your") shall mean an individual or Legal Entity | |
| 25 | + exercising permissions granted by this License. | |
| 26 | + | |
| 27 | + "Source" form shall mean the preferred form for making modifications, | |
| 28 | + including but not limited to software source code, documentation | |
| 29 | + source, and configuration files. | |
| 30 | + | |
| 31 | + "Object" form shall mean any form resulting from mechanical | |
| 32 | + transformation or translation of a Source form, including but | |
| 33 | + not limited to compiled object code, generated documentation, | |
| 34 | + and conversions to other media types. | |
| 35 | + | |
| 36 | + "Work" shall mean the work of authorship, whether in Source or | |
| 37 | + Object form, made available under the License, as indicated by a | |
| 38 | + copyright notice that is included in or attached to the work | |
| 39 | + (an example is provided in the Appendix below). | |
| 40 | + | |
| 41 | + "Derivative Works" shall mean any work, whether in Source or Object | |
| 42 | + form, that is based on (or derived from) the Work and for which the | |
| 43 | + editorial revisions, annotations, elaborations, or other modifications | |
| 44 | + represent, as a whole, an original work of authorship. For the purposes | |
| 45 | + of this License, Derivative Works shall not include works that remain | |
| 46 | + separable from, or merely link (or bind by name) to the interfaces of, | |
| 47 | + the Work and Derivative Works thereof. | |
| 48 | + | |
| 49 | + "Contribution" shall mean any work of authorship, including | |
| 50 | + the original version of the Work and any modifications or additions | |
| 51 | + to that Work or Derivative Works thereof, that is intentionally | |
| 52 | + submitted to Licensor for inclusion in the Work by the copyright owner | |
| 53 | + or by an individual or Legal Entity authorized to submit on behalf of | |
| 54 | + the copyright owner. For the purposes of this definition, "submitted" | |
| 55 | + means any form of electronic, verbal, or written communication sent | |
| 56 | + to the Licensor or its representatives, including but not limited to | |
| 57 | + communication on electronic mailing lists, source code control systems, | |
| 58 | + and issue tracking systems that are managed by, or on behalf of, the | |
| 59 | + Licensor for the purpose of discussing and improving the Work, but | |
| 60 | + excluding communication that is conspicuously marked or otherwise | |
| 61 | + designated in writing by the copyright owner as "Not a Contribution." | |
| 62 | + | |
| 63 | + "Contributor" shall mean Licensor and any individual or Legal Entity | |
| 64 | + on behalf of whom a Contribution has been received by Licensor and | |
| 65 | + subsequently incorporated within the Work. | |
| 66 | + | |
| 67 | + 2. Grant of Copyright License. Subject to the terms and conditions of | |
| 68 | + this License, each Contributor hereby grants to You a perpetual, | |
| 69 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |
| 70 | + copyright license to reproduce, prepare Derivative Works of, | |
| 71 | + publicly display, publicly perform, sublicense, and distribute the | |
| 72 | + Work and such Derivative Works in Source or Object form. | |
| 73 | + | |
| 74 | + 3. Grant of Patent License. Subject to the terms and conditions of | |
| 75 | + this License, each Contributor hereby grants to You a perpetual, | |
| 76 | + worldwide, non-exclusive, no-charge, royalty-free, irrevocable | |
| 77 | + (except as stated in this section) patent license to make, have made, | |
| 78 | + use, offer to sell, sell, import, and otherwise transfer the Work, | |
| 79 | + where such license applies only to those patent claims licensable | |
| 80 | + by such Contributor that are necessarily infringed by their | |
| 81 | + Contribution(s) alone or by combination of their Contribution(s) | |
| 82 | + with the Work to which such Contribution(s) was submitted. If You | |
| 83 | + institute patent litigation against any entity (including a | |
| 84 | + cross-claim or counterclaim in a lawsuit) alleging that the Work | |
| 85 | + or a Contribution incorporated within the Work constitutes direct | |
| 86 | + or contributory patent infringement, then any patent licenses | |
| 87 | + granted to You under this License for that Work shall terminate | |
| 88 | + as of the date such litigation is filed. | |
| 89 | + | |
| 90 | + 4. Redistribution. You may reproduce and distribute copies of the | |
| 91 | + Work or Derivative Works thereof in any medium, with or without | |
| 92 | + modifications, and in Source or Object form, provided that You | |
| 93 | + meet the following conditions: | |
| 94 | + | |
| 95 | + (a) You must give any other recipients of the Work or | |
| 96 | + Derivative Works a copy of this License; and | |
| 97 | + | |
| 98 | + (b) You must cause any modified files to carry prominent notices | |
| 99 | + stating that You changed the files; and | |
| 100 | + | |
| 101 | + (c) You must retain, in the Source form of any Derivative Works | |
| 102 | + that You distribute, all copyright, patent, trademark, and | |
| 103 | + attribution notices from the Source form of the Work, | |
| 104 | + excluding those notices that do not pertain to any part of | |
| 105 | + the Derivative Works; and | |
| 106 | + | |
| 107 | + (d) If the Work includes a "NOTICE" text file as part of its | |
| 108 | + distribution, then any Derivative Works that You distribute must | |
| 109 | + include a readable copy of the attribution notices contained | |
| 110 | + within such NOTICE file, excluding those notices that do not | |
| 111 | + pertain to any part of the Derivative Works, in at least one | |
| 112 | + of the following places: within a NOTICE text file distributed | |
| 113 | + as part of the Derivative Works; within the Source form or | |
| 114 | + documentation, if provided along with the Derivative Works; or, | |
| 115 | + within a display generated by the Derivative Works, if and | |
| 116 | + wherever such third-party notices normally appear. The contents | |
| 117 | + of the NOTICE file are for informational purposes only and | |
| 118 | + do not modify the License. You may add Your own attribution | |
| 119 | + notices within Derivative Works that You distribute, alongside | |
| 120 | + or as an addendum to the NOTICE text from the Work, provided | |
| 121 | + that such additional attribution notices cannot be construed | |
| 122 | + as modifying the License. | |
| 123 | + | |
| 124 | + You may add Your own copyright statement to Your modifications and | |
| 125 | + may provide additional or different license terms and conditions | |
| 126 | + for use, reproduction, or distribution of Your modifications, or | |
| 127 | + for any such Derivative Works as a whole, provided Your use, | |
| 128 | + reproduction, and distribution of the Work otherwise complies with | |
| 129 | + the conditions stated in this License. | |
| 130 | + | |
| 131 | + 5. Submission of Contributions. Unless You explicitly state otherwise, | |
| 132 | + any Contribution intentionally submitted for inclusion in the Work | |
| 133 | + by You to the Licensor shall be under the terms and conditions of | |
| 134 | + this License, without any additional terms or conditions. | |
| 135 | + Notwithstanding the above, nothing herein shall supersede or modify | |
| 136 | + the terms of any separate license agreement you may have executed | |
| 137 | + with Licensor regarding such Contributions. | |
| 138 | + | |
| 139 | + 6. Trademarks. This License does not grant permission to use the trade | |
| 140 | + names, trademarks, service marks, or product names of the Licensor, | |
| 141 | + except as required for reasonable and customary use in describing the | |
| 142 | + origin of the Work and reproducing the content of the NOTICE file. | |
| 143 | + | |
| 144 | + 7. Disclaimer of Warranty. Unless required by applicable law or | |
| 145 | + agreed to in writing, Licensor provides the Work (and each | |
| 146 | + Contributor provides its Contributions) on an "AS IS" BASIS, | |
| 147 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or | |
| 148 | + implied, including, without limitation, any warranties or conditions | |
| 149 | + of TITLE, NON-INFRINGEMENT, MERCHANTABILITY, or FITNESS FOR A | |
| 150 | + PARTICULAR PURPOSE. You are solely responsible for determining the | |
| 151 | + appropriateness of using or redistributing the Work and assume any | |
| 152 | + risks associated with Your exercise of permissions under this License. | |
| 153 | + | |
| 154 | + 8. Limitation of Liability. In no event and under no legal theory, | |
| 155 | + whether in tort (including negligence), contract, or otherwise, | |
| 156 | + unless required by applicable law (such as deliberate and grossly | |
| 157 | + negligent acts) or agreed to in writing, shall any Contributor be | |
| 158 | + liable to You for damages, including any direct, indirect, special, | |
| 159 | + incidental, or consequential damages of any character arising as a | |
| 160 | + result of this License or out of the use or inability to use the | |
| 161 | + Work (including but not limited to damages for loss of goodwill, | |
| 162 | + work stoppage, computer failure or malfunction, or any and all | |
| 163 | + other commercial damages or losses), even if such Contributor | |
| 164 | + has been advised of the possibility of such damages. | |
| 165 | + | |
| 166 | + 9. Accepting Warranty or Additional Liability. While redistributing | |
| 167 | + the Work or Derivative Works thereof, You may choose to offer, | |
| 168 | + and charge a fee for, acceptance of support, warranty, indemnity, | |
| 169 | + or other liability obligations and/or rights consistent with this | |
| 170 | + License. However, in accepting such obligations, You may act only | |
| 171 | + on Your own behalf and on Your sole responsibility, not on behalf | |
| 172 | + of any other Contributor, and only if You agree to indemnify, | |
| 173 | + defend, and hold each Contributor harmless for any liability | |
| 174 | + incurred by, or claims asserted against, such Contributor by reason | |
| 175 | + of your accepting any such warranty or additional liability. | |
| 176 | + | |
| 177 | + END OF TERMS AND CONDITIONS | |
| 178 | + | |
| 179 | + APPENDIX: How to apply the Apache License to your work. | |
| 180 | + | |
| 181 | + To apply the Apache License to your work, attach the following | |
| 182 | + boilerplate notice, with the fields enclosed by brackets "[]" | |
| 183 | + replaced with your own identifying information. (Don't include | |
| 184 | + the brackets!) The text should be enclosed in the appropriate | |
| 185 | + comment syntax for the file format. We also recommend that a | |
| 186 | + file or class name and description of purpose be included on the | |
| 187 | + same "printed page" as the copyright notice for easier | |
| 188 | + identification within third-party archives. | |
| 189 | + | |
| 190 | + Copyright 2013 AI-COMP and Contributors of Terraforming | |
| 191 | + | |
| 192 | + Licensed under the Apache License, Version 2.0 (the "License"); | |
| 193 | + you may not use this file except in compliance with the License. | |
| 194 | + You may obtain a copy of the License at | |
| 195 | + | |
| 196 | + http://www.apache.org/licenses/LICENSE-2.0 | |
| 197 | + | |
| 198 | + Unless required by applicable law or agreed to in writing, software | |
| 199 | + distributed under the License is distributed on an "AS IS" BASIS, | |
| 200 | + WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. | |
| 201 | + See the License for the specific language governing permissions and | |
| 202 | + limitations under the License. | |
| \ No newline at end of file |
| @@ -96,11 +96,10 @@ namespace Visualizer | ||
| 96 | 96 | |
| 97 | 97 | private void SymmetryCopy() |
| 98 | 98 | { |
| 99 | - for (int x = 0; x < Width; x++) | |
| 99 | + for (int x = 0; x < Size; x++) | |
| 100 | 100 | { |
| 101 | - for (int y = 0; y < Height; y++) | |
| 101 | + for (int y = Size; y < Height; y++) | |
| 102 | 102 | { |
| 103 | - if (field[x, y].Terrain == Terrain.Outside) continue; | |
| 104 | 103 | field[y, FuncA(x, y)] = field[x, y]; |
| 105 | 104 | field[FuncA(x, y), x] = field[x, y]; |
| 106 | 105 | } |
| @@ -118,7 +117,7 @@ namespace Visualizer | ||
| 118 | 117 | field[y, FuncA(x, y)].Player = player[1]; |
| 119 | 118 | field[FuncA(x, y), x].Terrain = Terrain.Initial; |
| 120 | 119 | field[FuncA(x, y), x].Player = player[2]; |
| 121 | - return JoiningCount(new bool[Width, Height], x, y); | |
| 120 | + return JoiningCount(new bool[Width, Height], new Point { X = x, Y = y }); | |
| 122 | 121 | } |
| 123 | 122 | |
| 124 | 123 | private int FuncA(int x, int y) |
| @@ -126,17 +125,16 @@ namespace Visualizer | ||
| 126 | 125 | return (Size - 1) * 3 - x - y; |
| 127 | 126 | } |
| 128 | 127 | |
| 129 | - private int JoiningCount(bool[,] settled, int x, int y) | |
| 128 | + private int JoiningCount(bool[,] settled, Point point) | |
| 130 | 129 | { |
| 131 | - if (!IsInRange(x, y)) return 0; | |
| 132 | - if (settled[x, y]) return 0; | |
| 133 | - if (field[x, y].Terrain == Terrain.Outside || field[x, y].Terrain == Terrain.Hole) return 0; | |
| 134 | - int result = 1, tx, ty; | |
| 135 | - settled[x, y] = true; | |
| 136 | - for (int i = 1; i < 7; i++) | |
| 130 | + if (!IsInRange(point)) return 0; | |
| 131 | + if (this[point].Terrain == Terrain.Outside || this[point].Terrain == Terrain.Hole) return 0; | |
| 132 | + if (settled[point.X, point.Y]) return 0; | |
| 133 | + settled[point.X, point.Y] = true; | |
| 134 | + int result = 1; | |
| 135 | + foreach(Point temp in Adjoin(point)) | |
| 137 | 136 | { |
| 138 | - TransformDirection(i, x, y, out tx, out ty); | |
| 139 | - result += JoiningCount(settled, tx, ty); | |
| 137 | + result += JoiningCount(settled, temp); | |
| 140 | 138 | } |
| 141 | 139 | return result; |
| 142 | 140 | } |
| @@ -21,6 +21,7 @@ | ||
| 21 | 21 | <CheckBox x:Name="ShowResource" Content="Resource" Click="ShowChangeHandler"/> |
| 22 | 22 | <CheckBox x:Name="ShowTowerDamage" Content="Tower damage" Click="ShowChangeHandler"/> |
| 23 | 23 | <CheckBox x:Name="ShowDistanse" Content="Distance" Click="ShowChangeHandler"/> |
| 24 | + <CheckBox x:Name="ShowPriority" Content="Build priority" Click="ShowChangeHandler"/> | |
| 24 | 25 | </StackPanel> |
| 25 | 26 | <GridSplitter Width="1" IsEnabled="False" Background="Black" Margin="0"/> |
| 26 | 27 | </Grid> |
| @@ -23,6 +23,7 @@ namespace Visualizer | ||
| 23 | 23 | { |
| 24 | 24 | GameManager manager; |
| 25 | 25 | DistanceMap distance; |
| 26 | + BuildPriority priority; | |
| 26 | 27 | MassInformation[,] mass; |
| 27 | 28 | int selectX; |
| 28 | 29 | int selectY; |
| @@ -31,8 +32,8 @@ namespace Visualizer | ||
| 31 | 32 | { |
| 32 | 33 | InitializeComponent(); |
| 33 | 34 | manager = new GameManager(new Random()); |
| 34 | - manager.AI[0] = new TestAI(); | |
| 35 | - manager.AI[1] = new TestAI(); | |
| 35 | + manager.AI[0] = new ColonizeAI(); | |
| 36 | + manager.AI[1] = new ColonizeAI(); | |
| 36 | 37 | manager.AI[2] = new ColonizeAI(); |
| 37 | 38 | manager.Prepare(); |
| 38 | 39 | int w = manager.Field.Width, h = manager.Field.Height; |
| @@ -71,6 +72,7 @@ namespace Visualizer | ||
| 71 | 72 | Player2Info.Text = manager.GetPlayerInfo(1); |
| 72 | 73 | Player3Info.Text = manager.GetPlayerInfo(2); |
| 73 | 74 | distance = new DistanceMap(manager.Field, manager.Player, new Common.Point { X = selectX, Y = selectY }); |
| 75 | + priority = new BuildPriority(manager.Field, manager.Player, new Common.Point { X = selectX, Y = selectY }, 255); | |
| 74 | 76 | GameField field = manager.Field; |
| 75 | 77 | int w = field.Width, h = field.Height; |
| 76 | 78 | for (int x = 0; x < w; x++) |
| @@ -105,6 +107,10 @@ namespace Visualizer | ||
| 105 | 107 | { |
| 106 | 108 | result.AppendLine("Dt:" + distance[x, y].ToString()); |
| 107 | 109 | } |
| 110 | + if (ShowPriority.IsChecked == true) | |
| 111 | + { | |
| 112 | + result.AppendLine("Bp:" + priority[x, y].ToString()); | |
| 113 | + } | |
| 108 | 114 | return result.ToString(); |
| 109 | 115 | } |
| 110 | 116 |
| @@ -0,0 +1,3 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +xbuild Common/Common.csproj | |
| 3 | +xbuild Production/Production.csproj | |
| \ No newline at end of file |
| @@ -0,0 +1,2 @@ | ||
| 1 | +#!/bin/sh | |
| 2 | +mono Production/bin/Debug/Production.exe | |
| \ No newline at end of file |
| @@ -0,0 +1,33 @@ | ||
| 1 | +CEDEC AI 2013 で使用したプログラムのソースコードです。 | |
| 2 | +このソースコードのライセンスは、パブリックドメインとしますので、ご自由にお使いください。 | |
| 3 | + | |
| 4 | +ただし、ビジュアライザーで使用している画像ファイルは、AI-Compが公開している物を使用しております。 | |
| 5 | +それについては、Apache License, Version 2.0のライセンスが適用されますのでご注意下さい。 | |
| 6 | + | |
| 7 | +内容の構成は以下の通りとなっております。 | |
| 8 | + | |
| 9 | +CedecAI.sln | |
| 10 | + Visual Studioのソリューションファイル。 | |
| 11 | + このソースコードを参考にして開発したい方は、 | |
| 12 | + このファイルをお手持ちのVisual Studio 2012で読み込んで下さい。 | |
| 13 | + | |
| 14 | +Commonフォルダ | |
| 15 | + 共通のプログラムとAIが入ったクラスライブラリ。 | |
| 16 | + | |
| 17 | +Productionフォルダ | |
| 18 | + 提出用実行ファイルを作成するプロジェクト。 | |
| 19 | + | |
| 20 | +Visualizerフォルダ | |
| 21 | + 開発の補助に使った自作ビジュアライザー。 | |
| 22 | + | |
| 23 | +Production.exe | |
| 24 | + 実際に提出した実行ファイル。 | |
| 25 | + | |
| 26 | +Visualizer.exe | |
| 27 | + ビジュアライザーの実行ファイル。 | |
| 28 | + | |
| 29 | +Common.dll | |
| 30 | + 共通のプログラムとAIが入ったクラスライブラリのDLL。 | |
| 31 | + | |
| 32 | +compile.sh, run.sh | |
| 33 | + 提出に必要だったシェルスクリプトファイル。 | |
| \ No newline at end of file |