Merge branch 'NetHack-3.6.0'

This commit is contained in:
nhmall
2016-03-06 09:17:08 -05:00
53 changed files with 4424 additions and 2436 deletions

20
Files
View File

@@ -36,16 +36,16 @@ align.h amiconf.h artifact.h artilist.h attrib.h
beconf.h botl.h color.h config.h config1.h
context.h coord.h decl.h def_os2.h dgn_file.h
display.h dlb.h dungeon.h engrave.h extern.h
flag.h func_tab.h global.h hack.h lev.h
lint.h mail.h mextra.h mfndpos.h micro.h
mkroom.h monattk.h mondata.h monflag.h monst.h
monsym.h ntconf.h obj.h objclass.h os2conf.h
patchlevel.h pcconf.h permonst.h prop.h qtext.h
quest.h rect.h region.h rm.h skills.h
sp_lev.h spell.h sys.h system.h tcap.h
timeout.h tosconf.h tradstdc.h trampoli.h trap.h
unixconf.h vision.h vmsconf.h wceconf.h winami.h
winprocs.h wintype.h you.h youprop.h
flag.h func_tab.h global.h hack.h integer.h
lev.h lint.h mail.h mextra.h mfndpos.h
micro.h mkroom.h monattk.h mondata.h monflag.h
monst.h monsym.h ntconf.h obj.h objclass.h
os2conf.h patchlevel.h pcconf.h permonst.h prop.h
qtext.h quest.h rect.h region.h rm.h
skills.h sp_lev.h spell.h sys.h system.h
tcap.h timeout.h tosconf.h tradstdc.h trampoli.h
trap.h unixconf.h vision.h vmsconf.h wceconf.h
winami.h winprocs.h wintype.h you.h youprop.h
(file for tty versions)
wintty.h
(files for X versions)

View File

@@ -19,7 +19,7 @@ Afraid of your valuables being stolen? Carry more junk!
Always be aware of the phase of the moon!
Always sweep the floor before engraving important messages.
Amulets of Yendor are hard to make. Even for a wand of wishing.
An elven cloak protects against magic.
An elven cloak is useful against magic.
An umber hulk can be a confusing sight.
As Crom is my witness, I'll never go hungry again!
Asking about monsters may be very useful.

View File

@@ -311,7 +311,7 @@ comfortable--"
[The Colour of Magic, by Terry Pratchett]
%e passage
# p. 228-229 (passage starts mid-paragraph)
# pp. 228-229 (passage starts mid-paragraph)
%passage 14
[...] She was the Goddess Who Must Not Be Named; those who sought her
never found her, yet she was known to come to the aid of those in greatest
@@ -962,7 +962,7 @@ racehorse."
[Mort, by Terry Pratchett]
%e passage
# p. 139-140 (passage ends mid-sentence)
# pp. 139-140 (passage ends mid-sentence)
%passage 7
"You don't know much about monarchy, do you?" said Keli.
@@ -983,8 +983,8 @@ appeal to my better nature under this here crusty exterior," he added,
[Mort, by Terry Pratchett]
%e passage
# p. 159-160 (Death has come to an employment agency--a new concept in
# Ankh-Morpork--looking for a job)
# pp. 159-160 (Death has come to an employment agency--a new concept in
# Ankh-Morpork--looking for a job)
%passage 9
"And what was your previous position?"
@@ -1091,8 +1091,8 @@ MANY HAVE, said Death evenly.
[Sourcery, by Terry Pratchett]
%e passage
# p. 40-41 (text has 'the moment and the words' which is obviously a typo;
# it might have intended 'that' for 'and'; we just drop 'and')
# pp. 40-41 (text has 'the moment and the words' which is obviously a typo;
# it might have intended 'that' for 'and'; we just drop 'and')
%passage 4
The thief, as will become apparent, was a special type of thief. This
thief was an artist of theft. Other thieves merely stole everything that
@@ -1117,10 +1117,10 @@ words were out of your mouth.
[Sourcery, by Terry Pratchett]
%e passage
# p. 63-64 ('Compleet', 'Majik', 'enterr', 'physycal', 'hys', 'bodie',
# 'Destinie', 'Deathe', 'werre', 'nowe', 'menne', 'Ende',
# 'Worlde', 'hadd', 'bee', 'goddes', 'ould', 'Apocralypse',
# 'legende', 'thee': all accurate; 'ould' may be a typo...)
# pp. 63-64 ('Compleet', 'Majik', 'enterr', 'physycal', 'hys', 'bodie',
# 'Destinie', 'Deathe', 'werre', 'nowe', 'menne', 'Ende',
# 'Worlde', 'hadd', 'bee', 'goddes', 'ould', 'Apocralypse',
# 'legende', 'thee': all accurate; 'ould' may be a typo...)
%passage 5
It was deathly quiet in the Library. The books were no longer frantic.
They'd passed through their fear and out into the calm waters of abject
@@ -1150,7 +1150,7 @@ his head.
[Sourcery, by Terry Pratchett]
%e passage
# p. 71-72
# pp. 71-72
%passage 6
The current Patrician, head of the extremely rich and powerful Vetinari
family, was thin, tall and apparently as cold-blooded as a dead penguin.
@@ -1211,7 +1211,7 @@ He looked down at his feet.
[Sourcery, by Terry Pratchett]
%e passage
# p. 141-142 (Rincewind and Nijel have just entered a harem)
# pp. 141-142 (Rincewind and Nijel have just entered a harem)
%passage 9
Rincewind had eyes for none of this. [...] they were swamped by the
considerably bigger flood of panic at the sight of four guards turning
@@ -1235,7 +1235,7 @@ would never quite forget to the end of this life.
[Sourcery, by Terry Pratchett]
%e passage
# p. 198-199
# pp. 198-199
%passage 10
The astro-philosophers of Krull once succeeded in proving conclusively
that all places are one place and that the distance between them is an
@@ -1936,8 +1936,8 @@ The orangutan threw a complex salute and swung away into the darkness.
[Guards! Guards!, by Terry Pratchett]
%e passage
# p. 299-300 + 325 (final part comes quite a bit later; Carrot is trying to
# alert oblivious Sergeant Colon that the dragon is coming)
# pp. 299-300 + 325 (final part comes quite a bit later; Carrot is trying to
# alert oblivious Sergeant Colon that the dragon is coming)
%passage 14
"This is what it comes to!" muttered Colon. "Decent women can't walk down
the street without being eaten! Right, you bastards, you're... you're
@@ -2315,8 +2315,8 @@ said Victor.
[Moving Pictures, by Terry Pratchett]
%e passage
# p. 111-112 ('dis', 'ort', 'yore', 'finking', 'mayonnaisey', 'specialitay',
# 'de lar mayson' all accurate)
# pp. 111-112 ('dis', 'ort', 'yore', 'finking', 'mayonnaisey', 'specialitay',
# 'de lar mayson' all accurate)
%passage 10
Borgle's commissary had decided to experiment with salads tonight. The
nearest salad growing district was thirty slow miles away.
@@ -2566,7 +2566,7 @@ He heard the voices stop. There was the sound of feet hurrying away.
[Reaper Man, by Terry Pratchett]
%e passage
# p. 81-82 (things have stopped dying because Death is no longer on the job)
# pp. 81-82 (things have stopped dying because Death is no longer on the job)
%passage 10
Everything that exists, yearns to live. That's what the cycle of life is
all about. That's the engine that drives the great biological pumps of
@@ -2654,13 +2654,273 @@ Rush off, or course, But slowly.
#
#
#
%title Witches Abroad (1)
%title Witches Abroad (14)
# p. 92 (ROC edition)
%passage 1
Vampires have risen from the dead, the grave and the crypt, but have never
managed it from the cat.
[Witches Abroad, by Terry Pratchett]
%e passage
# pp. 12-13
%passage 2
Desiderata Hollow was making her will.
When Desiderata Hollow was a girl, her grandmother had given her four
important pieces of advice to guide her young footsteps on the unexpectedly
twisting pathway of life.
They were:
Never trust a dog with orange eyebrows,
Always get the young man's name and address,
Never get between two mirrors,
And always wear completely clean underwear every day because you never knew
when you were going to be knocked down and killed by a runaway horse and if
people found you had unsatisfactory underwear on, you'd die of shame.
And then Desiderata grew up to become a witch. And one of the minor
benefits of being a witch is that you know exactly when you're going to die
and can wear what underwear you like.(1)
That had been eighty years earlier, when the idea of knowing exactly when
you were going to die had seemed quite attractive because secretly, of
course, you knew you were going to live forever.
That was then.
And this was now.
Forever didn't seem to last as long these days as once it did.
(1) Which explains a lot about witches.
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 64 (passage ends mid-paragraph)
%passage 3
"You know," said Nanny, investigating the recesses of the basket, "whenever
I deals with dwarfs, the phrase 'Duck's arse' swims across my mind."
"Mean little devils. You should see the prices they tries to charge me
when I takes my broom to be repaired," said Granny.
"Yes, but you never pay," said Magrat.
"That's not the point," said Granny Weatherwax. "They shouldn't be allowed
to charge that sort of money. That's thievin', that is."
"I don't see how it can be thieving if you don't pay anyway," said Magrat.
"I never pay for anything," said Granny. [...]
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 93 (passage is a footnote)
%passage 4
Nanny Ogg sent a number of cards home to her family, not a single one of
which got back before she did. This is traditional, and happens everywhere
in the universe.
[Witches Abroad, by Terry Pratchett]
%e passage
# pp. 118-119 (Magrat has been teaching herself martial arts via books)
%passage 5
"Lobsang Dibbler says sometimes you have to lose in order to win," said
Magrat.
"Sounds daft to me," said Nanny. "That's Yen Buddhism, is it?"
"No. They're the ones who say you have to have lots of money to win," said
Magrat.(1) "In the Path of the Scorpion, the way to win is to lose every
fight except the last one. You use the enemy's strength against himself."
"What, you get him to hit himself, sort of thing?" said Nanny. "Sounds
daft."
(1) The Yen Buddhists are the richest religious sect in the universe. They
hold that the accumulation of money is a great evil and burden to the soul.
They therefore, regardless of personal hazard, see it as their unpleasant
duty to acquire as much as possible to reduce the risk to innocent people.
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 131
%passage 6
They had breakfast in a forest clearing. It was grilled pumpkin. The dwarf
bread was brought out for inspection. But it was miraculous, the dwarf
bread. No one ever went hungry when they had some dwarf bread to avoid.
You only had to look at it for a moment, and instantly you could think of
dozens of things you'd rather eat. Your boots for example. Mountains. Raw
sheep. Your own foot.
[Witches Abroad, by Terry Pratchett]
%e passage
# pp. 194-195 ("he just" is accurate; cockerel == adolescent rooster)
%passage 7
"This is Legba, a dark and dangerous spirit," said Mrs. Gogol. She leaned
closer and spoke out of the corner of her mouth. "Between you and me, he
just a big black cockerel. But you know how it is."
"It pays to advertise," Nanny agreed. "This is Greebo. Between you and me,
he's a fiend from hell."
"Well, he's a cat," said Mrs. Gogol, generously. "It's only to be expected."
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 218
%passage 8
"/And/ still a bit of the wedding cake," said the first coachman. "Ain't
you et that up yet?"
"We have it every night," said the undercoachman.
The shed shook with the ensuing laughter. It is a universal fact that any
innocent comment made by any recently married young member of any workforce
is an instant trigger for coarse merriment among his or her older and more
cynical colleagues. This happens even if everyone concerned has nine legs
and lives at the bottom of an ocean of ammonia on a huge cold planet. It's
just one of those things.
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 228
%passage 9
"You ought to be more adventurous, Granny," said Magrat.
"I ain't against adventure, in moderation," said Granny, "but not when I'm
eatin'."
[Witches Abroad, by Terry Pratchett]
%e passage
# pp. 263-264 (Nanny is trying to stop an elaborate clock; despite damage
# inflicted on it, it goes on to announce midnight [early])
%passage 10
Let's see thought Nanny. This bit is connected to that bit, this one turns,
that one turns /faster/, this spiky bit wobbles backwards and forwards...
Oh, well. Just twist the first thing you can grab, as the High Priest said
to the vestal virgin.(1)
Nanny Ogg spat on her hands, gripped the largest cog-wheel, and twisted.
It carried on turning, pulling her with it.
Blimey. Oh, well...
Then she did was neither Granny Weatherwax nor Magrat would have dreamed of
doing in the circumstances. But Nanny Ogg's voyages on the sea of
intersexual dalliance had gone rather further than twice around the
lighthouse, and she saw nothing demeaning in getting a man to help her.
She simpered at Casanunda.
"Things would be a lot more comfortable in our little /pie-de-terre/ if you
could just push this little wheel around a bit," she said. "I'm sure /you/
could manage it," she added.
"Oh, no problem, good lady," said Casanunda. He reached up with one hand.
Dwarfs are immensely strong for their size. The wheel seemed to offer him
no resistance at all.
Somewhere in the mechanism something resisted for a moment and then went
/clonk/. Big wheels turned reluctantly. Little wheels screamed on their
axles. A small important piece flew out and pinged off of Casanunda's
small bullet head.
And, much faster than nature had ever intended, the hands sped around the
face.
(1) This is the last line to a Discworld joke lost, alas, to posterity.
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 265 ('pate' has a couple of accent marks which can't be rendered in ascii)
%passage 11
There are various forms of voodoo in the multiverse, because it's a
religion that can be put together from any ingredients that happen to be
lying around. And all of them try, in some way, to call a god into the body
of a human being.
That was stupid, Mrs. Gogol thought. That was dangerous.
Mrs. Gogol's voodoo worked the other way about. What was a god? A focus of
belief. If people believed, a god began to grow. Feebly at first, but if
the swamp taught anything, it taught patience. Anything could be the focus
of a god. A handful of feathers with a red ribbon around them, a hat and
coat on a couple of sticks... anything. Because when all people had was
practically nothing, then anything could be almost everything. And then you
fed it, and lulled it, like a goose heading for pate, and let the power grow
very slowly, and when the time was ripe you opened the path... backwards.
A human could ride the god, rather than the other way around. There would
be a price to pay later, but there always was. In Mrs. Gogol's experience,
everyone ended up dying.
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 270 (Greebo has been temporarily transformed--polymorphed?--into a human)
%passage 12
Greebo wasn't a happy cat. [...]
Then he'd smelled the kitchen. Cats gravitate to kitchens like rocks
gravitate to gravity.
[Witches Abroad, by Terry Pratchett]
%e passage
# p. 282 (Casanunda the dwarf is Discworld's Casanova; he appears again in
# /Lords and Ladies/)
%passage 13
"How come you're in the palace guard, Casanunda?"
"Soldier of fortune takes whatever jobs are going, Mrs. Ogg," said Casanunda
earestly.
"But all the rest of 'em are six foot tall and you're--of the shorter
persuasion."
"I lied about my height, Mrs. Ogg. I'm a world-famous liar."
"Is that true?"
"No."
"What about you being the world's greatest lover?"
There was silence for a while.
"Well, maybe I'm only No. 2," said Casanunda. "But I try harder."
[Witches Abroad, by Terry Pratchett]
%e passage
# pp. 285-286 (Greebo is still in human form)
%passage 14
Greebo leapt.
Cats are like witches. They don't fight to kill, but to win. There is a
difference. There's no point in killing an opponent. That way, they won't
know they've lost, and to be a real winner you have to have an opponent who
is beaten and knows it. There's no triumph over a corpse, but a beaten
opponent, who will remain beaten every day for the remainder of their sad
and wretched life, is something to treasure.
Cats do not, of course, rationise this far. They just like to send someone
limping off minus a tail and a few square inches of fur.
Greebo's technique was unscientific and wouldn't have stood a chance against
any decent swordsmanship, but on his side was the fact that it is almost
impossible to develop decent swordsmanship when you seem to have run into a
food mixer that is biting your ear off.
The witches watched with interest.
"I think we can leave him now," said Nanny. "I think he's having fun."
[Witches Abroad, by Terry Pratchett]
%e passage
%e title
#
#
@@ -5015,8 +5275,8 @@ comp-lic-ated documents."
[Carpe Jugulum, by Terry Pratchett]
%e passage
# p. 336-337 (the plot is driven by the actions of a family of vampyres
# who do mostly cooperate with each other)
# pp. 336-337 (the plot is driven by the actions of a family of vampyres
# who do mostly cooperate with each other)
%passage 7
Vampires are not naturally cooperative creatures. It's not in their nature.
Every other vampire is a rival for the next meal. In fact, the ideal
@@ -5344,8 +5604,8 @@ man!"
[Thief of Time, by Terry Pratchett]
%e passage
# p. 74-75 (the novices didn't know that the little old man known as Sweeper
# is actually Lu-Tze; see passage 3 regarding Rule One)
# pp. 74-75 (the novices didn't know that the little old man known as Sweeper
# is actually Lu-Tze; see passage 3 regarding Rule One)
%passage 4
One day a group of senior novices, for mischief, kicked over the little
shrine that Lu-Tze kept beside his sleeping mat.
@@ -6645,9 +6905,9 @@ Treason than met the eye.
[Wintersmith, by Terry Pratchett]
%e passage
# p. 53-54 (in Carpe Jugulum, most of the lore [for humans] about how to kill
# vampires had been written by long-lived/long-not-defunct vampires
# [meaning that it was deliberately full of inaccuracies...])
# pp. 53-54 (in Carpe Jugulum, most of the lore [for humans] about how to kill
# vampires had been written by long-lived/long-not-defunct vampires
# [meaning that it was deliberately full of inaccuracies...])
%passage 6
It was in fact Miss Tick who had written /Witch Hunting for Dumb People/,
and she made sure that copies of it found their way into those areas where
@@ -6663,7 +6923,7 @@ even underwater.
[Wintersmith, by Terry Pratchett]
%e passage
# p. 55-56
# pp. 55-56
%passage 7
Working quickly, she emptied her pockets and started a shamble.
@@ -6728,8 +6988,8 @@ dark art. It was just so /hard/.
[Wintersmith, by Terry Pratchett]
%e passage
# p. 126-127 (passage starts mid-paragraph;
# witches know in advance when they're going to die)
# pp. 126-127 (passage starts mid-paragraph;
# witches know in advance when they're going to die)
%passage 10
"[...] We shall hold the funeral tomorrow afternoon."
@@ -6756,8 +7016,8 @@ witches is an "argument."
[Wintersmith, by Terry Pratchett]
%e passage
# p. 174-175 (passage starts mid-paragraph; last paragraph continues, but
# changes topic so abruptly Tiffany gasps; 'rumbustious' is accurate)
# pp. 174-175 (passage starts mid-paragraph; last paragraph continues, but
# changes topic so abruptly Tiffany gasps; 'rumbustious' is accurate)
%passage 12
"[...] And now I shall tell you something vitally important. It is the
secret of my long life."
@@ -6813,7 +7073,7 @@ as good as she ought to be.
[Wintersmith, by Terry Pratchett]
%e passage
# p. 360-361 ('wurds' is accurate)
# pp. 360-361 ('wurds' is accurate)
%passage 15
"An heroic effect, Mr. Anybody," said Granny. "The first thing a hero must
conquer is his fear, and when it comes to fightin', the Nac Mac Feegle
@@ -6824,7 +7084,7 @@ o' wurds!"
[Wintersmith, by Terry Pratchett]
%e passage
# p. 398-399 ("Chumsfanleigh" is pronounced "Chuffley")
# pp. 398-399 ("Chumsfanleigh" is pronounced "Chuffley")
%passage 16
At the back of the Feegles' chalk pit, more chalk had been carved out of
the wall to make a tunnel about five feet high and perhaps as long.
@@ -7314,7 +7574,7 @@ pp'd at all. Incidentally, how loud were his screams?"
[Unseen Academicals, by Terry Pratchett]
%e passage
# p. 192-193 ('pants': underpants; 'football': soccer ;-)
# pp. 192-193 ('pants': underpants; 'football': soccer ;-)
%passage 9
"You will arrange yourself into two teams, set up goals, and strive to win!
No man will leave the field of play unless injured! The hands are not to
@@ -8040,7 +8300,7 @@ IF YOU ASK ME, said Death, NOBODY COULD DO ANY BETTER THAN THAT...
# Death Quotes are always one line, and '%e passage' can be omitted.
#
%section Death
%title Death Quotes (30)
%title Death Quotes (31)
%passage 1
WHERE THE FIRST PRIMAL CELL WAS, THERE WAS I ALSO. WHERE MAN IS, THERE AM I. WHEN THE LAST LIFE CRAWLS UNDER FREEZING STARS, THERE WILL I BE.
%e passage
@@ -8145,6 +8405,10 @@ JUST BECAUSE SOMETHING IS A METAPHORE DOESN'T MEAN IT CAN'T BE REAL.
# p. 334
%passage 30
I AM ALWAYS ALONE. BUT JUST NOW I WANT TO BE ALONE BY MYSELF.
# Witches Abroad, p. 298 (Death's explanation why he didn't come for zombie 12
# years earlier: YOU STOPPED LIVING. YOU NEVER DIED.)
%passage 31
I HAD AN APPOINTMENT WITH YOU TONIGHT.
%e title
%e section
#

View File

@@ -1,11 +1,11 @@
.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.191 $ $NHDT-Date: 1450306152 2015/12/16 22:49:12 $
.\" $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.203 $ $NHDT-Date: 1456192371 2016/02/23 01:52:51 $
.ds h0 "NetHack Guidebook
.ds h1
.ds h2 %
.ds vr "NetHack 3.6
.ds f0 "\*(vr
.ds f1
.ds f2 "January 18, 2016
.ds f2 "February 22, 2016
.\" labeled paragraph start (should be part of tmac.n, but I don't want to
.\" make changes to that file)
.\" .PS word
@@ -26,7 +26,7 @@
.br
\\h'|-\\n(PYu'\\$1\\h'|-\\n(PXu'\ -\ \\c \" back up, output the label, then
. \" skip to width-of(" - ") before the
. \" normal indentation, output the " - "
. \" normal indentation, output the " - "
. \" then attach the next line (the
. \" text) without stopping (\c: nroff
. \" section 4.2)
@@ -62,29 +62,29 @@ Original version - Eric S. Raymond
Preface - Version 3.6
.pg
This version of the game is special in a particular way. Near the end of
the development of 3.6, one of the significant inspirations for many of the
the development of 3.6, one of the significant inspirations for many of the
humorous and fun features found in the game, author \fITerry Pratchett\fP,
passed away. We have dedicated this version of the game in his memory.
.hn 1
Introduction
.pg
Recently, you have begun to find yourself unfulfilled and distant
in your daily occupation. Strange dreams of prospecting, stealing,
crusading, and combat have haunted you in your sleep for many months,
but you aren't sure of the reason. You wonder whether you have in
fact been having those dreams all your life, and somehow managed to
Recently, you have begun to find yourself unfulfilled and distant
in your daily occupation. Strange dreams of prospecting, stealing,
crusading, and combat have haunted you in your sleep for many months,
but you aren't sure of the reason. You wonder whether you have in
fact been having those dreams all your life, and somehow managed to
forget about them until now. Some nights you awaken suddenly
and cry out, terrified at the vivid recollection of the strange and
powerful creatures that seem to be lurking behind every corner of the
dungeon in your dream. Could these details haunting your dreams be real?
As each night passes, you feel the desire to enter the mysterious caverns
near the ruins grow stronger. Each morning, however, you quickly put
the idea out of your head as you recall the tales of those who entered
the caverns before you and did not return. Eventually you can resist
the yearning to seek out the fantastic place in your dreams no longer.
After all, when other adventurers came back this way after spending time
in the caverns, they usually seemed better off than when they passed
through the first time. And who was to say that all of those who did
and cry out, terrified at the vivid recollection of the strange and
powerful creatures that seem to be lurking behind every corner of the
dungeon in your dream. Could these details haunting your dreams be real?
As each night passes, you feel the desire to enter the mysterious caverns
near the ruins grow stronger. Each morning, however, you quickly put
the idea out of your head as you recall the tales of those who entered
the caverns before you and did not return. Eventually you can resist
the yearning to seek out the fantastic place in your dreams no longer.
After all, when other adventurers came back this way after spending time
in the caverns, they usually seemed better off than when they passed
through the first time. And who was to say that all of those who did
not return had not just kept going?
.pg
@@ -93,23 +93,23 @@ which, if you can find it, will bring you great wealth. One legend you were
told even mentioned that the one who finds the amulet will be granted
immortality by the gods. The amulet is rumored to be somewhere beyond the
Valley of Gehennom, deep within the Mazes of Menace. Upon hearing the
legends, you immediately realize that there is some profound and
undiscovered reason that you are to descend into the caverns and seek
out that amulet of which they spoke. Even if the rumors of the amulet's
powers are untrue, you decide that you should at least be able to sell the
tales of your adventures to the local minstrels for a tidy sum, especially
if you encounter any of the terrifying and magical creatures of
your dreams along the way. You spend one last night fortifying yourself
at the local inn, becoming more and more depressed as you watch the odds
of your success being posted on the inn's walls getting lower and lower.
legends, you immediately realize that there is some profound and
undiscovered reason that you are to descend into the caverns and seek
out that amulet of which they spoke. Even if the rumors of the amulet's
powers are untrue, you decide that you should at least be able to sell the
tales of your adventures to the local minstrels for a tidy sum, especially
if you encounter any of the terrifying and magical creatures of
your dreams along the way. You spend one last night fortifying yourself
at the local inn, becoming more and more depressed as you watch the odds
of your success being posted on the inn's walls getting lower and lower.
.pg
In the morning you awake, collect your belongings, and
set off for the dungeon. After several days of uneventful
travel, you see the ancient ruins that mark the entrance to the
Mazes of Menace. It is late at night, so you make camp at the entrance
and spend the night sleeping under the open skies. In the morning, you
gather your gear, eat what may be your last meal outside, and enter the
In the morning you awake, collect your belongings, and
set off for the dungeon. After several days of uneventful
travel, you see the ancient ruins that mark the entrance to the
Mazes of Menace. It is late at night, so you make camp at the entrance
and spend the night sleeping under the open skies. In the morning, you
gather your gear, eat what may be your last meal outside, and enter the
dungeon...
.hn 1
@@ -295,6 +295,9 @@ do other tasks requiring agility or manipulation of objects.
.lp Constitution
Constitution affects your ability to recover from injuries and other
strains on your stamina.
When strength is low or modest, consitution also affects how much you
can carry. With sufficiently high strength, the contribution to
carrying capacity from your constitution no longer matters.
.lp Intelligence
Intelligence affects your ability to cast spells and read spellbooks.
.lp Wisdom
@@ -331,7 +334,7 @@ amount available.
.lp "Armor Class
A measure of how effectively your armor stops blows from unfriendly
creatures. The lower this number is, the more effective the armor; it
is quite possible to have negative armor class.
is quite possible to have negative armor class.
.lp Experience
Your current experience level and experience points. As you
adventure, you gain experience points. At certain experience point
@@ -547,6 +550,8 @@ a monster there, you will fight the monster instead. Only these
one-step movement commands cause you to fight monsters; the others
(below) are ``safe.''
.sd
.\" note: the two number pad layouts are separated by a tab on each line;
.\" converting those tabs to spaces will screw up the formatting
.TS S
center;
c c.
@@ -582,8 +587,8 @@ is computed over map locations the hero knows about (e.g. seen or
previously traversed). If there is no known path, a guess is made instead.
Stops on most of
the same conditions as the `G' command, but without picking up
objects, similar to the `M' command. For ports with mouse
support, the command is also invoked when a mouse-click takes place on a
objects, similar to the `M' command. For ports with mouse
support, the command is also invoked when a mouse-click takes place on a
location other than the current position.
.lp .
Rest, do nothing for one turn.
@@ -592,7 +597,7 @@ Apply (use) a tool (pick-axe, key, lamp...).
.lp A
Remove one or more worn items, such as armor.
.lp ""
Use `T' (take off) to take off only one piece of armor
Use `T' (take off) to take off only one piece of armor
or `R' (remove) to take off only one accessory.
.lp ^A
Redo the previous command.
@@ -615,7 +620,7 @@ In answer to the question
.lp ""
``What kinds of things do you want to drop? [!%= BUCXaium]''
.lp ""
you should type zero or more object symbols possibly followed by
you should type zero or more object symbols possibly followed by
`a' and/or `i' and/or `u' and/or `m'. In addition, one or more of
the blessed/uncursed/cursed groups may be typed.
.sd
@@ -641,7 +646,7 @@ Eat food.
Engrave a message on the floor.
.sd
.si
E- - write in the dust with your fingers.
E- - write in the dust with your fingers.
.ei
.ed
.lp ""
@@ -912,7 +917,7 @@ Jump to another location.
.lp #kick
Kick something.
.lp #loot
Loot a box or bag on the floor beneath you, or the saddle
Loot a box or bag on the floor beneath you, or the saddle
from a steed standing next to you.
.lp #monster
Use a monster's special ability (when polymorphed into monster form).
@@ -1055,7 +1060,7 @@ Jump to another location. Same as ``#jump'' or ``M-j''.
.lp k
Kick something (usually a door). Same as `^D'.
.lp l
Loot a box or bag on the floor beneath you, or the saddle
Loot a box or bag on the floor beneath you, or the saddle
from a steed standing next to you. Same as ``#loot'' or ``M-l''.
.lp N
Name a monster, an individual object, or a type of object. Same
@@ -1068,7 +1073,7 @@ Untrap a trap, door, or chest. Same as ``#untrap'' or ``M-u''.
Rooms and corridors
.pg
Rooms and corridors in the dungeon are either lit or dark.
Any lit areas within your line of sight will be displayed;
Any lit areas within your line of sight will be displayed;
dark areas are only displayed if they are within one space of you.
Walls and corridors remain on the map as you explore them.
.pg
@@ -1226,7 +1231,7 @@ you attack them. Some of them are very dangerous when angered.
Remember: discretion is the better part of valor.
.pg
In most circumstances, if you attempt to attack a peaceful monster by
moving into its location, you'll be asked to confirm your intent. By
moving into its location, you'll be asked to confirm your intent. By
default an answer of 'y' acknowledges that intent,
which can be error prone if you're using 'y' to move. You can set the
.op paranoid_confirmation
@@ -1267,11 +1272,11 @@ Steeds
.pg
Some types of creatures in the dungeon can actually be ridden if you
have the right equipment and skill. Convincing a wild beast to let
you saddle it up is difficult to say the least. Many a dungeoneer
you saddle it up is difficult to say the least. Many a dungeoneer
has had to resort to magic and wizardry in order to forge the alliance.
Once you do have the beast under your control however, you can
Once you do have the beast under your control however, you can
easily climb in and out of the saddle with the `#ride' command. Lead
the beast around the dungeon when riding, in the same manner as
the beast around the dungeon when riding, in the same manner as
you would move yourself. It is the beast that you will see displayed
on the map.
.pg
@@ -1289,7 +1294,7 @@ former player; it is probably still lurking around, gloating over its
last victory.
.hn 1
Objects
Objects
.pg
When you find something in the dungeon, it is common to want to pick
it up. In NetHack, this is accomplished automatically by walking over
@@ -1298,7 +1303,7 @@ the object (unless you turn off the
option (see below), or move with the `m' prefix (see above)), or
manually by using the `,' command.
.pg
If you're carrying too many items, NetHack will tell you so and you won't
If you're carrying too many items, NetHack will tell you so and you won't
be able to pick
up anything more. Otherwise, it will add the object(s) to your pack and tell
you what you just picked up.
@@ -1306,7 +1311,8 @@ you what you just picked up.
As you add items to your inventory, you also add the weight of that object
to your load. The amount that you can carry depends on your strength and
your constitution. The
stronger you are, the less the additional load will affect you. There comes
stronger and sturdier
you are, the less the additional load will affect you. There comes
a point, though, when the weight of all of that stuff you are carrying around
with you through the dungeon will encumber you. Your reactions
will get slower and you'll burn calories faster, requiring food more frequently
@@ -1523,7 +1529,7 @@ To wield two weapons, you need to use the ``#twoweapon'' command.
But first you need to have a weapon in each hand.
(Note that your two weapons are not fully equal; the one in the
hand you normally wield with is considered primary and the other
one is considered secondary. The most noticeable difference is
one is considered secondary. The most noticeable difference is
after you stop--or before you begin, for that matter--wielding
two weapons at once. The primary is your wielded weapon and the
secondary is just an item in your inventory that's been designated
@@ -1577,6 +1583,7 @@ elven mithril-coat 5
chain mail 5
orcish chain mail 6
scale mail 6
dragon scales 7
studded leather armor 7
ring mail 7
orcish ring mail 8
@@ -1672,10 +1679,12 @@ The command to drink a potion is `q' (quaff).
.hn 2
Wands (`/')
.pg
Magic wands usually have multiple magical charges. Some wands are
directional\(emyou must give a direction in which to zap them. You can also
Wands usually have multiple magical charges.
Some types of wands require a direction in which to zap them.
You can also
zap them at yourself (just give a `.' or `s' for the direction). Be warned,
however, for this is often unwise. Other wands are nondirectional\(emthey
however, for this is often unwise.
Other types of wands
don't require a direction. The number of charges in a wand is random and
decreases by one whenever you use it.
.pg
@@ -1711,7 +1720,7 @@ Putting on a ring activates its magic. You can wear only two
rings, one on each ring finger.
.pg
Most rings also cause you to grow hungry more rapidly, the rate
varying with the type of ring.
varying with the type of ring.
.pg
The commands to use rings are `P' (put on) and `R' (remove).
.hn 2
@@ -1731,16 +1740,18 @@ energy and the time required in casting.
.pg
Casting a spell calls forth magical energies and focuses them with
your naked mind. Some of the magical energy released comes from within
you, and casting several spells in a row may tire you.
you.
Casting temporarily drains your magical power, which will slowly be
recovered, and causes you to need additional food.
Casting of spells also requires practice. With practice, your
skill in each category of spell casting will improve. Over time, however,
your memory of each spell will dim, and you will need to relearn it.
.pg
Some spells are
directional\(emyou must give a direction in which to cast them. You can also
cast them at yourself (just give a `.' or `s' for the direction). Be warned,
however, for this is often unwise. Other spells are nondirectional\(emthey
don't require a direction.
Some spells require a direction in which to cast them, similar to wands.
To cast one at yourself, just give a `.' or `s' for the direction.
A few spells require you to pick a target location rather than just specify
a particular direction.
Other spells don't require any direction or target.
.pg
Just as weapons are divided into groups in which a character can become
proficient (to varying degrees), spells are similarly grouped.
@@ -1816,6 +1827,9 @@ heavy. It is rumored that some statues are not what they seem.
.pg
Very large humanoids (giants and their ilk) have been known to use boulders
as weapons.
.pg
For some configurations of the program, statues are no longer shown as `\`'
but by the letter representing the monster they depict instead.
.hn 2
Gold (`$')
.pg
@@ -1955,7 +1969,7 @@ Using the NETHACKOPTIONS environment variable
The NETHACKOPTIONS variable is a comma-separated list of initial
values for the various options. Some can only be turned on or off.
You turn one of these on by adding the name of the option to the list,
and turn it off by typing a `!' or ``no'' before the name. Others take a
and turn it off by typing a `!' or ``no'' before the name. Others take a
character string as a value. You can set string options by typing
the option name, a colon or equals sign, and then the value of the string.
The value is terminated by the next comma or the end of string.
@@ -1980,15 +1994,16 @@ Any line in the configuration file starting with ``OPTIONS='' may be
filled out with options in the same syntax as in NETHACKOPTIONS.
Any line starting with ``SYMBOLS=''
is taken as defining the corresponding symbol
in a different syntax, a sequence of decimal numbers giving
the character position in the current font to be used in displaying
each entry. Such a sequence can be continued to multiple lines by putting a `\e'
in a different syntax, a sequence of decimal numbers giving
the character position in the current font to be used in displaying
each entry. Such a sequence can be continued to multiple lines by
putting a `\e'
at the end of each line to be continued.
.pg
Any line starting with ``AUTOPICKUP_EXCEPTION='' is taken
as defining an exception to the
as defining an exception to the
.op pickup_types
option.
option.
There is a section of this Guidebook that discusses that.
.pg
The default name of the configuration file varies on different
@@ -2031,7 +2046,7 @@ Persistent.
Your starting alignment (align:lawful, align:neutral,
or align:chaotic). You may specify just the first letter.
The default is to randomly pick an appropriate alignment.
If you prefix a `!' or ``no'' to the value, you can
If you prefix the value with `!' or ``no'', you will
exclude that alignment from being picked randomly.
Cannot be set with the `O' command. Persistent.
.lp autodescribe
@@ -2059,34 +2074,39 @@ into account the blessed/cursed status, enchantment, damage, or
quality of the weapon; you are free to manually fill your quiver or quiver sack
or make ready
with the `Q' command instead. If no weapon is found or the option is
false, the `t' (throw) command is executed instead. Persistent. (default false)
false, the `t' (throw) command is executed instead.
Persistent. (default false)
.lp blind
Start the character permanently blind. Persistent. (default false)
.lp bones
Allow saving and loading bones files. Persistent. (default true)
.lp boulder
Set the character used to display boulders (default is rock class symbol).
Set the character used to display boulders (default is the ``large rock''
class symbol, `\`').
.lp catname
Name your starting cat (ex. ``catname:Morris'').
Cannot be set with the `O' command.
.lp character
Pick your type of character (ex. ``character:Monk'');
synonym for ``role''. See ``name'' for an alternate method
of specifying your role. Normally only the first letter of
the value is examined; the string ``random'' is an exception.
Synonym for ``role'' to pick the type of your character
(ex. ``character:Monk'').
See
.op role
for more details.
.lp checkpoint
Save game state after each level change, for possible recovery after
program crash (default on). Persistent.
.lp checkspace
Check free disk space before writing files to disk (default on).
You may have to turn this off if you have more than 2 GB free space
on the partition used for your save and level files.
on the partition used for your save and level files
(because too much space might overflow the calculation and end up
looking like insufficient space).
Only applies when MFLOPPY was defined during compilation.
.lp clicklook
Allows looking at things on the screen by navigating the mouse
over them and clicking the right mouse button (default off).
.lp cmdassist
Have the game provide some additional command assistance for
Have the game provide some additional command assistance for
new players if it detects some anticipated mistakes (default on).
.lp "confirm "
Have user confirm attacks on pets, shopkeepers, and other
@@ -2144,7 +2164,7 @@ Cannot be set with the `O' command.
.lp extmenu
Changes the extended commands interface to pop-up a menu of available commands.
It is keystroke compatible with the traditional interface except that it does
not require that you hit Enter. It is implemented only by the tty port
not require that you hit Enter. It is implemented only by the tty port
(default off), when the game has been compiled to support tty graphics.
.lp female
An obsolete synonym for ``gender:female''.
@@ -2165,7 +2185,7 @@ You may specify just the first letter. Although you can
still denote your gender using the ``male'' and ``female''
options, the ``gender'' option will take precedence.
The default is to randomly pick an appropriate gender.
If you prefix a `!' or ``no'' to the value, you can
If you prefix the value with `!' or ``no'', you will
exclude that gender from being picked randomly.
Cannot be set with the `O' command. Persistent.
.lp "help "
@@ -2269,7 +2289,7 @@ the object symbols act as menu accelerators (default off).
Do not clear the screen before drawing menus, and align
menus to the right edge of the screen. Only for the tty port.
(default on)
.lp menu_previous_page
.lp menu_previous_page
Menu character accelerator to goto the previous menu page.
Implemented by the Amiga, Gem and tty ports.
Default '<'.
@@ -2412,7 +2432,7 @@ or match an autopickup exception. Default is on. Persistent.
.lp pickup_types
Specify the object types to be picked up when
.op autopickup
is on. Default is all types. You can use
is on. Default is all types. You can use
.op autopickup_exception
configuration file lines to further refine
.op autopickup
@@ -2440,7 +2460,7 @@ Likewise for the `a' (apply) command if it causes the applied item to
become wielded. Persistent.
.lp "race "
Selects your race (for example, ``race:human''). Default is random.
If you prefix a `!' or ``no'' to the value, you can
If you prefix the value with `!' or ``no'', you will
exclude that race from being picked randomly.
Cannot be set with the `O' command. Persistent.
.lp rest_on_space
@@ -2451,13 +2471,15 @@ Pick your type of character (ex. ``role:Samurai'');
synonym for ``character''. See ``name'' for an alternate method
of specifying your role. Normally only the first letter of the
value is examined; `r' is an exception with ``Rogue'', ``Ranger'',
and ``random'' values. If you prefix a `!' or ``no'' to the value, you can
exclude that role from being picked randomly. Persistent.
and ``random'' values.
If you prefix the value with `!' or ``no'', you will
exclude that role from being picked randomly.
Cannot be set with the `O' command. Persistent.
.lp roguesymset
This option may be used to select one of the named symbol sets found within
``symbols'' to alter the symbols displayed on the screen on the rogue level.
.lp rlecomp
When writing out a save file, perform run length compression of the map.
When writing out a save file, perform run length compression of the map.
Not all ports support run length compression. It has no
effect on reading an existing save file.
.lp runmode
@@ -2476,7 +2498,7 @@ update the map after each step;
like walk, but pause briefly after each step.
.PE
This option only affects the game's screen display, not the actual
results of moving. The default is `run'; versions prior to 3.4.1
results of moving. The default is `run'; versions prior to 3.4.1
used `teleport' only. Whether or not the effect is noticeable will
depend upon the window port used or on the type of terminal. Persistent.
.lp safe_pet
@@ -2525,11 +2547,11 @@ Enable coloring of status fields (default off).
See ``Configuring Status Hilites'' for futher information.
.lp suppress_alert
This option may be set to a NetHack version level to suppress
alert notification messages about feature changes for that
alert notification messages about feature changes for that
and prior versions (ex. ``suppress_alert:3.3.1'').
.lp symset
This option may be used to select one of the named symbol sets found within
``symbols'' to alter the symbols displayed on the screen.
``symbols'' to alter the symbols displayed on the screen.
Use ``symset:default'' to explicitly select the default symbols.
.lp "time "
Show the elapsed game time in turns on bottom line (default off). Persistent.
@@ -2578,8 +2600,8 @@ Select which windowing system to use, such as ``tty'' or ``X11''
(default depends on version).
Cannot be set with the `O' command.
.lp zerocomp
When writing out a save file, perform zero-comp compression of the
contents. Not all ports support zero-comp compression. It has no effect
When writing out a save file, perform zero-comp compression of the
contents. Not all ports support zero-comp compression. It has no effect
on reading an existing save file.
.hn 2
Window Port Customization options
@@ -2603,44 +2625,44 @@ Where to align or place the message window (top, bottom, left, or right)
Where to align or place the status window (top, bottom, left, or right).
.lp ascii_map
NetHack should display an ascii character map if it can.
.lp color
NetHack should display color if it can for different monsters,
.lp color
NetHack should display color if it can for different monsters,
objects, and dungeon features
.lp eight_bit_tty
.lp eight_bit_tty
NetHack should pass eight-bit character values (for example, specified with the
.op traps
option) straight through to your terminal (default off).
.lp font_map
.lp font_map
NetHack should use a font by the chosen name for the map window.
.lp font_menu
.lp font_menu
NetHack should use a font by the chosen name for menu windows.
.lp font_message
.lp font_message
NetHack should use a font by the chosen name for the message window.
.lp font_status
.lp font_status
NetHack should use a font by the chosen name for the status window.
.lp font_text
.lp font_text
NetHack should use a font by the chosen name for text windows.
.lp font_size_map
.lp font_size_map
NetHack should use this size font for the map window.
.lp font_size_menu
.lp font_size_menu
NetHack should use this size font for menu windows.
.lp font_size_message
.lp font_size_message
NetHack should use this size font for the message window.
.lp font_size_status
NetHack should use this size font for the status window.
.lp font_size_text
.lp font_size_text
NetHack should use this size font for text windows.
.lp fullscreen
NetHack should try and display on the entire screen rather than in a window.
.lp large_font
.lp large_font
NetHack should use a large font.
.lp map_mode
.lp map_mode
NetHack should display the map in the manner specified.
.lp mouse_support
Allow use of the mouse for input and travel.
.lp player_selection
NetHack should pop up dialog boxes, or use prompts for character selection.
.lp popup_dialog
.lp popup_dialog
NetHack should pop up dialog boxes for input.
.lp preload_tiles
NetHack should preload tiles into memory.
@@ -2661,7 +2683,7 @@ choose from at game startup, if it can. Not all ports support this option.
Display an onscreen keyboard. Handhelds are most likely to support this option.
.lp splash_screen
NetHack should display an opening splash screen when it starts up (default yes).
.lp tiled_map
.lp tiled_map
NetHack should display a tiled map if it can.
.lp tile_file
Specify the name of an alternative tile file to override the default.
@@ -2680,12 +2702,12 @@ the message window.
NetHack should display windows with the specified foreground/background
colors if it can.
.lp wraptext
NetHack port should wrap long lines of text if they don't fit in
NetHack port should wrap long lines of text if they don't fit in
the visible area of the window.
.hn 2
Platform-specific Customization options
.pg
Here are explanations of options that are used by specific platforms or ports
Here are explanations of options that are used by specific platforms or ports
to customize and change the port behavior.
.lp altkeyhandler
Select an alternate keystroke handler dll to load (Win32 tty NetHack only).
@@ -2740,7 +2762,7 @@ Cannot be set with the `O' command.
Set the video mode used (PC NetHack only).
Values are `autodetect', `default', or `vga'.
Setting `vga' (or `autodetect' with vga hardware present) will cause
the game to display tiles.
the game to display tiles.
Cannot be set with the `O' command.
.lp videocolors
Set the color palette for PC systems using NO_TERMS
@@ -2769,17 +2791,17 @@ Configuring Autopickup Exceptions
.pg
You can further refine the behavior of the
.op autopickup
option beyond what is available through the
option beyond what is available through the
.op pickup_types
option.
option.
.pg
By placing
By placing
.op autopickup_exception
lines in your configuration
file, you can define patterns to be checked when the game is about to
autopickup something.
.lp autopickup_exception
Sets an exception to the
Sets an exception to the
.op pickup_types
option.
The
@@ -2788,7 +2810,7 @@ option should be followed by a regular expression to be used as a pattern to
match against the singular form of the description of an object at your
location.
.lp ""
In addition, some characters are treated specially if they occur as the first
In addition, some characters are treated specially if they occur as the first
character in the pattern, specifically:
.sd
.si
@@ -2918,7 +2940,7 @@ displayed with the ``uncursed'' description.
.hn 2
Configuring User Sounds
.pg
Some platforms allow you to define sound files to be played when a message
Some platforms allow you to define sound files to be played when a message
that matches a user-defined pattern is delivered to the message window.
At this time the Qt port and the win32tty and win32gui ports support the
use of user sounds.
@@ -2947,7 +2969,7 @@ The pattern should be a POSIX extended regular expression.
Configuring Status Hilites
.pg
Your copy of NetHack may have been compiled with support for ``Status Hilites''.
If so, you can customize your game display by setting thresholds to
If so, you can customize your game display by setting thresholds to
change the color or appearance of fields in the status display.
.pg
For example, the following line in your config file will cause
@@ -2993,7 +3015,7 @@ config file.
The whole feature can be disabled by setting option statushilites off.
.pg
.hn 2
Modifying NetHack Symbols
Modifying NetHack Symbols
.pg
NetHack can load entire symbol sets from the symbol file.
.pg
@@ -3218,18 +3240,18 @@ overall location of items on the screen.
.pg
While it is not difficult for experienced users to edit the \fBdefaults.nh\fP
file to accomplish this, novices may find this task somewhat daunting.
Included within the ``symbols'' file of all official distributions of NetHack
Included within the ``symbols'' file of all official distributions of NetHack
is a symset called \fBNHAccess\fP. Selecting that symset in your
configuration file will cause the game to run in a manner accessible
to the blind. After you have gained some experience with the game
and with editing files, you may want to alter settings via \fBSYMBOLS=\fP
in your configuration file to better suit your preferences.
configuration file will cause the game to run in a manner accessible
to the blind. After you have gained some experience with the game
and with editing files, you may want to alter settings via \fBSYMBOLS=\fP
in your configuration file to better suit your preferences.
The most crucial settings to make the game accessible are:
.pg
.lp symset:NHAccess
Load a symbol set appropriate for use by blind players.
.lp roguesymset:NHAccess
Load a symbol set for the rogue level that is appropriate for
Load a symbol set for the rogue level that is appropriate for
use by blind players.
.lp menustyle:traditional
This will assist in the interface to speech synthesizers.
@@ -3249,59 +3271,55 @@ The options recognized in this file are listed below. Any option not
set uses a compiled-in default (which may not be appropriate for your
system).
.pg
.\" '\ =\ Word' follow each option name with space+equals+space+first
.\" word of sentence in a way that won't have spaces inserted
.\" there if that line is padded from left to right;
.\" essentially, "OPTION = Word" becomes one token as far
.\" as filling and justifying are concerned
.lp
WIZARDS
A space-separated list of user names who are allowed to play in wizard
WIZARDS\ =\ A space-separated list of user names who are allowed to
play in wizard
mode (the debugging mode, not the magic-using role). A value of a single
asterisk (*) allows anyone to start a game in wizard mode.
.lp
SHELLERS
A list of users who are allowed to use the shell escape command (!). The
SHELLERS\ =\ A list of users who are allowed to use the shell
escape command (!). The syntax is the same as WIZARDS.
.lp
EXPLORERS\ =\ A list of users who are allowed to use the explore mode. The
syntax is the same as WIZARDS.
.lp
EXPLORERS
A list of users who are allowed to use the explore mode. The
syntax is the same as WIZARDS.
MAXPLAYERS\ =\ Limit the maximum number of games that can be running
at the same time.
.lp
MAXPLAYERS
Limit the maximum number of games that can be running at the same time.
SUPPORT\ =\ A string explaining how to get local support (no default value).
.lp
SUPPORT
A string explaining how to get local support (no default value).
RECOVER\ =\ A string explaining how to recover a game on this system
(no default value).
.lp
RECOVER
A string explaining how to recover a game on this system (no default value).
SEDUCE\ =\ 0 or 1 to disable or enable, respectively, the SEDUCE option.
When disabled, incubi and succubi behave like nymphs.
.lp
SEDUCE
0 or 1 to disable or enable, respectively, the SEDUCE option (see the source
for details on this function).
CHECK_PLNAME\ =\ Setting this to 1 will make the EXPLORERS, WIZARDS, and
SHELLERS check for the player name instead of the user's login name.
.lp
CHECK_PLNAME
Setting this to 1 will make the EXPLORERS, WIZARDS, and SHELLERS check
for the player name instead of the user's login name.
.lp
CHECK_SAVE_UID
0 or 1 to disable or enable, respectively, the UID checking for savefiles.
CHECK_SAVE_UID\ =\ 0 or 1 to disable or enable, respectively, the UID
(used identification number) checking for save files (to verify that the
user who is restoring is the same one who saved).
.pg
The following options affect the score file:
.pg
.lp
PERSMAX
Maximum number of entries for one person.
PERSMAX\ =\ Maximum number of entries for one person.
.lp
ENTRYMAX
Maximum number of entries in the score file.
ENTRYMAX\ =\ Maximum number of entries in the score file.
.lp
POINTSMIN
Minimum number of points to get an entry in the score file.
POINTSMIN\ =\ Minimum number of points to get an entry in the score file.
.lp
PERS_IS_UID
0 or 1 to use user names or numeric userids, respectively, to identify
unique people for the score file.
PERS_IS_UID\ =\ 0 or 1 to use user names or numeric userids, respectively,
to identify unique people for the score file.
.lp
MAX_STATUENAME_RANK
Maximum number of score file entries to use for random statue names
(default is 10).
MAX_STATUENAME_RANK\ =\ Maximum number of score file entries to use for
random statue names (default is 10).
.hn 1
Scoring
.pg
@@ -3370,7 +3388,7 @@ or not available will result in falling back to explore mode instead.
.hn
Credits
.pg
The original \fIhack\fP game was modeled on the Berkeley
The original \fIhack\fP game was modeled on the Berkeley
.ux
\fIrogue\fP game. Large portions of this paper were shamelessly
cribbed from \fIA Guide to the Dungeons of Doom\fP, by Michael C. Toy
@@ -3492,29 +3510,31 @@ DevTeam and incorporated the best of these ideas in NetHack 3.3.
The final update to 3.2 was the bug fix release 3.2.3, which was released
simultaneously with 3.3.0 in December 1999 just in time for the Year 2000.
.pg
The 3.3 development team, consisting of \fBMichael Allison\fP, \fBKen Arromdee\fP,
\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSteve Creps\fP, \fBKevin Darcy\fP,
\fBTimo Hakulinen\fP, \fBKevin Hugo\fP, \fBSteve Linhart\fP, \fBKen Lorber\fP,
\fBDean Luick\fP, \fBPat Rankin\fP, \fBEric Smith\fP, \fBMike Stephenson\fP,
\fBJanet Walz\fP, and \fBPaul Winner\fP, released 3.3.0 in
The 3.3 development team, consisting of
\fBMichael Allison\fP, \fBKen Arromdee\fP,
\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSteve Creps\fP, \fBKevin Darcy\fP,
\fBTimo Hakulinen\fP, \fBKevin Hugo\fP, \fBSteve Linhart\fP, \fBKen Lorber\fP,
\fBDean Luick\fP, \fBPat Rankin\fP, \fBEric Smith\fP, \fBMike Stephenson\fP,
\fBJanet Walz\fP, and \fBPaul Winner\fP, released 3.3.0 in
December 1999 and 3.3.1 in August of 2000.
.pg
Version 3.3 offered many firsts. It was the first version to separate race
and profession. The Elf class was removed in preference to an elf race,
and the races of dwarves, gnomes, and orcs made their first appearance in
the game alongside the familiar human race. Monk and Ranger roles joined
Archeologists, Barbarians, Cavemen, Healers, Knights, Priests, Rogues, Samurai,
Version 3.3 offered many firsts. It was the first version to separate race
and profession. The Elf class was removed in preference to an elf race,
and the races of dwarves, gnomes, and orcs made their first appearance in
the game alongside the familiar human race. Monk and Ranger roles joined
Archeologists, Barbarians, Cavemen, Healers, Knights, Priests, Rogues,
Samurai,
Tourists, Valkyries and of course, Wizards. It was also the first version
to allow you to ride a steed, and was the first version to have a publicly
available web-site listing all the bugs that had been discovered. Despite
to allow you to ride a steed, and was the first version to have a publicly
available web-site listing all the bugs that had been discovered. Despite
that constantly growing bug list, 3.3 proved stable enough to last for
more than a year and a half.
.pg
The 3.4 development team initially consisted of
\fBMichael Allison\fP, \fBKen Arromdee\fP,
\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBKevin Hugo\fP, \fBKen Lorber\fP,
\fBDean Luick\fP, \fBPat Rankin\fP, \fBMike Stephenson\fP,
\fBJanet Walz\fP, and \fBPaul Winner\fP, with \fB Warwick Allison\fP joining
\fBDean Luick\fP, \fBPat Rankin\fP, \fBMike Stephenson\fP,
\fBJanet Walz\fP, and \fBPaul Winner\fP, with \fB Warwick Allison\fP joining
just before the release of NetHack 3.4.0 in March 2002.
.pg
As with version 3.3, various people contributed to the game as a whole as
@@ -3528,46 +3548,48 @@ and \fBYitzhak Sapir\fP provided encouragement.
\fBDean Luick\fP, \fBMark Modrall\fP, and \fBKevin Hugo\fP maintained and enhanced the
Macintosh port of 3.4.
.pg
\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBAlex Kompel\fP, \fBDion Nicolaas\fP, and
\fBYitzhak Sapir\fP maintained and enhanced 3.4 for the Microsoft Windows platform.
\fBAlex Kompel\fP contributed a new graphical interface for the Windows port.
\fBMichael Allison\fP, \fBDavid Cohrs\fP, \fBAlex Kompel\fP,
\fBDion Nicolaas\fP, and
\fBYitzhak Sapir\fP maintained and enhanced 3.4 for the Microsoft Windows
platform.
\fBAlex Kompel\fP contributed a new graphical interface for the Windows port.
\fBAlex Kompel\fP also contributed a Windows CE port for 3.4.1.
.pg
\fBRon Van Iwaarden\fP was the sole maintainer of NetHack for OS/2 the past
several releases. Unfortunately Ron's last OS/2 machine stopped working in
early 2006. A great many thanks to Ron for keeping NetHack alive on OS/2
early 2006. A great many thanks to Ron for keeping NetHack alive on OS/2
all these years.
.pg
\fBJanne Salmijarvi\fP and \fBTeemu Suikki\fP maintained and
enhanced the Amiga port of 3.4 after \fBJanne Salmijarvi\fP resurrected
\fBJanne Salmijarvi\fP and \fBTeemu Suikki\fP maintained and
enhanced the Amiga port of 3.4 after \fBJanne Salmijarvi\fP resurrected
it for 3.3.1.
.pg
\fBChristian ``Marvin'' Bressler\fP maintained 3.4 for the Atari after he
\fBChristian ``Marvin'' Bressler\fP maintained 3.4 for the Atari after he
resurrected it for 3.3.1.
.pg
The release of NetHack 3.4.3 in December 2003 marked the beginning of a
The release of NetHack 3.4.3 in December 2003 marked the beginning of a
long release hiatus. 3.4.3 proved to be a remarkably stable version that
provided continued enjoyment by the community for more than a decade. The
devteam slowly and quietly continued to work on the game behind the scenes
during the tenure of 3.4.3. It was during that same period that several new
variants emerged within the NetHack community. Notably sporkhack by
\fBDerek S. Ray\fP, unnethack by \fBPatric Mueller\fP, nitrohack and its
successors originally by \fBDaniel Thaler\fP and then by \fBAlex Smith\fP,
and Dynahack by \fBTung Nguyen\fP. Some of those variants continue to be
provided continued enjoyment by the community for more than a decade. The
devteam slowly and quietly continued to work on the game behind the scenes
during the tenure of 3.4.3. It was during that same period that several new
variants emerged within the NetHack community. Notably sporkhack by
\fBDerek S. Ray\fP, unnethack by \fBPatric Mueller\fP, nitrohack and its
successors originally by \fBDaniel Thaler\fP and then by \fBAlex Smith\fP,
and Dynahack by \fBTung Nguyen\fP. Some of those variants continue to be
developed, maintained, and enjoyed by the community to this day.
.pg
At the beginning of development for what would eventually get released
as 3.6.0, the development team consisted of \fBWarwick Allison\fP,
as 3.6.0, the development team consisted of \fBWarwick Allison\fP,
\fBMichael Allison\fP, \fBKen Arromdee\fP,
\fBDavid Cohrs\fP, \fBJessie Collet\fP,
\fBKen Lorber\fP, \fBDean Luick\fP, \fBPat Rankin\fP,
\fBDavid Cohrs\fP, \fBJessie Collet\fP,
\fBKen Lorber\fP, \fBDean Luick\fP, \fBPat Rankin\fP,
\fBMike Stephenson\fP, \fBJanet Walz\fP, and \fBPaul Winner\fP.
Leading up to the release of 3.6.0 in early 2015, new members
\fBSean Hunt\fP, \fBPasi Kallinen\fP, and \fBDerek S. Ray\fP
joined the NetHack development team.
.pg
In September 2014, an interim snapshot of the code under development was
released publicly by other parties. Since that code was a work-in-progress
In September 2014, an interim snapshot of the code under development was
released publicly by other parties. Since that code was a work-in-progress
and had not gone through the process of debugging it as a suitable release,
it was decided that the version numbers present on that code snapshot would
be retired and never used in an official NetHack release. An announcement
@@ -3580,35 +3602,36 @@ version merges work done by the development team since the previous release
with some of the beloved community patches. Many bugs were fixed and a
large amount of code was restructured.
.pg
\fBThe development team, as well as \fBSteve VanDevender\fP and
\fBKevin Smolkowski\fP ensured that NetHack 3.6 continued to operate on
various Unix flavors and maintained the X11 interface.
\fBThe development team, as well as \fBSteve VanDevender\fP and
\fBKevin Smolkowski\fP ensured that NetHack 3.6 continued to operate on
various Unix flavors and maintained the X11 interface.
.pg
\fBKen Lorber\fP, \fBHaoyang Wang\fP, \fBPat Rankin\fP, and \fBDean Luick\fP
\fBKen Lorber\fP, \fBHaoyang Wang\fP, \fBPat Rankin\fP, and \fBDean Luick\fP
maintained the port of NetHack 3.6 for Mac.
.pg
\fBMichael Allison\fP, \fBDerek S. Ray\fP, \fBYitzhak Sapir\fP,
\fBAlex Kompel\fP, and \fBDion Nicolaas\fP maintained the port of
\fBMichael Allison\fP, \fBDerek S. Ray\fP, \fBYitzhak Sapir\fP,
\fBAlex Kompel\fP, and \fBDion Nicolaas\fP maintained the port of
NetHack 3.6 for Microsoft Windows.
.pg
The 3.6 development team consisting of
\fBMichael Allison\fP, \fBWarwick Allison\fP, \fBKen Arromdee\fP,
\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSean Hunt\fP,
\fBPasi Kallinen\fP, \fBKen Lorber\fP, \fBDean Luick\fP, \fBPat Rankin\fP,
\fBMike Stephenson\fP, \fBDerek S. Ray\fP, \fBJanet Walz\fP, and \fBPaul Winner\fP
\fBDavid Cohrs\fP, \fBJessie Collet\fP, \fBSean Hunt\fP,
\fBPasi Kallinen\fP, \fBKen Lorber\fP, \fBDean Luick\fP, \fBPat Rankin\fP,
\fBMike Stephenson\fP, \fBDerek S. Ray\fP, \fBJanet Walz\fP, and
\fBPaul Winner\fP
released 3.6.1 as a bug fix release in January 2016.
.pg
The official NetHack web site is maintained by \fBKen Lorber\fP at http://www.nethack.org/.
.pg
SHOUT-OUTS
.pg
The devteam would like to give a special "shout-out" to thank the generous
people primarily responsible for the public NetHack servers available for
playing the game at nethack.alt.org and devnull.net. In addition to providing
a way for the public to play a game of NetHack from almost anywhere, they
have hosted annual NetHack tournaments for many, many years.
.pg
On behalf of the NetHack community, thank you very much to
The devteam would like to give a special "shout-out" to thank the generous
people primarily responsible for the public NetHack servers available for
playing the game at nethack.alt.org and devnull.net. In addition to providing
a way for the public to play a game of NetHack from almost anywhere, they
have hosted annual NetHack tournaments for many, many years.
.pg
On behalf of the NetHack community, thank you very much to
\fBM. Drew Streib\fP, \fBPasi Kallinen\fP and \fBRobin Bandy\fP.
.pg
- - - - - - - - - -

View File

@@ -45,7 +45,7 @@
%.au
\author{Original version - Eric S. Raymond\\
(Edited and expanded for 3.6 by Mike Stephenson and others)}
\date{January 18, 2016}
\date{February 22, 2016}
\maketitle
@@ -346,6 +346,9 @@ do other tasks requiring agility or manipulation of objects.
\item[\bb{Constitution}]
Constitution affects your ability to recover from injuries and other
strains on your stamina.
When strength is low or modest, consitution also affects how much you
can carry. With sufficiently high strength, the contribution to
carrying capacity from your constitution no longer matters.
%.lp
\item[\bb{Intelligence}]
Intelligence affects your ability to cast spells and read spellbooks.
@@ -1599,7 +1602,8 @@ to your pack and tell you what you just picked up.
As you add items to your inventory, you also add the weight of that object
to your load. The amount that you can carry depends on your strength and
your constitution. The
stronger you are, the less the additional load will affect you. There comes
stronger and sturdier
you are, the less the additional load will affect you. There comes
a point, though, when the weight of all of that stuff you are carrying around
with you through the dungeon will encumber you. Your reactions
will get slower and you'll burn calories faster, requiring food more frequently
@@ -1897,10 +1901,10 @@ crystal plate mail & 3 & & bronze plate mail & 4\\
splint mail & 4 & & banded mail & 4\\
dwarvish mithril-coat & 4 & & elven mithril-coat & 5\\
chain mail & 5 & & orcish chain mail & 6\\
scale mail & 6 & & studded leather armor & 7\\
ring mail & 7 & & orcish ring mail & 8\\
leather armor & 8 & & leather jacket & 9\\
no armor & 10
scale mail & 6 & & dragon scales & 7\\
studded leather armor & 7 & & ring mail & 7\\
orcish ring mail & 8 & & leather armor & 8\\
leather jacket & 9 & & no armor & 10\\
\end{tabular}
\end{center}
@@ -2015,11 +2019,13 @@ The command to drink a potion is `{\tt q}' (quaff).
\subsection*{Wands (`{\tt /}')}
%.pg
Magic wands usually have multiple magical charges. Some wands are
directional---you must give a direction in which to zap them. You can also
Wands usually have multiple magical charges.
Some types of wands require a direction in which to zap them.
You can also
zap them at yourself (just give a `{\tt .}' or `{\tt s}' for the direction).
Be warned, however, for this is often unwise. Other wands are
nondirectional---they don't require a direction. The number of charges in a
Be warned, however, for this is often unwise.
Other types of wands
don't require a direction. The number of charges in a
wand is random and decreases by one whenever you use it.
%.pg
@@ -2087,17 +2093,19 @@ energy and the time required in casting.
%.pg
Casting a spell calls forth magical energies and focuses them with
your naked mind. Some of the magical energy released comes from within
you, and casting several spells in a row may tire you.
you.
Casting temporarily drains your magical power, which will slowly be
recovered, and causes you to need additional food.
Casting of spells also requires practice. With practice, your
skill in each category of spell casting will improve. Over time, however,
your memory of each spell will dim, and you will need to relearn it.
%.pg
Some spells are
directional---you must give a direction in which to cast them. You can also
cast them at yourself (just give a `{\tt .}' or `{\tt s}' for the direction).
Be warned, however, for this is often unwise. Other spells are
nondirectional---they don't require a direction.
Some spells require a direction in which to cast them, similar to wands.
To cast one at yourself, just give a `{\tt .}' or `{\tt s}' for the direction.
A few spells require you to pick a target location rather than just specify
a particular direction.
Other spells don't require any direction or target.
%.pg
Just as weapons are divided into groups in which a character can become
@@ -2193,6 +2201,11 @@ heavy. It is rumored that some statues are not what they seem.
Very large humanoids (giants and their ilk) have been known to use boulders
as weapons.
%.pg
For some configurations of the program, statues are no longer shown
as `{\tt `}'
but by the letter representing the monster they depict instead.
%.hn 2
\subsection*{Gold (`{\tt \$}')}
@@ -2447,7 +2460,7 @@ Persistent.
Your starting alignment ({\tt align:lawful}, {\tt align:neutral},
or {\tt align:chaotic}). You may specify just the first letter.
The default is to randomly pick an appropriate alignment.
If you prefix `{\tt !}' or ``{\tt no}'' to the value, you can
If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
exclude that alignment from being picked randomly.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
@@ -2487,7 +2500,8 @@ Start the character permanently blind. Persistent. (default false)
Allow saving and loading bones files. Persistent. (default true)
%.lp
\item[\ib{boulder}]
Set the character used to display boulders (default is rock class symbol).
Set the character used to display boulders (default is the ``large rock''
class symbol, `{\tt `}').
%.lp
\item[\ib{catname}]
Name your starting cat (ex.\ ``{\tt catname:Morris}'').
@@ -2495,9 +2509,7 @@ Cannot be set with the `{\tt O}' command.
%.lp character
\item[\ib{character}]
Pick your type of character (ex.\ ``{\tt character:Monk}'');
synonym for ``{\it role\/}''. See ``{\it name\/}'' for an alternate method
of specifying your role. Normally only the first letter of
the value is examined; the string ``{\tt random}'' is an exception.
synonym for ``{\it role\/}''. See {\it role\/} for more details.
%.lp
\item[\ib{checkpoint}]
Save game state after each level change, for possible recovery after
@@ -2506,7 +2518,9 @@ program crash (default on). Persistent.
\item[\ib{checkspace}]
Check free disk space before writing files to disk (default on).
You may have to turn this off if you have more than 2 GB free space
on the partition used for your save and level files.
on the partition used for your save and level files
(because too much space might overflow the calculation and end up
looking like insufficient space).
Only applies when MFLOPPY was defined during compilation.
%.lp
\item[\ib{clicklook}]
@@ -2603,7 +2617,7 @@ You may specify just the first letter. Although you can
still denote your gender using the ``{\tt male}'' and ``{\tt female}''
options, the ``{\tt gender}'' option will take precedence.
The default is to randomly pick an appropriate gender.
If you prefix `{\tt !}' or ``{\tt no}'' to the value, you can
If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
exclude that gender from being picked randomly.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
@@ -2917,7 +2931,7 @@ become wielded. Persistent.
%.Ip
\item[\ib{race}]
Selects your race (for example, ``{\tt race:human}''). Default is random.
If you prefix `{\tt !}' or ``{\tt no}'' to the value, you can
If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
exclude that race from being picked randomly.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
@@ -2930,9 +2944,10 @@ Pick your type of character (ex.\ ``{\tt role:Samurai}'');
synonym for ``{\it character\/}''. See ``{\it name\/}'' for an alternate method
of specifying your role. Normally only the first letter of the
value is examined; `r' is an exception with ``{\tt Rogue}'', {\tt Ranger}'',
and ``{\tt random}'' values. If you prefix `{\tt !}' or ``{\tt no}'' to the
value, you can exclude that role from being picked randomly.
Persistent.
and ``{\tt random}'' values.
If you prefix the value with `{\tt !}' or ``{\tt no}'', you will
exclude that role from being picked randomly.
Cannot be set with the `{\tt O}' command. Persistent.
%.lp
\item[\ib{roguesymset}]
This option may be used to select one of the named symbol sets found within
@@ -3885,7 +3900,7 @@ mode (the debugging mode, not the magic-useing role). A value of a single
asterisk (*) allows anyone to start a game in wizard mode.
%.lp
\item[\ib{SHELLERS}]
A list of users who are allowed to use the shell escape command (!).
A list of users who are allowed to use the shell escape command (`{\tt !}').
The syntax is the same as WIZARDS.
%.lp
\item[\ib{EXPLORERS}]

File diff suppressed because it is too large Load Diff

View File

@@ -163,6 +163,20 @@ using 'R' on armor would bypass some restrictions imposed by 'T' (inner layer
when examining hidden monsters (probing, persistent monster detection), tell
how they're hidden (under an object, on the ceiling, etc)
some quest text corrections
use a much tighter upper bound when summoning nasties; old method could
theoretically create 200 critters at a time
if a long worm inherited inventory from a previous shape, and if an egg or
figurine in that inventory hatched or auto-activated, messages were
given when hero could see any tail segment even if head was unseen,
making it seem as if worm's inventory was kept in the visible segment
Wizard will now steal any quest artifact from hero, not just own role's
prevent a hostile renegade Angel of <lawful god> from delivering taunt
messages which mention threats of retribution from that god
a few types of monster (barrow wight, Nazgul, erinys) have weapon attacks that
don't deal physical damage, so special damage like stoning via wielded
cockatrice corpse wouldn't be inflicted
non-item-using monsters who happened to be carrying scroll or wand of fire or
a fire horn could use it to cure themselves of being turned into slime
Platform- and/or Interface-Specific Fixes
@@ -173,6 +187,8 @@ tty: specifying all four of role, race, gender, and alignment still prompted
for confirmation with "Is this ok?" before starting play
tty: responding with <return> or <enter> during role, race, &c selection
behaved same as <escape> to quit; now it will pick [random] instead
tty: rename struct variable 'filter' (role.c) and function 'winch()' (wintty.c)
to avoid conflicts with <curses.h>
unix/X11: in top level Makefile, some commented out definitions of VARDATND
misspelled pilemark.xbm (as pilemark.xpm)
unix: options file with CR+LF line ends and an invalid option line resulted in
@@ -211,7 +227,8 @@ allow knife and stiletto as possible tin opening tools
wizard mode #wizintrinsic command
additional tribute passages for The Colour of Magic, The Light Fantastic,
Equal Rites, Mort, Sourcery, Wyrd Sisters, Pyramids, Guards! Guards!,
Eric, Moving Pictures, Reaper Man, Snuff, and Raising Steam
Eric, Moving Pictures, Reaper Man, Witches Abroad, Snuff, and
Raising Steam
compile-time options SIMPLE_MAIL and SERVER_ADMIN_MSG for public server use
database entries for Cleaver, Sunsword, Frost and Fire brands, and
polymorph trap
@@ -220,6 +237,12 @@ allow showing coordinates when picking a position on the map and
new status line conditions Stone Strngl Deaf Lev Fly Ride
allow some extra color name aliases for menucolors and status hilites
add extended command #kick
when choosing an inventory item and '-' for bare-hands/fingers/no-ammo is a
choice, include that in the inventory menu if player types '?' or '*'
feedback from probing of long worm now includes number of segments it has
monk starts with 'shuriken' pre-discovered (despite language issue...)
item-using monster on or next to a fire trap can use it to be cured of
turning into slime
Platform- and/or Interface-Specific New Features
@@ -232,11 +255,26 @@ unix: add CHECK_PLNAME-option to sysconf to make WIZARDS, EXPLORERS, and
X11: new NetHack*highlight_prompt resource to control whether the persistent
prompt line between the map and message windows for the NetHack*slow
configuration will be highlighted when it's expecting input
X11: NetHack*extcmd_height_delta resource can be used to adjust initial size
of the extended commands menu
X11: status display split into three columns to accomodate Stone/Deaf/Lev/&c;
NetHack*status_condition.foreground, .background, and .showGrip
resources replaced by status_condition[1-3].*
NetHack Community Patches (or Variation) Included
-------------------------------------------------
Malcolm Ryan's improved tin opener
Ray Chason's keyboard may stop responding after locking or unlocking a door when
using altkeyhandler=nhraykey.dll
Ray Chason's fix: window interfaces that support transparency may give away unseen
parts of the map
Ray Chason's xprname should honor iflags.menu_tab_sep
Ray Chason's punctuation for "That foo is really a mimic."
Ray Chason's proper background tiles for lava and water
Ray Chason's MS-DOS port restored to functionality with credit to Reddit user
b_helyer for the fix to sys/share/pcmain.c
Ray Chason's MSDOS port support for some VESA modes
Code Cleanup and Reorganization

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 extern.h $NHDT-Date: 1455672983 2016/02/17 01:36:23 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.548 $ */
/* NetHack 3.6 extern.h $NHDT-Date: 1456992437 2016/03/03 08:07:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.550 $ */
/* Copyright (c) Steve Creps, 1988. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1136,8 +1136,8 @@ E const char *FDECL(mpoisons_subj, (struct monst *, struct attack *));
E void NDECL(u_slow_down);
E struct monst *NDECL(cloneu);
E void FDECL(expels, (struct monst *, struct permonst *, BOOLEAN_P));
E struct attack *FDECL(getmattk,
(struct permonst *, int, int *, struct attack *));
E struct attack *FDECL(getmattk, (struct monst *, struct monst *,
int, int *, struct attack *));
E int FDECL(mattacku, (struct monst *));
E int FDECL(magic_negation, (struct monst *));
E boolean NDECL(gulp_blnd_check);
@@ -2715,6 +2715,7 @@ E void FDECL(place_worm_tail_randomly, (struct monst *, XCHAR_P, XCHAR_P));
E int FDECL(count_wsegs, (struct monst *));
E boolean FDECL(worm_known, (struct monst *));
E boolean FDECL(worm_cross, (int, int, int, int));
E int FDECL(wseg_at, (struct monst *, int, int));
/* ### worn.c ### */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 flag.h $NHDT-Date: 1451683047 2016/01/01 21:17:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.93 $ */
/* NetHack 3.6 flag.h $NHDT-Date: 1457207000 2016/03/05 19:43:20 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.101 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -261,6 +261,8 @@ struct instance_flags {
#ifdef MSDOS
boolean hasvga; /* has a vga adapter */
boolean usevga; /* use the vga adapter */
boolean hasvesa; /* has a VESA-capable VGA adapter */
boolean usevesa; /* use the VESA-capable VGA adapter */
boolean grmode; /* currently in graphics mode */
#endif
#ifdef LAN_FEATURES

40
include/integer.h Normal file
View File

@@ -0,0 +1,40 @@
/* NetHack 3.6 integer.h $NHDT-Date: 1457210314 2016/03/05 20:38:34 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */
/* NetHack may be freely redistributed. See license for details. */
/* integer.h -- provide sized integer types */
#ifndef INTEGER_H
#define INTEGER_H
#if defined(__STDC__) && __STDC__ >= 199101L
/* The compiler claims to conform to C99. Use stdint.h */
#include <stdint.h>
typedef uint8_t uint8;
typedef int16_t int16;
typedef uint16_t uint16;
typedef int32_t int32;
typedef uint32_t uint32;
#else /* !C99 */
/* Provide uint8, int16, uint16, int32 and uint32 */
typedef unsigned char uint8;
typedef short int16;
typedef unsigned short uint16;
#if defined(__WATCOMC__) && !defined(__386__)
/* Open Watcom providing a 16 bit build for MS-DOS or OS/2 */
/* int is 16 bits; use long for 32 bits */
typedef long int32;
typedef unsigned long uint32;
#else
/* Otherwise, assume either a 32- or 64-bit compiler */
/* long may be 64 bits; use int for 32 bits */
typedef int int32;
typedef unsigned int uint32;
#endif
#endif /* !C99 */
#endif /* INTEGER_H */

View File

@@ -12,55 +12,53 @@
/*
* Adding new mextra structures:
*
* 1. Add the structure definition and any required macros in this file
* above the mextra struct.
* 2. Add a pointer to your new struct to the mextra struct in this
*file.
* 3. Add a referencing macro at the bottom of this file after the
*mextra
* struct (see MNAME, EGD, EPRI, ESHK, EMIN, or EDOG for examples).
* 4. Create a newXX(mtmp) function and possibly a free_XX(mtmp)
*function
* in an appropriate new or existing source file and add a prototype
* for it to include/extern.h.
* 1. Add the structure definition and any required macros in this
* file above the mextra struct.
* 2. Add a pointer to your new struct to the mextra struct in this
* file.
* 3. Add a referencing macro at bottom of this file after the mextra
* struct (see MNAME, EGD, EPRI, ESHK, EMIN, or EDOG for examples).
* 4. Create a newXX(mtmp) function and possibly a free_XX(mtmp)
* function in an appropriate new or existing source file and add
* a prototype for it to include/extern.h.
*
* void FDECL(newXX, (struct monst *));
* void FDECL(free_XX, (struct monst *));
* void FDECL(newXX, (struct monst *));
* void FDECL(free_XX, (struct monst *));
*
* void
* newXX(mtmp)
* struct monst *mtmp;
* {
* if (!mtmp->mextra) mtmp->mextra = newmextra();
* if (!XX(mtmp)) {
* XX(mtmp) = (struct XX *)alloc(sizeof(struct XX));
* (void) memset((genericptr_t) XX(mtmp),
* 0, sizeof(struct XX));
* }
* }
* void
* newXX(mtmp)
* struct monst *mtmp;
* {
* if (!mtmp->mextra)
* mtmp->mextra = newmextra();
* if (!XX(mtmp)) {
* XX(mtmp) = (struct XX *) alloc(sizeof (struct XX));
* (void) memset((genericptr_t) XX(mtmp),
* 0, sizeof (struct XX));
* }
* }
*
* 5. Consider adding a new makemon flag MM_XX flag to include/hack.h
*and
* a corresponding change to makemon() if you require your structure
* to be added at monster creation time. Initialize your struct
* after a successful return from makemon().
* 5. Consider adding a new makemon flag MM_XX flag to include/hack.h
* and a corresponding change to makemon() if you require your
* structure to be added at monster creation time. Initialize your
* struct after a successful return from makemon().
*
* src/makemon.c: if (mmflags & MM_XX) newXX(mtmp);
* your new code: mon = makemon(&mons[mnum], x, y, MM_XX);
* src/makemon.c: if (mmflags & MM_XX) newXX(mtmp);
* your new code: mon = makemon(&mons[mnum], x, y, MM_XX);
*
* 6. Adjust size_monst() in src/cmd.c appropriately.
* 7. Adjust dealloc_mextra() in src/mon.c to clean up
* properly during monst deallocation.
* 8. Adjust copy_mextra() in src/mon.c to make duplicate
* copies of your struct or data on another monst struct.
* 9. Adjust restmon() in src/restore.c to deal with your
* struct or data during a restore.
* 10. Adjust savemon() in src/save.c to deal with your
* struct or data during a save.
* 6. Adjust size_monst() in src/cmd.c appropriately.
* 7. Adjust dealloc_mextra() in src/mon.c to clean up
* properly during monst deallocation.
* 8. Adjust copy_mextra() in src/mon.c to make duplicate
* copies of your struct or data on another monst struct.
* 9. Adjust restmon() in src/restore.c to deal with your
* struct or data during a restore.
* 10. Adjust savemon() in src/save.c to deal with your
* struct or data during a save.
*/
/***
** formerly vault.h -- vault guard extension
** formerly vault.h -- vault guard extension
*/
#define FCSIZ (ROWNO + COLNO)
#define GD_EATGOLD 0x01
@@ -84,7 +82,7 @@ struct egd {
};
/***
** formerly epri.h -- temple priest extension
** formerly epri.h -- temple priest extension
*/
struct epri {
aligntyp shralign; /* alignment of priest's shrine */
@@ -100,7 +98,7 @@ struct epri {
(and emin extension) */
/***
** formerly eshk.h -- shopkeeper extension
** formerly eshk.h -- shopkeeper extension
*/
#define REPAIR_DELAY 5 /* minimum delay between shop damage & repair */
#define BILLSZ 200
@@ -135,7 +133,7 @@ struct eshk {
};
/***
** formerly emin.h -- minion extension
** formerly emin.h -- minion extension
*/
struct emin {
aligntyp min_align; /* alignment of minion */
@@ -143,17 +141,17 @@ struct emin {
};
/***
** formerly edog.h -- pet extension
** formerly edog.h -- pet extension
*/
/* various types of pet food, the lower, the better liked */
/* various types of pet food, the lower, the better liked */
#define DOGFOOD 0
#define CADAVER 1
#define ACCFOOD 2
#define MANFOOD 3
#define APPORT 4
#define POISON 5
#define UNDEF 6
#define TABU 7
#define APPORT 4
#define POISON 5
#define UNDEF 6
#define TABU 7
struct edog {
long droptime; /* moment dog dropped object */
@@ -169,7 +167,7 @@ struct edog {
};
/***
** mextra.h -- collection of all monster extensions
** mextra.h -- collection of all monster extensions
*/
struct mextra {
char *mname;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 obj.h $NHDT-Date: 1450306176 2015/12/16 22:49:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.51 $ */
/* NetHack 3.6 obj.h $NHDT-Date: 1456618994 2016/02/28 00:23:14 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.53 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -200,6 +200,8 @@ struct obj {
&& objects[otmp->otyp].oc_skill >= -P_SHURIKEN \
&& objects[otmp->otyp].oc_skill <= -P_BOW)
#define uslinging() (uwep && objects[uwep->otyp].oc_skill == P_SLING)
/* 'is_quest_artifact()' only applies to the current role's artifact */
#define any_quest_artifact(o) ((o)->oartifact >= ART_ORB_OF_DETECTION)
/* Armor */
#define is_shield(otmp) \

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pcconf.h $NHDT-Date: 1432512776 2015/05/25 00:12:56 $ $NHDT-Branch: master $:$NHDT-Revision: 1.17 $ */
/* NetHack 3.6 pcconf.h $NHDT-Date: 1457207019 2016/03/05 19:43:39 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.19 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -79,6 +79,7 @@
#if (defined(SCREEN_BIOS) || defined(SCREEN_DJGPPFAST)) && !defined(PC9800)
#ifdef USE_TILES
#define SCREEN_VGA /* Include VGA graphics routines in the build */
#define SCREEN_VESA
#endif
#endif
#else
@@ -86,6 +87,7 @@
#undef SCREEN_BIOS
#undef SCREEN_DJGPPFAST
#undef SCREEN_VGA
#undef SCREEN_VESA
#undef TERMLIB
#define ANSI_DEFAULT
#endif
@@ -310,9 +312,8 @@
#endif
/* SCREEN_8514, SCREEN_VESA are only placeholders presently - sub VGA instead
*/
#if defined(SCREEN_8514) || defined(SCREEN_VESA)
#if defined(SCREEN_8514)
#undef SCREEN_8514
#undef SCREEN_VESA
#define SCREEN_VGA
#endif
/* Graphical tile sanity checks */

43
include/tileset.h Normal file
View File

@@ -0,0 +1,43 @@
/* NetHack 3.6 tileset.h $NHDT-Date: 1457207052 2016/03/05 19:44:12 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */
/* Copyright (c) Ray Chason, 2016. */
/* NetHack may be freely redistributed. See license for details. */
#ifndef TILESET_H
#define TILESET_H
struct Pixel {
unsigned char r, g, b, a;
};
struct TileImage {
/* Image data */
unsigned width, height;
struct Pixel *pixels; /* for direct color */
unsigned char *indexes; /* for paletted images */
};
boolean FDECL(read_tiles, (const char *filename, BOOLEAN_P true_color));
const struct Pixel *NDECL(get_palette);
void NDECL(free_tiles);
const struct TileImage *FDECL(get_tile, (unsigned tile_index));
/* Used internally by the tile set code */
struct TileSetImage {
/* Image data */
unsigned width, height;
struct Pixel *pixels; /* for direct color */
unsigned char *indexes; /* for paletted images */
struct Pixel palette[256];
/* Image description from the file */
char *image_desc;
/* Tile dimensions */
unsigned tile_width, tile_height;
};
boolean FDECL(read_bmp_tiles, (const char *filename, struct TileSetImage *image));
boolean FDECL(read_gif_tiles, (const char *filename, struct TileSetImage *image));
boolean FDECL(read_png_tiles, (const char *filename, struct TileSetImage *image));
#endif

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winX.h $NHDT-Date: 1454977916 2016/02/09 00:31:56 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.22 $ */
/* NetHack 3.6 winX.h $NHDT-Date: 1457079196 2016/03/04 08:13:16 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.23 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -252,6 +252,7 @@ typedef struct {
String tile_file; /* name of file to open for tiles */
String icon; /* name of desired icon */
int message_lines; /* number of lines to attempt to show */
int extcmd_height_delta; /* bottom margin for extended command menu */
String pet_mark_bitmap; /* X11 bitmap file used to mark pets */
Pixel pet_mark_color; /* color of pet mark */
String pilemark_bitmap; /* X11 bitmap file used to mark item piles */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 apply.c $NHDT-Date: 1455140802 2016/02/10 21:46:42 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.220 $ */
/* NetHack 3.6 apply.c $NHDT-Date: 1457207021 2016/03/05 19:43:41 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.223 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -323,6 +323,8 @@ register struct obj *obj;
context.stethoscope_move = moves;
context.stethoscope_movement = youmonst.movement;
bhitpos.x = u.ux, bhitpos.y = u.uy; /* tentative, reset below */
notonhead = u.uswallow;
if (u.usteed && u.dz > 0) {
if (interference) {
pline("%s interferes.", Monnam(u.ustuck));
@@ -369,6 +371,10 @@ register struct obj *obj;
const char *mnm = x_monnam(mtmp, ARTICLE_A, (const char *) 0,
SUPPRESS_IT | SUPPRESS_INVISIBLE, FALSE);
/* bhitpos needed by mstatusline() iff mtmp is a long worm */
bhitpos.x = rx, bhitpos.y = ry;
notonhead = (mtmp->mx != rx || mtmp->my != ry);
if (mtmp->mundetected) {
if (!canspotmon(mtmp))
There("is %s hidden there.", mnm);
@@ -389,10 +395,11 @@ register struct obj *obj;
break;
}
seemimic(mtmp);
pline("That %s is really %s", what, mnm);
pline("That %s is really %s.", what, mnm);
} else if (flags.verbose && !canspotmon(mtmp)) {
There("is %s there.", mnm);
}
mstatusline(mtmp);
if (!canspotmon(mtmp))
map_invisible(rx, ry);
@@ -403,6 +410,7 @@ register struct obj *obj;
newsym(rx, ry);
pline_The("invisible monster must have moved.");
}
lev = &levl[rx][ry];
switch (lev->typ) {
case SDOOR:
@@ -1966,8 +1974,8 @@ long timeout;
if (mtmp) {
char and_vanish[BUFSZ];
struct obj *mshelter = level.objects[mtmp->mx][mtmp->my];
Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
Sprintf(monnambuf, "%s", an(m_monnam(mtmp)));
and_vanish[0] = '\0';
if ((mtmp->minvis && !See_invisible)
|| (mtmp->data->mlet == S_MIMIC
@@ -2009,11 +2017,13 @@ long timeout;
case OBJ_MINVENT:
if (cansee_spot && !silent && !suppress_see) {
struct monst *mon;
mon = figurine->ocarry;
/* figurine carrying monster might be invisible */
if (canseemon(figurine->ocarry)) {
if (canseemon(figurine->ocarry)
&& (!mon->wormno || cansee(mon->mx, mon->my)))
Sprintf(carriedby, "%s pack", s_suffix(a_monnam(mon)));
} else if (is_pool(mon->mx, mon->my))
else if (is_pool(mon->mx, mon->my))
Strcpy(carriedby, "empty water");
else
Strcpy(carriedby, "thin air");

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 cmd.c $NHDT-Date: 1452660189 2016/01/13 04:43:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.219 $ */
/* NetHack 3.6 cmd.c $NHDT-Date: 1457207033 2016/03/05 19:43:53 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.220 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -355,7 +355,7 @@ doextlist(VOID_ARGS)
return 0;
}
#ifdef TTY_GRAPHICS
#if defined(TTY_GRAPHICS) || defined(CURSES_GRAPHICS)
#define MAX_EXT_CMD 50 /* Change if we ever have > 50 ext cmds */
/*

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 display.c $NHDT-Date: 1446808439 2015/11/06 11:13:59 $ $NHDT-Branch: master $:$NHDT-Revision: 1.77 $ */
/* NetHack 3.6 display.c $NHDT-Date: 1457207034 2016/03/05 19:43:54 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.82 $ */
/* Copyright (c) Dean Luick, with acknowledgements to Kevin Darcy */
/* and Dave Cohrs, 1990. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1748,7 +1748,8 @@ xchar x, y;
int idx, bkglyph = NO_GLYPH;
struct rm *lev = &levl[x][y];
if (iflags.use_background_glyph) {
if (iflags.use_background_glyph && lev->seenv != 0
&& gbuf[y][x].glyph != cmap_to_glyph(S_stone)) {
switch (lev->typ) {
case SCORR:
case STONE:
@@ -1769,9 +1770,16 @@ xchar x, y;
case CLOUD:
idx = S_cloud;
break;
case POOL:
case MOAT:
idx = S_pool;
break;
case WATER:
idx = S_water;
break;
case LAVAPOOL:
idx = S_lava;
break;
default:
idx = S_room;
break;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 engrave.c $NHDT-Date: 1455491569 2016/02/14 23:12:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.60 $ */
/* NetHack 3.6 engrave.c $NHDT-Date: 1456304550 2016/02/24 09:02:30 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.61 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -535,7 +535,7 @@ doengrave()
return 0;
if (otmp == &zeroobj) {
Strcat(strcpy(fbuf, "your "), makeplural(body_part(FINGER)));
Strcat(strcpy(fbuf, "your "), body_part(FINGERTIP));
writer = fbuf;
} else
writer = yname(otmp);
@@ -993,8 +993,7 @@ doengrave()
if (otmp != &zeroobj)
You("%s the %s with %s.", everb, eloc, doname(otmp));
else
You("%s the %s with your %s.", everb, eloc,
makeplural(body_part(FINGER)));
You("%s the %s with your %s.", everb, eloc, body_part(FINGERTIP));
/* Prompt for engraving! */
Sprintf(qbuf, "What do you want to %s the %s here?", everb, eloc);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 invent.c $NHDT-Date: 1454061993 2016/01/29 10:06:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.193 $ */
/* NetHack 3.6 invent.c $NHDT-Date: 1457207035 2016/03/05 19:43:55 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.197 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -6,6 +6,7 @@
#define NOINVSYM '#'
#define CONTAINED_SYM '>' /* designator for inside a container */
#define HANDS_SYM '-'
STATIC_DCL int FDECL(CFDECLSPEC sortloot_cmp, (struct obj *, struct obj *));
STATIC_DCL void NDECL(reorder_invent);
@@ -21,7 +22,8 @@ STATIC_PTR int FDECL(ckunpaid, (struct obj *));
STATIC_PTR int FDECL(ckvalidcat, (struct obj *));
STATIC_PTR char *FDECL(safeq_xprname, (struct obj *));
STATIC_PTR char *FDECL(safeq_shortxprname, (struct obj *));
STATIC_DCL char FDECL(display_pickinv, (const char *, BOOLEAN_P, long *));
STATIC_DCL char FDECL(display_pickinv, (const char *, const char *,
BOOLEAN_P, long *));
STATIC_DCL char FDECL(display_used_invlets, (CHAR_P));
STATIC_DCL void FDECL(tally_BUCX,
(struct obj *, int *, int *, int *, int *, int *));
@@ -1004,9 +1006,7 @@ register const char *let, *word;
useboulder = TRUE;
if (allownone)
*bp++ = '-';
if (bp > buf && bp[-1] == '-')
*bp++ = ' ';
*bp++ = HANDS_SYM, *bp++ = ' '; /* '-' */
ap = altlets;
if (!flags.invlet_constant)
@@ -1184,6 +1184,7 @@ register const char *let, *word;
ilet = yn_function(qbuf, (char *) 0, '\0');
if (digit(ilet)) {
long tmpcnt = 0;
if (!allowcnt) {
pline("No count allowed with this command.");
continue;
@@ -1199,7 +1200,7 @@ register const char *let, *word;
pline1(Never_mind);
return (struct obj *) 0;
}
if (ilet == '-') {
if (ilet == HANDS_SYM) { /* '-' */
if (!allownone) {
char *suf = (char *) 0;
@@ -1225,21 +1226,34 @@ register const char *let, *word;
char *allowed_choices = (ilet == '?') ? lets : (char *) 0;
long ctmp = 0;
qbuf[0] = '\0';
if (!strcmp(word, "grease"))
Sprintf(qbuf, "your %s", makeplural(body_part(FINGER)));
else if (!strcmp(word, "write with"))
Sprintf(qbuf, "your %s", body_part(FINGERTIP));
else if (!strcmp(word, "wield"))
Sprintf(qbuf, "your %s %s", uarmg ? "gloved" : "bare",
makeplural(body_part(HAND)));
else if (!strcmp(word, "ready"))
Strcpy(qbuf, "empty quiver");
if (ilet == '?' && !*lets && *altlets)
allowed_choices = altlets;
ilet = display_pickinv(allowed_choices, TRUE,
allowcnt ? &ctmp : (long *) 0);
ilet = display_pickinv(allowed_choices, *qbuf ? qbuf : (char *) 0,
TRUE, allowcnt ? &ctmp : (long *) 0);
if (!ilet)
continue;
if (allowcnt && ctmp >= 0) {
cnt = ctmp;
cntgiven = TRUE;
}
if (ilet == HANDS_SYM)
return &zeroobj;
if (ilet == '\033') {
if (flags.verbose)
pline1(Never_mind);
return (struct obj *) 0;
}
if (allowcnt && ctmp >= 0) {
cnt = ctmp;
cntgiven = TRUE;
}
/* they typed a letter (not a space) at the prompt */
}
/* find the item which was picked */
@@ -1423,7 +1437,7 @@ boolean combo; /* combination menu flag */
unsigned *resultflags;
{
int FDECL((*ckfn), (OBJ_P)) = (int FDECL((*), (OBJ_P))) 0;
boolean FDECL((*filter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
boolean FDECL((*ofilter), (OBJ_P)) = (boolean FDECL((*), (OBJ_P))) 0;
boolean takeoff, ident, allflag, m_seen;
int itemcount;
int oletct, iletct, unpaid, oc_of_sym;
@@ -1441,13 +1455,13 @@ unsigned *resultflags;
add_valid_menu_class(0); /* reset */
if (taking_off(word)) {
takeoff = TRUE;
filter = is_worn;
ofilter = is_worn;
} else if (!strcmp(word, "identify")) {
ident = TRUE;
filter = not_fully_identified;
ofilter = not_fully_identified;
}
iletct = collect_obj_classes(ilets, invent, FALSE, filter, &itemcount);
iletct = collect_obj_classes(ilets, invent, FALSE, ofilter, &itemcount);
unpaid = count_unpaid(invent);
if (ident && !iletct) {
@@ -1905,22 +1919,25 @@ long quan; /* if non-0, print this quantity, not obj->quan */
#else
static char li[BUFSZ];
#endif
boolean use_invlet = flags.invlet_constant && let != CONTAINED_SYM;
boolean use_invlet = (flags.invlet_constant
&& let != CONTAINED_SYM && let != HANDS_SYM);
long savequan = 0;
if (quan && obj) {
savequan = obj->quan;
obj->quan = quan;
}
/*
* If let is:
* - Then obj == null and 'txt' refers to hands or fingers.
* * Then obj == null and we are printing a total amount.
* > Then the object is contained and doesn't have an inventory letter.
*/
if (cost != 0 || let == '*') {
/* if dot is true, we're doing Iu, otherwise Ix */
Sprintf(li, "%c - %-45s %6ld %s",
Sprintf(li,
iflags.menu_tab_sep ? "%c - %s\t%6ld %s"
: "%c - %-45s %6ld %s",
(dot && use_invlet ? obj->invlet : let),
(txt ? txt : doname(obj)), cost, currency(cost));
} else {
@@ -1995,8 +2012,9 @@ free_pickinv_cache()
* any count returned from the menu selection is placed here.
*/
STATIC_OVL char
display_pickinv(lets, want_reply, out_cnt)
display_pickinv(lets, xtra_choice, want_reply, out_cnt)
register const char *lets;
const char *xtra_choice; /* "fingers", pick hands rather than an object */
boolean want_reply;
long *out_cnt;
{
@@ -2009,7 +2027,7 @@ long *out_cnt;
menu_item *selected;
struct obj **oarray;
if (flags.perm_invent && lets && *lets) {
if (flags.perm_invent && ((lets && *lets) || xtra_choice)) {
/* partial inventory in perm_invent setting; don't operate on
full inventory window, use an alternate one instead; create
the first time needed and keep it for re-use as needed later */
@@ -2029,8 +2047,21 @@ long *out_cnt;
* don't know at this level if its up or not. This may not be
* an issue if empty checks are done before hand and the call
* to here is short circuited away.
*
* 2: our count here is only to distinguish between 0 and 1 and
* more than 1; for the last one, we don't need a precise number.
* For perm_invent update we force 'more than 1'.
*/
if (!invent && !(flags.perm_invent && !lets && !want_reply)) {
n = (flags.perm_invent && !lets && !want_reply) ? 2
: lets ? (int) strlen(lets)
: !invent ? 0 : !invent->nobj ? 1 : 2;
/* for xtra_choice, there's another 'item' not included in initial 'n';
for !lets (full invent) and for override_ID (wizard mode identify),
skip message_menu handling of single item even if item count was 1 */
if (xtra_choice || (n == 1 && (!lets || iflags.override_ID)))
++n;
if (n == 0) {
pline("Not carrying anything.");
return 0;
}
@@ -2039,31 +2070,39 @@ long *out_cnt;
if (!flags.invlet_constant)
reassign();
if (lets && strlen(lets) == 1 && !iflags.override_ID) {
if (n == 1) {
/* when only one item of interest, use pline instead of menus;
we actually use a fake message-line menu in order to allow
the user to perform selection at the --More-- prompt for tty */
ret = '\0';
for (otmp = invent; otmp; otmp = otmp->nobj) {
if (otmp->invlet == lets[0]) {
ret = message_menu(
lets[0], want_reply ? PICK_ONE : PICK_NONE,
xprname(otmp, (char *) 0, lets[0], TRUE, 0L, 0L));
if (out_cnt)
*out_cnt = -1L; /* select all */
break;
}
if (xtra_choice) {
/* xtra_choice is "bare hands" (wield), "fingertip" (Engrave),
"nothing" (ready Quiver), or "fingers" (apply grease) */
ret = message_menu(HANDS_SYM, PICK_ONE,
xprname((struct obj *) 0, xtra_choice,
HANDS_SYM, TRUE, 0L, 0L)); /* '-' */
} else {
for (otmp = invent; otmp; otmp = otmp->nobj)
if (!lets || otmp->invlet == lets[0])
break;
if (otmp)
ret = message_menu(otmp->invlet,
want_reply ? PICK_ONE : PICK_NONE,
xprname(otmp, (char *) 0, lets[0],
TRUE, 0L, 0L));
}
if (out_cnt)
*out_cnt = -1L; /* select all */
return ret;
}
/* count the number of items */
/* count the number of items (preliminary count of 0,1,more was 'more'
and is now obsolete); we have at least 2 items or want to behave as
if we do (full invent and wiz_identify use this even for 1 item) */
for (n = 0, otmp = invent; otmp; otmp = otmp->nobj)
if (!lets || !*lets || index(lets, otmp->invlet))
n++;
oarray = objarr_init(n);
/* Add objects to the array */
i = 0;
for (otmp = invent; otmp; otmp = otmp->nobj)
@@ -2074,23 +2113,31 @@ long *out_cnt;
start_menu(win);
any = zeroany;
if (wizard && iflags.override_ID) {
char prompt[BUFSZ];
char prompt[QBUFSZ];
any.a_char = -1;
/* wiz_identify stuffed the wiz_identify cmd character
into iflags.override_ID */
/* wiz_identify stuffed the wiz_identify command character (^I)
into iflags.override_ID for our use as an accelerator */
Sprintf(prompt, "Debug Identify (%s to permanently identify)",
visctrl(iflags.override_ID));
add_menu(win, NO_GLYPH, &any, '_', iflags.override_ID, ATR_NONE,
prompt, MENU_UNSELECTED);
} else if (xtra_choice) {
/* wizard override ID and xtra_choice are mutually exclusive */
if (flags.sortpack)
add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
"Miscellaneous", MENU_UNSELECTED);
any.a_char = HANDS_SYM; /* '-' */
add_menu(win, NO_GLYPH, &any, HANDS_SYM, 0, ATR_NONE,
xtra_choice, MENU_UNSELECTED);
}
nextclass:
classcount = 0;
any = zeroany; /* set all bits to zero */
for (i = 0; i < n; i++) {
otmp = oarray[i];
ilet = otmp->invlet;
any = zeroany; /* zero */
if (!flags.sortpack || otmp->oclass == *invlet) {
any = zeroany; /* all bits zero */
ilet = otmp->invlet;
if (flags.sortpack && !classcount) {
add_menu(win, NO_GLYPH, &any, 0, 0, iflags.menu_headings,
let_to_name(*invlet, FALSE,
@@ -2138,7 +2185,7 @@ display_inventory(lets, want_reply)
const char *lets;
boolean want_reply;
{
return display_pickinv(lets, want_reply, (long *) 0);
return display_pickinv(lets, (char *) 0, want_reply, (long *) 0);
}
/*

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mhitm.c $NHDT-Date: 1446854229 2015/11/06 23:57:09 $ $NHDT-Branch: master $:$NHDT-Revision: 1.83 $ */
/* NetHack 3.6 mhitm.c $NHDT-Date: 1456992461 2016/03/03 08:07:41 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.86 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -351,7 +351,7 @@ register struct monst *magr, *mdef;
/* Now perform all attacks for the monster. */
for (i = 0; i < NATTK; i++) {
res[i] = MM_MISS;
mattk = getmattk(pa, i, res, &alt_attk);
mattk = getmattk(magr, mdef, i, res, &alt_attk);
otmp = (struct obj *) 0;
attk = 1;
switch (mattk->aatyp) {

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 mhitu.c $NHDT-Date: 1451084422 2015/12/25 23:00:22 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.132 $ */
/* NetHack 3.6 mhitu.c $NHDT-Date: 1456992469 2016/03/03 08:07:49 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.136 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -256,12 +256,14 @@ boolean message;
/* select a monster's next attack, possibly substituting for its usual one */
struct attack *
getmattk(mptr, indx, prev_result, alt_attk_buf)
struct permonst *mptr;
getmattk(magr, mdef, indx, prev_result, alt_attk_buf)
struct monst *magr, *mdef;
int indx, prev_result[];
struct attack *alt_attk_buf;
{
struct permonst *mptr = magr->data;
struct attack *attk = &mptr->mattk[indx];
struct obj *weap = (magr == &youmonst) ? uwep : MON_WEP(magr);
/* prevent a monster with two consecutive disease or hunger attacks
from hitting with both of them on the same turn; if the first has
@@ -275,7 +277,7 @@ struct attack *alt_attk_buf;
attk->adtyp = AD_STUN;
/* make drain-energy damage be somewhat in proportion to energy */
} else if (attk->adtyp == AD_DREN) {
} else if (attk->adtyp == AD_DREN && mdef == &youmonst) {
int ulev = max(u.ulevel, 6);
*alt_attk_buf = *attk;
@@ -293,6 +295,25 @@ struct attack *alt_attk_buf;
attk->damd += 3; /* very high energy: 3d6 -> 3d9 */
/* note: 3d9 is slightly higher than previous 4d6 */
}
/* barrow wight, Nazgul, erinys have weapon attack for non-physical
damage; force physical damage if attacker has been cancelled or
if weapon is sufficiently interesting; a few unique creatures
have two weapon attacks where one does physical damage and other
doesn't--avoid forcing physical damage for those */
} else if (indx == 0 && magr != &youmonst
&& attk->aatyp == AT_WEAP && attk->adtyp != AD_PHYS
&& !(mptr->mattk[1].aatyp == AT_WEAP
&& mptr->mattk[1].adtyp == AD_PHYS)
&& (magr->mcan
|| (weap
&& ((weap->otyp == CORPSE
&& touch_petrifies(&mons[weap->corpsenm]))
|| weap->oartifact == ART_STORMBRINGER
|| weap->oartifact == ART_VORPAL_BLADE)))) {
*alt_attk_buf = *attk;
attk = alt_attk_buf;
attk->adtyp = AD_PHYS;
}
return attk;
}
@@ -608,7 +629,7 @@ register struct monst *mtmp;
for (i = 0; i < NATTK; i++) {
sum[i] = 0;
mattk = getmattk(mdat, i, sum, &alt_attk);
mattk = getmattk(mtmp, &youmonst, i, sum, &alt_attk);
if ((u.uswallow && mattk->aatyp != AT_ENGL)
|| (skipnonmagc && mattk->aatyp != AT_MAGC))
continue;
@@ -1321,11 +1342,11 @@ register struct attack *mattk;
case AD_SAMU:
hitmsg(mtmp, mattk);
/* when the Wiz hits, 1/20 steals the amulet */
if (u.uhave.amulet || u.uhave.bell || u.uhave.book || u.uhave.menorah
|| u.uhave.questart) /* carrying the Quest Artifact */
if (!rn2(20))
stealamulet(mtmp);
/* when the Wizard or quest nemesis hits, there's a 1/20 chance
to steal a quest artifact (any, not just the one for the hero's
own role) or the Amulet or one of the invocation tools */
if (!rn2(20))
stealamulet(mtmp);
break;
case AD_TLPT:
@@ -1373,9 +1394,10 @@ register struct attack *mattk;
hitmsg(mtmp, mattk);
break;
}
if (!uwep && !uarmu && !uarm && !uarmh && !uarms && !uarmg && !uarmc
&& !uarmf) {
if (!uwep && !uarmu && !uarm && !uarmc
&& !uarms && !uarmg && !uarmf && !uarmh) {
boolean goaway = FALSE;
pline("%s hits! (I hope you don't mind.)", Monnam(mtmp));
if (Upolyd) {
u.mh += rnd(7);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 monmove.c $NHDT-Date: 1455402384 2016/02/13 22:26:24 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.84 $ */
/* NetHack 3.6 monmove.c $NHDT-Date: 1456959639 2016/03/02 23:00:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.85 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1218,12 +1218,12 @@ postmov:
}
ptr = mtmp->data;
/* open a door, or crash through it, if you can */
/* open a door, or crash through it, if 'mtmp' can */
if (IS_DOOR(levl[mtmp->mx][mtmp->my].typ)
&& !passes_walls(ptr) /* doesn't need to open doors */
&& !can_tunnel) { /* taken care of below */
struct rm *here = &levl[mtmp->mx][mtmp->my];
boolean btrapped = (here->doormask & D_TRAPPED),
boolean btrapped = (here->doormask & D_TRAPPED) != 0,
observeit = canseeit && canspotmon(mtmp);
if ((here->doormask & (D_LOCKED | D_CLOSED)) != 0
@@ -1296,7 +1296,7 @@ postmov:
else if (!Deaf)
You_hear("a door crash open.");
}
if (here->doormask & D_LOCKED && !rn2(2))
if ((here->doormask & D_LOCKED) != 0 && !rn2(2))
here->doormask = D_NODOOR;
else
here->doormask = D_BROKEN;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 muse.c $NHDT-Date: 1449799863 2015/12/11 02:11:03 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.69 $ */
/* NetHack 3.6 muse.c $NHDT-Date: 1457254910 2016/03/06 09:01:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.72 $ */
/* Copyright (C) 1990 by Ken Arromdee */
/* NetHack may be freely redistributed. See license for details. */
@@ -34,7 +34,7 @@ STATIC_DCL boolean FDECL(cures_stoning, (struct monst *, struct obj *,
BOOLEAN_P));
STATIC_DCL boolean FDECL(mcould_eat_tin, (struct monst *));
STATIC_DCL boolean FDECL(muse_unslime, (struct monst *, struct obj *,
BOOLEAN_P));
struct trap *, BOOLEAN_P));
STATIC_DCL int FDECL(cures_sliming, (struct monst *, struct obj *));
STATIC_DCL boolean FDECL(green_mon, (struct monst *));
@@ -605,7 +605,7 @@ struct monst *mtmp;
int i, fleetim, how = 0;
struct obj *otmp = m.defensive;
boolean vis, vismon, oseen;
const char *mcsa = "%s can see again.";
const char *Mnam, *mcsa = "%s can see again.";
if ((i = precheck(mtmp, otmp)) != 0)
return i;
@@ -824,9 +824,10 @@ struct monst *mtmp;
if (vis) {
struct trap *t = t_at(trapx, trapy);
pline("%s %s into a %s!", Monnam(mtmp),
makeplural(locomotion(mtmp->data, "jump")),
t->ttyp == TRAPDOOR ? "trap door" : "hole");
Mnam = Monnam(mtmp);
pline("%s %s into a %s!", Mnam,
vtense(Mnam, locomotion(mtmp->data, "jump")),
(t->ttyp == TRAPDOOR) ? "trap door" : "hole");
if (levl[trapx][trapy].typ == SCORR) {
levl[trapx][trapy].typ = CORR;
unblock_point(trapx, trapy);
@@ -920,8 +921,9 @@ struct monst *mtmp;
case MUSE_TELEPORT_TRAP:
m_flee(mtmp);
if (vis) {
pline("%s %s onto a teleport trap!", Monnam(mtmp),
makeplural(locomotion(mtmp->data, "jump")));
Mnam = Monnam(mtmp);
pline("%s %s onto a teleport trap!", Mnam,
vtense(Mnam, locomotion(mtmp->data, "jump")));
seetrap(t_at(trapx, trapy));
}
/* don't use rloc_to() because worm tails must "move" */
@@ -1114,7 +1116,7 @@ struct monst *mtmp;
m.has_offense = MUSE_WAN_FIRE;
}
nomore(MUSE_FIRE_HORN);
if (obj->otyp == FIRE_HORN && obj->spe > 0) {
if (obj->otyp == FIRE_HORN && obj->spe > 0 && can_blow(mtmp)) {
m.offensive = obj;
m.has_offense = MUSE_FIRE_HORN;
}
@@ -1124,7 +1126,7 @@ struct monst *mtmp;
m.has_offense = MUSE_WAN_COLD;
}
nomore(MUSE_FROST_HORN);
if (obj->otyp == FROST_HORN && obj->spe > 0) {
if (obj->otyp == FROST_HORN && obj->spe > 0 && can_blow(mtmp)) {
m.offensive = obj;
m.has_offense = MUSE_FROST_HORN;
}
@@ -1862,9 +1864,12 @@ struct monst *mtmp;
m_useup(mtmp, otmp);
return 2;
case MUSE_POLY_TRAP:
if (vismon)
pline("%s deliberately %s onto a polymorph trap!", Monnam(mtmp),
makeplural(locomotion(mtmp->data, "jump")));
if (vismon) {
const char *Mnam = Monnam(mtmp);
pline("%s deliberately %s onto a polymorph trap!", Mnam,
vtense(Mnam, locomotion(mtmp->data, "jump")));
}
if (vis)
seetrap(t_at(trapx, trapy));
@@ -2069,7 +2074,7 @@ struct obj *obj;
if (typ == UNICORN_HORN)
return (boolean) (!obj->cursed && !is_unicorn(mon->data));
if (typ == FROST_HORN || typ == FIRE_HORN)
return (obj->spe > 0);
return (obj->spe > 0 && can_blow(mon));
break;
case FOOD_CLASS:
if (typ == CORPSE)
@@ -2322,6 +2327,7 @@ struct monst *mon;
boolean by_you;
{
struct obj *obj, odummy;
struct permonst *mptr = mon->data;
/*
* muse_unslime() gives "mon starts turning green", "mon zaps
@@ -2330,7 +2336,7 @@ boolean by_you;
* (via our caller) newcham()'s "mon turns into slime" feedback.
*/
if (slimeproof(mon->data))
if (slimeproof(mptr))
return FALSE;
if (mon->meating || !mon->mcanmove || mon->msleeping)
return FALSE;
@@ -2342,27 +2348,61 @@ boolean by_you;
[possible extension: monst capable of casting high level clerical
spells could toss pillar of fire at self--probably too suicidal] */
if (!mon->mcan && !mon->mspec_used
&& attacktype_fordmg(mon->data, AT_BREA, AD_FIRE)) {
&& attacktype_fordmg(mptr, AT_BREA, AD_FIRE)) {
odummy = zeroobj; /* otyp == STRANGE_OBJECT */
return muse_unslime(mon, &odummy, by_you);
return muse_unslime(mon, &odummy, (struct trap *) 0, by_you);
}
for (obj = mon->minvent; obj; obj = obj->nobj)
if (cures_sliming(mon, obj))
return muse_unslime(mon, obj, by_you);
/* same MUSE criteria as use_defensive() */
if (!is_animal(mptr) && !mindless(mptr)) {
struct trap *t;
/* TODO: check for and move onto an adjacent fire trap */
for (obj = mon->minvent; obj; obj = obj->nobj)
if (cures_sliming(mon, obj))
return muse_unslime(mon, obj, (struct trap *) 0, by_you);
if (((t = t_at(mon->mx, mon->my)) == 0 || t->ttyp != FIRE_TRAP)
&& !mon->mtrapped && !mptr->mmove == 0) {
int xy[2][8], x, y, idx, ridx, nxy = 0;
for (x = mon->mx - 1; x <= mon->mx + 1; ++x)
for (y = mon->my - 1; y <= mon->my + 1; ++y)
if (isok(x, y) && accessible(x, y)
&& !m_at(x, y) && (x != u.ux || y != u.uy)) {
xy[0][nxy] = x, xy[1][nxy] = y;
++nxy;
}
for (idx = 0; idx < nxy; ++idx) {
ridx = rn1(nxy - idx, idx);
if (ridx != idx) {
x = xy[0][idx];
xy[0][idx] = xy[0][ridx];
xy[0][ridx] = x;
y = xy[1][idx];
xy[1][idx] = xy[1][ridx];
xy[1][ridx] = y;
}
if ((t = t_at(xy[0][idx], xy[1][idx])) != 0
&& t->ttyp == FIRE_TRAP)
break;
}
}
if (t && t->ttyp == FIRE_TRAP)
return muse_unslime(mon, &zeroobj, t, by_you);
} /* MUSE */
return FALSE;
}
/* mon uses an item--selected by caller--to burn away incipient slime */
STATIC_OVL boolean
muse_unslime(mon, obj, by_you)
muse_unslime(mon, obj, trap, by_you)
struct monst *mon;
struct obj *obj;
struct trap *trap;
boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
{
{ /* [by_you not honored if 'mon' triggers fire trap]. */
struct obj *odummyp;
int otyp = obj->otyp, dmg;
boolean vis = canseemon(mon), res = TRUE;
@@ -2373,7 +2413,30 @@ boolean by_you; /* true: if mon kills itself, hero gets credit/blame */
/* -4 => sliming, causes quiet loss of enhanced speed */
mon_adjust_speed(mon, -4, (struct obj *) 0);
if (otyp == STRANGE_OBJECT) {
if (trap) {
const char *Mnam = vis ? Monnam(mon) : 0;
if (mon->mx == trap->tx && mon->my == trap->ty) {
if (vis)
pline("%s triggers %s fire trap!", Mnam,
trap->tseen ? "the" : "a");
} else {
remove_monster(mon->mx, mon->my);
newsym(mon->mx, mon->my);
place_monster(mon, trap->tx, trap->ty);
if (mon->wormno) /* won't happen; worms don't MUSE to unslime */
worm_move(mon);
newsym(mon->mx, mon->my);
if (vis)
pline("%s %s %s %s fire trap!", Mnam,
vtense(Mnam, locomotion(mon->data, "move")),
is_floater(mon->data) ? "over" : "onto",
trap->tseen ? "the" : "a");
}
/* hack to avoid mintrap()'s chance of avoiding known trap */
mon->mtrapseen &= ~(1 << (FIRE_TRAP - 1));
mintrap(mon);
} else if (otyp == STRANGE_OBJECT) {
/* monster is using fire breath on self */
if (vis)
pline("%s breathes fire on %sself.", Monnam(mon), mhim(mon));
@@ -2429,7 +2492,8 @@ struct obj *obj;
if (obj->otyp == SCR_FIRE)
return (haseyes(mon->data) && mon->mcansee);
/* hero doesn't need hands or even limbs to zap, so mon doesn't either */
return ((obj->otyp == WAN_FIRE || obj->otyp == FIRE_HORN)
return ((obj->otyp == WAN_FIRE
|| (obj->otyp == FIRE_HORN && can_blow(mon)))
&& obj->spe > 0);
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pline.c $NHDT-Date: 1455672995 2016/02/17 01:36:35 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
/* NetHack 3.6 pline.c $NHDT-Date: 1456528597 2016/02/26 23:16:37 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.49 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -397,6 +397,22 @@ register struct monst *mtmp;
}
} else if (mtmp->mpeaceful)
Strcat(info, ", peaceful");
if (mtmp->data == &mons[PM_LONG_WORM]) {
int segndx, nsegs = count_wsegs(mtmp);
/* the worm code internals don't consider the head of be one of
the worm's segments, but we count it as such when presenting
worm feedback to the player */
if (!nsegs) {
Strcat(info, ", single segment");
} else {
++nsegs; /* include head in the segment count */
segndx = wseg_at(mtmp, bhitpos.x, bhitpos.y);
Sprintf(eos(info), ", %d%s of %d segments",
segndx, ordin(segndx), nsegs);
}
}
if (mtmp->cham >= LOW_PM && mtmp->data != &mons[mtmp->cham])
/* don't reveal the innate form (chameleon, vampire, &c),
just expose the fact that this current form isn't it */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 role.c $NHDT-Date: 1453514597 2016/01/23 02:03:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.36 $ */
/* NetHack 3.6 role.c $NHDT-Date: 1456907852 2016/03/02 08:37:32 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.37 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985-1999. */
/* NetHack may be freely redistributed. See license for details. */
@@ -768,7 +768,7 @@ const struct Align aligns[] = {
static struct {
boolean roles[SIZE(roles)];
short mask;
} filter;
} rfilter;
STATIC_DCL int NDECL(randrole_filtered);
STATIC_DCL char *FDECL(promptsep, (char *, int));
@@ -1046,7 +1046,7 @@ int rolenum, racenum, gendnum, alignnum;
short allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1) {
if (filter.roles[rolenum])
if (rfilter.roles[rolenum])
return FALSE;
allow = roles[rolenum].allow;
if (racenum >= 0 && racenum < SIZE(races) - 1
@@ -1062,7 +1062,7 @@ int rolenum, racenum, gendnum, alignnum;
} else {
/* random; check whether any selection is possible */
for (i = 0; i < SIZE(roles) - 1; i++) {
if (filter.roles[i])
if (rfilter.roles[i])
continue;
allow = roles[i].allow;
if (racenum >= 0 && racenum < SIZE(races) - 1
@@ -1114,7 +1114,7 @@ int rolenum, racenum, gendnum, alignnum;
short allow;
if (racenum >= 0 && racenum < SIZE(races) - 1) {
if (filter.mask & races[racenum].selfmask)
if (rfilter.mask & races[racenum].selfmask)
return FALSE;
allow = races[racenum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1130,7 +1130,7 @@ int rolenum, racenum, gendnum, alignnum;
} else {
/* random; check whether any selection is possible */
for (i = 0; i < SIZE(races) - 1; i++) {
if (filter.mask & races[i].selfmask)
if (rfilter.mask & races[i].selfmask)
continue;
allow = races[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1187,7 +1187,7 @@ int alignnum UNUSED;
short allow;
if (gendnum >= 0 && gendnum < ROLE_GENDERS) {
if (filter.mask & genders[gendnum].allow)
if (rfilter.mask & genders[gendnum].allow)
return FALSE;
allow = genders[gendnum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1200,7 +1200,7 @@ int alignnum UNUSED;
} else {
/* random; check whether any selection is possible */
for (i = 0; i < ROLE_GENDERS; i++) {
if (filter.mask & genders[i].allow)
if (rfilter.mask & genders[i].allow)
continue;
allow = genders[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1256,7 +1256,7 @@ int alignnum;
short allow;
if (alignnum >= 0 && alignnum < ROLE_ALIGNS) {
if (filter.mask & aligns[alignnum].allow)
if (rfilter.mask & aligns[alignnum].allow)
return FALSE;
allow = aligns[alignnum].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1269,7 +1269,7 @@ int alignnum;
} else {
/* random; check whether any selection is possible */
for (i = 0; i < ROLE_ALIGNS; i++) {
if (filter.mask & aligns[i].allow)
if (rfilter.mask & aligns[i].allow)
return FALSE;
allow = aligns[i].allow;
if (rolenum >= 0 && rolenum < SIZE(roles) - 1
@@ -1356,13 +1356,13 @@ const char *bufp;
boolean reslt = TRUE;
if ((i = str2role(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
filter.roles[i] = TRUE;
rfilter.roles[i] = TRUE;
else if ((i = str2race(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
filter.mask |= races[i].selfmask;
rfilter.mask |= races[i].selfmask;
else if ((i = str2gend(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
filter.mask |= genders[i].allow;
rfilter.mask |= genders[i].allow;
else if ((i = str2align(bufp)) != ROLE_NONE && i != ROLE_RANDOM)
filter.mask |= aligns[i].allow;
rfilter.mask |= aligns[i].allow;
else
reslt = FALSE;
return reslt;
@@ -1373,10 +1373,10 @@ gotrolefilter()
{
int i;
if (filter.mask)
if (rfilter.mask)
return TRUE;
for (i = 0; i < SIZE(roles); ++i)
if (filter.roles[i])
if (rfilter.roles[i])
return TRUE;
return FALSE;
}
@@ -1387,8 +1387,8 @@ clearrolefilter()
int i;
for (i = 0; i < SIZE(roles); ++i)
filter.roles[i] = FALSE;
filter.mask = 0;
rfilter.roles[i] = FALSE;
rfilter.mask = 0;
}
#define BP_ALIGN 0
@@ -1836,7 +1836,7 @@ boolean preselect;
what = "role";
f = r;
for (i = 0; i < SIZE(roles); ++i)
if (i != f && !filter.roles[i])
if (i != f && !rfilter.roles[i])
break;
if (i == SIZE(roles)) {
constrainer = "filter";
@@ -1855,7 +1855,7 @@ boolean preselect;
constrainer = "role";
forcedvalue = races[c].noun;
} else if (f >= 0
&& (allowmask & ~filter.mask) == races[f].selfmask) {
&& (allowmask & ~rfilter.mask) == races[f].selfmask) {
/* if there is only one race choice available due to user
options disallowing others, race menu entry is disabled */
constrainer = "filter";
@@ -1877,7 +1877,7 @@ boolean preselect;
constrainer = "role";
forcedvalue = genders[g].adj;
} else if (f >= 0
&& (allowmask & ~filter.mask) == genders[f].allow) {
&& (allowmask & ~rfilter.mask) == genders[f].allow) {
/* if there is only one gender choice available due to user
options disallowing other, gender menu entry is disabled */
constrainer = "filter";
@@ -1912,7 +1912,7 @@ boolean preselect;
constrainer = "race";
}
if (f >= 0 && !constrainer
&& (ROLE_ALIGNMASK & ~filter.mask) == aligns[f].allow) {
&& (ROLE_ALIGNMASK & ~rfilter.mask) == aligns[f].allow) {
/* if there is only one alignment choice available due to user
options disallowing others, algn menu entry is disabled */
constrainer = "filter";

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 steal.c $NHDT-Date: 1446713643 2015/11/05 08:54:03 $ $NHDT-Branch: master $:$NHDT-Revision: 1.65 $ */
/* NetHack 3.6 steal.c $NHDT-Date: 1456618998 2016/02/28 00:23:18 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.67 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -506,50 +506,82 @@ register struct obj *otmp;
return freed_otmp;
}
/* called for AD_SAMU (the Wizard and quest nemeses) */
void
stealamulet(mtmp)
struct monst *mtmp;
{
struct obj *otmp = (struct obj *) 0;
int real = 0, fake = 0;
char buf[BUFSZ];
struct obj *otmp = 0, *obj = 0;
int real = 0, fake = 0, n;
/* select the artifact to steal */
if (u.uhave.amulet) {
real = AMULET_OF_YENDOR;
fake = FAKE_AMULET_OF_YENDOR;
} else if (u.uhave.questart) {
/* target every quest artifact, not just current role's;
if hero has more than one, choose randomly so that player
can't use inventory ordering to influence the theft */
for (n = 0, obj = invent; obj; obj = obj->nobj)
if (any_quest_artifact(obj))
++n, otmp = obj;
if (n > 1) {
n = rnd(n);
for (otmp = invent; otmp; otmp = otmp->nobj)
if (is_quest_artifact(otmp))
break;
if (!otmp)
return; /* should we panic instead? */
} else if (u.uhave.bell) {
real = BELL_OF_OPENING;
fake = BELL;
} else if (u.uhave.book) {
real = SPE_BOOK_OF_THE_DEAD;
} else if (u.uhave.menorah) {
real = CANDELABRUM_OF_INVOCATION;
} else
return; /* you have nothing of special interest */
if (!otmp) {
/* If we get here, real and fake have been set up. */
for (otmp = invent; otmp; otmp = otmp->nobj)
if (otmp->otyp == real || (otmp->otyp == fake && !mtmp->iswiz))
if (any_quest_artifact(otmp) && !--n)
break;
}
if (!otmp) {
/* if we didn't find any quest arifact, find another valuable item */
if (u.uhave.amulet) {
real = AMULET_OF_YENDOR;
fake = FAKE_AMULET_OF_YENDOR;
} else if (u.uhave.bell) {
real = BELL_OF_OPENING;
fake = BELL;
} else if (u.uhave.book) {
real = SPE_BOOK_OF_THE_DEAD;
} else if (u.uhave.menorah) {
real = CANDELABRUM_OF_INVOCATION;
} else
return; /* you have nothing of special interest */
/* If we get here, real and fake have been set up. */
for (n = 0, obj = invent; obj; obj = obj->nobj)
if (obj->otyp == real || (obj->otyp == fake && !mtmp->iswiz))
++n, otmp = obj;
if (n > 1) {
n = rnd(n);
for (otmp = invent; otmp; otmp = otmp->nobj)
if ((otmp->otyp == real
|| (otmp->otyp == fake && !mtmp->iswiz)) && !--n)
break;
}
}
if (otmp) { /* we have something to snatch */
/* take off outer gear if we're targetting [hypothetical]
quest artifact suit, shirt, gloves, or rings */
if ((otmp == uarm || otmp == uarmu) && uarmc)
(void) Cloak_off();
if (otmp == uarmu && uarm)
(void) Armor_off();
if ((otmp == uarmg || ((otmp == uright || otmp == uleft) && uarmg))
&& uwep) {
/* gloves are about to be unworn; unwield weapon(s) first */
if (u.twoweap)
uswapwepgone(); /* will clear u.twoweap */
uwepgone();
}
if ((otmp == uright || otmp == uleft) && uarmg)
(void) Gloves_off(); /* handles wielded cockatrice corpse */
/* finally, steal the target item */
if (otmp->owornmask)
remove_worn_item(otmp, TRUE);
if (otmp->unpaid)
subfrombill(otmp, shop_keeper(*u.ushops));
freeinv(otmp);
/* mpickobj wont merge otmp because none of the above things
to steal are mergable */
(void) mpickobj(mtmp, otmp); /* may merge and free otmp */
pline("%s stole %s!", Monnam(mtmp), doname(otmp));
Strcpy(buf, doname(otmp));
(void) mpickobj(mtmp, otmp); /* could merge and free otmp but won't */
pline("%s steals %s!", Monnam(mtmp), buf);
if (can_teleport(mtmp->data) && !tele_restrict(mtmp))
(void) rloc(mtmp, TRUE);
}
@@ -643,7 +675,7 @@ boolean verbosely;
/* some monsters bypass the normal rules for moving between levels or
even leaving the game entirely; when that happens, prevent them from
taking the Amulet or invocation tools with them */
taking the Amulet, invocation items, or quest artifact with them */
void
mdrop_special_objs(mon)
struct monst *mon;
@@ -653,8 +685,10 @@ struct monst *mon;
for (obj = mon->minvent; obj; obj = otmp) {
otmp = obj->nobj;
/* the Amulet, invocation tools, and Rider corpses resist even when
artifacts and ordinary objects are given 0% resistance chance */
if (obj_resists(obj, 0, 0)) {
artifacts and ordinary objects are given 0% resistance chance;
current role's quest artifact is rescued too--quest artifacts
for the other roles are not */
if (obj_resists(obj, 0, 0) || is_quest_artifact(obj)) {
obj_extract_self(obj);
mdrop_obj(mon, obj, FALSE);
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 timeout.c $NHDT-Date: 1452660198 2016/01/13 04:43:18 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.64 $ */
/* NetHack 3.6 timeout.c $NHDT-Date: 1456526165 2016/02/26 22:36:05 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.65 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -614,14 +614,17 @@ long timeout;
case OBJ_MINVENT:
if (cansee_hatchspot) {
/* egg carrying monster might be invisible */
if (canseemon(egg->ocarry)) {
mon2 = egg->ocarry;
if (canseemon(mon2)
&& (!mon2->wormno || cansee(mon2->mx, mon2->my))) {
Sprintf(carriedby, "%s pack",
s_suffix(a_monnam(egg->ocarry)));
s_suffix(a_monnam(mon2)));
knows_egg = TRUE;
} else if (is_pool(mon->mx, mon->my))
} else if (is_pool(mon->mx, mon->my)) {
Strcpy(carriedby, "empty water");
else
} else {
Strcpy(carriedby, "thin air");
}
You_see("%s %s out of %s!", monnambuf,
locomotion(mon->data, "drop"), carriedby);
}

View File

@@ -701,31 +701,25 @@ u_init()
ini_inv(Knight);
knows_class(WEAPON_CLASS);
knows_class(ARMOR_CLASS);
/* give knights chess-like mobility
* -- idea from wooledge@skybridge.scl.cwru.edu */
/* give knights chess-like mobility--idea from wooledge@..cwru.edu */
HJumping |= FROMOUTSIDE;
skill_init(Skill_K);
break;
case PM_MONK:
switch (rn2(90) / 30) {
case 0:
Monk[M_BOOK].trotyp = SPE_HEALING;
break;
case 1:
Monk[M_BOOK].trotyp = SPE_PROTECTION;
break;
case 2:
Monk[M_BOOK].trotyp = SPE_SLEEP;
break;
}
case PM_MONK: {
static short M_spell[] = { SPE_HEALING, SPE_PROTECTION, SPE_SLEEP };
Monk[M_BOOK].trotyp = M_spell[rn2(90) / 30]; /* [0..2] */
ini_inv(Monk);
if (!rn2(5))
ini_inv(Magicmarker);
else if (!rn2(10))
ini_inv(Lamp);
knows_class(ARMOR_CLASS);
/* sufficiently martial-arts oriented item to ignore language issue */
knows_object(SHURIKEN);
skill_init(Skill_Mon);
break;
}
case PM_PRIEST:
ini_inv(Priest);
if (!rn2(10))

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 uhitm.c $NHDT-Date: 1454664302 2016/02/05 09:25:02 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.154 $ */
/* NetHack 3.6 uhitm.c $NHDT-Date: 1456992470 2016/03/03 08:07:50 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.155 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -2085,7 +2085,7 @@ register struct monst *mon;
for (i = 0; i < NATTK; i++) {
sum[i] = 0;
mattk = getmattk(youmonst.data, i, sum, &alt_attk);
mattk = getmattk(&youmonst, mon, i, sum, &alt_attk);
switch (mattk->aatyp) {
case AT_WEAP:
use_weapon:

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 wizard.c $NHDT-Date: 1446078768 2015/10/29 00:32:48 $ $NHDT-Branch: master $:$NHDT-Revision: 1.42 $ */
/* NetHack 3.6 wizard.c $NHDT-Date: 1456618999 2016/02/28 00:23:19 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.48 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -20,21 +20,37 @@ STATIC_DCL boolean FDECL(you_have, (int));
STATIC_DCL unsigned long FDECL(target_on, (int, struct monst *));
STATIC_DCL unsigned long FDECL(strategy, (struct monst *));
/* adding more neutral creatures will tend to reduce the number of monsters
summoned by nasty(); adding more lawful creatures will reduce the number
of monsters summoned by lawfuls; adding more chaotic creatures will reduce
the number of monsters summoned by chaotics; prior to 3.6.1, there were
only four lawful candidates, so lawful summoners tended to summon more
(trying to get lawful or neutral but obtaining chaotic instead) than
their chaotic counterparts */
static NEARDATA const int nasties[] = {
PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR, PM_RED_DRAGON,
PM_BLACK_DRAGON, PM_GREEN_DRAGON, PM_OWLBEAR, PM_PURPLE_WORM,
PM_ROCK_TROLL, PM_XAN, PM_GREMLIN, PM_UMBER_HULK, PM_VAMPIRE_LORD,
PM_XORN, PM_ZRUTY, PM_ELF_LORD, PM_ELVENKING, PM_YELLOW_DRAGON,
PM_LEOCROTTA, PM_BALUCHITHERIUM, PM_CARNIVOROUS_APE, PM_FIRE_GIANT,
PM_COUATL, PM_CAPTAIN, PM_WINGED_GARGOYLE, PM_MASTER_MIND_FLAYER,
PM_FIRE_ELEMENTAL, PM_JABBERWOCK, PM_ARCH_LICH, PM_OGRE_KING, PM_OLOG_HAI,
PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME, PM_DISENCHANTER
/* neutral */
PM_COCKATRICE, PM_ETTIN, PM_STALKER, PM_MINOTAUR,
PM_OWLBEAR, PM_PURPLE_WORM, PM_XAN, PM_UMBER_HULK,
PM_XORN, PM_ZRUTY, PM_LEOCROTTA, PM_BALUCHITHERIUM,
PM_CARNIVOROUS_APE, PM_FIRE_ELEMENTAL, PM_JABBERWOCK,
PM_IRON_GOLEM, PM_OCHRE_JELLY, PM_GREEN_SLIME,
/* chaotic */
PM_BLACK_DRAGON, PM_RED_DRAGON, PM_ARCH_LICH, PM_VAMPIRE_LORD,
PM_MASTER_MIND_FLAYER, PM_DISENCHANTER, PM_WINGED_GARGOYLE,
PM_STORM_GIANT, PM_OLOG_HAI, PM_ELF_LORD, PM_ELVENKING,
PM_OGRE_KING, PM_CAPTAIN, PM_GREMLIN,
/* lawful */
PM_SILVER_DRAGON, PM_ORANGE_DRAGON, PM_GREEN_DRAGON,
PM_YELLOW_DRAGON, PM_GUARDIAN_NAGA, PM_FIRE_GIANT,
PM_ALEAX, PM_COUATL, PM_HORNED_DEVIL, PM_BARBED_DEVIL,
/* (titans, ki-rin, and golden nagas are suitably nasty, but
they're summoners so would aggravate excessive summoning) */
};
static NEARDATA const unsigned wizapp[] = {
PM_HUMAN, PM_WATER_DEMON, PM_VAMPIRE, PM_RED_DRAGON,
PM_TROLL, PM_UMBER_HULK, PM_XORN, PM_XAN,
PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER
PM_COCKATRICE, PM_FLOATING_EYE, PM_GUARDIAN_NAGA, PM_TRAPPER,
};
/* If you've found the Amulet, make the Wizard appear after some time */
@@ -103,7 +119,8 @@ register struct monst *mtmp;
register struct obj *otmp;
for (otmp = mtmp->minvent; otmp; otmp = otmp->nobj)
if (otmp->otyp == AMULET_OF_YENDOR || is_quest_artifact(otmp)
if (otmp->otyp == AMULET_OF_YENDOR
|| any_quest_artifact(otmp)
|| otmp->otyp == BELL_OF_OPENING
|| otmp->otyp == CANDELABRUM_OF_INVOCATION
|| otmp->otyp == SPE_BOOK_OF_THE_DEAD)
@@ -159,7 +176,7 @@ register short otyp;
if (otyp) {
if (otmp->otyp == otyp)
return 1;
} else if (is_quest_artifact(otmp))
} else if (any_quest_artifact(otmp))
return 1;
}
return 0;
@@ -191,7 +208,7 @@ register short otyp;
if (otyp) {
if (otmp->otyp == otyp)
return otmp;
} else if (is_quest_artifact(otmp))
} else if (any_quest_artifact(otmp))
return otmp;
return (struct obj *) 0;
}
@@ -505,57 +522,88 @@ pick_nasty()
return res;
}
/* create some nasty monsters, aligned or neutral with the caster */
/* a null caster defaults to a chaotic caster (e.g. the wizard) */
/* create some nasty monsters, aligned with the caster or neutral; chaotic
and unaligned are treated as equivalent; if summoner is Null, this is
for late-game harassment (after the Wizard has been killed at least once
or the invocation ritual has been performed), in which case we treat
'summoner' as neutral, since that will produce the greatest number of
creatures on average (in 3.6.0 and earlier, Null was treated as chaotic);
returns the number of monsters created */
int
nasty(mcast)
struct monst *mcast;
nasty(summoner)
struct monst *summoner;
{
register struct monst *mtmp;
register int i, j, tmp;
int castalign = (mcast ? sgn(mcast->data->maligntyp) : -1);
register int i, j;
int castalign = (summoner ? sgn(summoner->data->maligntyp) : 0);
coord bypos;
int count, census;
int count, census, tmp, makeindex, s_cls, m_cls;
#define MAXNASTIES 10 /* more than this can be created */
/* some candidates may be created in groups, so simple count
of non-null makemon() return is inadequate */
census = monster_census(FALSE);
if (!rn2(10) && Inhell) {
/* this might summon a demon prince or lord */
count = msummon((struct monst *) 0); /* summons like WoY */
} else {
count = 0;
tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1; /* just in case -- rph */
/* if we don't have a casting monster, the nasties appear around you
*/
s_cls = summoner ? summoner->data->mlet : 0;
tmp = (u.ulevel > 3) ? u.ulevel / 3 : 1;
/* if we don't have a casting monster, nasties appear around hero,
otherwise they'll appear around spot summoner thinks she's at */
bypos.x = u.ux;
bypos.y = u.uy;
for (i = rnd(tmp); i > 0; --i)
for (i = rnd(tmp); i > 0 && count < MAXNASTIES; --i)
/* Of the 42 nasties[], 10 are lawful, 14 are chaotic,
* and 18 are neutral.
*
* Neutral caster, used for late-game harrassment,
* has 18/42 chance to stop the inner loop on each
* critter, 24/42 chance for another iteration.
* Lawful caster has 28/42 chance to stop unless the
* summoner is an angel or demon, in which case the
* chance is 26/42.
* Chaotic or unaligned caster has 32/42 chance to
* stop, so will summon fewer creatures on average.
*
* The outer loop potentially gives chaotic/unaligned
* a chance to even things up since others will hit
* MAXNASTIES sooner, but its number of iterations is
* randomized so it won't always do so.
*/
for (j = 0; j < 20; j++) {
int makeindex;
/* Don't create more spellcasters of the monsters' level or
* higher--avoids chain summoners filling up the level.
*/
do {
makeindex = pick_nasty();
} while (mcast && attacktype(&mons[makeindex], AT_MAGC)
&& monstr[makeindex] >= monstr[mcast->mnum]);
m_cls = mons[makeindex].mlet;
} while (summoner
&& ((attacktype(&mons[makeindex], AT_MAGC)
&& monstr[makeindex] >= monstr[summoner->mnum])
|| (s_cls == S_DEMON && m_cls == S_ANGEL)
|| (s_cls == S_ANGEL && m_cls == S_DEMON)));
/* do this after picking the monster to place */
if (mcast
&& !enexto(&bypos, mcast->mux, mcast->muy,
&mons[makeindex]))
if (summoner && !enexto(&bypos, summoner->mux, summoner->muy,
&mons[makeindex]))
continue;
/* this honors genocide but overrides extinction; it ignores
inside-hell-only (G_HELL) & outside-hell-only (G_NOHELL) */
if ((mtmp = makemon(&mons[makeindex], bypos.x, bypos.y,
NO_MM_FLAGS)) != 0) {
mtmp->msleeping = mtmp->mpeaceful = mtmp->mtame = 0;
set_malign(mtmp);
} else /* GENOD? */
} else /* random monster to substitute for geno'd selection */
mtmp = makemon((struct permonst *) 0, bypos.x, bypos.y,
NO_MM_FLAGS);
if (mtmp) {
count++;
if (mtmp->data->maligntyp == 0
/* delay first use of spell or breath attack */
mtmp->mspec_used = rnd(4);
if (++count >= MAXNASTIES
|| mtmp->data->maligntyp == 0
|| sgn(mtmp->data->maligntyp) == castalign)
break;
}
@@ -703,11 +751,12 @@ register struct monst *mtmp;
verbalize("%s %s!",
random_malediction[rn2(SIZE(random_malediction))],
random_insult[rn2(SIZE(random_insult))]);
} else if (is_lminion(mtmp)) {
} else if (is_lminion(mtmp)
&& !(mtmp->isminion && EMIN(mtmp)->renegade)) {
com_pager(rn2(QTN_ANGELIC - 1 + (Hallucination ? 1 : 0))
+ QT_ANGELIC);
} else {
if (!rn2(5))
if (!rn2(is_minion(mtmp->data) ? 100 : 5))
pline("%s casts aspersions on your ancestry.", Monnam(mtmp));
else
com_pager(rn2(QTN_DEMONIC) + QT_DEMONIC);

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 worm.c $NHDT-Date: 1446887540 2015/11/07 09:12:20 $ $NHDT-Branch: master $:$NHDT-Revision: 1.19 $ */
/* NetHack 3.6 worm.c $NHDT-Date: 1456528599 2016/02/26 23:16:39 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.20 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -89,11 +89,9 @@ get_wormno()
while (new_wormno < MAX_NUM_WORMS) {
if (!wheads[new_wormno])
return new_wormno; /* found an empty wtails[] slot at new_wormno
*/
return new_wormno; /* found empty wtails[] slot at new_wormno */
new_wormno++;
}
return 0; /* level infested with worms */
}
@@ -296,11 +294,9 @@ register struct monst *worm;
/* if (!wnum) return; bullet proofing */
/* This does not work right now because mattacku() thinks that the head
* is
* out of range of the player. We might try to kludge, and bring the
* head
* within range for a tiny moment, but this needs a bit more looking at
* before we decide to do this.
* is out of range of the player. We might try to kludge, and bring
* the head within range for a tiny moment, but this needs a bit more
* looking at before we decide to do this.
*/
for (seg = wtails[wnum]; seg; seg = seg->nseg)
if (distu(seg->wx, seg->wy) < 3)
@@ -373,7 +369,6 @@ struct obj *weap;
* it's head at "curr" and its tail at "new_tail". The old worm
* must be at least level 3 in order to produce a new worm.
*/
new_worm = 0;
new_wnum = (worm->m_lev >= 3 && !rn2(3)) ? get_wormno() : 0;
if (new_wnum) {
@@ -683,22 +678,19 @@ register xchar *nx, *ny;
}
/* count_wsegs()
* returns the number of visible segments that a worm has.
* returns the number of segments that a worm has.
*/
int
count_wsegs(mtmp)
struct monst *mtmp;
{
register int i = 0;
register struct wseg *curr = (wtails[mtmp->wormno])->nseg;
register struct wseg *curr;
/* if (!mtmp->wormno) return 0; bullet proofing */
while (curr) {
i++;
curr = curr->nseg;
if (mtmp->wormno) {
for (curr = wtails[mtmp->wormno]->nseg; curr; curr = curr->nseg)
i++;
}
return i;
}
@@ -802,4 +794,29 @@ int x1, y1, x2, y2;
return FALSE;
}
/* construct an index number for a worm tail segment */
int
wseg_at(worm, x, y)
struct monst *worm;
int x, y;
{
int res = 0;
if (worm && worm->wormno && m_at(x, y) == worm) {
struct wseg *curr;
int i, n;
xchar wx = (xchar) x, wy = (xchar) y;
for (i = 0, curr = wtails[worm->wormno]; curr; curr = curr->nseg) {
if (curr->wx == wx && curr->wy == wy)
break;
++i;
}
for (n = i; curr; curr = curr->nseg)
++n;
res = n - i;
}
return res;
}
/*worm.c*/

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 zap.c $NHDT-Date: 1449669396 2015/12/09 13:56:36 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.238 $ */
/* NetHack 3.6 zap.c $NHDT-Date: 1456528600 2016/02/26 23:16:40 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.247 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -55,21 +55,21 @@ STATIC_DCL int FDECL(spell_hit_bonus, (int));
STATIC_VAR const char are_blinded_by_the_flash[] =
"are blinded by the flash!";
const char *const flash_types[] =
{ /* also used in buzzmu(mcastu.c) */
"magic missile", /* Wands must be 0-9 */
"bolt of fire", "bolt of cold", "sleep ray", "death ray",
"bolt of lightning", "", "", "", "",
const char *const flash_types[] = /* also used in buzzmu(mcastu.c) */
{
"magic missile", /* Wands must be 0-9 */
"bolt of fire", "bolt of cold", "sleep ray", "death ray",
"bolt of lightning", "", "", "", "",
"magic missile", /* Spell equivalents must be 10-19 */
"fireball", "cone of cold", "sleep ray", "finger of death",
"bolt of lightning", /* There is no spell, used for retribution */
"", "", "", "",
"magic missile", /* Spell equivalents must be 10-19 */
"fireball", "cone of cold", "sleep ray", "finger of death",
"bolt of lightning", /* there is no spell, used for retribution */
"", "", "", "",
"blast of missiles", /* Dragon breath equivalents 20-29*/
"blast of fire", "blast of frost", "blast of sleep gas",
"blast of disintegration", "blast of lightning", "blast of poison gas",
"blast of acid", "", ""
"blast of missiles", /* Dragon breath equivalents 20-29*/
"blast of fire", "blast of frost", "blast of sleep gas",
"blast of disintegration", "blast of lightning",
"blast of poison gas", "blast of acid", "", ""
};
/*
@@ -140,12 +140,13 @@ struct obj *otmp;
int dmg, otyp = otmp->otyp;
const char *zap_type_text = "spell";
struct obj *obj;
boolean disguised_mimic =
(mtmp->data->mlet == S_MIMIC && mtmp->m_ap_type != M_AP_NOTHING);
boolean disguised_mimic = (mtmp->data->mlet == S_MIMIC
&& mtmp->m_ap_type != M_AP_NOTHING);
if (u.uswallow && mtmp == u.ustuck)
reveal_invis = FALSE;
notonhead = (mtmp->mx != bhitpos.x || mtmp->my != bhitpos.y);
switch (otyp) {
case WAN_STRIKING:
zap_type_text = "wand";
@@ -2523,6 +2524,8 @@ struct obj *obj; /* wand or spell */
{
int steedhit = FALSE;
bhitpos.x = u.usteed->mx, bhitpos.y = u.usteed->my;
notonhead = FALSE;
switch (obj->otyp) {
/*
* Wands that are allowed to hit the steed
@@ -3915,6 +3918,7 @@ register int dx, dy;
if (type >= 0)
mon->mstrategy &= ~STRAT_WAITMASK;
buzzmonst:
notonhead = (mon->mx != bhitpos.x || mon->my != bhitpos.y);
if (zap_hit(find_mac(mon), spell_type)) {
if (mon_reflects(mon, (char *) 0)) {
if (cansee(mon->mx, mon->my)) {

View File

@@ -1,4 +1,4 @@
# NetHack 3.6 Makefile.GCC $NHDT-Date: 1432512792 2015/05/25 00:13:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.28 $
# NetHack 3.6 Makefile.GCC $NHDT-Date: 1457207036 2016/03/05 19:43:56 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.29 $
# Copyright (c) NetHack PC Development Team 1996-2006.
# PC NetHack 3.6 Makefile for djgpp V2
#
@@ -66,7 +66,7 @@ LIBRARIES = $(LIBS) $(TERMLIB)
#
# If you have yacc/lex or a work-alike set YACC_LEX to Y
#
YACC_LEX = Y
YACC_LEX = N
ifeq ($(YACC_LEX),Y)
DO_YACC = YACC_ACT
DO_LEX = LEX_ACT
@@ -161,8 +161,8 @@ LFLAGS =
else
# Debugging
#cflags = -pg -c -I../include $(DLBFLG) -DUSE_TILES
#LFLAGS = -pg
#cflags = -g -c -I../include $(DLBFLG) -DUSE_TILES
#LFLAGS = -g
# Normal
cflags = -c -O -I../include $(DLBFLG) -DUSE_TILES
@@ -173,7 +173,7 @@ endif
#================ RULES ==================
#==========================================
.SUFFIXES: .exe .o .tib .til .uu .c .y .l
.SUFFIXES: .exe .o .til .uu .c .y .l
#==========================================
# Rules for files in src
@@ -241,7 +241,7 @@ U = $(UTIL)/
# Utility Objects.
#==========================================
VGAOBJ = $(O)vidvga.o
VGAOBJ = $(O)vidvga.o $(O)vidvesa.o
MAKESRC = makedefs.c
@@ -267,10 +267,10 @@ RECOVOBJS = $(O)recover.o
ifeq ($(SUPPRESS_GRAPHICS),Y)
TILOBJ =
TILOBJ2 =
TEXTIO =
TEXTIO2 =
PLANAR_TIB =
OVERVIEW_TIB =
TILE_BMP =
TILEUTIL =
TILEFILES =
TILEFILES2 =
@@ -281,7 +281,9 @@ PPMWRIT2 =
else
TILOBJ = $(O)tile.o $(O)pctiles.o $(VGAOBJ)
TILOBJ = $(O)tile.o $(VGAOBJ)
TILOBJ2 = $(O)tileset.o $(O)bmptiles.o $(O)giftiles.o
TEXTIO = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o $(O)decl.o $(O)monst.o \
$(O)objects.o $(O)stubvid.o
@@ -289,11 +291,9 @@ TEXTIO = $(O)tiletext.o $(O)tiletxt.o $(O)drawing.o $(O)decl.o $(O)monst.o
TEXTIO2 = $(O)tiletex2.o $(O)tiletxt2.o $(O)drawing.o $(O)decl.o $(O)monst.o \
$(O)objects.o $(O)stubvid.o
PLANAR_TIB = $(DAT)/NetHack1.tib
TILE_BMP = $(DAT)/nhtiles.bmp
OVERVIEW_TIB = $(DAT)/NetHacko.tib
TILEUTIL = $(TILOBJ) $(U)tile2bin.exe $(U)til2bin2.exe $(PLANAR_TIB) $(OVERVIEW_TIB)
TILEUTIL = $(TILOBJ) $(U)tile2bin.exe $(U)til2bin2.exe $(TILE_BMP)
TILEFILES = $(WSHR)/monsters.txt $(WSHR)/objects.txt $(WSHR)/other.txt
@@ -336,7 +336,7 @@ VOBJ19 = $(O)trap.o $(O)u_init.o $(O)uhitm.o $(O)vault.o $(O)vision.o
VOBJ20 = $(O)vis_tab.o $(O)weapon.o $(O)were.o $(O)wield.o $(O)windows.o
VOBJ21 = $(O)wintty.o $(O)wizard.o $(O)worm.o $(O)worn.o $(O)write.o
VOBJ22 = $(O)zap.o $(O)light.o $(O)dlb.o $(O)dig.o $(O)teleport.o
VOBJ23 = $(O)region.o $(O)sys.o
VOBJ23 = $(O)region.o $(O)sys.o $(O)pmatchre.o $(O)string.o $(O)unicode.o
SOBJ = $(O)msdos.o $(O)sound.o $(O)pcsys.o $(O)tty.o $(O)unix.o \
$(O)video.o $(O)vidtxt.o $(O)pckeys.o
@@ -349,7 +349,7 @@ VOBJ = $(VOBJ01) $(VOBJ02) $(VOBJ03) $(VOBJ04) $(VOBJ05) \
$(VOBJ16) $(VOBJ17) $(VOBJ18) $(VOBJ19) $(VOBJ20) \
$(VOBJ21) $(VOBJ22) $(VOBJ23)
ALLOBJ = $(VOBJ) $(SOBJ) $(TILOBJ) $(VVOBJ)
ALLOBJ = $(VOBJ) $(SOBJ) $(TILOBJ) $(TILOBJ2) $(VVOBJ)
#==========================================
# Header file macros
@@ -391,7 +391,7 @@ DLB_H = $(INCL)/dlb.h
ifeq ($(SUPPRESS_GRAPHICS),Y)
TILE_H =
else
TILE_H = $(WSHR)/tile.h $(MSYS)/pctiles.h
TILE_H = $(WSHR)/tile.h $(INCL)/tileset.h
endif
ifeq ($(USE_DLB),Y)
@@ -448,11 +448,12 @@ endif
ifdef TERMLIB
@$(subst /,\,copy $(SSHR)/termcap $(GAMEDIR))
endif
@$(subst /,\,if exist $(DAT)/*.tib copy $(DAT)/*.tib $(GAMEDIR))
@$(subst /,\,if exist $(TILE_BMP) copy $(TILE_BMP) $(GAMEDIR))
@$(subst /,\,if exist $(DAT)/symbols copy $(DAT)/symbols $(GAMEDIR))
@$(subst /,\,copy $(SSHR)/NetHack.cnf $(GAMEDIR)/defaults.nh)
@$(subst /,\,copy $(MSYS)/NHAccess.nh $(GAMEDIR))
-@$(subst /,\,touch $(GAMEDIR)/record)
@$(subst /,\,copy $(DOC)/guidebo*.txt $(GAMEDIR))
@$(subst /,\,copy ../sys/winnt/sysconf $(GAMEDIR))
@$(subst /,\,if exist $(DOC)/nethack.txt copy $(DOC)/nethack.txt $(GAMEDIR))
ifdef CWSDPMI
@$(subst /,\,if exist $(CWSDPMI) copy $(CWSDPMI) $(GAMEDIR))
@@ -466,7 +467,35 @@ endif
#==========================================
$(GAMEFILE): $(O)obj.tag $(PATCHLEV_H) $(O)utility.tag $(ALLOBJ) $(O)$(GAME).lnk
$(LINK) $(LFLAGS) -o$(GAME).exe @$(O)$(GAME).lnk $(LIBRARIES) $(ZLIB)
@if exist temp.a del temp.a
@ar ru temp.a $(VOBJ01)
@ar ru temp.a $(VOBJ02)
@ar ru temp.a $(VOBJ03)
@ar ru temp.a $(VOBJ04)
@ar ru temp.a $(VOBJ05)
@ar ru temp.a $(VOBJ06)
@ar ru temp.a $(VOBJ07)
@ar ru temp.a $(VOBJ08)
@ar ru temp.a $(VOBJ09)
@ar ru temp.a $(VOBJ10)
@ar ru temp.a $(VOBJ11)
@ar ru temp.a $(VOBJ12)
@ar ru temp.a $(VOBJ13)
@ar ru temp.a $(VOBJ14)
@ar ru temp.a $(VOBJ15)
@ar ru temp.a $(VOBJ16)
@ar ru temp.a $(VOBJ17)
@ar ru temp.a $(VOBJ18)
@ar ru temp.a $(VOBJ19)
@ar ru temp.a $(VOBJ20)
@ar ru temp.a $(VOBJ21)
@ar ru temp.a $(VOBJ22)
@ar ru temp.a $(VOBJ23)
@ar ru temp.a $(SOBJ)
@ar ru temp.a $(TILOBJ)
@ar ru temp.a $(TILOBJ2)
@ar ru temp.a $(VVOBJ)
$(LINK) $(LFLAGS) -o$(GAME).exe temp.a $(LIBRARIES) $(ZLIB)
@$(subst /,\,stubedit $(GAME).exe minstack=2048K)
@$(subst /,\,copy $(GAME).exe $(GAMEFILE))
@$(subst /,\,del $(GAME).exe)
@@ -497,6 +526,7 @@ $(O)$(GAME).lnk: $(ALLOBJ)
echo $(VOBJ23) >> $(subst /,\,$@)
echo $(SOBJ) >> $(subst /,\,$@)
echo $(TILOBJ) >> $(subst /,\,$@)
echo $(TILOBJ2) >> $(subst /,\,$@)
echo $(VVOBJ) >> $(subst /,\,$@)
@@ -513,6 +543,7 @@ clean:
$(subst /,\,if exist $(O)sp_lev.tag del $(O)sp_lev.tag)
$(subst /,\,if exist $(O)thintile.tag del $(O)thintile.tag)
$(subst /,\,if exist $(O)utility.tag del $(O)utility.tag)
$(subst /,\,if exist temp.a del temp.a)
spotless: clean
@@ -527,6 +558,7 @@ spotless: clean
$(subst /,\,if exist $(U)dgn_comp.exe del $(U)dgn_comp.exe)
$(subst /,\,if exist $(U)recover.exe del $(U)recover.exe)
$(subst /,\,if exist $(U)tilemap.exe del $(U)tilemap.exe)
$(subst /,\,if exist $(U)tile2bmp.exe del $(U)tile2bmp.exe)
$(subst /,\,if exist $(U)tile2bin.exe del $(U)tile2bin.exe)
$(subst /,\,if exist $(U)til2bin2.exe del $(U)til2bin2.exe)
$(subst /,\,if exist $(U)thintile.exe del $(U)thintile.exe)
@@ -547,11 +579,13 @@ spotless: clean
$(subst /,\,if exist $(DAT)/dungeon del $(DAT)/dungeon)
$(subst /,\,if exist $(DAT)/oracles del $(DAT)/oracles)
$(subst /,\,if exist $(DAT)/quest.dat del $(DAT)/quest.dat)
$(subst /,\,if exist $(DAT)/bogusmon del $(DAT)/bogusmon)
$(subst /,\,if exist $(DAT)/engrave del $(DAT)/engrave)
$(subst /,\,if exist $(DAT)/epitaph del $(DAT)/epitaph)
$(subst /,\,if exist $(DAT)/dlb.lst del $(DAT)/dlb.lst)
$(subst /,\,if exist $(DAT)/nhdat del $(DAT)/nhdat)
$(subst /,\,if exist $(DAT)/*.lev del $(DAT)/*.lev)
$(subst /,\,if exist $(PLANAR_TIB) del $(PLANAR_TIB))
$(subst /,\,if exist $(OVERVIEW_TIB) del $(OVERVIEW_TIB))
$(subst /,\,if exist $(TILE_BMP) del $(TILE_BMP))
$(subst /,\,if exist $(WSHR)/monthin.txt del $(WSHR)/monthin.txt)
$(subst /,\,if exist $(WSHR)/objthin.txt del $(WSHR)/objthin.txt)
$(subst /,\,if exist $(WSHR)/oththin.txt del $(WSHR)/oththin.txt)
@@ -614,7 +648,9 @@ $(O)makedefs.o: $(CONFIG_H) $(PERMONST_H) $(INCL)/objclass.h \
#==========================================
$(U)lev_comp.exe: $(SPLEVOBJS)
$(LINK) $(LFLAGS) -o$@ $(SPLEVOBJS)
@rm -f temp.a
@ar ru temp.a $(SPLEVOBJS)
$(LINK) $(LFLAGS) -o$@ temp.a
ifeq ($(YACC_LEX),Y)
@@ -770,23 +806,26 @@ $(O)tilemap.o: $(WSHR)/tilemap.c $(HACK_H) $(TILE_H)
# Required for tile support
#==========================================
$(DAT)/NetHack1.tib: $(TILEFILES) $(U)tile2bin.exe
$(DAT)/nhtiles.bmp: $(TILEFILES) $(U)tile2bmp.exe
@echo Creating binary tile files (this may take some time)
@$(subst /,\,chdir $(DAT))
@$(subst /,\,$(U)tile2bin.exe)
@$(subst /,\,$(U)tile2bmp.exe $@)
@$(subst /,\,chdir $(SRC))
$(DAT)/NetHacko.tib: $(O)thintile.tag $(TILEFILES2) $(U)til2bin2.exe
@echo Creating overview binary tile files (this may take some time)
@$(subst /,\,chdir $(DAT))
@$(subst /,\,$(U)til2bin2.exe)
@$(subst /,\,chdir $(SRC))
$(U)tile2bmp.exe: $(O)tile2bmp.o $(TEXTIO)
@rm -f temp.a
@ar ru temp.a $(TEXTIO)
$(LINK) $(LFLAGS) -o$@ $(O)tile2bmp.o temp.a
$(U)tile2bin.exe: $(O)tile2bin.o $(TEXTIO)
$(LINK) $(LFLAGS) -o$@ $(O)tile2bin.o $(TEXTIO)
@rm -f temp.a
@ar ru temp.a $(TEXTIO)
$(LINK) $(LFLAGS) -o$@ $(O)tile2bin.o temp.a
$(U)til2bin2.exe: $(O)til2bin2.o $(TEXTIO2)
$(LINK) $(LFLAGS) -o$@ $(O)til2bin2.o $(TEXTIO2)
@rm -f temp.a
@ar ru temp.a $(TEXTIO2)
$(LINK) $(LFLAGS) -o$@ $(O)til2bin2.o temp.a
$(U)thintile.exe: $(O)thintile.o
$(LINK) $(LFLAGS) -o$@ $(O)thintile.o
@@ -798,6 +837,9 @@ $(O)thintile.tag: $(U)thintile.exe $(TILEFILES)
@$(subst /,\,$(U)thintile.exe)
@$(subst /,\,echo thintiles created >$@)
$(O)tile2bmp.o: $(HACK_H) $(TILE_H) $(WSHR)/tile2bmp.c
$(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(WSHR)/tile2bmp.c
$(O)tile2bin.o: $(HACK_H) $(TILE_H) $(MSYS)/pctiles.h $(MSYS)/pcvideo.h $(MSYS)/tile2bin.c
$(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/tile2bin.c
@@ -900,6 +942,15 @@ $(DAT)/quest.dat: $(O)utility.tag $(DAT)/quest.txt
$(DAT)/oracles: $(O)utility.tag $(DAT)/oracles.txt
@$(subst /,\,$(U)makedefs.exe -h)
$(DAT)/bogusmon: $(O)utility.tag $(DAT)/bogusmon.txt
@$(subst /,\,$(U)makedefs.exe -s)
$(DAT)/engrave: $(O)utility.tag $(DAT)/engrave.txt
@$(subst /,\,$(U)makedefs.exe -s)
$(DAT)/epitaph: $(O)utility.tag $(DAT)/epitaph.txt
@$(subst /,\,$(U)makedefs.exe -s)
$(O)sp_lev.tag: $(O)utility.tag $(DAT)/bigroom.des $(DAT)/castle.des \
$(DAT)/endgame.des $(DAT)/gehennom.des $(DAT)/knox.des \
$(DAT)/medusa.des $(DAT)/oracle.des $(DAT)/tower.des \
@@ -949,24 +1000,14 @@ $(DAT)/dungeon: $(O)utility.tag $(DAT)/dungeon.def
#note that dir below assumes bin/dir.exe from djgpp distribution
#
$(DAT)/nhdat: $(U)dlb_main.exe $(DAT)/data $(DAT)/rumors $(DAT)/dungeon \
$(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag
$(DAT)/oracles $(DAT)/quest.dat $(O)sp_lev.tag \
$(DAT)/bogusmon $(DAT)/engrave $(DAT)/epitaph $(DAT)/tribute
@$(subst /,\,echo dat done >$(O)dat.tag)
@$(subst /,\,cd $(DAT))
@$(subst /,\,copy $(MSYS)/msdoshlp.txt .)
@$(subst /,\,echo data >dlb.lst)
@$(subst /,\,echo dungeon >>dlb.lst)
@$(subst /,\,echo oracles >>dlb.lst)
@$(subst /,\,echo options >>dlb.lst)
@$(subst /,\,echo quest.dat >>dlb.lst)
@$(subst /,\,echo rumors >>dlb.lst)
@$(subst /,\,echo help >>dlb.lst)
@$(subst /,\,echo hh >>dlb.lst)
@$(subst /,\,echo cmdhelp >>dlb.lst)
@$(subst /,\,echo history >>dlb.lst)
@$(subst /,\,echo opthelp >>dlb.lst)
@$(subst /,\,echo wizhelp >>dlb.lst)
@$(subst /,\,echo license >>dlb.lst)
@$(subst /,\,echo msdoshlp.txt >>dlb.lst)
@$(LS) data dungeon oracles options quest.dat rumors help hh >dlb.lst
@$(LS) cmdhelp history opthelp wizhelp license msdoshlp.txt >>dlb.lst
@$(LS) bogusmon engrave epitaph tribute >>dlb.lst
$(LS) $(subst /,\,*.lev) >>dlb.lst
@$(subst /,\,$(U)dlb_main cvIf dlb.lst nhdat)
@$(subst /,\,cd $(SRC))
@@ -1013,6 +1054,9 @@ $(O)video.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/portio.h $(MSYS)/video.c
$(O)vidvga.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidvga.c
$(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/vidvga.c
$(O)vidvesa.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidvesa.c
$(CC) $(cflags) -I$(MSYS) -I$(WSHR) -o$@ $(MSYS)/vidvesa.c
$(O)vidtxt.o : $(HACK_H) $(MSYS)/pcvideo.h $(MSYS)/portio.h $(TILE_H) $(MSYS)/vidtxt.c
# $(CC) $(cflags) -o$@ -I$(MSYS) $(MSYS)/vidtxt.c
@@ -1270,6 +1314,10 @@ $(O)worm.o: worm.c $(HACK_H) $(INCL)/lev.h
$(O)worn.o: worn.c $(HACK_H)
$(O)write.o: write.c $(HACK_H)
$(O)zap.o: zap.c $(HACK_H)
$(O)pmatchre.o: $(SSHR)/pmatchre.c $(HACK_H)
$(O)tileset.o: $(WSHR)/tileset.c $(HACK_H)
$(O)bmptiles.o: $(WSHR)/bmptiles.c $(INCL)/config.h $(INCL)/tileset.h $(INCL)/integer.h
$(O)giftiles.o: $(WSHR)/giftiles.c $(INCL)/config.h $(INCL)/tileset.h $(INCL)/integer.h
# end of file

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pckeys.c $NHDT-Date: 1432512792 2015/05/25 00:13:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
/* NetHack 3.6 pckeys.c $NHDT-Date: 1457207039 2016/03/05 19:43:59 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.11 $ */
/* Copyright (c) NetHack PC Development Team 1996 */
/* NetHack may be freely redistributed. See license for details. */
@@ -14,6 +14,10 @@
#include "pcvideo.h"
boolean FDECL(pckeys, (unsigned char, unsigned char));
static void FDECL(userpan, (BOOLEAN_P));
static void FDECL(overview, (BOOLEAN_P));
static void FDECL(traditional, (BOOLEAN_P));
static void NDECL(refresh);
extern struct WinDesc *wins[MAXWIN]; /* from wintty.c */
extern boolean inmap; /* from video.c */
@@ -47,25 +51,25 @@ unsigned char shift;
#endif
case 0x74: /* Control-right_arrow = scroll horizontal to right */
if ((shift & CTRL) && iflags.tile_view && !opening_dialog)
vga_userpan(1);
userpan(1);
break;
case 0x73: /* Control-left_arrow = scroll horizontal to left */
if ((shift & CTRL) && iflags.tile_view && !opening_dialog)
vga_userpan(0);
userpan(0);
break;
case 0x3E: /* F4 = toggle overview mode */
if (iflags.tile_view && !opening_dialog && !Is_rogue_level(&u.uz)) {
iflags.traditional_view = FALSE;
vga_overview(iflags.over_view ? FALSE : TRUE);
vga_refresh();
overview(iflags.over_view ? FALSE : TRUE);
refresh();
}
break;
case 0x3F: /* F5 = toggle traditional mode */
if (iflags.tile_view && !opening_dialog && !Is_rogue_level(&u.uz)) {
iflags.over_view = FALSE;
vga_traditional(iflags.traditional_view ? FALSE : TRUE);
vga_refresh();
traditional(iflags.traditional_view ? FALSE : TRUE);
refresh();
}
break;
default:
@@ -73,6 +77,61 @@ unsigned char shift;
}
return TRUE;
}
static void
userpan(on)
boolean on;
{
#ifdef SCREEN_VGA
if (iflags.usevga)
vga_userpan(on);
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa)
vesa_userpan(on);
#endif
}
static void
overview(on)
boolean on;
{
#ifdef SCREEN_VGA
if (iflags.usevga)
vga_overview(on);
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa)
vesa_overview(on);
#endif
}
static void
traditional(on)
boolean on;
{
#ifdef SCREEN_VGA
if (iflags.usevga)
vga_traditional(on);
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa)
vesa_traditional(on);
#endif
}
static void
refresh()
{
#ifdef SCREEN_VGA
if (iflags.usevga)
vga_refresh();
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa)
vesa_refresh();
#endif
}
#endif /* USE_TILES */
#endif /* MSDOS */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pctiles.h $NHDT-Date: 1432512791 2015/05/25 00:13:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
/* NetHack 3.6 pctiles.h $NHDT-Date: 1457207040 2016/03/05 19:44:00 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.9 $ */
/* Copyright (c) NetHack PC Development Team 1993, 1994 */
/* NetHack may be freely redistributed. See license for details. */
/* */
@@ -11,6 +11,10 @@
*/
#ifdef USE_TILES
#ifndef TILE_X
#define TILE_X 16
#endif
#define NETHACK_PLANAR_TILEFILE "NetHack1.tib" /* Planar style tiles */
#define NETHACK_PACKED_TILEFILE "NetHack2.tib" /* Packed style tiles */
#define NETHACK_OVERVIEW_TILEFILE "NetHacko.tib" /* thin overview tiles */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pcvideo.h $NHDT-Date: 1432512792 2015/05/25 00:13:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
/* NetHack 3.6 pcvideo.h $NHDT-Date: 1457207040 2016/03/05 19:44:00 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.9 $ */
/* Copyright (c) NetHack PC Development Team 1993, 1994 */
/* NetHack may be freely redistributed. See license for details. */
/* */
@@ -166,7 +166,7 @@ struct overview_planar_cell_struct {
#define M_BRIGHTCYAN 11
#define M_TEXT M_GRAY
#define BACKGROUND_COLOR 0
#define BACKGROUND_COLOR 1
#define ATTRIB_NORMAL M_TEXT /* Normal attribute */
#define ATTRIB_INTENSE M_WHITE /* Intense White */
#define ATTRIB_MONO_NORMAL 0x01 /* Underlined,white */
@@ -176,9 +176,9 @@ struct overview_planar_cell_struct {
#endif /*SCREEN_BIOS || SCREEN_DJGPPFAST */
#if defined(SCREEN_VGA) || defined(SCREEN_8514)
#define BACKGROUND_VGA_COLOR 0
#define BACKGROUND_VGA_COLOR 1
#define ATTRIB_VGA_NORMAL CLR_GRAY /* Normal attribute */
#define ATTRIB_VGA_INTENSE 13 /* Intense White 94/06/07 palette chg*/
#define ATTRIB_VGA_INTENSE 14 /* Intense White 94/06/07 palette chg*/
#endif /*SCREEN_VGA || SCREEN_8514*/
#if defined(PC9800)
@@ -258,9 +258,6 @@ E int NDECL(vga_detect);
#ifdef SIMULATE_CURSOR
E void NDECL(vga_DrawCursor);
#endif
E void FDECL(vga_DisplayCell, (struct planar_cell_struct *, int, int));
E void FDECL(vga_DisplayCell_O,
(struct overview_planar_cell_struct *, int, int));
E void NDECL(vga_Finish);
E char __far *NDECL(vga_FontPtrs);
E void NDECL(vga_get_scr_size);
@@ -272,12 +269,8 @@ E void FDECL(vga_update_positionbar, (char *));
E void NDECL(vga_HideCursor);
#endif
E void NDECL(vga_Init);
E void FDECL(vga_SwitchMode, (unsigned int));
E void FDECL(vga_SetPalette, (char *));
E void NDECL(vga_tty_end_screen);
E void FDECL(vga_tty_startup, (int *, int *));
E void FDECL(vga_WriteChar, (int, int, int, int));
E void FDECL(vga_WriteStr, (char *, int, int, int, int));
E void FDECL(vga_xputs, (const char *, int, int));
E void FDECL(vga_xputc, (CHAR_P, int));
E void FDECL(vga_xputg, (int, int, unsigned));
@@ -286,6 +279,35 @@ E void FDECL(vga_overview, (BOOLEAN_P));
E void FDECL(vga_traditional, (BOOLEAN_P));
E void NDECL(vga_refresh);
#endif /* SCREEN_VGA */
#ifdef SCREEN_VESA
E void NDECL(vesa_backsp);
E void FDECL(vesa_clear_screen, (int));
E void FDECL(vesa_cl_end, (int, int));
E void FDECL(vesa_cl_eos, (int));
E int NDECL(vesa_detect);
#ifdef SIMULATE_CURSOR
E void NDECL(vesa_DrawCursor);
#endif
E void NDECL(vesa_Finish);
E void NDECL(vesa_get_scr_size);
E void FDECL(vesa_gotoloc, (int, int));
#ifdef POSITIONBAR
E void FDECL(vesa_update_positionbar, (char *));
#endif
#ifdef SIMULATE_CURSOR
E void NDECL(vesa_HideCursor);
#endif
E void NDECL(vesa_Init);
E void NDECL(vesa_tty_end_screen);
E void FDECL(vesa_tty_startup, (int *, int *));
E void FDECL(vesa_xputs, (const char *, int, int));
E void FDECL(vesa_xputc, (CHAR_P, int));
E void FDECL(vesa_xputg, (int, int, unsigned));
E void FDECL(vesa_userpan, (BOOLEAN_P));
E void FDECL(vesa_overview, (BOOLEAN_P));
E void FDECL(vesa_traditional, (BOOLEAN_P));
E void NDECL(vesa_refresh);
#endif /* SCREEN_VESA */
#endif /* NO_TERMS */
#undef E

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 tile2bin.c $NHDT-Date: 1432512792 2015/05/25 00:13:12 $ $NHDT-Branch: master $:$NHDT-Revision: 1.8 $ */
/* NetHack 3.6 tile2bin.c $NHDT-Date: 1457207041 2016/03/05 19:44:01 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.9 $ */
/* Copyright (c) NetHack PC Development Team 1993, 1994, 1995 */
/* NetHack may be freely redistributed. See license for details. */
@@ -38,6 +38,12 @@
extern unsigned _stklen = STKSIZ;
#endif
/* Produce only a planar file if building the overview file; with packed
files, we can make overview-size tiles on the fly */
#if defined(OVERVIEW_FILE) && defined(PACKED_FILE)
#undef PACKED_FILE
#endif
extern char *FDECL(tilename, (int, int));
#ifdef PLANAR_FILE
@@ -62,7 +68,8 @@ struct tibhdr_struct tibheader;
static void FDECL(write_tibtile, (int));
static void FDECL(write_tibheader, (FILE *, struct tibhdr_struct *));
static void FDECL(build_tibtile, (pixel(*) [TILE_X]));
static void FDECL(build_tibtile, (pixel(*) [TILE_X], BOOLEAN_P));
static void NDECL(remap_colors);
#ifndef OVERVIEW_FILE
char *tilefiles[] = { "../win/share/monsters.txt", "../win/share/objects.txt",
@@ -85,6 +92,7 @@ char *argv[];
struct tm *newtime;
time_t aclock;
char *paletteptr;
unsigned num_monsters = 0;
if (argc != 1) {
Fprintf(stderr, "usage: tile2bin (from the util directory)\n");
@@ -135,6 +143,7 @@ char *argv[];
}
if (!paletteflag) {
remap_colors();
paletteptr = tibheader.palette;
for (i = 0; i < num_colors; i++) {
*paletteptr++ = ColorMap[CM_RED][i],
@@ -145,15 +154,33 @@ char *argv[];
}
while (read_text_tile(pixels)) {
build_tibtile(pixels);
build_tibtile(pixels, FALSE);
write_tibtile(tilecount);
tilecount++;
}
(void) fclose_text_file();
if (filenum == 0) {
num_monsters = tilecount;
}
++filenum;
}
/* Build the statue glyphs */
if (!fopen_text_file(tilefiles[0], RDTMODE)) {
Fprintf(stderr,
"usage: tile2bin (from the util or src directory)\n");
exit(EXIT_FAILURE);
}
while (read_text_tile(pixels)) {
build_tibtile(pixels, TRUE);
write_tibtile(tilecount);
tilecount++;
}
(void) fclose_text_file();
#if defined(_MSC_VER)
tibheader.compiler = MSC_COMP;
#elif defined(__BORLANDC__)
@@ -207,17 +234,24 @@ struct tibhdr_struct *tibhdr;
}
static void
build_tibtile(pixels)
build_tibtile(pixels, statues)
pixel (*pixels)[TILE_X];
boolean statues;
{
static int graymappings[] = {
/* . A B C D E F G H I J K L M N O P */
0, 1, 17, 18, 19, 20, 27, 22, 23, 24, 25, 26, 21, 15, 13, 14, 14
};
int i, j, k, co_off;
unsigned char co_mask, tmp;
#ifdef PLANAR_FILE
#ifndef OVERVIEW_FILE
memset((void *) &planetile, 0, sizeof(struct planar_cell_struct));
#else
memset((void *) &planetile, 0,
sizeof(struct overview_planar_cell_struct));
#endif
#endif
for (j = 0; j < TILE_Y; j++) {
for (i = 0; i < TILE_X; i++) {
@@ -229,6 +263,15 @@ pixel (*pixels)[TILE_X];
}
if (k >= num_colors)
Fprintf(stderr, "color not in colormap!\n");
if (statues) {
k = graymappings[k];
} else {
if (k == 16) {
k = 13;
} else if (k == 13) {
k = 16;
}
}
#ifdef PACKED_FILE
packtile[j][i] = k;
#endif
@@ -242,6 +285,14 @@ pixel (*pixels)[TILE_X];
co_mask = masktable[i];
}
if (!statues) {
if (k == 28) {
k = 0;
}
if (k >= 16) {
fprintf(stderr, "Warning: pixel value %d in 16 color bitmap\n", k);
}
}
tmp = planetile.plane[0].image[j][co_off];
planetile.plane[0].image[j][co_off] =
(k & 0x0008) ? (tmp | co_mask) : (tmp & ~co_mask);
@@ -299,3 +350,19 @@ int recnum;
fwrite(&packtile, sizeof(packtile), 1, tibfile2);
#endif
}
static void
remap_colors()
{
char swap;
swap = ColorMap[CM_RED][13];
ColorMap[CM_RED][13] = ColorMap[CM_RED][16];
ColorMap[CM_RED][16] = swap;
swap = ColorMap[CM_GREEN][13];
ColorMap[CM_GREEN][13] = ColorMap[CM_GREEN][16];
ColorMap[CM_GREEN][16] = swap;
swap = ColorMap[CM_BLUE][13];
ColorMap[CM_BLUE][13] = ColorMap[CM_BLUE][16];
ColorMap[CM_BLUE][16] = swap;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 video.c $NHDT-Date: 1432512791 2015/05/25 00:13:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
/* NetHack 3.6 video.c $NHDT-Date: 1457207042 2016/03/05 19:44:02 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.11 $ */
/* Copyright (c) NetHack PC Development Team 1993, 1994, 2001 */
/* NetHack may be freely redistributed. See license for details. */
/* */
@@ -79,6 +79,11 @@ get_scr_size()
if (iflags.usevga) {
vga_get_scr_size();
} else
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa) {
vesa_get_scr_size();
} else
#endif
txt_get_scr_size();
}
@@ -141,6 +146,10 @@ backsp()
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_backsp();
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_backsp();
#endif
}
}
@@ -153,6 +162,10 @@ clear_screen()
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_clear_screen(BACKGROUND_VGA_COLOR);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_clear_screen(BACKGROUND_VGA_COLOR);
#endif
}
}
@@ -168,6 +181,10 @@ void cl_end() /* clear to end of line */
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_cl_end(col, row);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_cl_end(col, row);
#endif
}
tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
@@ -182,6 +199,10 @@ void cl_eos() /* clear to end of screen */
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_cl_eos(cy);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_cl_eos(cy);
#endif
}
tty_curs(BASE_WINDOW, (int) ttyDisplay->curx + 1, (int) ttyDisplay->cury);
@@ -198,6 +219,10 @@ register int col, row;
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_gotoloc(col, row);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_gotoloc(col, row);
#endif
}
}
@@ -223,6 +248,10 @@ home()
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_gotoloc(0, 0);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_gotoloc(0, 0);
#endif
}
}
@@ -236,6 +265,10 @@ int col, row;
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_gotoloc(col, row);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_gotoloc(col, row);
#endif
}
}
@@ -360,6 +393,10 @@ tty_end_screen()
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_tty_end_screen();
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_tty_end_screen();
#endif
}
}
@@ -395,6 +432,11 @@ int *wid, *hgt;
if (iflags.usevga) {
vga_tty_startup(wid, hgt);
} else
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa) {
vesa_tty_startup(wid, hgt);
} else
#endif
txt_startup(wid, hgt);
@@ -430,39 +472,44 @@ tty_start_screen()
void
gr_init()
{
if (iflags.usevga) {
#ifdef SCREEN_VGA
if (iflags.usevga) {
vga_Init();
} else
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
if (iflags.usevesa) {
vesa_Init();
} else
#endif
#ifdef SCREEN_8514
} else if (iflags.use8514) {
if (iflags.use8514) {
v8514_Init();
} else
#endif
}
{}
}
void
gr_finish()
{
if (iflags.grmode) {
if (iflags.usevga) {
#ifdef SCREEN_VGA
if (iflags.usevga) {
vga_Finish();
} else
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
if (iflags.usevesa) {
vesa_Finish();
} else
#endif
#ifdef SCREEN_8514
} else if (iflags.use8514) {
if (iflags.use8514) {
v8514_Finish();
} else
#endif
}
{}
}
}
@@ -510,6 +557,10 @@ const char *s;
#ifdef SCREEN_VGA
} else if (iflags.usevga) {
vga_xputs(s, col, row);
#endif
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_xputs(s, col, row);
#endif
}
}
@@ -529,6 +580,10 @@ char ch;
} else if (iflags.usevga) {
vga_xputc(ch, attribute);
#endif /*SCREEN_VGA*/
#ifdef SCREEN_VESA
} else if (iflags.usevesa) {
vesa_xputc(ch, attribute);
#endif /*SCREEN_VESA*/
}
}
@@ -541,8 +596,12 @@ unsigned special;
if (!iflags.grmode || !iflags.tile_view) {
xputc((char) ch);
#ifdef SCREEN_VGA
} else {
} else if (iflags.grmode && iflags.usevga) {
vga_xputg(glyphnum, ch, special);
#endif
#ifdef SCREEN_VESA
} else if (iflags.grmode && iflags.usevesa) {
vesa_xputg(glyphnum, ch, special);
#endif
}
}
@@ -555,9 +614,13 @@ char *posbar;
if (!iflags.grmode)
return;
#ifdef SCREEN_VGA
else
else if (iflags.usevga)
vga_update_positionbar(posbar);
#endif
#ifdef SCREEN_VESA
else if (iflags.usevesa)
vesa_update_positionbar(posbar);
#endif
}
#endif
@@ -593,7 +656,12 @@ void
DrawCursor()
{
#ifdef SCREEN_VGA
vga_DrawCursor();
if (iflags.usevga)
vga_DrawCursor();
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa)
vesa_DrawCursor();
#endif
}
@@ -601,7 +669,12 @@ void
HideCursor()
{
#ifdef SCREEN_VGA
vga_HideCursor();
if (iflags.usevga)
vga_HideCursor();
#endif
#ifdef SCREEN_VESA
if (iflags.usevesa)
vesa_HideCursor();
#endif
}
@@ -854,7 +927,9 @@ char *sopt;
* getch();
*/
iflags.grmode = 0;
iflags.hasvesa = 0;
iflags.hasvga = 0;
iflags.usevesa = 0;
iflags.usevga = 0;
if (strncmpi(sopt, "def", 3) == 0) { /* default */
@@ -892,9 +967,10 @@ char *sopt;
#endif
/*
* Auto-detect Priorities (arbitrary for now):
* VGA
* VESA, VGA
*/
if (iflags.hasvga) {
if (iflags.hasvesa) iflags.usevesa = 1;
else if (iflags.hasvga) {
iflags.usevga = 1;
/* VGA depends on BIOS to enable function keys*/
iflags.BIOS = 1;
@@ -911,9 +987,13 @@ tileview(enable)
boolean enable;
{
#ifdef SCREEN_VGA
if (iflags.grmode)
if (iflags.grmode && iflags.usevga)
vga_traditional(enable ? FALSE : TRUE);
#endif
#ifdef SCREEN_VESA
if (iflags.grmode && iflags.usevesa)
vesa_traditional(enable ? FALSE : TRUE);
#endif
}
#endif /* NO_TERMS */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 vidtxt.c $NHDT-Date: 1432512791 2015/05/25 00:13:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.10 $ */
/* NetHack 3.6 vidtxt.c $NHDT-Date: 1457207043 2016/03/05 19:44:03 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.11 $ */
/* Copyright (c) NetHack PC Development Team 1993 */
/* NetHack may be freely redistributed. See license for details. */
/* */
@@ -235,18 +235,19 @@ void txt_cl_eos() /* clear to end of screen */
#else
txt_get_cursor(&col, &row);
txt_cl_end(col, row); /* clear to end of line */
txt_gotoxy(0, (row < (LI - 1) ? row + 1 : (LI - 1)));
regs.h.dl = (char) (CO - 1); /* X of lower right */
regs.h.dh = (char) (LI - 1); /* Y of lower right */
regs.h.cl = 0; /* X of upper left */
/* Y (row) of upper left */
regs.h.ch = (char) (row < (LI - 1) ? row + 1 : (LI - 1));
regs.x.cx = 0;
regs.x.ax = 0;
regs.x.bx = 0;
regs.h.bh = (char) attrib_text_normal;
regs.h.ah = SCROLL;
(void) int86(VIDEO_BIOS, &regs, &regs); /* Scroll or initialize window */
if (row < LI - 1) {
txt_gotoxy(0, (row < (LI - 1) ? row + 1 : (LI - 1)));
regs.h.dl = (char) (CO - 1); /* X of lower right */
regs.h.dh = (char) (LI - 1); /* Y of lower right */
regs.h.cl = 0; /* X of upper left */
/* Y (row) of upper left */
regs.h.ch = (char) (row < (LI - 1) ? row + 1 : (LI - 1));
regs.x.ax = 0;
regs.x.bx = 0;
regs.h.bh = (char) attrib_text_normal;
regs.h.ah = SCROLL;
(void) int86(VIDEO_BIOS, &regs, &regs); /* Scroll or initialize window */
}
#endif
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 vidvga.c $NHDT-Date: 1432512791 2015/05/25 00:13:11 $ $NHDT-Branch: master $:$NHDT-Revision: 1.17 $ */
/* NetHack 3.6 vidvga.c $NHDT-Date: 1457207044 2016/03/05 19:44:04 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.18 $ */
/* Copyright (c) NetHack PC Development Team 1995 */
/* NetHack may be freely redistributed. See license for details. */
/*
@@ -10,7 +10,7 @@
#ifdef SCREEN_VGA /* this file is for SCREEN_VGA only */
#include "pcvideo.h"
#include "tile.h"
#include "pctiles.h"
#include "tileset.h"
#include <dos.h>
#include <ctype.h>
@@ -102,6 +102,8 @@
#include <conio.h>
#endif
extern short glyph2tile[];
/* STATIC_DCL void FDECL(vga_NoBorder, (int)); */
void FDECL(vga_gotoloc, (int, int)); /* This should be made a macro */
void NDECL(vga_backsp);
@@ -109,7 +111,7 @@ void NDECL(vga_backsp);
STATIC_DCL void FDECL(vga_scrollmap, (BOOLEAN_P));
#endif
STATIC_DCL void FDECL(vga_redrawmap, (BOOLEAN_P));
void FDECL(vga_cliparound, (int, int));
static void FDECL(vga_cliparound, (int, int));
STATIC_OVL void FDECL(decal_planar, (struct planar_cell_struct *, unsigned));
#ifdef POSITIONBAR
@@ -117,6 +119,19 @@ STATIC_DCL void NDECL(positionbar);
static void FDECL(vga_special, (int, int, int));
#endif
static void FDECL(vga_DisplayCell, (struct planar_cell_struct *, int, int));
static void FDECL(vga_DisplayCell_O,
(struct overview_planar_cell_struct *, int, int));
static void FDECL(vga_SwitchMode, (unsigned int));
static void FDECL(vga_SetPalette, (const struct Pixel *));
static void FDECL(vga_WriteChar, (int, int, int, int));
static void FDECL(vga_WriteStr, (char *, int, int, int, int));
static void FDECL(read_planar_tile, (unsigned, struct planar_cell_struct *));
static void FDECL(read_planar_tile_O,
(unsigned, struct overview_planar_cell_struct *));
static void FDECL(read_tile_indexes, (unsigned, unsigned char (*)[TILE_X]));
extern int clipx, clipxmax; /* current clipping column from wintty.c */
extern boolean clipping; /* clipping on? from wintty.c */
extern int savevmode; /* store the original video mode */
@@ -135,7 +150,7 @@ extern boolean inmap; /* in the map window */
STATIC_VAR unsigned char __far *font;
STATIC_VAR char *screentable[SCREENHEIGHT];
STATIC_VAR char *paletteptr;
STATIC_VAR const struct Pixel *paletteptr;
STATIC_VAR struct map_struct {
int glyph;
int ch;
@@ -156,8 +171,8 @@ STATIC_VAR struct map_struct {
}
#define TOP_MAP_ROW 1
STATIC_VAR int vgacmap[CLR_MAX] = { 0, 3, 5, 9, 4, 8, 12, 14,
11, 2, 6, 7, 1, 8, 12, 13 };
STATIC_VAR int vgacmap[CLR_MAX] = { 1, 4, 6, 10, 5, 9, 0, 15,
12, 3, 7, 8, 2, 9, 0, 14 };
STATIC_VAR int viewport_size = 40;
/* STATIC_VAR char masktable[8]={0x80,0x40,0x20,0x10,0x08,0x04,0x02,0x01}; */
/* STATIC_VAR char bittable[8]= {0x01,0x02,0x04,0x08,0x10,0x20,0x40,0x80}; */
@@ -187,13 +202,8 @@ int vp[SCREENPLANES] = { 8, 4, 2, 1 };
#endif
int vp2[SCREENPLANES] = { 1, 2, 4, 8 };
STATIC_VAR struct planar_cell_struct *planecell;
STATIC_VAR struct overview_planar_cell_struct *planecell_O;
#if defined(USE_TILES)
STATIC_VAR struct tibhdr_struct tibheader;
/* extern FILE *tilefile; */ /* Not needed in here most likely */
#endif
STATIC_VAR struct planar_cell_struct planecell;
STATIC_VAR struct overview_planar_cell_struct planecell_O;
/* STATIC_VAR int g_attribute; */ /* Current attribute to use */
@@ -365,6 +375,11 @@ unsigned special; /* special feature: corpse, invis, detected, pet, ridden -
int attr;
int ry;
/* If statue glyph, map to the generic statue */
if (GLYPH_STATUE_OFF <= glyphnum && glyphnum < GLYPH_STATUE_OFF + NUMMONS) {
glyphnum = objnum_to_glyph(STATUE);
}
row = currow;
col = curcol;
if ((col < 0 || col >= COLNO)
@@ -380,20 +395,14 @@ unsigned special; /* special feature: corpse, invis, detected, pet, ridden -
vga_WriteChar((unsigned char) ch, col, row, attr);
} else if (!iflags.over_view) {
if ((col >= clipx) && (col <= clipxmax)) {
if (!ReadPlanarTileFile(glyph2tile[glyphnum], &planecell)) {
if (map[ry][col].special)
decal_planar(planecell, special);
vga_DisplayCell(planecell, col - clipx, row);
} else
pline("vga_xputg: Error reading tile (%d,%d) from file",
glyphnum, glyph2tile[glyphnum]);
read_planar_tile(glyphnum, &planecell);
if (map[ry][col].special)
decal_planar(&planecell, special);
vga_DisplayCell(&planecell, col - clipx, row);
}
} else {
if (!ReadPlanarTileFile_O(glyph2tile[glyphnum], &planecell_O))
vga_DisplayCell_O(planecell_O, col, row);
else
pline("vga_xputg: Error reading tile (%d,%d) from file", glyphnum,
glyph2tile[glyphnum]);
read_planar_tile_O(glyphnum, &planecell_O);
vga_DisplayCell_O(&planecell_O, col, row);
}
if (col < (CO - 1))
++col;
@@ -422,7 +431,7 @@ int col, row;
}
#if defined(USE_TILES) && defined(CLIPPING)
void
static void
vga_cliparound(x, y)
int x, y;
{
@@ -489,22 +498,13 @@ boolean clearfirst;
t = map[y][x].glyph;
if (!(clearfirst && t == cmap_to_glyph(S_stone))) {
if (!iflags.over_view) {
if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) {
if (map[y][x].special)
decal_planar(planecell, map[y][x].special);
vga_DisplayCell(planecell, x - clipx,
y + TOP_MAP_ROW);
} else
pline("vga_redrawmap: Error reading tile (%d,%d)",
t, glyph2tile[t]);
read_planar_tile(t, &planecell);
if (map[y][x].special)
decal_planar(&planecell, map[y][x].special);
vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW);
} else {
if (!ReadPlanarTileFile_O(glyph2tile[t],
&planecell_O)) {
vga_DisplayCell_O(planecell_O, x,
y + TOP_MAP_ROW);
} else
pline("vga_redrawmap: Error reading tile (%d,%d)",
t, glyph2tile[t]);
read_planar_tile_O(t, &planecell_O);
vga_DisplayCell_O(&planecell_O, x, y + TOP_MAP_ROW);
}
}
}
@@ -632,19 +632,98 @@ boolean left;
for (y = 0; y < ROWNO; ++y) {
for (x = i; x < j; x += 2) {
t = map[y][x].glyph;
if (!ReadPlanarTileFile(glyph2tile[t], &planecell)) {
if (map[y][x].special)
decal_planar(planecell, map[y][x].special);
vga_DisplayCell(planecell, x - clipx, y + TOP_MAP_ROW);
} else {
pline("vga_shiftmap: Error reading tile (%d,%d)", t,
glyph2tile[t]);
}
read_planar_tile(t, &planecell);
if (map[y][x].special)
decal_planar(&planecell, map[y][x].special);
vga_DisplayCell(&planecell, x - clipx, y + TOP_MAP_ROW);
}
}
}
#endif /* SCROLLMAP */
static void
read_planar_tile(glyph, cell)
unsigned glyph;
struct planar_cell_struct *cell;
{
unsigned char indexes[TILE_Y][TILE_X];
unsigned plane, y, byte, bit;
read_tile_indexes(glyph, indexes);
/* cell->plane[0..3].image[0..15][0..1] */
for (plane = 0; plane < SCREENPLANES; ++plane) {
for (y = 0; y < TILE_Y; ++y) {
for (byte = 0; byte < MAX_BYTES_PER_CELL; ++byte) {
unsigned char b = 0;
for (bit = 0; bit < 8; ++bit) {
unsigned char x = byte * 8 + bit;
unsigned char i = indexes[y][x];
b <<= 1;
if (i & (0x8 >> plane)) b |= 1;
}
cell->plane[plane].image[y][byte] = b;
}
}
}
}
static void
read_planar_tile_O(glyph, cell)
unsigned glyph;
struct overview_planar_cell_struct *cell;
{
unsigned char indexes[TILE_Y][TILE_X];
unsigned plane, y, bit;
read_tile_indexes(glyph, indexes);
/* cell->plane[0..3].image[0..15][0..0] */
for (plane = 0; plane < SCREENPLANES; ++plane) {
for (y = 0; y < TILE_Y; ++y) {
unsigned char b = 0;
for (bit = 0; bit < 8; ++bit) {
unsigned char x = bit * 2;
unsigned char i = indexes[y][x];
b <<= 1;
if (i & (0x8 >> plane)) b |= 1;
}
cell->plane[plane].image[y][0] = b;
}
}
}
static void
read_tile_indexes(glyph, indexes)
unsigned glyph;
unsigned char (*indexes)[TILE_X];
{
const struct TileImage *tile;
unsigned x, y;
/* We don't have enough colors to show the statues */
if (glyph >= GLYPH_STATUE_OFF) {
glyph = GLYPH_OBJ_OFF + STATUE;
}
/* Get the tile from the image */
tile = get_tile(glyph2tile[glyph]);
/* Map to a 16 bit palette; assume colors laid out as in default tileset */
memset(indexes, 0, sizeof(indexes));
for (y = 0; y < TILE_Y && y < tile->height; ++y) {
for (x = 0; x < TILE_X && x < tile->width; ++x) {
unsigned i = tile->indexes[y * tile->width + x];
if (i == 28) {
i = 0;
} else if (i == 16) {
i = 13;
} else if (i > 15) {
i = 15;
}
indexes[y][x] = i;
}
}
}
STATIC_OVL void
decal_planar(gp, special)
struct planar_cell_struct *gp;
@@ -671,17 +750,20 @@ vga_Init(void)
int i;
#ifdef USE_TILES
const char *tile_file;
int tilefailure = 0;
/*
* Attempt to open the required tile files. If we can't
* don't perform the video mode switch, use TTY code instead.
*
*/
if (OpenTileFile(NETHACK_PLANAR_TILEFILE, FALSE))
tile_file = iflags.wc_tile_file;
if (tile_file == NULL || tile_file == '\0') {
tile_file = "nhtiles.bmp";
}
if (!read_tiles(tile_file, FALSE))
tilefailure |= 1;
if (OpenTileFile(NETHACK_OVERVIEW_TILEFILE, TRUE))
tilefailure |= 2;
if (ReadTileFileHeader(&tibheader, FALSE))
if (get_palette() == NULL)
tilefailure |= 4;
if (tilefailure) {
@@ -708,7 +790,7 @@ vga_Init(void)
/* vga_NoBorder(BACKGROUND_VGA_COLOR); */ /* Not needed after palette
mod */
#ifdef USE_TILES
paletteptr = tibheader.palette;
paletteptr = get_palette();
iflags.tile_view = TRUE;
iflags.over_view = FALSE;
#else
@@ -730,7 +812,7 @@ vga_Init(void)
* mode (video mode 0x12). No other modes are currently supported.
*
*/
void
static void
vga_SwitchMode(unsigned int mode)
{
union REGS regs;
@@ -760,8 +842,7 @@ vga_SwitchMode(unsigned int mode)
void
vga_Finish(void)
{
CloseTileFile(0);
CloseTileFile(1);
free_tiles();
vga_SwitchMode(MODETEXT);
windowprocs.win_cliparound = tty_cliparound;
g_attribute = attrib_text_normal;
@@ -853,7 +934,7 @@ vga_detect()
* do it using the colour 'colour'.
*
*/
void
static void
vga_WriteChar(chr, col, row, colour)
int chr, col, row, colour;
{
@@ -901,7 +982,7 @@ int chr, col, row, colour;
* not the x,y pixel location.
*
*/
void
static void
vga_DisplayCell(gp, col, row)
struct planar_cell_struct *gp;
int col, row;
@@ -932,7 +1013,7 @@ int col, row;
egawriteplane(15);
}
void
static void
vga_DisplayCell_O(gp, col, row)
struct overview_planar_cell_struct *gp;
int col, row;
@@ -965,7 +1046,7 @@ int col, row;
* is 'len' at location (x,y) using the 'colour' colour.
*
*/
void
static void
vga_WriteStr(s, len, col, row, colour)
char *s;
int len, col, row, colour;
@@ -993,19 +1074,20 @@ int len, col, row, colour;
* 16 colour mode at 640 x 480.
*
*/
void
static void
vga_SetPalette(p)
char *p;
const struct Pixel *p;
{
union REGS regs;
int i;
outportb(0x3c6, 0xff);
for (i = 0; i < COLORDEPTH; ++i) {
struct Pixel color = (i == 13) ? p[16] : p[i];
outportb(0x3c8, i);
outportb(0x3c9, (*p++) >> 2);
outportb(0x3c9, (*p++) >> 2);
outportb(0x3c9, (*p++) >> 2);
outportb(0x3c9, color.r >> 2);
outportb(0x3c9, color.g >> 2);
outportb(0x3c9, color.b >> 2);
}
regs.x.bx = 0x0000;
for (i = 0; i < COLORDEPTH; ++i) {
@@ -1021,10 +1103,10 @@ static unsigned char colorbits[] = { 0x08, 0x04, 0x02, 0x01 };
#ifdef POSITIONBAR
#define PBAR_ROW (LI - 4)
#define PBAR_COLOR_ON 15 /* slate grey background colour of tiles */
#define PBAR_COLOR_OFF 12 /* bluish grey, used in old style only */
#define PBAR_COLOR_STAIRS 9 /* brown */
#define PBAR_COLOR_HERO 14 /* creamy white */
#define PBAR_COLOR_ON 13 /* slate grey background colour of tiles */
#define PBAR_COLOR_OFF 0 /* bluish grey, used in old style only */
#define PBAR_COLOR_STAIRS 10 /* brown */
#define PBAR_COLOR_HERO 15 /* creamy white */
static unsigned char pbar[COLNO];
@@ -1152,7 +1234,7 @@ int chr, col, color;
pixy = PBAR_ROW * MAX_ROWS_PER_CELL;
for (vplane = 0; vplane < SCREENPLANES; ++vplane) {
egareadplane(vplane);
egareadplane(SCREENPLANES - 1 - vplane);
y = pixy;
for (i = 0; i < ROWS_PER_CELL; ++i) {
tmp_d = screentable[y++] + col;

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 pcmain.c $NHDT-Date: 1451697809 2016/01/02 01:23:29 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.68 $ */
/* NetHack 3.6 pcmain.c $NHDT-Date: 1457207045 2016/03/05 19:44:05 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.69 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -115,9 +115,11 @@ char *argv[];
{
register int fd;
register char *dir;
#if defined(WIN32)
#if defined(WIN32) || defined(MSDOS)
char *envp = NULL;
char *sptr = NULL;
#endif
#if defined(WIN32)
char fnamebuf[BUFSZ], encodedfnamebuf[BUFSZ];
boolean save_getreturn_status = getreturn_enabled;
#endif

View File

@@ -1,5 +1,5 @@
#!/bin/sh
# NetHack 3.6 macosx.sh $NHDT-Date: 1455747518 2016/02/17 22:18:38 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.15 $
# NetHack 3.6 macosx.sh $NHDT-Date: 1455930387 2016/02/20 01:06:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.16 $
# Copyright (c) Kenneth Lorber, Kensington, Maryland, 2007.
# NetHack may be freely redistributed. See license for details.
#

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 nhraykey.c $NHDT-Date: 1432512794 2015/05/25 00:13:14 $ $NHDT-Branch: master $:$NHDT-Revision: 1.15 $ */
/* NetHack 3.6 nhraykey.c $NHDT-Date: 1457207047 2016/03/05 19:44:07 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.16 $ */
/* Copyright (c) NetHack PC Development Team 2003 */
/* NetHack may be freely redistributed. See license for details. */
@@ -559,19 +559,24 @@ INPUT_RECORD *ir;
scan = ir->Event.KeyEvent.wVirtualScanCode;
shiftstate = ir->Event.KeyEvent.dwControlKeyState;
vk = ir->Event.KeyEvent.wVirtualKeyCode;
keycode = MapVirtualKey(vk, 2);
if (is_altseq(shiftstate)) {
if (ch || inmap(keycode, vk))
altseq = 1;
else
altseq = -1; /* invalid altseq */
}
if (ch || iskeypad(scan) || altseq) {
done = 1; /* Stop looking */
retval = 1; /* Found what we sought */
if (scan == 0 && vk == 0) {
/* It's the bogus_key. Discard it */
ReadConsoleInput(hConIn,ir,1,&count);
} else {
/* Strange Key event; let's purge it to avoid trouble */
ReadConsoleInput(hConIn, ir, 1, &count);
keycode = MapVirtualKey(vk, 2);
if (is_altseq(shiftstate)) {
if (ch || inmap(keycode, vk))
altseq = 1;
else
altseq = -1; /* invalid altseq */
}
if (ch || iskeypad(scan) || altseq) {
done = 1; /* Stop looking */
retval = 1; /* Found what we sought */
} else {
/* Strange Key event; let's purge it to avoid trouble */
ReadConsoleInput(hConIn, ir, 1, &count);
}
}
} else if ((ir->EventType == MOUSE_EVENT

View File

@@ -1,4 +1,4 @@
! $NHDT-Date: 1454977917 2016/02/09 00:31:57 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.10 $
! $NHDT-Date: 1457079198 2016/03/04 08:13:18 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.11 $
! The display_file, tombstone, and menu windows are all formatted assuming
! a fixed width font. Text windows may or may not be formatted as above.
@@ -188,6 +188,15 @@ NetHack*extended_commands*help.accelerators: #override\n\
:<Key>?: set() notify() unset()
NetHack*extended_commands*dismiss.accelerators: #override\n\
<Key>Escape: set() notify() unset()
!
! The extended command menu may be too big to fit on the screen so need
! a vertical scroll bar. When truncated, its height will be as tall as
! possible unless height_delta is non-zero, in which case there will be
! that many pixels of margin left unused. On OSX, this can be used to
! avoid overlapping with the desktop docking tray to prevent that from
! obscuring the bottom of the menu.
NetHack*extcmd_height_delta: 75
!
!
! The following are the default 15 colors that the nethack map uses.

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winX.c $NHDT-Date: 1455389907 2016/02/13 18:58:27 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.40 $ */
/* NetHack 3.6 winX.c $NHDT-Date: 1457079197 2016/03/04 08:13:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.41 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -1064,6 +1064,9 @@ static XtResource resources[] = {
XtOffset(AppResources *, icon), XtRString, nhStr("nh72") },
{ nhStr("message_lines"), nhStr("Message_lines"), XtRInt, sizeof(int),
XtOffset(AppResources *, message_lines), XtRString, nhStr("12") },
{ nhStr("extcmd_height_delta"), nhStr("Extcmd_height_delta"),
XtRInt, sizeof (int),
XtOffset(AppResources *, extcmd_height_delta), XtRString, nhStr("0") },
{ nhStr("pet_mark_bitmap"), nhStr("Pet_mark_bitmap"), XtRString,
sizeof(String), XtOffset(AppResources *, pet_mark_bitmap), XtRString,
nhStr("pet_mark.xbm") },

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 winmisc.c $NHDT-Date: 1455526714 2016/02/15 08:58:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
/* NetHack 3.6 winmisc.c $NHDT-Date: 1457079197 2016/03/04 08:13:17 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.25 $ */
/* Copyright (c) Dean Luick, 1992 */
/* NetHack may be freely redistributed. See license for details. */
@@ -1199,36 +1199,20 @@ Widget *formp; /* return */
else
free((char *) commands);
/*
* We actually want height of topmost background window, which
* may or may not be the root window.
*
* On OSX, screen height includes the space taken up by the
* desktop title bar, which isn't accessible to applications
* unless the preference settings for X11 are changed to force
* full-screen mode (so by default, this 'screen_height' value
* ends up being bigger than the available size...).
*/
screen_height = XHeightOfScreen(XtScreen(popup));
/*
* If the menu's complete height is too big for the display,
* forcing the height to be smaller will cause the vertical
* scroll bar (enabled but not forced above) to be included.
*/
screen_height = XHeightOfScreen(XtScreen(popup));
screen_height -= appResources.extcmd_height_delta; /* NetHack.ad */
if (cumulative_height >= screen_height) {
/* trial and error:
25 is a guesstimate for scrollbar width on width adjustment;
75 is for cumulative height of 3 title bars (desktop,
application, and popup) on height adjustment; that will be
bigger than needed if the popup can overlap the application's
title bar or if there is no desktop title bar; this ought to
be deriveable on the fly, or at least user-controlled by a
resource, but for now it's hardcoded--user can manually
resize if sufficiently motivated... */
/* 25 is a guesstimate for scrollbar width;
window manager might override the request for y==1 */
num_args = 0;
XtSetArg(args[num_args], XtNy, 1); num_args++;
XtSetArg(args[num_args], XtNwidth, max_width + 25); num_args++;
XtSetArg(args[num_args], XtNheight, screen_height - 75); num_args++;
XtSetArg(args[num_args], XtNheight, screen_height - 1); num_args++;
XtSetValues(popup, args, num_args);
}
XtRealizeWidget(popup);

622
win/share/bmptiles.c Normal file
View File

@@ -0,0 +1,622 @@
/* NetHack 3.6 bmptiles.c $NHDT-Date: 1457207054 2016/03/05 19:44:14 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */
/* Copyright (c) Ray Chason, 2016. */
/* NetHack may be freely redistributed. See license for details. */
#include "config.h"
#include "integer.h"
#include "tileset.h"
/* First BMP file header */
struct BitmapHeader {
char magic[2];
uint32 bmp_size;
uint32 img_offset;
};
/* Color model information for larger BMP headers */
struct CIE_XYZ {
uint32 ciexyzX;
uint32 ciexyzY;
uint32 ciexyzZ;
};
struct CIE_XYZTriple {
struct CIE_XYZ ciexyzRed;
struct CIE_XYZ ciexyzGreen;
struct CIE_XYZ ciexyzBlue;
};
/* Second BMP file header */
/* This one can vary in size; contents can vary according to the size */
struct BitmapInfoHeader {
uint32 Size; /* 12 40 52 56 108 124 64 */
int32 Width; /* 12 40 52 56 108 124 64 */
int32 Height; /* 12 40 52 56 108 124 64 */
uint16 NumPlanes; /* 12 40 52 56 108 124 64 */
uint16 BitsPerPixel; /* 12 40 52 56 108 124 64 */
uint32 Compression; /* 40 52 56 108 124 64 */
uint32 ImageDataSize; /* 40 52 56 108 124 64 */
int32 XResolution; /* 40 52 56 108 124 64 */
int32 YResolution; /* 40 52 56 108 124 64 */
uint32 ColorsUsed; /* 40 52 56 108 124 64 */
uint32 ColorsImportant; /* 40 52 56 108 124 64 */
uint32 RedMask; /* 52 56 108 124 */
uint32 GreenMask; /* 52 56 108 124 */
uint32 BlueMask; /* 52 56 108 124 */
uint32 AlphaMask; /* 56 108 124 */
uint32 CSType; /* 108 124 */
struct CIE_XYZTriple Endpoints; /* 108 124 */
uint32 GammaRed; /* 108 124 */
uint32 GammaGreen; /* 108 124 */
uint32 GammaBlue; /* 108 124 */
uint32 Intent; /* 124 */
uint32 ProfileData; /* 124 */
uint32 ProfileSize; /* 124 */
};
/* Compression */
#define BI_RGB 0
#define BI_RLE8 1
#define BI_RLE4 2
#define BI_BITFIELDS 3
#define BI_JPEG 4
#define BI_PNG 5
static uint16 FDECL(read_u16, (const unsigned char buf[2]));
static uint32 FDECL(read_u32, (const unsigned char buf[4]));
static int32 FDECL(read_s32, (const unsigned char buf[4]));
static struct Pixel FDECL(build_pixel, (const struct BitmapInfoHeader *, uint32));
static unsigned char FDECL(pixel_element, (uint32, uint32));
static boolean FDECL(read_header, (FILE *, struct BitmapHeader *));
static boolean FDECL(read_info_header, (FILE *, struct BitmapInfoHeader *));
static boolean FDECL(check_info_header, (const struct BitmapInfoHeader *));
static unsigned FDECL(get_palette_size, (const struct BitmapInfoHeader *));
static boolean FDECL(read_palette, (FILE *, struct Pixel *, unsigned));
/* Read a .BMP file into the image structure */
/* Return TRUE if successful, FALSE on any error */
boolean
read_bmp_tiles(filename, image)
const char *filename;
struct TileSetImage *image;
{
struct BitmapHeader header1;
struct BitmapInfoHeader header2;
unsigned palette_size;
size_t num_pixels, size;
unsigned x, y, y_start, y_end, y_inc;
unsigned bytes_per_row;
FILE *fp = NULL; /* custodial */
unsigned char *row_bytes = NULL; /* custodial */
image->width = 0;
image->height = 0;
image->pixels = NULL; /* custodial, returned */
image->indexes = NULL; /* custodial, returned */
image->image_desc = NULL; /* custodial, returned */
image->tile_width = 0;
image->tile_height = 0;
fp = fopen(filename, "rb");
if (fp == NULL) goto error;
/* Read the headers */
if (!read_header(fp, &header1)) goto error;
if (memcmp(header1.magic, "BM", 2) != 0) goto error;
if (!read_info_header(fp, &header2)) goto error;
if (!check_info_header(&header2)) goto error;
#if 0 /* TODO */
if (header2.Compression == BI_PNG) {
/* Image data is an embedded PNG bit stream */
boolean ok = do_read_png_tiles(fp, image));
fclose(fp);
return ok;
}
#endif
/* header2.Height < 0 means the Y coordinate is reversed; the origin is
* top left rather than bottom left */
image->width = header2.Width;
image->height = labs(header2.Height);
/* Allocate pixel area; watch out for overflow */
num_pixels = (size_t) image->width * (size_t) image->height;
if (num_pixels / image->width != image->height) goto error; /* overflow */
size = num_pixels * sizeof(image->pixels[0]);
if (size / sizeof(image->pixels[0]) != num_pixels) goto error; /* overflow */
image->pixels = (struct Pixel *) alloc(size);
if (header2.BitsPerPixel <= 8) {
image->indexes = (unsigned char *) alloc(num_pixels);
}
/* Read the palette */
palette_size = get_palette_size(&header2);
if (!read_palette(fp, image->palette, palette_size)) goto error;
/* Read the pixels */
fseek(fp, header1.img_offset, SEEK_SET);
if (header2.Height < 0) {
y_start = 0;
y_end = image->height;
y_inc = 1;
} else {
y_start = image->height - 1;
y_end = (unsigned) -1;
y_inc = -1;
}
if (header2.Compression == BI_RLE4 || header2.Compression == BI_RLE8) {
unsigned char *p;
p = image->indexes;
memset(p, 0, num_pixels);
x = 0;
y = image->height - 1;
while (TRUE) {
int b1, b2;
b1 = fgetc(fp);
if (b1 == EOF) goto error;
b2 = fgetc(fp);
if (b2 == EOF) goto error;
/*
* b1 b2
* 0 0 end of line
* 0 1 end of bitmap
* 0 2 next two bytes are x and y offset
* 0 >2 b2 is a count of bytes
* >0 any repeat b2, b1 times
*/
if (b1 == 0) {
if (b2 == 0) {
/* end of line */
--y;
x = 0;
} else if (b2 == 1) {
/* end of bitmap */
break;
} else if (b2 == 2) {
/* next two bytes are x and y offset */
b1 = fgetc(fp);
if (b1 == EOF) break;
b2 = fgetc(fp);
if (b2 == EOF) break;
x += b1;
y += b2;
} else {
/* get bytes */
int i;
if (y < image->height) {
p = image->indexes + y * image->width;
for (i = 0; i < b2; ++i) {
b1 = fgetc(fp);
if (b1 == EOF) break;
if (header2.BitsPerPixel == 8) {
if (x < image->width) {
p[x] = b1;
}
++x;
} else {
if (x < image->width) {
p[x] = b1 >> 4;
}
++x;
if (x < image->width) {
p[x] = b1 & 0xF;
}
++x;
}
}
if (b2 & 1) {
b1 = fgetc(fp);
if (b1 == EOF) break;
}
}
}
} else {
/* repeat b2, b1 times */
int i;
if (y < image->height) {
p = image->indexes + y * image->width;
for (i = 0; i < b1; ++i) {
if (header2.BitsPerPixel == 8) {
if (x < image->width) {
p[x] = b2;
}
++x;
} else {
if (x < image->width) {
p[x] = b2 >> 4;
}
++x;
if (x < image->width) {
p[x] = b2 & 0xF;
}
++x;
}
}
}
}
}
} else {
bytes_per_row = (image->width * header2.BitsPerPixel + 31) / 32 * 4;
row_bytes = (unsigned char *) alloc(bytes_per_row);
if (header2.Compression == BI_RGB) {
switch (header2.BitsPerPixel) {
case 16:
header2.RedMask = 0x001F;
header2.GreenMask = 0x07E0;
header2.BlueMask = 0xF800;
header2.AlphaMask = 0x0000;
break;
case 32:
header2.RedMask = 0x000000FF;
header2.GreenMask = 0x0000FF00;
header2.BlueMask = 0x00FF0000;
header2.AlphaMask = 0xFF000000;
break;
}
}
for (y = y_start; y != y_end; y += y_inc) {
struct Pixel *row = image->pixels + y * image->width;
unsigned char *ind = image->indexes + y * image->width;
size = fread(row_bytes, 1, bytes_per_row, fp);
if (size < bytes_per_row) goto error;
switch (header2.BitsPerPixel) {
case 1:
for (x = 0; x < image->width; ++x) {
unsigned byte = x / 8;
unsigned shift = x % 8;
unsigned color = (row_bytes[byte] >> shift) & 1;
ind[x] = color;
}
break;
case 4:
for (x = 0; x < image->width; ++x) {
unsigned byte = x / 2;
unsigned shift = (x % 2) * 4;
unsigned color = (row_bytes[byte] >> shift) & 1;
ind[x] = color;
}
break;
case 8:
for (x = 0; x < image->width; ++x) {
ind[x] = row_bytes[x];
}
break;
case 16:
for (x = 0; x < image->width; ++x) {
uint16 color = read_u16(row_bytes + x * 2);
row[x] = build_pixel(&header2, color);
}
break;
case 24:
for (x = 0; x < image->width; ++x) {
row[x].r = row_bytes[x * 3 + 2];
row[x].g = row_bytes[x * 3 + 1];
row[x].b = row_bytes[x * 3 + 0];
row[x].a = 255;
}
break;
case 32:
for (x = 0; x < image->width; ++x) {
uint32 color = read_u32(row_bytes + x * 2);
row[x] = build_pixel(&header2, color);
}
break;
}
}
free(row_bytes);
row_bytes = NULL;
}
if (image->indexes != NULL) {
size_t i;
for (i = 0; i < num_pixels; ++i) {
image->pixels[i] = image->palette[image->indexes[i]];
}
}
fclose(fp);
return TRUE;
error:
if (fp) fclose(fp);
free(row_bytes);
free(image->pixels);
image->pixels = NULL;
free(image->indexes);
image->indexes = NULL;
free(image->image_desc);
image->image_desc = NULL;
return FALSE;
}
/* Read and decode the first header */
static boolean
read_header(fp, header)
FILE *fp;
struct BitmapHeader *header;
{
unsigned char buf[14];
size_t size;
size = fread(buf, 1, sizeof(buf), fp);
if (size < sizeof(buf)) return FALSE;
memcpy(header->magic, buf + 0, 2);
header->bmp_size = read_u32(buf + 2);
/* 6 and 8 are 16 bit integers giving the hotspot of a cursor */
header->img_offset = read_u32(buf + 10);
return TRUE;
}
/* Read and decode the second header */
static boolean
read_info_header(fp, header)
FILE *fp;
struct BitmapInfoHeader *header;
{
unsigned char buf[124]; /* maximum size */
size_t size;
boolean have_color_mask;
memset(header, 0, sizeof(*header));
/* Get the header size */
size = fread(buf, 1, 4, fp);
if (size < 4) return FALSE;
header->Size = read_u32(buf + 0);
if (header->Size > sizeof(buf)) return FALSE;
/* Get the rest of the header */
size = fread(buf + 4, 1, header->Size - 4, fp);
if (size < header->Size - 4) return FALSE;
have_color_mask = FALSE;
switch (header->Size) {
case 124: /* BITMAPV5INFOHEADER */
/* 120 is reserved */
header->ProfileSize = read_u32(buf + 116);
header->ProfileData = read_u32(buf + 112);
header->Intent = read_u32(buf + 108);
/* fall through */
case 108: /* BITMAPV4INFOHEADER */
header->GammaBlue = read_u32(buf + 104);
header->GammaGreen = read_u32(buf + 100);
header->GammaRed = read_u32(buf + 96);
header->Endpoints.ciexyzBlue.ciexyzZ = read_u32(buf + 92);
header->Endpoints.ciexyzBlue.ciexyzY = read_u32(buf + 88);
header->Endpoints.ciexyzBlue.ciexyzX = read_u32(buf + 84);
header->Endpoints.ciexyzGreen.ciexyzZ = read_u32(buf + 80);
header->Endpoints.ciexyzGreen.ciexyzY = read_u32(buf + 76);
header->Endpoints.ciexyzGreen.ciexyzX = read_u32(buf + 72);
header->Endpoints.ciexyzRed.ciexyzZ = read_u32(buf + 68);
header->Endpoints.ciexyzRed.ciexyzY = read_u32(buf + 64);
header->Endpoints.ciexyzRed.ciexyzX = read_u32(buf + 60);
header->CSType = read_u32(buf + 56);
/* fall through */
case 56: /* BITMAPV3INFOHEADER */
header->AlphaMask = read_u32(buf + 52);
/* fall through */
case 52: /* BITMAPV2INFOHEADER */
header->BlueMask = read_u32(buf + 48);
header->GreenMask = read_u32(buf + 44);
header->RedMask = read_u32(buf + 40);
have_color_mask = TRUE;
/* fall through */
case 40: /* BITMAPINFOHEADER */
case 64: /* OS22XBITMAPHEADER */
/* The last 24 bytes in OS22XBITMAPHEADER are incompatible with the
* later Microsoft versions of the header */
header->ColorsImportant = read_u32(buf + 36);
header->ColorsUsed = read_u32(buf + 32);
header->YResolution = read_s32(buf + 28);
header->XResolution = read_s32(buf + 24);
header->ImageDataSize = read_u32(buf + 20);
header->Compression = read_u32(buf + 16);
header->BitsPerPixel = read_u16(buf + 14);
header->NumPlanes = read_u16(buf + 12);
header->Height = read_s32(buf + 8);
header->Width = read_s32(buf + 4);
break;
case 12: /* BITMAPCOREHEADER */
header->BitsPerPixel = read_u16(buf + 10);
header->NumPlanes = read_u16(buf + 8);
header->Height = read_u16(buf + 6);
header->Width = read_u16(buf + 4);
break;
default:
return FALSE;
}
/* For BI_BITFIELDS, the next three 32 bit words are the color masks */
if (header->Compression == BI_BITFIELDS && !have_color_mask) {
size = fread(buf, 1, 12, fp);
if (size < 12) return FALSE;
header->RedMask = read_u32(buf + 0);
header->GreenMask = read_u32(buf + 4);
header->BlueMask = read_u32(buf + 8);
}
return TRUE;
}
/* Check the second header for consistency and unsupported features */
static boolean
check_info_header(header)
const struct BitmapInfoHeader *header;
{
if (header->NumPlanes != 1) return FALSE;
switch (header->BitsPerPixel) {
#if 0 /* TODO */
case 0:
if (header->Compression != BI_PNG) return FALSE;
/* JPEG not supported */
break;
#endif
case 1:
case 24:
if (header->Compression != BI_RGB) return FALSE;
break;
case 4:
if (header->Compression != BI_RGB
&& header->Compression != BI_RLE4) return FALSE;
break;
case 8:
if (header->Compression != BI_RGB
&& header->Compression != BI_RLE8) return FALSE;
break;
case 16:
case 32:
if (header->Compression != BI_RGB
&& header->Compression != BI_BITFIELDS) return FALSE;
/* Any of the color masks could conceivably be zero; the bitmap, though
* limited, would still be meaningful */
if (header->Compression == BI_BITFIELDS
&& header->RedMask == 0
&& header->GreenMask == 0
&& header->BlueMask == 0) return FALSE;
break;
default:
return FALSE;
}
if (header->Height < 0 && header->Compression != BI_RGB
&& header->Compression != BI_BITFIELDS) return FALSE;
return TRUE;
}
/* Return the number of palette entries to read from the file */
static unsigned
get_palette_size(header)
const struct BitmapInfoHeader *header;
{
switch (header->BitsPerPixel) {
case 1:
return 2;
case 4:
return header->ColorsUsed ? header->ColorsUsed : 16;
case 8:
return header->ColorsUsed ? header->ColorsUsed : 256;
default:
return 0;
}
}
/*
* Read the palette from the file
* palette_size is the number of entries to read, but no more than 256 will
* be written into the palette array
* Return TRUE if successful, FALSE on any error
*/
static boolean
read_palette(fp, palette, palette_size)
FILE *fp;
struct Pixel *palette;
unsigned palette_size;
{
unsigned i;
unsigned char buf[4];
unsigned read_size;
read_size = (palette_size < 256) ? palette_size : 256;
for (i = 0; i < read_size; ++i) {
size_t size = fread(buf, 1, sizeof(buf), fp);
if (size < sizeof(buf)) return FALSE;
palette[i].b = buf[0];
palette[i].g = buf[1];
palette[i].r = buf[2];
palette[i].a = 255;
}
for (; i < 256; ++i) {
palette[i].b = 0;
palette[i].g = 0;
palette[i].r = 0;
palette[i].a = 255;
}
fseek(fp, 4 * (palette_size - read_size), SEEK_CUR);
return TRUE;
}
/* Decode an unsigned 16 bit quantity */
static uint16
read_u16(buf)
const unsigned char buf[2];
{
return ((uint16)buf[0] << 0)
| ((uint16)buf[1] << 8);
}
/* Decode an unsigned 32 bit quantity */
static uint32
read_u32(buf)
const unsigned char buf[4];
{
return ((uint32)buf[0] << 0)
| ((uint32)buf[1] << 8)
| ((uint32)buf[2] << 16)
| ((uint32)buf[3] << 24);
}
/* Decode a signed 32 bit quantity */
static int32
read_s32(buf)
const unsigned char buf[4];
{
return (int32)((read_u32(buf) ^ 0x80000000) - 0x80000000);
}
/* Build a pixel structure, given the mask words in the second header and
* a packed 16 or 32 bit pixel */
static struct Pixel
build_pixel(header, color)
const struct BitmapInfoHeader *header;
uint32 color;
{
struct Pixel pixel;
pixel.r = pixel_element(header->RedMask, color);
pixel.g = pixel_element(header->GreenMask, color);
pixel.b = pixel_element(header->BlueMask, color);
pixel.a = header->AlphaMask ? pixel_element(header->AlphaMask, color) : 255;
return pixel;
}
/* Extract one element (red, green, blue or alpha) from a pixel */
static unsigned char
pixel_element(mask, color)
uint32 mask;
uint32 color;
{
uint32 bits, shift;
if (mask == 0) return 0;
bits = 0xFFFF; /* 0xFF, 0xF, 0x3, 0x1 */
shift = 16; /* 8, 4, 2, 1 */
while (bits != 0) {
if ((mask & bits) == 0) {
mask >>= shift;
color >>= shift;
}
shift /= 2;
bits >>= shift;
}
color &= mask;
return color * 255 / mask;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 thintile.c $NHDT-Date: 1432512803 2015/05/25 00:13:23 $ $NHDT-Branch: master $:$NHDT-Revision: 1.9 $ */
/* NetHack 3.6 thintile.c $NHDT-Date: 1457207049 2016/03/05 19:44:09 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.10 $ */
/* Copyright (c) NetHack Development Team 1995 */
/* NetHack may be freely redistributed. See license for details. */
@@ -32,7 +32,7 @@ copy_colormap()
int r, g, b;
char c[2];
while (fscanf(infile, "%[A-Za-z0-9] = (%d, %d, %d) ", c, &r, &g, &b)
while (fscanf(infile, "%[A-Za-z0-9.] = (%d, %d, %d) ", c, &r, &g, &b)
== 4) {
Fprintf(outfile, "%c = (%d, %d, %d)\n", c[0], r, g, b);
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 tilemap.c $NHDT-Date: 1454502429 2016/02/03 12:27:09 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.28 $ */
/* NetHack 3.6 tilemap.c $NHDT-Date: 1457207051 2016/03/05 19:44:11 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.29 $ */
/* NetHack may be freely redistributed. See license for details. */
/*
@@ -21,7 +21,7 @@ extern void FDECL(exit, (int));
#endif
#endif
#if defined(WIN32)
#if defined(MSDOS) || defined(WIN32)
#define STATUES_LOOK_LIKE_MONSTERS
#endif

225
win/share/tileset.c Normal file
View File

@@ -0,0 +1,225 @@
/* NetHack 3.6 tileset.c $NHDT-Date: 1457207053 2016/03/05 19:44:13 $ $NHDT-Branch: chasonr $:$NHDT-Revision: 1.0 $ */
/* Copyright (c) Ray Chason, 2016. */
/* NetHack may be freely redistributed. See license for details. */
#include "hack.h"
#include "tileset.h"
static void FDECL(get_tile_map, (const char *));
static void FDECL(split_tiles, (const struct TileSetImage *));
static void FDECL(free_image, (struct TileSetImage *));
static struct TileImage *tiles;
static unsigned num_tiles;
static struct TileImage blank_tile; /* for graceful undefined tile handling */
static boolean have_palette;
static struct Pixel palette[256];
boolean
read_tiles(filename, true_color)
const char *filename;
boolean true_color;
{
static const unsigned char png_sig[] = {
0x89, 0x50, 0x4E, 0x47, 0x0D, 0x0A, 0x1A, 0x0A
};
struct TileSetImage image;
FILE *fp = NULL; /* custodial */
char header[16];
boolean ok;
/* Fill the image structure with known values */
image.width = 0;
image.height = 0;
image.pixels = NULL; /* custodial */
image.indexes = NULL; /* custodial */
image.image_desc = NULL; /* custodial */
image.tile_width = 0;
image.tile_height = 0;
/* Identify the image type */
fp = fopen(filename, "rb");
if (fp == NULL) goto error;
memset(header, 0, sizeof(header));
fread(header, 1, sizeof(header), fp);
fclose(fp);
/* Call the loader appropriate for the image */
if (memcmp(header, "BM", 2) == 0) {
ok = read_bmp_tiles(filename, &image);
} else if (memcmp(header, "GIF87a", 6) == 0
|| memcmp(header, "GIF89a", 6) == 0) {
ok = read_gif_tiles(filename, &image);
} else if (memcmp(header, png_sig, sizeof(png_sig)) == 0) {
ok = read_png_tiles(filename, &image);
} else {
ok = FALSE;
}
if (!ok) goto error;
/* Reject if the interface cannot handle direct color and the image does
not use a palette */
if (!true_color && image.indexes == NULL) goto error;
/* Save the palette if present */
have_palette = image.indexes != NULL;
memcpy(palette, image.palette, sizeof(palette));
/* Set defaults for tile metadata */
if (image.tile_width == 0) {
image.tile_width = image.width / 40;
}
if (image.tile_height == 0) {
image.tile_height = image.tile_width;
}
/* Set the tile dimensions if the user has not done so */
if (iflags.wc_tile_width == 0) {
iflags.wc_tile_width = image.tile_width;
}
if (iflags.wc_tile_height == 0) {
iflags.wc_tile_height = image.tile_height;
}
/* Parse the tile map */
get_tile_map(image.image_desc);
/* Split the image into tiles */
split_tiles(&image);
fclose(fp);
free_image(&image);
return TRUE;
error:
if (fp) fclose(fp);
free_image(&image);
return FALSE;
}
const struct Pixel *
get_palette()
{
return have_palette ? palette : NULL;
}
/* TODO: derive tile_map from image_desc */
static void
get_tile_map(image_desc)
const char *image_desc;
{
}
void
free_tiles()
{
unsigned i;
if (tiles != NULL) {
for (i = 0; i < num_tiles; ++i) {
free(tiles[i].pixels);
free(tiles[i].indexes);
}
}
free(tiles);
tiles = NULL;
num_tiles = 0;
free(blank_tile.pixels);
blank_tile.pixels = NULL;
free(blank_tile.indexes);
blank_tile.indexes = NULL;
}
static void
free_image(image)
struct TileSetImage *image;
{
free(image->pixels);
image->pixels = NULL;
free(image->indexes);
image->indexes = NULL;
free(image->image_desc);
image->image_desc = NULL;
}
const struct TileImage *
get_tile(tile_index)
unsigned tile_index;
{
if (tile_index >= num_tiles) {
return &blank_tile;
} else {
return &tiles[tile_index];
}
}
static void
split_tiles(image)
const struct TileSetImage *image;
{
unsigned tile_rows, tile_cols;
size_t tile_size, i, j;
unsigned x1, y1, x2, y2;
/* Get the number of tiles */
tile_rows = image->height / iflags.wc_tile_height;
tile_cols = image->width / iflags.wc_tile_width;
num_tiles = tile_rows * tile_cols;
tile_size = (size_t) iflags.wc_tile_height * (size_t) iflags.wc_tile_width;
/* Allocate the tile array */
tiles = (struct TileImage *) alloc(num_tiles * sizeof(tiles[0]));
memset(tiles, 0, num_tiles * sizeof(tiles[0]));
/* Copy the pixels into the tile structures */
for (y1 = 0; y1 < tile_rows; ++y1) {
for (x1 = 0; x1 < tile_cols; ++x1) {
struct TileImage *tile = &tiles[y1 * tile_cols + x1];
tile->width = iflags.wc_tile_width;
tile->height = iflags.wc_tile_height;
tile->pixels = (struct Pixel *)
alloc(tile_size * sizeof(struct Pixel));
if (image->indexes != NULL) {
tile->indexes = (unsigned char *) alloc(tile_size);
}
for (y2 = 0; y2 < iflags.wc_tile_height; ++y2) {
for (x2 = 0; x2 < iflags.wc_tile_width; ++x2) {
unsigned x = x1 * iflags.wc_tile_width + x2;
unsigned y = y1 * iflags.wc_tile_height + y2;
i = y * image->width + x;
j = y2 * tile->width + x2;
tile->pixels[j] = image->pixels[i];
if (image->indexes != NULL) {
tile->indexes[j] = image->indexes[i];
}
}
}
}
}
/* Create a blank tile for use when the tile index is invalid */
blank_tile.width = iflags.wc_tile_width;
blank_tile.height = iflags.wc_tile_height;
blank_tile.pixels = (struct Pixel *)
alloc(tile_size * sizeof(struct Pixel));
for (i = 0; i < tile_size; ++i) {
blank_tile.pixels[i].r = 0;
blank_tile.pixels[i].g = 0;
blank_tile.pixels[i].b = 0;
blank_tile.pixels[i].a = 255;
}
if (image->indexes) {
blank_tile.indexes = (unsigned char *) alloc(tile_size);
memset(blank_tile.indexes, 0, tile_size);
}
}
boolean
read_png_tiles(filename, image)
const char *filename;
struct TileSetImage *image;
{
/* stub */
return FALSE;
}

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 termcap.c $NHDT-Date: 1447234979 2015/11/11 09:42:59 $ $NHDT-Branch: master $:$NHDT-Revision: 1.23 $ */
/* NetHack 3.6 termcap.c $NHDT-Date: 1456907853 2016/03/02 08:37:33 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.24 $ */
/* Copyright (c) Stichting Mathematisch Centrum, Amsterdam, 1985. */
/* NetHack may be freely redistributed. See license for details. */
@@ -1246,6 +1246,7 @@ int color;
xputs(hilites[color]);
}
/* not to be confused with has_colors() in unixtty.c */
int
has_color(color)
int color;
@@ -1253,23 +1254,24 @@ int color;
#ifdef X11_GRAPHICS
/* XXX has_color() should be added to windowprocs */
if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "X11"))
return TRUE;
return 1;
#endif
#ifdef GEM_GRAPHICS
/* XXX has_color() should be added to windowprocs */
if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "Gem"))
return TRUE;
return 1;
#endif
#ifdef QT_GRAPHICS
/* XXX has_color() should be added to windowprocs */
if (windowprocs.name != NULL && !strcmpi(windowprocs.name, "Qt"))
return TRUE;
return 1;
#endif
#ifdef AMII_GRAPHICS
/* hilites[] not used */
return iflags.use_color;
#endif
return iflags.use_color ? 1 : 0;
#else
return hilites[color] != (char *) 0;
#endif
}
#endif /* TEXTCOLOR */

View File

@@ -1,4 +1,4 @@
/* NetHack 3.6 wintty.c $NHDT-Date: 1453514601 2016/01/23 02:03:21 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.124 $ */
/* NetHack 3.6 wintty.c $NHDT-Date: 1456907854 2016/03/02 08:37:34 $ $NHDT-Branch: NetHack-3.6.0 $:$NHDT-Revision: 1.125 $ */
/* Copyright (c) David Cohrs, 1991 */
/* NetHack may be freely redistributed. See license for details. */
@@ -31,8 +31,7 @@ extern void msmsg(const char *, ...);
#include "wintty.h"
#ifdef CLIPPING /* might want SIGWINCH */
#if defined(BSD) || defined(ULTRIX) || defined(AIX_31) \
|| defined(_BULL_SOURCE)
#if defined(BSD) || defined(ULTRIX) || defined(AIX_31) || defined(_BULL_SOURCE)
#include <signal.h>
#endif
#endif
@@ -226,8 +225,21 @@ const char *mesg;
}
#if defined(SIGWINCH) && defined(CLIPPING)
STATIC_DCL void FDECL(winch_handler, (int));
/*
* This really ought to just set a flag like the hangup handler does,
* then check the flag at "safe" times, in case the signal arrives
* while something fragile is executing. Better to have a brief period
* where display updates don't fit the new size than for tty internals
* to become corrupted.
*
* 'winch_seen' has been "notyet" for a long time....
*/
/*ARGUSED*/
STATIC_OVL void
winch()
winch_handler(sig_unused) /* signal handler is called with at least 1 arg */
int sig_unused UNUSED;
{
int oldLI = LI, oldCO = CO, i;
register struct WinDesc *cw;
@@ -345,7 +357,7 @@ char **argv UNUSED;
ttyDisplay->lastwin = WIN_ERR;
#if defined(SIGWINCH) && defined(CLIPPING) && !defined(NO_SIGNAL)
(void) signal(SIGWINCH, winch);
(void) signal(SIGWINCH, (SIG_RET_TYPE) winch_handler);
#endif
/* add one a space forward menu command alias */