diff --git a/README.md b/README.md index cea1b41..f18526a 100644 --- a/README.md +++ b/README.md @@ -15,7 +15,7 @@ go install github.com/MichaelS11/tetris Then run the binary created, tetris or tetris.exe -## Keys +## Keys during game | Key | Action | | --- | --- | @@ -30,6 +30,15 @@ Then run the binary created, tetris or tetris.exe | q | quit | | i | toggle AI | +## Keys start screen + +| Key | Action | +| --- | --- | +| ← | previous board | +| → | next board | +| spacebar | start game | +| q | quit | + ## Features include @@ -38,6 +47,7 @@ Then run the binary created, tetris or tetris.exe - Next piece - Ghost piece - Top scores +- Board choices ## Screenshots @@ -46,4 +56,11 @@ Then run the binary created, tetris or tetris.exe ![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot2.png "Golang Tetris") -![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot3.png "Tetris Top Scores") +![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot3.png "Golang Tetris Heart") + +![alt text](https://raw.githubusercontent.com/MichaelS11/tetris/master/screenshots/screenshot4.png "Tetris High Scores") + + +## To do + +* Improve AI speed (slow on large boards) diff --git a/ai.go b/ai.go index 587cb5b..e199427 100644 --- a/ai.go +++ b/ai.go @@ -1,26 +1,22 @@ package main -const ( - aiQueueSize = (boardWidth+1)/2 + 6 - aiMoveLength = (boardWidth + 1) / 2 -) - -type Ai struct { - queue [aiQueueSize]rune - index int -} - func NewAi() *Ai { ai := Ai{} - for i := 0; i < aiQueueSize; i++ { - ai.queue[i] = 'x' - } + queue := make([]rune, 1) + queue[0] = 'x' + ai.queue = &queue return &ai } -func (ai *Ai) ProcessQueue() bool { +func (ai *Ai) ProcessQueue() { + if ai.newQueue != nil { + ai.queue = ai.newQueue + ai.newQueue = nil + ai.index = 0 + } + queue := *ai.queue // wasd + qe keyboard keys - switch ai.queue[ai.index] { + switch queue[ai.index] { case 'w': board.MinoDrop() case 'a': @@ -32,51 +28,31 @@ func (ai *Ai) ProcessQueue() bool { case 'e': board.MinoRotateRight() case 'x': - return false + return } ai.index++ - if ai.index == aiQueueSize { - ai.index = 0 - } view.RefreshScreen() - return true } func (ai *Ai) GetBestQueue() { - ai.addMovesToQueue(ai.getBestQueue()) -} - -func (ai *Ai) addMovesToQueue(queue []rune) { - insertIndex := ai.index - for _, char := range queue { - ai.queue[insertIndex] = char - insertIndex++ - if insertIndex == aiQueueSize { - insertIndex = 0 - } - } -} - -func (ai *Ai) getBestQueue() []rune { - bestQueue := make([]rune, 0, 0) bestScore := -9999999 - var slideScore int - bestSlide := 6 + bestQueue := make([]rune, 0, 0) + currentMino := *board.currentMino - for move1 := 0; move1 <= boardWidth; move1++ { - for rotate1 := 0; rotate1 < 5; rotate1++ { - for slide1 := 0; slide1 <= 5; slide1++ { + for slide1 := 0; slide1 < 5; slide1++ { + for move1 := board.width; move1 >= 0; move1-- { + for rotate1 := 0; rotate1 < 5; rotate1++ { - queue, mino1 := ai.getMovesforMino(rotate1, move1, slide1, nil) + queue, mino1 := board.getMovesforMino(rotate1, move1, slide1, ¤tMino, nil) if mino1 == nil { continue } - for move2 := 0; move2 <= boardWidth; move2++ { - for rotate2 := 0; rotate2 < 5; rotate2++ { - for slide2 := 0; slide2 <= 5; slide2++ { + for slide2 := 0; slide2 < 5; slide2++ { + for move2 := board.width; move2 >= 0; move2-- { + for rotate2 := 0; rotate2 < 5; rotate2++ { - _, mino2 := ai.getMovesforMino(rotate2, move2, slide2, mino1) + _, mino2 := board.getMovesforMino(rotate2, move2, slide2, board.previewMino, mino1) if mino2 == nil { continue } @@ -84,16 +60,9 @@ func (ai *Ai) getBestQueue() []rune { fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) score := ai.getScoreFromBoardStats(fullLines, holes, bumpy) - if slide1 < 3 { - slideScore = slide1 - } else { - slideScore = slide1 - 2 - } - - if score > bestScore || (score == bestScore && slideScore < bestSlide) { + if score > bestScore { bestScore = score bestQueue = queue - bestSlide = slideScore } } @@ -104,100 +73,95 @@ func (ai *Ai) getBestQueue() []rune { } } - return bestQueue + if len(bestQueue) < 1 { + bestQueue = append(bestQueue, 'x') + } + + ai.newQueue = &bestQueue } -func (ai *Ai) getMovesforMino(rotate int, move int, slide int, mino1 *Mino) ([]rune, *Mino) { +func (board *Board) getMovesforMino(rotate int, move int, slide int, mino1 *Mino, mino2 *Mino) ([]rune, *Mino) { queue := make([]rune, 0, 4) - var mino Mino - if mino1 != nil { - mino = *board.previewMino - } else { - mino = *board.currentMino - } - if rotate < 3 { + mino := *mino1 + + if rotate%2 == 0 { + rotate /= 2 for i := 0; i < rotate; i++ { mino.RotateRight() queue = append(queue, 'e') - if !mino.ValidLocation(false) || (mino1 != nil && mino1.minoOverlap(&mino)) { + if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) { return queue, nil } } } else { - for i := 0; i < rotate-2; i++ { + rotate = rotate/2 + 1 + for i := 0; i < rotate; i++ { mino.RotateLeft() queue = append(queue, 'q') - if !mino.ValidLocation(false) || (mino1 != nil && mino1.minoOverlap(&mino)) { + if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) { return queue, nil } } } - if move <= aiMoveLength { - move = aiMoveLength - move + + if move%2 == 0 { + move /= 2 for i := 0; i < move; i++ { mino.MoveLeft() queue = append(queue, 'a') - if !mino.ValidLocation(false) || (mino1 != nil && mino1.minoOverlap(&mino)) { + if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) { return queue, nil } } } else { - move = move - aiMoveLength + 1 + move = move/2 + 1 for i := 0; i < move; i++ { mino.MoveRight() queue = append(queue, 'd') - if !mino.ValidLocation(false) || (mino1 != nil && mino1.minoOverlap(&mino)) { + if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) { return queue, nil } } } - for mino.ValidLocation(false) && (mino1 == nil || !mino1.minoOverlap(&mino)) { + for mino.ValidLocation(false) && (mino2 == nil || !mino2.minoOverlap(&mino)) { mino.MoveDown() } mino.MoveUp() queue = append(queue, 'w') - if slide < 3 { + + if slide%2 == 0 { + slide /= 2 for i := 0; i < slide; i++ { mino.MoveLeft() queue = append(queue, 'a') - if !mino.ValidLocation(false) || (mino1 != nil && mino1.minoOverlap(&mino)) { + if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) { return queue, nil } } } else { - slide = slide - 2 + slide = slide/2 + 1 for i := 0; i < slide; i++ { mino.MoveRight() queue = append(queue, 'd') - if !mino.ValidLocation(false) || (mino1 != nil && mino1.minoOverlap(&mino)) { + if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) { return queue, nil } } } + + if !mino.ValidLocation(true) { + return queue, nil + } queue = append(queue, 'x') return queue, &mino } -func (mino *Mino) minoOverlap(mino1 *Mino) bool { - minoBlocks := mino.minoRotation[mino.rotation] - for i := 0; i < mino.length; i++ { - for j := 0; j < mino.length; j++ { - if minoBlocks[i][j] != blankColor { - if mino1.isMinoAtLocation(mino.x+i, mino.y+j) { - return true - } - } - } - } - return false -} - func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int, holes int, bumpy int) { // fullLines fullLinesY := make(map[int]bool, 2) - for j := 0; j < boardHeight; j++ { + for j := 0; j < board.height; j++ { isFullLine := true - for i := 0; i < boardWidth; i++ { + for i := 0; i < board.width; i++ { if board.colors[i][j] == blankColor && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) { isFullLine = false break @@ -211,10 +175,10 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int // holes and bumpy indexLast := 0 - for i := 0; i < boardWidth; i++ { - index := boardHeight + for i := 0; i < board.width; i++ { + index := board.height indexOffset := 0 - for j := 0; j < boardHeight; j++ { + for j := 0; j < board.height; j++ { if _, found := fullLinesY[j]; found { indexOffset++ } else { @@ -236,7 +200,7 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int indexLast = index + fullLines - indexOffset index++ - for j := index; j < boardHeight; j++ { + for j := index; j < board.height; j++ { if board.colors[i][j] == blankColor && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) { holes++ } @@ -245,24 +209,9 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int return } -func (mino *Mino) isMinoAtLocation(x int, y int) bool { - xIndex := x - mino.x - yIndex := y - mino.y - if xIndex < 0 || xIndex >= mino.length || yIndex < 0 || yIndex >= mino.length { - return false - } - - minoBlocks := mino.minoRotation[mino.rotation] - if minoBlocks[xIndex][yIndex] != blankColor { - return true - } - - return false -} - func (ai *Ai) getScoreFromBoardStats(fullLines int, holes int, bumpy int) (score int) { if fullLines == 4 { - score += 256 + score += 512 } score -= 75 * holes score -= 25 * bumpy diff --git a/ai_test.go b/ai_test.go index 054d91c..a41e986 100644 --- a/ai_test.go +++ b/ai_test.go @@ -1,494 +1,291 @@ package main import ( - "gopkg.in/inconshreveable/log15.v2" - "os" "testing" ) -func TestMain(m *testing.M) { - setupForTesting() - retCode := m.Run() - os.Exit(retCode) +type testAiStruct struct { + info string + minos []testMinoStruct + fullLines int + holes int + bumpy int } -func setupForTesting() { - logger = log15.New() - logger.SetHandler(log15.StreamHandler(os.Stdout, log15.LogfmtFormat())) +func TestAI(t *testing.T) { + // this must be set to the blank 10x20 board + board.boardsIndex = 0 + board.Clear() - engine = NewEngine() + tests := []testAiStruct{ + {info: "fullLines 2x minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + }, fullLines: 0, holes: 0, bumpy: 1}, + {info: "fullLines 2x2 minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 17}, // minoI + }, fullLines: 0, holes: 0, bumpy: 2}, + {info: "fullLines 2x minoI minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + }, fullLines: 1, holes: 0, bumpy: 1}, + {info: "fullLines 2x2 minoI minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + }, fullLines: 2, holes: 0, bumpy: 0}, + {info: "fullLines 5x minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 2, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 4, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 6, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + }, fullLines: 2, holes: 0, bumpy: 0}, + {info: "fullLines 4x4 minoI 2x minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 16}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 16}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 15}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 15}, // minoI + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 16}, // minoO + }, fullLines: 4, holes: 0, bumpy: 0}, + {info: "holes 2x minoI minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 6, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[3], x: 4, y: 17}, // minoO + }, fullLines: 0, holes: 2, bumpy: 4}, + {info: "holes 6x minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 4, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 2, y: 16}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 6, y: 16}, // minoO + }, fullLines: 0, holes: 8, bumpy: 8}, + {info: "holes 4x minoT 2x minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[5], x: 0, y: 18}, // minoT + testMinoStruct{minoRotation: minos.minoBag[5], x: 7, y: 18}, // minoT + testMinoStruct{minoRotation: minos.minoBag[5], x: 3, y: 16}, // minoT + testMinoStruct{minoRotation: minos.minoBag[5], x: 7, y: 16}, // minoT + testMinoStruct{minoRotation: minos.minoBag[0], x: 2, y: 14}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 6, y: 14}, // minoI + }, fullLines: 0, holes: 19, bumpy: 4}, + {info: "holes 3x minoZ", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[6], x: 0, y: 18}, // minoZ + testMinoStruct{minoRotation: minos.minoBag[6], x: 3, y: 18}, // minoZ + testMinoStruct{minoRotation: minos.minoBag[6], x: 6, y: 18}, // minoZ + }, fullLines: 0, holes: 3, bumpy: 6}, + {info: "bumpy 2x minoT - 1", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[5], x: 0, y: 18}, // minoT + testMinoStruct{minoRotation: minos.minoBag[5], x: 5, y: 18}, // minoT + }, fullLines: 0, holes: 0, bumpy: 7}, + {info: "bumpy 2x minoT - 2", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[5], x: 1, y: 18}, // minoT + testMinoStruct{minoRotation: minos.minoBag[5], x: 6, y: 18}, // minoT + }, fullLines: 0, holes: 0, bumpy: 8}, + {info: "bumpy 2x minoT - 3", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[5], x: 2, y: 18}, // minoT + testMinoStruct{minoRotation: minos.minoBag[5], x: 7, y: 18}, // minoT + }, fullLines: 0, holes: 0, bumpy: 7}, + {info: "bumpy 2x minoJ - 1", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[1], x: 0, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 5, y: 18}, // minoJ + }, fullLines: 0, holes: 0, bumpy: 6}, + {info: "bumpy 2x minoJ - 2", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[1], x: 1, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 6, y: 18}, // minoJ + }, fullLines: 0, holes: 0, bumpy: 8}, + {info: "bumpy 2x minoJ - 2", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[1], x: 2, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 7, y: 18}, // minoJ + }, fullLines: 0, holes: 0, bumpy: 7}, + {info: "bumpy 2x minoL - 1", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[2], x: 0, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 5, y: 18}, // minoL + }, fullLines: 0, holes: 0, bumpy: 7}, + {info: "bumpy 2x minoL - 2", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[2], x: 1, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 6, y: 18}, // minoL + }, fullLines: 0, holes: 0, bumpy: 8}, + {info: "bumpy 2x minoL - 3", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[2], x: 2, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 7, y: 18}, // minoL + }, fullLines: 0, holes: 0, bumpy: 6}, + } + + runAiTests(t, tests) } -func TestBoardStatsFullLines1(t *testing.T) { - board = NewBoard() +func TestBigBoardAI(t *testing.T) { + // this must be set to the blank 20x20 board + board.boardsIndex = 3 + board.Clear() - // minoO - mino1 := &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 18 - mino1.SetOnBoard() - - // minoI - mino1 = &Mino{ - minoRotation: minoBag[0], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 2 - mino1.y = 18 - - // minoI - mino2 := &Mino{ - minoRotation: minoBag[0], - } - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 6 - mino2.y = 18 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 1 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 0 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 1 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) + tests := []testAiStruct{ + {info: "fullLines 4x minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 8, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 12, y: 18}, // minoI + }, fullLines: 0, holes: 0, bumpy: 1}, + {info: "fullLines 5x minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 8, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 12, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 16, y: 18}, // minoI + }, fullLines: 1, holes: 0, bumpy: 0}, + {info: "fullLines 5x2 minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 8, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 12, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 16, y: 18}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 0, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 4, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 8, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 12, y: 17}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 16, y: 17}, // minoI + }, fullLines: 2, holes: 0, bumpy: 0}, + {info: "fullLines 9x minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 2, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 4, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 6, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 10, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 12, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 14, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 16, y: 18}, // minoO + }, fullLines: 0, holes: 0, bumpy: 2}, + {info: "fullLines 10x minoO", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 2, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 4, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 6, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 10, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 12, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 14, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 16, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 18, y: 18}, // minoO + }, fullLines: 2, holes: 0, bumpy: 0}, + {info: "holes 3x minoO 3x minoI", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 6, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[3], x: 12, y: 18}, // minoO + testMinoStruct{minoRotation: minos.minoBag[0], x: 2, y: 16}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 8, y: 16}, // minoI + testMinoStruct{minoRotation: minos.minoBag[0], x: 14, y: 16}, // minoI + }, fullLines: 0, holes: 24, bumpy: 8}, + {info: "holes 5x minoZ", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[6], x: 0, y: 18}, // minoZ + testMinoStruct{minoRotation: minos.minoBag[6], x: 4, y: 18}, // minoZ + testMinoStruct{minoRotation: minos.minoBag[6], x: 8, y: 18}, // minoZ + testMinoStruct{minoRotation: minos.minoBag[6], x: 12, y: 18}, // minoZ + testMinoStruct{minoRotation: minos.minoBag[6], x: 16, y: 18}, // minoZ + }, fullLines: 0, holes: 5, bumpy: 18}, + {info: "bumpy 4x minoJ - 1", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[1], x: 0, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 5, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 10, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 15, y: 18}, // minoJ + }, fullLines: 0, holes: 0, bumpy: 14}, + {info: "bumpy 4x minoJ - 2", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[1], x: 1, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 6, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 11, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 16, y: 18}, // minoJ + }, fullLines: 0, holes: 0, bumpy: 16}, + {info: "bumpy 4x minoJ - 3", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[1], x: 2, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 7, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 12, y: 18}, // minoJ + testMinoStruct{minoRotation: minos.minoBag[1], x: 17, y: 18}, // minoJ + }, fullLines: 0, holes: 0, bumpy: 15}, + {info: "bumpy 4x minoL - 1", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[2], x: 0, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 5, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 10, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 15, y: 18}, // minoL + }, fullLines: 0, holes: 0, bumpy: 15}, + {info: "bumpy 4x minoL - 2", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[2], x: 1, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 6, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 11, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 16, y: 18}, // minoL + }, fullLines: 0, holes: 0, bumpy: 16}, + {info: "bumpy 4x minoL - 3", minos: []testMinoStruct{ + testMinoStruct{minoRotation: minos.minoBag[2], x: 2, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 7, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 12, y: 18}, // minoL + testMinoStruct{minoRotation: minos.minoBag[2], x: 17, y: 18}, // minoL + }, fullLines: 0, holes: 0, bumpy: 14}, } - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() + runAiTests(t, tests) } -func TestBoardStatsFullLines2(t *testing.T) { - board = NewBoard() +func runAiTests(t *testing.T, tests []testAiStruct) { + var mino1 *Mino + var mino2 *Mino - // minoO - mino1 := &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 18 - mino1.SetOnBoard() + for _, test := range tests { + board.Clear() - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 2 - mino1.y = 18 - mino1.SetOnBoard() + for i, minoTest := range test.minos { + mino := NewMino() + mino.minoRotation = minoTest.minoRotation + mino.length = len(mino.minoRotation[0]) + mino.x = minoTest.x + mino.y = minoTest.y + if i < len(test.minos)-2 { + mino.SetOnBoard() + } else if i == len(test.minos)-2 { + mino1 = mino + } else { + mino2 = mino + } + } - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 4 - mino1.y = 18 - mino1.SetOnBoard() + fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 6 - mino1.y = 18 - mino1.SetOnBoard() + if fullLines != test.fullLines { + mino1.SetOnBoard() + lines := board.getDebugBoardWithMino(mino2) + for i := 0; i < len(lines); i++ { + t.Log(lines[i]) + } + t.Errorf("AI fullLines - received: %v - expected: %v - info %v", fullLines, test.fullLines, test.info) + continue + } + if holes != test.holes { + mino1.SetOnBoard() + lines := board.getDebugBoardWithMino(mino2) + for i := 0; i < len(lines); i++ { + t.Log(lines[i]) + } + t.Errorf("AI holes - received: %v - expected: %v - info %v", holes, test.holes, test.info) + continue + } + if bumpy != test.bumpy { + mino1.SetOnBoard() + lines := board.getDebugBoardWithMino(mino2) + for i := 0; i < len(lines); i++ { + t.Log(lines[i]) + } + t.Errorf("AI bumpy - received: %v - expected: %v - info %v", bumpy, test.bumpy, test.info) + continue + } - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 8 - mino1.y = 18 - mino1.SetOnBoard() - - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 16 - mino1.SetOnBoard() - - // minoI - mino1 = &Mino{ - minoRotation: minoBag[0], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 2 - mino1.y = 16 - - // minoI - mino2 := &Mino{ - minoRotation: minoBag[0], - } - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 6 - mino2.y = 16 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 3 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 0 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 1 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsFullLines3(t *testing.T) { - board = NewBoard() - - // minoO - mino1 := &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 18 - mino1.SetOnBoard() - - // minoI - mino1 = &Mino{ - minoRotation: minoBag[0], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 16 - mino1.SetOnBoard() - - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 4 - mino1.y = 18 - mino1.SetOnBoard() - - // minoI - mino1 = &Mino{ - minoRotation: minoBag[0], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 4 - mino1.y = 16 - mino1.SetOnBoard() - - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 8 - mino1.y = 18 - - // minoO - mino2 := &Mino{ - minoRotation: minoBag[3], - } - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 8 - mino2.y = 16 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 1 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 0 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 9 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsBumpy1(t *testing.T) { - board = NewBoard() - - // minoO - mino1 := &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 18 - - // minoO - mino2 := &Mino{ - minoRotation: minoBag[3], - } - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 0 - mino2.y = 16 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 0 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 0 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 4 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsBumpy2(t *testing.T) { - board = NewBoard() - - // minoO - mino1 := &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 18 - mino1.SetOnBoard() - - // minoI - mino1 = &Mino{ - minoRotation: minoBag[0], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 16 - - // minoI - mino2 := &Mino{ - minoRotation: minoBag[0], - } - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 0 - mino2.y = 15 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 0 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 4 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 4 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsBumpy3(t *testing.T) { - board = NewBoard() - - // minoO - mino1 := &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 0 - mino1.y = 18 - mino1.SetOnBoard() - - // minoO - mino1 = &Mino{ - minoRotation: minoBag[3], - } - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 1 - mino1.y = 16 - - // minoO - mino2 := &Mino{ - minoRotation: minoBag[3], - } - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 2 - mino2.y = 14 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 0 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 6 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 10 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsBumpy4(t *testing.T) { - board = NewBoard() - - // minoI - mino1 := &Mino{ - minoRotation: minoBag[0], - } - mino1.rotation = 1 - mino1.length = len(mino1.minoRotation[0]) - mino1.x = 6 - mino1.y = 16 - - // minoI - mino2 := &Mino{ - minoRotation: minoBag[0], - } - mino2.rotation = 1 - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 6 - mino2.y = 12 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 0 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 0 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 16 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsholes1(t *testing.T) { - board = NewBoard() - - // minoJ - mino1 := &Mino{ - minoRotation: minoBag[1], - } - mino1.rotation = 1 - mino1.length = len(mino1.minoRotation[0]) - mino1.x = -1 - mino1.y = 17 - - // minoJ - mino2 := &Mino{ - minoRotation: minoBag[1], - } - mino2.rotation = 1 - mino2.length = len(mino2.minoRotation[0]) - mino2.x = 1 - mino2.y = 17 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 0 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 4 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 3 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() -} - -func TestBoardStatsholes2(t *testing.T) { - board = NewBoard() - - // minoJ - mino1 := &Mino{ - minoRotation: minoBag[1], - } - mino1.rotation = 1 - mino1.length = len(mino1.minoRotation[0]) - mino1.x = -1 - mino1.y = 17 - - // minoJ - mino2 := &Mino{ - minoRotation: minoBag[1], - } - mino2.rotation = 1 - mino2.length = len(mino2.minoRotation[0]) - mino2.x = -1 - mino2.y = 14 - - fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2) - expected := 0 - if fullLines != expected { - t.Error("fullLines expected", expected, "got", fullLines) - } - expected = 4 - if holes != expected { - t.Error("holes expected", expected, "got", holes) - } - expected = 6 - if bumpy != expected { - t.Error("bumpy expected", expected, "got", bumpy) - } - - // for debuging - // mino1.SetOnBoard() - // mino2.SetOnBoard() - // board.drawDebugBoard() } diff --git a/board.go b/board.go index cea9bb5..e1e1637 100644 --- a/board.go +++ b/board.go @@ -2,33 +2,49 @@ package main import ( "fmt" - "github.com/nsf/termbox-go" "time" + + "github.com/nsf/termbox-go" ) -type Board struct { - colors [boardWidth][boardHeight]termbox.Attribute - rotation [boardWidth][boardHeight]int - previewMino *Mino - currentMino *Mino - dropDistance int +func NewBoard() { + board = &Board{} + board.Clear() } -func NewBoard() *Board { - board := &Board{} - for i := 0; i < boardWidth; i++ { - for j := 0; j < boardHeight; j++ { - board.colors[i][j] = blankColor - } +func (board *Board) Clear() { + board.width = len(boards[board.boardsIndex].colors) + board.height = len(boards[board.boardsIndex].colors[0]) + board.colors = make([][]termbox.Attribute, len(boards[board.boardsIndex].colors)) + for i := 0; i < len(boards[board.boardsIndex].colors); i++ { + board.colors[i] = make([]termbox.Attribute, len(boards[board.boardsIndex].colors[i])) + copy(board.colors[i], boards[board.boardsIndex].colors[i]) } - for i := 0; i < boardWidth; i++ { - for j := 0; j < boardHeight; j++ { - board.rotation[i][j] = 0 - } + board.rotation = make([][]int, len(boards[board.boardsIndex].rotation)) + for i := 0; i < len(boards[board.boardsIndex].rotation); i++ { + board.rotation[i] = make([]int, len(boards[board.boardsIndex].rotation[i])) + copy(board.rotation[i], boards[board.boardsIndex].rotation[i]) } board.previewMino = NewMino() board.currentMino = NewMino() - return board +} + +func (board *Board) PreviousBoard() { + board.boardsIndex-- + if board.boardsIndex < 0 { + board.boardsIndex = len(boards) - 1 + } + engine.PreviewBoard() + board.Clear() +} + +func (board *Board) NextBoard() { + board.boardsIndex++ + if board.boardsIndex == len(boards) { + board.boardsIndex = 0 + } + engine.PreviewBoard() + board.Clear() } func (board *Board) MinoMoveLeft() { @@ -160,7 +176,7 @@ func (board *Board) nextMino() { board.currentMino = board.previewMino board.previewMino = NewMino() - engine.ResetAiTimer() + engine.AiGetBestQueue() engine.ResetTimer(0) } @@ -180,7 +196,7 @@ func (board *Board) deleteCheck() { func (board *Board) fullLines() []int { fullLines := make([]int, 0, 1) - for j := 0; j < boardHeight; j++ { + for j := 0; j < board.height; j++ { if board.isFullLine(j) { fullLines = append(fullLines, j) } @@ -189,7 +205,7 @@ func (board *Board) fullLines() []int { } func (board *Board) isFullLine(j int) bool { - for i := 0; i < boardWidth; i++ { + for i := 0; i < board.width; i++ { if board.colors[i][j] == blankColor { return false } @@ -198,16 +214,16 @@ func (board *Board) isFullLine(j int) bool { } func (board *Board) deleteLine(line int) { - for i := 0; i < boardWidth; i++ { + for i := 0; i < board.width; i++ { board.colors[i][line] = blankColor } for j := line; j > 0; j-- { - for i := 0; i < boardWidth; i++ { + for i := 0; i < board.width; i++ { board.colors[i][j] = board.colors[i][j-1] board.rotation[i][j] = board.rotation[i][j-1] } } - for i := 0; i < boardWidth; i++ { + for i := 0; i < board.width; i++ { board.colors[i][0] = blankColor } } @@ -218,7 +234,7 @@ func (board *Board) SetColor(x int, y int, color termbox.Attribute, rotation int } func ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool { - if x < 0 || x >= boardWidth || y >= boardHeight { + if x < 0 || x >= board.width || y >= board.height { return false } if mustBeOnBoard { @@ -239,12 +255,12 @@ func ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool { } func ValidDisplayLocation(x int, y int) bool { - return x >= 0 && x < boardWidth && y >= 0 && y < boardHeight + return x >= 0 && x < board.width && y >= 0 && y < board.height } func (board *Board) DrawBoard() { - for i := 0; i < boardWidth; i++ { - for j := 0; j < boardHeight; j++ { + for i := 0; i < board.width; i++ { + for j := 0; j < board.height; j++ { if board.colors[i][j] != blankColor { view.DrawBlock(i, j, board.colors[i][j], board.rotation[i][j]) } @@ -273,9 +289,9 @@ func (board *Board) DrawDropMino() { } // for debuging -func (board *Board) drawDebugBoard() { - for j := 0; j < boardHeight; j++ { - for i := 0; i < boardWidth; i++ { +func (board *Board) printDebugBoard() { + for j := 0; j < board.height; j++ { + for i := 0; i < board.width; i++ { switch board.colors[i][j] { case blankColor: fmt.Print(".") @@ -293,8 +309,89 @@ func (board *Board) drawDebugBoard() { fmt.Print("W") case termbox.ColorYellow: fmt.Print("Y") + default: + fmt.Print("U") } } fmt.Println("") } } + +// for debuging +func (board *Board) getDebugBoard() []string { + lines := make([]string, board.height) + for j := 0; j < board.height; j++ { + for i := 0; i < board.width; i++ { + switch board.colors[i][j] { + case blankColor: + lines[j] += "." + case termbox.ColorBlue: + lines[j] += "B" + case termbox.ColorCyan: + lines[j] += "C" + case termbox.ColorGreen: + lines[j] += "G" + case termbox.ColorMagenta: + lines[j] += "M" + case termbox.ColorRed: + lines[j] += "R" + case termbox.ColorWhite: + lines[j] += "W" + case termbox.ColorYellow: + lines[j] += "Y" + default: + lines[j] += "U" + } + } + } + return lines +} + +// for debuging +func (board *Board) getDebugBoardWithMino(mino *Mino) []string { + lines := make([]string, board.height) + for j := 0; j < board.height; j++ { + for i := 0; i < board.width; i++ { + switch mino.getMinoColorAtLocation(i, j) { + case blankColor: + switch board.colors[i][j] { + case blankColor: + lines[j] += "." + case termbox.ColorBlue: + lines[j] += "B" + case termbox.ColorCyan: + lines[j] += "C" + case termbox.ColorGreen: + lines[j] += "G" + case termbox.ColorMagenta: + lines[j] += "M" + case termbox.ColorRed: + lines[j] += "R" + case termbox.ColorWhite: + lines[j] += "W" + case termbox.ColorYellow: + lines[j] += "Y" + default: + lines[j] += "U" + } + case termbox.ColorBlue: + lines[j] += "b" + case termbox.ColorCyan: + lines[j] += "c" + case termbox.ColorGreen: + lines[j] += "g" + case termbox.ColorMagenta: + lines[j] += "m" + case termbox.ColorRed: + lines[j] += "r" + case termbox.ColorWhite: + lines[j] += "w" + case termbox.ColorYellow: + lines[j] += "y" + default: + lines[j] += "u" + } + } + } + return lines +} diff --git a/boards.go b/boards.go new file mode 100644 index 0000000..a467a5f --- /dev/null +++ b/boards.go @@ -0,0 +1,1086 @@ +package main + +import ( + "github.com/nsf/termbox-go" +) + +func init() { + boards = []Boards{ + + // 10 x 20 blank + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 10 x 20 checkerboard double + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + }}, + + // 10 x 20 checkerboard single + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 20 x 20 blank + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 20 x 20 heart + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorWhite, + termbox.ColorWhite, termbox.ColorWhite, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + termbox.ColorMagenta, termbox.ColorWhite, termbox.ColorYellow, termbox.ColorYellow, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, termbox.ColorMagenta, + termbox.ColorMagenta, termbox.ColorMagenta, termbox.ColorYellow, termbox.ColorYellow, termbox.ColorBlue, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorWhite, termbox.ColorWhite, termbox.ColorWhite, + termbox.ColorCyan, termbox.ColorCyan, termbox.ColorCyan, termbox.ColorCyan, termbox.ColorBlue, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorGreen, termbox.ColorGreen, termbox.ColorWhite, + termbox.ColorWhite, termbox.ColorWhite, termbox.ColorRed, termbox.ColorRed, termbox.ColorBlue, termbox.ColorBlue, blankColor, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorGreen, termbox.ColorGreen, + termbox.ColorWhite, termbox.ColorRed, termbox.ColorRed, termbox.ColorCyan, termbox.ColorCyan, termbox.ColorCyan, termbox.ColorCyan, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorBlue, termbox.ColorBlue, + termbox.ColorWhite, termbox.ColorGreen, termbox.ColorGreen, termbox.ColorMagenta, termbox.ColorMagenta, termbox.ColorMagenta, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorGreen, termbox.ColorBlue, + termbox.ColorYellow, termbox.ColorYellow, termbox.ColorGreen, termbox.ColorGreen, termbox.ColorMagenta, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorGreen, termbox.ColorGreen, termbox.ColorBlue, + termbox.ColorYellow, termbox.ColorYellow, termbox.ColorYellow, termbox.ColorYellow, termbox.ColorWhite, termbox.ColorWhite, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorGreen, termbox.ColorRed, termbox.ColorRed, + termbox.ColorGreen, termbox.ColorGreen, termbox.ColorYellow, termbox.ColorYellow, termbox.ColorWhite, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, termbox.ColorMagenta, + termbox.ColorBlue, termbox.ColorGreen, termbox.ColorGreen, termbox.ColorBlue, termbox.ColorWhite, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorMagenta, termbox.ColorMagenta, + termbox.ColorBlue, termbox.ColorBlue, termbox.ColorBlue, termbox.ColorBlue, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorMagenta, + termbox.ColorBlue, termbox.ColorBlue, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 2, + 2, 2, 0, 0, 2, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 0, 0, 0, 0, 0, 2, 2, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 2, 2, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 2, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 2, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 2, 2, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 2, 2, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 20 x 20 checkerboard double + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 20 x 20 checkerboard single + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 30 x 30 blank + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, + blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + + // 30 x 30 checkerboard double + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, + blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, + termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed, blankColor, blankColor, termbox.ColorRed, termbox.ColorRed}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 2, 2, + 0, 0, 2, 2, 0, 0, 2, 2, 0, 0, + 2, 2, 0, 0, 2, 2, 0, 0, 2, 2}, + }}, + + // 30 x 30 checkerboard single + Boards{ + colors: [][]termbox.Attribute{ + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, + blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed}, + []termbox.Attribute{blankColor, blankColor, blankColor, blankColor, blankColor, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, + termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor, termbox.ColorRed, blankColor}, + }, + rotation: [][]int{ + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + []int{0, 0, 0, 0, 0, 0, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2, + 0, 2, 0, 2, 0, 2, 0, 2, 0, 2}, + []int{0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, + 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, + }}, + } +} diff --git a/boards_test.go b/boards_test.go new file mode 100644 index 0000000..937a097 --- /dev/null +++ b/boards_test.go @@ -0,0 +1,30 @@ +package main + +import ( + "testing" +) + +func TestBoards(t *testing.T) { + for i := 0; i < len(boards); i++ { + b := boards[i] + width := len(b.colors) + height := len(b.colors[0]) + + for j := 1; j < width; j++ { + if len(b.colors[j]) != height { + t.Fatalf("board height - received: %v - expected: %v - index %v", len(b.colors[j]), height, i) + } + } + + if len(b.rotation) != width { + t.Fatalf("rotation width - received: %v - expected: %v - index %v", len(b.rotation), width, i) + } + + for j := 0; j < width; j++ { + if len(b.rotation[j]) != height { + t.Fatalf("rotation height - received: %v - expected: %v - index %v", len(b.rotation[j]), height, i) + } + } + + } +} diff --git a/engine.go b/engine.go index 0a3711f..e344feb 100644 --- a/engine.go +++ b/engine.go @@ -1,29 +1,13 @@ package main import ( - "github.com/nsf/termbox-go" "time" + + "github.com/nsf/termbox-go" ) -type Engine struct { - stopped bool - chanStop chan struct{} - keyInput *KeyInput - ranking *Ranking - timer *time.Timer - tickTime time.Duration - paused bool - gameOver bool - score int - level int - deleteLines int - ai *Ai - aiEnabled bool - aiTimer *time.Timer -} - -func NewEngine() *Engine { - return &Engine{ +func NewEngine() { + engine = &Engine{ chanStop: make(chan struct{}, 1), gameOver: true, tickTime: time.Hour, @@ -42,7 +26,7 @@ func (engine *Engine) Run() { engine.aiTimer.Stop() engine.ranking = NewRanking() - board = NewBoard() + board.Clear() view.RefreshScreen() engine.keyInput = NewKeyInput() @@ -61,9 +45,8 @@ loop: case <-engine.timer.C: engine.tick() case <-engine.aiTimer.C: - if engine.ai.ProcessQueue() { - engine.aiTimer.Reset(engine.tickTime / 4) - } + engine.ai.ProcessQueue() + engine.aiTimer.Reset(engine.tickTime / 6) case <-engine.chanStop: break loop } @@ -105,15 +88,19 @@ func (engine *Engine) Pause() { func (engine *Engine) UnPause() { engine.timer.Reset(engine.tickTime) if engine.aiEnabled { - engine.aiTimer.Reset(engine.tickTime / 4) + engine.aiTimer.Reset(engine.tickTime / 6) } engine.paused = false } +func (engine *Engine) PreviewBoard() { + engine.previewBoard = true +} + func (engine *Engine) NewGame() { logger.Info("Engine NewGame start") - board = NewBoard() + board.Clear() engine.tickTime = 480 * time.Millisecond engine.score = 0 engine.level = 1 @@ -128,6 +115,7 @@ loop: } } + engine.previewBoard = false engine.gameOver = false if engine.aiEnabled { engine.ai.GetBestQueue() @@ -153,12 +141,11 @@ func (engine *Engine) ResetTimer(duration time.Duration) { } } -func (engine *Engine) ResetAiTimer() { +func (engine *Engine) AiGetBestQueue() { if !engine.aiEnabled { return } - engine.ai.GetBestQueue() - engine.aiTimer.Reset(engine.tickTime / 4) + go engine.ai.GetBestQueue() } func (engine *Engine) tick() { @@ -190,8 +177,8 @@ func (engine *Engine) AddDeleteLines(lines int) { func (engine *Engine) AddScore(add int) { engine.score += add - if engine.score > 999999 { - engine.score = 999999 + if engine.score > 9999999 { + engine.score = 9999999 } } @@ -222,13 +209,9 @@ func (engine *Engine) GameOver() { logger.Info("Engine GameOver start") engine.Pause() - - view.ShowGameOverAnimation() - engine.gameOver = true - engine.ranking.InsertScore(uint64(engine.score)) - engine.ranking.Save() + view.ShowGameOverAnimation() loop: for { @@ -239,21 +222,24 @@ loop: } } + engine.ranking.InsertScore(uint64(engine.score)) + engine.ranking.Save() + logger.Info("Engine GameOver end") } func (engine *Engine) EnabledAi() { engine.aiEnabled = true - engine.ai.GetBestQueue() - engine.aiTimer.Reset(engine.tickTime / 4) + go engine.ai.GetBestQueue() + engine.aiTimer.Reset(engine.tickTime / 6) } func (engine *Engine) DisableAi() { + engine.aiEnabled = false if !engine.aiTimer.Stop() { select { case <-engine.aiTimer.C: default: } } - engine.aiEnabled = false } diff --git a/globals.go b/globals.go new file mode 100644 index 0000000..74e15c9 --- /dev/null +++ b/globals.go @@ -0,0 +1,103 @@ +package main + +import ( + "time" + + "github.com/nsf/termbox-go" + "gopkg.in/inconshreveable/log15.v2" +) + +const ( + blankColor = termbox.ColorBlack + boardXOffset = 4 + boardYOffset = 2 + rankingFileName = "/tetris.db" + + MinoPreview MinoType = iota + MinoCurrent = iota + MinoDrop = iota +) + +type ( + MinoType int + MinoBlocks [][]termbox.Attribute + MinoRotation [4]MinoBlocks + + Mino struct { + x int + y int + length int + rotation int + minoRotation MinoRotation + } + + Minos struct { + minoBag [7]MinoRotation + bagRand []int + bagIndex int + } + + Board struct { + boardsIndex int + width int + height int + colors [][]termbox.Attribute + rotation [][]int + previewMino *Mino + currentMino *Mino + dropDistance int + } + + Boards struct { + colors [][]termbox.Attribute + rotation [][]int + } + + KeyInput struct { + stopped bool + chanStop chan struct{} + chanKeyInput chan *termbox.Event + } + + View struct { + } + + Ai struct { + queue *[]rune + newQueue *[]rune + index int + } + + Ranking struct { + scores []uint64 + } + + Engine struct { + stopped bool + chanStop chan struct{} + keyInput *KeyInput + ranking *Ranking + timer *time.Timer + tickTime time.Duration + paused bool + gameOver bool + previewBoard bool + score int + level int + deleteLines int + ai *Ai + aiEnabled bool + aiTimer *time.Timer + } +) + +var ( + boards []Boards + + baseDir string + logger log15.Logger + minos *Minos + board *Board + view *View + engine *Engine +) diff --git a/keyInput.go b/keyInput.go index 7a09dc4..ecf1131 100644 --- a/keyInput.go +++ b/keyInput.go @@ -1,15 +1,10 @@ package main import ( - "github.com/nsf/termbox-go" "runtime" -) -type KeyInput struct { - stopped bool - chanStop chan struct{} - chanKeyInput chan *termbox.Event -} + "github.com/nsf/termbox-go" +) func NewKeyInput() *KeyInput { return &KeyInput{ @@ -29,16 +24,11 @@ loop: default: } event := termbox.PollEvent() - if event.Type == termbox.EventKey { + if event.Type == termbox.EventKey && len(keyInput.chanKeyInput) < 8 { select { case <-keyInput.chanStop: break loop - default: - select { - case keyInput.chanKeyInput <- &event: - case <-keyInput.chanStop: - break loop - } + case keyInput.chanKeyInput <- &event: } } } @@ -47,7 +37,6 @@ loop: } func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) { - if event.Key == termbox.KeyCtrlI { // ctrl i to log stack trace buffer := make([]byte, 1<<16) @@ -66,8 +55,15 @@ func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) { } if engine.gameOver { - if event.Key == termbox.KeySpace { - engine.NewGame() + if event.Ch == 0 { + switch event.Key { + case termbox.KeySpace: + engine.NewGame() + case termbox.KeyArrowLeft: + board.PreviousBoard() + case termbox.KeyArrowRight: + board.NextBoard() + } } return } diff --git a/mino.go b/mino.go index e6cd68c..5b63df3 100644 --- a/mino.go +++ b/mino.go @@ -2,47 +2,22 @@ package main import ( "math/rand" - "time" + + "github.com/nsf/termbox-go" ) -type MinoType int - -const ( - MinoPreview MinoType = iota - MinoCurrent = iota - MinoDrop = iota -) - -var ( - bagRand []int - bagIndex int -) - -func init() { - rand.Seed(time.Now().UnixNano()) - bagRand = rand.Perm(7) -} - -type Mino struct { - x int - y int - length int - rotation int - minoRotation MinoRotation -} - func NewMino() *Mino { - minoRotation := minoBag[bagRand[bagIndex]] - bagIndex++ - if bagIndex > 6 { - bagIndex = 0 - bagRand = rand.Perm(7) + minoRotation := minos.minoBag[minos.bagRand[minos.bagIndex]] + minos.bagIndex++ + if minos.bagIndex > 6 { + minos.bagIndex = 0 + minos.bagRand = rand.Perm(7) } mino := &Mino{ minoRotation: minoRotation, length: len(minoRotation[0]), } - mino.x = boardWidth/2 - (mino.length+1)/2 + mino.x = board.width/2 - (mino.length+1)/2 mino.y = -1 return mino } @@ -152,3 +127,43 @@ func (mino *Mino) DrawMino(minoType MinoType) { } } } + +func (mino *Mino) minoOverlap(mino1 *Mino) bool { + minoBlocks := mino.minoRotation[mino.rotation] + for i := 0; i < mino.length; i++ { + for j := 0; j < mino.length; j++ { + if minoBlocks[i][j] != blankColor { + if mino1.isMinoAtLocation(mino.x+i, mino.y+j) { + return true + } + } + } + } + return false +} + +func (mino *Mino) isMinoAtLocation(x int, y int) bool { + xIndex := x - mino.x + yIndex := y - mino.y + if xIndex < 0 || xIndex >= mino.length || yIndex < 0 || yIndex >= mino.length { + return false + } + + minoBlocks := mino.minoRotation[mino.rotation] + if minoBlocks[xIndex][yIndex] != blankColor { + return true + } + + return false +} + +func (mino *Mino) getMinoColorAtLocation(x int, y int) termbox.Attribute { + xIndex := x - mino.x + yIndex := y - mino.y + if xIndex < 0 || xIndex >= mino.length || yIndex < 0 || yIndex >= mino.length { + return blankColor + } + + minoBlocks := mino.minoRotation[mino.rotation] + return minoBlocks[xIndex][yIndex] +} diff --git a/mino_test.go b/mino_test.go new file mode 100644 index 0000000..71d6650 --- /dev/null +++ b/mino_test.go @@ -0,0 +1,120 @@ +package main + +import ( + "math/rand" + "os" + "testing" + + "gopkg.in/inconshreveable/log15.v2" +) + +type testMinoStruct struct { + minoRotation MinoRotation + x int + y int +} + +func TestMain(m *testing.M) { + setupForTesting() + retCode := m.Run() + os.Exit(retCode) +} + +func setupForTesting() { + logger = log15.New() + logger.SetHandler(log15.StreamHandler(os.Stdout, log15.LogfmtFormat())) + + rand.Seed(1) + + NewMinos() + NewBoard() + NewEngine() +} + +func TestMinoValidLocation(t *testing.T) { + // this must be set to the blank boards + for _, i := range []int{0, 3} { + board.boardsIndex = i + board.Clear() + + tests := []struct { + info string + mino testMinoStruct + changeLocation bool + mustBeOnBoard bool + validLocation bool + }{ + {info: "start 0 false", mino: testMinoStruct{minoRotation: minos.minoBag[0]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 0 true", mino: testMinoStruct{minoRotation: minos.minoBag[0]}, mustBeOnBoard: true, validLocation: true}, + {info: "start 1 false", mino: testMinoStruct{minoRotation: minos.minoBag[1]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 1 true", mino: testMinoStruct{minoRotation: minos.minoBag[1]}, mustBeOnBoard: true, validLocation: false}, + {info: "start 2 false", mino: testMinoStruct{minoRotation: minos.minoBag[2]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 2 true", mino: testMinoStruct{minoRotation: minos.minoBag[2]}, mustBeOnBoard: true, validLocation: false}, + {info: "start 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3]}, mustBeOnBoard: true, validLocation: false}, + {info: "start 4 false", mino: testMinoStruct{minoRotation: minos.minoBag[4]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 4 true", mino: testMinoStruct{minoRotation: minos.minoBag[4]}, mustBeOnBoard: true, validLocation: false}, + {info: "start 5 false", mino: testMinoStruct{minoRotation: minos.minoBag[5]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 5 true", mino: testMinoStruct{minoRotation: minos.minoBag[5]}, mustBeOnBoard: true, validLocation: false}, + {info: "start 6 false", mino: testMinoStruct{minoRotation: minos.minoBag[6]}, mustBeOnBoard: false, validLocation: true}, + {info: "start 6 true", mino: testMinoStruct{minoRotation: minos.minoBag[6]}, mustBeOnBoard: true, validLocation: false}, + + {info: "top left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 0}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "top left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: 0}, changeLocation: true, mustBeOnBoard: true, validLocation: true}, + {info: "top right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: 0}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "top right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: 0}, changeLocation: true, mustBeOnBoard: true, validLocation: true}, + {info: "bottom right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: board.height - 2}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "bottom right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: board.height - 2}, changeLocation: true, mustBeOnBoard: true, validLocation: true}, + {info: "bottom left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: board.height - 2}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "bottom left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: board.height - 2}, changeLocation: true, mustBeOnBoard: true, validLocation: true}, + + {info: "up 1 top left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: -1}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "up 1 top left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: -1}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "up 1 top right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: -1}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "up 1 top right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: -1}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + + {info: "up 2 top left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: -2}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "up 2 top left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: -2}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "up 2 top right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: -2}, changeLocation: true, mustBeOnBoard: false, validLocation: true}, + {info: "up 2 top right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: -2}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + + {info: "up 3 top left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: -3}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "up 3 top left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: -3}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "up 3 top right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: -3}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "up 3 top right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: -3}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + + {info: "off top left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: -1, y: 0}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "off top left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: -1, y: 0}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "off top right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 1, y: 0}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "off top right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 1, y: 0}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "off bottom right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 1, y: board.height - 2}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "off bottom right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 1, y: board.height - 2}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "off bottom right 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: board.height - 1}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "off bottom right 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: board.width - 2, y: board.height - 1}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "off bottom left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: -1, y: board.height - 2}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "off bottom left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: -1, y: board.height - 2}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + {info: "off bottom left 3 false", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: board.height - 1}, changeLocation: true, mustBeOnBoard: false, validLocation: false}, + {info: "off bottom left 3 true", mino: testMinoStruct{minoRotation: minos.minoBag[3], x: 0, y: board.height - 1}, changeLocation: true, mustBeOnBoard: true, validLocation: false}, + } + + for _, test := range tests { + mino := NewMino() + mino.minoRotation = test.mino.minoRotation + mino.length = len(mino.minoRotation[0]) + if test.changeLocation { + mino.x = test.mino.x + mino.y = test.mino.y + } + validLocation := mino.ValidLocation(test.mustBeOnBoard) + if validLocation != test.validLocation { + lines := board.getDebugBoardWithMino(mino) + for i := 0; i < len(lines); i++ { + t.Log(lines[i]) + } + t.Errorf("MinoValidLocation validLocation - received: %v - expected: %v - info %v", validLocation, test.validLocation, test.info) + } + } + + } + +} diff --git a/minos.go b/minos.go index 2bafd4c..8cf19f7 100644 --- a/minos.go +++ b/minos.go @@ -1,16 +1,12 @@ package main import ( + "math/rand" + "github.com/nsf/termbox-go" ) -type MinoBlocks [][]termbox.Attribute - -type MinoRotation [4]MinoBlocks - -var minoBag [7]MinoRotation - -func init() { +func NewMinos() { minoI := MinoBlocks{ []termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor}, []termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor}, @@ -50,17 +46,17 @@ func init() { var minoRotationI MinoRotation minoRotationI[0] = minoI for i := 1; i < 4; i++ { - minoRotationI[i] = initCloneRotateRight(minoRotationI[i-1]) + minoRotationI[i] = minosCloneRotateRight(minoRotationI[i-1]) } var minoRotationJ MinoRotation minoRotationJ[0] = minoJ for i := 1; i < 4; i++ { - minoRotationJ[i] = initCloneRotateRight(minoRotationJ[i-1]) + minoRotationJ[i] = minosCloneRotateRight(minoRotationJ[i-1]) } var minoRotationL MinoRotation minoRotationL[0] = minoL for i := 1; i < 4; i++ { - minoRotationL[i] = initCloneRotateRight(minoRotationL[i-1]) + minoRotationL[i] = minosCloneRotateRight(minoRotationL[i-1]) } var minoRotationO MinoRotation minoRotationO[0] = minoO @@ -70,23 +66,26 @@ func init() { var minoRotationS MinoRotation minoRotationS[0] = minoS for i := 1; i < 4; i++ { - minoRotationS[i] = initCloneRotateRight(minoRotationS[i-1]) + minoRotationS[i] = minosCloneRotateRight(minoRotationS[i-1]) } var minoRotationT MinoRotation minoRotationT[0] = minoT for i := 1; i < 4; i++ { - minoRotationT[i] = initCloneRotateRight(minoRotationT[i-1]) + minoRotationT[i] = minosCloneRotateRight(minoRotationT[i-1]) } var minoRotationZ MinoRotation minoRotationZ[0] = minoZ for i := 1; i < 4; i++ { - minoRotationZ[i] = initCloneRotateRight(minoRotationZ[i-1]) + minoRotationZ[i] = minosCloneRotateRight(minoRotationZ[i-1]) } - minoBag = [7]MinoRotation{minoRotationI, minoRotationJ, minoRotationL, minoRotationO, minoRotationS, minoRotationT, minoRotationZ} + minos = &Minos{ + minoBag: [7]MinoRotation{minoRotationI, minoRotationJ, minoRotationL, minoRotationO, minoRotationS, minoRotationT, minoRotationZ}, + bagRand: rand.Perm(7), + } } -func initCloneRotateRight(minoBlocks MinoBlocks) MinoBlocks { +func minosCloneRotateRight(minoBlocks MinoBlocks) MinoBlocks { length := len(minoBlocks) newMinoBlocks := make(MinoBlocks, length, length) for i := 0; i < length; i++ { diff --git a/ranking.go b/ranking.go index 4500607..2dd3a7b 100644 --- a/ranking.go +++ b/ranking.go @@ -8,21 +8,13 @@ import ( "strings" ) -const ( - rankingFileName = "/tetris.db" -) - -type Ranking struct { - scores []uint64 -} - func NewRanking() *Ranking { ranking := &Ranking{ - scores: make([]uint64, 10), + scores: make([]uint64, 9), } if _, err := os.Stat(baseDir + rankingFileName); os.IsNotExist(err) { - for i := 0; i < 10; i++ { + for i := 0; i < 9; i++ { ranking.scores[i] = 0 } return ranking @@ -35,6 +27,9 @@ func NewRanking() *Ranking { scoreStrings := strings.Split(string(scoreBytes), ",") for index, scoreString := range scoreStrings { + if index > 8 { + break + } score, err := strconv.ParseUint(scoreString, 10, 64) if err != nil { logger.Error("NewRanking ParseUint", "error", err.Error()) @@ -49,7 +44,7 @@ func NewRanking() *Ranking { func (ranking *Ranking) Save() { var buffer bytes.Buffer - for i := 0; i < 10; i++ { + for i := 0; i < 9; i++ { if i != 0 { buffer.WriteRune(',') } diff --git a/screenshots/screenshot3.png b/screenshots/screenshot3.png index dd423a9..a9f4016 100644 Binary files a/screenshots/screenshot3.png and b/screenshots/screenshot3.png differ diff --git a/screenshots/screenshot4.png b/screenshots/screenshot4.png new file mode 100644 index 0000000..67e62b9 Binary files /dev/null and b/screenshots/screenshot4.png differ diff --git a/tetris.go b/tetris.go index c3909fa..3fce15a 100644 --- a/tetris.go +++ b/tetris.go @@ -1,24 +1,12 @@ package main import ( - "github.com/nsf/termbox-go" - "gopkg.in/inconshreveable/log15.v2" + "math/rand" "os" "path/filepath" -) + "time" -const ( - boardWidth = 10 - boardHeight = 20 - blankColor = termbox.ColorBlack -) - -var ( - baseDir string - logger log15.Logger - view *View - engine *Engine - board *Board + "gopkg.in/inconshreveable/log15.v2" ) func main() { @@ -29,8 +17,12 @@ func main() { logger.SetHandler(log15.Must.FileHandler(baseDir+"/tetris.log", log15.LogfmtFormat())) } - view = NewView() - engine = NewEngine() + rand.Seed(time.Now().UnixNano()) + + NewMinos() + NewBoard() + NewView() + NewEngine() engine.Run() diff --git a/view.go b/view.go index 073dfc5..9be12cc 100644 --- a/view.go +++ b/view.go @@ -2,27 +2,20 @@ package main import ( "fmt" - "github.com/nsf/termbox-go" + "math/rand" "time" + + "github.com/nsf/termbox-go" ) -const ( - boardXOffset = 4 - boardYOffset = 2 -) - -type View struct { - drawDropMarkerDisabled bool -} - -func NewView() *View { +func NewView() { err := termbox.Init() if err != nil { panic(err) } termbox.SetInputMode(termbox.InputEsc) termbox.Flush() - return &View{} + view = &View{} } func (view *View) Stop() { @@ -38,12 +31,18 @@ func (view *View) RefreshScreen() { view.drawBackground() view.drawTexts() - board.DrawPreviewMino() - if engine.gameOver { + if engine.previewBoard { + board.DrawBoard() view.drawGameOver() + } else if engine.gameOver { + view.drawGameOver() + view.drawRankingScores() + } else if engine.paused { + view.drawPaused() } else { board.DrawBoard() + board.DrawPreviewMino() board.DrawDropMino() board.DrawCurrentMino() } @@ -55,8 +54,8 @@ func (view *View) drawBackground() { // playing board xOffset := boardXOffset yOffset := boardYOffset - xEnd := boardXOffset + boardWidth*2 + 4 - yEnd := boardYOffset + boardHeight + 2 + xEnd := boardXOffset + board.width*2 + 4 + yEnd := boardYOffset + board.height + 2 for x := xOffset; x < xEnd; x++ { for y := yOffset; y < yEnd; y++ { if x == xOffset || x == xOffset+1 || x == xEnd-1 || x == xEnd-2 || @@ -69,7 +68,7 @@ func (view *View) drawBackground() { } // piece preview - xOffset = boardXOffset + boardWidth*2 + 8 + xOffset = boardXOffset + board.width*2 + 8 yOffset = boardYOffset xEnd = xOffset + 14 yEnd = yOffset + 6 @@ -87,7 +86,7 @@ func (view *View) drawBackground() { } func (view *View) drawTexts() { - xOffset := boardXOffset + boardWidth*2 + 8 + xOffset := boardXOffset + board.width*2 + 8 yOffset := boardYOffset + 7 view.drawText(xOffset, yOffset, "SCORE:", termbox.ColorWhite, termbox.ColorBlue) @@ -135,7 +134,7 @@ func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, ro char1 = ' ' char2 = '▓' } - xOffset := 2*x + 2*boardWidth + boardXOffset + 11 + (4 - length) + xOffset := 2*x + 2*board.width + boardXOffset + 11 + (4 - length) termbox.SetCell(xOffset, y+boardYOffset+2, char1, color, color^termbox.AttrBold) termbox.SetCell(xOffset+1, y+boardYOffset+2, char2, color, color^termbox.AttrBold) } @@ -160,17 +159,32 @@ func (view *View) DrawBlock(x int, y int, color termbox.Attribute, rotation int) } } -func (view *View) drawGameOver() { - xOffset := boardXOffset + 4 - yOffset := boardYOffset + 2 +func (view *View) drawPaused() { + yOffset := (board.height+1)/2 + boardYOffset + view.drawTextCenter(yOffset, "Paused", termbox.ColorWhite, termbox.ColorBlack) +} - view.drawText(xOffset, yOffset, " GAME OVER", termbox.ColorWhite, termbox.ColorBlack) +func (view *View) drawGameOver() { + yOffset := boardYOffset + 2 + view.drawTextCenter(yOffset, " GAME OVER", termbox.ColorWhite, termbox.ColorBlack) yOffset += 2 - view.drawText(xOffset, yOffset, "sbar for new game", termbox.ColorWhite, termbox.ColorBlack) + view.drawTextCenter(yOffset, "sbar for new game", termbox.ColorWhite, termbox.ColorBlack) + + if engine.previewBoard { + return + } + yOffset += 2 - xOffset += 2 + // ascii arrow characters add extra two spaces + view.drawTextCenter(yOffset, "←previous board", termbox.ColorWhite, termbox.ColorBlack) + yOffset += 2 + view.drawTextCenter(yOffset, "→next board", termbox.ColorWhite, termbox.ColorBlack) +} + +func (view *View) drawRankingScores() { + yOffset := boardYOffset + 10 for index, line := range engine.ranking.scores { - view.drawText(xOffset, yOffset+index, fmt.Sprintf("%2d: %6d", index+1, line), termbox.ColorWhite, termbox.ColorBlack) + view.drawTextCenter(yOffset+index, fmt.Sprintf("%1d: %6d", index+1, line), termbox.ColorWhite, termbox.ColorBlack) } } @@ -180,9 +194,14 @@ func (view *View) drawText(x int, y int, text string, fg termbox.Attribute, bg t } } -func (view *View) ShowDeleteAnimation(lines []int) { - view.drawDropMarkerDisabled = true +func (view *View) drawTextCenter(y int, text string, fg termbox.Attribute, bg termbox.Attribute) { + xOffset := board.width - (len(text)+1)/2 + boardXOffset + 2 + for index, char := range text { + termbox.SetCell(index+xOffset, y, rune(char), fg, bg) + } +} +func (view *View) ShowDeleteAnimation(lines []int) { view.RefreshScreen() for times := 0; times < 3; times++ { @@ -195,26 +214,77 @@ func (view *View) ShowDeleteAnimation(lines []int) { view.RefreshScreen() time.Sleep(140 * time.Millisecond) } - - view.drawDropMarkerDisabled = false } func (view *View) ShowGameOverAnimation() { - view.drawDropMarkerDisabled = true + logger.Info("View ShowGameOverAnimation start") - view.RefreshScreen() + switch rand.Intn(3) { + case 0: + for y := board.height - 1; y >= 0; y-- { + view.colorizeLine(y, termbox.ColorBlack) + termbox.Flush() + time.Sleep(60 * time.Millisecond) + } - for y := boardHeight - 1; y >= 0; y-- { - view.colorizeLine(y, termbox.ColorBlack) - termbox.Flush() - time.Sleep(60 * time.Millisecond) + case 1: + for y := 0; y < board.height; y++ { + view.colorizeLine(y, termbox.ColorBlack) + termbox.Flush() + time.Sleep(60 * time.Millisecond) + } + + case 2: + sleepTime := 50 * time.Millisecond + topStartX := boardXOffset + 3 + topEndX := board.width*2 + boardXOffset + 1 + topY := boardYOffset + 1 + rightStartY := boardYOffset + 1 + rightEndY := board.height + boardYOffset + 1 + rightX := board.width*2 + boardXOffset + 1 + bottomStartX := topEndX - 1 + bottomEndX := topStartX - 1 + bottomY := board.height + boardYOffset + leftStartY := rightEndY - 1 + leftEndY := rightStartY - 1 + leftX := boardXOffset + 2 + + for topStartX <= topEndX && rightStartY <= rightEndY { + for x := topStartX; x < topEndX; x++ { + termbox.SetCell(x, topY, ' ', termbox.ColorBlack, termbox.ColorBlack) + } + topStartX++ + topEndX-- + topY++ + for y := rightStartY; y < rightEndY; y++ { + termbox.SetCell(rightX, y, ' ', termbox.ColorBlack, termbox.ColorBlack) + } + rightStartY++ + rightEndY-- + rightX-- + for x := bottomStartX; x > bottomEndX; x-- { + termbox.SetCell(x, bottomY, ' ', termbox.ColorBlack, termbox.ColorBlack) + } + bottomStartX-- + bottomEndX++ + bottomY-- + for y := leftStartY; y > leftEndY; y-- { + termbox.SetCell(leftX, y, ' ', termbox.ColorBlack, termbox.ColorBlack) + } + leftStartY-- + leftEndY++ + leftX++ + termbox.Flush() + time.Sleep(sleepTime) + sleepTime += 4 * time.Millisecond + } } - view.drawDropMarkerDisabled = false + logger.Info("View ShowGameOverAnimation end") } func (view *View) colorizeLine(y int, color termbox.Attribute) { - for x := 0; x < boardWidth; x++ { + for x := 0; x < board.width; x++ { termbox.SetCell(x*2+boardXOffset+2, y+boardYOffset+1, ' ', termbox.ColorDefault, color) termbox.SetCell(x*2+boardXOffset+3, y+boardYOffset+1, ' ', termbox.ColorDefault, color) }