August 21, 2026 - prerelease - stable
Neo Angband v0.24.0
Neo Angband 0.24.0
What you can download
| Platform | File |
|---|---|
| Windows (installer) | Neo Angband Setup 0.24.0.exe |
| Windows (portable, one file) | Neo Angband-0.24.0-portable.exe |
| macOS | .dmg, or the .zip if you prefer to unpack it yourself |
| Linux | .AppImage (no install), .deb, or .tar.gz |
| Self-hosting | neo-angband-web-0.24.0.zip - static files, any web server |
The portable Windows build and the AppImage need no installer: download, run, and the game keeps its saves in a folder beside itself.
These builds are not code-signed
There is no Apple Developer identity or Windows certificate behind this project yet, so your OS blocks the first launch.
Windows is one click: SmartScreen says “Windows protected your PC”, choose More info then Run anyway.
macOS is not one click, and the dialog it shows you does not contain the way through - it offers only Done and Move to Trash. Do this:
- Drag the app out of the
.dmg, then double-click it and press Done on the refusal. This step is required: it is what makes the permission below appear, and it expires about an hour later. - Open System Settings -> Privacy & Security and scroll to Security, near the bottom.
- Press Open Anyway on the line naming Neo Angband, authenticate, and launch it again.
Or, the same decision in one command:
xattr -d com.apple.quarantine "/Applications/Neo Angband.app"
The old right-click -> Open trick does NOT work: Apple removed that bypass in macOS 15 Sequoia.
On Apple Silicon take the arm64 build. The x64 one is for Intel Macs, not a fallback - Apple is withdrawing Rosetta 2, so on a current Mac it is likelier to refuse to launch than to run slowly.
If that trade is not one you want to make, build it yourself -
docs/INSTALL.md - or play in the browser, which needs no trust decision.
Your save
Saves survive an update. Every save-format change ships the conversion that reads the version before it, and a save this build cannot open is left untouched rather than replaced.
Current state of the project at version 0.24.0 - a fixes release. Nothing
about the game’s rules changed. A game played with random artifacts on now
reloads correctly, which it did not; the desktop build checks a URL before
handing it to the operating system; a mod whose newest release needs a newer
game now offers one that runs here instead of refusing outright; and the mod
consent screen stopped implying that a short permission list bounds what a
mod’s code can reach.
Fixed
-
Random artifacts keep their created, seen and everseen flags across a reload, and a carried random artifact stays an artifact. With
birth_randartson, every artifact id in the savefile was matched against the STANDARD artifact names rather than the random ones. An id is a slug of the artifact’s name and the save was written from the random names, so nothing matched: an artifact you had already found came back unknown, and a random artifact in your pack, in a shop or on the floor came back as its plain base item. The artifact set is now rebuilt before those ids are resolved, reading the birth option and the seed as the file recorded them, so one resolver serves the save migration, the flags and every saved object alike. Upstream writes these fields positionally by index and so has nothing to lose here, which makes this the port’s own defect rather than a wart to preserve. A game withbirth_randartsoff is unchanged. -
A mod’s artifact keeps its provenance when random artifacts are on. The whole artifact array is replaced by the generated set, and the clone it was built from dropped two fields: the stamp saying which pack contributed the record, and the place a mod’s own fields on that record live. An artifact’s savefile id is minted from that stamp, so a mod’s artifact was written into the save under core’s namespace instead of the mod’s, and a plugin reading its own fields back off the artifact found nothing. Nothing about an unmodded run changes: core’s records carry neither field, and neither is read by artifact generation, which the recorded whole-set vectors confirm.
-
The desktop build checks a URL before handing it to the operating system. The update page’s reveal link and the external-link opener both called
shell.openExternalwith whatever string reached them, and the reveal link’s string usually begins as GitHub’s own release JSON, fetched over the network rather than built into the program. Both are also reachable directly from any script running in the game page, a mod’s plugin.js included, since a mod’s code is a plain module import into that same page. Neither origin was validated, so a scheme other than http or https would have reached whatever program is registered for it on your machine instead of a browser. The reveal link is now checked against this project’s own github.com releases pages and the external-link opener against http and https generally; either rejection is logged with what was rejected rather than failing silently.
Changed
-
The mod consent screen warns about the code for every mod that ships code, and the modding docs say what a permission actually gates. The warning used to appear only when one of the requested permissions was flagged powerful, which made it read as a consequence of the list: a plugin asking for nothing but a tile or vocabulary registry got a consent screen with no such line, and a plugin asking for nothing at all got no consent screen and a manager row reading
Asks for no permissions. That reassurance was wrong. Aregistry:*permission gates one convenience facade, and the same live registries arrive at the plugin a second time with no check at all, so a mod that declared no domain can still register a room builder, a cave builder, a dungeon profile, a vault glyph, an item class, a rune, a randart ability or a message type. Fourteen of the gated domains have such a twin. That is inherent in running trusted code inside the engine rather than a gap to close, since nothing reachable from inside the engine namespace can be withheld from code already inside it, so the words moved instead of the mechanism: the screen names the code, the manager row on a code mod that asks for nothing says it still runs code, anddocs/modding/PLUGINS.mdgains “What a capability gates, and what it does not” with the table of twins and the reason declaring still matters, which is that the player reads the declaration and the conflict report is built from it. The boundary that does hold is the install, which is where a player decides to trust a mod’s code at all. A test measures both halves, the gate refusing and the twin reaching, against the real bound registries and the real plugin context, so the prose cannot drift back into claiming containment. -
A mod whose newest release needs a newer game now offers the newest release that does not. The mod screen used to read
will not run on this versionand stop there, even when the same mod still had an earlier release that ran perfectly on your build. It now looks back through that mod’s earlier releases and offers the newest one your game can actually run. It names the newer release it stepped past, and it tells you to update the game only when updating the game is what would get you that release. A mod with nothing that runs here is still refused, and now says how many of its releases were tried instead of leaving you to wonder whether the older ones were looked at.- Update installed mods stopped offering an update the game would then refuse to load. A mod already on the newest release your build can run is described that way rather than as out of date, and the row says which newer release is waiting on a game update.
Found something that does not match Angband 4.2.6? Open an issue or come and say so in the Discord.