v0.1.0 initial commit

This commit is contained in:
2026-07-15 01:28:56 -04:00
commit 874abee663
35 changed files with 3486 additions and 0 deletions
+116
View File
@@ -0,0 +1,116 @@
package parameter
// Row-reset funnels, drawn in the inter-tile gap row of the player lane.
// Drop = jump expiry (falling to the base row), Rise = slide expiry.
// %s is the countdown; formatted width must not exceed RenderNoteWidth
const (
DropFunnelFormat = `\\ %s //`
RiseFunnelFormat = `// %s \\`
)
// Inbound — chords until the lane shuts.
// Clear — chords until the lane reopens.
// Open — the wall run reaches the window edge; the value is a lower bound.
// Trap — the lane reopens for <= TrapGapMax chords before shutting again;
// flagged on both the inbound and the clear timer
const (
TimerInboundPrefix = '▼'
TimerClearPrefix = '▲'
TimerOpenSuffix = '+'
TimerTrapSuffix = '!'
)
// StripEmptyChar is lookahead strip rail cell — a chord with no content at this position
const StripEmptyChar = '·'
// ItemFadeChars is the glyph tail of a consumed item's burn-out. Stage 0
// keeps the item glyph; later stages collapse it into the rail cell
var ItemFadeChars = [...]rune{'+', StripEmptyChar}
// UnknownChar is placeholder for a Value with no authored visual.
// Keeps NoteVisual total so an unrendered kind is visible rather than eating an item slot
const UnknownChar = '?'
// MutedText marks the host audio gate in the header. ASCII, so it
// renders in both atlases
const MutedText = "MUTE"
// QuadrantChars provides 2x2 sub-cell resolution for TrueColor mode
// Bitmap encoding: bit0=UL, bit1=UR, bit2=LL, bit3=LR
// Layout: [UL][UR]
//
// [LL][LR]
var QuadrantChars = [16]rune{
' ', // 0000 - empty
'▘', // 0001 - upper-left
'▝', // 0010 - upper-right
'▀', // 0011 - upper half
'▖', // 0100 - lower-left
'▌', // 0101 - left half
'▞', // 0110 - anti-diagonal
'▛', // 0111 - UL + UR + LL
'▗', // 1000 - lower-right
'▚', // 1001 - diagonal
'▐', // 1010 - right half
'▜', // 1011 - UL + UR + LR
'▄', // 1100 - lower half
'▙', // 1101 - UL + LL + LR
'▟', // 1110 - UR + LL + LR
'█', // 1111 - full block
}
// Half256Chars provides vertical half-cell resolution for 256-color mode.
// Unicode block characters, CP437-equivalent visuals, naked-TTY compatible
// Bitmap encoding: bit0=top, bit1=bottom
var Half256Chars = [4]rune{
' ', // 00 - empty
'\u2580', // 01 - top half only (▀)
'\u2584', // 10 - bottom half only (▄)
'\u2588', // 11 - both halves (█)
}
// Horizontal256Chars provides horizontal half-cell characters.
// Reserved for future horizontal sub-pixel support
var Horizontal256Chars = [2]rune{
'\u258C', // ▌ - left half
'\u258E', // ▐ - right half
}
// Density256Chars provides intensity variants for trail and glow effects,
// ordered lowest to highest density. Also indexes wall proximity bands
var Density256Chars = [4]rune{
'\u2591', // ░ - light shade (25%)
'\u2592', // ▒ - medium shade (50%)
'\u2593', // ▓ - dark shade (75%)
'\u2588', // █ - full block (100%)
}
// Single-line box drawing characters
const (
BorderSingleHorizontal = '─' // U+2500
BorderSingleVertical = '│' // U+2502
BorderSingleTopLeft = '┌' // U+250C
BorderSingleTopRight = '┐' // U+2510
BorderSingleBottomLeft = '└' // U+2514
BorderSingleBottomRight = '┘' // U+2518
BorderSingleVerticalRight = '├' // U+251C
BorderSingleVerticalLeft = '┤' // U+2524
BorderSingleHorizontalDown = '┬' // U+252C
BorderSingleHorizontalUp = '┴' // U+2534
BorderSingleCross = '┼' // U+253C
)
// Double-line box drawing characters
const (
BorderDoubleHorizontal = '═' // U+2550
BorderDoubleVertical = '║' // U+2551
BorderDoubleTopLeft = '╔' // U+2554
BorderDoubleTopRight = '╗' // U+2557
BorderDoubleBottomLeft = '╚' // U+255A
BorderDoubleBottomRight = '╝' // U+255D
BorderDoubleVerticalRight = '╠' // U+2560
BorderDoubleVerticalLeft = '╣' // U+2563
BorderDoubleHorizontalDown = '╦' // U+2566
BorderDoubleHorizontalUp = '╩' // U+2569
BorderDoubleCross = '╬' // U+256C
)
+159
View File
@@ -0,0 +1,159 @@
package parameter
import (
"time"
)
// Core game grid and timing
const (
// GameRenderUpdate is the frontend frame interval (~60fps). Beat
// quantization is owned by the engine; this only paces UI wakeups
GameRenderUpdate = 16 * time.Millisecond
// GameDeltaZBase is the level-1 inter-chord interval. GameDeltaZStep
// shortens it per level down to the GameDeltaZMin floor
GameDeltaZBase = 500 * time.Millisecond
GameDeltaZStep = 20 * time.Millisecond
GameDeltaZMin = 300 * time.Millisecond
// PlayerRowResetChords chords at whatever tempo is running, so a pattern's
// landing chord is invariant across levels and across a Boost.
// 3 * GameDeltaZBase == the previous 1500ms; level 1 is unchanged.
// Lane (X) shifts are persistent and never auto-reset
PlayerRowResetChords = 3
// ItemFadeDuration is the burn-out span of a consumed positive item.
// Kept under GameDeltaZMin/BoostSpeedFactor so the effect always completes inside one
// chord and reads as consumption, not as the strip scrolling
ItemFadeDuration = 140 * time.Millisecond
// ItemFlashFraction is the leading white-flash portion of the burn-out
ItemFlashFraction = 0.25
// TransitionDuration is the level-clear interlude length
TransitionDuration = 2000 * time.Millisecond
// Song length ceiling
GamePlayIndexZMax = 256
// Chord dimensions
GamePlayIndexYMax = 3
GamePlayIndexXMax = 3
// Player spawn position (grid center)
GamePlayIndexYStart = GamePlayIndexYMax / 2
GamePlayIndexXStart = GamePlayIndexXMax / 2
)
// Song generation
const (
// SongBaseLength + (level-1)*SongLengthPerLevel chords per level,
// capped at GamePlayIndexZMax
SongBaseLength = 72
SongLengthPerLevel = 12
// Guaranteed empty chords at song edges (grace-in, clean finish)
GenIntroRest = 6
GenOutroRest = 4
// Rest gap between pattern chains: GenRestBase shrinks by one per level
// down to GenRestMin
GenRestBase = 7
GenRestMin = 2
// Patterns chained back-to-back per burst
GenChainBase = 1
GenChainMax = 5
// Chance of a single empty chord between chained patterns
GenBreatherProbability = 0.5
)
// Lookahead observation window. Window width covers every wall band; band
// geometry and trap threshold are parameterized here
const (
// PositionLookaheadWindow is how many upcoming chords (starting at the
// current one, distance 0) are scanned per grid position.
// Hard ceiling: game.TileLookaheadMaxWindow (wall bitmask width)
PositionLookaheadWindow = 10
// Wall proximity bands. Band 0 is the arrived wall (distance 0); bands
// 1..WallBandCount-1 each span WallBandSize chords. Band index selects
// border fill density and color
WallBandSize = 3
WallBandCount = 4
// TrapGapMax is the largest reopen gap still flagged as a trap: a lane
// that clears for <= this many chords before another wall shuts it
TrapGapMax = 2
// ConsumeRingSize bounds the consumed-note ring the frontends read
// for burn-out. A magnet sweep can consume up to
// GamePlayIndexYMax*GamePlayIndexXMax*PositionLookaheadWindow notes; on
// overflow the oldest burn-out is dropped (visual-only degradation)
ConsumeRingSize = 64
// MorphWindow is the chord-distance over which a non-wall Value's color
// interpolates from distant to arrived
MorphWindow = 4
)
// Player effects granted by items. Both survive a level change and are cleared on restart
const (
// BoostDuration is the wall-clock lifetime of a Boost. A second pickup
// refreshes the deadline, it does not extend it
BoostDuration = 10 * time.Second
// BoostSpeedFactor divides the inter-chord interval while a Boost runs.
// Integer divisor: the boosted interval stays exact. A slow effect would
// multiply in the same place
BoostSpeedFactor = 2
// BoostWarnRemaining is the Boost tail over which the HUD countdown blinks.
// Expiry inside a wall band kills on the next beat; the player
// needs the lead time to leave the lane
BoostWarnRemaining = 2 * time.Second
// ShieldCharges is the charge count a Shield pickup arms. Each charge
// absorbs one negative contact; charges never expire and do not stack
ShieldCharges = 1
)
// The burn-out must finish inside the tightest beat — the level floor divided by the Boost factor.
// Also proves the boosted interval is > 0, which bounds the Update beat loop
const _ = uint(GameDeltaZMin/BoostSpeedFactor - ItemFadeDuration)
// Compile-time: the window must reach the far edge of the last band
const _ = uint(PositionLookaheadWindow - (WallBandSize*(WallBandCount-1) + 1))
// Tile geometry derives from the strip. PositionLookaheadWindow is
// the only knob; width follows so the strip is 1:1 with the interior
const (
RenderMarginX = 1
RenderMarginY = 1
// RenderHeaderRows is the chrome above the grid (LEVEL / ENERGY).
// No footer, no title
RenderHeaderRows = 1
// One interior column per lookahead chord, plus the two border columns
RenderNoteWidth = PositionLookaheadWindow + 2
RenderNoteHeight = 5
RenderGapX = 2
RenderGapY = 1
// Fixed interior row offsets, relative to the tile top border
RenderRowTimer = 1
RenderRowDist = 2
RenderRowStrip = 3
// Distance row: "gDD gDD" — glyph + chord-distance, positive group then negative group
RenderDistDigits = 2
RenderDistCols = 2*(1+RenderDistDigits) + 1
// RenderBlinkPeriod is the half-cycle of the nearest-item blink. The
// distance-row group of the tile(s) holding the grid-wide nearest
// positive/negative occurrence alternates between two colors at this rate
RenderBlinkPeriod = 120 * time.Millisecond
)