# birth.tcl --
#
#

namespace eval NSBirth {

variable BirthPriv

# NSBirth::InitModule --
#
#	Called by angband_birth() to kick off character creation.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitModule {} {

	global NSPlayer
	variable BirthPriv

	set oop [NSObject::New NSBirth]

	# Create a player-info window...
	set playerId [NSObject::New NSPlayer]

	# Hack -- Get player-info window
	set win $NSPlayer($playerId,win)
	set BirthPriv(playerId) $playerId
	set BirthPriv(canvas) $win.canvas

	# ...but don't feed the Term when keys are pressed
	bind $win <KeyPress> {}

	# Never allow change of name during creation
	bind $win <c> {}

	# Do stuff when window closes
	wm protocol $win WM_DELETE_WINDOW "NSBirth::Close $oop"

	# Window to show progress during autoroller
	InitAutoProgressWindow

	# Put the main window on front again, and then position the
	# Birth Window and make it the front window.
	raise . ; focus .
	set win $::NSBirth($oop,win)
	WindowPosition $win 2 3
	WindowBringToFront $win

	# Read a dead-character's save file
	if {[info exists ::AngbandPriv(load,win)]} {
		wm withdraw $::AngbandPriv(load,win)

	# Creating a new character
	} else {
		wm withdraw .
	}
}

# NSBirth::NSBirth --
#
#	Object constructor called by NSObject::New().
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc NSBirth oop {

	global NSBirth

	InitWindow $oop

	set NSBirth($oop,gender) Female
	set NSBirth($oop,race) Human
	set NSBirth($oop,class) Warrior
	set NSBirth($oop,realm1) None
	set NSBirth($oop,realm2) None
	set NSBirth($oop,max_quest) 20
	set NSBirth($oop,hard_quests) 0
	set NSBirth($oop,wilderness) 1

	set win $NSBirth($oop,win)

	wm geometry $win +[winfo screenwidth $win]+0

	set minx [set miny 0]
	foreach screen {Gender Race Class Realm1 Realm2 Options Quest AutoRoll} {
		set NSBirth($oop,screen) $screen
		BirthHack $oop
		InitScreen_$screen $oop
		update
		set minx [expr $minx < [winfo width $win] ? [winfo width $win] : $minx]
		set miny [expr $miny < [winfo height $win] ? [winfo height $win] : $miny]
		eval destroy [winfo children $win.content]
	}
	$win configure -width $minx
	$win configure -height $miny
	grid propagate $win no

#	WindowPosition $win 2 3
#	WindowBringToFront $win

	set NSBirth($oop,screen) Gender
	InitScreen_Gender $oop

	# On the first screen, so user can't go back
	$win.buttons.back configure -state disabled
}

# NSBirth::InitWindow --
#
#	Initialize the Wizard-like window for character creation. The
#	window has a prompt, an info label, a varying content area, and
#	some buttons at the bottom.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitWindow oop {

	global NSBirth

	set win .birth$oop
	toplevel $win
	wm title $win "Character Creation"

	# Do stuff when window closes
	wm protocol $win WM_DELETE_WINDOW "NSBirth::Close $oop"

	set NSBirth($oop,win) $win

	set label $win.prompt
	label $label \
		-font "{MS Sans Serif} 10 bold underline"

	set label $win.info
	message $label \
		-width 350

	set frame $win.content
	frame $frame \
		-borderwidth 0

	set frame $win.divider1
	frame $frame \
		-borderwidth 1 -height 2 -relief sunken

	set frame $win.buttons
	frame $frame \
		-borderwidth 0
	button $frame.cancel \
		-command "NSBirth::Close $oop" -text "Quit" -underline 0 \
		-width 9
	button $frame.next \
		-command "NSBirth::Next $oop" -text "Next >" -underline 0 \
		-width 9
	button $frame.back \
		-command "NSBirth::Back $oop" -text "< Back" -underline 2 \
		-width 9

	grid rowconfigure $win 0 -weight 0
	grid rowconfigure $win 1 -weight 0
	grid rowconfigure $win 2 -weight 1
	grid rowconfigure $win 3 -weight 0
	grid rowconfigure $win 4 -weight 0
	grid columnconfigure $win 0 -weight 1

	grid $win.prompt \
		-row 0 -col 0 -rowspan 1 -columnspan 1 -sticky w -padx 5 -pady 5
	grid $win.info \
		-row 1 -col 0 -rowspan 1 -columnspan 1 -sticky w -padx 10 -pady 5
	grid $win.content \
		-row 2 -col 0 -rowspan 1 -columnspan 1 -sticky news -padx 10 -pady 5
	grid $win.divider1 \
		-row 3 -col 0 -rowspan 1 -columnspan 1 -sticky ew -padx 10
	grid $win.buttons \
		-row 4 -col 0 -rowspan 1 -columnspan 1 -sticky ew -padx 5 -pady 5

	set frame $win.buttons
	pack $frame.cancel \
		-side right -pady 5 -padx 5
	pack $frame.next \
		-side right -pady 5 -padx 5
	pack $frame.back \
		-side right -pady 5 -padx 5

	bind $win <KeyPress-Right> "tkButtonInvoke $frame.next"
	bind $win <KeyPress-n> "tkButtonInvoke $frame.next"
	bind $win <KeyPress-Left> "tkButtonInvoke $frame.back"
	bind $win <KeyPress-b> "tkButtonInvoke $frame.back"
	bind $win <KeyPress-q> "tkButtonInvoke $frame.cancel"
	bind $win <KeyPress-Escape> "tkButtonInvoke $frame.cancel"
}

# NSBirth::Close --
#
#	Quit the game when one of the windows is closed.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Close oop {
	angband game abort
}

# NSBirth::InitAutoProgressWindow --
#
#	Initializes the window used to display feedback during the autoroller.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitAutoProgressWindow {} {

	global NSPlayer
	variable BirthPriv

	set playerId $BirthPriv(playerId)

	set win .autoprogress
	toplevel $win
	wm title $win "Autoroller"
	wm transient $win $NSPlayer($playerId,win)

	label $win.prompt \
		-text "> Hit any key to stop <" -font {Times 12 bold}
	pack $win.prompt \
		-side top -padx 5 -pady 5

	frame $win.divider1 \
		-borderwidth 1 -height 2 -relief sunken
	pack $win.divider1 \
		-side top -fill x

	set data {
		"    Strength:" strength
		"Intelligence:" intelligence
		"      Wisdom:" wisdom
		"   Dexterity:" dexterity
		"Constitution:" constitution
		"    Charisma:" charisma
	}

	set frame $win.stats
	frame $frame \
		-borderwidth 0

	foreach {title stat} $data {

		set frame $win.stats.$stat
		set name $frame.name
		set value $frame.value
		set match $frame.match

		frame $frame \
			-borderwidth 0
		label $name \
			-text $title -font {Courier 9} -borderwidth 0
		label $value \
			-width 6 -font {Courier 9 bold} -anchor e -borderwidth 0
		label $match \
			-width 6 -font {Courier 9 italic} -anchor e -borderwidth 0

		pack $frame \
			-side top -expand yes -fill x -anchor w
		pack $name \
			-side left -expand no
		pack $value \
			-side left -expand no -padx 4
		pack $match \
			-side left -expand no
	}

	pack $win.stats \
		-side top -anchor c -padx 10 -pady 5

	frame $win.divider2 \
		-borderwidth 1 -height 2 -relief sunken
	pack $win.divider2 \
		-side top -fill x

	label $win.autoround \
		-font {Courier 9} -text "Round: XXXXX"
	pack $win.autoround \
		-side top -pady 5 -anchor c

	# Binding to interupt autoroller
	bind $win <KeyPress> {
		set NSBirth::BirthPriv(userAbort) 1
	}

	WindowPosition $win 2 3

	wm withdraw $win
}

# NSBirth::InitScreen_Gender --
#
#	Creates the display in the Birth Window to let the user choose
#	a gender.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Gender oop {

	global NSBirth

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Choose your character's gender"
	$win.info configure -text "Your character's gender does not have\
		any significant gameplay effects."

	set frame $win.content
	foreach gender [birth info gender_name] {
		set name [string tolower $gender]
		radiobutton $frame.$name \
			-text $gender -variable NSBirth($oop,gender) -value $gender \
			-borderwidth 0
		pack $frame.$name \
			-side top -padx 55 -anchor w
	}

	return 0
}

variable Detail

set Detail(Human) "The human is the base character.  All other races are\
compared to them. Humans can choose any class and are average at everything. \
Humans tend to go up levels faster than any other race because of their\
shorter life spans.  No racial adjustments or intrinsics occur to\
characters choosing human."

set Detail(Half-Elf) "Half-elves tend to be smarter and faster than a\
human, but not as strong.  Half-elves are slightly better at searching,\
disarming, saving throws, stealth, bows, and magic, but they\
are not as good at hand weapons.  Half-elves may choose any\
class and do not receive any intrinsic abilities."

set Detail(Elf) "Elves are better magicians then humans, but not as good at\
fighting.  They tend to be smarter and faster than either\
humans or half-elves and also have better wisdom.  Elves\
are better at searching, disarming, perception, stealth, bows,\
and magic, but they are not as good at hand weapons.  Elves\
may choose any class except Paladin.  They resist light\
effects intrinsically."

set Detail(Hobbit) "Hobbits, or Halflings, are very good at bows, throwing,\
and have good saving throws.  They also are very good at searching,\
disarming, perception, and stealth; so they make excellent rogues, but\
prefer to be called burglars.  They will be much weaker than humans,\
and no good at melee fighting.  Halflings have fair infravision, so\
they can detect warm creatures at a distance.  Hobbits can choose\
between being a warrior, mage, or rogue.  They have their dexterity\
sustained."

set Detail(Gnome) "Gnomes are smaller than dwarves but larger than\
halflings.  They, like the halflings, live in the earth in burrow-like\
homes.  Gnomes make excellent mages, and have very good saving\
throws.  They are good at searching, disarming, perception,\
and stealth.  They have lower strength than humans so they\
are not very good at fighting with hand weapons.  Gnomes have\
fair infra-vision, so they can detect warm-blooded creatures\
at a distance.  A gnome may choose between being a warrior,\
mage, priest, or rogue.  Gnomes are intrinsically protected\
against paralysis and some slowing effects."

set Detail(Dwarf) "Dwarves are the headstrong miners and fighters of\
legend.  Since dungeons are the natural home of a dwarf, they are\
excellent choices for a warrior or priest.  Dwarves tend to\
be stronger and tougher but slower and less intelligent than\
humans.  Because they are so headstrong and are somewhat wise,\
they resist spells which are cast on them.  Dwarves also have\
very good infra-vision because they live underground.  They\
do have one big drawback, though.  Dwarves are loudmouthed and\
proud, singing in loud voices, arguing with themselves for no\
good reason, screaming out challenges at imagined foes.  In\
other words, dwarves have a miserable stealth.  They can never\
be blinded."

set Detail(Half-Orc) "Half-Orcs make excellent warriors and decent priests,\
but are terrible at magic.  They are as bad as dwarves at stealth,\
and horrible at searching, disarming, and perception.  Half-Orcs are,\
let's face it, ugly.  They tend to pay more for goods in town. \
Half-Orcs do make good warriors and rogues, for the simple reason that\
Half-Orcs tend to have great constitutions and lots of hit points. \
Because of their preference to living underground to on the surface,\
half-orcs resist darkness attacks."

set Detail(Half-Troll) "Half-Trolls are incredibly strong, and have more\
hit points than any other character race.  They are also very stupid and\
slow.  They will make great warriors and iffy priests.  They\
are bad at searching, disarming, perception, and stealth. \
They are so ugly that a Half-Orc grimaces in their presence.\
They also happen to be fun to run...  Half-trolls always have\
their strength sustained."

set Detail(Amberite) "The Amberites are a reputedly immortal race, who are endowed\
with numerous advantages, not only their longevity.  They are\
very tough and endurant; their constitution cannot be reduced,\
and their ability to heal wounds far surpasses that of any\
other race.  Having seen virtually everything, very little\
is new to them, and they gain levels much slower than the\
other races.  But should they advance high enough, they will\
learn the innate Amberite powers of Pattern Mindwalking and\
Shadow Shifting."

set Detail(High-Elf) "High-elves are a race of immortal beings dating\
from the beginning of time.  Levels are even harder for them to gain\
than to Dunadan.  They are masters of all skills, and are\
strong and intelligent, although their wisdom is sometimes\
suspect.  They can play all classes except Paladin, and very\
well at that.  High-elves begin their lives able to see the\
unseen, and resist light effects just like regular elves."

set Detail(Barbarian) "Barbarians are hardy men of the north. They are fierce in\
combat, and their wrath is feared throughout the world.\
Combat is their life: they feel no fear, and they learn\
to enter battle frenzy at will even sooner than half-trolls.\
Barbarians are, however, suspicious of magic, which makes\
magic devices fairly hard for them to use, and also makes\
it impossible for them to play Mages. They cannot play\
Paladins, either, because their wild bloodlust is totally\
incompatible with the strict discipline of knighthood."

set Detail(Half-Ogre) "Half-Ogres are like Half-Orcs, but only more so. They\
are big, bad, and stupid. For warriors, they have all\
the necessary attributes, and they can even become\
wizards: after all, they are related to Ogre Magi,\
from whom they have learned the skill of setting\
trapped runes once their level is high enough. Like Half-\
Orcs, they resist darkness, and like Half-Trolls, they\
have their strength sustained."

set Detail(Half-Giant) "Half-Giants are not too unusual, as there has been a\
tradition according to which it is a noble and brave thing\
to do to consort a giant (especially a giant-maid). Never-\
theless, the poor offspring of such a union is seldom very\
popular in the world of men. Their limited intelligence\
makes it impossible for them to become full spellcasters,\
but with their huge strength they make excellent warriors.\
They also love to wander in the wilderness, and can become\
rangers. No ordinary wall can withstand the fury of a giant,\
or a half-giant, and at higher levels they can learn the\
power of magical digging. Their thick skin makes them\
resistant to shards, and like Half-Ogres and Half-Trolls,\
they have their strength sustained."

set Detail(Half-Titan) "Half-mortal descendants of the mighty titans, these\
immensely powerful creatures put almost any other race\
to shame. They may lack the fascinating special powers\
of certain other races, but their enhanced attributes\
more than make up for that. They learn to estimate the\
strengths of their foes, and their love for law and\
order makes them resistant to the effects of Chaos."

set Detail(Cyclops) "With but one eye, a cyclops can see more than many\
with two eyes. They are headstrong, and loud noises\
bother them very little. They are not quite qualified\
for the magic using professions, but as a certain Mr\
Ulysses can testify, their accuracy with thrown rocks\
can be deadly..."

set Detail(Yeek) "Yeeks are among the most pathetic creatures. Fortunately,\
their horrible screams can scare away less confident foes,\
and their skin becomes more and more resistant to acid,\
as they gain experience. But having said that, even a\
mediocre monster can proverbially wipe the floor with\
an unwary yeek."

set Detail(Klackon) "Klackons are bizarre semi-intelligent ant-like insectoid\
creatures. They make great servants and warriors, but\
their mental abilities are severely limited. Obedient\
and well-ordered, they can never be confused. They are\
also very nimble, and become faster as they advance\
levels. They are also very acidic, inherently resisting\
acid, and capable of spitting acid at higher levels."

set Detail(Kobold) "Kobolds are a weak goblin race. They love poisoned weapons,\
and can learn to throw poisoned darts (of which they carry\
an unlimited supply). They are also inherently resistant to\
poison, and can become adequate fighters, although they are\
not one of the more powerful races."

set Detail(Nibelung) "The hated and persecuted race of nocturnal dwarves, these\
cave-dwellers are not much bothered by darkness. Their\
natural inclination to magical items has made them immune\
to effects which could drain away magical energy, and like\
ordinary dwarves, they can examine the dungeon to discover\
traps and secret doors."

set Detail(Dark*Elf) "Another dark, cave-dwelling race, likewise unhampered by\
darkness attacks, the Dark Elves have a long tradition\
and knowledge of magic. With their intelligence they can\
become superb mages or priests, and they have an inherent\
magic missile attack available to them at a low level. With\
their keen sight, they also learn to see invisible things\
as their relatives High-Elves do, but at a higher level."

set Detail(Draconian) "A humanoid race with dragon-like attributes. As they advance\
levels, they gain new elemental resistances (up to Poison\
Resistance), and they also have a breath weapon, which\
becomes more powerful with experience. The exact type of\
the breath weapon depends on the draconian's class and\
level. With their wings, they can easily escape any pit\
trap unharmed."

set Detail(Mindflayer) "A secretive and mysterious ancient race. Their civilization\
may well be older than any other on our planet, and their\
intelligence and wisdom are naturally sustained, and are so\
great that they enable Mind Flayers to become more powerful\
spellcasters than any other race, even if their physical\
attributes are a good deal less admirable. As they advance\
levels, they gain the powers of See Invisible, Telepathy\
and a mind blast attack."

set Detail(Imp) "A demon-creature from the nether-world, naturally resistant\
to fire attacks, and capable of learning fire bolt and fire\
ball attacks. They are little loved by other races, but\
can perform fairly well in most professions."

set Detail(Golem) "A golem is an artificial creature, built from a lifeless\
raw material like clay, and awakened to life. They are\
nearly mindless, making them useless for professions which\
rely on magic, but as warriors they are very tough. They\
are resistant to poison, they can see invisible things,\
and move freely. At higher levels, they also become resistant\
to attacks which threaten to drain away their life force.\
They also learn to temporarily turn their skin into a very\
hard, stonelike substance. In the most recent version, golems\
gain very little nutrition from ordinary food. They need to\
collect scrolls of satisfy hunger, or perish of exhaustion\
when the life force animating their body runs out. In the\
most recent version golems also gain natural armor class\
bonus from their tough body."

set Detail(Skeleton) "There are two types of skeletons: the ordinary, warrior-\
like skeletons, and the spell-using skeletons, which are\
also called liches. As undead beings, skeletons need to\
worry very little about poison or attacks that can drain\
life. They do not really use eyes for perceiving things,\
and are thus not fooled by invisibility. Their bones are\
resistant to sharp shrapnels (not much to cut there),\
and they will quickly become resistant to cold. Should\
a skeleton be unlucky enough to lose some of his or her\
remaining life, he or she will learn to restore it at\
will. It is very hard for skeletons to eat food or drink\
potions. Although the magical effects of these will affect\
the skeleton even without entering the skeleton's (non-\
existent) belly, the potion / food itself will fall through\
the skeleton's jaws, giving no nutritional benefit."

set Detail(Zombie) "Much like Skeletons, Zombies too are undead horrors: they\
are resistant to life-draining attacks, and can learn to\
restore their life-force. Like skeletons, they become\
resistant to cold-based attacks (actually earlier than\
skeletons), resist poison and can see invisible. While\
still vulnerable to cuts (unlike skeletons), Zombies are\
resistant to Nether. Like golems, they gain very little\
nutrition from the food of mortals. However, Zombies are,\
as the name implies, practically mindless: in this company,\
Groo would seem a genius."

set Detail(Vampire) "One of the mightier undead creatures, the Vampire is an\
awe-inspiring sight. Yet this mighty creature has a serious\
weakness: the bright rays of sun are its bane, and it will\
need to flee the surface to the deep recesses of earth until\
the sun finally sets. Darkness, on the other hand, only makes\
the Vampire stronger. As undead, the Vampire has a firm hold\
on its life force, and resists nether attacks. The Vampire\
also resists cold and poison based attacks. It is, however,\
susceptible to its perpetual hunger for fresh blood, which\
can only be satiated by sucking the blood from a nearby\
monster, which is the Vampire's special power. It should be\
noted that the vampires are so sensitive to daylight that\
even certain artifact light items which are filled with\
daylight will hurt them if they try to wield the items.\
Fortunately, the vampires do not really need these items,\
since they radiate an aura of 'dark light' of their own.\
Light resistance will, in any case, protect the vampire\
from the adverse effects of sunlight."

set Detail(Spectre) "Another powerful undead creature: the spectre is a ghastly\
apparition, surrounded by an unearthly green glow. They exist\
only partially on our plane of existence: half-corporeal,\
they can pass through walls, although the density of the\
wall will hurt them in the process of doing this. The spectre\
can scream an eldritch howl, which is enough to scare lesser\
monsters witless. As undead, they have a firm hold on their\
life force, see invisible, and resist poison and cold. They\
also resist nether; in fact, their half-corporeal form\
actually grows stronger from the effects of nether. At\
higher levels they develop telepathic abilities. Spectres\
make superb spellcasters, but their physical form is very\
weak. Like Golems and Zombies, Spectres gain almost no\
nutrition from ordinary food."

set Detail(Sprite) "One of the several fairy races, sprites are very small.\
They have tiny wings, and can fly over traps that may open\
up beneath them. They enjoy sunlight intensely, and need\
worry little about light based attacks. Although physically\
among the weakest races, Sprites are very talented in magic,\
and can become highly skilled wizards. Sprites have the\
special power of spraying Sleeping Dust, and at higher\
levels they learn to fly faster."

set Detail(Beastman) "This race is a blasphemous abomination produced by Chaos.\
It is not an independent race but rather a humanoid creature,\
most often a human, twisted by the Chaos, or a nightmarsh\
crossbreed of a human and a beast. All Beastmen are accustomed\
to Chaos so much that they are untroubled by confusion and\
sound, although raw Logrus can still have effects on them.\
Beastmen revel in chaos, as it twists them more and more.\
Beastmen are subject to mutations: when they have been\
created, they receive a random mutation. After that,\
every time they advance a level they have a little chance\
of gaining yet another mutation."

# NSBirth::InfoListAppend --
#
#	Adds an item to the Race List or Class List.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InfoListAppend {oop desc detail value} {

	global NSBirth

	set win $NSBirth($oop,win)
	set list $win.content.frameList.list
	$list insert end $desc

	lappend NSBirth($oop,detail) $detail
	lappend NSBirth($oop,value) $value
}

# NSBirth::SelectionChanged --
#
#	Called when the selection changes in the Race List or Class List.
#	Displays help information.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc SelectionChanged {oop what} {

	global NSBirth
	variable Detail

	set win $NSBirth($oop,win)
	set list $win.content.frameList.list
	set selection [$list curselection]
	if {![llength $selection]} return
	set row [lindex $selection 0]

	set text $win.content.frameText.text
	$text delete 1.0 end
	$text insert end [$list get $row]\n
	$text tag add header 1.0 "end -1 chars"
	$text tag configure header -font "{MS Sans Serif} 8 bold" -underline yes
	set detail [lindex $NSBirth($oop,detail) $row]
	regsub -all " " $detail * detail
	$text insert end $Detail($detail)

	set NSBirth($oop,$what) [lindex $NSBirth($oop,value) $row]
}

# NSBirth::InitScreen_Race --
#
#	Creates the display in the Birth Window to let the user choose
#	a race.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Race oop {

	global NSBirth

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Choose your character's race"
	$win.info configure -text "Each race has different abilities\
		and bonuses to stats. Any race can play any class, although\
		some races are better at certain classes."

	set frame $win.content
	set frame $frame.frameList
	frame $frame \
		-borderwidth 2 -relief sunken
	set list $frame.list
	listbox $list \
		-width 20 -height 8 -yscrollcommand "$frame.yscroll set" \
		-background White -borderwidth 0 -highlightthickness 0
	scrollbar $frame.yscroll \
		-orient vertical -command "$list yview"

	bind $list <Double-Button-1> \
		"tkButtonInvoke $win.buttons.next"
	bind $list <ButtonRelease-1> "NSBirth::SelectionChanged $oop race"

	set frame $win.content.frameText
	frame $frame \
		-borderwidth 2 -relief sunken	
	set text $frame.text
	text $text \
		-width 40 -height 8 -yscrollcommand "$frame.yscroll set" \
		-borderwidth 0 -wrap word -cursor {}
	scrollbar $frame.yscroll \
		-orient vertical -command "$text yview"

	bindtags $text [list $text $win all]

	set frame $win.content.frameList
	pack $frame \
		-side left -pady 5 -fill y
	pack $list \
		-side left -fill y
	pack $frame.yscroll \
		-side left -fill y

	pack [frame $win.content.filler1 -width 5 -borderwidth 0] \
		-side left -fill y

	set frame $win.content.frameText
	pack $frame \
		-side left -pady 5 -fill both
	pack $text \
		-side left -fill both
	pack $frame.yscroll \
		-side left -fill y

	set NSBirth($oop,detail) {}
	set NSBirth($oop,value) {}
	foreach race [lsort -dictionary [birth info race_name]] {
		InfoListAppend $oop $race $race $race
	}

	set row [lsearch [$list get 0 end] $NSBirth($oop,race)]
	$list selection set $row
	$list see $row
	SelectionChanged $oop race

	return 0
}

set Detail(Warrior) "A Warrior is a hack-and-slash character, who solves\
most of his problems by cutting them to pieces, but will occasionally\
fall back on the help of a magical device.  His prime stats are Strength\
and Constitution, and a good Dexterity can really help at times. \
A Warrior will be good at Fighting and Throwing/Bows, but bad at most\
other skills."

set Detail(Mage) "A Mage must live by his wits.  He cannot hope to simply\
hack his way through the dungeon, and so must therefore use his\
magic to defeat, deceive, confuse, and escape.  A mage is\
not really complete without an assortment of magical devices\
to use in addition to his spells.  He can master the higher\
level magical devices far easier than anyone else, and has\
the best saving throw to resist effects of spells cast at\
him.  Intelligence and Dexterity are his primary stats.\
There is no rule that says a mage cannot become a good\
fighter, but spells are his true realm."

set Detail(Priest) "A Priest is a character of holy devotion. \
They explore the dungeon only to destroy the evil that lurks within,\
and if treasure just happens to fall into their packs, well, so\
much more to the glory of their church!  Priests receive\
their spells from a deity, and therefore do not choose which\
spells they will learn.  They are familiar with magical devices,\
preferring to call them instruments of god, but are\
not as good as a mage in their use.  Priests have good\
saving throws, and make decent fighters, preferring blunt\
weapons over edged ones.  Wisdom and Charisma are the\
priest's primary stats."

set Detail(Rogue) "A Rogue is a character that prefers to live by his
cunning, but is capable of fighting his way out of a tight spot.  He\
is the master of traps and locks, no device being impossible\
for him to overcome.  A rogue has a high stealth allowing\
him to sneak around many creatures without having to fight,\
or sneak up and get the first blow.  A rogue's perception is\
higher than any other class, and many times he will notice a\
trap or secret door before having to search.  A rogue is\
better than warriors or paladins with magical devices, but\
still can not rely on their performance.  Rogues can also\
learn a few spells, but not the powerful offensive spells\
magi can use.  A rogue's primary stats are Intelligence and\
Dexterity."

set Detail(Ranger) "A Ranger is a warrior/mage.  He is a good fighter,\
and the best of the classes with a missile weapon such as a bow.\
The ranger learns spells much more slowly than a mage, but\
is capable of learning all but the most powerful spells.\
Because a ranger is really a dual class character, more\
experience is required for him to advance.  A ranger has a\
good stealth, good perception, good searching, a good saving\
throw, and is good with magical devices.  His primary stats\
are Intelligence and Dexterity."

set Detail(Paladin) "A Paladin is a warrior/priest.  He is a very good\
fighter, second only to the warrior class, but not very good at missile\
weapons.  He receives prayers at a slower pace then the\
priest, but can even receive the most powerful prayers. \
Because a paladin is really a dual class character, it\
requires more experience to advance him.  A paladin lacks\
much in the way of abilities.  He is poor at stealth, perception,\
searching, and magical devices.  He has a decent\
saving throw due to his divine alliance.  His primary stats\
are Strength and Charisma."

set Detail(Warrior-Mage) "A Warrior-Mage is precisely what the name suggests: a cross\
between the warrior and mage classes. While their brothers,\
the Rangers, specialize in Nature magic and survival skills,\
true Warrior-Mages attempt to reach the best of both worlds:\
as magicians, they are trained in Arcane magic and can\
select another realm, eventually learning every spell in\
both of them (although slower than true magicians); as\
warriors they are much superior to the usual Mage class. The\
Warrior-Mage is a truly powerful class, which is\
recommended for the players who want to cast spells but\
whose mages tend to die too quickly.  However, the power\
does not come without a price: Warrior-Mages require\
more experience to advance levels than any other class."

set Detail(Chaos-Warrior) "Chaos Warriors are the feared servants of the terrible Demon\
Lords of Chaos. Every Chaos Warrior has a Patron Demon, such\
as Arioch, Mabelode or Balaan.  Whenever a Chaos Warrior\
advances a level, his Patron Demon may reward him with a\
Gift of Chaos: he might be healed or polymorphed, his stats\
could be increased, or he might be rewarded with an awesome\
weapon.  Or his Patron Demon might, for some reason, get\
annoyed with him and do something fairly nasty to him, like\
surround him with monsters, drain his stats or wreck his\
equipment. Or they might simply ignore him. The Demon Lords\
of Chaos are chaotic and unpredictable indeed.  The exact\
type of reward depends on the Patron Demon Lord (different\
Demons give different rewards) and chance.\
Chaos Warriors are very good fighters, but they are also\
trained in Chaos magic, and can learn every Chaos spell."

set Detail(Monk) "The Monk character class is very different from all other\
classes. Although they can use weapons and armour just like\
any other class, their training in martial arts makes them\
much more powerful with no armour nor weapons.  To gain the\
resistances necessary for survival at higher levels a monk\
may need to wear some kind of armour, but if the armour he\
wears is too heavy, it will severely disturb his martial\
arts maneuvers. As the monk advances levels, new, powerful\
forms of attack become available. His defensive capabilities\
(blocking and dodging) increase likewise, but if armour is\
being worn, their effect decreases. It is rumoured that the\
monastic training even makes monks faster than any other\
character class!  Fortunately, also the amount of armour a\
monk can wear, while still fighting efficiently, also\
increases with experience.\
There are three kinds of monasteries: those devoted to Life,\
those devoted to Nature, and those devoted to Death.  These\
are the three possible realms of magic avaiilable to a monk,\
who can learn every prayer in the realm of his choice."

set Detail(Mindcrafter) "The Mindcrafter is character who uses the powers of mind\
instead of magic. These powers are unique to the Mindcrafter\
class, and vary from simple extrasensory powers to mental\
domination of others.  Since these powers are developed by\
the practice of certain disciplines, a Mindcrafter requires\
no spellbooks to use them.  The available powers are simply\
determined by the character level.  The Mindcrafter uses the\
wisdom score to determine how well he / she can perform the\
psychic powers, and in combat a Mindcrafter is roughly the\
equivalent of a priest, although a Mindcrafter is never\
penalized for wielding an edged weapon (unlike a priest)."

set Detail(High-Mage) "High Mages are specialist Mages of the highest order. In\
most respects they are exactly like ordinary Mages, although\
their spell stat is slightly higher.  Instead of selecting\
two realms of magic, a High Mage selects only one realm of\
magic and studies it extremely well, gaining substantial\
benefits in mana costs, minimum levels and failure rates."

# NSBirth::InitScreen_Class --
#
#	Creates the display in the Birth Window to let the user choose
#	a class.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Class oop {

	global NSBirth

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Choose your character's class"
	$win.info configure -text "Your character's class is like his\
		or her profession. Each class has special abilities and \
		weaknesses that make playing them a different challenge."

	set frame $win.content
	set frame $frame.frameList
	frame $frame \
		-borderwidth 2 -relief sunken
	set list $frame.list
	listbox $list \
		-width 20 -height 8 -yscrollcommand "$frame.yscroll set" \
		-background White -borderwidth 0 -highlightthickness 0
	scrollbar $frame.yscroll \
		-orient vertical -command "$list yview"

	bind $list <Double-Button-1> \
		"tkButtonInvoke $win.buttons.next"
	bind $list <ButtonRelease-1> "NSBirth::SelectionChanged $oop class"

	set frame $win.content.frameText
	frame $frame \
		-borderwidth 2 -relief sunken	
	set text $frame.text
	text $text \
		-width 40 -height 8 -yscrollcommand "$frame.yscroll set" \
		-borderwidth 0 -wrap word -cursor {}
	scrollbar $frame.yscroll \
		-orient vertical -command "$text yview"

	set frame $win.content.frameList
	pack $frame \
		-side left -pady 5 -fill y
	pack $list \
		-side left -fill y
	pack $frame.yscroll \
		-side left -fill y

	pack [frame $win.content.filler1 -width 5 -borderwidth 0] \
		-side left -fill y

	set frame $win.content.frameText
	pack $frame \
		-side left -pady 5 -fill both
	pack $text \
		-side left -fill both
	pack $frame.yscroll \
		-side left -fill y

	set NSBirth($oop,detail) {}
	set NSBirth($oop,value) {}
	foreach class [lsort -dictionary [birth info class_name]] {
		InfoListAppend $oop $class $class $class
	}

	set row [lsearch [$list get 0 end] $NSBirth($oop,class)]
	$list selection set $row
	$list see $row
	SelectionChanged $oop class

	return 0
}

set Detail(Life) "Life magic is 'good' magic; it relies mostly on healing\
and protective spells. It does have a few attack spells as well,\
but these are mostly used for harming and banishing foul minions\
of evil. It is rumoured that there is a secret high level prayer\
which will make the priest (or paladin) completely impervious\
to all forms of hostile action."

set Detail(Sorcery) "Sorcery is a `meta` realm, including enchantment and\
general spells.  It provides superb protection spells (such as\
Teleport spells for fleeing and even Globe of Invulnerability),\
spells to enhance your odds in combat (Slow Monster, Haste Self,\
Confuse Monster) and, most importantly, a vast selection of\
spells for gathering information: in addition to the usual\
detection and identify spells, one of the standard spellbooks\
has a spell called Identify True, which gives you full knowledge\
of a given object!  In the rare books, there are spells with\
which you can enchant your items or turn unwanted items to\
gold.  However, Sorcery has one weakness: it has no spells \
to deal direct damage to your enemies."

set Detail(Arcane) "Even more than Sorcery, Arcane magic is a general purpose\
realm of magic. It attempts to encompass all 'useful' spells from\
all realms, and almost succeeds, with the probable exception of\
*Identify*.  This is the downside of Arcane magic: while Arcane\
does have all the necessary 'tool' spells for a dungeon delver,\
it has no ultra-powerful high level spells. As a consequence, all\
Arcane spellbooks can be bought in town.  It should also be noted\
that the 'specialized' realms (i.e. other than Arcane) usually\
offer the same spell at a lower level and cost.  Arcane magic is\
therefore perhaps not recommendable as one's only realm of magic,\
but it should be a very nice addition to fill up the gaps in the\
selection of tools spells in another realm."

set Detail(Trump) "Trump magic seems an independent source of power, although\
its supposed association with Chaos magic has been mentioned in\
several places. Although it lacks the unpredictable chaotic side-\
effects of Chaos magic, it has a few spells whose exact effets\
seem more or less random.  One such spell is Shuffle: the Trump\
spellbooks actually consist of decks of trumps, and the Shuffle\
spell allows the caster to shuffle the deck and pick one card at\
random.  The effect depends on the card picked, and is not always\
pleasant.  In the Amber universe, the Trump gateways are also a\
major method of transportation: Trump magic has, indeed, an\
admirable selection of teleportation spells.  Since the Trump\
gateways can also be used to summon other creatures, Trump magic\
has an equally impressive selection of summoning spells. However,\
not all monsters appreciate being drawn to another place by Trump\
user. The only summoned creatures whose loyalty is guaranteed are\
the Phantasmal Servants, who lack a will of their own (but can\
develop one, if you treat them badly)."

set Detail(Nature) "Early levels may be rather difficult for a spellcaster\
relying on Nature magic, as the early spells offer only limited\
protection, detection and curing capabilities.  However, at \
higher levels there are very useful offensive spells available,\
especially should the spellcaster be lucky enough to find an\
extremely rare spellbook called \"Nature`s Wrath\".  Nature also \
has a spell of Herbal Healing, which is the only powerful healing\
spell outside the realm of Life magic."

set Detail(Chaos) "There are few types of magic more unpredictable and\
difficult to control than Chaos magic.  Chaos is the very \
element of unmaking, and the Chaos spells are the most \
terrible weapons of destruction imaginable.  From Magic\
Missile and Acid Bolt to the medium level Fire Ball and\
and Doom Bolt, and finally to the awesome spells of \
Invoke Logrus, Mana Storm and Call the Void, Chaos offers \
an unsurpassable arsenal of attack spells.  The caster can \
also call on the primal forces of Chaos to induce \
mutations in his / her opponents and even him/herself, but \
otherwise, Chaos has no protective spells. Beware, though, \
Chaos spells are known to backfire easily and product \
undesired effects. This is especially true in the version\
2.1.0 of Zangband and later, where the forces of Chaos can\
easily twist the hapless individual foolish enough to\
invoke them, turning them horrendous spawns of Chaos."

set Detail(Death) "There is no fouler nor more evil category of spells\
than the necromantic spells of Death Magic.  These spells \
are relatively hard to learn, but at higher levels the\
spells give the caster power over living and the (un)dead.\
Poison, vampirism, death spells and even hellfire can be\
directed by the caster, but the most powerful spells need\
his / her own blood as the focus, often hurting the caster\
in the process of casting.  Should a Death wizard find the\
legendary tome Necronomicon, he can expect to gain very\
great powers indeed, but at a cost: few that have studied\
the accursed tome have retained their sanity."

# NSBirth::InitScreen_Realm1 --
#
#	Creates the display in the Birth Window to let the user choose
#	the character's first realm of magic.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Realm1 oop {

	global NSBirth

	# The "birth info realm_name" command returns a list of magic realm names which the
	# user can choose. This list always includes "None". If it only includes
	# 1 or 2 choices, the user really doesn't have a choice, in which case this screen
	# is not presented.
	set realms [birth info realm_name]
	if {[llength $realms] <= 2} {

		# Choose the realm for the user. This will either be None or some other.
		set NSBirth($oop,realm1) [lindex $realms end]

		# Skip this screen
		return 1
	}

	set win $NSBirth($oop,win)

	$win.prompt configure -text "Choose your character's first realm of magic"
	$win.info configure -text "The realm of magic will determine which spells your character can learn."

	set frame $win.content
	set frame $frame.frameList
	frame $frame \
		-borderwidth 2 -relief sunken
	set list $frame.list
	listbox $list \
		-width 20 -height 8 -yscrollcommand "$frame.yscroll set" \
		-background White -borderwidth 0 -highlightthickness 0
	scrollbar $frame.yscroll \
		-orient vertical -command "$list yview"

	bind $list <Double-Button-1> \
		"tkButtonInvoke $win.buttons.next"
	bind $list <ButtonRelease-1> "NSBirth::SelectionChanged $oop realm1"

	set frame $win.content.frameText
	frame $frame \
		-borderwidth 2 -relief sunken	
	set text $frame.text
	text $text \
		-width 40 -height 8 -yscrollcommand "$frame.yscroll set" \
		-borderwidth 0 -wrap word -cursor {}
	scrollbar $frame.yscroll \
		-orient vertical -command "$text yview"

	set frame $win.content.frameList
	pack $frame \
		-side left -pady 5 -fill y
	pack $list \
		-side left -fill y
	pack $frame.yscroll \
		-side left -fill y

	pack [frame $win.content.filler1 -width 5 -borderwidth 0] \
		-side left -fill y

	set frame $win.content.frameText
	pack $frame \
		-side left -pady 5 -fill both
	pack $text \
		-side left -fill both
	pack $frame.yscroll \
		-side left -fill y

	set NSBirth($oop,detail) {}
	set NSBirth($oop,value) {}
	foreach realm [lrange [birth info realm_name] 1 end] {
		InfoListAppend $oop $realm $realm $realm
	}

	set row [lsearch [$list get 0 end] $NSBirth($oop,realm1)]
	$list selection set $row
	$list see $row
	SelectionChanged $oop realm1

	return 0
}

# NSBirth::InitScreen_Realm2 --
#
#	Creates the display in the Birth Window to let the user choose
#	the character's second realm of magic.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Realm2 oop {

	global NSBirth

	# The "birth info realm_name" command returns a list of magic realm names which the
	# user can choose. This list always includes "None". If it only includes
	# 1 or 2 choices, the user really doesn't have a choice, in which case this screen
	# is not presented.
	set realms [birth info realm_name]
	if {[llength $realms] <= 2} {

		# Choose the realm for the user. This will either be None or some other.
		set NSBirth($oop,realm2) [lindex $realms end]

		# Skip this screen
		return 1
	}

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Choose your character's second realm of magic"
	$win.info configure -text "The realm of magic will determine which spells your character can learn."

	set frame $win.content
	set frame $frame.frameList
	frame $frame \
		-borderwidth 2 -relief sunken
	set list $frame.list
	listbox $list \
		-width 20 -height 8 -yscrollcommand "$frame.yscroll set" \
		-background White -borderwidth 0 -highlightthickness 0
	scrollbar $frame.yscroll \
		-orient vertical -command "$list yview"

	bind $list <Double-Button-1> \
		"tkButtonInvoke $win.buttons.next"
	bind $list <ButtonRelease-1> "NSBirth::SelectionChanged $oop realm2"

	set frame $win.content.frameText
	frame $frame \
		-borderwidth 2 -relief sunken	
	set text $frame.text
	text $text \
		-width 40 -height 8 -yscrollcommand "$frame.yscroll set" \
		-borderwidth 0 -wrap word -cursor {}
	scrollbar $frame.yscroll \
		-orient vertical -command "$text yview"

	set frame $win.content.frameList
	pack $frame \
		-side left -pady 5 -fill y
	pack $list \
		-side left -fill y
	pack $frame.yscroll \
		-side left -fill y

	pack [frame $win.content.filler1 -width 5 -borderwidth 0] \
		-side left -fill y

	set frame $win.content.frameText
	pack $frame \
		-side left -pady 5 -fill both
	pack $text \
		-side left -fill both
	pack $frame.yscroll \
		-side left -fill y

	set NSBirth($oop,detail) {}
	set NSBirth($oop,value) {}
	foreach realm [lrange [birth info realm_name] 1 end] {
		InfoListAppend $oop $realm $realm $realm
	}

	set row [lsearch [$list get 0 end] $NSBirth($oop,realm2)]
	$list selection set $row
	$list see $row
	SelectionChanged $oop realm2

	return 0
}

# NSBirth::InitScreen_Options --
#
#	Creates the display in the Birth Window to let the user choose
#	options that control character creation.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Options oop {

	global NSBirth

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Set character creation options"
	$win.info configure -text "These options control various aspects\
		of the character creation process. These options can only be\
		changed here, not after your character is generated."

	set frame $win.content
	checkbutton $frame.maximize \
		-text "Using 'maximize' mode makes the game harder at the\
		start, but often makes it easier to win" \
		-variable NSBirth($oop,maximize) -wraplength 300 \
		-justify left -borderwidth 0
	checkbutton $frame.preserve \
		-text "Using 'preserve' mode makes it difficult to 'lose'\
		artifacts" -variable NSBirth($oop,preserve) -wraplength 300 \
		-justify left -borderwidth 0
	checkbutton $frame.autoroll \
		-text "The 'auto-roller' allows you to specify certain\
		'minimal' stats, but be warned that the various stats may not\
		be independant!" -variable NSBirth($oop,autoroll) \
		-wraplength 300 -justify left -borderwidth 0
	checkbutton $frame.wilderness \
		-text "'Wilderness' mode enables the extended wilderness of ZAngband" \
		-variable NSBirth($oop,wilderness) \
		-wraplength 300 -justify left -borderwidth 0

	pack $frame.maximize \
		-side top -anchor w -padx 25
	pack $frame.preserve \
		-side top -anchor w -padx 25
	pack $frame.autoroll \
		-side top -anchor w -padx 25
	pack $frame.wilderness \
		-side top -anchor w -padx 25

	return 0
}

# NSBirth::InitScreen_Quest --
#
#	Creates the display in the Birth Window to let the user enter
#	the number of desired optional quests.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_Quest oop {

	global NSBirth

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Enter number of quests"
	$win.info configure -text "Enter the number of quests you'd like your\
		character to complete in addition to the two required quests\
		(Oberon and the Serpent of Chaos). If you do not want any\
		additional quests, enter 0."

	set frame $win.content.quest
	frame $frame \
		-borderwidth 0
	entry $frame.num \
		-width 4 -font {Courier 9} -textvariable NSBirth($oop,max_quest)
	label $frame.max \
		-text "(Max of [birth info max_quest])" \
		-font {Courier 9}

	message $win.content.labelHard \
		-text "Using 'hard quests' mode makes the random quests harder,\
			because you have to kill all monsters at the same visit to the\
			quest level. If you leave the level while some quest monsters\
			are still alive, then all killed quest monsters are revived on\
			your next visit to this level." -width 350
	checkbutton $win.content.checkHard \
		-text "Use hard quests" \
		-variable NSBirth($oop,hard_quests) -borderwidth 0

	pack $frame \
		-side top -anchor w -padx 50
	pack $frame.num \
		-side left -expand no
	pack $frame.max \
		-side left -expand no
	pack [frame $win.content.filler -borderwidth 0 -height 10] \
		-side top
	pack $win.content.labelHard \
		-side top -anchor w -padx 0 -pady 0
	pack $win.content.checkHard \
		-side top -anchor w -padx 50

	$frame.num selection range 0 end
	$frame.num icursor end
	focus $frame.num

	return 0
}

# NSBirth::Validate_Quest --
#
#	Make sure the user entered a valid number of quests.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Validate_Quest oop {

	global NSBirth

	set win $NSBirth($oop,win)

	set number $NSBirth($oop,max_quest)
	if {[string length $number]} {
		if {![regsub -all \[^0-9\] $number "" number]} {
			if {$number >= 0 && $number <= [birth info max_quest]} {
				return 1
			}
		}
	}

	# Failed
	set entry $win.content.quest.num
	$entry delete 0 end
	$entry insert 0 20
	$entry selection range 0 end
	$entry icursor end
	focus $entry
	bell
	return 0
}

# NSBirth::InitScreen_AutoRoll --
#
#	Creates the display in the Birth Window to let the user enter
#	minimum stats for the autoroller
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_AutoRoll oop {

	global NSBirth

	set win $NSBirth($oop,win)

	$win.prompt configure 	-text "Enter minimum desired stats for the 'autoroller'"
	$win.info configure -text "The autoroller will attempt create a character\
		with stats that are at least as high as you enter here.  It is\
		possible the autoroller will be unable to roll a character if you\
		set the minimums too high. You can leave any or all of the stats\
		empty."

	set data {
		"    Strength:" strength
		"Intelligence:" intelligence
		"      Wisdom:" wisdom
		"   Dexterity:" dexterity
		"Constitution:" constitution
		"    Charisma:" charisma
	}

	set frame $win.content.stats
	frame $frame \
		-borderwidth 0

	foreach {title stat} $data {

		set frame $win.content.stats.$stat
		set label $frame.$stat
		set entry $frame.${stat}_entry

		frame $frame \
			-borderwidth 0
		label $label \
			-text $title -font {Courier 9}
		entry $entry \
			-width 5 -font {Courier 9}
		label $frame.max \
			-text "(Max of [cnv_stat [birth stat $stat max]])" \
			-font {Courier 9}

		pack $frame \
			-side top -expand yes -fill x -pady 2 -anchor w
		pack $label \
			-side left -expand no
		pack $entry \
			-side left -expand no -padx 4
		pack $frame.max \
			-side left -expand no
	}

	pack $win.content.stats \
		-side top -anchor c

	focus $win.content.stats.strength.strength_entry

	return 0
}

# NSBirth::ValidateAutoStats --
#
#	Extract the user's entered stats from the autroller display.
#	Validate that the stats are not greater than the maximum.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	If the stats are valid, the BirthPriv(stat_limit,STAT) array
#	is set, and 1 is returned. If any stat is above the  maximum then 0
#	is returned. Any or all of the stats can be left empty.

proc ValidateAutoStats oop {

	global NSBirth
	variable BirthPriv

	set win $NSBirth($oop,win)

	foreach stat {strength intelligence wisdom dexterity constitution charisma} {

		# Default to no minimum requested
		set BirthPriv(stat_limit,$stat) 0

		set frame $win.content.stats.$stat
		set entry $frame.${stat}_entry
		set string [$entry get]
		
		# No value entered (that's allowed)
		if {$string == {}} continue

		# Split string into value and bonus
		set partList [split $string /]
	
		# Get number of parts (should be 1 or 2)
		set partCnt [llength $partList]

		# Error
		if {$partCnt > 2} {
			bell ; focus $entry ; $entry selection range 0 end
			return 0
		}

		# Attempt to extract value and bonus. Catch the operations
		# in case the value/bonus are not integers.
		if {[catch {

			# Value before the /
			set value [lindex $partList 0]

			# Bonus after the / (optional)
			if {$partCnt == 2} {
				incr value [lindex $partList 1]
			}

			# Validate value < limit
			if {$value > [birth stat $stat max]} {
				bell ; focus $entry ; $entry selection range 0 end
				return 0
			}

		}]} {

			# Invalid format
			bell ; focus $entry ; $entry selection range 0 end
			return 0
		}

		# Save the valid minimum
		set BirthPriv(stat_limit,$stat) $value
	}

	# Success!
	return 1
}

# NSBirth::InitScreen_RollOne --
#
#	Hides the Birth Window, shows the Player Window, and then
#	rolls up the first character.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc InitScreen_RollOne oop {

	global NSBirth
	global NSPlayer
	variable BirthPriv

	set playerId $BirthPriv(playerId)
	set win $NSPlayer($playerId,win)
	WindowPosition $win 2 3
	WindowBringToFront $win

	wm withdraw $NSBirth($oop,win)

	# One-time autoroller setup
	set BirthPriv(auto_round) 0
	set BirthPriv(last_round) 0

	# Reset the "success" counter
	foreach stat {strength intelligence wisdom dexterity constitution charisma} {
		set BirthPriv(stat_match,$stat) 0
	}
	set BirthPriv(autoroll) $NSBirth($oop,autoroll)

	Configure $oop Roll

	return 0
}

# NSBirth::RollOne --
#
#	Randomly generate a character. If using the auto-roller, then
#	loop until an acceptable character is generated, or the user
#	aborts.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc RollOne oop {

	variable BirthPriv

	if $BirthPriv(autoroll) {

		# Note when we started
		set BirthPriv(last_round) $BirthPriv(auto_round)

		# User can cancel
		set BirthPriv(userAbort) 0

		# Clear the display
		NSPlayer::WipeInfo $BirthPriv(playerId)

		# Show the progress window
		wm deiconify .autoprogress
		focus .autoprogress

	} else {

		# Get a new character
		birth get_stats
	}

	# Auto-roll
	while $BirthPriv(autoroll) {

		set accept 1

		# Get a new character
		birth get_stats

		# Advance the round
		incr BirthPriv(auto_round)

		# Hack -- Prevent overflow
		if {$BirthPriv(auto_round) >= 1000000} break

		# Check and count acceptable stats
		foreach stat {strength intelligence wisdom dexterity constitution charisma} {

			# This stat is okay
			if {[birth stat $stat] >= $BirthPriv(stat_limit,$stat)} {
				incr BirthPriv(stat_match,$stat)

			# This stat is not okay
			} else {
				set accept 0
			}
		}

		# Break if "happy"
		if $accept break

		# Take note every 25 rolls
		set flag [expr !($BirthPriv(auto_round) % 25)]

		# Update display occasionally
		if {$flag || ($BirthPriv(auto_round) < $BirthPriv(last_round) + 100)} {

			# Dump stats
			AutoProgress $oop

			# Delay 1/10 second
			if $flag {after 100}

			# Draw, and check for events
			update

			# Check for a keypress
			if $BirthPriv(userAbort) break
		}
	}

	if $BirthPriv(autoroll) {

		# Hide the progress window
		wm withdraw .autoprogress
	}

	# Generate other player info
	birth get_player

	# Set player-info display...
	NSPlayer::SetInfo $BirthPriv(playerId)

	# ...but clear the name
	$BirthPriv(canvas) itemconfigure name -text ""
}

# NSBirth::AutoProgress --
#
#	Display progress of the autoroller.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc AutoProgress oop {

	global NSPlayer
	global Windows
	variable BirthPriv

	set win .autoprogress

	foreach stat {strength intelligence wisdom dexterity constitution charisma} {

		set frame $win.stats.$stat
		set value $frame.value
		set match $frame.match

		# Put the stat
		$value configure -text [cnv_stat [birth stat $stat]]

		# Put the percent
		if $BirthPriv(stat_match,$stat) {

			set p [expr 1000 * $BirthPriv(stat_match,$stat) / $BirthPriv(auto_round)]
			set buf "[expr $p / 10].[expr $p % 10]%"
			$match configure -text $buf

		# Never happened
		} else {
			$match configure -text (NONE)
		}
	}

	# Display round
	$win.autoround configure -text "Round: $BirthPriv(auto_round)"

}

# NSBirth::BirthHack --
#
#	The "birth" command requires that each stage of character creation
#	be completed in order. Because this display allows the user to go
#	forwards and backwards, we must *reset* the "birth" stage and then
#	artificially move it forward to the correct stage, by supplying
#	values for the stages already gained.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc BirthHack oop {

	global NSBirth

	birth reset
	birth name ""

	foreach screen {Gender Race Class Realm1 Realm2 Options Quest AutoRoll RollOne} {
		if {![string compare $screen $NSBirth($oop,screen)]} break
		switch $screen {	
			Gender {birth gender $NSBirth($oop,gender)}
			Race {birth race $NSBirth($oop,race)}
			Class {birth class $NSBirth($oop,class)}
			Realm1 {birth realm1 $NSBirth($oop,realm1)}
			Realm2 {birth realm2 $NSBirth($oop,realm2)}
			Options {
				birth option maximize $NSBirth($oop,maximize)
				birth option preserve $NSBirth($oop,preserve)
				birth option wilderness $NSBirth($oop,wilderness)
			}
			Quest {
				birth option hard_quests $NSBirth($oop,hard_quests)
				birth max_quest $NSBirth($oop,max_quest)
			}
			AutoRoll {}
			RollOne {}
		}
	}
}

# NSBirth::GetName --
#
#	Let's the user enter a name for the character.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc GetName oop {

	variable BirthPriv

	set playerId $BirthPriv(playerId)
	set canvas $BirthPriv(canvas)

	# Prompt

	# Get a character name from the user. The default is
	# the current name, because the character might be from
	# an dead character's file.
	set name [NSPlayer::GetName $playerId [angband player name] 0]

	# Set character name
	birth name $name

	# Set name in player-info window
	$canvas itemconfigure name -text $name -fill turquoise2
}

# NSBirth::Next --
#
#	Goes to the next screen in the Birth Window.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Next oop {

	global NSBirth

	set win $NSBirth($oop,win)

	set nextScreen ""

	switch $NSBirth($oop,screen) {

		Gender {set nextScreen Race}
		Race {set nextScreen Class}
		Class {set nextScreen Realm1}
		Realm1 {set nextScreen Realm2}
		Realm2 {set nextScreen Options}
		Options {set nextScreen Quest}
		Quest {
			if {[Validate_Quest $oop]} {
				if $NSBirth($oop,autoroll) {
					set nextScreen AutoRoll
				} else {
					set nextScreen RollOne
				}
			}
		}
		AutoRoll {
			if {[ValidateAutoStats $oop]} {
				set nextScreen RollOne
			}
		}
		RollOne {}
	}

	if {[string compare $nextScreen ""]} {
		eval destroy [winfo children $win.content]
		set NSBirth($oop,screen) $nextScreen
		BirthHack $oop
		if {[InitScreen_$nextScreen $oop]} {
			Next $oop
		}
		
		# Not on the first screen, so user can go back
		$win.buttons.back configure -state normal
	}
}

# NSBirth::Back --
#
#	Goes to the previous screen in the Birth Window.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Back oop {

	global NSBirth

	set win $NSBirth($oop,win)

	set prevScreen ""

	switch $NSBirth($oop,screen) {

		Race {set prevScreen Gender}
		Class {set prevScreen Race}
		Realm1 {set prevScreen Class}
		Realm2 {set prevScreen Realm1}
		Options {set prevScreen Realm2}
		Quest {set prevScreen Options}
		AutoRoll {set prevScreen Quest}
		RollOne {
			if $NSBirth($oop,autoroll) {
				set prevScreen AutoRoll
			} else {
				set prevScreen Quest
			}
		}
	}

	if {[string compare $prevScreen ""]} {
		eval destroy [winfo children $win.content]
		set NSBirth($oop,screen) $prevScreen
		BirthHack $oop
		if {[InitScreen_$prevScreen $oop]} {
			Back $oop
		}

		# On the first screen, so user can't go back
		if {$NSBirth($oop,screen) == "Gender"} {
			$win.buttons.back configure -state disabled
		}
	}
}

# NSBirth::Configure --
#
#	Manages the flow of control after the Player Window is displayed.
#
# Arguments:
#	arg1					about arg1
#
# Results:
#	What happened.

proc Configure {oop stage} {

	global NSBirth
	global NSPlayer
	variable BirthPriv

	set playerId $BirthPriv(playerId)
	set win $NSPlayer($playerId,win)
	set canvas $BirthPriv(canvas)

	switch -- $stage {
		StartOver {
			birth reset
			set NSBirth($oop,screen) Gender
			InitScreen_Gender $oop
			wm deiconify $NSBirth($oop,win)
			focus $NSBirth($oop,win)
			wm withdraw $win
		}
		Roll {
			$BirthPriv(canvas) itemconfigure prompt -text "Rolling..."
			bind $win <s> {}
			bind $win <r> {}
			bind $win <Escape> {}

			RollOne $oop

			$canvas itemconfigure prompt \
				-text "Type 's' to restart, 'r' to reroll, Escape to accept"
			bind $win <s> "NSBirth::Configure $oop StartOver"
			bind $win <r> "NSBirth::Configure $oop Roll"
			bind $win <Escape> "NSBirth::Configure $oop Name"
		}
		Name {
			$canvas itemconfigure prompt \
				-text "Enter a name (hit Enter when done):"
			bind $win <s> {}
			bind $win <r> {}
			bind $win <Escape> {}

			GetName $oop

			$canvas itemconfigure prompt \
				-text "Type 's' to restart, Escape to accept"
			bind $win <s> "NSBirth::Configure $oop StartOver"
			bind $win <Escape> "NSBirth::Configure $oop Accept"
		}
		Accept {

			# Cleanup at the C level
			birth done

			# Read a dead-character's save file
			if {[info exists ::AngbandPriv(load,win)]} {
				WindowBringToFront $::AngbandPriv(load,win)

			# Hack -- Initialize the Load Window now, so when the
			# Player Window is destroyed, the application still has
			# an active front window (otherwise the application will
			# be swapped into the background.
			} else {
				angband_load init
			}

			# Destroy player-info display
			destroy $win
			NSObject::Delete NSPlayer $playerId
			namespace delete ::NSPlayer
			unset ::Windows(player,win)

			# Clean up
			destroy .autoprogress
			destroy $NSBirth($oop,win)
			NSWindowManager::UnregisterWindow player
			NSObject::Delete NSBirth $oop
			namespace delete ::NSBirth

			# Hack -- Feed the Term to continue at C level
			angband keypress " "
		}
	}
}

# namespace eval NSBirth
}

# in main-window.tcl also!
proc cnv_stat val {

	# Above 18
	if {$val > 18} {

		set bonus [expr $val - 18];
		if {$bonus >= 10} {
			return 18/$bonus
		}
		return 18/0$bonus

	# From 3 to 18
	} else {

		return $val
	}
}

# in main-window.tcl also!
proc cnv_stat_disp val {

	# Above 18
	if {$val > 18} {

		set bonus [expr $val - 18];
		if {$bonus >= 220} {
			return 18/***
		} elseif {$bonus >= 10} {
			return 18/$bonus
		}
		return 18/0$bonus

	# From 3 to 18
	} else {

		return $val
	}
}
