The earliest version of Rogue I can find is 3.6, which has source code available, and formed the basis of the version that I played and finished. It’s written in C, which I know, but the code is still quite terse and difficult to parse, as C code tended to be back in its heyday. But it is surprisingly complete in terms of comments. I say surprisingly, because this isn’t the first game with source code that I have looked at, but the source of previous games such as Zork and Akalabeth provided no inline comments at all.
The following is information that I was able to understand and found shed interesting light on Rogue’s mechanics (e.g. not mundane, self-evident things like explaining how removing your armor works or computery things like bandwidth management).
Note that this is all based on the Rogue 3.6 code. Later versions could be different!
rogue.hSome data is stored here.
MAXOBJ 9 – There are no more than nine treasures spawned per level.
MAXPACK 23 – You may only carry 22 items in your inventory (the 23rd item won’t fit)
MAXTRAPS 10 – No more than ten traps per level, though in practice you’ll almost certainly never get close to this.
GOLDCALC (rnd(50 + 10 * level) + 2) – A formula that gets used in a few places where gold is concerned. This formula picks a random number between 2 and [51 + 10 * level]. Level refers to dungeon level.
BEARTIME 3 – Bear traps keep you stuck for 3 turns.
SLEEPTIME 5 – Sleep traps put you to sleep for 5 turns.
HOLDTIME 2 – Potions of paralysis incapacitate you for 2 turns.
WANDERTIME 70 – After 70 turns, a monster may wander into the dungeon.
HUHDURATION 20 – Confusion lasts a minimum of 20 turns.
SEEDURATION 850 – Blindness and see invisibility potions last 850 turns.
HUNGERTIME 1300 – Your stomach begins with 1300 food units. Eating fills it an average of 1300 food units.
MORETIME 150 – You’ll be weak at 150 food units, and hungry at twice that.
There are a number of “saves” defined here, including:
Only poison and magic are actually used by anything.
Odds of a successful save vs. poison are (7 + [Level/2]) * 5%. Level refers to your character level.
Odds of a successful save vs. magic are (4 + [Level/2]) * 5%. That goes for monsters too, who can make save vs. magic checks against some of your attacks, and their character level is used for these checks.
TablesThese tables come from all over the code. In some cases, I’ve added columns that don’t actually appear in the game code directly, but I’ve put them there for clarity.
“Vp” represents “vorpalness,” a rough measure of how tough the monster type is, and a stat governing which monsters may appear in each dungeon level.
A dungeon level’s “vorpal range” is [dungeon level – 6] to [dungeon level + 3]. Minimum vorpal range is always between 0 and 21, maximum is always 25 or less. Any monster within this vorpal range may spawn in the dungeon level.
Treasure % is the chance that the monster will have an item in its pack, which it will drop when you kill it. The item is determined at the same time the monster spawns, and follows the exact same rules as any other item drop does, except that it does not count toward the nine treasure per level limit. The fact that it’s determined at monster spawn time matters because of a rule that ensures food spawns every three dungeon levels. If a monster spawns carrying food, then this satisfies the “food every three levels” criteria whether you kill the monster or not.
Flags hold the following meaning:
- ISMEAN – Every round where you can see the monster, there is a 67% chance that it will chase you, unless you are wearing the ring of stealth.
- NOWANDER – The monster will never be spawned by the wander daemon. It only spans among the initial monsters when you enter a level.
- ISBLOCK – Doesn’t seem to do anything. Only the Orc has this flag.
- ISREGEN – Each time it attacks you, there is a 33% chance of it gaining an HP.
- ISINVIS – Monster icon does not show, unless zapped by a staff of cancellation or if wearing a ring of see invisible. Only the invisible stalker has this flag.
- ISGREED – Monster will be drawn to gold in the room. Only the dragon has this flag.
Some monsters have special effects when they hit you. These effects only happen once per turn that they hit you, even if the monster hits you multiple times in that turn.
- Rust monsters put a -1 modifier on your equipped armor, unless you already have an AC of 9 or 10.
- Floating eyes transfix you, incapacitating you for 2 or 3 turns.
- Giant ants decrease your strength by 1, unless you save vs. poison or have a ring of sustain strength equipped.
- Wraith hits have a 15% chance that you lose a level and 1d10 max HP. Your XP will then be set to the amount just below what is needed to level up.
- Violet fungi prevent you from moving away until you beat them, otherwise get rid of them, or teleport away. They also have a unique damage property, doing 1 damage the first time they hit you, 2 damage the second, 3 damage the third, and so on.
- Leprechauns steal 5*GOLDCALC from you, unless you save vs. magic. If you succeed, then they only steal GOLDCALC. Either way, they then vanish. If you kill them, then they drop GOLDCALD gold, or 5*GOLDCALC if you make a successful save vs. magic. This is then added to the existing pile of gold in the room if there is one.
- Nymphs vanish and steal one randomly chosen magical item, including:
- Armor with any + or – modifiers
- Weapons with any + or – modifiers
- The Amulet of Yendor (!!)
- The first time you see an umber hulk, you must save vs. magic or be confused for 20-39 turns. Either way, once the check is made you are now immune to that umber hulk’s gaze (but not to the gaze of other hulks). Seeing an umber hulk while already confused adds another 20-39 turns to the clock.
Each monster’s HP is determined by rolling 1d8 for each of its levels. So for instance, a level 2 giant ant gets 2d8 HP.
Some monsters have multiple attacks per turn, and this is indicated by a “/” separating the rolls. For instance, a centaur gets two attacks, both 1d6.
D-factor is my own calculation, and it represents the average amount of damage you can expect to take per turn, with the assumption that you are unable to avoid being hit. Keep in mind it’s just an average; maximums can be significantly larger than this. A Dragon, for instance, can do anywhere from 5 to 46 damage against a defenseless player in a turn, but will average 25.5 per turn.
The above table is used whenever treasure spawns, to randomly determine what its type will be from the probability. Rings and sticks are the rarest kind of treasure, only spawning 5% of the time.
|Monster confusion||8||170||Next hit permanently confuses the monster
|No, but your hands glow red.|
|Magic mapping||5||180||Completes the level map.||Yes.|
|Light||10||100||Illuminates the room.||Yes.|
|Hold monster||2||200||Holds all monsters within two spaces until you
|Sleep||5||50||You sleep for 4-8 turns.||Yes.|
|Enchant armor||8||130||+1 enchantment to your armor and removes
|No, but your armor glows.|
|Identify||21||100||Identifies an item.||Yes.|
|Scare monster||4||180||Drop to become invulnerable until you step
away from the scroll.
|No, but you hear laughter (and the scroll is wasted)
if you read it.
|Gold detection||4||110||Shows location of gold on the map.||Only if there is gold on the map.|
|Teleportation||7||175||Teleport yourself to a random room in the
|Only if the new room is different from the old room.|
|Enchant weapon||10||150||Equal chance of +1 enchantment to your
weapon’s to-hit or damage property and
removes any curses.
|No, but your weapon glows blue.|
|Create monster||5||75||Create a random monster right next to you.||No.|
|Remove curse||8||105||Removes curses from all equipped items.||No, but you “feel somebody is watching.”|
|Aggravate monsters||1||60||Alerts all monsters in the dungeon||No, but you hear a high-pitched hum.|
|Blank paper||1||50||Nothing||No, but “seems to be blank.”|
|Genocide||1||200||Prevent a monster type of your choice from
ever spawning again.
When a treasure spawns and it is determined to be a scroll, the ‘%’ column is used to randomly select what kind of scroll it will be. The worth column is the amount of gold you get for it when you beat the game while still holding it (this didn’t happen to me for some reason!).
Those funky scroll names are generated from a list of “syllable” strings, each of them no more than three characters long. Each scroll gets between 2 and 5 “words,” and each word will consist of between 1 and 3 syllables, randomly chosen from the list.
|Confusion||8||50||Confuses you 20-27 turns.
If already confused, then 20-27 turns are added to the
|Paralysis||10||50||Incapacitates you for 2 turns.||Yes|
|Poison||8||50||Lowers your strength by 1-3. Nullified by a ring of
|Gain strength||15||150||Increases strength by 1.||Yes|
|See invisible||2||170||See invisible stalkers for 850 turns, lights the current
room, and cures blindness.
“tastes like slime-mold juice.”
|Healing||15||130||Restores 1d4 HP for each character level.
|Monster detection||6||120||Shows positions of monsters on the level.||Only if the level has monsters.|
|Magic detection||6||105||Shows positions of magic treasures on the level.||Only if the level has magic treasure.|
|Raise level||2||220||Level up.||Yes.|
|Extra healing||5||180||Restores 1d8 HP for each character level.
|Haste self||4||200||Hastes you 4-7 turns.
If already hasted, you faint for 0-7 turns.
While hasted, monsters only move every other turn.
|Restore strength||14||120||Restores strength to the maximum that you ever attained.||No, but “tastes great –
you feel warm all over.”
|Blindness||4||50||Blindness for 850 turns.||Yes.|
|Thirst quenching||1||50||None.||No, but “tastes dull.”|
|Protection||9||200||Equivalent to -1 AC per enchantment level. Can be cursed/negative.|
|Add strength||9||200||+1 strength per enchantment level. Can be cursed/negative.|
|Sustain strength||5||180||Prevents strength loss. Consumes 1 food per turn.|
|Searching||10||200||Free search every time you move. Two rings mean two free searches.
A 33% chance per turn of consuming 1 food.
|See invisible||10||175||Lights the room when equipped. Reveals invisible stalkers.|
|Aggravate monster||11||100||Cursed. Makes all monsters target you.|
|Dexterity||8||220||+5% to-hit chance per enchantment level. Can be cursed/negative.|
|Increase damage||8||220||+1 melee damage per enchantment level. Can be cursed/negative.|
|Regeneration||4||260||Regenerate 1 HP per turn. Consumes 2 food per turn.|
|Slow digestion||9||240||A 50% chance per turn of adding 1 food to your stomach.
Two rings basically means you’ll never need to eat again.
|Teleportation||9||100||Cursed. 2% chance of teleporting to a random room each time you move.
Two rings mean slightly less than a 4% chance of teleporting, and a very small chance of
|Stealth||7||100||Mean, sleeping monsters don't wake up when you see them. No effect on wandering monsters.|
Left or right handedness doesn’t seem to have any effect on what a ring does.
When a ring of add strength, protection, dexterity, or increase damage spawns, there is an equal 1/3 chance of it being +1, +2, or cursed -1.
Rings with enchantment values get an additional worth bonus of (20 * [enchantment value]). If cursed, then the ring is worth 50, total.
|Light||12||120||Illuminate the room.|
|Striking||9||115||Must be zapped at a monster in melee range. Behaves like a melee swing of 1d8 with a +3, +3 bonus.
There’s a 5% chance that the damage will be 3d8+3 instead.
|Lightning||3||200||A projectile with 6d6 damage. Can bounce off walls and hit you. Monsters (or you) may save vs. magic.|
|Fire||3||200||Same as lightning.|
|Cold||3||200||Same as lightning.|
|Polymorph||15||210||Transform the monster to another selected randomly.|
|Magic missile||10||170||A projectile with 1d4 damage. Monsters may save vs. magic.|
|Haste monster||9||50||Hasted monster moves twice per turn. Haste and slow cancel each other out.|
|Slow monster||11||220||Slowed monster moves every other turn. Slow and haste cancel each other out.|
|Drain life||9||210||Drain half of your remaining HP, and do that much damage to all monsters in the room,
spread evenly among them.
|Teleport away||5||140||Teleport a monster to a random room.|
|Teleport to||5||60||Teleport a monster right next to you.|
|Cancellation||5||130||Reveal invisible stalkers.|
Sticks can be staves or wands. Each magic-type of stick is assigned only one of these physical forms at the start of the game, e.g, if you find a staff of light, you will not also find a wand of light.
Sticks normally have 3-7 charges. Sticks of light have 10-19 charges.
Sticks can be equipped. Staves have a melee damage of 2d3. Wands can be equipped or thrown and have melee and throw damage of 1d1.
Sticks of striking are 1d8 with a +3, +3 enchantment. This is separate from their zap ability.
If you equip a staff of striking and hit a monster, or throw a wand of striking at a monster and hit, then it will lose its charges and any further ability to inflict damage.
Sticks usually do not self-identify. Exceptions are sticks of light, and sticks of polymorph.
Sticks get an additional worth bonus of (20 * [remaining charges]).
|Studded leather armor||7||15||15|
AC uses old D&D rules, where lower AC is better.
When armor spawns, there is a 20% chance of cursed armor with a -1 to -3 disenchantment (adds to the AC), and an 8% chance of enchanted armor with a +1 to +3 enchantment (subtracts from the AC).
Rust monsters’ attacks permanently lower your armor’s enchantment by 1, but it does not become cursed, even if the enchantment reaches negative levels.
Enchanted armor gets a worth multiplier of [1 + (10 * [Enchantment level])]. So for instance, +2 splint mail that I finished with would have gotten a 21x multiplier, and would be worth 1680 gold. Rusted or cursed armor with a negative enchantment value is worth nothing, but doesn't cost you anything either.
|Name||Melee damage||Throw damage||Special||Worth|
For weapons without the ISMISL flag, the melee and throw damage columns work as you would expect. But for weapons with the ISMISL flag, throw damage only applies when you have the corresponding launcher equipped. E.g. – if you have a bow equipped, throwing arrows does 1d6 damage, and otherwise, throwing arrows does 1d1. Consequently, daggers and darts always do melee damage, because they don’t have any corresponding launchers. Either this is a bug, or I’ve misunderstood the logic here.
ISMANY means that when this weapon spawns it will be a stack of several, and count as one item for inventory limit purposes. Items that spawned separately will belong to separate stacks, even if they are the same item!
Enchanted weapons might have two separate enchantments, such as your starting +1, +1 mace. The first number is the to-hit bonus, and the second number is the damage bonus.
When spawning a weapon, there is a 10% chance of a cursed weapon with -1 to -3 to-hit penalty, and a 5% chance of an enchanted weapon with a +1 to +3 to-hit bonus.
Enchanted weapons get a worth multiplier of [1 + (10 * [Sum of enchantments])]. So for instance, the +1, +1 mace you start with gets a 21x multiplier, and is worth 168 gold. Weapons with negative enchantments are, like the armor, worth nothing.
Other items with value:
chase.cWhen moving, confused monsters have an 80% chance to move randomly instead of in their selected direction. Non-confused Invisible Stalkers always have a 20% chance, and non-confused Bats always have a 50% chance. The randomly selected direction will always be a legal move, and will never result in a confused thing bumping into walls. Each time a confused monster moves randomly, there is a 5% chance that the confusion disperses.
command.cSearching has a 20% chance to find secret doors and a 50% chance to find hidden traps. It does nothing if you are blind.
daemons.cHealing has two logic paths depending on your character level.
- At levels 1-7, you heal one point every [21-LVL*2] turns without fighting.
- At levels 8+, you heal between 1 and [LVL-7] points every three turns without fighting.
After 70 turns, a “wander” daemon activates. When activated, every fourth move has a 1/6th chance that a monster will spawn and deactivate the daemon. Monsters spawned this way will immediately be hostile toward the player.
Your stomach holds 2000 food units. Every turn, this decreases by 1, unless you are holding the amulet. Rings can further empty your stomach, or in the case of rings of slow digestion, fill it.
At 300 food units, you’ll feel hungry. At 150 food units, you’ll feel weak. At 0 food units, every move has a 20% chance that you faint instead, which incapacitates you for between 4 and 11 turns.
fight.cWhenever you swing or throw a weapon, this is your chance of hitting:
([Your level] + [Enemy AC] + [Strength to-hit bonus] + [Dexterity bonus] + [Weapon to-hit bonus] + [Launcher to-hit bonus]) * 5%
AC follows old D&D rules where lower AC is better.
Strength to-hit bonus is determined as follows:
- At 18/100 strength, +3 to-hit bonus.
- At 18/51 strength, +2 to-hit bonus.
- At 17+ strength, +1 to-hit bonus.
- At 6 strength or less, a [STR-7] to-hit penalty.
Dexterity bonus is determined entirely based on your equipped rings of dexterity, if any. For instance, if you have a ring of +2 dexterity and a ring of +1 dexterity, then you would get a +3 dexterity bonus.
Enchanted weapons have one or two “+” modifiers. The first of them is the to-hit bonus, and the second, if present, is the damage bonus. If you threw your weapon, then the weapon bonus is determined by the thrown weapon, not the equipped weapon.
The launcher bonus applies only if you throw a missile weapon, and only if you have an appropriate launcher equipped. It is determined by the equipped launcher.
On a successful hit, damage is determined by this formula:
[Base damage roll] + [Weapon damage bonus] + [Launcher damage bonus] + [Ring damage bonus] + [Strength damage bonus]
Base damage roll is standard D&D style dice rolls. A 2d4 mace rolls two four-sided dice. Each weapon has two base damages; one for melee, one for being thrown. Thrown damage is only used if you throw a melee weapon, or if you throw a missile weapon and have an appropriate launcher equipped. If you throw an arrow while having a sword equipped, then the arrow’s melee damage is used.
Weapon damage bonus is the weapon’s second “+” modifier, if it has one.
Launcher damage bonus applies only when throwing missiles and only when you have an appropriate launcher equipped. It is the launcher’s second “+” modifier, if it has one.
Ring damage bonus is determined entirely based on your equipped rings of increase damage.
Strength damage bonus is determined as follows:
- At 18/100 strength, +6 damage
- At 18/91 strength, +5 damage
- At 18/76 strength, +4 damage
- At 18/1 strength, +3 damage
- At 18 strength, +2 damage
- At 16+ strength, +1 damage
- At 6 strength or less, a [STR – 7] damage penalty
When a monster swings at you (and some monsters can swing multiple times in a turn), the chance for you to get hit is:
([Monster’s level] + [Your AC] – [Your protection bonus]) * 5%
The AC is your AC, and again, lower AC is better.
Protection bonus is determined by your equipped rings of protection, if any.
Monsters don’t have weapons, rings, or strength bonuses or penalties, so the damage done on a hit is always determined by their base damage roll(s).
The text when you hit or miss (e.g. “you scored an excellent hit on the snake”) is chosen randomly, and does not indicate anything except whether you hit or missed.
init.cThis file is where most of the data lives.
You begin with 1300 food units in your stomach.
A new player has a 1% chance of starting with 18 strength. When this happens, an additional “exceptional” bonus factor is rolled with a 1d100. This factor is used for strength bonus calculations, as outlined above. Otherwise, a new player gets 16 strength.
main.cRogue’s world is bound to the size of your terminal window. It expects a minimum of 70 columns and 22 lines, but won’t object if your window is even bigger, and there doesn’t seem to be any real limit. I imagine that if you were to maximize a terminal window on an 8K monitor and then run Rogue in it, you’d have a terrifyingly huge game world where you’d starve to death exploring the first level.
You always start with the same gear. Only your arrows are random, and will be between 25 and 39 in count.
misc.cWhen you eat food rations, there’s a 30% chance that the food tastes awful, and you gain 1 XP. There’s no other effect of the food’s taste.
Any food that you eat adds between 1100 and 1499 food units to your stomach, up to a maximum of 2000 units.
The following tiers of exceptional strength exist beyond 18:
If your strength is 18, then increasing your strength will take you to the next tier of exceptional strength, with the exceptional stat chosen randomly in the range of the tier, except for at the very top tier, where the rules are a bit complicated and not really worth going into. Losing strength while exceptional will take you down a tier.
On dungeon levels 26 and below, mimics can be disguised as the Amulet of Yendor.
move.cThe odds of getting hit by a dart trap are:
(12 + [Your level]) * 5%
I think I am getting that right, that the higher your character level, the more likely you are to get hit, which means that at character level 8 you are guaranteed to be hit. The function seems to be badly coded. Dungeon level would make more sense than player level. It also looks like the code is meant to take the armor class into account, but it uses the base armor class rather than the equipment armor class, and your base AC is always 10 no matter what armor you have equipped.
A successful dart hit does 1d4 damage and lowers your strength by 1.
The odds of getting hit by an arrow trap are:(10 + [Your level]) * 5%
An arrow does 1d6 damage.
newlevel.cIf you have the amulet, and the level you are on is not the deepest you’ve been to yet (i.e. you are now climbing stairs to go up instead of down), then no treasure will spawn.
The game keeps track of how many levels have been generated without spawning food. When this reaches 3 or more, the next treasure spawn is guaranteed to be food.
There is a [Level * 10%] chance that the dungeon level will have traps in it. At dungeon level 1, this is a 10% chance. At dungeon levels 10 and higher, this is a 100% chance.
If any traps are generated, then the number of traps will be a random number between 1 and [Dungeon level / 4], with a minimum of 1 and a maximum of 10.
When a trap is created, the type of trap is randomly selected, and the odds are equal for each trap type.
Every time you enter a new dungeon level for the first time, there will be nine chances for treasure to spawn. Each chance is 35%. No treasure spawns when visiting dungeon levels that you’ve been to before, though treasure-carrying monsters may still spawn.
The amulet is guaranteed to spawn if the dungeon level is 26 or below, and the player hasn’t found an amulet yet.
room.cThere is a 50% chance that any given room will have gold, provided the current dungeon level is the deepest you have gone to yet (meaning that gold will not spawn when you ascend stairs after finding the amulet). Rooms with gold have an 80% chance of having a monster. Rooms without gold have a 25% chance of having a monster.
things.cWhen spawning treasure, if no food has been spawned in three dungeon levels, then the next treasure is guaranteed to be food. Otherwise, there is an equal chance of the treasure being food, a potion, a scroll, a weapon, armor, ring, or stick.
When spawning food, there is a 10% chance of spawning a slime-mold. There’s no difference except eating a slime-mold grants 1 XP and produces a different message.
Interesting reading. About the unintuitive scare monster scroll I'd imagine since the game was open-source at that point and probably played mostly by computer nerds, you would just look into the code to clarify things. I've started playing roguelikes with Angband and whenever I've had trouble understanding the game logic or cryptic game messages and the manual didn't help I just read the code. Coincidentally, that was also how I learned to program and specifically program games:)ReplyDelete
Also interesting is how the lack of town with replenishing supplies totally changes the gameplay dynamic. It's either use whatever you have or die. Options to run away are sparse and reserved for the most troublesome encounters. The food clock is also a more integral part of the game due to the same reason. I'd describe the Rogue's design as much more tight compared to later games in the genre. And the amount of D&D influence is staggering.