Add minotaur cmd
This commit is contained in:
@@ -0,0 +1,116 @@
|
|||||||
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"context"
|
||||||
|
"flag"
|
||||||
|
"fmt"
|
||||||
|
"log/slog"
|
||||||
|
"os"
|
||||||
|
"os/signal"
|
||||||
|
"path/filepath"
|
||||||
|
"syscall"
|
||||||
|
"time"
|
||||||
|
|
||||||
|
"code.chimeric.al/dwrz/minotaur/internal/minotaur"
|
||||||
|
"code.chimeric.al/dwrz/minotaur/pkg/terminal"
|
||||||
|
)
|
||||||
|
|
||||||
|
var (
|
||||||
|
height = flag.Int("h", 0, "height (default: terminal rows)")
|
||||||
|
width = flag.Int("w", 0, "width (default: terminal columns)")
|
||||||
|
tick = flag.Int("t", 250, "ms between minotaur movement")
|
||||||
|
)
|
||||||
|
|
||||||
|
func main() {
|
||||||
|
flag.Parse()
|
||||||
|
|
||||||
|
var log = slog.New(slog.NewTextHandler(os.Stderr, &slog.HandlerOptions{
|
||||||
|
AddSource: true,
|
||||||
|
Level: slog.LevelDebug,
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Setup the main context.
|
||||||
|
// The context cancels on SIGINT or SIGTERM.
|
||||||
|
ctx, stop := signal.NotifyContext(
|
||||||
|
context.Background(),
|
||||||
|
syscall.SIGINT,
|
||||||
|
syscall.SIGTERM,
|
||||||
|
)
|
||||||
|
defer stop()
|
||||||
|
|
||||||
|
if err := run(ctx, log); err != nil {
|
||||||
|
log.Error("failed", slog.Any("error", err))
|
||||||
|
os.Exit(1)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func run(ctx context.Context, log *slog.Logger) error {
|
||||||
|
if *height < 0 {
|
||||||
|
return fmt.Errorf("invalid height: %d", *height)
|
||||||
|
}
|
||||||
|
if *width < 0 {
|
||||||
|
return fmt.Errorf("invalid width: %d", *width)
|
||||||
|
}
|
||||||
|
if *tick <= 0 {
|
||||||
|
return fmt.Errorf("invalid tick: %d", *tick)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup workspace and log file.
|
||||||
|
cdir, err := os.UserCacheDir()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf(
|
||||||
|
"failed to determine user cache directory: %w", err,
|
||||||
|
)
|
||||||
|
}
|
||||||
|
wdir := filepath.Join(cdir, "minotaur")
|
||||||
|
|
||||||
|
if err := os.MkdirAll(wdir, os.ModeDir|0700); err != nil {
|
||||||
|
return fmt.Errorf("failed to create tmp dir: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
f, err := os.Create(wdir + "/log")
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create log file: %w", err)
|
||||||
|
}
|
||||||
|
defer f.Close()
|
||||||
|
|
||||||
|
var gameLog = slog.New(slog.NewTextHandler(f, &slog.HandlerOptions{
|
||||||
|
AddSource: true,
|
||||||
|
Level: slog.LevelDebug,
|
||||||
|
}))
|
||||||
|
|
||||||
|
// Retrieve terminal info.
|
||||||
|
t, err := terminal.New(os.Stdin.Fd())
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get terminal attributes: %w", err)
|
||||||
|
}
|
||||||
|
size, err := t.Size()
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to get terminal size: %w", err)
|
||||||
|
}
|
||||||
|
if *height == 0 {
|
||||||
|
rows := int(size.Rows)
|
||||||
|
height = &rows
|
||||||
|
}
|
||||||
|
if *width == 0 {
|
||||||
|
cols := int(size.Columns)
|
||||||
|
width = &cols
|
||||||
|
}
|
||||||
|
|
||||||
|
// Setup the game.
|
||||||
|
game, err := minotaur.New(minotaur.Parameters{
|
||||||
|
Height: *height,
|
||||||
|
In: os.Stdin,
|
||||||
|
Log: gameLog,
|
||||||
|
Out: os.Stdout,
|
||||||
|
Terminal: t,
|
||||||
|
Tick: time.Duration(*tick) * time.Millisecond,
|
||||||
|
Width: *width,
|
||||||
|
})
|
||||||
|
if err != nil {
|
||||||
|
return fmt.Errorf("failed to create game: %w", err)
|
||||||
|
}
|
||||||
|
|
||||||
|
// Run the game.
|
||||||
|
return game.Run(ctx)
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user