-
Notifications
You must be signed in to change notification settings - Fork 14
/
BoardManipulationOddR.cs
182 lines (149 loc) · 6.01 KB
/
BoardManipulationOddR.cs
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
using System.Collections.Generic;
using HexBoardGame.SharedData;
using Tools.Extensions.Arrays;
using UnityEngine;
namespace HexBoardGame.Runtime
{
/// <summary>
/// The way to manipulate a board in the Odd-Row layout.
/// TODO: Open for many memory/cache optimizations and algorithms improvements.
/// </summary>
public class BoardManipulationOddR : IBoardManipulation
{
private static readonly Hex[] NeighboursDirections =
{
new Hex(1, 0), new Hex(1, -1), new Hex(0, -1),
new Hex(-1, 0), new Hex(-1, 1), new Hex(0, 1)
};
private readonly Hex[] _hexPoints;
public BoardManipulationOddR(BoardDataShape dataShape)
{
_hexPoints = dataShape.GetHexPoints();
}
public Hex[] GetNeighbours(Vector3Int cell)
{
var point = GetHexCoordinate(cell);
var center = GetIfExistsOrEmpty(point);
var neighbours = new Hex[] { };
foreach (var direction in NeighboursDirections)
{
var neighbour = Hex.Add(center[0], direction);
neighbours = neighbours.Append(GetIfExistsOrEmpty(neighbour));
}
return neighbours;
}
/// <summary>
/// If the point is present among the starting configuration returns it. Otherwise returns a empty array.
/// </summary>
private Hex[] GetIfExistsOrEmpty(Hex hex)
{
var cell = GetCellCoordinate(hex);
return Contains(cell) ? new[] {GetHexCoordinate(cell)} : new Hex[] { };
}
#region Operations
public bool Contains(Vector3Int cell)
{
var hex = GetHexCoordinate(cell);
foreach (var i in _hexPoints)
if (i == hex)
return true;
return false;
}
public Hex[] GetVertical(Vector3Int cell, int length)
{
//For Odd-R the vertical is always empty.
return new Hex[] { };
}
public Hex[] GetHorizontal(Vector3Int cell, int length)
{
var point = GetHexCoordinate(cell);
var halfLength = length / 2;
var points = GetIfExistsOrEmpty(point);
var x = point.q;
var y = point.r;
for (var i = 1; i <= halfLength; i++)
points = points.Append(GetIfExistsOrEmpty(new Hex(x + i, y)));
for (var i = -1; i >= -halfLength; i--)
points = points.Append(GetIfExistsOrEmpty(new Hex(x + i, y)));
return points;
}
public Hex[] GetDiagonalAscendant(Vector3Int cell, int length)
{
var point = GetHexCoordinate(cell);
var halfLength = length / 2;
var points = GetIfExistsOrEmpty(point);
var x = point.q;
var y = point.r;
for (var i = 1; i <= halfLength; i++)
points = points.Append(GetIfExistsOrEmpty(new Hex(x, y + i)));
for (var i = -1; i >= -halfLength; i--)
points = points.Append(GetIfExistsOrEmpty(new Hex(x, y + i)));
return points;
}
public Hex[] GetDiagonalDescendant(Vector3Int cell, int length)
{
var point = GetHexCoordinate(cell);
var halfLength = length / 2;
var points = GetIfExistsOrEmpty(point);
var x = point.q;
var y = point.r;
for (var i = 1; i <= halfLength; i++)
points = points.Append(GetIfExistsOrEmpty(new Hex(x - i, y + i)));
for (var i = -1; i >= -halfLength; i--)
points = points.Append(GetIfExistsOrEmpty(new Hex(x - i, y + i)));
return points;
}
public Hex[] GetPathBreadthSearch(Vector3Int begin, Vector3Int end)
{
var beginHex = GetHexCoordinate(begin);
var endHex = GetHexCoordinate(end);
var frontier = new Queue<Hex>();
frontier.Enqueue(beginHex);
var visited = new Dictionary<Hex, Hex>();
//Creating the breadcrumbs
while (frontier.Count > 0)
{
var current = frontier.Dequeue();
if (current == endHex)
break;
var currentCell = GetCellCoordinate(current);
var neighbours = GetNeighbours(currentCell);
foreach (var next in neighbours)
{
if (!visited.ContainsKey(next))
{
frontier.Enqueue(next);
visited[next] = current;
}
}
}
//Backtracking from the ending point
var path = new List<Hex>();
while(endHex != beginHex)
{
path.Add(endHex);
endHex = visited[endHex];
}
path.Add(beginHex);
path.Reverse();
return path.ToArray();
}
/// <summary>
/// Unity by default makes use the R-Offset Odd to reference tiles inside a TileMap with a vector3Int cell.
/// The internal board manipulation works with HexCoordinates, this method converts vector3int cell to hex.
/// </summary>
public static Hex GetHexCoordinate(Vector3Int cell)
{
return OffsetCoordHelper.RoffsetToCube(OffsetCoord.Parity.Odd, new OffsetCoord(cell.x, cell.y));
}
/// <summary>
/// Unity by default makes use the R-Offset Odd to reference tiles inside a TileMap with a vector3Int cell.
/// The internal board manipulation works with HexCoordinates, this method converts hex to unity vector3int cell.
/// </summary>
public static Vector3Int GetCellCoordinate(Hex hex)
{
return OffsetCoordHelper.RoffsetFromCube(OffsetCoord.Parity.Odd, hex).ToVector3Int();
}
#endregion
}
}