Added comments
This commit is contained in:
parent
ebcc296976
commit
0ad9733f01
3
ai.go
3
ai.go
|
@ -4,6 +4,7 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewAi creates a new AI
|
||||
func NewAi() *Ai {
|
||||
ai := Ai{}
|
||||
queue := make([]rune, 1)
|
||||
|
@ -12,6 +13,7 @@ func NewAi() *Ai {
|
|||
return &ai
|
||||
}
|
||||
|
||||
// ProcessQueue checks AI queue and process key moments
|
||||
func (ai *Ai) ProcessQueue() {
|
||||
if ai.newQueue != nil {
|
||||
ai.queue = ai.newQueue
|
||||
|
@ -38,6 +40,7 @@ func (ai *Ai) ProcessQueue() {
|
|||
view.RefreshScreen()
|
||||
}
|
||||
|
||||
// GetBestQueue gets the best queue
|
||||
func (ai *Ai) GetBestQueue() {
|
||||
bestScore := -9999999
|
||||
bestQueue := make([]rune, 0, 0)
|
||||
|
|
29
board.go
29
board.go
|
@ -7,11 +7,13 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewBoard creates a new clear board
|
||||
func NewBoard() {
|
||||
board = &Board{}
|
||||
board.Clear()
|
||||
}
|
||||
|
||||
// Clear clears the board
|
||||
func (board *Board) Clear() {
|
||||
board.width = len(boards[board.boardsIndex].colors)
|
||||
board.height = len(boards[board.boardsIndex].colors[0])
|
||||
|
@ -29,6 +31,7 @@ func (board *Board) Clear() {
|
|||
board.currentMino = NewMino()
|
||||
}
|
||||
|
||||
// PreviousBoard switchs to previous board
|
||||
func (board *Board) PreviousBoard() {
|
||||
board.boardsIndex--
|
||||
if board.boardsIndex < 0 {
|
||||
|
@ -38,6 +41,7 @@ func (board *Board) PreviousBoard() {
|
|||
board.Clear()
|
||||
}
|
||||
|
||||
// NextBoard switchs to next board
|
||||
func (board *Board) NextBoard() {
|
||||
board.boardsIndex++
|
||||
if board.boardsIndex == len(boards) {
|
||||
|
@ -47,6 +51,7 @@ func (board *Board) NextBoard() {
|
|||
board.Clear()
|
||||
}
|
||||
|
||||
// MinoMoveLeft moves mino left
|
||||
func (board *Board) MinoMoveLeft() {
|
||||
board.dropDistance = 0
|
||||
mino := board.currentMino.CloneMoveLeft()
|
||||
|
@ -56,6 +61,7 @@ func (board *Board) MinoMoveLeft() {
|
|||
}
|
||||
}
|
||||
|
||||
// MinoMoveRight moves mino right
|
||||
func (board *Board) MinoMoveRight() {
|
||||
board.dropDistance = 0
|
||||
mino := board.currentMino.CloneMoveRight()
|
||||
|
@ -65,6 +71,7 @@ func (board *Board) MinoMoveRight() {
|
|||
}
|
||||
}
|
||||
|
||||
// MinoRotateRight rotates mino right
|
||||
func (board *Board) MinoRotateRight() {
|
||||
board.dropDistance = 0
|
||||
mino := board.currentMino.CloneRotateRight()
|
||||
|
@ -88,6 +95,7 @@ func (board *Board) MinoRotateRight() {
|
|||
}
|
||||
}
|
||||
|
||||
// MinoRotateLeft rotates mino right
|
||||
func (board *Board) MinoRotateLeft() {
|
||||
board.dropDistance = 0
|
||||
mino := board.currentMino.CloneRotateLeft()
|
||||
|
@ -111,6 +119,7 @@ func (board *Board) MinoRotateLeft() {
|
|||
}
|
||||
}
|
||||
|
||||
// MinoMoveDown moves mino down
|
||||
func (board *Board) MinoMoveDown() {
|
||||
mino := board.currentMino.CloneMoveDown()
|
||||
if mino.ValidLocation(false) {
|
||||
|
@ -128,6 +137,7 @@ func (board *Board) MinoMoveDown() {
|
|||
board.nextMino()
|
||||
}
|
||||
|
||||
// MinoDrop dropps mino
|
||||
func (board *Board) MinoDrop() {
|
||||
board.dropDistance = 0
|
||||
mino := board.currentMino.CloneMoveDown()
|
||||
|
@ -150,6 +160,7 @@ func (board *Board) MinoDrop() {
|
|||
}
|
||||
}
|
||||
|
||||
// StartLockDelayIfBottom if at bottom, starts lock delay
|
||||
func (board *Board) StartLockDelayIfBottom() bool {
|
||||
mino := board.currentMino.CloneMoveDown()
|
||||
if mino.ValidLocation(false) {
|
||||
|
@ -159,6 +170,7 @@ func (board *Board) StartLockDelayIfBottom() bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// nextMino gets next mino
|
||||
func (board *Board) nextMino() {
|
||||
engine.AddScore(board.dropDistance)
|
||||
|
||||
|
@ -180,6 +192,7 @@ func (board *Board) nextMino() {
|
|||
engine.ResetTimer(0)
|
||||
}
|
||||
|
||||
// deleteCheck checks if there are any lines on the board that can be deleted
|
||||
func (board *Board) deleteCheck() {
|
||||
lines := board.fullLines()
|
||||
if len(lines) < 1 {
|
||||
|
@ -194,6 +207,7 @@ func (board *Board) deleteCheck() {
|
|||
engine.AddDeleteLines(len(lines))
|
||||
}
|
||||
|
||||
// fullLines returns the line numbers that have full lines
|
||||
func (board *Board) fullLines() []int {
|
||||
fullLines := make([]int, 0, 1)
|
||||
for j := 0; j < board.height; j++ {
|
||||
|
@ -204,6 +218,7 @@ func (board *Board) fullLines() []int {
|
|||
return fullLines
|
||||
}
|
||||
|
||||
// isFullLine checks if line is full
|
||||
func (board *Board) isFullLine(j int) bool {
|
||||
for i := 0; i < board.width; i++ {
|
||||
if board.colors[i][j] == blankColor {
|
||||
|
@ -213,6 +228,7 @@ func (board *Board) isFullLine(j int) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// deleteLine deletes the line
|
||||
func (board *Board) deleteLine(line int) {
|
||||
for i := 0; i < board.width; i++ {
|
||||
board.colors[i][line] = blankColor
|
||||
|
@ -228,11 +244,13 @@ func (board *Board) deleteLine(line int) {
|
|||
}
|
||||
}
|
||||
|
||||
// SetColor sets the color and rotation of board location
|
||||
func (board *Board) SetColor(x int, y int, color termbox.Attribute, rotation int) {
|
||||
board.colors[x][y] = color
|
||||
board.rotation[x][y] = rotation
|
||||
}
|
||||
|
||||
// ValidBlockLocation checks if block location is vaild
|
||||
func (board *Board) ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool {
|
||||
if x < 0 || x >= board.width || y >= board.height {
|
||||
return false
|
||||
|
@ -254,10 +272,12 @@ func (board *Board) ValidBlockLocation(x int, y int, mustBeOnBoard bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// ValidDisplayLocation checks if vaild display location
|
||||
func ValidDisplayLocation(x int, y int) bool {
|
||||
return x >= 0 && x < board.width && y >= 0 && y < board.height
|
||||
}
|
||||
|
||||
// DrawBoard draws the board with help from view
|
||||
func (board *Board) DrawBoard() {
|
||||
for i := 0; i < board.width; i++ {
|
||||
for j := 0; j < board.height; j++ {
|
||||
|
@ -268,14 +288,17 @@ func (board *Board) DrawBoard() {
|
|||
}
|
||||
}
|
||||
|
||||
// DrawPreviewMino draws the preview mino
|
||||
func (board *Board) DrawPreviewMino() {
|
||||
board.previewMino.DrawMino(MinoPreview)
|
||||
}
|
||||
|
||||
// DrawCurrentMino draws the current mino
|
||||
func (board *Board) DrawCurrentMino() {
|
||||
board.currentMino.DrawMino(MinoCurrent)
|
||||
}
|
||||
|
||||
// DrawDropMino draws the drop mino
|
||||
func (board *Board) DrawDropMino() {
|
||||
mino := board.currentMino.CloneMoveDown()
|
||||
if !mino.ValidLocation(false) {
|
||||
|
@ -288,7 +311,7 @@ func (board *Board) DrawDropMino() {
|
|||
mino.DrawMino(MinoDrop)
|
||||
}
|
||||
|
||||
// for debuging
|
||||
// printDebugBoard is for printing board in text for debuging
|
||||
func (board *Board) printDebugBoard() {
|
||||
for j := 0; j < board.height; j++ {
|
||||
for i := 0; i < board.width; i++ {
|
||||
|
@ -317,7 +340,7 @@ func (board *Board) printDebugBoard() {
|
|||
}
|
||||
}
|
||||
|
||||
// for debuging
|
||||
// getDebugBoard returns board as string for debuging and testing
|
||||
func (board *Board) getDebugBoard() []string {
|
||||
lines := make([]string, board.height)
|
||||
for j := 0; j < board.height; j++ {
|
||||
|
@ -347,7 +370,7 @@ func (board *Board) getDebugBoard() []string {
|
|||
return lines
|
||||
}
|
||||
|
||||
// for debuging
|
||||
// getDebugBoardWithMino returns board with mino placed on it
|
||||
func (board *Board) getDebugBoardWithMino(mino *Mino) []string {
|
||||
lines := make([]string, board.height)
|
||||
for j := 0; j < board.height; j++ {
|
||||
|
|
95
boards.go
95
boards.go
|
@ -1082,5 +1082,100 @@ func init() {
|
|||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0,
|
||||
0, 0, 0, 0, 0, 0, 0, 0, 0, 0},
|
||||
}},
|
||||
|
||||
// 20 x 20 pumpkin
|
||||
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},
|
||||
}},
|
||||
}
|
||||
}
|
||||
|
|
16
engine.go
16
engine.go
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewEngine creates new engine
|
||||
func NewEngine() {
|
||||
engine = &Engine{
|
||||
chanStop: make(chan struct{}, 1),
|
||||
|
@ -15,6 +16,7 @@ func NewEngine() {
|
|||
}
|
||||
}
|
||||
|
||||
// Run runs the engine
|
||||
func (engine *Engine) Run() {
|
||||
logger.Println("Engine Run start")
|
||||
|
||||
|
@ -56,6 +58,7 @@ loop:
|
|||
logger.Println("Engine Run end")
|
||||
}
|
||||
|
||||
// Stop stops the engine
|
||||
func (engine *Engine) Stop() {
|
||||
logger.Println("Engine Stop start")
|
||||
|
||||
|
@ -69,6 +72,7 @@ func (engine *Engine) Stop() {
|
|||
logger.Println("Engine Stop end")
|
||||
}
|
||||
|
||||
// Pause pauses the engine
|
||||
func (engine *Engine) Pause() {
|
||||
if !engine.timer.Stop() {
|
||||
select {
|
||||
|
@ -85,6 +89,7 @@ func (engine *Engine) Pause() {
|
|||
engine.paused = true
|
||||
}
|
||||
|
||||
// UnPause resumes running the engine
|
||||
func (engine *Engine) UnPause() {
|
||||
engine.timer.Reset(engine.tickTime)
|
||||
if engine.aiEnabled {
|
||||
|
@ -93,10 +98,12 @@ func (engine *Engine) UnPause() {
|
|||
engine.paused = false
|
||||
}
|
||||
|
||||
// PreviewBoard sets previewBoard to true
|
||||
func (engine *Engine) PreviewBoard() {
|
||||
engine.previewBoard = true
|
||||
}
|
||||
|
||||
// NewGame resets board and starts a new game
|
||||
func (engine *Engine) NewGame() {
|
||||
logger.Println("Engine NewGame start")
|
||||
|
||||
|
@ -125,6 +132,7 @@ loop:
|
|||
logger.Println("Engine NewGame end")
|
||||
}
|
||||
|
||||
// ResetTimer resets the time for lock delay or tick time
|
||||
func (engine *Engine) ResetTimer(duration time.Duration) {
|
||||
if !engine.timer.Stop() {
|
||||
select {
|
||||
|
@ -141,6 +149,7 @@ func (engine *Engine) ResetTimer(duration time.Duration) {
|
|||
}
|
||||
}
|
||||
|
||||
// AiGetBestQueue calls AI to get best queue
|
||||
func (engine *Engine) AiGetBestQueue() {
|
||||
if !engine.aiEnabled {
|
||||
return
|
||||
|
@ -148,11 +157,13 @@ func (engine *Engine) AiGetBestQueue() {
|
|||
go engine.ai.GetBestQueue()
|
||||
}
|
||||
|
||||
// tick move mino down and refreshes screen
|
||||
func (engine *Engine) tick() {
|
||||
board.MinoMoveDown()
|
||||
view.RefreshScreen()
|
||||
}
|
||||
|
||||
// AddDeleteLines adds deleted lines to score
|
||||
func (engine *Engine) AddDeleteLines(lines int) {
|
||||
engine.deleteLines += lines
|
||||
if engine.deleteLines > 999999 {
|
||||
|
@ -175,6 +186,7 @@ func (engine *Engine) AddDeleteLines(lines int) {
|
|||
}
|
||||
}
|
||||
|
||||
// AddScore adds to score
|
||||
func (engine *Engine) AddScore(add int) {
|
||||
engine.score += add
|
||||
if engine.score > 9999999 {
|
||||
|
@ -182,6 +194,7 @@ func (engine *Engine) AddScore(add int) {
|
|||
}
|
||||
}
|
||||
|
||||
// LevelUp goes up a level
|
||||
func (engine *Engine) LevelUp() {
|
||||
if engine.level >= 30 {
|
||||
return
|
||||
|
@ -205,6 +218,7 @@ func (engine *Engine) LevelUp() {
|
|||
}
|
||||
}
|
||||
|
||||
// GameOver pauses engine and sets to game over
|
||||
func (engine *Engine) GameOver() {
|
||||
logger.Println("Engine GameOver start")
|
||||
|
||||
|
@ -228,12 +242,14 @@ loop:
|
|||
logger.Println("Engine GameOver end")
|
||||
}
|
||||
|
||||
// EnabledAi enables the AI
|
||||
func (engine *Engine) EnabledAi() {
|
||||
engine.aiEnabled = true
|
||||
go engine.ai.GetBestQueue()
|
||||
engine.aiTimer.Reset(engine.tickTime / 6)
|
||||
}
|
||||
|
||||
// DisableAi disables the AI
|
||||
func (engine *Engine) DisableAi() {
|
||||
engine.aiEnabled = false
|
||||
if !engine.aiTimer.Stop() {
|
||||
|
|
23
globals.go
23
globals.go
|
@ -13,16 +13,23 @@ const (
|
|||
boardYOffset = 2
|
||||
rankingFileName = "/tetris.db"
|
||||
|
||||
// MinoPreview is for the preview mino
|
||||
MinoPreview MinoType = iota
|
||||
MinoCurrent = iota
|
||||
MinoDrop = iota
|
||||
// MinoCurrent is for the current mino
|
||||
MinoCurrent = iota
|
||||
// MinoDrop is for the drop mino
|
||||
MinoDrop = iota
|
||||
)
|
||||
|
||||
type (
|
||||
MinoType int
|
||||
MinoBlocks [][]termbox.Attribute
|
||||
// MinoType is the type of mino
|
||||
MinoType int
|
||||
// MinoBlocks is the blocks of the mino
|
||||
MinoBlocks [][]termbox.Attribute
|
||||
// MinoRotation is the rotation of the mino
|
||||
MinoRotation [4]MinoBlocks
|
||||
|
||||
// Mino is a mino
|
||||
Mino struct {
|
||||
x int
|
||||
y int
|
||||
|
@ -31,12 +38,14 @@ type (
|
|||
minoRotation MinoRotation
|
||||
}
|
||||
|
||||
// Minos is a bag of minos
|
||||
Minos struct {
|
||||
minoBag [7]MinoRotation
|
||||
bagRand []int
|
||||
bagIndex int
|
||||
}
|
||||
|
||||
// Board is the Tetris board
|
||||
Board struct {
|
||||
boardsIndex int
|
||||
width int
|
||||
|
@ -48,30 +57,36 @@ type (
|
|||
dropDistance int
|
||||
}
|
||||
|
||||
// Boards holds all the premade boards
|
||||
Boards struct {
|
||||
colors [][]termbox.Attribute
|
||||
rotation [][]int
|
||||
}
|
||||
|
||||
// KeyInput is the key input engine
|
||||
KeyInput struct {
|
||||
stopped bool
|
||||
chanStop chan struct{}
|
||||
chanKeyInput chan *termbox.Event
|
||||
}
|
||||
|
||||
// View is the display engine
|
||||
View struct {
|
||||
}
|
||||
|
||||
// Ai is the AI engine
|
||||
Ai struct {
|
||||
queue *[]rune
|
||||
newQueue *[]rune
|
||||
index int
|
||||
}
|
||||
|
||||
// Ranking holds the ranking scores
|
||||
Ranking struct {
|
||||
scores []uint64
|
||||
}
|
||||
|
||||
// Engine is the Tetirs game engine
|
||||
Engine struct {
|
||||
stopped bool
|
||||
chanStop chan struct{}
|
||||
|
|
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewKeyInput creates a new KeyInput
|
||||
func NewKeyInput() *KeyInput {
|
||||
return &KeyInput{
|
||||
chanStop: make(chan struct{}, 1),
|
||||
|
@ -13,6 +14,7 @@ func NewKeyInput() *KeyInput {
|
|||
}
|
||||
}
|
||||
|
||||
// Run starts the KeyInput engine
|
||||
func (keyInput *KeyInput) Run() {
|
||||
logger.Println("KeyInput Run start")
|
||||
|
||||
|
@ -36,6 +38,7 @@ loop:
|
|||
logger.Println("KeyInput Run end")
|
||||
}
|
||||
|
||||
// ProcessEvent process the key input event
|
||||
func (keyInput *KeyInput) ProcessEvent(event *termbox.Event) {
|
||||
if event.Key == termbox.KeyCtrlI {
|
||||
// Ctrl l (lower case L) to log stack trace
|
||||
|
|
18
mino.go
18
mino.go
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewMino creates a new Mino
|
||||
func NewMino() *Mino {
|
||||
minoRotation := minos.minoBag[minos.bagRand[minos.bagIndex]]
|
||||
minos.bagIndex++
|
||||
|
@ -22,32 +23,38 @@ func NewMino() *Mino {
|
|||
return mino
|
||||
}
|
||||
|
||||
// CloneMoveLeft creates copy of the mino and moves it left
|
||||
func (mino *Mino) CloneMoveLeft() *Mino {
|
||||
newMino := *mino
|
||||
newMino.MoveLeft()
|
||||
return &newMino
|
||||
}
|
||||
|
||||
// MoveLeft moves the mino left
|
||||
func (mino *Mino) MoveLeft() {
|
||||
mino.x--
|
||||
}
|
||||
|
||||
// CloneMoveRight creates copy of the mino and moves it right
|
||||
func (mino *Mino) CloneMoveRight() *Mino {
|
||||
newMino := *mino
|
||||
newMino.MoveRight()
|
||||
return &newMino
|
||||
}
|
||||
|
||||
// MoveRight moves the mino right
|
||||
func (mino *Mino) MoveRight() {
|
||||
mino.x++
|
||||
}
|
||||
|
||||
// CloneRotateRight creates copy of the mino and rotates it right
|
||||
func (mino *Mino) CloneRotateRight() *Mino {
|
||||
newMino := *mino
|
||||
newMino.RotateRight()
|
||||
return &newMino
|
||||
}
|
||||
|
||||
// RotateRight rotates the mino right
|
||||
func (mino *Mino) RotateRight() {
|
||||
mino.rotation++
|
||||
if mino.rotation > 3 {
|
||||
|
@ -55,12 +62,14 @@ func (mino *Mino) RotateRight() {
|
|||
}
|
||||
}
|
||||
|
||||
// CloneRotateLeft creates copy of the mino and rotates it left
|
||||
func (mino *Mino) CloneRotateLeft() *Mino {
|
||||
newMino := *mino
|
||||
newMino.RotateLeft()
|
||||
return &newMino
|
||||
}
|
||||
|
||||
// RotateLeft rotates the mino left
|
||||
func (mino *Mino) RotateLeft() {
|
||||
if mino.rotation < 1 {
|
||||
mino.rotation = 3
|
||||
|
@ -69,20 +78,24 @@ func (mino *Mino) RotateLeft() {
|
|||
mino.rotation--
|
||||
}
|
||||
|
||||
// CloneMoveDown creates copy of the mino and moves it down
|
||||
func (mino *Mino) CloneMoveDown() *Mino {
|
||||
newMino := *mino
|
||||
newMino.MoveDown()
|
||||
return &newMino
|
||||
}
|
||||
|
||||
// MoveDown moves the mino down
|
||||
func (mino *Mino) MoveDown() {
|
||||
mino.y++
|
||||
}
|
||||
|
||||
// MoveUp moves the mino up
|
||||
func (mino *Mino) MoveUp() {
|
||||
mino.y--
|
||||
}
|
||||
|
||||
// ValidLocation check if the mino is in a valid location
|
||||
func (mino *Mino) ValidLocation(mustBeOnBoard bool) bool {
|
||||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
|
@ -97,6 +110,7 @@ func (mino *Mino) ValidLocation(mustBeOnBoard bool) bool {
|
|||
return true
|
||||
}
|
||||
|
||||
// SetOnBoard attaches mino to the board
|
||||
func (mino *Mino) SetOnBoard() {
|
||||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
|
@ -108,6 +122,7 @@ func (mino *Mino) SetOnBoard() {
|
|||
}
|
||||
}
|
||||
|
||||
// DrawMino draws the mino on the board
|
||||
func (mino *Mino) DrawMino(minoType MinoType) {
|
||||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
|
@ -128,6 +143,7 @@ func (mino *Mino) DrawMino(minoType MinoType) {
|
|||
}
|
||||
}
|
||||
|
||||
// minoOverlap check if a mino overlaps anohter mino
|
||||
func (mino *Mino) minoOverlap(mino1 *Mino) bool {
|
||||
minoBlocks := mino.minoRotation[mino.rotation]
|
||||
for i := 0; i < mino.length; i++ {
|
||||
|
@ -142,6 +158,7 @@ func (mino *Mino) minoOverlap(mino1 *Mino) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// isMinoAtLocation check if a mino block is in a location
|
||||
func (mino *Mino) isMinoAtLocation(x int, y int) bool {
|
||||
xIndex := x - mino.x
|
||||
yIndex := y - mino.y
|
||||
|
@ -157,6 +174,7 @@ func (mino *Mino) isMinoAtLocation(x int, y int) bool {
|
|||
return false
|
||||
}
|
||||
|
||||
// getMinoColorAtLocation gets the mino color at a location
|
||||
func (mino *Mino) getMinoColorAtLocation(x int, y int) termbox.Attribute {
|
||||
xIndex := x - mino.x
|
||||
yIndex := y - mino.y
|
||||
|
|
2
minos.go
2
minos.go
|
@ -6,6 +6,7 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewMinos creates the minos and minoBag
|
||||
func NewMinos() {
|
||||
minoI := MinoBlocks{
|
||||
[]termbox.Attribute{blankColor, termbox.ColorCyan, blankColor, blankColor},
|
||||
|
@ -85,6 +86,7 @@ func NewMinos() {
|
|||
}
|
||||
}
|
||||
|
||||
// minosCloneRotateRight clones a mino and rotates the mino to the right
|
||||
func minosCloneRotateRight(minoBlocks MinoBlocks) MinoBlocks {
|
||||
length := len(minoBlocks)
|
||||
newMinoBlocks := make(MinoBlocks, length, length)
|
||||
|
|
|
@ -8,6 +8,7 @@ import (
|
|||
"strings"
|
||||
)
|
||||
|
||||
// NewRanking create a new ranking
|
||||
func NewRanking() *Ranking {
|
||||
ranking := &Ranking{
|
||||
scores: make([]uint64, 9),
|
||||
|
@ -41,6 +42,7 @@ func NewRanking() *Ranking {
|
|||
return ranking
|
||||
}
|
||||
|
||||
// Save saves the rankings to a file
|
||||
func (ranking *Ranking) Save() {
|
||||
var buffer bytes.Buffer
|
||||
|
||||
|
@ -54,6 +56,7 @@ func (ranking *Ranking) Save() {
|
|||
ioutil.WriteFile(baseDir+rankingFileName, buffer.Bytes(), 0644)
|
||||
}
|
||||
|
||||
// InsertScore inserts a score into the rankings
|
||||
func (ranking *Ranking) InsertScore(newScore uint64) {
|
||||
for index, score := range ranking.scores {
|
||||
if newScore > score {
|
||||
|
@ -64,6 +67,7 @@ func (ranking *Ranking) InsertScore(newScore uint64) {
|
|||
}
|
||||
}
|
||||
|
||||
// slideScores slides the scores down to make room for a new score
|
||||
func (ranking *Ranking) slideScores(index int) {
|
||||
for i := len(ranking.scores) - 1; i > index; i-- {
|
||||
ranking.scores[i] = ranking.scores[i-1]
|
||||
|
|
15
view.go
15
view.go
|
@ -8,6 +8,7 @@ import (
|
|||
"github.com/nsf/termbox-go"
|
||||
)
|
||||
|
||||
// NewView creates a new view
|
||||
func NewView() {
|
||||
err := termbox.Init()
|
||||
if err != nil {
|
||||
|
@ -18,6 +19,7 @@ func NewView() {
|
|||
view = &View{}
|
||||
}
|
||||
|
||||
// Stop stops the view
|
||||
func (view *View) Stop() {
|
||||
logger.Println("View Stop start")
|
||||
|
||||
|
@ -26,6 +28,7 @@ func (view *View) Stop() {
|
|||
logger.Println("View Stop end")
|
||||
}
|
||||
|
||||
// RefreshScreen refreshs the updated view to the screen
|
||||
func (view *View) RefreshScreen() {
|
||||
termbox.Clear(termbox.ColorDefault, termbox.ColorDefault)
|
||||
|
||||
|
@ -50,6 +53,7 @@ func (view *View) RefreshScreen() {
|
|||
termbox.Flush()
|
||||
}
|
||||
|
||||
// drawBackground draws the background
|
||||
func (view *View) drawBackground() {
|
||||
// playing board
|
||||
xOffset := boardXOffset
|
||||
|
@ -85,6 +89,7 @@ func (view *View) drawBackground() {
|
|||
|
||||
}
|
||||
|
||||
// drawTexts draws the text
|
||||
func (view *View) drawTexts() {
|
||||
xOffset := boardXOffset + board.width*2 + 8
|
||||
yOffset := boardYOffset + 7
|
||||
|
@ -124,6 +129,7 @@ func (view *View) drawTexts() {
|
|||
view.drawText(xOffset, yOffset, "q - quit", termbox.ColorWhite, termbox.ColorBlack)
|
||||
}
|
||||
|
||||
// DrawPreviewMinoBlock draws the preview mino
|
||||
func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, rotation int, length int) {
|
||||
var char1 rune
|
||||
var char2 rune
|
||||
|
@ -139,6 +145,7 @@ func (view *View) DrawPreviewMinoBlock(x int, y int, color termbox.Attribute, ro
|
|||
termbox.SetCell(xOffset+1, y+boardYOffset+2, char2, color, color^termbox.AttrBold)
|
||||
}
|
||||
|
||||
// DrawBlock draws a block
|
||||
func (view *View) DrawBlock(x int, y int, color termbox.Attribute, rotation int) {
|
||||
var char1 rune
|
||||
var char2 rune
|
||||
|
@ -159,11 +166,13 @@ func (view *View) DrawBlock(x int, y int, color termbox.Attribute, rotation int)
|
|||
}
|
||||
}
|
||||
|
||||
// drawPaused draws Paused
|
||||
func (view *View) drawPaused() {
|
||||
yOffset := (board.height+1)/2 + boardYOffset
|
||||
view.drawTextCenter(yOffset, "Paused", termbox.ColorWhite, termbox.ColorBlack)
|
||||
}
|
||||
|
||||
// drawGameOver draws GAME OVER
|
||||
func (view *View) drawGameOver() {
|
||||
yOffset := boardYOffset + 2
|
||||
view.drawTextCenter(yOffset, " GAME OVER", termbox.ColorWhite, termbox.ColorBlack)
|
||||
|
@ -181,6 +190,7 @@ func (view *View) drawGameOver() {
|
|||
view.drawTextCenter(yOffset, "→next board", termbox.ColorWhite, termbox.ColorBlack)
|
||||
}
|
||||
|
||||
// drawRankingScores draws the ranking scores
|
||||
func (view *View) drawRankingScores() {
|
||||
yOffset := boardYOffset + 10
|
||||
for index, line := range engine.ranking.scores {
|
||||
|
@ -188,12 +198,14 @@ func (view *View) drawRankingScores() {
|
|||
}
|
||||
}
|
||||
|
||||
// drawText draws the provided text
|
||||
func (view *View) drawText(x int, y int, text string, fg termbox.Attribute, bg termbox.Attribute) {
|
||||
for index, char := range text {
|
||||
termbox.SetCell(x+index, y, rune(char), fg, bg)
|
||||
}
|
||||
}
|
||||
|
||||
// drawTextCenter draws text in the center of the board
|
||||
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 {
|
||||
|
@ -201,6 +213,7 @@ func (view *View) drawTextCenter(y int, text string, fg termbox.Attribute, bg te
|
|||
}
|
||||
}
|
||||
|
||||
// ShowDeleteAnimation draws the delete animation
|
||||
func (view *View) ShowDeleteAnimation(lines []int) {
|
||||
view.RefreshScreen()
|
||||
|
||||
|
@ -216,6 +229,7 @@ func (view *View) ShowDeleteAnimation(lines []int) {
|
|||
}
|
||||
}
|
||||
|
||||
// ShowGameOverAnimation draws one randomily picked gave over animation
|
||||
func (view *View) ShowGameOverAnimation() {
|
||||
logger.Println("View ShowGameOverAnimation start")
|
||||
|
||||
|
@ -283,6 +297,7 @@ func (view *View) ShowGameOverAnimation() {
|
|||
logger.Println("View ShowGameOverAnimation end")
|
||||
}
|
||||
|
||||
// colorizeLine changes the color of a line
|
||||
func (view *View) colorizeLine(y int, color termbox.Attribute) {
|
||||
for x := 0; x < board.width; x++ {
|
||||
termbox.SetCell(x*2+boardXOffset+2, y+boardYOffset+1, ' ', termbox.ColorDefault, color)
|
||||
|
|
Loading…
Reference in New Issue