CEDEC AI 2013 の決勝で使用したプログラムのソースコード。
Revisión | baa4ee3f812d338a411aef0666213d8176e342eb (tree) |
---|---|
Tiempo | 2013-08-15 18:48:30 |
Autor | B_head <b_head@user...> |
Commiter | B_head |
オーダーシステム作成。
Signed-off-by: B_head <b_head@users.sourceforge.jp>
@@ -0,0 +1,11 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + class ColonizeAI | |
9 | + { | |
10 | + } | |
11 | +} |
@@ -15,6 +15,12 @@ namespace Common | ||
15 | 15 | public int WaitRobot; |
16 | 16 | } |
17 | 17 | |
18 | + public struct IntPoint | |
19 | + { | |
20 | + public int X; | |
21 | + public int Y; | |
22 | + } | |
23 | + | |
18 | 24 | public enum Terrain |
19 | 25 | { |
20 | 26 | Outside, |
@@ -31,22 +37,27 @@ namespace Common | ||
31 | 37 | |
32 | 38 | public enum Direction |
33 | 39 | { |
40 | + Center, | |
34 | 41 | Right, |
35 | - UpperRight, | |
36 | 42 | DownerRight, |
43 | + DownerLeft, | |
37 | 44 | Left, |
38 | 45 | UpperLeft, |
39 | - DownerLeft, | |
46 | + UpperRight, | |
40 | 47 | } |
41 | 48 | |
42 | 49 | public interface GameAI |
43 | 50 | { |
44 | 51 | string Prepare(int player, GameField field); |
45 | - void Think(int turn, int maxTurn, int player, GameField field, Commander com); | |
52 | + void Think(int turn, int maxTurn, int player, GameField field, Commander commander); | |
46 | 53 | } |
47 | 54 | |
48 | 55 | public interface Commander |
49 | 56 | { |
57 | + bool IsMove { get; } | |
58 | + bool IsBuild { get; } | |
59 | + bool IsFinish { get; } | |
60 | + int Player { get; } | |
50 | 61 | void Move(int x, int y, Direction dir, int robot); |
51 | 62 | void Build(int x, int y, Terrain building); |
52 | 63 | void Finish(); |
@@ -11,7 +11,7 @@ | ||
11 | 11 | <AssemblyName>Common</AssemblyName> |
12 | 12 | <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
13 | 13 | <FileAlignment>512</FileAlignment> |
14 | - <TargetFrameworkProfile /> | |
14 | + <TargetFrameworkProfile>Client</TargetFrameworkProfile> | |
15 | 15 | </PropertyGroup> |
16 | 16 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
17 | 17 | <DebugSymbols>true</DebugSymbols> |
@@ -39,10 +39,16 @@ | ||
39 | 39 | </ItemGroup> |
40 | 40 | <ItemGroup> |
41 | 41 | <Compile Include="Common.cs" /> |
42 | + <Compile Include="DispositionRobot.cs" /> | |
43 | + <Compile Include="DistanceMap.cs" /> | |
42 | 44 | <Compile Include="ExamineFunction.cs" /> |
43 | 45 | <Compile Include="GameField.cs" /> |
44 | 46 | <Compile Include="Field.cs" /> |
47 | + <Compile Include="KamikazeAI.cs" /> | |
48 | + <Compile Include="Orders.cs" /> | |
49 | + <Compile Include="EvaluateGround.cs" /> | |
45 | 50 | <Compile Include="Properties\AssemblyInfo.cs" /> |
51 | + <Compile Include="SearchNearRobot.cs" /> | |
46 | 52 | <Compile Include="TestAI.cs" /> |
47 | 53 | </ItemGroup> |
48 | 54 | <Import Project="$(MSBuildToolsPath)\Microsoft.CSharp.targets" /> |
@@ -0,0 +1,11 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + class CompanyAI | |
9 | + { | |
10 | + } | |
11 | +} |
@@ -0,0 +1,57 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + public class DispositionRobot | |
9 | + { | |
10 | + public readonly int Player; | |
11 | + List<Order> orders; | |
12 | + | |
13 | + public DispositionRobot(int player) | |
14 | + { | |
15 | + Player = player; | |
16 | + orders = new List<Order>(); | |
17 | + } | |
18 | + | |
19 | + public Order this[int index] | |
20 | + { | |
21 | + get | |
22 | + { | |
23 | + return orders[index]; | |
24 | + } | |
25 | + } | |
26 | + | |
27 | + public void AddMoveOrder(int priority, int x, int y, int robot, bool once) | |
28 | + { | |
29 | + OrderMove temp = new OrderMove(priority, x, y, robot, once); | |
30 | + orders.Add(temp); | |
31 | + } | |
32 | + | |
33 | + public void AddBuildOrder(int priority, int x, int y, Terrain building) | |
34 | + { | |
35 | + OrderBuild temp = new OrderBuild(priority, x, y, building); | |
36 | + orders.Add(temp); | |
37 | + } | |
38 | + | |
39 | + public void Clear() | |
40 | + { | |
41 | + orders.Clear(); | |
42 | + } | |
43 | + | |
44 | + public void Dispose(GameField field, Commander commander) | |
45 | + { | |
46 | + orders.Sort(); | |
47 | + for (int i = orders.Count - 1; i >= 0; i--) | |
48 | + { | |
49 | + if (orders[i].Execute(field, commander)) | |
50 | + { | |
51 | + orders.RemoveAt(i); | |
52 | + } | |
53 | + } | |
54 | + commander.Finish(); | |
55 | + } | |
56 | + } | |
57 | +} |
@@ -0,0 +1,64 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + public class DistanceMap : Field<byte> | |
9 | + { | |
10 | + readonly GameField gameField; | |
11 | + public const byte Impossible = byte.MaxValue; | |
12 | + | |
13 | + public DistanceMap(GameField gameField, int player, int x, int y) | |
14 | + : base(gameField.Width, gameField.Height) | |
15 | + { | |
16 | + this.gameField = gameField; | |
17 | + Initalize(); | |
18 | + Investigate(0, player, x, y); | |
19 | + } | |
20 | + | |
21 | + private void Initalize() | |
22 | + { | |
23 | + for (int x = 0; x < Width; x++) | |
24 | + { | |
25 | + for (int y = 0; y < Height; y++) | |
26 | + { | |
27 | + field[x, y] = Impossible; | |
28 | + } | |
29 | + } | |
30 | + } | |
31 | + | |
32 | + private void Investigate(byte distanse, int player, int x, int y) | |
33 | + { | |
34 | + if (!IsInRange(x, y)) return; | |
35 | + if (field[x, y] <= distanse) return; | |
36 | + if (gameField[x, y].Ter == Terrain.Outside) return; | |
37 | + if (gameField[x, y].Player != player && | |
38 | + gameField[x, y].Ter != Terrain.Wasteland && gameField[x, y].Ter != Terrain.Hole) return; | |
39 | + if (gameField[x, y].Ter == Terrain.Hole && distanse > 0) return; | |
40 | + field[x, y] = distanse; | |
41 | + int tx, ty; | |
42 | + for (int i = 1; i < 7; i++) | |
43 | + { | |
44 | + TransformDirection(i, x, y, out tx, out ty); | |
45 | + Investigate((byte)(distanse + 1), player, tx, ty); | |
46 | + } | |
47 | + } | |
48 | + | |
49 | + public Direction ApproachTerget(int x, int y) | |
50 | + { | |
51 | + int tx, ty; | |
52 | + for (int i = 1; i < 7; i++) | |
53 | + { | |
54 | + if (TransformDirection(i, x, y, out tx, out ty)) continue; | |
55 | + if (gameField[tx, ty].Ter == Terrain.Hole && field[tx, ty] != 0) continue; | |
56 | + if (field[x, y] - 1 == field[tx, ty]) | |
57 | + { | |
58 | + return (Direction)i; | |
59 | + } | |
60 | + } | |
61 | + return Direction.Center; | |
62 | + } | |
63 | + } | |
64 | +} |
@@ -0,0 +1,100 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + public class EvaluateGround : Field<byte> | |
9 | + { | |
10 | + GameField gameField; | |
11 | + public const byte Obstacle = byte.MaxValue; | |
12 | + | |
13 | + public EvaluateGround(GameField gameField) | |
14 | + : base(gameField.Width, gameField.Height) | |
15 | + { | |
16 | + this.gameField = gameField; | |
17 | + Initalize(); | |
18 | + AllEvaluate(); | |
19 | + } | |
20 | + | |
21 | + private void Initalize() | |
22 | + { | |
23 | + for (int x = 0; x < Width; x++) | |
24 | + { | |
25 | + for (int y = 0; y < Height; y++) | |
26 | + { | |
27 | + if (gameField[x, y].Ter != Terrain.Wasteland) | |
28 | + { | |
29 | + field[x, y] = Obstacle; | |
30 | + } | |
31 | + } | |
32 | + } | |
33 | + } | |
34 | + | |
35 | + private void AllEvaluate() | |
36 | + { | |
37 | + for (int x = 0; x < Width; x++) | |
38 | + { | |
39 | + for (int y = 0; y < Height; y++) | |
40 | + { | |
41 | + if (field[x, y] == Obstacle) continue; | |
42 | + field[x, y] = (byte)Evaluate(x, y); | |
43 | + } | |
44 | + } | |
45 | + } | |
46 | + | |
47 | + private int Evaluate(int x, int y) | |
48 | + { | |
49 | + int result = 0, tx, ty; | |
50 | + for (int i = 0; i < 12; i++) | |
51 | + { | |
52 | + if (TransformSitePropose(i, x, y, out tx, out ty)) continue; | |
53 | + if (!PertEvaluate(tx, ty)) continue; | |
54 | + if(i <6) | |
55 | + { | |
56 | + result += 2; | |
57 | + } | |
58 | + else | |
59 | + { | |
60 | + result += 3; | |
61 | + } | |
62 | + } | |
63 | + return result; | |
64 | + } | |
65 | + | |
66 | + private bool PertEvaluate(int x, int y) | |
67 | + { | |
68 | + int tx, ty; | |
69 | + for (int i = 0; i < 7; i++) | |
70 | + { | |
71 | + if (TransformDirection(i, x, y, out tx, out ty)) return false; | |
72 | + if (field[tx, ty] == Obstacle) return false; | |
73 | + } | |
74 | + return true; | |
75 | + } | |
76 | + | |
77 | + public bool TransformSitePropose(int i, int x, int y, out int tx, out int ty) | |
78 | + { | |
79 | + tx = x; | |
80 | + ty = y; | |
81 | + switch (i) | |
82 | + { | |
83 | + case 0: tx += 1; ty += 0; break; | |
84 | + case 1: tx += 1; ty += -1; break; | |
85 | + case 2: tx += 0; ty += 1; break; | |
86 | + case 3: tx += -1; ty += 0; break; | |
87 | + case 4: tx += -1; ty += 1; break; | |
88 | + case 5: tx += 0; ty += -1; break; | |
89 | + case 6: tx += 1; ty += 1; break; | |
90 | + case 7: tx += -1; ty += 2; break; | |
91 | + case 8: tx += -2; ty += 1; break; | |
92 | + case 9: tx += -1; ty += -1; break; | |
93 | + case 10: tx += 1; ty += -2; break; | |
94 | + case 11: tx += 2; ty += -1; break; | |
95 | + default: throw new Exception(); | |
96 | + } | |
97 | + return !IsInRange(tx, ty); | |
98 | + } | |
99 | + } | |
100 | +} |
@@ -13,8 +13,7 @@ namespace Common | ||
13 | 13 | int result = 0, tx, ty; |
14 | 14 | for (int i = 1; i < 13; i++) |
15 | 15 | { |
16 | - field.TransformTowerRange(i, x, y, out tx, out ty); | |
17 | - if (field.IsInRange(tx, ty)) continue; | |
16 | + if (field.TransformTowerRange(i, x, y, out tx, out ty)) continue; | |
18 | 17 | if (field[tx, ty].Ter != Terrain.AttackTower) continue; |
19 | 18 | if (field[tx, ty].Player == player) continue; |
20 | 19 | result += 2; |
@@ -29,12 +29,35 @@ namespace Common | ||
29 | 29 | |
30 | 30 | public bool IsInRange(int x, int y) |
31 | 31 | { |
32 | - return x < 0 || x >= Width || y < 0 || y >= Height; | |
32 | + return x >= 0 && x < Width && y >= 0 && y < Height; | |
33 | 33 | } |
34 | 34 | |
35 | 35 | public void CopyTo(Field<TYPE> other) |
36 | 36 | { |
37 | 37 | Array.Copy(field, other.field, Width * Height); |
38 | 38 | } |
39 | + | |
40 | + public bool TransformDirection(int dir, int x, int y, out int tx, out int ty) | |
41 | + { | |
42 | + return TransformDirection((Direction)dir, x, y, out tx, out ty); | |
43 | + } | |
44 | + | |
45 | + public bool TransformDirection(Direction dir, int x, int y, out int tx, out int ty) | |
46 | + { | |
47 | + tx = x; | |
48 | + ty = y; | |
49 | + switch (dir) | |
50 | + { | |
51 | + case Direction.Center: tx += 0; ty += 0; break; | |
52 | + case Direction.Right: tx += 1; ty += 0; break; | |
53 | + case Direction.UpperRight: tx += 1; ty += -1; break; | |
54 | + case Direction.DownerRight: tx += 0; ty += 1; break; | |
55 | + case Direction.Left: tx += -1; ty += 0; break; | |
56 | + case Direction.DownerLeft: tx += -1; ty += 1; break; | |
57 | + case Direction.UpperLeft: tx += 0; ty += -1; break; | |
58 | + default: throw new Exception(); | |
59 | + } | |
60 | + return !IsInRange(tx, ty); | |
61 | + } | |
39 | 62 | } |
40 | 63 | } |
@@ -39,12 +39,13 @@ namespace Common | ||
39 | 39 | } |
40 | 40 | } |
41 | 41 | |
42 | - public bool Move(int player, int fromX, int fromY, Direction dir, int robot) | |
42 | + public bool Move(int fromX, int fromY, Direction dir, int robot) | |
43 | 43 | { |
44 | - if (!IsMove(player, fromX, fromY, dir, robot)) return false; | |
44 | + if (!IsMove(fromX, fromY, dir, robot)) return false; | |
45 | 45 | int toX, toY; |
46 | 46 | TransformDirection(dir, fromX, fromY, out toX, out toY); |
47 | 47 | GameMass from = field[fromX, fromY], to = field[toX, toY]; |
48 | + int player = from.Player; | |
48 | 49 | if (to.Player == player) |
49 | 50 | { |
50 | 51 | from.ActiveRobot -= robot; |
@@ -68,14 +69,13 @@ namespace Common | ||
68 | 69 | return true; |
69 | 70 | } |
70 | 71 | |
71 | - public bool IsMove(int player, int fromX, int fromY, Direction dir, int robot) | |
72 | + public bool IsMove(int fromX, int fromY, Direction dir, int robot) | |
72 | 73 | { |
73 | 74 | if (robot <= 0) return false; |
74 | 75 | int toX, toY; |
75 | - TransformDirection(dir, fromX, fromY, out toX, out toY); | |
76 | - if (IsInRange(toX, toY)) return false; | |
76 | + if (TransformDirection(dir, fromX, fromY, out toX, out toY)) return false; | |
77 | 77 | GameMass from = field[fromX, fromY], to = field[toX, toY]; |
78 | - if (from.Player != player) return false; | |
78 | + int player = from.Player; | |
79 | 79 | if (from.ActiveRobot < robot) return false; |
80 | 80 | if (from.Ter == Terrain.Hole) return false; |
81 | 81 | if (to.Player == player) |
@@ -89,23 +89,30 @@ namespace Common | ||
89 | 89 | return true; |
90 | 90 | } |
91 | 91 | |
92 | - public bool Build(int player, int x, int y, Terrain building, ref int extraPoint) | |
92 | + public bool Build(int x, int y, Terrain building, ref int extraPoint) | |
93 | 93 | { |
94 | - if (!IsBuild(player, x, y, building)) return false; | |
94 | + if (!IsBuild(x, y, building)) return false; | |
95 | 95 | int resource, robot; |
96 | 96 | GetRequirement(building, out resource, out robot); |
97 | 97 | if (building == Terrain.Town) |
98 | 98 | { |
99 | 99 | extraPoint += GetPrepareResource(x, y) - resource; |
100 | + int tx, ty, player = field[x,y].Player; | |
101 | + for (int i = 1; i < 7; i++) | |
102 | + { | |
103 | + if (TransformDirection(i, x, y, out tx, out ty)) continue; | |
104 | + if (field[tx, ty].Player != player) continue; | |
105 | + if (field[tx, ty].Ter != Terrain.Wasteland) continue; | |
106 | + field[tx, ty].Ter = Terrain.House; | |
107 | + } | |
100 | 108 | } |
101 | 109 | field[x, y].ActiveRobot -= robot; |
102 | 110 | field[x, y].Ter = building; |
103 | 111 | return true; |
104 | 112 | } |
105 | 113 | |
106 | - public bool IsBuild(int player, int x, int y, Terrain building) | |
114 | + public bool IsBuild(int x, int y, Terrain building) | |
107 | 115 | { |
108 | - if (field[x, y].Player != player) return false; | |
109 | 116 | if (field[x, y].Ter != Terrain.Wasteland && field[x, y].Ter != Terrain.Hole) return false; |
110 | 117 | if (field[x, y].Ter == Terrain.Wasteland && building == Terrain.Bridge) return false; |
111 | 118 | if (field[x, y].Ter == Terrain.Hole && building != Terrain.Bridge) return false; |
@@ -215,10 +222,9 @@ namespace Common | ||
215 | 222 | { |
216 | 223 | if (field[x, y].Player == player) return 0; |
217 | 224 | int result = 0, tx, ty; |
218 | - for (int i = 1; i < 13; i++) | |
225 | + for (int i = 0; i < 12; i++) | |
219 | 226 | { |
220 | - TransformTowerRange(i, x, y, out tx, out ty); | |
221 | - if (IsInRange(tx, ty)) continue; | |
227 | + if (TransformTowerRange(i, x, y, out tx, out ty)) continue; | |
222 | 228 | if (field[tx, ty].Ter != Terrain.AttackTower) continue; |
223 | 229 | if (field[tx, ty].Player != player) continue; |
224 | 230 | result += 2; |
@@ -231,8 +237,7 @@ namespace Common | ||
231 | 237 | int result = 0, player = field[x, y].Player, tx, ty; |
232 | 238 | for (int i = 0; i < 7; i++) |
233 | 239 | { |
234 | - TransformAdjoin(i, x, y, out tx, out ty); | |
235 | - if (IsInRange(tx, ty)) continue; | |
240 | + if (TransformDirection(i, x, y, out tx, out ty)) continue; | |
236 | 241 | if (field[tx, ty].Player != player) continue; |
237 | 242 | result += GetYieldResource(tx, ty); |
238 | 243 | } |
@@ -245,8 +250,7 @@ namespace Common | ||
245 | 250 | int result = 1, player = field[x, y].Player, tx, ty; |
246 | 251 | for (int i = 1; i < 7; i++) |
247 | 252 | { |
248 | - TransformAdjoin(i, x, y, out tx, out ty); | |
249 | - if (IsInRange(tx, ty)) continue; | |
253 | + if (TransformDirection(i, x, y, out tx, out ty)) continue; | |
250 | 254 | if (field[tx, ty].Player != player) continue; |
251 | 255 | if (field[tx, ty].Ter != Terrain.Excavator) continue; |
252 | 256 | result++; |
@@ -254,60 +258,27 @@ namespace Common | ||
254 | 258 | return result; |
255 | 259 | } |
256 | 260 | |
257 | - public void TransformDirection(Direction dir, int x, int y, out int tx, out int ty) | |
258 | - { | |
259 | - tx = x; | |
260 | - ty = y; | |
261 | - switch (dir) | |
262 | - { | |
263 | - case Direction.Right: tx += 1; ty += 0; break; | |
264 | - case Direction.UpperRight: tx += 1; ty += -1; break; | |
265 | - case Direction.DownerRight: tx += 0; ty += 1; break; | |
266 | - case Direction.Left: tx += -1; ty += 0; break; | |
267 | - case Direction.DownerLeft: tx += -1; ty += 1; break; | |
268 | - case Direction.UpperLeft: tx += 0; ty += -1; break; | |
269 | - default: throw new Exception(); | |
270 | - } | |
271 | - } | |
272 | - | |
273 | - public void TransformAdjoin(int i, int x, int y, out int tx, out int ty) | |
274 | - { | |
275 | - tx = x; | |
276 | - ty = y; | |
277 | - switch (i) | |
278 | - { | |
279 | - case 0: tx += 0; ty += 0; break; | |
280 | - case 1: tx += 1; ty += 0; break; | |
281 | - case 2: tx += 1; ty += -1; break; | |
282 | - case 3: tx += 0; ty += 1; break; | |
283 | - case 4: tx += -1; ty += 0; break; | |
284 | - case 5: tx += -1; ty += 1; break; | |
285 | - case 6: tx += 0; ty += -1; break; | |
286 | - default: throw new Exception(); | |
287 | - } | |
288 | - } | |
289 | - | |
290 | - public void TransformTowerRange(int i, int x, int y, out int tx, out int ty) | |
261 | + public bool TransformTowerRange(int i, int x, int y, out int tx, out int ty) | |
291 | 262 | { |
292 | 263 | tx = x; |
293 | 264 | ty = y; |
294 | 265 | switch (i) |
295 | 266 | { |
296 | - case 0: tx += 0; ty += 0; break; | |
297 | - case 1: tx += 1; ty += 0; break; | |
298 | - case 2: tx += 1; ty += -1; break; | |
299 | - case 3: tx += 0; ty += 1; break; | |
300 | - case 4: tx += -1; ty += 0; break; | |
301 | - case 5: tx += -1; ty += 1; break; | |
302 | - case 6: tx += 0; ty += -1; break; | |
303 | - case 7: tx += 2; ty += 0; break; | |
304 | - case 8: tx += 2; ty += -2; break; | |
305 | - case 9: tx += 0; ty += 2; break; | |
306 | - case 10: tx += -2; ty += 0; break; | |
307 | - case 11: tx += -2; ty += 2; break; | |
308 | - case 12: tx += 0; ty += -2; break; | |
267 | + case 0: tx += 1; ty += 0; break; | |
268 | + case 1: tx += 1; ty += -1; break; | |
269 | + case 2: tx += 0; ty += 1; break; | |
270 | + case 3: tx += -1; ty += 0; break; | |
271 | + case 4: tx += -1; ty += 1; break; | |
272 | + case 5: tx += 0; ty += -1; break; | |
273 | + case 6: tx += 2; ty += 0; break; | |
274 | + case 7: tx += 2; ty += -2; break; | |
275 | + case 8: tx += 0; ty += 2; break; | |
276 | + case 9: tx += -2; ty += 0; break; | |
277 | + case 10: tx += -2; ty += 2; break; | |
278 | + case 11: tx += 0; ty += -2; break; | |
309 | 279 | default: throw new Exception(); |
310 | 280 | } |
281 | + return !IsInRange(tx, ty); | |
311 | 282 | } |
312 | 283 | } |
313 | 284 | } |
@@ -0,0 +1,11 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + class GovernAI | |
9 | + { | |
10 | + } | |
11 | +} |
@@ -0,0 +1,11 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + class InvadeAI | |
9 | + { | |
10 | + } | |
11 | +} |
@@ -0,0 +1,34 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + public class KamikazeAI : GameAI | |
9 | + { | |
10 | + DispositionRobot disposition; | |
11 | + | |
12 | + public string Prepare(int player, GameField field) | |
13 | + { | |
14 | + disposition = new DispositionRobot(player); | |
15 | + return "B_head:KamikazeAI"; | |
16 | + } | |
17 | + | |
18 | + public void Think(int turn, int maxTurn, int player, GameField field, Commander commander) | |
19 | + { | |
20 | + int w = field.Width, h = field.Height; | |
21 | + for (int x = 0; x < w; x++) | |
22 | + { | |
23 | + for (int y = 0; y < h; y++) | |
24 | + { | |
25 | + if (field[x, y].Player != player && field[x, y].Ter == Terrain.Wasteland) | |
26 | + { | |
27 | + disposition.AddMoveOrder(-field[x, y].WaitRobot, x, y, field[x, y].WaitRobot + 1, true); | |
28 | + } | |
29 | + } | |
30 | + } | |
31 | + disposition.Dispose(field, commander); | |
32 | + } | |
33 | + } | |
34 | +} |
@@ -0,0 +1,105 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + public abstract class Order : IComparable<Order> | |
9 | + { | |
10 | + int priority; | |
11 | + | |
12 | + public Order(int priority) | |
13 | + { | |
14 | + this.priority = priority; | |
15 | + } | |
16 | + | |
17 | + public abstract bool Execute(GameField field, Commander commander); | |
18 | + | |
19 | + protected bool IsForbidMove(Commander commander) | |
20 | + { | |
21 | + return commander.IsBuild || commander.IsFinish; | |
22 | + } | |
23 | + | |
24 | + protected bool IsForbidBuild(Commander commander) | |
25 | + { | |
26 | + return commander.IsMove || commander.IsBuild || commander.IsFinish; | |
27 | + } | |
28 | + | |
29 | + protected void NearRobotMove(int x, int y, int robot, GameField field, Commander commander) | |
30 | + { | |
31 | + SearchNearRobot search = new SearchNearRobot(field, commander.Player, x, y); | |
32 | + int moveCount = 0, tx, ty; | |
33 | + Direction dir; | |
34 | + while (moveCount < robot) | |
35 | + { | |
36 | + if (search.Next(out tx, out ty, out dir)) break; | |
37 | + int moveRobot = Math.Min(field[tx, ty].ActiveRobot, robot - moveCount); | |
38 | + field.Move(tx, ty, dir, moveRobot); | |
39 | + if (dir != Direction.Center) | |
40 | + { | |
41 | + commander.Move(tx, ty, dir, moveRobot); | |
42 | + } | |
43 | + moveCount += moveRobot; | |
44 | + } | |
45 | + } | |
46 | + | |
47 | + public int CompareTo(Order other) | |
48 | + { | |
49 | + return priority - other.priority; | |
50 | + } | |
51 | + } | |
52 | + | |
53 | + public class OrderMove : Order | |
54 | + { | |
55 | + int x; | |
56 | + int y; | |
57 | + int robot; | |
58 | + bool once; | |
59 | + | |
60 | + public OrderMove(int priority, int x, int y, int robot, bool once) | |
61 | + : base(priority) | |
62 | + { | |
63 | + this.x = x; | |
64 | + this.y = y; | |
65 | + this.robot = robot; | |
66 | + this.once = once; | |
67 | + } | |
68 | + | |
69 | + public override bool Execute(GameField field, Commander commander) | |
70 | + { | |
71 | + if (IsForbidMove(commander)) return once; | |
72 | + NearRobotMove(x, y, robot, field, commander); | |
73 | + return once; | |
74 | + } | |
75 | + } | |
76 | + | |
77 | + public class OrderBuild : Order | |
78 | + { | |
79 | + int x; | |
80 | + int y; | |
81 | + Terrain building; | |
82 | + | |
83 | + public OrderBuild(int priority, int x, int y, Terrain building) | |
84 | + : base(priority) | |
85 | + { | |
86 | + this.x = x; | |
87 | + this.y = y; | |
88 | + this.building = building; | |
89 | + } | |
90 | + | |
91 | + public override bool Execute(GameField field, Commander commander) | |
92 | + { | |
93 | + if (!IsForbidBuild(commander) || field.IsBuild(x, y, building)) | |
94 | + { | |
95 | + commander.Build(x, y, building); | |
96 | + return true; | |
97 | + } | |
98 | + if (IsForbidMove(commander)) return false; | |
99 | + int resource, robot; | |
100 | + field.GetRequirement(building, out resource, out robot); | |
101 | + NearRobotMove(x, y, robot, field, commander); | |
102 | + return false; | |
103 | + } | |
104 | + } | |
105 | +} |
@@ -0,0 +1,55 @@ | ||
1 | +using System; | |
2 | +using System.Collections.Generic; | |
3 | +using System.Linq; | |
4 | +using System.Text; | |
5 | + | |
6 | +namespace Common | |
7 | +{ | |
8 | + | |
9 | + public class SearchNearRobot | |
10 | + { | |
11 | + Queue<IntPoint> queue; | |
12 | + GameField field; | |
13 | + DistanceMap distance; | |
14 | + int player; | |
15 | + | |
16 | + public SearchNearRobot(GameField field, int player, int x, int y) | |
17 | + { | |
18 | + queue = new Queue<IntPoint>(); | |
19 | + queue.Enqueue(new IntPoint { X = x, Y = y }); | |
20 | + this.field = field; | |
21 | + distance = new DistanceMap(field, player, x, y); | |
22 | + this.player = player; | |
23 | + } | |
24 | + | |
25 | + //todo 重複して捜査している。 | |
26 | + public bool Next(out int x, out int y, out Direction dir) | |
27 | + { | |
28 | + while (queue.Count > 0) | |
29 | + { | |
30 | + IntPoint point = queue.Dequeue(); | |
31 | + if (field[point.X, point.Y].Player == player && field[point.X, point.Y].ActiveRobot > 0) | |
32 | + { | |
33 | + x = point.X; | |
34 | + y = point.Y; | |
35 | + dir = distance.ApproachTerget(x, y); | |
36 | + return false; | |
37 | + } | |
38 | + int tx, ty; | |
39 | + for (int i = 1; i < 7; i++) | |
40 | + { | |
41 | + if (distance.TransformDirection(i, point.X, point.Y, out tx, out ty)) continue; | |
42 | + int temp = distance[point.X, point.Y] + 1; | |
43 | + if (temp == distance[tx, ty] && field[tx, ty].Ter != Terrain.Hole) | |
44 | + { | |
45 | + queue.Enqueue(new IntPoint { X = tx, Y = ty }); | |
46 | + } | |
47 | + } | |
48 | + } | |
49 | + x = -1; | |
50 | + y = -1; | |
51 | + dir = Direction.Center; | |
52 | + return true; | |
53 | + } | |
54 | + } | |
55 | +} |
@@ -20,16 +20,16 @@ namespace Common | ||
20 | 20 | return "B_head:TestAI"; |
21 | 21 | } |
22 | 22 | |
23 | - public void Think(int turn, int maxTurn, int player, GameField field, Commander com) | |
23 | + public void Think(int turn, int maxTurn, int player, GameField field, Commander commander) | |
24 | 24 | { |
25 | - if (!Build(player, field, com)) | |
25 | + if (!Build(player, field, commander)) | |
26 | 26 | { |
27 | - Move(player, field, com); | |
27 | + Move(player, field, commander); | |
28 | 28 | } |
29 | - com.Finish(); | |
29 | + commander.Finish(); | |
30 | 30 | } |
31 | 31 | |
32 | - private void Move(int player, GameField field, Commander com) | |
32 | + private void Move(int player, GameField field, Commander commander) | |
33 | 33 | { |
34 | 34 | int w = field.Width, h = field.Height; |
35 | 35 | for (int x = 0; x < w; x++) |
@@ -38,15 +38,15 @@ namespace Common | ||
38 | 38 | { |
39 | 39 | Direction dir = ToDirection(random.Next(6)); |
40 | 40 | int robot = random.Next(field[x, y].ActiveRobot) + 1; |
41 | - if (field.IsMove(player, x, y, dir, robot)) | |
41 | + if (field.IsMove(x, y, dir, robot)) | |
42 | 42 | { |
43 | - com.Move(x, y, dir, robot); | |
43 | + commander.Move(x, y, dir, robot); | |
44 | 44 | } |
45 | 45 | } |
46 | 46 | } |
47 | 47 | } |
48 | 48 | |
49 | - private bool Build(int player, GameField field, Commander com) | |
49 | + private bool Build(int player, GameField field, Commander commander) | |
50 | 50 | { |
51 | 51 | Terrain building = ToBuilding(random.Next(6)); |
52 | 52 | int w = field.Width, h = field.Height; |
@@ -54,9 +54,9 @@ namespace Common | ||
54 | 54 | { |
55 | 55 | for (int y = 0; y < h; y++) |
56 | 56 | { |
57 | - if (field.IsBuild(player, x, y, building)) | |
57 | + if (field.IsBuild(x, y, building)) | |
58 | 58 | { |
59 | - com.Build(x, y, building); | |
59 | + commander.Build(x, y, building); | |
60 | 60 | return true; |
61 | 61 | } |
62 | 62 | } |
@@ -1,6 +1,6 @@ | ||
1 | 1 | <?xml version="1.0"?> |
2 | 2 | <configuration> |
3 | 3 | <startup> |
4 | - <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0"/> | |
4 | + <supportedRuntime version="v4.0" sku=".NETFramework,Version=v4.0,Profile=Client"/> | |
5 | 5 | </startup> |
6 | 6 | </configuration> |
@@ -10,22 +10,26 @@ namespace Production | ||
10 | 10 | { |
11 | 11 | class LinkGameField : GameField |
12 | 12 | { |
13 | - public LinkGameField(int size) | |
13 | + public readonly int Turn; | |
14 | + public readonly int MaxTurn; | |
15 | + public readonly int Player; | |
16 | + | |
17 | + public LinkGameField(int size, int turn, int maxTurn, int player) | |
14 | 18 | : base(size) |
15 | 19 | { |
16 | - | |
20 | + Turn = turn; | |
21 | + MaxTurn = maxTurn; | |
22 | + Player = player; | |
17 | 23 | } |
18 | 24 | |
19 | - public static LinkGameField ParseText(out int turn, out int maxTurn, out int playerTurn) | |
25 | + public static LinkGameField ParseText() | |
20 | 26 | { |
21 | 27 | string[] line; |
22 | 28 | if (Console.ReadLine() != "START") throw new Exception(); |
23 | 29 | line = Console.ReadLine().Split(' '); |
24 | - turn = int.Parse(line[0]); | |
25 | - maxTurn = int.Parse(line[1]); | |
26 | - playerTurn = int.Parse(line[2]); | |
30 | + int turn = int.Parse(line[0]), maxTurn = int.Parse(line[1]), playerTurn = int.Parse(line[2]); | |
27 | 31 | line = Console.ReadLine().Split(' '); |
28 | - LinkGameField result = new LinkGameField(int.Parse(line[0])); | |
32 | + LinkGameField result = new LinkGameField(int.Parse(line[0]), turn, maxTurn, playerTurn); | |
29 | 33 | int count = int.Parse(line[1]); |
30 | 34 | for (int i = 0; i < count; i++) |
31 | 35 | { |
@@ -92,17 +96,29 @@ namespace Production | ||
92 | 96 | class LinkCommander : Commander |
93 | 97 | { |
94 | 98 | LinkGameField parent; |
99 | + public bool IsMove { get; private set; } | |
100 | + public bool IsBuild { get; private set; } | |
101 | + public bool IsFinish { get; private set; } | |
95 | 102 | |
96 | 103 | public LinkCommander(LinkGameField parent) |
97 | 104 | { |
98 | 105 | this.parent = parent; |
99 | 106 | } |
100 | 107 | |
108 | + public int Player | |
109 | + { | |
110 | + get | |
111 | + { | |
112 | + return parent.Player; | |
113 | + } | |
114 | + } | |
115 | + | |
101 | 116 | public void Move(int x, int y, Direction dir, int robot) |
102 | 117 | { |
103 | 118 | string temp = GenerateDirectionCode(dir); |
104 | 119 | parent.ToRedress(ref x, ref y); |
105 | 120 | Console.WriteLine("move {0} {1} {2} {3}", x, y, temp, robot); |
121 | + IsMove = true; | |
106 | 122 | } |
107 | 123 | |
108 | 124 | public void Build(int x, int y, Terrain building) |
@@ -110,11 +126,13 @@ namespace Production | ||
110 | 126 | string temp = GenerateBuildingCode(building); |
111 | 127 | parent.ToRedress(ref x, ref y); |
112 | 128 | Console.WriteLine("build {0} {1} {2}", x, y, temp); |
129 | + IsBuild = true; | |
113 | 130 | } |
114 | 131 | |
115 | 132 | public void Finish() |
116 | 133 | { |
117 | 134 | Console.WriteLine("finish"); |
135 | + IsFinish = true; | |
118 | 136 | } |
119 | 137 | |
120 | 138 | private string GenerateDirectionCode(Direction dir) |
@@ -11,7 +11,7 @@ | ||
11 | 11 | <AssemblyName>Production</AssemblyName> |
12 | 12 | <TargetFrameworkVersion>v4.0</TargetFrameworkVersion> |
13 | 13 | <FileAlignment>512</FileAlignment> |
14 | - <TargetFrameworkProfile /> | |
14 | + <TargetFrameworkProfile>Client</TargetFrameworkProfile> | |
15 | 15 | </PropertyGroup> |
16 | 16 | <PropertyGroup Condition=" '$(Configuration)|$(Platform)' == 'Debug|AnyCPU' "> |
17 | 17 | <PlatformTarget>AnyCPU</PlatformTarget> |
@@ -11,14 +11,13 @@ namespace Production | ||
11 | 11 | { |
12 | 12 | static void Main(string[] args) |
13 | 13 | { |
14 | - int turn, maxTurn, player; | |
15 | 14 | GameAI ai = new TestAI(); |
16 | - LinkGameField field = LinkGameField.ParseText(out turn, out maxTurn, out player); | |
17 | - Console.WriteLine(ai.Prepare(player, field)); | |
18 | - for (int i = 0; i < maxTurn; i++) | |
15 | + LinkGameField field = LinkGameField.ParseText(); | |
16 | + Console.WriteLine(ai.Prepare(field.Player, field)); | |
17 | + for (int i = 0; i < field.MaxTurn; i++) | |
19 | 18 | { |
20 | - field = LinkGameField.ParseText(out turn, out maxTurn, out player); | |
21 | - ai.Think(turn, maxTurn, player, field, field.GetCommander()); | |
19 | + field = LinkGameField.ParseText(); | |
20 | + ai.Think(field.Turn, field.MaxTurn, field.Player, field, field.GetCommander()); | |
22 | 21 | } |
23 | 22 | } |
24 | 23 | } |
@@ -65,26 +65,36 @@ namespace Visualizer | ||
65 | 65 | class ManagerCommander : Commander |
66 | 66 | { |
67 | 67 | GameManager parent; |
68 | - public bool IsMove; | |
69 | - public bool IsBuild; | |
70 | - public bool IsFinish; | |
68 | + public bool IsMove { get; private set; } | |
69 | + public bool IsBuild { get; private set; } | |
70 | + public bool IsFinish { get; private set; } | |
71 | 71 | |
72 | 72 | public ManagerCommander(GameManager parent) |
73 | 73 | { |
74 | 74 | this.parent = parent; |
75 | 75 | } |
76 | 76 | |
77 | + public int Player | |
78 | + { | |
79 | + get | |
80 | + { | |
81 | + return parent.Player; | |
82 | + } | |
83 | + } | |
84 | + | |
77 | 85 | public void Move(int x, int y, Direction dir, int robot) |
78 | 86 | { |
79 | 87 | if (IsFinish || IsBuild) throw new Exception(); |
80 | - if (!parent.Field.Move(parent.Player, x, y, dir, robot)) throw new Exception(); | |
88 | + if (parent.Field[x, y].Player != Player) throw new Exception(); | |
89 | + if (!parent.Field.Move(x, y, dir, robot)) throw new Exception(); | |
81 | 90 | IsMove = true; |
82 | 91 | } |
83 | 92 | |
84 | 93 | public void Build(int x, int y, Terrain building) |
85 | 94 | { |
86 | 95 | if (IsFinish || IsBuild || IsMove) throw new Exception(); |
87 | - if (!parent.Field.Build(parent.Player, x, y, building, ref parent.ExtraPoint[parent.Player])) throw new Exception(); | |
96 | + if (parent.Field[x, y].Player != Player) throw new Exception(); | |
97 | + if (!parent.Field.Build(x, y, building, ref parent.ExtraPoint[parent.Player])) throw new Exception(); | |
88 | 98 | IsBuild = true; |
89 | 99 | } |
90 | 100 |
@@ -85,14 +85,14 @@ namespace Visualizer | ||
85 | 85 | |
86 | 86 | private int JoiningCount(bool[,] settled, int x, int y) |
87 | 87 | { |
88 | - if (IsInRange(x, y)) return 0; | |
88 | + if (!IsInRange(x, y)) return 0; | |
89 | 89 | if (settled[x, y]) return 0; |
90 | 90 | if (field[x, y].Ter == Terrain.Outside || field[x, y].Ter == Terrain.Hole) return 0; |
91 | 91 | int result = 1, tx, ty; |
92 | 92 | settled[x, y] = true; |
93 | 93 | for (int i = 1; i < 7; i++) |
94 | 94 | { |
95 | - TransformAdjoin(i, x, y, out tx, out ty); | |
95 | + TransformDirection(i, x, y, out tx, out ty); | |
96 | 96 | result += JoiningCount(settled, tx, ty); |
97 | 97 | } |
98 | 98 | return result; |
@@ -18,6 +18,8 @@ | ||
18 | 18 | <CheckBox x:Name="ShowRobot" Content="Robot" IsChecked="True" Click="ShowChangeHandler"/> |
19 | 19 | <CheckBox x:Name="ShowResource" Content="Resource" Click="ShowChangeHandler"/> |
20 | 20 | <CheckBox x:Name="ShowTowerDamage" Content="Tower damage" Click="ShowChangeHandler"/> |
21 | + <CheckBox x:Name="ShowDistanse" Content="Distance" Click="ShowChangeHandler"/> | |
22 | + <CheckBox x:Name="ShowEvaluate" Content="Evaluate" Click="ShowChangeHandler"/> | |
21 | 23 | </StackPanel> |
22 | 24 | <GridSplitter Width="1" IsEnabled="False" Background="Black" Margin="0"/> |
23 | 25 | </Grid> |
@@ -22,23 +22,30 @@ namespace Visualizer | ||
22 | 22 | public partial class MainWindow : Window |
23 | 23 | { |
24 | 24 | GameManager manager; |
25 | + DistanceMap distance; | |
26 | + EvaluateGround evaluate; | |
25 | 27 | MassInformation[,] mass; |
28 | + int selectX; | |
29 | + int selectY; | |
26 | 30 | |
27 | 31 | public MainWindow() |
28 | 32 | { |
29 | 33 | InitializeComponent(); |
30 | 34 | manager = new GameManager(new Random()); |
31 | - manager.AI[0] = new TestAI(); | |
32 | - manager.AI[1] = new TestAI(); | |
33 | - manager.AI[2] = new TestAI(); | |
35 | + manager.AI[0] = new KamikazeAI(); | |
36 | + manager.AI[1] = new KamikazeAI(); | |
37 | + manager.AI[2] = new KamikazeAI(); | |
34 | 38 | manager.Prepare(); |
35 | 39 | int w = manager.Field.Width, h = manager.Field.Height; |
36 | 40 | mass = new MassInformation[w, h]; |
41 | + selectX = w / 2; | |
42 | + selectY = h / 2; | |
37 | 43 | for (int x = 0; x < w; x++) |
38 | 44 | { |
39 | 45 | for (int y = 0; y < h; y++) |
40 | 46 | { |
41 | 47 | MassInformation temp = new MassInformation(); |
48 | + temp.MouseDown += CreateMassSelectHandler(x, y); | |
42 | 49 | mass[x, y] = temp; |
43 | 50 | FieldInfo.Children.Add(temp); |
44 | 51 | Canvas.SetLeft(temp, (x + y / 2.0) * temp.Width); |
@@ -48,17 +55,30 @@ namespace Visualizer | ||
48 | 55 | UpdateInfo(); |
49 | 56 | } |
50 | 57 | |
58 | + private MouseButtonEventHandler CreateMassSelectHandler(int x, int y) | |
59 | + { | |
60 | + return (sender, e) => | |
61 | + { | |
62 | + selectX = x; | |
63 | + selectY = y; | |
64 | + UpdateInfo(); | |
65 | + }; | |
66 | + } | |
67 | + | |
51 | 68 | private void UpdateInfo() |
52 | 69 | { |
53 | 70 | Player1Info.Text = manager.GetPlayerInfo(0); |
54 | 71 | Player2Info.Text = manager.GetPlayerInfo(1); |
55 | 72 | Player3Info.Text = manager.GetPlayerInfo(2); |
73 | + distance = new DistanceMap(manager.Field, manager.Player, selectX, selectY); | |
74 | + evaluate = new EvaluateGround(manager.Field); | |
56 | 75 | GameField field = manager.Field; |
57 | 76 | int w = field.Width, h = field.Height; |
58 | 77 | for (int x = 0; x < w; x++) |
59 | 78 | { |
60 | 79 | for (int y = 0; y < h; y++) |
61 | 80 | { |
81 | + mass[x, y].UpdateSelected(x == selectX && y == selectY); | |
62 | 82 | mass[x, y].UpdateTerrain(field[x, y].Player, field[x, y].Ter); |
63 | 83 | mass[x, y].UpdateTextInfo(BuildMassInfo(x, y)); |
64 | 84 | } |
@@ -81,6 +101,14 @@ namespace Visualizer | ||
81 | 101 | { |
82 | 102 | result.AppendLine("Td:" + field.GetEstimateTowerDamage(field[x, y].Player, x, y) + "(" + field.GetTowerDamage(manager.Player, x, y).ToString() + ")"); |
83 | 103 | } |
104 | + if (ShowDistanse.IsChecked == true) | |
105 | + { | |
106 | + result.AppendLine("Dt:" + distance[x, y].ToString()); | |
107 | + } | |
108 | + if (ShowEvaluate.IsChecked == true) | |
109 | + { | |
110 | + result.AppendLine("Ev:" + evaluate[x, y].ToString()); | |
111 | + } | |
84 | 112 | return result.ToString(); |
85 | 113 | } |
86 | 114 |
@@ -57,6 +57,18 @@ namespace Visualizer | ||
57 | 57 | return result; |
58 | 58 | } |
59 | 59 | |
60 | + public void UpdateSelected(bool select) | |
61 | + { | |
62 | + if (select) | |
63 | + { | |
64 | + BorderBrush = Brushes.White; | |
65 | + } | |
66 | + else | |
67 | + { | |
68 | + BorderBrush = Brushes.Black; | |
69 | + } | |
70 | + } | |
71 | + | |
60 | 72 | public void UpdateTerrain(int player, Terrain ter) |
61 | 73 | { |
62 | 74 | switch (player) |