package board import ( "bytes" "encoding/json" "fmt" "io" "log" "math/rand" "net/http" ) type Board struct { Cols int `json:"cols"` Rows int `json:"rows"` Finish Coordinate `json:"finish"` Tiles []byte `json:"-"` } type req struct { x, y, width, height int } type response struct { boardTile io.ReadCloser x, y int } // Create a new randomly generated board. func New(width, height int) *Board { b := &Board{ Cols: width, Rows: height, Tiles: make([]byte, height*width)} log.Printf("Start creating board %v x %v", width, height) regionWidth := 8 regionHieght := 8 regionWidthNum := width / regionWidth regionHeightNum := height / regionHieght returnChan := make(chan response) for i := 0; i < regionWidthNum; i++ { for j := 0; j < regionHeightNum; j++ { x := i * regionWidth y := j * regionHieght gbt := req{ x: x, y: y, width: regionWidth, height: regionHieght, } go genRegion(gbt, returnChan) } } answers := 0 for regionWidthNum+regionHeightNum > answers { result := <-returnChan n :=-1 for n != 0 { index := result.x*b.Cols+result.y ba := b.Tiles[index:index+regionWidth] n, _ = result.boardTile.Read(ba) } answers++ } igloY := rand.Intn(height-2) + 1 b.Set(width-2, igloY, Iglo) b.Finish.X = width - 2 b.Finish.Y = igloY b.Set(width-2, igloY-1, Water) b.Set(width-2, igloY+1, Water) log.Printf("Finished creating board %v x %v\n", width, height) return b } func genRegion(req req, responseChan chan response) { requestUrl := fmt.Sprintf("http://localhost:8080/&width=%v&height=%v&x=%v&y=%v", req.width, req.height, req.x, req.y) log.Printf("Requested generation of tile with url: %v\n", requestUrl) resp, _ := http.Get(requestUrl) result := response{ x: req.x, y: req.y, boardTile: resp.Body, } responseChan <- result } // 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] = byte(val) } // Get the tile in column x and row y. func (b *Board) Get(x, y int) Tile { return Tile(b.Tiles[y*b.Cols+x]) } func (b *Board) String() string { var buffer bytes.Buffer 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()) } return buffer.String() } func (b *Board) WriteJSON(w io.Writer, startCol, startRow, cols, rows int) { sc, sr, cols, rows := sanitizeViewPort(b, startCol, startRow, cols, rows) fmt.Fprintf(w, "{\"x\":%v,\"y\":%v,\"rows\":%v,\"cols\":%v,\"tiles\":[", sc, sr, cols, rows) for y := startRow; y < sr+rows; y++ { for x := startCol; x < sc+cols; x++ { if !(x == startCol && y == startRow) { w.Write([]byte{','}) } t := &jsonTile{x, y, b.Get(x, y).Name(), ""} bs, _ := json.Marshal(t) w.Write(bs) } } fmt.Fprintf(w, "]}") } func sanitizeViewPort(b *Board, startCol, startRow, cols, rows int) (int, int, int, int) { if startCol > b.Cols { startCol = b.Cols } if startCol < 0 { cols += startCol startCol = 0 } if startRow > b.Rows { startRow = b.Rows } if startRow < 0 { rows += startRow startRow = 0 } if startCol+cols > b.Cols { cols = b.Cols - startCol } if startRow+rows > b.Rows { rows = b.Rows - startRow } if cols < 0 { cols = 0 } if rows < 0 { rows = 0 } return startCol, startRow, cols, rows }