From 018a4c5dd2aded63ae2561a51c96b2c7bda89ada Mon Sep 17 00:00:00 2001 From: Benjamin Chausse Date: Tue, 31 Dec 2019 10:05:01 -0500 Subject: Initial commit --- aesthetics.go | 78 ++++++++++++++++++++++++++++ backend.go | 163 ++++++++++++++++++++++++++++++++++++++++++++++++++++++++++ main.go | 82 +++++++++++++++++++++++++++++ 3 files changed, 323 insertions(+) create mode 100644 aesthetics.go create mode 100644 backend.go create mode 100644 main.go 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()) + + } + } +} -- cgit v1.2.3