summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorBenjamin Chausse <benjamin@chausse.xyz>2019-12-31 10:05:01 -0500
committerBenjamin Chausse <benjamin@chausse.xyz>2019-12-31 10:05:01 -0500
commit018a4c5dd2aded63ae2561a51c96b2c7bda89ada (patch)
treea46a476c3cfde739b71c70d296a26d42a18bfeae
Initial commit
-rw-r--r--aesthetics.go78
-rw-r--r--backend.go163
-rw-r--r--main.go82
3 files changed, 323 insertions, 0 deletions
diff --git a/aesthetics.go b/aesthetics.go
new file mode 100644
index 0000000..efc7cef
--- /dev/null
+++ b/aesthetics.go
@@ -0,0 +1,78 @@
+package main
+
+import (
+ "strconv"
+)
+
+// printPrimary displays using ASCII art the primary battleship board
+func (plyr player) PrimaryDisplay() string {
+ text := "\n A B C D E F G H I J \n"
+ for i := 0; i < 10; i++ {
+ text += strconv.Itoa(i)
+ text += " "
+ for j := 0; j < 10; j++ {
+ switch plyr.primary[i][j][2] {
+ case 0: // That coordinate was not hit
+ text += boatchars[1][plyr.primary[i][j][1]]
+ case 1: // That coordinates was hit
+ text += boatchars[0][plyr.primary[i][j][1]]
+ // default:
+ // return errors.New("Unknown State (hit/unhit) at a given coordinate")
+ }
+ text += " "
+ }
+ text += "\n"
+ }
+ // fmt.Println(text)
+ return text
+}
+
+func (plyr player) TargetDisplay() string {
+ text := "\n A B C D E F G H I J \n"
+ for i := 0; i < 10; i++ {
+ text += strconv.Itoa(i)
+ text += " "
+ for j := 0; j < 10; j++ {
+ switch plyr.target[i][j][0] {
+ case 0:
+ text += boatchars[1][0]
+ case 1:
+ if plyr.gains[plyr.prey.primary[i][j][0]] {
+ text += boatchars[0][plyr.prey.primary[i][j][1]]
+ } else {
+ switch plyr.prey.primary[i][j][0] {
+ case 0:
+ text += boatchars[0][0]
+ default:
+ text += mistery_hit
+ }
+ }
+ }
+ text += " "
+ }
+ text += "\n"
+ }
+ // fmt.Println(text)
+ return text
+}
+
+// TODO: Function which returns what was hit as a commentary for the hitter
+
+/* Boats Info:
+ |------------+--------+----------------|
+ | BoatName | BoatID | HorizontalBoat |
+ | Carrier | 0 | ◁ ▭ ▭ ▭ ▷ |
+ | Battleship | 1 | ◁ ▭ ▭ ▷ |
+ | Destroyer | 2 | ▭ ▭ ▷ |
+ | Submarine | 3 | ◁ ▭ ▷ |
+ | PatrolBoat | 4 | ▭ ▷ |
+ |------------+--------+----------------|
+*/
+var boatchars = [2][7]string{
+ {`◌`, `▲`, `▼`, `◀`, `►`, `▮`, `▬`},
+ {`~`, `△`, `▽`, `◁`, `▷`, `▯`, `▭`},
+}
+
+// This constant keeps information about boats that aren't totally sunk secret.
+// It therefore substitues the shape of a boat on the target board when it is unsunk.
+const mistery_hit = `▣`
diff --git a/backend.go b/backend.go
new file mode 100644
index 0000000..d1cd758
--- /dev/null
+++ b/backend.go
@@ -0,0 +1,163 @@
+package main
+
+import (
+// "fmt"
+)
+
+type parameters struct {
+ vs_cpu bool
+ ssh_game 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 {
+ 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
+}
+
+// initBoat places a boat on a players primary grid.
+// boat sizes are defined by the boatlist variable.
+// Consult it for more info.
+func initBoat(plyr *player, boat [4]int) {
+ boatID := boat[0]
+ boat_length := len(boatlist[boatID][0])
+ x, y := boat[2], boat[3]
+ if boat[1] == 0 { // Boat is HORIZONTAL
+ for i := 0; i < boat_length; 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 < boat_length; 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(coord [2]int) bool {
+ x, y := coord[0], coord[1]
+ plyr.prey.primary[y][x][2] = 1
+ plyr.target[y][x] = [2]int{1, plyr.prey.primary[y][x][0]}
+
+ if BoatID := plyr.prey.primary[y][x][0]; BoatID > 0 {
+ 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
+ }
+}
diff --git a/main.go b/main.go
new file mode 100644
index 0000000..933b63c
--- /dev/null
+++ b/main.go
@@ -0,0 +1,82 @@
+package main
+
+import (
+ "fmt"
+)
+
+func main() {
+
+ settings := parameters{
+ debug: true,
+ ssh_game: false,
+ }
+
+ if settings.debug {
+
+ // SETUP:
+ var player_one = player{}
+ var player_two = player{}
+ // Setting up prey for when using Hit function
+ player_one.prey = &player_two
+ player_two.prey = &player_one
+
+ if settings.debug {
+ fmt.Println("# #---TESTING SEQUENCE---# #")
+
+ player_one.primary = [10][10][3]int{} // Empty plyr1 board
+ // Initialising boats on the board work* (see initBoat TODOS)
+ initBoat(&player_one, [4]int{0, 0, 0, 0}) // Index 0 -> Carrier
+ initBoat(&player_one, [4]int{1, 0, 6, 9}) // Index 1 -> Battleship
+ initBoat(&player_one, [4]int{2, 1, 4, 3}) // Index 2 -> Destroyer
+ initBoat(&player_one, [4]int{3, 1, 7, 1}) // Index 3 -> Submarine
+ initBoat(&player_one, [4]int{4, 1, 1, 8}) // Index 4 -> PatrolBoat
+ // fmt.Println("Player 1:")
+ // fmt.Print(player_one.PrimaryDisplay())
+
+ // Initialising the board works
+ // fmt.Println("Empty:")
+ // fmt.Print(player_one.PrimaryDisplay())
+
+ player_two.primary = [10][10][3]int{} // Empty plyr2 board
+ initBoat(&player_two, [4]int{0, 0, 3, 3}) // Index 0 -> Carrier
+ initBoat(&player_two, [4]int{1, 0, 4, 8}) // Index 1 -> Battleship
+ initBoat(&player_two, [4]int{2, 1, 2, 4}) // Index 2 -> Destroyer
+ initBoat(&player_two, [4]int{3, 1, 9, 0}) // Index 3 -> Submarine
+ initBoat(&player_two, [4]int{4, 1, 7, 4}) // Index 4 -> PatrolBoat
+
+ fmt.Println("Player 2:")
+ fmt.Print(player_two.PrimaryDisplay())
+
+ // fmt.Println("Hit B2:")
+ // hit_coord := [2]int{1, 2} // Water hit at B2
+ // fmt.Print("There was a boat: ")
+ // fmt.Println(player_one.Hit(hit_coord))
+ // fmt.Println(player_two.PrimaryDisplay())
+ // fmt.Println("Hit H4:")
+ // hit_coord = [2]int{7, 4} // PatrolBoat hit at H4
+ // fmt.Print("There was a boat: ")
+ // fmt.Println(player_one.Hit(hit_coord))
+ // fmt.Println(player_two.PrimaryDisplay())
+ // fmt.Println("Player 1 TargetDisplay:")
+ // fmt.Println(player_one.TargetDisplay())
+ // fmt.Println("Hit H5:")
+ // hit_coord = [2]int{7, 5} // PatrolBoat hit at H4
+ // fmt.Print("There was a boat: ")
+ // fmt.Println(player_one.Hit(hit_coord))
+ // fmt.Println(player_two.PrimaryDisplay())
+ // fmt.Println("Player 1 TargetDisplay:")
+ // fmt.Println(player_one.TargetDisplay())
+
+ fmt.Println("Hit: E8, F8, G8")
+ player_one.Hit([2]int{4, 8})
+ player_one.Hit([2]int{5, 8})
+ player_one.Hit([2]int{6, 8})
+ fmt.Println(player_two.PrimaryDisplay())
+ fmt.Println(player_one.TargetDisplay())
+ player_one.Hit([2]int{6, 8})
+ fmt.Println(player_two.PrimaryDisplay())
+ fmt.Println(player_one.TargetDisplay())
+
+ }
+ }
+}