Added heightEnds to AI

This commit is contained in:
MichaelS11 2019-01-14 16:11:46 -08:00
parent 5991cea645
commit 39e38c05d9
4 changed files with 190 additions and 128 deletions

111
ai.go
View File

@ -43,10 +43,15 @@ func (ai *Ai) ProcessQueue() {
// GetBestQueue gets the best queue
func (ai *Ai) GetBestQueue() {
bestScore := -9999999
bestQueue := make([]rune, 0, 0)
currentMino := *board.currentMino
bestQueue := []rune{'x'}
currentMino := board.currentMino
previewMino := board.previewMino
rotations1 := 5
rotations2 := 5
slides := 5
if board.width > 10 {
slides = 3
}
switch currentMino.minoRotation[0][1][1] {
case termbox.ColorCyan, termbox.ColorGreen, termbox.ColorRed:
@ -54,33 +59,33 @@ func (ai *Ai) GetBestQueue() {
case termbox.ColorYellow:
rotations1 = 1
}
switch board.previewMino.minoRotation[0][1][1] {
switch previewMino.minoRotation[0][1][1] {
case termbox.ColorCyan, termbox.ColorGreen, termbox.ColorRed:
rotations2 = 2
case termbox.ColorYellow:
rotations2 = 1
}
for slide1 := 0; slide1 < 5; slide1++ {
for slide1 := 0; slide1 < slides; slide1++ {
for move1 := board.width; move1 >= 0; move1-- {
for rotate1 := 0; rotate1 < rotations1; rotate1++ {
queue, mino1 := board.getMovesforMino(rotate1, move1, slide1, &currentMino, nil)
queue, mino1 := board.getMovesforMino(rotate1, move1, slide1, currentMino, nil)
if mino1 == nil {
continue
}
for slide2 := 0; slide2 < 5; slide2++ {
for slide2 := 0; slide2 < slides; slide2++ {
for move2 := board.width; move2 >= 0; move2-- {
for rotate2 := 0; rotate2 < rotations2; rotate2++ {
_, mino2 := board.getMovesforMino(rotate2, move2, slide2, board.previewMino, mino1)
_, mino2 := board.getMovesforMino(rotate2, move2, slide2, previewMino, mino1)
if mino2 == nil {
continue
}
fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2)
score := ai.getScoreFromBoardStats(fullLines, holes, bumpy)
fullLines, holes, bumpy, heightEnds := board.boardStatsWithMinos(mino1, mino2)
score := ai.getScoreFromBoardStats(fullLines, holes, bumpy, heightEnds, mino1.y, mino2.y)
if score > bestScore {
bestScore = score
@ -95,54 +100,53 @@ func (ai *Ai) GetBestQueue() {
}
}
if len(bestQueue) < 1 {
bestQueue = append(bestQueue, 'x')
}
ai.newQueue = &bestQueue
}
func (board *Board) getMovesforMino(rotate int, move int, slide int, mino1 *Mino, mino2 *Mino) ([]rune, *Mino) {
queue := make([]rune, 0, rotate+move+slide+1)
var i int
queue := make([]rune, 0, (rotate/2+1)+(move/2+1)+(slide/2+1)+1)
mino := *mino1
mino.MoveDown()
if rotate%2 == 0 {
rotate /= 2
for i := 0; i < rotate; i++ {
for i = 0; i < rotate; i++ {
mino.RotateRight()
queue = append(queue, 'e')
if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) {
return queue, nil
}
queue = append(queue, 'e')
}
} else {
rotate = rotate/2 + 1
for i := 0; i < rotate; i++ {
for i = 0; i < rotate; i++ {
mino.RotateLeft()
queue = append(queue, 'q')
if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) {
return queue, nil
}
queue = append(queue, 'q')
}
}
if move%2 == 0 {
move /= 2
for i := 0; i < move; i++ {
mino.MoveLeft()
queue = append(queue, 'a')
for i = 0; i < move; i++ {
mino.MoveRight()
if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) {
return queue, nil
}
queue = append(queue, 'd')
}
} else {
move = move/2 + 1
for i := 0; i < move; i++ {
mino.MoveRight()
queue = append(queue, 'd')
for i = 0; i < move; i++ {
mino.MoveLeft()
if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) {
return queue, nil
}
queue = append(queue, 'a')
}
}
for mino.ValidLocation(false) && (mino2 == nil || !mino2.minoOverlap(&mino)) {
@ -153,34 +157,35 @@ func (board *Board) getMovesforMino(rotate int, move int, slide int, mino1 *Mino
if slide%2 == 0 {
slide /= 2
for i := 0; i < slide; i++ {
for i = 0; i < slide; i++ {
mino.MoveLeft()
queue = append(queue, 'a')
if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) {
return queue, nil
}
queue = append(queue, 'a')
}
} else {
slide = slide/2 + 1
for i := 0; i < slide; i++ {
for i = 0; i < slide; i++ {
mino.MoveRight()
queue = append(queue, 'd')
if !mino.ValidLocation(false) || (mino2 != nil && mino2.minoOverlap(&mino)) {
return queue, nil
}
queue = append(queue, 'd')
}
}
if !mino.ValidLocation(true) {
return queue, nil
}
queue = append(queue, 'x')
return queue, &mino
return append(queue, 'x'), &mino
}
func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int, holes int, bumpy int) {
func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int, holes int, bumpy int, heightEnds int) {
var i int
var j int
// fullLines
for j = 0; j < board.height; j++ {
board.fullLinesY[j] = true
@ -196,47 +201,57 @@ func (board *Board) boardStatsWithMinos(mino1 *Mino, mino2 *Mino) (fullLines int
}
// holes and bumpy
indexLast := 0
var foundLast int
var fullLinesFound int
for i = 0; i < board.width; i++ {
index := board.height
indexOffset := 0
found := board.height
fullLinesFound = 0
for j = 0; j < board.height; j++ {
if board.fullLinesY[j] {
indexOffset++
fullLinesFound++
} else {
if board.colors[i][j] != blankColor || mino1.isMinoAtLocation(i, j) || mino2.isMinoAtLocation(i, j) {
index = j
found = j
break
}
}
}
if i != 0 {
diffrence := (index + fullLines - indexOffset) - indexLast
if i == 0 {
heightEnds = board.height - (found + fullLines - fullLinesFound)
} else {
diffrence := (found + fullLines - fullLinesFound) - foundLast
if diffrence < 0 {
diffrence = -diffrence
}
bumpy += diffrence
}
indexLast = index + fullLines - indexOffset
foundLast = found + fullLines - fullLinesFound
index++
for k := index; k < board.height; k++ {
if board.colors[i][k] == blankColor && !mino1.isMinoAtLocation(i, k) && !mino2.isMinoAtLocation(i, k) {
for j++; j < board.height; j++ {
if board.colors[i][j] == blankColor && !mino1.isMinoAtLocation(i, j) && !mino2.isMinoAtLocation(i, j) {
holes++
}
}
}
heightEnds += board.height - foundLast
return
}
func (ai *Ai) getScoreFromBoardStats(fullLines int, holes int, bumpy int) int {
score := 0
if fullLines == 4 {
func (ai *Ai) getScoreFromBoardStats(fullLines int, holes int, bumpy int, heightEnds int, height1 int, height2 int) int {
score := 8 * heightEnds
if fullLines > 3 {
score += 512
}
score -= 80 * holes
score -= 20 * bumpy
score -= 75 * holes
score -= 15 * bumpy
if height1 < 6 {
score -= 10 * (5 - height1)
}
if height2 < 6 {
score -= 10 * (5 - height2)
}
return score
}

View File

@ -5,11 +5,12 @@ import (
)
type testAiStruct struct {
info string
minos []testMinoStruct
fullLines int
holes int
bumpy int
info string
minos []testMinoStruct
fullLines int
holes int
bumpy int
heightEnds int
}
func TestAI(t *testing.T) {
@ -21,32 +22,32 @@ func TestAI(t *testing.T) {
{info: "fullLines 2x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
}, fullLines: 0, holes: 0, bumpy: 1},
}, fullLines: 0, holes: 0, bumpy: 1, heightEnds: 1},
{info: "fullLines 2x2 minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 0, y: 17}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 17}, // minoI
}, fullLines: 0, holes: 0, bumpy: 2},
}, fullLines: 0, holes: 0, bumpy: 2, heightEnds: 2},
{info: "fullLines 2x minoI minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO
}, fullLines: 1, holes: 0, bumpy: 1},
}, fullLines: 1, holes: 0, bumpy: 1, heightEnds: 1},
{info: "fullLines 2x2 minoI minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 0, y: 17}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 17}, // minoI
{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO
}, fullLines: 2, holes: 0, bumpy: 0},
}, fullLines: 2, holes: 0, bumpy: 0, heightEnds: 0},
{info: "fullLines 5x minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 2, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 4, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 6, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO
}, fullLines: 2, holes: 0, bumpy: 0},
}, fullLines: 2, holes: 0, bumpy: 0, heightEnds: 0},
{info: "fullLines 4x4 minoI 2x minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
@ -58,19 +59,19 @@ func TestAI(t *testing.T) {
{minoRotation: minos.minoBag[0], x: 4, y: 15}, // minoI
{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 8, y: 16}, // minoO
}, fullLines: 4, holes: 0, bumpy: 0},
}, fullLines: 4, holes: 0, bumpy: 0, heightEnds: 0},
{info: "holes 2x minoI minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 6, y: 18}, // minoI
{minoRotation: minos.minoBag[3], x: 4, y: 17}, // minoO
}, fullLines: 0, holes: 2, bumpy: 4},
}, fullLines: 0, holes: 2, bumpy: 4, heightEnds: 2},
{info: "holes 6x minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 4, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 8, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 2, y: 16}, // minoO
{minoRotation: minos.minoBag[3], x: 6, y: 16}, // minoO
}, fullLines: 0, holes: 8, bumpy: 8},
}, fullLines: 0, holes: 8, bumpy: 8, heightEnds: 4},
{info: "holes 4x minoT 2x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[5], x: 0, y: 18}, // minoT
{minoRotation: minos.minoBag[5], x: 7, y: 18}, // minoT
@ -78,12 +79,12 @@ func TestAI(t *testing.T) {
{minoRotation: minos.minoBag[5], x: 7, y: 16}, // minoT
{minoRotation: minos.minoBag[0], x: 2, y: 14}, // minoI
{minoRotation: minos.minoBag[0], x: 6, y: 14}, // minoI
}, fullLines: 0, holes: 19, bumpy: 4},
}, fullLines: 0, holes: 19, bumpy: 4, heightEnds: 6},
{info: "holes 3x minoZ", minos: []testMinoStruct{
{minoRotation: minos.minoBag[6], x: 0, y: 18}, // minoZ
{minoRotation: minos.minoBag[6], x: 3, y: 18}, // minoZ
{minoRotation: minos.minoBag[6], x: 6, y: 18}, // minoZ
}, fullLines: 0, holes: 3, bumpy: 6},
}, fullLines: 0, holes: 3, bumpy: 6, heightEnds: 2},
{info: "holes 4x minoT 2x minoI 2x minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[5], x: 0, y: 18}, // minoT
{minoRotation: minos.minoBag[5], x: 7, y: 18}, // minoT
@ -93,43 +94,43 @@ func TestAI(t *testing.T) {
{minoRotation: minos.minoBag[3], x: 0, y: 14}, // minoO
{minoRotation: minos.minoBag[0], x: 2, y: 14}, // minoI
{minoRotation: minos.minoBag[0], x: 6, y: 14}, // minoI
}, fullLines: 1, holes: 9, bumpy: 16},
}, fullLines: 1, holes: 9, bumpy: 16, heightEnds: 8},
{info: "bumpy 2x minoT - 1", minos: []testMinoStruct{
{minoRotation: minos.minoBag[5], x: 0, y: 18}, // minoT
{minoRotation: minos.minoBag[5], x: 5, y: 18}, // minoT
}, fullLines: 0, holes: 0, bumpy: 7},
}, fullLines: 0, holes: 0, bumpy: 7, heightEnds: 1},
{info: "bumpy 2x minoT - 2", minos: []testMinoStruct{
{minoRotation: minos.minoBag[5], x: 1, y: 18}, // minoT
{minoRotation: minos.minoBag[5], x: 6, y: 18}, // minoT
}, fullLines: 0, holes: 0, bumpy: 8},
}, fullLines: 0, holes: 0, bumpy: 8, heightEnds: 0},
{info: "bumpy 2x minoT - 3", minos: []testMinoStruct{
{minoRotation: minos.minoBag[5], x: 2, y: 18}, // minoT
{minoRotation: minos.minoBag[5], x: 7, y: 18}, // minoT
}, fullLines: 0, holes: 0, bumpy: 7},
}, fullLines: 0, holes: 0, bumpy: 7, heightEnds: 1},
{info: "bumpy 2x minoJ - 1", minos: []testMinoStruct{
{minoRotation: minos.minoBag[1], x: 0, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 5, y: 18}, // minoJ
}, fullLines: 0, holes: 0, bumpy: 6},
}, fullLines: 0, holes: 0, bumpy: 6, heightEnds: 2},
{info: "bumpy 2x minoJ - 2", minos: []testMinoStruct{
{minoRotation: minos.minoBag[1], x: 1, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 6, y: 18}, // minoJ
}, fullLines: 0, holes: 0, bumpy: 8},
}, fullLines: 0, holes: 0, bumpy: 8, heightEnds: 0},
{info: "bumpy 2x minoJ - 2", minos: []testMinoStruct{
{minoRotation: minos.minoBag[1], x: 2, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 7, y: 18}, // minoJ
}, fullLines: 0, holes: 0, bumpy: 7},
}, fullLines: 0, holes: 0, bumpy: 7, heightEnds: 1},
{info: "bumpy 2x minoL - 1", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 0, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 5, y: 18}, // minoL
}, fullLines: 0, holes: 0, bumpy: 7},
}, fullLines: 0, holes: 0, bumpy: 7, heightEnds: 1},
{info: "bumpy 2x minoL - 2", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 1, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 6, y: 18}, // minoL
}, fullLines: 0, holes: 0, bumpy: 8},
}, fullLines: 0, holes: 0, bumpy: 8, heightEnds: 0},
{info: "bumpy 2x minoL - 3", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 2, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 7, y: 18}, // minoL
}, fullLines: 0, holes: 0, bumpy: 6},
}, fullLines: 0, holes: 0, bumpy: 6, heightEnds: 2},
}
runAiTests(t, tests)
@ -146,14 +147,14 @@ func TestBigBoardAI(t *testing.T) {
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 18}, // minoI
}, fullLines: 0, holes: 0, bumpy: 1},
}, fullLines: 0, holes: 0, bumpy: 1, heightEnds: 1},
{info: "fullLines 5x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 18}, // minoI
}, fullLines: 1, holes: 0, bumpy: 0},
}, fullLines: 1, holes: 0, bumpy: 0, heightEnds: 0},
{info: "fullLines 5x2 minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[0], x: 0, y: 18}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 18}, // minoI
@ -165,7 +166,7 @@ func TestBigBoardAI(t *testing.T) {
{minoRotation: minos.minoBag[0], x: 8, y: 17}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 17}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 17}, // minoI
}, fullLines: 2, holes: 0, bumpy: 0},
}, fullLines: 2, holes: 0, bumpy: 0, heightEnds: 0},
{info: "fullLines 9x minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 2, y: 18}, // minoO
@ -176,7 +177,7 @@ func TestBigBoardAI(t *testing.T) {
{minoRotation: minos.minoBag[3], x: 12, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 14, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 16, y: 18}, // minoO
}, fullLines: 0, holes: 0, bumpy: 2},
}, fullLines: 0, holes: 0, bumpy: 2, heightEnds: 2},
{info: "fullLines 10x minoO", minos: []testMinoStruct{
{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 2, y: 18}, // minoO
@ -188,7 +189,7 @@ func TestBigBoardAI(t *testing.T) {
{minoRotation: minos.minoBag[3], x: 14, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 16, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 18, y: 18}, // minoO
}, fullLines: 2, holes: 0, bumpy: 0},
}, fullLines: 2, holes: 0, bumpy: 0, heightEnds: 0},
{info: "holes 3x minoO 3x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[3], x: 0, y: 18}, // minoO
{minoRotation: minos.minoBag[3], x: 6, y: 18}, // minoO
@ -196,14 +197,14 @@ func TestBigBoardAI(t *testing.T) {
{minoRotation: minos.minoBag[0], x: 2, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 14, y: 16}, // minoI
}, fullLines: 0, holes: 24, bumpy: 8},
}, fullLines: 0, holes: 24, bumpy: 8, heightEnds: 2},
{info: "holes 5x minoZ", minos: []testMinoStruct{
{minoRotation: minos.minoBag[6], x: 0, y: 18}, // minoZ
{minoRotation: minos.minoBag[6], x: 4, y: 18}, // minoZ
{minoRotation: minos.minoBag[6], x: 8, y: 18}, // minoZ
{minoRotation: minos.minoBag[6], x: 12, y: 18}, // minoZ
{minoRotation: minos.minoBag[6], x: 16, y: 18}, // minoZ
}, fullLines: 0, holes: 5, bumpy: 18},
}, fullLines: 0, holes: 5, bumpy: 18, heightEnds: 2},
{info: "holes 6x minoT 2x minoO 5x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[5], x: 0, y: 18}, // minoT
{minoRotation: minos.minoBag[5], x: 6, y: 18}, // minoT
@ -218,43 +219,79 @@ func TestBigBoardAI(t *testing.T) {
{minoRotation: minos.minoBag[0], x: 8, y: 14}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 14}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 14}, // minoI
}, fullLines: 1, holes: 18, bumpy: 23},
}, fullLines: 1, holes: 18, bumpy: 23, heightEnds: 5},
{info: "bumpy 4x minoJ - 1", minos: []testMinoStruct{
{minoRotation: minos.minoBag[1], x: 0, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 5, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 10, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 15, y: 18}, // minoJ
}, fullLines: 0, holes: 0, bumpy: 14},
}, fullLines: 0, holes: 0, bumpy: 14, heightEnds: 2},
{info: "bumpy 4x minoJ - 2", minos: []testMinoStruct{
{minoRotation: minos.minoBag[1], x: 1, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 6, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 11, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 16, y: 18}, // minoJ
}, fullLines: 0, holes: 0, bumpy: 16},
}, fullLines: 0, holes: 0, bumpy: 16, heightEnds: 0},
{info: "bumpy 4x minoJ - 3", minos: []testMinoStruct{
{minoRotation: minos.minoBag[1], x: 2, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 7, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 12, y: 18}, // minoJ
{minoRotation: minos.minoBag[1], x: 17, y: 18}, // minoJ
}, fullLines: 0, holes: 0, bumpy: 15},
}, fullLines: 0, holes: 0, bumpy: 15, heightEnds: 1},
{info: "bumpy 4x minoL - 1", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 0, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 5, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 10, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 15, y: 18}, // minoL
}, fullLines: 0, holes: 0, bumpy: 15},
}, fullLines: 0, holes: 0, bumpy: 15, heightEnds: 1},
{info: "bumpy 4x minoL - 2", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 1, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 6, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 11, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 16, y: 18}, // minoL
}, fullLines: 0, holes: 0, bumpy: 16},
}, fullLines: 0, holes: 0, bumpy: 16, heightEnds: 0},
{info: "bumpy 4x minoL - 3", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 2, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 7, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 12, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 17, y: 18}, // minoL
}, fullLines: 0, holes: 0, bumpy: 14},
}, fullLines: 0, holes: 0, bumpy: 14, heightEnds: 2},
{info: "bumpy 4x minoL & 10x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 2, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 7, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 12, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 17, y: 18}, // minoL
{minoRotation: minos.minoBag[0], x: 0, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 0, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 15}, // minoI
}, fullLines: 2, holes: 0, bumpy: 14, heightEnds: 2},
{info: "bumpy 8x minoL & 10x minoI", minos: []testMinoStruct{
{minoRotation: minos.minoBag[2], x: 2, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 7, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 12, y: 18}, // minoL
{minoRotation: minos.minoBag[2], x: 17, y: 18}, // minoL
{minoRotation: minos.minoBag[0], x: 0, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 16}, // minoI
{minoRotation: minos.minoBag[0], x: 0, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 4, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 8, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 12, y: 15}, // minoI
{minoRotation: minos.minoBag[0], x: 16, y: 15}, // minoI
{minoRotation: minos.minoBag[2], x: 2, y: 14}, // minoL
{minoRotation: minos.minoBag[2], x: 7, y: 14}, // minoL
{minoRotation: minos.minoBag[2], x: 12, y: 14}, // minoL
{minoRotation: minos.minoBag[2], x: 17, y: 14}, // minoL
}, fullLines: 2, holes: 8, bumpy: 28, heightEnds: 4},
}
runAiTests(t, tests)
@ -282,7 +319,7 @@ func runAiTests(t *testing.T, tests []testAiStruct) {
}
}
fullLines, holes, bumpy := board.boardStatsWithMinos(mino1, mino2)
fullLines, holes, bumpy, heightEnds := board.boardStatsWithMinos(mino1, mino2)
if fullLines != test.fullLines {
mino1.SetOnBoard()
@ -311,6 +348,15 @@ func runAiTests(t *testing.T, tests []testAiStruct) {
t.Errorf("AI bumpy - received: %v - expected: %v - info %v", bumpy, test.bumpy, test.info)
continue
}
if heightEnds != test.heightEnds {
mino1.SetOnBoard()
lines := board.getDebugBoardWithMino(mino2)
for i := 0; i < len(lines); i++ {
t.Log(lines[i])
}
t.Errorf("AI heightEnds - received: %v - expected: %v - info %v", heightEnds, test.heightEnds, test.info)
continue
}
}
}

View File

@ -240,26 +240,26 @@ var boardsInternal = []byte(`
"name":"10 x 20 checkerboard single",
"mino":[
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"]
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"]
],
"rotation":[
[0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
]
},
@ -408,46 +408,46 @@ var boardsInternal = []byte(`
"name":"20 x 20 checkerboard single",
"mino":[
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"],
["b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z"],
["b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"]
["b","b","b","b","b","b","z","b","z","b","z","b","z","b","z","b","z","b","z","b"]
],
"rotation":[
[0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,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,0,0,0,0,2,0,2,0,2,0,2,0,2,0,2,0,2,0,2],
[0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0]
]
},

21
mino.go
View File

@ -100,10 +100,11 @@ func (mino *Mino) ValidLocation(mustBeOnBoard bool) 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 !board.ValidBlockLocation(mino.x+i, mino.y+j, mustBeOnBoard) {
return false
}
if minoBlocks[i][j] == blankColor {
continue
}
if !board.ValidBlockLocation(mino.x+i, mino.y+j, mustBeOnBoard) {
return false
}
}
}
@ -148,10 +149,11 @@ 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
}
if minoBlocks[i][j] == blankColor {
continue
}
if mino1.isMinoAtLocation(mino.x+i, mino.y+j) {
return true
}
}
}
@ -166,8 +168,7 @@ func (mino *Mino) isMinoAtLocation(x int, y int) bool {
return false
}
minoBlocks := mino.minoRotation[mino.rotation]
if minoBlocks[xIndex][yIndex] != blankColor {
if mino.minoRotation[mino.rotation][xIndex][yIndex] != blankColor {
return true
}