The read_scroll switch becomes gameData.readHandlers, indexed by ScrollKind; the five identify scrolls share one handler. The magic mapping cell logic is extracted into revealSpot. Effect order and RNG call sequence unchanged.
331 lines
6.9 KiB
Go
331 lines
6.9 KiB
Go
package game
|
|
|
|
// scrolls.c — read a scroll and let it happen.
|
|
|
|
// readScroll reads a scroll from the pack and does the appropriate thing
|
|
// (scrolls.c read_scroll).
|
|
func (g *RogueGame) readScroll() {
|
|
p := &g.Player
|
|
|
|
obj, ok := g.promptPackItem("read", KindScroll)
|
|
if !ok {
|
|
return
|
|
}
|
|
|
|
if obj.Kind != KindScroll {
|
|
if !g.Options.Terse {
|
|
g.msg("there is nothing on it to read")
|
|
} else {
|
|
g.msg("nothing to read")
|
|
}
|
|
|
|
return
|
|
}
|
|
// Calculate the effect it has on the poor guy.
|
|
if obj == p.CurWeapon {
|
|
p.CurWeapon = nil
|
|
}
|
|
// Get rid of the thing
|
|
g.leavePack(obj, false, false)
|
|
|
|
if h := g.data.readHandlers[obj.ScrollKind()]; h != nil {
|
|
h(g, obj)
|
|
}
|
|
|
|
g.look(true) // put the result of the scroll on the screen
|
|
g.status()
|
|
|
|
g.callIt(&g.Items.Scrolls[obj.Which])
|
|
}
|
|
|
|
// The per-scroll effect handlers, dispatched through
|
|
// gameData.readHandlers. Each is one case of the C read_scroll switch.
|
|
|
|
func (g *RogueGame) readMonsterConfusion(*Object) {
|
|
// Scroll of monster confusion. Give him that power.
|
|
g.Player.Flags.Set(CanConfuse)
|
|
g.msg("your hands begin to glow %s", g.pickColor("red"))
|
|
}
|
|
|
|
func (g *RogueGame) readEnchantArmor(*Object) {
|
|
p := &g.Player
|
|
if p.CurArmor != nil {
|
|
p.CurArmor.ArmorClass--
|
|
p.CurArmor.Flags.Clear(Cursed)
|
|
g.msg("your armor glows %s for a moment", g.pickColor("silver"))
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readHoldMonster(*Object) {
|
|
// Hold monster scroll. Stop all monsters within two spaces from
|
|
// chasing after the hero.
|
|
p := &g.Player
|
|
held := 0
|
|
|
|
for x := p.Pos.X - 2; x <= p.Pos.X+2; x++ {
|
|
if x < 0 || x >= NumCols {
|
|
continue
|
|
}
|
|
|
|
for y := p.Pos.Y - 2; y <= p.Pos.Y+2; y++ {
|
|
if y < 0 || y > NumLines-1 {
|
|
continue
|
|
}
|
|
|
|
if mp := g.Level.MonsterAt(y, x); mp != nil && mp.On(Awake) {
|
|
mp.Flags.Clear(Awake)
|
|
mp.Flags.Set(Held)
|
|
|
|
held++
|
|
}
|
|
}
|
|
}
|
|
|
|
if held > 0 {
|
|
g.addmsgf("the monster")
|
|
|
|
if held > 1 {
|
|
g.addmsgf("s around you")
|
|
}
|
|
|
|
g.addmsgf(" freeze")
|
|
|
|
if held == 1 {
|
|
g.addmsgf("s")
|
|
}
|
|
|
|
g.endmsg()
|
|
g.Items.Scrolls[ScrollHoldMonster].Know = true
|
|
} else {
|
|
g.msg("you feel a strange sense of loss")
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readSleep(*Object) {
|
|
// Scroll which makes you fall asleep
|
|
g.Items.Scrolls[ScrollSleep].Know = true
|
|
g.NoCommand += g.rnd(g.spread(5)) + 4 // SLEEPTIME
|
|
|
|
g.Player.Flags.Clear(Awake)
|
|
g.msg("you fall asleep")
|
|
}
|
|
|
|
func (g *RogueGame) readCreateMonster(*Object) {
|
|
// Create a monster: first look in a circle around him, next try
|
|
// his room, otherwise give up
|
|
p := &g.Player
|
|
i := 0
|
|
|
|
var mp Coord
|
|
|
|
for y := p.Pos.Y - 1; y <= p.Pos.Y+1; y++ {
|
|
for x := p.Pos.X - 1; x <= p.Pos.X+1; x++ {
|
|
// Don't put a monster on top of the player.
|
|
if y == p.Pos.Y && x == p.Pos.X {
|
|
continue
|
|
}
|
|
// Or anything else nasty
|
|
if ch := g.Level.VisibleChar(y, x); stepOk(ch) {
|
|
if ch == Scroll {
|
|
if fo := g.Level.ObjectAt(y, x); fo != nil && fo.ScrollKind() == ScrollScareMonster {
|
|
continue
|
|
}
|
|
}
|
|
|
|
if i++; g.rnd(i) == 0 {
|
|
mp = Coord{Y: y, X: x}
|
|
}
|
|
}
|
|
}
|
|
}
|
|
|
|
if i == 0 {
|
|
g.msg("you hear a faint cry of anguish in the distance")
|
|
} else {
|
|
tp := &Monster{}
|
|
g.newMonster(tp, g.randMonster(false), mp)
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readIdentify(obj *Object) {
|
|
// Identify, let him figure something out
|
|
g.Items.Scrolls[obj.Which].Know = true
|
|
g.msg("this scroll is an %s scroll", g.Items.Scrolls[obj.Which].Name)
|
|
g.whatis(true, g.data.idType[obj.ScrollKind()])
|
|
}
|
|
|
|
func (g *RogueGame) readMagicMapping(*Object) {
|
|
// Scroll of magic mapping.
|
|
g.Items.Scrolls[ScrollMagicMapping].Know = true
|
|
g.msg("oh, now this scroll has a map on it")
|
|
// take all the things we want to keep hidden out of the window
|
|
for y := 1; y < NumLines-1; y++ {
|
|
for x := range NumCols {
|
|
g.revealSpot(y, x)
|
|
}
|
|
}
|
|
}
|
|
|
|
// revealSpot uncovers one map cell for magic mapping: secret doors and
|
|
// passages become real, hidden traps show, and the visible character is
|
|
// drawn (the loop body of the C SCR_MAP case).
|
|
func (g *RogueGame) revealSpot(y, x int) {
|
|
pp := g.Level.At(y, x)
|
|
ch := pp.Ch
|
|
pass := false
|
|
|
|
switch ch {
|
|
case Door, Stairs:
|
|
case '-', '|':
|
|
if !pp.Flags.Has(FReal) {
|
|
ch = Door
|
|
pp.Ch = Door
|
|
pp.Flags.Set(FReal)
|
|
}
|
|
case ' ':
|
|
if pp.Flags.Has(FReal) {
|
|
// def: hidden things in walls stay hidden
|
|
if pp.Flags.Has(FPassage) {
|
|
pass = true
|
|
} else {
|
|
ch = ' '
|
|
}
|
|
} else {
|
|
pp.Flags.Set(FReal)
|
|
pp.Ch = Passage
|
|
pass = true
|
|
}
|
|
case Passage:
|
|
pass = true
|
|
case Floor:
|
|
if pp.Flags.Has(FReal) {
|
|
ch = ' '
|
|
} else {
|
|
ch = Trap
|
|
pp.Ch = Trap
|
|
pp.Flags.Set(FSeen | FReal)
|
|
}
|
|
default:
|
|
if pp.Flags.Has(FPassage) {
|
|
pass = true
|
|
} else {
|
|
ch = ' '
|
|
}
|
|
}
|
|
|
|
if pass {
|
|
if !pp.Flags.Has(FReal) {
|
|
pp.Ch = Passage
|
|
}
|
|
|
|
pp.Flags.Set(FSeen | FReal)
|
|
|
|
ch = Passage
|
|
}
|
|
|
|
if ch != ' ' {
|
|
if tp := pp.Monst; tp != nil {
|
|
tp.OldCh = ch
|
|
if !g.Player.On(SenseMonsters) {
|
|
g.mvaddch(y, x, ch)
|
|
}
|
|
} else {
|
|
g.mvaddch(y, x, ch)
|
|
}
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readFoodDetection(*Object) {
|
|
// Food detection
|
|
found := false
|
|
|
|
g.scr.Hw.Clear()
|
|
|
|
for _, fo := range g.Level.Objects {
|
|
if fo.Kind == KindFood {
|
|
found = true
|
|
|
|
g.scr.Hw.MvAddCh(fo.Pos.Y, fo.Pos.X, Food)
|
|
}
|
|
}
|
|
|
|
if found {
|
|
g.Items.Scrolls[ScrollFoodDetection].Know = true
|
|
g.showWin("Your nose tingles and you smell food.--More--")
|
|
} else {
|
|
g.msg("your nose tingles")
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readTeleportation(*Object) {
|
|
// Scroll of teleportation: make him disappear and reappear
|
|
p := &g.Player
|
|
curRoom := p.Room
|
|
|
|
g.teleport()
|
|
|
|
if curRoom != p.Room {
|
|
g.Items.Scrolls[ScrollTeleportation].Know = true
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readEnchantWeapon(*Object) {
|
|
p := &g.Player
|
|
if p.CurWeapon == nil || p.CurWeapon.Kind != KindWeapon {
|
|
g.msg("you feel a strange sense of loss")
|
|
} else {
|
|
p.CurWeapon.Flags.Clear(Cursed)
|
|
|
|
if g.rnd(2) == 0 {
|
|
p.CurWeapon.HPlus++
|
|
} else {
|
|
p.CurWeapon.DPlus++
|
|
}
|
|
|
|
g.msg("your %s glows %s for a moment",
|
|
g.Items.Weapons[p.CurWeapon.Which].Name, g.pickColor("blue"))
|
|
}
|
|
}
|
|
|
|
func (g *RogueGame) readScareMonster(*Object) {
|
|
// Reading it is a mistake and produces laughter at her poor boo
|
|
// boo.
|
|
g.msg("you hear maniacal laughter in the distance")
|
|
}
|
|
|
|
func (g *RogueGame) readRemoveCurse(*Object) {
|
|
p := &g.Player
|
|
|
|
uncurse(p.CurArmor)
|
|
uncurse(p.CurWeapon)
|
|
uncurse(p.CurRing[Left])
|
|
uncurse(p.CurRing[Right])
|
|
g.msg("%s", g.chooseStr("you feel in touch with the Universal Onenes",
|
|
"you feel as if somebody is watching over you"))
|
|
}
|
|
|
|
func (g *RogueGame) readAggravateMonsters(*Object) {
|
|
// This scroll aggravates all the monsters on the current level
|
|
// and sets them running towards the hero
|
|
g.aggravate()
|
|
g.msg("you hear a high pitched humming noise")
|
|
}
|
|
|
|
func (g *RogueGame) readProtectArmor(*Object) {
|
|
p := &g.Player
|
|
if p.CurArmor != nil {
|
|
p.CurArmor.Flags.Set(Protected)
|
|
g.msg("your armor is covered by a shimmering %s shield",
|
|
g.pickColor("gold"))
|
|
} else {
|
|
g.msg("you feel a strange sense of loss")
|
|
}
|
|
}
|
|
|
|
// uncurse uncurses an item (scrolls.c uncurse).
|
|
func uncurse(obj *Object) {
|
|
if obj != nil {
|
|
obj.Flags.Clear(Cursed)
|
|
}
|
|
}
|