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
|
package main
import (
// "fmt"
)
type parameters struct {
vsCPU bool
sshGame bool
debug bool
}
type userError struct {
query string
err error
}
// boatlist catalogs boat structures for use with icons.
// It is meant to be used with a "boatchars" slice containing said icons (with sunk and unsunk boats).
// Here are the slice values meanings:
// 0: Water
// 1: Vertical north tip (Triangle)
// 2: Vertical south tip (Triangle)
// 3: Horizontal west tip (Triangle)
// 4: Horizontal east tip (Triangle)
// 5: Vertical body section (rectangle)
// 6: Horizontal body section (rectangle)
var boatlist = [5][2][5]int{
// Horizontal | Vertical
// Carrier:
{{3, 6, 6, 6, 4}, {1, 5, 5, 5, 2}},
// Battleship
{{3, 6, 6, 4, 0}, {1, 5, 5, 2, 0}},
// Destroyer
{{3, 6, 6, 0, 0}, {1, 5, 5, 0, 0}},
// Submarine
{{3, 6, 4, 0, 0}, {1, 5, 2, 0, 0}},
// PatrolBoat
{{3, 6, 0, 0, 0}, {1, 5, 0, 0, 0}},
}
/* Boats Info:
|------------+--------+----------------|
| BoatName | BoatID | HorizontalBoat |
| Carrier | 0 | ◁ ▭ ▭ ▭ ▷ |
| Battleship | 1 | ◁ ▭ ▭ ▷ |
| Destroyer | 2 | ▭ ▭ ▷ |
| Submarine | 3 | ◁ ▭ ▷ |
| PatrolBoat | 4 | ▭ ▷ |
|------------+--------+----------------|
*/
// player contains all the environment of a player.
// primary is the grid containing his own boats.
// target stores info the player knows about the ennemy.
// gains keeps track of the ships the player has managed to sink.
type player struct {
name string
primary [10][10][3]int
// Primary Boat Tile Vector
// [y][x][boatID, position, hitStatus]int
// - [y][x]
// The last slice index defines his coordinates in the x,y axis.
// - BoatID:
// n+1: Water
// n: ID of the boat
// - Position:
// 0: Water
// 1: North arrow
// 2: South arrow
// 3: West arrow
// 4: East arrow
// 5: Vertical middle
// 6: Horizontal middle
// - HitStatus:
// 0: Unhit
// 1: Hit
target [10][10][2]int
// Target Boat Tile Vector
// [ hit, id ]
// - hit:
// true: Was hit
// false: Has not been hit
// - id:
// 0: water or unknown
// n: ID of the boat
gains [5]bool
// True if a boat index (ID) is sunk
prey *player
}
func (plyr *player) InitBoard(opponent *player) {
// Sets the players' opponent
plyr.prey = opponent
for r := 0; r < 10; r++ {
for c := 0; c < 10; c++ {
plyr.primary[r][c] = [3]int{6, 0, 0}
plyr.target[r][c] = [2]int{0, 6}
}
}
}
// initBoat places a boat on a players primary grid.
// boat sizes are defined by the boatlist variable.
// Consult it for more info.
func (plyr *player) InitBoat(boatID, orientation, x, y int) {
boatLength := len(boatlist[boatID][0])
if orientation == 0 { // Boat is HORIZONTAL
for i := 0; i < boatLength; i++ {
char := boatlist[boatID][0][i]
if char == 0 { // Compensating for boatlist having
break // zeros at the end of slices
}
//TODO: Add error handling for stacking boats
plyr.primary[y][x][0] = boatID
plyr.primary[y][x][1] = char
x++ // HORIZONTAL: Therefore the loop increments the x axis
}
} else { // Boat is VERTICAL
for i := 0; i < boatLength; i++ {
char := boatlist[boatID][1][i]
if char == 0 {
break
}
plyr.primary[y][x][0] = boatID
plyr.primary[y][x][1] = char
y++ // VERTICAL: Therefore the loop increments the y axis
}
}
}
func (plyr *player) Hit(x, y int) bool {
// We change the coord status to hit
// We add the id of the boat since we know it now.
plyr.prey.primary[y][x][2] = 1
plyr.target[y][x] = [2]int{1, plyr.prey.primary[y][x][0]}
// If that coordinate contains a boat
if BoatID := plyr.prey.primary[y][x][0]; BoatID < 5 {
switch plyr.prey.primary[y][x][1] {
case 1, 2, 5: // If the hit boat was vertical
// We suppose the boat is sunk since it only takes one unhit coordinate to prove this wrong
plyr.gains[plyr.prey.primary[y][x][0]] = true
// We check the entire column iteratively
for i := 0; i < 10; i++ {
// If the boat ID of the coordinate on the board is the same as the boat which was hit
// AND
// If the boat was not hit at that coordinate
if plyr.prey.primary[i][x][0] == plyr.prey.primary[y][x][0] && plyr.prey.primary[i][x][2] == 0 {
// Then reset the boat to being unsunk
plyr.gains[plyr.prey.primary[y][x][0]] = false
break
}
}
case 3, 4, 6: // If the hit boat was horizontal
// We suppose the boat is sunk since it only takes one unhit coordinate to prove this wrong
plyr.gains[plyr.prey.primary[y][x][0]] = true
// We check the entire row iteratively
for j := 0; j < 10; j++ {
// If the boat ID of the coordinate on the board is the same as the boat which was hit
// AND
// If the boat was not hit at that coordinate
if plyr.prey.primary[y][j][0] == plyr.prey.primary[y][x][0] && plyr.prey.primary[y][j][2] == 0 {
// Then reset the boat to being unsunk
plyr.gains[plyr.prey.primary[y][x][0]] = false
break
}
}
}
return true // Returns true if there was a hit
} else {
return false // Returns false if water was hit
}
}
const horizontal = 0
const vertical = 1
|