A native Apple-silicon macOS and iOS game in a raw black-metal style β six falling-block puzzle modes on one shared, deterministic core. Written in Swift with SwiftUI and SpriteKit.
π Sprache / Language: English Β· Deutsch
Ready-made, Apple-notarized macOS builds are available as DMGs on the releases page: download the DMG, open it, and drag Steinregen into the Applications folder. Requires macOS 15+ on Apple Silicon. To build the macOS or iOS app from source, see Build & Run below.
- Rockfall (Columns-style) β falling columns of three stones. Line up three or more of the same kind horizontally, vertically, or diagonally to clear them; cleared stones make the ones above fall, which can set off chain reactions for bonus points.
- Entombed (Tetris-style) β falling tetromino pieces (four-block shapes). Fill a whole row to clear it. Seven shapes, a 7-bag randomizer, simple wall kicks.
- Blood Clots (Puyo-style) β falling two-stone pairs in four colors. Four or more of the same kind connected side by side clear; the halves fall independently, and cascades chain.
- Crushed (pentomino variant) β Entombed's brutal sibling: all 18 one-sided pentominoes (five-block shapes) on a bigger board.
- Exorcism (Dr.-Mario-style) β the board starts littered with curses that stick in place. Three colors; four or more in a row or column clear. Purge every curse and you win β the only mode with a victory condition.
- Reaper (Lumines-style) β falling 2Γ2 blocks of two stone kinds. Same-colored 2Γ2 squares are marked and then harvested by a scythe line sweeping across the board.
All six modes run on the same deterministic core and share the look, sound, music, and high-score list. Pick the mode (and per-mode board size) on the start screen.
Pitch black, bone white, a single oxblood accent, film grain, a jagged hand-inked logo, and AI-generated foggy-night backgrounds. The six stones are told apart by a white sigil (shape), backed by a muted, desaturated color tint.
- 6 stones, marked by sigils β inverted pentagram, inverted cross, Tiwaz rune, triquetra, skull, crescent. Told apart by shape, with a muted color tint as a secondary cue.
- Selectable stone sets β switch in Settings (with live preview) between six sets: the engraved "Sigils" and grimy "Doom" black-metal sets, three friendlier gem sets from the sibling project Zaubersteine ("Zaubersteine", "G20", "Jewels"), and a "FreeDoom" pixel-art set built from original Freedoom sprites. Adding one is a single renderer plus one registry entry.
- Configurable board size per mode, set in Settings.
- Selectable starting speed (levels 1β10), rising as you clear stones β or a constant "endless" tempo that keeps the starting speed.
- Graveyard (high-score list) β on death, enter a name (up to 16 chars). The persistent top 16 shows names and scores and is viewable from the menu.
- Sound effects β landing, clearing, rotating, level-up and game-over cues, with several random variants per event. In Settings you can pick Steinregen (locally generated), Freedoom (BSD-3-Clause), or Silenced; T toggles in-game.
- Music (AI-generated) β 13 atmospheric instrumental metal tracks in a random, non-repeating order: every track plays once before a new shuffle begins. Three were generated locally with ACE-Step XL Turbo and ten with MiniMax Music 2.6; all are 128 kbit/s stereo MP3. Music is on by default but only starts with a level, not in the menu; toggle it independently in Settings or with M in-game.
- Backgrounds β AI-generated foggy-night motifs (graveyard, dead winter forest, ruined cathedral, foggy moor, blood-red moon); a different one each game, never the same twice in a row.
- Magic Jewel (Rockfall) β a rare, bright column pulsing through all six sigils. Where it lands it wipes every stone of the kind directly beneath it from the board.
- Reproducible, seed-driven β the same seed replays the exact same game, move for move.
- Runs on Apple-silicon macOS (keyboard) and iOS / iPad (touch), sharing the same core and renderer. Intel Macs are not a supported release target.
- English and German β the interface follows your system language and can be switched in Settings.
Steinregen runs entirely offline. It has no accounts, analytics, telemetry, advertising, or network
code. Settings and the Graveyard are stored locally in the app's UserDefaults container and are
never transmitted.
On iOS the game is played by touch (tap to rotate, swipe to move/drop, plus on-screen buttons). On macOS, by keyboard:
| Key | Action |
|---|---|
| β β Β· A D | move the piece |
| β Β· W | rotate |
| β Β· S | soft drop (faster fall) |
| Space | hard drop |
| T | toggle sound effects (off = "Silenced") |
| M | toggle music |
| Esc | back to main menu |
Requires an Apple-silicon Mac with macOS 15+ and the Xcode toolchain.
swift build
swift run Steinregenbash tools/make-app.shBuilds an arm64 dist/Steinregen.app (ad-hoc signed, with a procedurally drawn Dock icon β an
inverted-pentagram sigil) plus a distributable dist/Steinregen-<version>.zip. Double-click the
.app in Finder, or drag it into /Applications. For a notarized, Gatekeeper-friendly build use
the entry points below (they require a Developer ID certificate and a notarytool keychain profile).
Three entry points, deliberately separated:
bash tools/make-app.sh # build only, stays in dist/
./install.sh # build, notarize, install into /Applications
./release.sh # build, notarize, package the DMG β never installs
./release.sh --publish # also tags + uploads the DMG to GitHub Releases
./release.sh --no-finder-layout # skip the Finder window layout (headless runs)
./release.sh --no-notarize # unsigned β quick local layout testinstall.sh and release.sh both notarize the app itself and staple its ticket before
anything else happens. That matters: an app that only travels inside a notarized disk image loses
its guarantee the moment someone drags it out. release.sh then notarizes and staples the disk
image as well.
Notarization needs a notarytool keychain profile. Keychain profiles are local to each Mac and are
never synchronized, so the name is taken from NOTARY_PROFILE or from this clone's own
configuration:
git config --local steinregen.notaryProfile <profile>
xcrun notarytool store-credentials <profile> --apple-id <apple-id> --team-id <team-id>The underlying tools can still be called directly for finer control β
tools/make-notarized.sh (app + notarized ZIP) and tools/make-dmg.sh (DMG).
Builds dist/Steinregen-<version>.dmg: the signed app inside a DMG with an install background and
an Applications shortcut, notarized and stapled so it opens without a Gatekeeper warning. The
background comes from tools/generate-dmg-background.swift (β assets/dmg-background.png).
Adding GITHUB_REPO=owner/name and the --publish argument to the signed command additionally tags
v<version> and creates the matching GitHub release with the DMG attached (notes from
CHANGELOG.md). It requires an authenticated gh, a clean local main, and an identical main
on the configured github remote (or GITHUB_REMOTE=remote-name). Only that release tag is pushed;
local archive tags remain private. The configured remote URL and GITHUB_REPO must canonically name
the same GitHub repository; after the push, the remote release tag must resolve to the checked
HEAD, and release creation refuses a missing tag. A release is cut per version bump β
documentation-only or other changes that don't bump VERSION produce no new DMG.
bash tools/make-ios-app.sh runGenerates an Xcode project from project.yml via xcodegen and builds + launches the app in the
iOS Simulator (needs full Xcode and xcodegen).
swift test alone fails on systems with only the Command Line Tools (no XCTest). Use the
Xcode toolchain:
DEVELOPER_DIR=/Applications/Xcode.app/Contents/Developer xcrun swift testThe non-publishing release preflight checks version consistency, required documents and licenses, local Markdown links, media pools, the social preview, shell syntax, private strings, release publishing contracts with fake git/gh tools, and β when installed locally β Git history with gitleaks. CI always checks out the complete history and runs a SHA- and version-pinned gitleaks gate:
bash tools/check-release-readiness.shThe app honors environment variables so it can be driven without the menu (useful for automated screenshots and smoke tests):
STEINREGEN_AUTOSTART=1 STEINREGEN_LEVEL=8 STEINREGEN_SEED=4242 swift run SteinregenSTEINREGEN_AUTOSTART=1β start a game immediatelySTEINREGEN_LEVEL=<1..10>β starting speedSTEINREGEN_SEED=<UInt64>β fixed seed (otherwise random)STEINREGEN_SET=<id>β stone set (sigil/doom/zaubersteine/g20/juwelen/freedoom)STEINREGEN_MODE=<id>β mode:saeulen(Rockfall),verschuettet(Entombed),klumpen(Blood Clots),fuenfling(Crushed),kapseln(Exorcism),schnitter(Reaper)STEINREGEN_ENDLESS=1β constant tempoSTEINREGEN_MUSIC=<0|1>β force music off / onSTEINREGEN_LANG=<de|en>β force the language (otherwise system language / saved choice)STEINREGEN_SETTINGS=1β open the settings dialog on launchSTEINREGEN_FRIEDHOF=1β open the Graveyard (high-score list) on launchSTEINREGEN_RULES=1β open the game-rules dialog on launch
Three Swift Package Manager modules plus tests:
SteinregenCoreβ pure game logic. Five engines (Enginefor Rockfall,TetrominoEnginefor Entombed and Crushed,PairEnginefor Blood Clots,CapsuleEnginefor Exorcism,SquareEnginefor Reaper), board, match detection, cascades, magic jewel, scoring. No global randomness and no wall-clock; all randomness flows through an injected, seeded PRNG, so a given seed always replays identically.SteinregenRenderβ SpriteKit scene that drives all modes through onePlayEngineprotocol: rendering, the gravity/animation loop, the procedurally drawn stone sets, the theme (palette/fonts/grain), sound effects, the music player, and the magic-jewel animation.SteinregenAppβ SwiftUI shell for macOS and iOS: menus, settings, rules, the Graveyard, and game-over overlay. Keyboard input on macOS, touch on iOS.
Several reusable building blocks (the seeded PRNG, the robust resource loader, the three-module layout) and the three "pleasant" gem sets (Zaubersteine / G20 / Jewels) come from the sibling project Zaubersteine.
Steinregen is an independent project and is not affiliated with, endorsed by, or sponsored by any of the referenced rights holders. Columns and Puyo Puyo are trademarks of Sega, Tetris is a registered trademark of The Tetris Company, LLC, Dr. Mario is a trademark of Nintendo, and Lumines is a trademark of its respective owner. Those names appear only as descriptive comparisons. Steinregen uses its own mode names and original presentation, graphics, and sounds.
The source code is MIT-licensed β see LICENSE. Bundled third-party and generated assets have their own terms and attributions; see THIRD-PARTY-ASSETS.md. In particular, FLUX.1 [dev]'s model license restricts use of the model but expressly allows generated outputs to be used for any purpose, including commercially. The app bundles include the MIT notice, this asset inventory, and the required Freedoom and font license texts.
Title/HUD typeface: Grenze Gotisch by Omnibus-Type, licensed under the SIL Open Font License.
The "FreeDoom" stone-set sprites come from the Freedoom project (its own free assets, not the original commercial Doom material), licensed under BSD-3-Clause.
The Steinregen sound set was generated locally with Stable Audio 3; the alternative Freedoom set is BSD-3-Clause material. Three music tracks were generated with ACE-Step XL Turbo, ten with MiniMax Music 2.6, and the foggy-night backgrounds with Qwen-Image. All ship as part of this project. See THIRD-PARTY-ASSETS.md for the full attribution and license overview.
Please report vulnerabilities according to SECURITY.md; never post sensitive details in a public issue.


