board.go 3.3 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171
  1. package board
  2. import (
  3. "bytes"
  4. "encoding/json"
  5. "fmt"
  6. "io"
  7. "log"
  8. "math/rand"
  9. "net/http"
  10. )
  11. type Board struct {
  12. Cols int `json:"cols"`
  13. Rows int `json:"rows"`
  14. Finish Coordinate `json:"finish"`
  15. Tiles []byte `json:"-"`
  16. }
  17. type req struct {
  18. x, y, width, height int
  19. }
  20. type response struct {
  21. boardTile io.ReadCloser
  22. x, y int
  23. }
  24. // Create a new randomly generated board.
  25. func New(width, height int) *Board {
  26. b := &Board{
  27. Cols: width,
  28. Rows: height,
  29. Tiles: make([]byte, height*width)}
  30. log.Printf("Start creating board %v x %v", width, height)
  31. regionWidth := 8
  32. regionHieght := 8
  33. regionWidthNum := width / regionWidth
  34. regionHeightNum := height / regionHieght
  35. returnChan := make(chan response)
  36. for i := 0; i < regionWidthNum; i++ {
  37. for j := 0; j < regionHeightNum; j++ {
  38. x := i * regionWidth
  39. y := j * regionHieght
  40. gbt := req{
  41. x: x,
  42. y: y,
  43. width: regionWidth,
  44. height: regionHieght,
  45. }
  46. go genRegion(gbt, returnChan)
  47. }
  48. }
  49. answers := 0
  50. for regionWidthNum+regionHeightNum > answers {
  51. result := <-returnChan
  52. n :=-1
  53. for n != 0 {
  54. index := result.x*b.Cols+result.y
  55. ba := b.Tiles[index:index+regionWidth]
  56. n, _ = result.boardTile.Read(ba)
  57. }
  58. answers++
  59. }
  60. igloY := rand.Intn(height-2) + 1
  61. b.Set(width-2, igloY, Iglo)
  62. b.Finish.X = width - 2
  63. b.Finish.Y = igloY
  64. b.Set(width-2, igloY-1, Water)
  65. b.Set(width-2, igloY+1, Water)
  66. log.Printf("Finished creating board %v x %v\n", width, height)
  67. return b
  68. }
  69. func genRegion(req req, responseChan chan response) {
  70. requestUrl := fmt.Sprintf("http://localhost:8080/&width=%v&height=%v&x=%v&y=%v", req.width, req.height, req.x, req.y)
  71. log.Printf("Requested generation of tile with url: %v\n", requestUrl)
  72. resp, _ := http.Get(requestUrl)
  73. result := response{
  74. x: req.x,
  75. y: req.y,
  76. boardTile: resp.Body,
  77. }
  78. responseChan <- result
  79. }
  80. // Set the tile in column x and row y to val.
  81. func (b *Board) Set(x, y int, val Tile) {
  82. b.Tiles[y*b.Cols+x] = byte(val)
  83. }
  84. // Get the tile in column x and row y.
  85. func (b *Board) Get(x, y int) Tile {
  86. return Tile(b.Tiles[y*b.Cols+x])
  87. }
  88. func (b *Board) String() string {
  89. var buffer bytes.Buffer
  90. for y := 0; y < b.Rows; y++ {
  91. for x := 0; x < b.Cols; x++ {
  92. buffer.WriteString(b.Get(x, y).String())
  93. }
  94. buffer.WriteString(fmt.Sprintln())
  95. }
  96. return buffer.String()
  97. }
  98. func (b *Board) WriteJSON(w io.Writer, startCol, startRow, cols, rows int) {
  99. sc, sr, cols, rows := sanitizeViewPort(b, startCol, startRow, cols, rows)
  100. fmt.Fprintf(w, "{\"x\":%v,\"y\":%v,\"rows\":%v,\"cols\":%v,\"tiles\":[", sc, sr, cols, rows)
  101. for y := startRow; y < sr+rows; y++ {
  102. for x := startCol; x < sc+cols; x++ {
  103. if !(x == startCol && y == startRow) {
  104. w.Write([]byte{','})
  105. }
  106. t := &jsonTile{x, y, b.Get(x, y).Name(), ""}
  107. bs, _ := json.Marshal(t)
  108. w.Write(bs)
  109. }
  110. }
  111. fmt.Fprintf(w, "]}")
  112. }
  113. func sanitizeViewPort(b *Board, startCol, startRow, cols, rows int) (int, int, int, int) {
  114. if startCol > b.Cols {
  115. startCol = b.Cols
  116. }
  117. if startCol < 0 {
  118. cols += startCol
  119. startCol = 0
  120. }
  121. if startRow > b.Rows {
  122. startRow = b.Rows
  123. }
  124. if startRow < 0 {
  125. rows += startRow
  126. startRow = 0
  127. }
  128. if startCol+cols > b.Cols {
  129. cols = b.Cols - startCol
  130. }
  131. if startRow+rows > b.Rows {
  132. rows = b.Rows - startRow
  133. }
  134. if cols < 0 {
  135. cols = 0
  136. }
  137. if rows < 0 {
  138. rows = 0
  139. }
  140. return startCol, startRow, cols, rows
  141. }