Resolve display not appearing square at size 3

This commit is contained in:
Trevor Slocum 2019-10-30 16:25:06 -07:00
parent 7fe65c1183
commit 886f47787d
9 changed files with 203 additions and 120 deletions

View File

@ -106,7 +106,7 @@ func resetPlayerSettingsForm() {
// BS 1: 10x10
// BS 2: 20x20
// BS 3: 30x40
// BS 3: 40x40
func handleResize(screen tcell.Screen) {
newScreenW, newScreenH = screen.Size()
if newScreenW == screenW && newScreenH == screenH {
@ -116,9 +116,9 @@ func handleResize(screen tcell.Screen) {
screenW, screenH = newScreenW, newScreenH
if !fixedBlockSize {
if screenW >= 80 && screenH >= 46 {
if screenW >= 106 && screenH >= 46 {
blockSize = 3
} else if screenW >= 80 && screenH >= 24 {
} else if screenW >= 56 && screenH >= 24 {
blockSize = 2
} else {
blockSize = 1
@ -129,7 +129,7 @@ func handleResize(screen tcell.Screen) {
if blockSize == 2 {
xMultiplier = 2
} else if blockSize == 3 {
xMultiplier = 3
xMultiplier = 4
}
if blockSize == 1 {
@ -165,7 +165,7 @@ func handleResize(screen tcell.Screen) {
} else if blockSize == 2 {
previewWidth = 10
} else {
previewWidth = 14
previewWidth = 18
}
multiplayerMatrixSize = ((screenW - screenPadding) - ((10 * xMultiplier) + previewWidth + 6)) / ((10 * xMultiplier) + 4)
@ -177,7 +177,7 @@ func handleResize(screen tcell.Screen) {
showLogLines = 1
}
gameGrid.SetRows(screenPadding, mainHeight, inputHeight, -1).SetColumns(screenPadding+1, 4+(10*xMultiplier), previewWidth, -1)
gameGrid.SetRows(screenPadding, mainHeight, inputHeight, -1).SetColumns(screenPadding+1, 3+(10*xMultiplier), previewWidth, -1)
draw <- event.DrawAll
}
@ -303,7 +303,7 @@ func renderPlayerGUI() {
} else if blockSize == 2 {
renderBuffer.WriteString(fmt.Sprintf("\n Combo\n\n %d\n\n\n Timer\n\n %.0f\n\n\nPending\n\n %d\n\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
} else if blockSize == 3 {
renderBuffer.WriteString(fmt.Sprintf("\n\n\n\n\n Combo\n\n %d\n\n\n\n\n\n Timer\n\n %.0f\n\n\n\n\n\n Pending\n\n %d\n\n\n\n\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
renderBuffer.WriteString(fmt.Sprintf("\n\n\n\n\n Combo\n\n %d\n\n\n\n\n\n Timer\n\n %.0f\n\n\n\n\n\n Pending\n\n %d\n\n\n\n\n\n Speed\n\n %s", combo, comboTime, m.PendingGarbage, speed))
}
side.Clear()
@ -366,6 +366,13 @@ func renderMultiplayerGUI() {
}
func renderPlayerDetails(m *mino.Matrix, bs int) {
xMultiplier := 1
if bs == 2 {
xMultiplier = 2
} else if bs == 3 {
xMultiplier = 4
}
var buf string
if !showDetails {
buf = m.PlayerName
@ -376,16 +383,16 @@ func renderPlayerDetails(m *mino.Matrix, bs int) {
buf = fmt.Sprintf("%d / %d @ %d", m.GarbageSent, m.GarbageReceived, m.Speed)
}
}
if len(buf) > m.W*bs {
buf = buf[:m.W*bs]
if len(buf) > m.W*xMultiplier {
buf = buf[:m.W*xMultiplier]
}
padBuf := ((m.W*bs - len(buf)) / 2) + 1
padBuf := ((m.W*xMultiplier - len(buf)) / 2) + 1
for i := 0; i < padBuf; i++ {
renderBuffer.WriteRune(' ')
}
renderBuffer.WriteString(buf)
padBuf = m.W*bs + 2 - len(buf) - padBuf
padBuf = m.W*xMultiplier + 2 - len(buf) - padBuf
for i := 0; i < padBuf; i++ {
renderBuffer.WriteRune(' ')
}
@ -407,15 +414,25 @@ func renderMatrixes(mx []*mino.Matrix) {
renderBuffer.WriteRune('\n')
if mx[0].Bag != nil {
p := mx[0].Bag.Next()
nextPieceWidth, _ = p.Size()
if nextPieceWidth == 2 && blockSize == 1 {
nextPieceWidth = 3
if p != nil {
nextPieceWidth, _ = p.Size()
}
}
if bs == 3 {
renderBuffer.WriteRune('\n')
}
} else if mt == mino.MatrixCustom {
bs = 1
}
xMultiplier := 1
if bs == 2 {
xMultiplier = 2
} else if bs == 3 {
xMultiplier = 4
}
for i := range mx {
mx[i].Lock()
mx[i].DrawPiecesL()
@ -428,7 +445,7 @@ func renderMatrixes(mx []*mino.Matrix) {
}
renderBuffer.Write(renderULCorner)
for x := 0; x < mx[i].W*bs; x++ {
for x := 0; x < mx[i].W*xMultiplier; x++ {
renderBuffer.Write(renderHLine)
}
renderBuffer.Write(renderURCorner)
@ -447,10 +464,6 @@ func renderMatrixes(mx []*mino.Matrix) {
renderBuffer.Write(renderVLine)
} else if m.Type == mino.MatrixPreview {
renderBuffer.WriteRune(' ')
if nextPieceWidth < 4 {
renderBuffer.WriteRune(' ')
}
}
for x := 0; x < m.W; x++ {
@ -460,7 +473,7 @@ func renderMatrixes(mx []*mino.Matrix) {
renderBuffer.Write(mino.Colors[m.Block(x, y)])
renderBuffer.WriteRune(']')
renderBuffer.WriteRune('▄')
renderBuffer.Write([]byte("[-:-]"))
renderBuffer.Write([]byte("[#FFFFFF:#000000]"))
}
if m.Type == mino.MatrixStandard {
@ -482,8 +495,7 @@ func renderMatrixes(mx []*mino.Matrix) {
if m.Type == mino.MatrixStandard {
renderBuffer.Write(renderVLine)
} else if m.Type == mino.MatrixPreview {
for pad := 0; pad < 3-nextPieceWidth; pad++ {
renderBuffer.WriteRune(' ')
if nextPieceWidth < 4 {
renderBuffer.WriteRune(' ')
}
}
@ -494,7 +506,7 @@ func renderMatrixes(mx []*mino.Matrix) {
renderBuffer.WriteRune(']')
renderBuffer.WriteRune('█')
renderBuffer.WriteRune('█')
renderBuffer.Write([]byte("[-]"))
renderBuffer.Write([]byte("[#FFFFFF]"))
}
if m.Type == mino.MatrixStandard {
@ -517,10 +529,7 @@ func renderMatrixes(mx []*mino.Matrix) {
if m.Type == mino.MatrixStandard {
renderBuffer.Write(renderVLine)
} else if m.Type == mino.MatrixPreview {
if nextPieceWidth == 2 {
renderBuffer.WriteRune(' ')
renderBuffer.WriteRune(' ')
} else if nextPieceWidth < 4 {
if nextPieceWidth < 4 {
renderBuffer.WriteRune(' ')
}
}
@ -532,7 +541,8 @@ func renderMatrixes(mx []*mino.Matrix) {
renderBuffer.WriteRune('█')
renderBuffer.WriteRune('█')
renderBuffer.WriteRune('█')
renderBuffer.Write([]byte("[-]"))
renderBuffer.WriteRune('█')
renderBuffer.Write([]byte("[#FFFFFF]"))
}
if m.Type == mino.MatrixStandard {
@ -554,7 +564,7 @@ func renderMatrixes(mx []*mino.Matrix) {
}
renderBuffer.Write(renderLLCorner)
for x := 0; x < mx[i].W*bs; x++ {
for x := 0; x < mx[i].W*xMultiplier; x++ {
renderBuffer.Write(renderHLine)
}
renderBuffer.Write(renderLRCorner)

View File

@ -1,6 +1,7 @@
package main
import (
"fmt"
"testing"
"git.sr.ht/~tslocum/netris/pkg/mino"
@ -10,63 +11,54 @@ func TestRenderMatrix(t *testing.T) {
renderLock.Lock()
defer renderLock.Unlock()
blockSize = 1
for bs := 1; bs <= 3; bs++ {
bs := bs // Capture
m, err := mino.NewTestMatrix()
if err != nil {
t.Error(err)
t.Run(fmt.Sprintf("Size=%d", bs), func(t *testing.T) {
blockSize = bs
m, err := mino.NewTestMatrix()
if err != nil {
t.Error(err)
}
m.AddTestBlocks()
mx := []*mino.Matrix{m}
renderMatrixes(mx)
})
}
m.AddTestBlocks()
mx := []*mino.Matrix{m}
renderMatrixes(mx)
blockSize = 1
}
func BenchmarkRenderStandardMatrix(b *testing.B) {
func BenchmarkRenderMatrix(b *testing.B) {
renderLock.Lock()
defer renderLock.Unlock()
blockSize = 1
for bs := 1; bs <= 3; bs++ {
bs := bs // Capture
m, err := mino.NewTestMatrix()
if err != nil {
b.Error(err)
}
b.Run(fmt.Sprintf("Size=%d", bs), func(b *testing.B) {
blockSize = bs
m.AddTestBlocks()
m, err := mino.NewTestMatrix()
if err != nil {
b.Error(err)
}
mx := []*mino.Matrix{m}
m.AddTestBlocks()
b.ReportAllocs()
b.ResetTimer()
mx := []*mino.Matrix{m}
for i := 0; i < b.N; i++ {
renderMatrixes(mx)
}
}
b.ReportAllocs()
b.ResetTimer()
func BenchmarkRenderLargeMatrix(b *testing.B) {
renderLock.Lock()
defer renderLock.Unlock()
blockSize = 2
m, err := mino.NewTestMatrix()
if err != nil {
b.Error(err)
}
m.AddTestBlocks()
mx := []*mino.Matrix{m}
b.ReportAllocs()
b.ResetTimer()
for i := 0; i < b.N; i++ {
renderMatrixes(mx)
for i := 0; i < b.N; i++ {
renderMatrixes(mx)
}
})
}
blockSize = 1

View File

@ -427,10 +427,10 @@ func (g *Game) handleDistributeMatrixes() {
requiredPlayers := 2
if g.Local {
requiredPlayers = 0
requiredPlayers = 1
}
if !g.gameOver && remainingPlayers <= requiredPlayers {
if !g.gameOver && remainingPlayers < requiredPlayers {
g.setGameOverL(true)
if g.Local {

View File

@ -1,45 +1,50 @@
package mino
import (
"fmt"
"testing"
)
func TestBag(t *testing.T) {
var (
minos []Mino
err error
)
t.Parallel()
for _, d := range minoTestData {
minos, err = Generate(d.Rank)
if err != nil {
t.Errorf("failed to generate minos for rank %d: %s", d.Rank, err)
}
d := d // Capture
if len(minos) != len(d.Minos) {
t.Errorf("failed to generate minos for rank %d: unexpected number of minos generated", d.Rank)
}
t.Run(fmt.Sprintf("Rank=%d", d.Rank), func(t *testing.T) {
t.Parallel()
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++ {
mino := b.Take()
taken[mino.String()]++
minos, err := Generate(d.Rank)
if err != nil {
t.Errorf("failed to generate minos for rank %d: %s", d.Rank, err)
}
if len(taken) != len(minos) {
t.Errorf("minos placed in rank %d bag do not match minos taken - placed: %s - taken: %v", d.Rank, minos, taken)
if len(minos) != len(d.Minos) {
t.Errorf("failed to generate minos for rank %d: unexpected number of minos generated", d.Rank)
}
for _, mino := range minos {
if taken[mino.String()] != i {
t.Fatalf("minos placed in rank %d bag do not match minos taken - placed: %s - taken: %v", d.Rank, minos, taken)
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++ {
mino := b.Take()
taken[mino.String()]++
}
if len(taken) != len(minos) {
t.Errorf("minos placed in rank %d bag do not match minos taken - placed: %s - taken: %v", d.Rank, minos, taken)
}
for _, mino := range minos {
if taken[mino.String()] != i {
t.Fatalf("minos placed in rank %d bag do not match minos taken - placed: %s - taken: %v", d.Rank, minos, taken)
}
}
}
}
})
}
}

View File

@ -5,12 +5,10 @@ import (
)
func TestGenerate(t *testing.T) {
var (
minos []Mino
err error
)
t.Parallel()
for _, d := range minoTestData {
minos, err = Generate(d.Rank)
minos, err := Generate(d.Rank)
if err != nil {
t.Errorf("failed to generate minos for rank %d: %s", d.Rank, err)
}

View File

@ -5,6 +5,8 @@ import (
)
func TestMatrix(t *testing.T) {
t.Parallel()
m, err := NewTestMatrix()
if err != nil {
t.Error(err)
@ -65,7 +67,7 @@ func TestMatrix(t *testing.T) {
ok = m.RotatePiece(1, 0)
if !ok {
t.Errorf("failed to rotate piece for right wall kick")
t.Errorf("failed to rotate piece for right 1wall kick")
}
for i := 0; i < 7; i++ {

View File

@ -44,6 +44,26 @@ const (
PentominoR = "(0,0),(1,0),(2,0),(3,0),(1,1)"
)
func NewMino(points string) Mino {
var m Mino
var last int
for i, p := range strings.Split(strings.ReplaceAll(strings.ReplaceAll(points, "(", ""), ")", ""), ",") {
v, err := strconv.Atoi(p)
if err != nil {
return nil
}
if i%2 == 0 {
last = v
continue
}
m = append(m, Point{last, v})
}
return m
}
func (m Mino) Equal(other Mino) bool {
if len(m) != len(other) {
return false

View File

@ -1,13 +0,0 @@
package mino
type Minos []Mino
func (ms Minos) Has(m Mino) bool {
for _, msm := range ms {
if msm.Equal(m) {
return true
}
}
return false
}

69
pkg/mino/piece_test.go Normal file
View File

@ -0,0 +1,69 @@
package mino
import (
"log"
"testing"
)
type PieceTestData struct {
R0 string
RR string
R2 string
RL string
}
var pieceTestData = []*PieceTestData{
{Monomino, Monomino, Monomino, Monomino},
{Domino, "(0,-1),(0,0)", Domino, "(0,-1),(0,0)"},
}
func TestPiece(t *testing.T) {
t.Parallel()
// TODO Resolve CCW rotation resulting in different coords than CW rotation before completing test
return
for i, d := range pieceTestData {
m := NewMino(d.R0)
if m == nil || m.String() != d.R0 {
t.Errorf("failed to create mino %d %s: got %s", i, d.R0, m)
}
p := NewPiece(m, Point{0, 0})
if p == nil || p.Mino.String() != d.R0 {
t.Errorf("failed to create piece %d %s: got %s", i, d.R0, p)
}
for direction := 0; direction <= 1; direction++ {
for rotations := 0; rotations < 8; rotations++ {
p.Mino = p.Rotate(1, direction)
expected := ""
switch rotations % 4 {
case 0:
if direction == 0 {
expected = d.RR
} else {
expected = d.RL
}
case 1:
expected = d.R2
case 2:
if direction == 0 {
expected = d.RL
} else {
expected = d.RR
}
case 3:
expected = d.R0
default:
t.Errorf("unexpected rotation count %d", rotations)
}
if p.Mino.String() != expected {
t.Errorf("failed to rotate piece %d - direction %d - rotation %d - expected %s: got %s", i, direction, rotations, expected, p.Mino)
}
}
}
log.Println(p)
}
}