package main import ( "fmt" "git.kiefte.eu/lapingvino/clitris/tris" "github.com/pkg/term" "time" "math/rand" ) // GetKey() returns the key currently pressed. It always returns a 3 byte slice. Check first element for Escape for handling arrow keys // Because a defer would trigger too late and the Restore and Close are essential, separated in a function. func GetKey() []byte { t, _ := term.Open("/dev/tty") term.RawMode(t) key := make([]byte, 3) t.SetReadTimeout(time.Second / 1000) t.Read(key) t.Restore() t.Close() return key } func main() { rand.Seed(time.Now().UnixNano()) var f tris.Field var floor, topout, harddrop bool var x, y int var rot tris.Rotation var key []byte fmt.Print("\033[2J") // Clear screen b := tris.NewBag() b, p := b.Pick() t := time.Tick(time.Second) key = GetKey() for { x, y, rot = p.X, p.Y, p.Rot if !harddrop { fmt.Print("\033[0;0H") // Position to 0,0 fmt.Println(f.Add(p).String()) key = GetKey() } switch key[0] { case 27: // Escape, read the arrow key pressed switch key[2] { case 65: // Up rot = (p.Rot + 1)%4 case 66: // Down y = p.Y + 1 case 67: // Right x = p.X + 1 case 68: // Left x = p.X - 1 default: fmt.Println("...escape, escape!") return } case 'x': rot = (p.Rot + 1)%4 case 'z': rot = (p.Rot + 3)%4 case ' ': harddrop = true case 'q': fmt.Println("...that was exciting!") return case 'Q': fmt.Println("...never let an engineer pick the name of your software?") return } select { case <-t: y = p.Y + 1 default: if harddrop { y = p.Y + 1 } } p, floor, topout = p.Move(f, rot, x, y) if floor && p.Lock.Add(tris.LockDelay).Before(time.Now()) { harddrop = false var l int f = f.Add(p) l, f = f.Lines() if l > 0 { fmt.Println(l, " lines removed!") time.Sleep(time.Second) } fmt.Print("\033[2J") // Clear screen b, p = b.Pick() } if !floor { p.Lock = time.Now() } if topout { fmt.Println("GAME OVER") return } } }