#nethack source code
Explore tagged Tumblr posts
hallowed-harlot · 10 months ago
Text
one day were going to get the tgirl tradrogue renaissance. games built on weird old tech with a unique and unused "artstyle" whos development leans on community and open source code? this is tgirl heaven
tradrogue: a traditional roguelike. usually: randomly generated dungeon crawlers. no cross run progression. player knowledge is the primary factor in success. see: Rogue (1980), Nethack (1987), Ancient Domains of Mystery (1994), Brogue (2007), Cogmind (2017), or any of dozens of other games
15 notes · View notes
cassette-fanfics · 7 months ago
Text
If you're reading this, hi! Hello!
Welcome to my little corner of the interwebs, where I gush about whichever cartoon or video game I'm currently hyperfixating on, reblog fanart and fandom memes, share my headcanons, post the silly ideas I've thought of while walking my dog, recommend fanfics I like, and talk about the fanfics that I will definitely write, eventually, bear with me.
Check out the #random musings tag for the- well- random musings I have throughout the day that I post on Tumblr because I didn't get to do so as a teenage girl so I'm doing it now.
Things I'm into:
Cartoons:
The Owl House,
Miraculous Ladybug,
the DuckTales reboot,
My Little Pony: Friendship is Magic,
Avatar: the Last Airbender,
Code Lyoko,
Ben 10 (haven't watched past UA),
Tangled the Series.
Video games:
NetHack and its variants,
Pokemon Scarlet and Violet,
Ace Attorney (original trilogy + Apollo Justice so far),
Super Paper Mario,
Cassette Beasts,
the Henry Stickmin collection,
Celeste,
Hollow Knight,
Stardew Valley,
Super Lesbian Animal RPG,
Celia's Stupid Rom-Hack,
Minecraft (but only singleplayer, on peaceful difficulty or in creative mode).
Other fandoms:
Pokemon Horizons - constantly a bit behind because I'm watching the Netflix dub (I know, I know),
Hearstopper - haven't watched season 3 yet, I will eventually,
Wednesday, but only through the lens of fluffy Wenclair fanfiction because I genuinely don't cope well with horror- or thriller-adjacent media,
The Wotch and El Goonish Shive webcomics,
the Back to the Future trilogy,
that one book series about a boy who learns he's a wizard (interest currently on hold, until the author comes back to her senses),
Ranger's Apprentice,
Percy Jackson & the Olympians and Heroes of Olympus (haven't had the chance to read past The Son of Neptune yet),
any sappy romantic comedy you could think of.
Things I'm interested in outside of fandom:
learning trivia related to the subtleties of translating a work of fiction from one language to another,
browsing through the source code of popular open-source libraries to see how they work from the inside,
cycling and skiing.
Things people have recommended to me that I've yet to get around to watching/reading/playing:
She-ra and the Princesses of Power,
anything Scott Pilgrim-related,
Hilda,
Kipo and the Age of the Wonderbeasts,
Arcane,
Tales of Arcadia,
Riders of Berk,
Star vs.,
The Lion Guard,
The Princess Bride,
My Hero Academia,
Little Witch Academia,
Kiki's Delivery Service,
Howl's Moving Castle,
Hamilton (musical),
Avatar: the Last Airbender post-canon comics.
4 notes · View notes
kawaoneechan · 2 years ago
Text
Some "achievements" a'ight...
So here's me looking at the achievements for NetHack Legacy, a Steam version of NetHack that apparently does not have the original developers' blessing and costs like five dollars unless you're willing to try and find the source code and then build it yourself. And the only reason the source code is there for free to begin with is to pay lip service to the original's license.
What do you get for your efforts? An in-game soundtrack, a CRT filter, some QoL from other NetHack forks, and of course achievements. So I'm looking at the list and...
Hmmm. It seems they couldn't think of any achievements for a roguelike either. That's the whole reason I started looking into the topic in the first place — Noxico used to have 'em for a short while, on my own self-hosted imitation system. There were like... two or three, mostly for testing purposes.
In NetHack Legacy, you get achievements for starting the game, one for each class, and another for having started at least once for each class. How is that worth anything? You expended literally no effort to earn this! You get one achievement for beating the game (good luck) and another for beating it as specific classes, and with various conducts. That's so much effort, statistically almost no NHL player even has any of these.
First of all, beating NetHack is not an easy feat and you're very liable to die trying. Two, beating the game while adhering to various conducts is among the most "proper achievements" stuff I've listed yet, but it's still super hard to beat the game in the first place.
And then there's the "NetHack Master" achievement. Description is hidden but the internal name is `ACH_ASCEND_ALLACH`, so that's the "beat the game all these other ways" achievement, if I had to guess.
According to Steam, "YES!" (the "beat the game at all" chive) has a 0.7% achievement rate. See? Statistically nothing. Specific classes? 0.1%, same as the conduct-specific ones. In case you doubted my words about NetHack being hard.
And then there's the quest and location achievements, which can be gained simply by playing long enough. Be a specific class, you're almost guaranteed to drop into your class' specific quest map.
The only standout I could find was "NetHacker", description hidden, but the ID tells me you get it for cheating in the Sokoban minigame.
Compare all that to Team Fortress 2. The "Crime and Punishment" achievement is earned by playing as a Heavy and killing ten enemies carrying your team's intel. This is achievement worthy because Heavy is slow and whoever carries the intel is likely to hotfoot it the hell outta there. You may even jump the gun and accidentally kill them before they grab the intel, and that doesn't count.
I don't think I need to tell you how different that is from, let's say, finding the Oracle in NetHack, which you are almost guaranteed to just stumble upon. I know this from personal experience with the original.
12 notes · View notes
alianoralacanta · 3 years ago
Quote
I learned that you should always write clean code that you won’t be embarrassed by, 35 years later, when it ends up in a museum.
Jean-Christophe Collet, one of the coders of Nethack, offers some sage advice to all software developers. NetHack, a rougelike role-playing game that has been in constant open-source development for the past 35 years, is to be included in the Museum of Modern Art’s collection, as an outstanding example of interaction design.
27 notes · View notes
procedural-generation · 8 years ago
Photo
Tumblr media
Nethack Level Generation, Part 2: Making Rooms
NetHack's maps are based around rooms and corridors. In gameplay, rooms are open areas that are usually lit, which makes them visible at a distance, while corridors are the connecting paths that are dark, which means that by default you can only see monsters that are one tile away. This creates a tradeoff between the bottlenecked corridors that are prone to ambushes and the more open spaces where you can see threats before they attack you. Doors are placed where corridors connect to the rooms, and have a chance to be secret doors. More than one player has gone down the stairs only to find themselves in a room that has no visible exits.
To create the rooms, makelevel() starts by calling two functions: makerooms() and sort_rooms().
The core of makerooms() is a while loop that runs until it reaches the maximum number of rooms (which is defined as 40) [] or runs out of places to put new rooms.
Each time it goes through the loop, it first check to see if it can try to place a vault. If it isn't placing a vault, instead it creates an ordinary room with -1 for all of the optional arguments. If it fails to place this room, it stops trying to place any more rooms, returning out of makerooms().
To place a vault requires the number of rooms to be at least one-sixth of the maximum (with the default max of 40 and C's truncation towards zero, this is usually 6). It also requires that no vault has previously been tried, plus a 50% random chance. It then calls create_vault(), which is a preprocessor macro for create_room() with a different set of arguments: (-1, -1, 2, 2, -1, -1, VAULT, TRUE). This creates a vault with a fixed size of 2 and guaranteed to be lit.
Either way, the bulk of the work is done in create_room(). Since this is also used by the special level system, it has some flexibility for specifying more kinds of rooms than the basic generator uses. It takes eight arguments: the x position, the y position, the width, the height, xal, yal, the room type, and whether it is lit.
The first step in creating a room is to check the requested light value; if it is -1, the lighting state is randomly set based on how deep the level is; once the player reaches level 10, there's an increasing chance that the room will be dark. (There's also a 1-in-77 chance that it will be lit, no matter the result of the first random check.)
Similarly, if any of the other arguments are -1, they will be generated randomly.
Way back in clear_level_structures(), the game built an array of rectangles in the level. This started as one large rectangle that covers the entire level. In create_room() it now grabs a random rectangle from this array. If this is our first room, there's only one rectangle to grab.
Rectangles are a struct with four variables: the low x and y coordinates, and the high x and y coordinates. (The terminology seems to date back at least to the early days of Hack, if not earlier.)
It picks some random coordinates based on the rectangle it grabbed:
Tumblr media
The result of all of this is a set of coordinates (absolute upper left corner x position, room x width, absolute y position, room y height) that define where it wants the room placed. 
Tumblr media
Using these values, it checks to see if a room will fit in that spot, shrinking it if necessary. If it fails, it starts over. If it fails more than 100 times, it gives up and returns with whatever rooms have already been created.
Assuming that a spot to place a room has been found, it splits the rectangle the new room is going to be in into smaller rectangles. It then adds the room to the array of rooms and writes the walls and floors onto the level map.
The next time through, create_room() will grab one of the smaller rectangles and attempt to put a room in it. If it fails completely, no more empty rectangles can be found, or MAXNROFROOMS is reached, then room creation is over and makerooms() returns.
Once makerooms() is done, sort_rooms() takes the array of rooms and runs a qsort on them, ordering them in the array according to their position on the map from left to right by their low x value.
(Unless you're compiling on Unix System V or DG/UX, in which case it uses a slightly different qsort call that passes the number of rooms as an unsigned variable. Same behavior, but demonstrates the lengths the code goes through for portability.)
The order of the rooms is going to be important for the corridors connecting the rooms, because it first tries to connect each room to the next one in the array. With a few more complications, which we'll get to next time in Part 3.
21 notes · View notes
krjpalmer · 4 years ago
Photo
Tumblr media
Computer Gaming World March 1992
A “World War II in the Pacific” flight simulator was promoted on this issue’s cover. “Are We There Yet?” referred not to “the future of computer games” but a computer game featuring “road trip puzzles,” and one small article talked about “public domain computer role-playing games” including NetHack, mentioning that those with “access to Internet/Usenet” could “get both the games and their source code.”
3 notes · View notes
hydralisk98 · 5 years ago
Text
alternae.dsk (plan / script)
Scenes list:
Animated introduction (Black BG, white snow, title and subtitles)
Paradise filesystem + Windows 3.11 interface ‘alternae.dsk’ exploration
Wolfenstein: The New Order (Boom Boom Wolfenstein TNO song over my Civ 5 nuclear rampage playtrough, William Strasser saying This is... a good one, Germans cracking the Allies’ code, )
Portal 2 & Stories Mel quotes (For science, I hate you so much, Agh Bird bird kill it it’s evil, Cave Johnson introduction with Caroline, ending GLaDOS lines, Ha I like your style You make up your own rules just like me, This sentence is false, Don’t come back, , Still alive song, Want you gone song, The answer is beneath us, I don’t blame you, I don’t hate you, No hard feelings, Whyyyy, )
DOOM Slayer memes (Hazbin Hotel video edit, that demon had a family I know they’re next, Simpsons Guitar Riff, Doot, Doom Eternal French edition, Bob Ross Brush, Atheist gamers when they die and realize that Hell is real, COVID-19, violence is a question and it says yes, Animal Crossing crossover stuff, DOOM guy crush #1 I love democracy)
Control the game
Black Ops 1 computer terminal
0x10c & Zachtronics & 16^12 memes (TIS-100 control unit ‘move’ what is my purpose, 0x10c forks, my 16^12′s Anzella memes)
Civilization 5 CE shorts with countryballs and planetballs
Civilization Beyond Earth Rising Tide
INTP mtbi
Pokemon Black & White
Democracy 3 and my political axes (Liberal very center somewhat left)
CRT TV/monitor heads
ASCII
RTTY
Command line interface is best interface
Manjaro Linux
Solaris
FreeBSD
MINIX 3
Classic and Power Metal songs
Internet Relay Chat & early World Wide Web
Quake 1
Quake 2 Raytraced
Half Life 2
Free and Open Source Software
Dwarf Fortress, Cataclysm Dark Days Ahead, Nethack
Europa Universalis IV
Venus planet
Neptune planet
Old world history
1910-2000
1-bit graphics (ZX Spectrum / Pentagon / Soviet clones demoscene)
Game Dev Tycoon
Eastern bloc cartoons and culture (OGAS, ‘69 abandonment of eastern  computer architectures, )
vintage electronics and technologies (PLATO, IBM 701, Intel 4040, )
choice threads
Greater German Reich ethos?
Space race
just Wehrmacht things
K’reel (Deathstars? Siths plz have you heard of kreel ray?)
Purge Slavery and Race systems + gene-modding customizations as of Stellaris
Robot inquisition
Colonizations
Nuclear wars
20th century log
Woodrow Wilson & his legacy must die
Xerox Alto and Xerox Star
Digital Equipement Corporation ‘DEC’
International Business Machines ‘IBM’
Symbolics
Maps
Flags
Miniatures
Cards
Mosi
TTRPGs
Talespinner & Pathfinder
‘Servitor’ game console master race
Lisp programming
Algol programming
Autistic culture
Ancient/Classical Greece
SEGA
YMCA Canada
Robotron K 1840 / DEC VAX
Jucika
Plan 9
Unix culture
Hexadecimal
Senary
12-bit-byte
Baba is You
4D Toys / Miegakure
Morphological freedom
Meme? Hak hak hak!
Philosophical aesthetics
Philosophical meta-physics
Animated ountro
[...]
0 notes
corysbitsandbots · 6 years ago
Text
Simulation of role-playing adventure or Multi-User Dungeons (MUDs), similar to NetHack, using basic rules of Dungeons & Dragons with a feel similar to Gauntlet or Diablo.
The pictures and video do not fully capture the brilliant color when seeing it for yourself.
youtube
The project makes a visually interesting simulation of a character wandering through a maze, looking for a key and trying to find the door to exit, only to be stuck repeating this for all eternity. Other enemy players try to kill the main character, can pick-up and use items including the key to open the door, resetting the maze. When any character dies, within a matter of time, regenerated with randomly selected base stats; forever stuck looking for potions to stay alive a little longer only to find another key and another door.
This is a new version of an older project: https://www.hackster.io/bitsandbots/existential-crisis-aka-arduinorpg-fdf238
Existential Crisis
  This simulation covers the basic motivation of fighting to stay alive in an effort to find the key hidden in the current map and then locate the door to exit.
Each player has hit-points, armor class, experience points, and can hold up to three items. Each map contains a key, and a randomly selected number of rewards, or items to help the player. Items available are: a potion of healing, a better weapon or magic.
A 64 RGB LEDs in an 8×8 display is used as the ‘viewer’ into the World of the simulation, displaying only a quadrant section of the overall map at one time. As the primary player moves around the map, the ‘viewer’ display moves to the relevant section.
Color Code:
RED – Opponent Player Characters ( Enemies )
GREEN – Main Player Character ( Game Focus )
BLUE – Wall
WHITE – Door
YELLOW – Key
#gallery-0-5 { margin: auto; } #gallery-0-5 .gallery-item { float: left; margin-top: 10px; text-align: center; width: 50%; } #gallery-0-5 img { border: 2px solid #cfcfcf; } #gallery-0-5 .gallery-caption { margin-left: 0; } /* see gallery_shortcode() in wp-includes/media.php */
Mini-Animations:
Find a key
Use a potion
Use magic
Open door using key
Player death
RGB LED Matrix
I have also included numbers 1 – 20 for showing the result of a simulated die roll. However, showing the number each time the player rolls is annoying so this animation has been disabled.
How the Simulation Works
On each turn, a player object executes the function WhatAreMyOptions
Move ( Direction Available: North, East, South, West ) A proximity-check to opponents is made to determine options. Short-term Memory of locations explored. Coordinates of recent moves are stored in the player object in an effort to reduce looping.
Attack: Each player rolls a 20-sided die trying to meet or exceed the Armor Class value of the opponent. Upon a successful hit, the player then rolls a 4-sided die for damage and applies any bonuses. The total damage is subtracted from the opponent’s hit points.
Check Inventory and Use Item: Randomly determined for simulation purposes.
Source-Code – I’m updating the source-code to look less like a collection of notes and more manageable.
Potential for Expansion using I2C
Add additional microcontroller or Raspberry Pi for Neural Network.
Add better controls, such as push-buttons, and even sensors.
Add a sound-effects module
Additional visual displays.
More About Electronics:
Why DIY when you could buy?
Why Arduino when you can Pi?
Making a Lightshow with Arduino
Making Sound Effects with Arduino
Working with Multiple Sensors and Arduino
Using a Raspberry Pi and USB Camera
Using a Raspberry Pi for your own Inventory Management System
More About hydroMazing:
Managing Nutrient Solution Systems
Setup hydroMazing Smart Garden System
Using Arduino to Wirelessly Control Appliances
More About Indoor Gardening:
What is a “Smart” Garden?
Starting a Smart Indoor Garden
Digging Deeper into Indoor Gardening
Indoor Gardening: What can go wrong?
    Existential Crisis – Role-Playing Game Simulator Simulation of role-playing adventure or Multi-User Dungeons (MUDs), similar to NetHack, using basic rules of…
0 notes
procedural-generation · 8 years ago
Photo
Tumblr media
NetHack Level Generation, Part 3
We're back in makelevel(), at line 666. The rooms are placed, but they're empty.
The one thing that every level needs are the stairs that will connect it to the levels above and below it. Unlike some other roguelikes with many stairs between levels, NetHack levels always have exactly one up stair, and every level except the bottom one also has one down stair. Plus, there is the possibility of a second down stair to one of the special branches of the dungeon.
To create the stairs, first pick a random room. If this isn't the bottom level, place the down stair at a random location in this room. Now, check to see if there is more than one room. NetHack prefers to place the stairs in different rooms, so if there are at least two rooms, it picks a new random room. This time, instead of picking from all of the rooms, it picks from any room except the last one. This is in case it randomly picks the same room that the down stair is already in, in which case it picks the room with the next highest number.
Whichever room it has selected, it places the up stairs in a random, unoccupied location within that room, by randomly generating coordinates in a while loop until it finds one that returns false for occupied(). At this point, "occupied" mostly means "the down stairs are in this tile". (This is terribly inefficient, but seldom matters.)
Then it checks to see if this level has a connection to a dungeon branch. This is where room_threshold finally gets set, with the ternary operator. If there is a branch, the threshold is 4; otherwise it is 3.
(If this is the special Rogue level, there’s a goto command here, to skip over this next bit. I told you this code was gnarly.)
The rooms are now connected with corridors via makecorridors().
First, it loops through the array of rooms, trying to join each room to the next one in the sequence. After each join, there's a 2% chance that it'll stop and go to the second step.
Second, it loops through the list again, this time trying to join each room to the room two steps down the array.
Third, it goes through the list of rooms, trying to join each room to every other room, but stopping once it runs out of rooms that aren't the current room (e.g. if there's only one room).
Finally, if there are more than two rooms, it picks a random number (based on the number of rooms), adds 4 to it, and then counts down, each loop attempting to link two random rooms. To keep the randomly selected rooms from being the same, it uses the same trick as with the stairs: a is random(number of rooms) and b is random(number of rooms minus two). If b is equal to or greater than a, add two to b.
As you can see, it attempts to add connections between nearly every room, so what is important here is the order the joins are attempted; join() tries to find places to put doors and then tries to dig corridors between them. It doesn't always succeed, which the algorithm takes advantage of. Enough corridors are placed to result in NetHack's characteristic look of rooms suspended in a sea of tunnels.
Once the corridors are placed, makelevel() calls make_niches()  to add closets  to the level, which are 1-square corridors-rooms that will either be connected to a room with a door (often a secret door) or which can only be reached by digging or teleportation.
For the number of niches, it picks a number between 0 and the number of rooms bitshifted to the right plus 1: rnd((nroom>>1) + 1). It also checks the depth: between level 5 and level 25 (noninclusive) there’s a chance for a trap door. And if the depth is greater than 15 and it’s a no-teleport level, there won’t be a teleport-trap niche.
Niche generation is handled by makeniche().
As long as the level hasn’t already exceeded DOORMAX, it runs a loop 8 times, picking a random room each time and attempting to place a connected niche. There’s some restrictions on where they’re allowed: only in ordinary rooms, only if there’s space to place it, etc.
If it can place a niche, it checks the requested trap type, and sets up the niche accordingly. Some traps get engravings (trap doors get “Vlad was here”).
Once there have been eight attempts at placing the niche, it finishes and returns, where we resume execution in makelevel().
Next time, we'll talk about adding special rooms and secret treasure vaults.
8 notes · View notes
procedural-generation · 8 years ago
Photo
Tumblr media
Nethack Level Generation, Part 1
Because so many roguelikes are open source, their map generators are available for examination. While many clearly borrow from each other, they also show a number of different approaches to procedural generation. Examining the source code can tell us a lot about what works.
NetHack is one of the major roguelikes, rivaling Angband at the most significant roguelike of the Usenet era. Unlike Angband, but like Rogue, it generates levels that are the same size as the screen and consist of rooms and connecting corridors. (It's close enough to Rogue that there's actually an optional Rogue-emulation bonus level!)
Nethack is mostly written in the 1989 version of ANSI C with some translation macro hacks to account for different compilers and versions of C. This makes for a fairly gnarly codebase, though it means that it is portable enough that the current version still runs natively on an Atari ST. The syntax isn't too hard to follow if you're familiar with the syntax of C++, C#, Java, or the like, but there's some weirdness even for C programs. (Many function declarations are actually preprocessor macros so the code can work on compilers with different ways of defining functions with a variable number of arguments.)
Because of this, I don't actually recommend copying NetHack's level generation line by line. It is undercommented and nearly three decades of development have left tons of hidden assumptions buried in the code. Or more than three decades: some of this code seems to date to Hack. Still, I think there’s a few things we can learn by looking at its approach.
Helpfully, the NetHackWiki has the source code of NetHack  in a relatively easy to access format. A few of the files have been annotated in great detail, though unfortunately that doesn't include much about the map generator (yet).
Note that when I’m basing this on the code in 3.4.3. This was because it had been the latest version for the past ten years, so I figured it was pretty stable. Right up until 3.6.0 came out and shocked everyone. There’s been a few changes to the code (and it’s formatted slightly differently) so I’ll continue to link to 3.4.3′s version. The essence of the code is pretty much the same.
When Nethack starts a new game, it does some setup of the player and the objects in the game, and then creates the first level by calling mklev(). The name has some historical reasons behind it, but the modern version is pretty straightforward.
If this isn't a bones level, we start by calling the makelevel() function, where the bulk of the room creation happens.
In makelevel(), we start by declaring some variables that will be used later:
Tumblr media
room_threshold is the minimum number of rooms before a special room can be added. There's always two reserved rooms (for the up and down stairs) and possibly a third (if there's a stair to a dungeon branch) so room_threshold will eventually be set to either 3 or 4, after the stairs are added.
The keyword "register" is a somewhat obsolete way to tell the C compiler to keep the variable in memory because we're going to be using it a lot. Modern compilers do this automatically, but NetHack doesn't rely on modern compilers.
The game then checks if wiz1_level.dlevel is equal to zero. There's nothing particularly relevant about this variable itself, it just uses this as a flag to check if things are uninitialized. If this variable is set to 0 (such as by the code that loads a saved game), it assumes that a bunch of other stuff isn't set either. A quick call to init_dungeons() takes care of that.
There's a couple of other setup things to do: set level dependent object probabilities (which appears to be only used for for gems?) and clear out the saved information about the current level, such as the number of rooms it has, the list of monsters, and so on.
Tumblr media
Once the setup is done, it does a check to see if this is a special level. There's a entire system for creating these special levels from templates, using the makemaz() function. So-called because if you don't specify a level, it will create a maze instead (again, this function dates back to Hack). There's also a separate check here to see if this is the Rogue emulation level, in which case it does the Rogue room generation instead, complete with a ghost of the Rogue player character.
Once we pass all those checks and setup, it's time to start making the actual rooms, which we'll discuss in Part 2.
11 notes · View notes