1 module gameboard;
2 
3 enum boardWidth = 6;
4 enum boardHeight = 9;
5 enum numRounds = 9;
6 
7 struct Hex
8 {
9 	size_t playerId;
10 	uint numShips;
11 	uint systemLevel;
12 }
13 
14 enum triPrimeX = 2;
15 enum triPrimeY = 3;
16 
17 bool isTriPrime(size_t x, size_t y)
18 {
19 	return
20 		(y == 3 && x == 2) ||
21 		(y == 4 && (x == 2 || x == 3)) ||
22 		(y == 5 && x == 2);
23 }
24 
25 struct HexCoords
26 {
27 	ubyte x;
28 	ubyte y;
29 }
30 
31 uint sectorNumber(HexCoords hexCoords)
32 {
33 	return hexCoords.x / 2 + (hexCoords.y / 3) * 3; // [0..9)
34 }
35 
36 HexCoords hexCoordsFromIndex(ubyte index) // [0..54)
37 {
38 	return HexCoords(index % boardWidth, index / boardWidth);
39 }
40 
41 // 6 x 9
42 struct GameBoard
43 {
44 	Hex[54] data;
45 
46 	ref Hex triPrime() @property
47 	{
48 		return data[triPrimeX + triPrimeY * boardWidth];
49 	}
50 
51 	ref Hex triPrime(Hex newData) @property
52 	{
53 		return data[triPrimeX + triPrimeY * boardWidth] = newData;
54 	}
55 
56 	ref Hex opIndex(size_t x, size_t y)
57 	{
58 		// x < 6 on even row, x < 5 on odd row.
59 		if (x >= boardWidth - (y % 2) || y >= boardHeight)
60 			return data[11]; // unused hex
61 
62 		if (isTriPrime(x, y))
63 			return triPrime;
64 
65 		return data[x + y * boardWidth];
66 	}
67 
68 	ref Hex opIndexAssign(Hex newData, size_t x, size_t y)
69 	{
70 		// x < 6 on even row, x < 5 on odd row.
71 		if (x >= boardWidth - (y % 2) || y >= boardHeight)
72 			return data[11]; // unused hex
73 
74 		if (isTriPrime(x, y))
75 			return triPrime = newData;
76 
77 		return data[x + y * boardWidth] = newData;
78 	}
79 
80 	auto sectorHexes(ubyte sectorId) // 0-8
81 	{
82 		HexCoords[] sectors;
83 		foreach(ubyte index, hex; data)
84 		{
85 			HexCoords coords = hexCoordsFromIndex(index);
86 			if (sectorNumber(coords) == sectorId)
87 				sectors ~= coords;
88 		}
89 		return sectors;
90 	}
91 }