|
@@ -9,71 +9,48 @@ import (
|
|
|
"time"
|
|
"time"
|
|
|
)
|
|
)
|
|
|
|
|
|
|
|
|
|
+var setMask [4]byte = [4]byte{0xFC, 0xF3, 0xCF, 0x3F}
|
|
|
|
|
+var getMask [4]byte = [4]byte{0x03, 0x0C, 0x30, 0xC0}
|
|
|
|
|
+
|
|
|
type Board struct {
|
|
type Board struct {
|
|
|
- Cols int `json:"cols"`
|
|
|
|
|
- Rows int `json:"rows"`
|
|
|
|
|
|
|
+ Width int `json:"cols"`
|
|
|
|
|
+ Height int `json:"rows"`
|
|
|
Finish Coordinate `json:"finish"`
|
|
Finish Coordinate `json:"finish"`
|
|
|
- Tiles []Tile `json:"-"`
|
|
|
|
|
|
|
+ data []byte `json:"-"`
|
|
|
}
|
|
}
|
|
|
|
|
|
|
|
const maxIceWidth = 26
|
|
const maxIceWidth = 26
|
|
|
|
|
|
|
|
// Create a new randomly generated board.
|
|
// 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) {
|
|
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, "]}")
|
|
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) {
|
|
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 {
|
|
if startCol < 0 {
|
|
|
cols += startCol
|
|
cols += startCol
|
|
|
startCol = 0
|
|
startCol = 0
|
|
|
}
|
|
}
|
|
|
- if startRow > b.Rows {
|
|
|
|
|
- startRow = b.Rows
|
|
|
|
|
|
|
+ if startRow > b.Height {
|
|
|
|
|
+ startRow = b.Height
|
|
|
}
|
|
}
|
|
|
if startRow < 0 {
|
|
if startRow < 0 {
|
|
|
rows += startRow
|
|
rows += startRow
|
|
|
startRow = 0
|
|
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 {
|
|
if cols < 0 {
|
|
|
cols = 0
|
|
cols = 0
|