2017-03-27 15:07:29 -05:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
|
|
|
"math/rand"
|
|
|
|
|
2019-12-01 15:03:27 -06:00
|
|
|
"github.com/gdamore/tcell"
|
2017-03-27 15:07:29 -05:00
|
|
|
)
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// NewMino creates a new Mino
|
2017-03-27 15:07:29 -05:00
|
|
|
func NewMino() *Mino {
|
2018-02-14 14:57:02 -06:00
|
|
|
minoRotation := minos.minoBag[minos.bagRand[minos.bagIndex]]
|
|
|
|
minos.bagIndex++
|
|
|
|
if minos.bagIndex > 6 {
|
|
|
|
minos.bagIndex = 0
|
|
|
|
minos.bagRand = rand.Perm(7)
|
2017-03-27 15:07:29 -05:00
|
|
|
}
|
|
|
|
mino := &Mino{
|
|
|
|
minoRotation: minoRotation,
|
|
|
|
length: len(minoRotation[0]),
|
|
|
|
}
|
2018-02-14 14:57:02 -06:00
|
|
|
mino.x = board.width/2 - (mino.length+1)/2
|
2017-03-27 15:07:29 -05:00
|
|
|
mino.y = -1
|
|
|
|
return mino
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// CloneMoveLeft creates copy of the mino and moves it left
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) CloneMoveLeft() *Mino {
|
|
|
|
newMino := *mino
|
|
|
|
newMino.MoveLeft()
|
|
|
|
return &newMino
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// MoveLeft moves the mino left
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) MoveLeft() {
|
|
|
|
mino.x--
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// CloneMoveRight creates copy of the mino and moves it right
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) CloneMoveRight() *Mino {
|
|
|
|
newMino := *mino
|
|
|
|
newMino.MoveRight()
|
|
|
|
return &newMino
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// MoveRight moves the mino right
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) MoveRight() {
|
|
|
|
mino.x++
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// CloneRotateRight creates copy of the mino and rotates it right
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) CloneRotateRight() *Mino {
|
|
|
|
newMino := *mino
|
|
|
|
newMino.RotateRight()
|
|
|
|
return &newMino
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// RotateRight rotates the mino right
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) RotateRight() {
|
|
|
|
mino.rotation++
|
|
|
|
if mino.rotation > 3 {
|
|
|
|
mino.rotation = 0
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// CloneRotateLeft creates copy of the mino and rotates it left
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) CloneRotateLeft() *Mino {
|
|
|
|
newMino := *mino
|
|
|
|
newMino.RotateLeft()
|
|
|
|
return &newMino
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// RotateLeft rotates the mino left
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) RotateLeft() {
|
|
|
|
if mino.rotation < 1 {
|
|
|
|
mino.rotation = 3
|
|
|
|
return
|
|
|
|
}
|
|
|
|
mino.rotation--
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// CloneMoveDown creates copy of the mino and moves it down
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) CloneMoveDown() *Mino {
|
|
|
|
newMino := *mino
|
|
|
|
newMino.MoveDown()
|
|
|
|
return &newMino
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// MoveDown moves the mino down
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) MoveDown() {
|
|
|
|
mino.y++
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// MoveUp moves the mino up
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) MoveUp() {
|
|
|
|
mino.y--
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// ValidLocation check if the mino is in a valid location
|
2017-03-27 15:07:29 -05:00
|
|
|
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++ {
|
2019-12-01 15:03:27 -06:00
|
|
|
if minoBlocks[i][j] == colorBlank {
|
2019-01-14 18:11:46 -06:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if !board.ValidBlockLocation(mino.x+i, mino.y+j, mustBeOnBoard) {
|
|
|
|
return false
|
2017-03-27 15:07:29 -05:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// SetOnBoard attaches mino to the board
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) SetOnBoard() {
|
|
|
|
minoBlocks := mino.minoRotation[mino.rotation]
|
|
|
|
for i := 0; i < mino.length; i++ {
|
|
|
|
for j := 0; j < mino.length; j++ {
|
2019-12-01 15:03:27 -06:00
|
|
|
if minoBlocks[i][j] != colorBlank {
|
2017-03-27 15:07:29 -05:00
|
|
|
board.SetColor(mino.x+i, mino.y+j, minoBlocks[i][j], mino.rotation)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// DrawMino draws the mino on the board
|
2017-03-27 15:07:29 -05:00
|
|
|
func (mino *Mino) DrawMino(minoType MinoType) {
|
|
|
|
minoBlocks := mino.minoRotation[mino.rotation]
|
|
|
|
for i := 0; i < mino.length; i++ {
|
|
|
|
for j := 0; j < mino.length; j++ {
|
2019-12-01 15:03:27 -06:00
|
|
|
if minoBlocks[i][j] != colorBlank {
|
2017-03-27 15:07:29 -05:00
|
|
|
switch minoType {
|
|
|
|
case MinoPreview:
|
|
|
|
view.DrawPreviewMinoBlock(i, j, minoBlocks[i][j], mino.rotation, mino.length)
|
|
|
|
case MinoDrop:
|
2019-12-01 15:03:27 -06:00
|
|
|
view.DrawBlock(mino.x+i, mino.y+j, colorBlank, mino.rotation)
|
2017-03-27 15:07:29 -05:00
|
|
|
case MinoCurrent:
|
|
|
|
if ValidDisplayLocation(mino.x+i, mino.y+j) {
|
|
|
|
view.DrawBlock(mino.x+i, mino.y+j, minoBlocks[i][j], mino.rotation)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
2018-02-14 14:57:02 -06:00
|
|
|
|
2018-10-15 14:53:57 -05:00
|
|
|
// minoOverlap check if a mino overlaps another mino
|
2018-02-14 14:57:02 -06:00
|
|
|
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++ {
|
2019-12-01 15:03:27 -06:00
|
|
|
if minoBlocks[i][j] == colorBlank {
|
2019-01-14 18:11:46 -06:00
|
|
|
continue
|
|
|
|
}
|
|
|
|
if mino1.isMinoAtLocation(mino.x+i, mino.y+j) {
|
|
|
|
return true
|
2018-02-14 14:57:02 -06:00
|
|
|
}
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// isMinoAtLocation check if a mino block is in a location
|
2018-02-14 14:57:02 -06:00
|
|
|
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
|
|
|
|
}
|
|
|
|
|
2019-12-01 15:03:27 -06:00
|
|
|
if mino.minoRotation[mino.rotation][xIndex][yIndex] != colorBlank {
|
2018-02-14 14:57:02 -06:00
|
|
|
return true
|
|
|
|
}
|
|
|
|
|
|
|
|
return false
|
|
|
|
}
|
|
|
|
|
2018-10-02 20:21:08 -05:00
|
|
|
// getMinoColorAtLocation gets the mino color at a location
|
2019-12-01 15:03:27 -06:00
|
|
|
func (mino *Mino) getMinoColorAtLocation(x int, y int) tcell.Color {
|
2018-02-14 14:57:02 -06:00
|
|
|
xIndex := x - mino.x
|
|
|
|
yIndex := y - mino.y
|
|
|
|
if xIndex < 0 || xIndex >= mino.length || yIndex < 0 || yIndex >= mino.length {
|
2019-12-01 15:03:27 -06:00
|
|
|
return colorBlank
|
2018-02-14 14:57:02 -06:00
|
|
|
}
|
|
|
|
|
|
|
|
minoBlocks := mino.minoRotation[mino.rotation]
|
|
|
|
return minoBlocks[xIndex][yIndex]
|
|
|
|
}
|