package tetris import "github.com/charmbracelet/lipgloss" // pieceType identifies a tetromino (0–6). type pieceType int const ( pieceI pieceType = iota pieceO pieceT pieceS pieceZ pieceJ pieceL ) const numPieceTypes = 7 // Standard Tetris colors. var pieceColors = [numPieceTypes]lipgloss.Color{ lipgloss.Color("#00FFFF"), // I — cyan lipgloss.Color("#FFFF00"), // O — yellow lipgloss.Color("#AA00FF"), // T — purple lipgloss.Color("#00FF00"), // S — green lipgloss.Color("#FF0000"), // Z — red lipgloss.Color("#0000FF"), // J — blue lipgloss.Color("#FF8800"), // L — orange } // Each piece has 4 rotations, each rotation is a list of (row, col) offsets // relative to the piece origin. type rotation [4][2]int var pieces = [numPieceTypes][4]rotation{ // I { {[2]int{0, 0}, [2]int{0, 1}, [2]int{0, 2}, [2]int{0, 3}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{2, 0}, [2]int{3, 0}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{0, 2}, [2]int{0, 3}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{2, 0}, [2]int{3, 0}}, }, // O { {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}}, }, // T { {[2]int{0, 0}, [2]int{0, 1}, [2]int{0, 2}, [2]int{1, 1}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{2, 0}, [2]int{1, 1}}, {[2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}, [2]int{1, 2}}, {[2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}, [2]int{2, 1}}, }, // S { {[2]int{0, 1}, [2]int{0, 2}, [2]int{1, 0}, [2]int{1, 1}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{1, 1}, [2]int{2, 1}}, {[2]int{0, 1}, [2]int{0, 2}, [2]int{1, 0}, [2]int{1, 1}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{1, 1}, [2]int{2, 1}}, }, // Z { {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 1}, [2]int{1, 2}}, {[2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}, [2]int{2, 0}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 1}, [2]int{1, 2}}, {[2]int{0, 1}, [2]int{1, 0}, [2]int{1, 1}, [2]int{2, 0}}, }, // J { {[2]int{0, 0}, [2]int{1, 0}, [2]int{1, 1}, [2]int{1, 2}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 0}, [2]int{2, 0}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{0, 2}, [2]int{1, 2}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{2, 0}, [2]int{2, 1}}, }, // L { {[2]int{0, 2}, [2]int{1, 0}, [2]int{1, 1}, [2]int{1, 2}}, {[2]int{0, 0}, [2]int{1, 0}, [2]int{2, 0}, [2]int{2, 1}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{0, 2}, [2]int{1, 0}}, {[2]int{0, 0}, [2]int{0, 1}, [2]int{1, 1}, [2]int{2, 1}}, }, } // spawnCol returns the starting column for a piece, centering it on the board. func spawnCol(pt pieceType, rot int) int { shape := pieces[pt][rot] minC, maxC := shape[0][1], shape[0][1] for _, off := range shape { if off[1] < minC { minC = off[1] } if off[1] > maxC { maxC = off[1] } } width := maxC - minC + 1 return (boardCols - width) / 2 }