Explorar o código

Efficientere bordrepresentatie, boardgenerater afgesplitst.

Harry de Boer %!s(int64=10) %!d(string=hai) anos
pai
achega
0e1d8a6799
Modificáronse 7 ficheiros con 126 adicións e 80 borrados
  1. 24 0
      battlecamp-go-boardgenerator/main.go
  2. 77 56
      board/board.go
  3. 1 1
      board/board_test.go
  4. 11 10
      board/tile.go
  5. 3 3
      games/game.go
  6. 9 9
      games/games_test.go
  7. 1 1
      urlrouter.go

+ 24 - 0
battlecamp-go-boardgenerator/main.go

@@ -0,0 +1,24 @@
+package main
+
+import (
+	"battlecamp-go-server/board"
+	"log"
+	"net/http"
+	"strconv"
+)
+
+func main() {
+	http.HandleFunc("", generateBoard)
+	log.Fatal(http.ListenAndServe(":8081", nil))
+}
+
+func generateBoard(w http.ResponseWriter, r *http.Request) {
+	x, _ := strconv.Atoi(r.FormValue("x"))
+	y, _ := strconv.Atoi(r.FormValue("y"))
+	width, _ := strconv.Atoi(r.FormValue("width"))
+	height, _ := strconv.Atoi(r.FormValue("height"))
+	totalWidth, _ := strconv.Atoi(r.FormValue("totalWidth"))
+	totalHeight, _ := strconv.Atoi(r.FormValue("totalHeight"))
+	b := board.NewPartial(x, y, width, height, totalWidth, totalHeight)
+	b.WriteData(w)
+}

+ 77 - 56
board/board.go

@@ -9,71 +9,48 @@ import (
 	"time"
 )
 
+var setMask [4]byte = [4]byte{0xFC, 0xF3, 0xCF, 0x3F}
+var getMask [4]byte = [4]byte{0x03, 0x0C, 0x30, 0xC0}
+
 type Board struct {
-	Cols   int        `json:"cols"`
-	Rows   int        `json:"rows"`
+	Width  int        `json:"cols"`
+	Height int        `json:"rows"`
 	Finish Coordinate `json:"finish"`
-	Tiles  []Tile     `json:"-"`
+	data   []byte     `json:"-"`
 }
 
 const maxIceWidth = 26
 
 // Create a new randomly generated board.
-func New(cols, rows int) *Board {
-	r := rand.New(rand.NewSource(time.Now().UnixNano()))
-	return new(cols, rows, r)
+func New(width, height int) *Board {
+	return NewPartial(0, 0, width, height, width, height)
 }
 
-func new(cols, rows int, r *rand.Rand) *Board {
-	b := &Board{
-		Cols:  cols,
-		Rows:  rows,
-		Tiles: make([]Tile, rows*cols, rows*cols)}
-
-	for y := 0; y < rows; y++ {
-		for x := 0; x < cols; x++ {
-			switch {
-			case r.Intn(10) > 7:
-				b.Set(x, y, Rock)
-			case x > (b.Cols-maxIceWidth)/2 && x < b.Cols/2+maxIceWidth/2 && r.Intn(maxIceWidth) >= abs((b.Cols/2)-x):
-				b.Set(x, y, Ice)
-			default:
-				b.Set(x, y, Water)
-			}
-		}
-	}
-
-	igloY := r.Intn(rows-2) + 1
-
-	b.Set(cols-2, igloY, Iglo)
-	b.Finish.X = cols - 2
-	b.Finish.Y = igloY
-	b.Set(cols-2, igloY-1, Water)
-	b.Set(cols-2, igloY+1, Water)
-	return b
+func NewPartial(startX, startY, width, height, totalWidth, totalHeight int) *Board {
+	r := rand.New(rand.NewSource(time.Now().UnixNano()))
+	return newPartial(startX, startY, width, height, totalWidth, totalHeight, r)
 }
 
-// Set the tile in column x and row y to val.
-func (b *Board) Set(x, y int, val Tile) {
-	b.Tiles[y*b.Cols+x] = val
+func (b *Board) Set(x, y int, t TileType) {
+	index := uint(y*b.Width + x)
+	i := index / 4
+	p := index % 4
+	b.data[i] = (b.data[i] & setMask[p]) | byte(t)<<(p<<1)
 }
 
-// Get the tile in column x and row y.
-func (b *Board) Get(x, y int) Tile {
-	return b.Tiles[y*b.Cols+x]
+func (b *Board) Get(x, y int) TileType {
+	index := y*b.Width + x
+	i := index / 4
+	p := index % 4
+	return TileType((b.data[i] & getMask[p]) >> uint(p<<1))
 }
 
-func (b *Board) String() string {
-	var buffer bytes.Buffer
+func (b *Board) WriteData(w io.Writer) {
+	n, err := w.Write(b.data)
 
-	for y := 0; y < b.Rows; y++ {
-		for x := 0; x < b.Cols; x++ {
-			buffer.WriteString(b.Get(x, y).String())
-		}
-		buffer.WriteString(fmt.Sprintln())
+	if err != nil {
+		fmt.Errorf("Error writing board after %v bytes: %v", n, err)
 	}
-
-	return buffer.String()
 }
 
 func (b *Board) WriteJSON(w io.Writer, startCol, startRow, cols, rows int) {
@@ -94,26 +71,70 @@ func (b *Board) WriteJSON(w io.Writer, startCol, startRow, cols, rows int) {
 	fmt.Fprintf(w, "]}")
 }
 
+func (b *Board) String() string {
+	var buffer bytes.Buffer
+
+	for y := 0; y < b.Height; y++ {
+		for x := 0; x < b.Width; x++ {
+			buffer.WriteString(b.Get(x, y).String())
+		}
+		buffer.WriteString(fmt.Sprintln())
+	}
+
+	return buffer.String()
+}
+
+func new(width, height int, r *rand.Rand) *Board {
+	return newPartial(0, 0, width, height, width, height, r)
+}
+
+func newPartial(startX, startY, width, height, totalWidth, totalHeight int, r *rand.Rand) *Board {
+	b := &Board{
+		Width:  width,
+		Height: height,
+		data:   make([]byte, width*height),
+	}
+
+	leftLimit := (totalWidth-maxIceWidth)/2 - startX
+	rightLimit := totalWidth/2 + maxIceWidth/2 - startX
+	mid := totalWidth/2 - startX
+
+	for y := 0; y < height; y++ {
+		for x := 0; x < width; x++ {
+			switch {
+			case r.Intn(10) > 7:
+				b.Set(x, y, Rock)
+			case x > leftLimit && x < rightLimit && r.Intn(maxIceWidth) >= abs(mid-x):
+				b.Set(x, y, Ice)
+			default:
+				b.Set(x, y, Water)
+			}
+		}
+	}
+
+	return b
+}
+
 func sanitizeViewPort(b *Board, startCol, startRow, cols, rows int) (int, int, int, int) {
-	if startCol > b.Cols {
-		startCol = b.Cols
+	if startCol > b.Width {
+		startCol = b.Width
 	}
 	if startCol < 0 {
 		cols += startCol
 		startCol = 0
 	}
-	if startRow > b.Rows {
-		startRow = b.Rows
+	if startRow > b.Height {
+		startRow = b.Height
 	}
 	if startRow < 0 {
 		rows += startRow
 		startRow = 0
 	}
-	if startCol+cols > b.Cols {
-		cols = b.Cols - startCol
+	if startCol+cols > b.Width {
+		cols = b.Width - startCol
 	}
-	if startRow+rows > b.Rows {
-		rows = b.Rows - startRow
+	if startRow+rows > b.Height {
+		rows = b.Height - startRow
 	}
 	if cols < 0 {
 		cols = 0

+ 1 - 1
board/board_test.go

@@ -22,7 +22,7 @@ var testBoard = `~~~~~~~~▲▲▲~▲▲~~*~*~~**~*▲****▲▲***▲~▲***~~
 ▲~▲~~▲▲~~▲~~~▲~~~~********▲▲▲▲***▲*~***▲▲~~~~▲~~~~~~~▲~~
 ~▲~~~~▲▲~~~~~▲~~▲*~*▲▲*▲****▲▲******▲*~~*~~~~▲~~~~~~~▲~~
 ~~~~~~~~~~~~~~▲▲~▲~******▲*▲*▲**~*~*~**~*~~~~~~~~▲▲~~~~▲
-~~▲▲~~~~~~~~~~~▲***▲~*▲**▲*~***▲*********~~~~▲▲~~~~~▲~~
+~~▲▲~~~~~~~~~~~▲***▲~*▲**▲*~***▲*********~~~~▲▲~~~~~▲~~~
 ~~▲~~~~~~▲▲▲~~~~*~~▲~*~▲*▲*▲*****▲**▲~*▲*~▲~~~~▲▲~▲~~~~~
 ~~~~~~▲~~~▲▲~~~~*▲▲**~**▲*▲*▲***▲**▲*****~~~~▲~~~~~~~▲~~
 ~~▲~~~~▲~~~~~▲~~~*~********▲**▲*~*▲*▲**▲~~~~~~~~~~~~~~▲~

+ 11 - 10
board/tile.go

@@ -1,6 +1,8 @@
 package board
 
-type Tile byte
+import "fmt"
+
+type TileType byte
 
 type jsonTile struct {
 	X      int    `json:"x"`
@@ -10,13 +12,13 @@ type jsonTile struct {
 }
 
 const (
-	Water Tile = '~'
-	Ice   Tile = '*'
-	Rock  Tile = '^'
-	Iglo  Tile = 'O'
+	Water TileType = 0
+	Rock  TileType = 1
+	Ice   TileType = 2
+	Iglo  TileType = 3
 )
 
-func (t Tile) String() string {
+func (t TileType) String() string {
 	switch t {
 	case Water:
 		return "~"
@@ -28,10 +30,10 @@ func (t Tile) String() string {
 		return "⌂"
 	}
 
-	panic("Unknown tile type")
+	panic(fmt.Sprintf("Unknown tile type %#v", t))
 }
 
-func (t Tile) Name() string {
+func (t TileType) Name() string {
 	switch t {
 	case Water:
 		return "W" // API says WATER... zucht.
@@ -43,6 +45,5 @@ func (t Tile) Name() string {
 		return "H"
 	}
 
-	panic("Unknown tile type")
-
+	panic(fmt.Sprintf("Unknown tile type %#v", t))
 }

+ 3 - 3
games/game.go

@@ -42,8 +42,8 @@ func (g *Game) Join(p *player.Player) {
 }
 
 func (g *Game) placePlayer(p *player.Player) {
-	xRange := g.Board.Cols / 5
-	yRange := g.Board.Rows
+	xRange := g.Board.Width / 5
+	yRange := g.Board.Height
 
 	for {
 		x := rand.Intn(xRange)
@@ -125,7 +125,7 @@ func (g *Game) isWinner(p *player.Player) bool {
 }
 
 func (g *Game) isValidPlayerPos(x, y int) bool {
-	if x < 0 || y < 0 || x >= g.Board.Cols || y >= g.Board.Rows {
+	if x < 0 || y < 0 || x >= g.Board.Width || y >= g.Board.Height {
 		return false
 	}
 

+ 9 - 9
games/games_test.go

@@ -1,14 +1,14 @@
-	package games
+package games
 
 import (
 	"testing"
 )
 
 func TestAddGame(t *testing.T) {
-	
+
 	game := NewGame(100,100)
 	games := New()
-	
+
 	games.AddGame(game)
 	if len(games.ListGames()) != 1 {
 		t.Fatalf("Incorrect ListGames size expeciting 1 got %v", len(games.ListGames()))
@@ -16,29 +16,29 @@ func TestAddGame(t *testing.T) {
 }
 
 func TestAdd2Games(t *testing.T) {
-	
+
 	game := NewGame(100,100)
 	game2 := NewGame(100,100)
 	games := New()
-	
+
 	games.AddGame(game)
 	games.AddGame(game2)
 	if len(games.ListGames()) != 2 {
 		t.Fatalf("Incorrect ListGames size expeciting 2 got %v", len(games.ListGames()))
 	}
-	
+
 	if games.ListGames()[0].Id != game.Id {
 		t.Fatalf("Incorrect gameid expected %v got %v", games.ListGames()[0].Id, game.Id)
 	}
 }
 
 func TestAddGetGame(t *testing.T) {
-	
+
 	game := NewGame(100,100)
 	game2 := NewGame(100,100)
 	game3 := NewGame(100,100)
 	games := New()
-	
+
 	games.AddGame(game)
 	games.AddGame(game2)
 	games.AddGame(game3)
@@ -46,4 +46,4 @@ func TestAddGetGame(t *testing.T) {
 	if  resultGame.Id != game2.Id {
 		t.Fatalf("Incorrect ListGames size expeciting %v got %v", resultGame.Id, game2.Id)
 	}
-}
+}

+ 1 - 1
urlrouter.go

@@ -160,7 +160,7 @@ func showBoard(w http.ResponseWriter, req *http.Request, ps httprouter.Params) {
 	} else if xString != "" || yString != "" || colsString != "" || rowsString != "" {
 		http.Error(w, "Bad request", http.StatusBadRequest)
 	} else {
-		b.WriteJSON(w, 0, 0, b.Cols, b.Rows)
+		b.WriteJSON(w, 0, 0, b.Width, b.Height)
 	}
 }