From 16aa91742cf9527a36f488b6078811cf9f73ea6c Mon Sep 17 00:00:00 2001 From: "Zed A. Shaw" Date: Sun, 28 Dec 2025 12:52:40 -0500 Subject: [PATCH] It now uses tcell colors to show build status and when you die. --- .ttarpit.json | 1 + Makefile | 2 +- builder/build.go | 22 +++++++++++--- config/settings.go | 1 + game/engine.go | 12 +++++++- go.mod | 4 +-- go.sum | 8 ++--- main.go | 12 +------- ui.go | 74 ++++++++++++++++++++++++++++++++++++++++++---- 9 files changed, 108 insertions(+), 28 deletions(-) diff --git a/.ttarpit.json b/.ttarpit.json index 3ceaca7..ab6f82d 100644 --- a/.ttarpit.json +++ b/.ttarpit.json @@ -1,5 +1,6 @@ { "StartingHP": 10, + "Deadline": "1h30m0s", "Includes": [ "^.*.go$" ], diff --git a/Makefile b/Makefile index 0e1c419..8af9b1e 100644 --- a/Makefile +++ b/Makefile @@ -18,7 +18,7 @@ build_tester: go build -o tester$(GO_IS_STUPID_EXE) ./tools/cmd/tester/main.go docs: - go tool pkgsite --open + pkgsite --open coverage: go build -cover -o webapp diff --git a/builder/build.go b/builder/build.go index ca8d4df..10f99e3 100644 --- a/builder/build.go +++ b/builder/build.go @@ -19,11 +19,19 @@ import ( type ErrorHandler func (data.ErrInfo) +const ( + START=0 + RUNNING=1 + FAILED=2 + PASSED=3 +) + type Builder struct { settings config.Config OnError ErrorHandler - BuildRunning bool + BuildState int + HadErrors bool } func New(settings config.Config, handler ErrorHandler) (*Builder) { @@ -75,6 +83,7 @@ func (build *Builder) LaunchLogger(in io.Reader, out io.Writer, err error) { if ok { build.OnError(errinfo) + build.HadErrors = true } } } @@ -122,8 +131,9 @@ func (build *Builder) MatchesPath(fp string) bool { } func (build *Builder) BeginBuild() bool { - if !build.BuildRunning { - build.BuildRunning = true + if build.BuildState != RUNNING { + build.BuildState = RUNNING + build.HadErrors = false return true } else { return false @@ -131,7 +141,11 @@ func (build *Builder) BeginBuild() bool { } func (build *Builder) EndBuild() { - build.BuildRunning = false + if build.HadErrors { + build.BuildState = FAILED + } else { + build.BuildState = PASSED + } } func (build *Builder) RunBuild() { diff --git a/config/settings.go b/config/settings.go index 9f78c4b..b274a10 100644 --- a/config/settings.go +++ b/config/settings.go @@ -20,6 +20,7 @@ type Config struct { Includes []string Processes map[string]Process StartingHP int + Deadline string ConfigPath string diff --git a/game/engine.go b/game/engine.go index 1898a89..980877b 100644 --- a/game/engine.go +++ b/game/engine.go @@ -4,6 +4,7 @@ import ( "lcthw.dev/go/ttarpit/config" "lcthw.dev/go/ttarpit/data" . "lcthw.dev/go/ttarpit/debug" + "time" ) type Game struct { @@ -11,6 +12,8 @@ type Game struct { HP int Errors int + StartTime time.Time + EndTime time.Time } func New(settings config.Config) *Game { @@ -18,6 +21,14 @@ func New(settings config.Config) *Game { game.settings = settings game.HP = settings.StartingHP + game.StartTime = time.Now() + time_out, err := time.ParseDuration(settings.Deadline) + + if err != nil { + panic(err) + } + + game.EndTime = time.Now().Add(time_out) return game } @@ -33,7 +44,6 @@ func (game *Game) TakeHit(errinfo data.ErrInfo) { if game.HP <= 0 { Log.Println("!!!!!! YOU DIED !!!!!!!") - game.HP = game.settings.StartingHP } Log.Println("===========================") diff --git a/go.mod b/go.mod index c192f02..3020661 100644 --- a/go.mod +++ b/go.mod @@ -11,7 +11,7 @@ require ( github.com/gdamore/encoding v1.0.1 // indirect github.com/lucasb-eyer/go-colorful v1.3.0 // indirect github.com/rivo/uniseg v0.4.7 // indirect - golang.org/x/sys v0.38.0 // indirect + golang.org/x/sys v0.39.0 // indirect golang.org/x/term v0.37.0 // indirect - golang.org/x/text v0.31.0 // indirect + golang.org/x/text v0.32.0 // indirect ) diff --git a/go.sum b/go.sum index bb86f56..240554f 100644 --- a/go.sum +++ b/go.sum @@ -26,8 +26,8 @@ golang.org/x/sys v0.0.0-20210615035016-665e8c7367d1/go.mod h1:oPkhp1MJrh7nUepCBc golang.org/x/sys v0.0.0-20220520151302-bc2c85ada10a/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.0.0-20220722155257-8c9f86f7a55f/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= golang.org/x/sys v0.5.0/go.mod h1:oPkhp1MJrh7nUepCBck5+mAzfO9JrbApNNgaTdGDITg= -golang.org/x/sys v0.38.0 h1:3yZWxaJjBmCWXqhN1qh02AkOnCQ1poK6oF+a7xWL6Gc= -golang.org/x/sys v0.38.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= +golang.org/x/sys v0.39.0 h1:CvCKL8MeisomCi6qNZ+wbb0DN9E5AATixKsvNtMoMFk= +golang.org/x/sys v0.39.0/go.mod h1:OgkHotnGiDImocRcuBABYBEXf8A9a87e/uXjp9XT3ks= golang.org/x/term v0.0.0-20201126162022-7de9c90e9dd1/go.mod h1:bj7SfCRtBDWHUb9snDiAeCFNEtKQo2Wmx5Cou7ajbmo= golang.org/x/term v0.0.0-20210927222741-03fcf44c2211/go.mod h1:jbD1KX2456YbFQfuXm/mYQcufACuNUgVhRMnK/tPxf8= golang.org/x/term v0.5.0/go.mod h1:jMB1sMXY+tzblOD4FWmEbocvup2/aLOaQEp7JmGp78k= @@ -38,8 +38,8 @@ golang.org/x/text v0.3.3/go.mod h1:5Zoc/QRtKVWzQhOtBMvqHzDpF6irO9z98xDceosuGiQ= golang.org/x/text v0.3.7/go.mod h1:u+2+/6zg+i71rQMx5EYifcz6MCKuco9NR6JIITiCfzQ= golang.org/x/text v0.7.0/go.mod h1:mrYo+phRRbMaCq/xk9113O4dZlRixOauAjOtrjsXDZ8= golang.org/x/text v0.14.0/go.mod h1:18ZOQIKpY8NJVqYksKHtTdi31H5itFRjB5/qKTNYzSU= -golang.org/x/text v0.31.0 h1:aC8ghyu4JhP8VojJ2lEHBnochRno1sgL6nEi9WGFGMM= -golang.org/x/text v0.31.0/go.mod h1:tKRAlv61yKIjGGHX/4tP1LTbc13YSec1pxVEWXzfoeM= +golang.org/x/text v0.32.0 h1:ZD01bjUt1FQ9WJ0ClOL5vxgxOI/sVCNgX1YtKwcY0mU= +golang.org/x/text v0.32.0/go.mod h1:o/rUWzghvpD5TXrTIBuJU77MTaN0ljMWE47kxGJQ7jY= golang.org/x/tools v0.0.0-20180917221912-90fa682c2a6e/go.mod h1:n7NCudcB/nEzxVGmLbDWY5pfWTLqBcC2KZ6jyYvM4mQ= golang.org/x/tools v0.0.0-20191119224855-298f0cb1881e/go.mod h1:b+2E5dAYhXwXZwtnZ6UAqBI28+e2cm9otk0dWdXHAEo= golang.org/x/tools v0.1.12/go.mod h1:hNGJHUnrk76NpqgfD5Aqm5Crs+Hm0VOH/i9J2+nxYbc= diff --git a/main.go b/main.go index a0e7af8..a1d40ba 100644 --- a/main.go +++ b/main.go @@ -1,7 +1,6 @@ package main import ( - "time" "lcthw.dev/go/ttarpit/builder" "lcthw.dev/go/ttarpit/config" "lcthw.dev/go/ttarpit/game" @@ -24,16 +23,7 @@ func main() { ui := MakeUI() - go func () { - for { - ui.Render(g) - time.Sleep(100 * time.Millisecond) - } - }() - - for ui.HandleEvents() { - ui.Render(g) - } + ui.RenderLoop(g, build) ui.Exit() } diff --git a/ui.go b/ui.go index 5ad3319..b08cdc3 100644 --- a/ui.go +++ b/ui.go @@ -2,14 +2,19 @@ package main import ( . "lcthw.dev/go/ttarpit/debug" + "time" "fmt" "github.com/gdamore/tcell/v2" "github.com/gdamore/tcell/v2/encoding" "lcthw.dev/go/ttarpit/game" + "lcthw.dev/go/ttarpit/builder" ) + type UI struct { Screen tcell.Screen + DefaultStyle tcell.Style + DeadStyle tcell.Style } func (ui *UI) DrawText(x int, y int, text string) { @@ -18,12 +23,48 @@ func (ui *UI) DrawText(x int, y int, text string) { } } -func (ui *UI) Render(data *game.Game) { - ui.Screen.Clear() +func (ui *UI) StyleText(x int, y int, text string, style tcell.Style) { + for i, cell := range text { + ui.Screen.SetContent(x+i, y, cell, nil, style) + } +} + +func (ui *UI) Render(data *game.Game, build *builder.Builder) { + if data.HP <= 0 { + ui.Screen.SetStyle(ui.DeadStyle) + ui.Screen.Sync() + ui.Screen.Clear() + ui.DrawText(0, 10, fmt.Sprintf("YOU DIED!")) + } else { + ui.Screen.SetStyle(ui.DefaultStyle) + ui.Screen.Clear() + } + + time_since := time.Until(data.EndTime) ui.DrawText(0, 0, "Welcome to Turing's Tarpit") - ui.DrawText(0, 1, fmt.Sprintf("HP: %d", data.HP)) - ui.DrawText(0, 2, fmt.Sprintf("Errors: %d", data.Errors)) + ui.DrawText(0, 2, fmt.Sprintf("HP: %d", data.HP)) + ui.DrawText(0, 3, fmt.Sprintf("Errors: %d", data.Errors)) + ui.DrawText(0, 4, fmt.Sprintf("Deadline: %s", time_since.Round(time.Second))) + + green := tcell.StyleDefault.Background(tcell.ColorGreen).Foreground(tcell.ColorBlack) + + red := tcell.StyleDefault.Background(tcell.ColorRed).Foreground(tcell.ColorBlack) + + yellow := tcell.StyleDefault.Background(tcell.ColorYellow).Foreground(tcell.ColorBlack) + + switch build.BuildState { + case builder.START: + ui.StyleText(0, 5, "Build: READY", green) + case builder.RUNNING: + ui.StyleText(0, 5, "Build: RUNNING", yellow) + case builder.PASSED: + ui.StyleText(0, 5, "Build: PASSED", green) + case builder.FAILED: + ui.StyleText(0, 5, "Build: FAILED", red) + } + + // show the errors ui.Screen.Show() } @@ -57,6 +98,19 @@ func (ui *UI) Exit() { ui.Screen.Fini() } +func (ui *UI) RenderLoop(g *game.Game, build *builder.Builder) { + go func () { + for { + ui.Render(g, build) + time.Sleep(100 * time.Millisecond) + } + }() + + for ui.HandleEvents() { + ui.Render(g, build) + } +} + func MakeUI() *UI { var err error @@ -70,6 +124,16 @@ func MakeUI() *UI { err = ui.Screen.Init() if err != nil { Log.Fatal(err) } + ui.DefaultStyle = tcell.StyleDefault. + Background(tcell.ColorBlack). + Foreground(tcell.ColorWhite) + + ui.DeadStyle = tcell.StyleDefault. + Background(tcell.ColorDarkRed). + Foreground(tcell.ColorWhite) + + ui.Screen.SetStyle(ui.DefaultStyle) + ui.Screen.Clear() + return ui } -