Skip to content

Releases: Chemaclass/phel-doom

v0.16.0

Choose a tag to compare

@Chemaclass Chemaclass released this 27 Jun 21:14
v0.16.0
5bb9ac3

Added

  • "Quad detail" setting (default off): packs a 2×2 quadrant Block-Elements glyph (▌▞▖▟…) wherever the four sub-pixels of a cell differ, adding a 2nd HORIZONTAL sample on top of the half-block's 2× vertical. Two payoffs: (1) the wall SILHOUETTE staircase — at each boundary cell the wall top/bottom is sampled at two sub-columns (bounds lerped 0.25 toward each neighbour column, kept fractional so they straddle the sub-row grid), so a receding/angled edge steps in half-cell diagonals instead of whole columns (the high-contrast wall/sky edge is the visible win — ~150 vertical-edge + ~130 diagonal glyphs/frame on a typical view); (2) the floor texture shows four texels per cell near the camera instead of two. The per-column raycast has no sub-column ray, so both lerp the basis/bounds from the neighbour columns; samples quantise to brightest-FG + darkest-BG and pick the glyph for that mask. No-horizontal-detail cells collapse to the half-block, so flat / far surfaces still RLE-coalesce and only edges/near-floor pay. Composes with Truecolor. Only with Sub-pixel on, full-detail px1. Cost when on: ~+40-47% CPU, low extra bytes (most edge cells swap →a quadrant glyph, same length). Off by default (golden hashes unchanged). Env PHEL_DOOM_QUAD=1 / PHEL_DOOM_NO_QUAD=1.
  • "Truecolor" setting (default off): the floor distance-fog now paints 24-bit \e[48;2;r;g;b cells instead of a nearest-256 code, removing the 6×6×6-cube / 24-step-grey snap banding so the ground recedes into the haze tint smoothly. A tagged-value scheme (>= 256 ⇒ packed RGB) lets the same cell builders mix a truecolor channel with a 256 one, and the pure-256 fast path is byte-identical (golden hashes unchanged) — so default-off render is unchanged. Costs ~+41% bytes/frame, ~+3% CPU when on (full-detail only; px2 stays 256). Needs a truecolor terminal. Env overrides PHEL_DOOM_TRUECOLOR=1 (force on) / PHEL_DOOM_NO_TRUECOLOR=1 (force off). Walls/sky still 256 (the seam mixer is a follow-up).
  • "Sub-pixel" setting (default on, #332): macOS Terminal.app draws the half-blocks with anti-aliased row seams (iTerm2 / kitty / WezTerm / Ghostty draw them pixel-tight), so the 3D view shows horizontal seams there. Turning Sub-pixel off uses one solid colour per cell, which Terminal.app renders cleanly. Wires PHEL_DOOM_NO_SUBPIXEL into a persisted setting; default on so render is byte-identical (golden hashes unchanged). docs/rendering.md has the root cause + recommended Terminal.app settings (line spacing 1.0 also clears the seams).
  • "Low detail" setting (default off): paints each wall AND floor cell as one flat colour instead of a two-sample , for ~11-26% less render time (scales with screen size) and ~31-40% fewer bytes/frame. Wall silhouettes / edges keep sub-pixel precision (the seam mixer still runs); sky and sprites untouched. Off by default (byte-identical); for large terminals / slow hardware. Dev override PHEL_DOOM_FLAT_WALLTEX=1.
  • Living, non-repeating soundtrack: the OST no longer loops one fixed 3s clip. music/session-riff concatenates several ornamented variant-riff sections (E-minor ostinato with random 3rd/5th/octave stabs, root +3/+7/+12, over chugging root hits) into one long track, seeded off the game pid so every session sounds fresh. Baked once and looped whole (no per-relaunch gaps between sections); click-free at section joins + the loop wrap.
  • Music pauses with the game: pausing (P menu, H info panel, menu Resume) SIGSTOPs the OST so it freezes and resumes exactly where it left off (music/pause-music! / resume-music!), instead of playing under the pause screen.
  • Random room layouts: every level scatters random interior walls (map/scatter-walls), sealed-connected so no floor, pickup, keycard or exit is stranded. The exit door can land on ANY wall reachable from the spawn (interior pillar or border edge), not just the sides. The L10 boss arena keeps its hand-designed geometry (un-scattered). A test asserts every level (1-10) has interior walls + exactly one reachable exit that varies with the seed.
  • Mouse look + click to shoot (issues #246, #318, #320, #288, #324, #275, #306, #295, #313): a + crosshair fixed at screen centre, gun firing dead-ahead; pointer motion turns yaw + pitch (mouse-look-gain over the raw column rate). Sensitivity slider follows 3 ^ ((pct - 50) / 50) - 50% = 1.0x, 0% ~0.33x for fine aim, 100% 3.0x for flicks - scaling the delta turn + edge-pan. A terminal can't lock / warp / hide the OS pointer (#313), so an edge-pan fallback keeps turning past a window border (a resting pointer never spins), and mouse-enable sends XTSMPOINTER \e[>3p to hide it where supported (xterm-family); iTerm2 / Apple Terminal can't, so the arrow stays visible but cosmetic (the turn reads MOTION) and the start-menu how-to says so + lists mouse - look/fire (terminal via $TERM_PROGRAM). Left-click fires (hold for auto-fire), via xterm SGR. Mouse on/off + Sensitivity persisted; mouse off is byte-for-byte the keyboard build (golden fixture unchanged). On by default; keyboard unchanged.

Changed

  • Weapon fire volume tracks the hit distance on a miss too: a shot that hits no enemy used to play full volume; now it attenuates by the wall it hits (cast-wall-dist) - near wall loud, far / open level quiet - the same proximity feedback as an enemy hit. Volume only; scaled by the global SFX setting.
  • Calmer 3D view: dropped the decorative blinks / strobes (every SGR \e[5 hardware-blink is gone); informational cues held steady instead (heartbeat edge, berserk border, HUD labels, powerup banners, JAMMED chip, hearts strip, doors, aggro-range enemy heads). Essential single-shot feedback (hit-vignette, kill flash, dry-fire CLICK, hit-marker) + pickup glow unchanged. Event-gated, golden hashes unchanged.
  • Heart pickup plays the Hero cue (#281): the most valuable pickup shared the generic loot tink (:door) with armor/ammo/doors; now it uses the soulsphere's :berserk (Hero) cue. Existing sound, render unchanged.
  • Rocket launcher ships with a usable reserve (#282): the L5 flagship arrived with one rocket (:reserve-start 0) and auto-switched onto an empty gun in the cyberdemon arena. Now 5 in reserve (6 shots with the mag), matching the BFG, under the 30 cap.
  • Shorter player-damage flash (#283): the all-white flash held ~3 frames (0.05s) and masked the gun / enemy / HUD even on armor-absorbed hits. Trimmed to ~2 frames (0.03s); the red i-frame wash + hurt-arrow still carry the hit.
  • Quicker strafe for dodging (game-feel): physics/strafe-speed 2.4 -> 3.0 u/s. Still slower than the 4.5 forward run (a sidestep, not a teleport) but quick enough to clear a caster bolt's path during its wind-up, so dodging reads as skill.
  • Kill-streak window widened 4s -> 7s (combat/streak-window-seconds): enemies respawn on a 3-6s band, so a 4s window reset the streak on nearly every kill (HUD stuck at 1). Sizing it above the respawn band lets a steady kill pace chain. Scoring/HUD only.

Performance

  • Compiler call inlining (issue #166): with phel-lang 0.46's let-body inliner (#2586 + the rename fix phel-lang#2622), ^:pure now inlines hot LET-BODIED pure helpers at opt level 2 (splicing the body, dropping the per-call getDefinition frame dispatch). ~45 helpers tagged - per-cell map/cell (~600-1400 calls/frame) + map/wall?, per-ray engine/cell-at + projection/wall-px, enemy/in-cone?, and the per-enemy / per-frame AI + physics + render-math helpers - plus the existing let-free physics/contribution / counter-on?. Byte-identical (full suite + golden hashes unchanged). Requires phel-lang/phel-lang ^0.46 (bumped from ^0.45). See docs/performance.md.
  • Render hot-path globals (issue #262): pin referred frame-math globals (tex-fade-table, bg-cell-cache, seam-darken-*) as frame-level locals in frame->string and hoist floor-flat? / vh-1 out of the inner loops, killing per-row / per-cell Phel::getDefinition() calls. Byte-identical; measured -5.9% at 180x40 (no-JIT local).
  • Throttled the per-frame terminal-size poll (issue #280): term-size forks + execs stty size (~1ms) every iteration. The four size-polling loops now sample every 6th frame and reuse the last dimensions (~5/6 fewer forks); first frame eager, a resize noticed within ~6 frames. Fixed-size frames byte-identical.
  • Dropped a per-column closure in build-wall-sub-bounds: rewrote the mix? flag from an and/or (which Phel compiles to a per-column IIFE closure capturing the whole frame->string scope) to a nested if ternary with zero capture - the documented closure-tax fix. Byte-identical.
  • Cached the px2 weapon-sprite floor gradient (render/floor-gradient-full-for): it was rebuilt every frame (~0.2ms) though it has no pitch shear and vh only changes on resize. A single-slot vh-keyed memo makes it O(1). Pixel-doubled mode only; byte-identical.

Removed

  • Removed the verticality / multi-tier system (issue #325): a deliberate full flat reset for a clean-slate redesign later. Reverts all the unreleased verticality work - per-cell floor (#232) + ceiling (#235) heights, Z physics with auto-climb / fall damage / handrails (#233/#299), multi-tier stair rooms + showcase (#237/#298/#310), enemy tier AI (#301/#311), cast riser/ceiling accumulators + second riser (#322), tier render bands / palette / sprite ground-pads / cross-tier occlusion (#236/#302/#304), floor-height hitscan anchoring (#291/#297). L2-L8 are flat rooms again, each keeping its identity (name, enemy mix, chase, lock, weapon drop, size). The look up/down pitch aim (#231/#240/#243) stays (a camera shear, not verticality). Byte-for-byte identical render.
  • Removed the Reduced motion setting: a no-op once the calm 3D view shipped as default - the toggle, the persisted :reduced-motion key and the PHEL_DOOM_REDUCED_MOTION env var are gone. Old settings files with the key load fine (unknown key ignored).

Fixed

...

Read more

v0.15.0

Choose a tag to compare

@Chemaclass Chemaclass released this 16 Jun 18:45
v0.15.0
a8d0fab

Added

  • Navigable pause menu (issue #203): p opens a Resume / Settings / Restart / Quit menu (up/down move, enter or space selects). Settings opens the options sub-page (enter/space/p back); Restart restarts from level 1 with a fresh seed; Quit exits. Paints only when paused, so the 3D loop is untouched.
  • Colorblind-safe minimap palette (issue #200): a Colorblind setting (none / deuteran / protan / tritan) remaps keycard and door markers - the only minimap glyphs told apart by colour alone - to a brightness-plus-hue CVD-safe triad (red-green: sky-blue/orange/white; blue-yellow: blue/red/white), a key and its door sharing one code. Overlay-only, no hot-path cost.
  • Reload-ready cue: a one-shot bright-green READY! flash at the reload-reminder row when a reload finishes.
  • Locked-door deny click: bumping a locked door without its key plays a muted click (at the ~1.5s NEED <COLOUR> KEY hint cadence) so a blocked door reads by ear.

Changed

  • Berserk window trimmed 20s to 18s: still chains two or three room clears, but ends with use-it-or-lose-it pressure.
  • Critical-HP heartbeat eased 0.85s to 0.90s in the 3-4 heart tier for a clearer first thump; the last-heart 0.55s panic tier is unchanged.

Fixed

  • Settings persistence dropped 5 of 9 fields: crosshair, run timer, reduced motion, high contrast and colorblind were never written to the settings JSON and reset to defaults on every launch (only music, SFX, minimap and difficulty survived). All nine now round-trip; enum fields save as their bare keyword name and a malformed value heals to its default on load.

Checksum

SHA256: 7bb98c70190a75c78e6346895828722ab76c71df90b8b35fe679857a57488af3

v0.14.0

Choose a tag to compare

@Chemaclass Chemaclass released this 14 Jun 14:24
v0.14.0
204f756

Added

  • Distance fog fades toward a near-neutral light-grey haze instead of pure black, with a filmic (ACES-ish) brightness curve: distant walls and floor converge on the same grey haze (aerial perspective) and mid-tones gain contrast, so depth reads "hazy/far" not just "dark". Baked at load (fade-256-fog re-quantizes via palette/nearest-256), so the hot path is unchanged. PHEL_DOOM_FLAT_FOG=1 restores fade-to-black.
  • 2D minimap is now a framed HUD panel: box-drawing border with a cyan MAP title, inset one row from the top, flush to the right edge. Overlay only - the 3D loop skips the bounded panel rect, render-ms within noise. Fog-of-war, all markers, --full-map, and narrow-terminal auto-scale unaffected.
  • Pickups render as real Freedoom item sprites instead of flat coloured quads: the LOD threshold dropped to max(2, 2*lodr) (height min(16*lodr, 0.55*sprite_h)), so they engage wherever the item is >= 2 rows tall - coloured-glow fallback kept for extreme range / PHEL_DOOM_NO_SPRITES=1. Baked via a separate rgb->256-pickup (gamma=0.50 lift only, no enemy gray-shift).
  • End-screen run summary + letter rank: death/victory screens show accuracy %, secrets found/total, damage taken (HP lost; armor-absorbed hits don't count), a per-weapon kill breakdown (most-used first), and a colour-coded rank S/A/B/C/D (0.7*accuracy + 0.3*secrets, a secret-less run never penalised). The :shots-fired/:shots-hit/:damage-taken/:kills-by-weapon counters accumulate across levels; grade + accuracy live in core/format.
  • Crosshair hit-marker: a connecting shot flashes over the reticle for ~0.12s - bold-red on a kill, bold-yellow × on a wound. New :hit-fx {:kill? :ttl} stamped in the combat step (single-target, pierce/spread, BFG-splash); fires only on confirmed contact, kept under reduced motion.
  • 8-way directional damage feedback: a hit paints a red arc on the screen edge the attacker came from - a centred bar for the four cardinals, an L at the corner for the four diagonals - so you read the exact incoming bearing during i-frames. New :hurt-dir octant (attacker-octant); the 4-way :hurt-side stays for blood-drip columns. Kept under reduced motion.
  • Reduced-motion toggle (Settings, default off; PHEL_DOOM_REDUCED_MOTION=1 to force on): photosensitivity-safe mode that drops the lights-flicker strobe; holds the heartbeat edge, berserk border, pulsing HUD labels and powerup banners steady; suppresses the jump-scare flash; statics the door-eye. Single-shot feedback (hit-vignette, kill flash) kept. New :reduced-motion setting.
  • High-contrast HUD toggle (Settings, default off): un-dims grey HUD elements (compass non-facing letters, empty heart pips, healthy ammo reserve) to bold white so the HUD reads on washed-out terminals. New :high-contrast setting.
  • Two new pause/options settings: Crosshair style (+ / · / / off, hit-marker still flashes when off) and an always-on Run timer (M:SS in the HUD). Both persist to the settings JSON; the :enum cycler was generalised so each field carries its own :choices.
  • Every level states an objective on its intro splash: FIND THE EXIT (orange, matching the compass exit arrow) on plain levels, plus the existing FIND THE <COLOUR> KEY (locked) and KILL THE BOSS TO ESCAPE (boss).

Changed

  • Enemy sprites render cleaner and fog with distance: each baked sprite carries box-filtered half/quarter mip levels picked by on-screen size (far less sparkle; near monsters byte-identical), and every texel routes through a 24-level fog LUT on the wall darkening curve, so a far monster sinks into the haze and a wounded one reads darker. Corpses, blood, fireballs and near-LOD pickups share the fade. Cost: one extra aget per texel (bench within noise).
  • Doors render as real textured doors: a procedural 64x64 amber metal door (rust border + frame, six planks, mid rail) sampled through the stone-wall texture path, replacing the striped-curtain face. Panels scale with perspective, fog is floored so a door never fades to black, and the 4 rad/s pulse breathes brightness. Boss door keeps its flat pulsing red slab.

Fixed

  • Far enemy sprites now show readable humanoid silhouettes instead of blobs: three load-time passes added to the m2 mip build in enemy_sprite.phel - min-opaque=1 box-filter preserves thin features (head, horns, limbs), a luminance contrast-stretch (min-range 40) restores light/dark separation, and silhouette edge darkening (frac 0.40) outlines the figure. Load-time only; per-frame cost unchanged. Near/mid LOD paths untouched.
  • Enemy sprite bodies are no longer near-black silhouettes: the bake tool applies a per-channel gamma=0.50 lift (tone-lift) before quantization (preserving hue), plus a +3-step gray-shift (gray-shift) on ramp codes. Sprite fog runs at half wall strength so shading bands survive at range, while the wound-damage tint is not halved (health-state readability kept).
  • Enemy sprite bodies read as warm olive-brown instead of gray: a warm-bias redirect in rgb->256-lifted (tools/bake-enemy-sprites.phel) maps tone-lifted pixels whose source is warm (r-b >= 12) to warm cube codes, raising warm coverage from ~31% to ~80% of opaque imp pixels. Neutral pixels (pure grays, the cacodemon's blue) unaffected. Sprites rebaked from the Freedoom WAD.
  • Pickup sprites no longer render as pale gray slabs: enemy_sprites_data.phel rebaked from the WAD via rgb->256-pickup (gamma=0.50 lift only, no gray-shift, no warm-bias), so the armor vest, ammo box, and soulsphere show correct olive-green, brass, and blue.
  • Sprites no longer show color-confetti on brown/tan art: the bake quantization now matches against the real xterm-256 cube levels (0/95/135/175/215/255) by nearest-squared-distance instead of evenly-spaced thresholds, so source browns stop rounding to spurious blue/green.
  • Mid-distance sprites no longer show speckled noise columns: mip-switch thresholds tightened (native below 1.5x oversampling, half below 3x, quarter at 3x+) and sub-row sampling shifted to center-of-footprint, removing the corner bias. No render-time cost.
  • Mid-distance sprites no longer merge into the dark wall behind them: the distance-fog cap dropped from 0.85 to 0.65, so a monster at max range stays at least 35% lit. The squared falloff curve is unchanged.

Checksum

SHA256: c29b159072c31168b43a209d194cd78bf5c773966fc7c92f7f8b8a31e120c0c4

v0.13.0

Choose a tag to compare

@Chemaclass Chemaclass released this 11 Jun 09:40
v0.13.0
6a56c60

Added

  • Half-block sub-pixel floor, walls, and sky: each cell emits a upper-half-block with independent top/bottom colours, doubling vertical resolution so stonework and the ground read with smaller, squarer pixels. Two colours is all a terminal cell carries, so this is the fidelity ceiling that does not throw colour away. halfblock memoizes each colour pair into a ready paint cell (~+2% CPU); bytes/frame rise ~50-70% on big screens - cap with --max-cols. PHEL_DOOM_NO_SUBPIXEL=1 restores flat one-colour cells.
  • Textured stone walls: plain walls sample the baked Freedoom flat (WALL70_2) via a per-column texture U, fogged by distance + side shading through a prebaked fade LUT (~2% render cost). Doors / boss door / blood-wash columns stay flat as nav cues. PHEL_DOOM_FLAT_WALLS=1 restores the flat look.
  • Textured floor: the ground plane is floor-cast from the same stone texture (distance-fogged, pulled darker so it reads as shadowed ground). Per-cell sample is two mul-adds + a texture fetch, no trig (~+12% render cost). Blood columns keep the red gradient; PHEL_DOOM_FLAT_FLOOR=1 restores the flat gradient.
  • Sharper enemy/pickup sprites via 2x2 quadrant sub-cells: fully-opaque interior cells reduce their 2x2 sample to two colours and pick a quadrant glyph (▘▀▌▚▛▜▙█); transparent/edge cells keep the half-block so silhouettes stay clean.
  • Auto-calibrated pixel detail, always full screen: the game renders a few full-detail frames under the intro splash, measures the real render time, and only when the machine needs it locks a pixel-doubled mode - half-resolution scene, each cell painted as a 2x2 block, ~4x cheaper, still filling the whole terminal. Framing, FOV and sprite sizes match full detail exactly (no zoom), sprites keep 2x2 sub-pixel detail, and sky/floor/walls keep full vertical colour fidelity (four vertical sub-samples per scene cell); only the horizontal axis gets chunkier. Stable per session, recalibrates on terminal resize.
  • --max-cols=N / --max-rows=N flags override the auto mode: a positive value fixes an inset render size (anchored top-left), --max-cols=0 forces the full terminal at full detail. Unset = auto.

Changed

  • Wide terminals render crisp 1:1 walls: the big-screen "perf mode" that cast one ray per 2 columns and replicated it (chunky walls past 200 cols) is removed; every terminal size uses the exact 1:1 cast.
  • Ammo-box budget scales with difficulty (hard x1.2, nightmare x1.5 on the enemy-HP baseline), so spray weapons (chaingun, incinerator) don't starve when faster enemies raise the miss rate.
  • Heal/armor pickups scale with difficulty: nightmare seeds 2 hearts + 5 armor shards per level (hard 1 + 4) vs the 1 + 3 baseline. Rare powerup odds (berserk/invuln/soulsphere) stay flat.
  • Kill-loot drop rate bumped from 25% to 35% (ammo 22%, armor 8%, heart 5%): the 8-weapon roster made 3-in-4 kills dropping nothing read as sparse.

Fixed

  • Diagonal wall edges: wall/floor and wall/sky junctions on textured walls used to step in whole-cell stairs (bright edge band per tread at full detail, mushy stone-on-stone seam in pixel-doubled mode). Both modes now trace the exact diagonal at sub-row precision with a graduated dark seam - near-black wall base line, darker first floor sub-row, lighter lip at the sky seam - so receding walls read like the floor texture's own perspective diagonals. Doors / boss door / blood columns keep whole-cell bands as nav cues. ~15% render cost at full detail, no measurable cost pixel-doubled.
  • Pixel-doubling only engages on genuinely big screens (cell area beyond 200x45): a normal-sized terminal keeps full pixel detail even when the measured frame cost misses the smoothness budget - at that size detail beats framerate.
  • Big-terminal rendering no longer shrinks into a small top-left inset: the first auto-smoothing pass capped the render area and left the rest of the terminal stale; replaced by the full-screen pixel-doubled mode above.
  • Floor texture cracks no longer read as harsh black speckle: the floor samples a contrast-softened copy of the texture (texels lerped toward mid-grey, codes compressed from 232-249 to ~237-246) so cracks calm to a gentle mottle; walls keep full contrast. Precomputed at load, no extra floor cost.
  • Wall/floor stone texture no longer shows colored confetti: the baked WALL70_2 flat carried colored seam columns, a corrupt top band, and saturated specks; the bake is sanitized to a pure grayscale ramp (luminance-remapped, corrupt rows + border columns repaired). Stone structure preserved.
  • Crosshair reads clearly on any background: the idle reticle is a solid bold bright-white + (bold bright-yellow on fire, keeping the one-row recoil jump) instead of the faint/dim SGR smudge, and its backdrop now reuses the centre cell rendered by the row loop verbatim, so the + always sits on the true wall texture / floor / sky / sprite pixel instead of a mismatched flat shade.
  • Horizontal FOV clamps at 100° on wide terminals: the ray spread widens naturally up to ~167 cols, then holds instead of bowing toward 110°+ edge fisheye; extra columns add horizontal resolution. Narrower terminals and wall scale unchanged.

Performance

  • 4-10x faster rendering at every screen size, byte-identical output. Phel compiles a let binding whose value is a cond/and/let into a PHP closure that copies all ~500 in-scope locals per invocation; the per-cell render loops paid that closure tax up to 7 times per cell. Both emitters now resolve each cell through statement-position conds writing into a tiny register array, with row-constant work hoisted out of the column loop. Measured (3-enemy corridor, interpreted PHP): 80x24 26.7 -> 7.1 ms, 120x30 44.7 -> 8.9 ms, 200x45 114.0 -> 13.6 ms (8.8 -> 74 fps), 240x60 pixel-doubled 56.7 -> 12.9 ms, 300x80 pixel-doubled 87.6 -> 17.3 ms. Every size sustains 55+ fps on the reference machine (md5-verified over a 24-config matrix); pixel-doubling stays the big-screen/slow-hardware reserve and simply engages far less often.
  • Big screens are no longer capped at 30fps: the perf-mode cadence ceiling is gone; cadence is a uniform 60fps target at every size and framerate tracks render capability.
  • Sky/floor gradients are memoized by viewport height: rebuilt only on resize instead of every frame, worth ~0.3-0.5ms/frame at 40-100 rows.

Checksum

SHA256: bf9e145fd2a3f0aa568b40c4049c96af61778c3c2c7373b54d86460834f48b60

v0.12.0 - Freedoom Visual Overhaul

Choose a tag to compare

@Chemaclass Chemaclass released this 09 Jun 08:30
v0.12.0
778895e

Added

  • Freedoom enemy sprites: monsters render as real DOOM-style billboards (imp, demon/pinky/spectre, cacodemon, baron, cyberdemon, revenant, archvile, mancubus), half-block sub-pixels at native aspect, depth-occluded. PHEL_DOOM_NO_SPRITES=1 keeps the glyph enemies. See docs/rendering.md.
  • Freedoom death + fireball sprites: kills play a per-type collapse-to-corpse animation instead of a red block; enemy fireballs use the real DOOM projectile sprite. Both fall back under PHEL_DOOM_NO_SPRITES=1.
  • Freedoom weapon viewmodels: first-person guns (pistol, shotgun, chaingun, chainsaw, BFG, incinerator, rocket) drawn as Freedoom sprites. PHEL_DOOM_NO_SPRITES=1 keeps the ASCII guns.
  • Freedoom weapon-fire sounds: each weapon plays its real DOOM-style report (baked Freedoom DMX, license-clean). See docs/audio.md.
  • Freedoom pickup sprites with distance LOD: floating items render as real DOOM sprites up close and as a clean colour blob at distance, so far pickups read clearly. PHEL_DOOM_NO_SPRITES=1 keeps the glyphs.
  • Energy-weapon muzzle flash: BFG, incinerator, and rocket show a Freedoom muzzle burst while firing; hitscan guns stay flash-free so their recoil reads.
  • Traveling BFG ball + rocket: a cosmetic Freedoom projectile flies from muzzle to impact and recedes as it travels (damage stays instant).
  • Weapon recoil: every gun snaps up and settles when fired.

Fixed

  • Quitting no longer leaves a stray escape sequence (e.g. 3;1:3u) on the shell prompt: the terminal's kitty key-release report is drained before cooked mode returns.

Removed

  • Super shotgun (weapon slot 8) and everything unique to it: weapon spec, slot-8 key, the L8 pickup drop, its ASCII silhouette and sound. The roster is the seven classic-DOOM weapons (slots 1-7), all with Freedoom sprites and sounds.

Checksum

SHA256: a7551fe5906ca286b8839f8445670c9ed69f8b5b466ca92f4c4bf1f99e03707f

v0.11.0

Choose a tag to compare

@Chemaclass Chemaclass released this 08 Jun 17:21
v0.11.0
22fcb49

Added

  • Background OST: an original, license-clean procedural riff (driving E-minor ostinato) loops under the run to evoke the original DOOM, replacing the old ambient drone bed. Synthesised on the fly (no shipped asset), seamless loop, rides the Music volume slider, and toggles with N. See docs/audio.md.
  • Landing page (site/): a retro-terminal static page (CRT scanlines, animated install terminal, feature grid, controls, gameplay video), auto-deployed to GitHub Pages by .github/workflows/pages.yml on any change under site/.
  • Tech-talk demo (demo --phase 1..4): a progressive reveal - 1 bare raycaster (arena + central pillar), 2 +pistol, 3 +enemies, 4 +interior cover walls - with the full minimap on. Reuses the real engine via a pure world->world per-phase transform. See docs/demo-showcase.md.
  • Level 7: a yellow-keyed locked exit + yellow keycard pickup - the third keycard colour (blue/yellow/red).

Changed

  • Weapon fire report is distance-attenuated: full volume point-blank, down to a ~0.1 floor when far, full on a clean miss. Scaled by your SFX setting.

Fixed

  • SFX volume setting is now respected: the audio probe no longer resets the SFX scalar to full on the first sound, so shots no longer stay loud at low SFX %.

Checksum

SHA256: bb5d1a694b72b278079a05715bc187ca30b5c07a4963b09e3f6b4e8571edaf57

v0.10.0

Choose a tag to compare

@Chemaclass Chemaclass released this 03 Jun 14:37
v0.10.0
9b679b5

Added

  • Start-menu welcome box and credits screen show the current version, sourced from a single src/core/version.phel constant that tools/release.sh bumps (also feeds --version), so a release updates it everywhere at once.
  • Each release publishes a SHA256 checksum of the PHAR: a checksum asset (verify with shasum -a 256 -c checksum) plus the hash in the release notes.

Changed

  • Start-menu welcome box restructured: controls now in two columns, with how-to-play kept below and the compass-hint section dropped, so the box is shorter and fits more terminals.

Checksum

SHA256: 0dde95f10d1f62a4344bf0d6f50c9adfdb873e3ae1a3bf6741884da4bb7b97a5

v0.9.0

Choose a tag to compare

@Chemaclass Chemaclass released this 03 Jun 13:39
v0.9.0
0c8ec30

Added

  • Distributable single-file phel-doom.phar (~2 MB): bundles the game with the Phel runtime into one executable. ./tools/release.sh builds, smoke-tests, and attaches it to each GitHub release. Run with php phel-doom.phar.

v0.8.0

Choose a tag to compare

@Chemaclass Chemaclass released this 02 Jun 15:21
v0.8.0
72beaee

Added

  • Super shotgun (#126). Slot 8, found L8: a high-burst tank-killer, :damage 5 over a wide but very short cone with a 2-shell barrel and slow reload. Beats the shotgun's TTK on 4-5HP tanks with no BFG ammo cost; appended so keys 1-7 keep their meaning.
  • Rocket launcher (#123). Slot 7, found L5: single-action mid-tier AoE (splash r2.0 / 3) between the chaingun and the BFG. Reuses the splash path; cheaper and more available than the BFG.
  • Incinerator (#122). Slot 6, found L6: a fast short-range :fire stream, the first weapon to deal :fire - activating the per-enemy resist system (caco / baron / archvile / mancubus shrug it off).
  • Run times show as a clock (M:SS, or H:MM:SS past an hour) on the victory/death screens, the best time, and the info-menu RUN line (#131).
  • Info menu lists F5 / F9 quick save / load, so the feature is discoverable in-game.

Changed

  • Each weapon now has its own gun-sprite silhouette, not just a recolour: the chainsaw shows a toothed blade over an engine (no barrel), the BFG a bulky cannon with a glowing aperture, the incinerator a thin nozzle over a fat fuel tank, the rocket a straight round tube, and the super shotgun a stubby twin-bore. Previously every weapon past the chaingun reused the pistol shape.
  • Berserk is melee-biased with a full heal (#127): pickup restores full health, and the rage window boosts melee (chainsaw x6) far more than guns (x2) - the DOOM "go punch everything" identity, not a flat all-weapon multiplier.
  • Shotgun fires a cone graze (#125): the nearest enemy takes full damage and up to two others in the cone are grazed - a crowd weapon, not one big hit.
  • Pistol pierces (#124): its round hits every enemy in the line, its edge over the higher-DPS chaingun. Overheat dropped (jamming the forced fallback weapon is anti-fun).
  • press R to RELOAD reminder is weapon-aware (#128): arms on the remaining-mag fraction, suppressed for single-round mags (the BFG).
  • Deeper wall shading: flat stone (no speckle), gamma distance falloff, stronger corner contrast.

Fixed

  • Info-menu WEAPONS table columns align: long names no longer collide with dmg, 2-digit damage no longer shifts the ammo column, and unowned --/-- rows line up.
  • Wall-top/ceiling seam no longer shows scattered dark dots (the edge cell now samples the gradient instead of a flat shade).
  • Start-menu settings (s) apply and persist (music/sfx/minimap/difficulty edits were silently dropped).
  • Chainsaw (slot 4) is obtainable: drops on L4 and included in --armory (was unreachable).
  • Powerup spawn odds and placement margins match their documented values (rng/int! off-by-one).
  • Settings cursor moves once per arrow tap (kitty release events no longer double-count as navigation).

v0.7.0 - Settings, BFG & half-hearts

Choose a tag to compare

@Chemaclass Chemaclass released this 01 Jun 20:13
v0.7.0
05b4e3f

Added

  • Settings page (#107). Pause (p, or s on start menu) sets music/sfx volume + default minimap/difficulty; arrows or WASD; persists to ~/.phel-doom-settings.json (afplay, macOS).
  • Half-heart health. 10 HP = 5 hearts; per-type hit damage (melee 1, casters 2, cyber 3); armor soaks a whole hit.
  • Demo record / replay (#64). --record / --demo on a seeded Park-Miller RNG.
  • Quick-save / load (#63). F5 / F9 to versioned JSON slots; fog re-reveals.
  • BFG splash weapon (#58). Slot 5: plasma beam + 3-cell AoE that ignores fire-resist.
  • Secret reward passages. Reveal a secret wall (F) for ammo + shard + a powerup.
  • Hit-stop on meaty kills (~70ms, boss ~160ms); trash mobs stay fast.
  • Ambient drone loop. Synthesised crash-safe bed, N-gated.
  • Projectile casters. Cacodemons + barons fire dodgeable, telegraphed fireballs.
  • Wandering idle enemies pace until LOS flips them to chase.
  • Backpack stacking (#68). Up to 3; reserve cap scales with level.
  • Armor shards (#68). Bank +1 past max to 2x.
  • Soulsphere (#68). Over-caps lives, decays back.
  • Remote switches (#62). F flips linked wall/floor cells.

Changed

  • Bump phel-lang/phel-lang to v0.41.0 (first pinned stable; was dev-main).
  • Caster tuning (#94). Slower, longer-telegraphed fireballs on a shorter cooldown; casters slower than melee.
  • Progressive difficulty. Chase speed climbs L1-L9, eases at L10; archvile caster (L8); L6 / L7 gain casters.
  • Per-level monster variety. L2-L5 mix melee into the headline type; L1 stays pure imps.
  • Start menu explicit keys: ENTER starts, s settings, q quits.

Fixed

  • Settings nav was dead on non-CSI arrows (SS3 / kitty under tmux); now counts every encoding + WASD fallback, in-game turning handles SS3 too.
  • Mixed-level enemies spawned at 1 HP; now use catalog HP (default-lives-for).
  • R (restart same map) reproduces geometry + spawns via core/rng.
  • Weapon report went silent on a connecting hit; every shot now plays its fire sound + kill cue.
  • Enemy face drew over closer sprites (#91); now gated by the front-most check.
  • Stale :pgrid after grid mutations (#61) let you walk through walls; rebuild-pgrid resyncs.
  • SHIFT+WASD sprint was a no-op on non-kitty terminals; capital WASD now arms :sprint.