Optimize matrix data model
This commit is contained in:
parent
e6a3c0527c
commit
f853512332
10 changed files with 111 additions and 143 deletions
|
@ -273,9 +273,11 @@ func renderPlayerGUI() {
|
|||
|
||||
player.Preview.Clear()
|
||||
|
||||
err := player.Preview.Add(p, p.Solid, mino.Point{0, 0}, false)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to render preview matrix: %+v", err)
|
||||
if !player.Matrix.GameOver {
|
||||
err := player.Preview.Add(p, p.Solid, mino.Point{0, 0}, false)
|
||||
if err != nil {
|
||||
log.Fatalf("failed to render preview matrix: failed to add ghost piece: %+v", err)
|
||||
}
|
||||
}
|
||||
|
||||
m.Lock()
|
||||
|
@ -453,9 +455,9 @@ func renderMatrixes(mx []*mino.Matrix) {
|
|||
|
||||
for x := 0; x < m.W; x++ {
|
||||
renderBuffer.WriteRune('[')
|
||||
renderBuffer.Write(m.Block(x, y-1).Color())
|
||||
renderBuffer.Write(mino.Colors[m.Block(x, y-1)])
|
||||
renderBuffer.WriteRune(':')
|
||||
renderBuffer.Write(m.Block(x, y).Color())
|
||||
renderBuffer.Write(mino.Colors[m.Block(x, y)])
|
||||
renderBuffer.WriteRune(']')
|
||||
renderBuffer.WriteRune('▄')
|
||||
renderBuffer.Write([]byte("[-:-]"))
|
||||
|
@ -466,7 +468,7 @@ func renderMatrixes(mx []*mino.Matrix) {
|
|||
}
|
||||
}
|
||||
|
||||
if y != 0 || mt != mino.MatrixCustom {
|
||||
if y > 1 || mt != mino.MatrixCustom {
|
||||
renderBuffer.WriteRune('\n')
|
||||
}
|
||||
}
|
||||
|
@ -488,7 +490,7 @@ func renderMatrixes(mx []*mino.Matrix) {
|
|||
|
||||
for x := 0; x < m.W; x++ {
|
||||
renderBuffer.WriteRune('[')
|
||||
renderBuffer.Write(m.Block(x, y).Color())
|
||||
renderBuffer.Write(mino.Colors[m.Block(x, y)])
|
||||
renderBuffer.WriteRune(']')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.WriteRune('█')
|
||||
|
@ -525,7 +527,7 @@ func renderMatrixes(mx []*mino.Matrix) {
|
|||
|
||||
for x := 0; x < m.W; x++ {
|
||||
renderBuffer.WriteRune('[')
|
||||
renderBuffer.Write(m.Block(x, y).Color())
|
||||
renderBuffer.Write(mino.Colors[m.Block(x, y)])
|
||||
renderBuffer.WriteRune(']')
|
||||
renderBuffer.WriteRune('█')
|
||||
renderBuffer.WriteRune('█')
|
||||
|
|
|
@ -88,10 +88,17 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
piece *mino.Piece
|
||||
addToRight bool
|
||||
i int
|
||||
offset int
|
||||
)
|
||||
for y := 0; y < 11; y++ {
|
||||
for x := 0; x < 4; x++ {
|
||||
piece = mino.NewPiece(minos[i], mino.Point{(x * 5) + 2, (y * 5)})
|
||||
if !addToRight {
|
||||
offset = 3
|
||||
} else {
|
||||
offset = 2
|
||||
}
|
||||
|
||||
piece = mino.NewPiece(minos[i], mino.Point{(x * 5) + offset, (y * 5)})
|
||||
|
||||
i++
|
||||
if i == len(minos) {
|
||||
|
@ -137,22 +144,23 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
buttonC = tview.NewButton("C")
|
||||
buttonLabelC = tview.NewTextView().SetTextAlign(tview.AlignCenter)
|
||||
|
||||
titleNameGrid := tview.NewGrid().SetRows(3).
|
||||
titleNameGrid := tview.NewGrid().SetRows(3, 2).
|
||||
AddItem(titleName, 0, 0, 1, 1, 0, 0, false).
|
||||
AddItem(tview.NewTextView().SetText(SubTitle+game.Version), 1, 0, 1, 1, 0, 0, false)
|
||||
|
||||
titleGrid = tview.NewGrid().
|
||||
SetRows(5, 3, 3, 3, 3, 3, 4).
|
||||
SetRows(5, 3, 3, 3, 3, 3, 3).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 7, 1, 0, 0, false).
|
||||
AddItem(titleL, 0, 0, 8, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 7, 1, 0, 0, false).
|
||||
AddItem(titleR, 0, 2, 8, 1, 0, 0, false).
|
||||
AddItem(buttonA, 1, 1, 1, 1, 0, 0, false).
|
||||
AddItem(buttonLabelA, 2, 1, 1, 1, 0, 0, false).
|
||||
AddItem(buttonB, 3, 1, 1, 1, 0, 0, false).
|
||||
AddItem(buttonLabelB, 4, 1, 1, 1, 0, 0, false).
|
||||
AddItem(buttonC, 5, 1, 1, 1, 0, 0, false).
|
||||
AddItem(buttonLabelC, 6, 1, 1, 1, 0, 0, false)
|
||||
AddItem(buttonLabelC, 6, 1, 1, 1, 0, 0, false).
|
||||
AddItem(pad, 7, 1, 1, 1, 0, 0, false)
|
||||
|
||||
gameListView = tview.NewTextView().SetDynamicColors(true)
|
||||
|
||||
|
@ -167,7 +175,7 @@ func initGUI(skipTitle bool) (*tview.Application, error) {
|
|||
gameListHeader = tview.NewTextView().SetTextAlign(tview.AlignCenter)
|
||||
|
||||
gameListGrid = tview.NewGrid().
|
||||
SetRows(5, 1, -1, 1, 3).
|
||||
SetRows(5, 1, 14, 1, 3).
|
||||
SetColumns(-1, 34, -1).
|
||||
AddItem(titleL, 0, 0, 5, 1, 0, 0, false).
|
||||
AddItem(titleNameGrid, 0, 1, 1, 1, 0, 0, false).
|
||||
|
@ -412,7 +420,7 @@ func newTitleMatrixName() *mino.Matrix {
|
|||
}
|
||||
}()
|
||||
|
||||
m := mino.NewMatrix(36, 5, 0, 1, ev, draw, mino.MatrixCustom)
|
||||
m := mino.NewMatrix(36, 6, 0, 1, ev, draw, mino.MatrixCustom)
|
||||
|
||||
centerStart := (m.W / 2) - 17
|
||||
|
||||
|
|
|
@ -19,7 +19,9 @@ func TestRenderMatrix(t *testing.T) {
|
|||
|
||||
m.AddTestBlocks()
|
||||
|
||||
renderPlayerMatrix(m)
|
||||
mx := []*mino.Matrix{m}
|
||||
|
||||
renderMatrixes(mx)
|
||||
}
|
||||
|
||||
func BenchmarkRenderStandardMatrix(b *testing.B) {
|
||||
|
@ -35,11 +37,13 @@ func BenchmarkRenderStandardMatrix(b *testing.B) {
|
|||
|
||||
m.AddTestBlocks()
|
||||
|
||||
mx := []*mino.Matrix{m}
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
renderPlayerMatrix(m)
|
||||
renderMatrixes(mx)
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -56,11 +60,13 @@ func BenchmarkRenderLargeMatrix(b *testing.B) {
|
|||
|
||||
m.AddTestBlocks()
|
||||
|
||||
mx := []*mino.Matrix{m}
|
||||
|
||||
b.ReportAllocs()
|
||||
b.ResetTimer()
|
||||
|
||||
for i := 0; i < b.N; i++ {
|
||||
renderPlayerMatrix(m)
|
||||
renderMatrixes(mx)
|
||||
}
|
||||
|
||||
blockSize = 1
|
||||
|
|
|
@ -338,7 +338,7 @@ func renderGameList() {
|
|||
gameListView.Write(renderRTee)
|
||||
gameListView.Write([]byte("\n"))
|
||||
|
||||
h := 9
|
||||
h := 10
|
||||
|
||||
for i, g := range gameList {
|
||||
p := strconv.Itoa(g.Players)
|
||||
|
|
|
@ -340,10 +340,7 @@ func (s *Server) handleGameCommands(pl *Player, g *Game) {
|
|||
|
||||
switch p := e.(type) {
|
||||
case *GameCommandDisconnect:
|
||||
log.Printf("%+v", g.Players)
|
||||
if _, ok := g.Players[p.SourcePlayer]; ok {
|
||||
g.RemovePlayerL(p.SourcePlayer)
|
||||
}
|
||||
g.RemovePlayerL(p.SourcePlayer)
|
||||
case *GameCommandMessage:
|
||||
if player, ok := g.Players[p.SourcePlayer]; ok {
|
||||
s.Logf("<%s> %s", player.Name, p.Message)
|
||||
|
|
|
@ -22,8 +22,8 @@ func TestBag(t *testing.T) {
|
|||
b, err := NewBag(0, minos, 10)
|
||||
if err != nil {
|
||||
t.Errorf("failed to create bag for rank %d: %s", d.Rank, err)
|
||||
|
||||
}
|
||||
|
||||
taken := make(map[string]int)
|
||||
for i := 1; i < 4; i++ {
|
||||
for i := 0; i < len(d.Minos); i++ {
|
||||
|
|
|
@ -1,5 +1,26 @@
|
|||
package mino
|
||||
|
||||
// Dark color ghosts are 60% original overlaid #777777
|
||||
// Light color ghosts are 40% original overlaid #888888
|
||||
var Colors = [][]byte{
|
||||
BlockNone: []byte("#000000"),
|
||||
BlockGarbage: []byte("#999999"),
|
||||
BlockGhostBlue: []byte("#6e7bc3"),
|
||||
BlockGhostCyan: []byte("#6bbaba"),
|
||||
BlockGhostRed: []byte("#ba6b6b"),
|
||||
BlockGhostYellow: []byte("#b1b16b"),
|
||||
BlockGhostMagenta: []byte("#a16ba8"),
|
||||
BlockGhostGreen: []byte("#6bb76b"),
|
||||
BlockGhostOrange: []byte("#c3806c"),
|
||||
BlockSolidBlue: []byte("#2864ff"),
|
||||
BlockSolidCyan: []byte("#00eeee"),
|
||||
BlockSolidRed: []byte("#ee0000"),
|
||||
BlockSolidYellow: []byte("#dddd00"),
|
||||
BlockSolidMagenta: []byte("#c000cc"),
|
||||
BlockSolidGreen: []byte("#00e900"),
|
||||
BlockSolidOrange: []byte("#ff7308"),
|
||||
}
|
||||
|
||||
type Block int
|
||||
|
||||
func (b Block) String() string {
|
||||
|
@ -19,48 +40,6 @@ func (b Block) Rune() rune {
|
|||
}
|
||||
}
|
||||
|
||||
func (b Block) Color() []byte {
|
||||
// Dark color ghosts are 60% original overlaid #777777
|
||||
// Light color ghosts are 40% original overlaid #888888
|
||||
|
||||
switch b {
|
||||
case BlockNone:
|
||||
return []byte("#000000")
|
||||
case BlockGhostBlue:
|
||||
return []byte("#6e7bc3")
|
||||
case BlockSolidBlue:
|
||||
return []byte("#2864ff")
|
||||
case BlockGhostCyan:
|
||||
return []byte("#6bbaba")
|
||||
case BlockSolidCyan:
|
||||
return []byte("#00eeee")
|
||||
case BlockGhostRed:
|
||||
return []byte("#ba6b6b")
|
||||
case BlockSolidRed:
|
||||
return []byte("#ee0000")
|
||||
case BlockGhostYellow:
|
||||
return []byte("#b1b16b")
|
||||
case BlockSolidYellow:
|
||||
return []byte("#dddd00")
|
||||
case BlockGhostMagenta:
|
||||
return []byte("#a16ba8")
|
||||
case BlockSolidMagenta:
|
||||
return []byte("#c000cc")
|
||||
case BlockGhostGreen:
|
||||
return []byte("#6bb76b")
|
||||
case BlockSolidGreen:
|
||||
return []byte("#00e900")
|
||||
case BlockGhostOrange:
|
||||
return []byte("#c3806c")
|
||||
case BlockSolidOrange:
|
||||
return []byte("#ff7308")
|
||||
case BlockGarbage:
|
||||
return []byte("#999999")
|
||||
default:
|
||||
return []byte("#ffffff")
|
||||
}
|
||||
}
|
||||
|
||||
const (
|
||||
BlockNone Block = iota
|
||||
BlockGarbage
|
||||
|
|
|
@ -30,8 +30,8 @@ type Matrix struct {
|
|||
H int `json:"-"` // Height
|
||||
B int `json:"-"` // Buffer height
|
||||
|
||||
M map[int]Block // Matrix
|
||||
O map[int]Block `json:"-"` // Overlay
|
||||
M []Block // Matrix
|
||||
O []Block `json:"-"` // Overlay
|
||||
|
||||
Bag *Bag `json:"-"`
|
||||
P *Piece
|
||||
|
@ -66,9 +66,17 @@ func I(x int, y int, w int) int {
|
|||
}
|
||||
|
||||
func NewMatrix(w int, h int, b int, players int, event chan<- interface{}, draw chan event.DrawObject, t MatrixType) *Matrix {
|
||||
m := Matrix{W: w, H: h, B: b, M: make(map[int]Block), O: make(map[int]Block), Event: event, draw: draw, Type: t}
|
||||
|
||||
m.Move = make(chan int, 10)
|
||||
m := Matrix{
|
||||
Type: t,
|
||||
W: w,
|
||||
H: h,
|
||||
B: b,
|
||||
M: make([]Block, w*(h+b)),
|
||||
O: make([]Block, w*(h+b)),
|
||||
Event: event,
|
||||
Move: make(chan int, 10),
|
||||
draw: draw,
|
||||
}
|
||||
|
||||
return &m
|
||||
}
|
||||
|
@ -212,7 +220,7 @@ func (m *Matrix) add(mn *Piece, b Block, loc Point, overlay bool) error {
|
|||
x, y int
|
||||
index int
|
||||
|
||||
M map[int]Block
|
||||
M []Block
|
||||
)
|
||||
|
||||
if overlay {
|
||||
|
@ -368,8 +376,8 @@ func (m *Matrix) ClearOverlay() {
|
|||
}
|
||||
|
||||
func (m *Matrix) clearOverlay() {
|
||||
for i := range m.O {
|
||||
if m.O[i] == BlockNone {
|
||||
for i, b := range m.O {
|
||||
if b == BlockNone {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -396,8 +404,8 @@ func (m *Matrix) Clear() {
|
|||
m.Lock()
|
||||
defer m.Unlock()
|
||||
|
||||
for i := range m.M {
|
||||
if m.M[i] == BlockNone {
|
||||
for i, b := range m.M {
|
||||
if b == BlockNone {
|
||||
continue
|
||||
}
|
||||
|
||||
|
@ -447,29 +455,15 @@ func (m *Matrix) DrawPiecesL() {
|
|||
}
|
||||
}
|
||||
|
||||
func (m *Matrix) NewM() map[int]Block {
|
||||
newM := make(map[int]Block, len(m.M))
|
||||
for i, b := range m.M {
|
||||
newM[i] = b
|
||||
}
|
||||
|
||||
return newM
|
||||
}
|
||||
|
||||
func (m *Matrix) NewO() map[int]Block {
|
||||
newO := make(map[int]Block, len(m.O))
|
||||
for i, b := range m.O {
|
||||
newO[i] = b
|
||||
}
|
||||
|
||||
return newO
|
||||
}
|
||||
|
||||
func (m *Matrix) Block(x int, y int) Block {
|
||||
index := I(x, y, m.W)
|
||||
if index < 0 || index > m.W*(m.H+m.B) {
|
||||
return BlockGarbage
|
||||
}
|
||||
|
||||
// Return overlay block first
|
||||
if b, ok := m.O[index]; ok && b != BlockNone {
|
||||
b := m.O[index]
|
||||
if b != BlockNone {
|
||||
return b
|
||||
}
|
||||
|
||||
|
@ -519,13 +513,13 @@ func (m *Matrix) SetBlock(x int, y int, block Block, overlay bool) bool {
|
|||
index := I(x, y, m.W)
|
||||
|
||||
if overlay {
|
||||
if b, ok := m.O[index]; ok && b != BlockNone {
|
||||
if m.O[index] != BlockNone {
|
||||
return false
|
||||
}
|
||||
|
||||
m.O[index] = block
|
||||
} else {
|
||||
if b, ok := m.M[index]; ok && b != BlockNone {
|
||||
if m.M[index] != BlockNone {
|
||||
return false
|
||||
}
|
||||
|
||||
|
|
|
@ -59,21 +59,20 @@ func (m Mino) Equal(other Mino) bool {
|
|||
}
|
||||
|
||||
func (m Mino) String() string {
|
||||
newMino := make(Mino, len(m))
|
||||
copy(newMino, m)
|
||||
|
||||
sort.Sort(newMino)
|
||||
sort.Sort(m)
|
||||
|
||||
var b strings.Builder
|
||||
for i := range newMino {
|
||||
b.Grow(5*len(m) + (len(m) - 1))
|
||||
|
||||
for i := range m {
|
||||
if i > 0 {
|
||||
b.WriteRune(',')
|
||||
}
|
||||
|
||||
b.WriteRune('(')
|
||||
b.WriteString(strconv.Itoa(newMino[i].X))
|
||||
b.WriteString(strconv.Itoa(m[i].X))
|
||||
b.WriteRune(',')
|
||||
b.WriteString(strconv.Itoa(newMino[i].Y))
|
||||
b.WriteString(strconv.Itoa(m[i].Y))
|
||||
b.WriteRune(')')
|
||||
}
|
||||
|
||||
|
|
|
@ -20,58 +20,41 @@ type RotationOffsets []Point
|
|||
type PieceType int
|
||||
|
||||
const (
|
||||
PieceI PieceType = iota
|
||||
PieceUnknown PieceType = iota
|
||||
PieceI
|
||||
PieceO
|
||||
PieceJ
|
||||
PieceL
|
||||
PieceS
|
||||
PieceT
|
||||
PieceZ
|
||||
|
||||
PieceJLSTZ
|
||||
)
|
||||
|
||||
var AllRotationPivotsCW = map[PieceType][]Point{
|
||||
PieceI: {{1, -2}, {-1, 0}, {1, -1}, {0, 0}},
|
||||
PieceO: {{1, 0}, {1, 0}, {1, 0}, {1, 0}},
|
||||
PieceJ: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceL: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceS: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceT: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceZ: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
var AllRotationPivotsCW = [][]Point{
|
||||
PieceUnknown: {{0, 0}, {0, 0}, {0, 0}, {0, 0}},
|
||||
PieceI: {{1, -2}, {-1, 0}, {1, -1}, {0, 0}},
|
||||
PieceO: {{1, 0}, {1, 0}, {1, 0}, {1, 0}},
|
||||
PieceJ: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceL: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceS: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceT: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
PieceZ: {{1, -1}, {0, 0}, {1, 0}, {1, 0}},
|
||||
}
|
||||
|
||||
// IN PROGRESS
|
||||
var AllRotationPivotsCCW = map[PieceType][]Point{
|
||||
PieceI: {{2, 1}, {-1, 00}, {2, 2}, {1, 3}},
|
||||
PieceO: {{0, 1}, {0, 1}, {0, 1}, {0, 1}},
|
||||
PieceJ: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
PieceL: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
PieceS: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
PieceT: {{1, 1}, {0, 2}, {1, 2}, {1, 2}},
|
||||
PieceZ: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
var AllRotationPivotsCCW = [][]Point{
|
||||
PieceUnknown: {{0, 0}, {0, 0}, {0, 0}, {0, 0}},
|
||||
PieceI: {{2, 1}, {-1, 00}, {2, 2}, {1, 3}},
|
||||
PieceO: {{0, 1}, {0, 1}, {0, 1}, {0, 1}},
|
||||
PieceJ: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
PieceL: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
PieceS: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
PieceT: {{1, 1}, {0, 2}, {1, 2}, {1, 2}},
|
||||
PieceZ: {{1, 1}, {0, 0}, {1, 2}, {1, 2}},
|
||||
}
|
||||
|
||||
// AllRotationOffets is a list of all piece offsets. Each set includes offsets
|
||||
// for 0, R, L and 2 rotation states.
|
||||
// Rotation offsets
|
||||
var AllOffsets = []Point{{0, 0}, {-1, 0}, {1, 0}, {0, -1}, {-1, -1}, {1, -1}, {-2, 0}, {2, 0}}
|
||||
|
||||
/*
|
||||
var AllRotationOffsets = map[PieceType][]RotationOffsets{
|
||||
PieceI: {
|
||||
{{0, 0}, {-1, 0}, {-1, 1}, {0, 1}},
|
||||
{{-1, 0}, {0, 0}, {1, 1}, {0, 1}},
|
||||
{{2, 0}, {0, 0}, {-2, 1}, {0, 1}},
|
||||
{{-1, 0}, {0, 1}, {1, 0}, {0, -1}},
|
||||
{{2, 0}, {0, -2}, {-2, 0}, {0, 2}}},
|
||||
PieceO: {{{0, 0}, {0, -1}, {-1, -1}, {-1, 0}}},
|
||||
PieceJLSTZ: {
|
||||
{{0, 0}, {0, 0}, {0, 0}, {0, 0}},
|
||||
{{0, 0}, {1, 0}, {0, 0}, {-1, 0}},
|
||||
{{0, 0}, {1, -1}, {0, 0}, {-1, -1}},
|
||||
{{0, 0}, {0, 2}, {0, 0}, {0, 2}},
|
||||
{{0, 0}, {1, 2}, {0, 0}, {-1, 2}}}}
|
||||
*/
|
||||
type Piece struct {
|
||||
Point `json:"pp,omitempty"`
|
||||
Mino `json:"pm,omitempty"`
|
||||
|
|
Loading…
Reference in a new issue