Decompose remaining effects-file hot spots (refactor step 7)
drain gains drainReaches; zapSpeed gains hasteTarget/slowTarget; readHoldMonster gains holdMonstersNear; readCreateMonster gains createMonsterSpot; revealSpot splits into revealChar/revealWall/ revealSolid/revealFloor; turnSee gains showSensed. potions.go, scrolls.go, and sticks.go are complexity-clean. Behavior and RNG call order unchanged.
This commit is contained in:
@@ -298,22 +298,8 @@ func (g *RogueGame) turnSee(turnOff bool) bool {
|
|||||||
if !canSee {
|
if !canSee {
|
||||||
g.addch(mp.OldCh)
|
g.addch(mp.OldCh)
|
||||||
}
|
}
|
||||||
} else {
|
} else if g.showSensed(mp, canSee) {
|
||||||
if !canSee {
|
addNew = true
|
||||||
g.standout()
|
|
||||||
}
|
|
||||||
|
|
||||||
if !g.Player.On(Hallucinating) {
|
|
||||||
g.addch(mp.Type)
|
|
||||||
} else {
|
|
||||||
g.addch(g.randomMonsterLetter())
|
|
||||||
}
|
|
||||||
|
|
||||||
if !canSee {
|
|
||||||
g.standend()
|
|
||||||
|
|
||||||
addNew = true
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -326,6 +312,29 @@ func (g *RogueGame) turnSee(turnOff bool) bool {
|
|||||||
return addNew
|
return addNew
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// showSensed draws one monster for monster sense, standout when it is
|
||||||
|
// otherwise invisible; it reports whether the monster was newly revealed
|
||||||
|
// (the turn-on arm of the C turn_see loop).
|
||||||
|
func (g *RogueGame) showSensed(mp *Monster, canSee bool) bool {
|
||||||
|
if !canSee {
|
||||||
|
g.standout()
|
||||||
|
}
|
||||||
|
|
||||||
|
if !g.Player.On(Hallucinating) {
|
||||||
|
g.addch(mp.Type)
|
||||||
|
} else {
|
||||||
|
g.addch(g.randomMonsterLetter())
|
||||||
|
}
|
||||||
|
|
||||||
|
if !canSee {
|
||||||
|
g.standend()
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
// seenStairs reports whether the player has seen the stairs (potions.c
|
// seenStairs reports whether the player has seen the stairs (potions.c
|
||||||
// seen_stairs).
|
// seen_stairs).
|
||||||
func (g *RogueGame) seenStairs() bool {
|
func (g *RogueGame) seenStairs() bool {
|
||||||
|
|||||||
163
game/scrolls.go
163
game/scrolls.go
@@ -59,6 +59,31 @@ func (g *RogueGame) readEnchantArmor(*Object) {
|
|||||||
func (g *RogueGame) readHoldMonster(*Object) {
|
func (g *RogueGame) readHoldMonster(*Object) {
|
||||||
// Hold monster scroll. Stop all monsters within two spaces from
|
// Hold monster scroll. Stop all monsters within two spaces from
|
||||||
// chasing after the hero.
|
// chasing after the hero.
|
||||||
|
held := g.holdMonstersNear()
|
||||||
|
|
||||||
|
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")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// holdMonstersNear freezes every awake monster within two spaces of the
|
||||||
|
// hero and reports how many froze (the scan of the C S_HOLD case).
|
||||||
|
func (g *RogueGame) holdMonstersNear() int {
|
||||||
p := &g.Player
|
p := &g.Player
|
||||||
held := 0
|
held := 0
|
||||||
|
|
||||||
@@ -81,24 +106,7 @@ func (g *RogueGame) readHoldMonster(*Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if held > 0 {
|
return held
|
||||||
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) {
|
func (g *RogueGame) readSleep(*Object) {
|
||||||
@@ -113,6 +121,19 @@ func (g *RogueGame) readSleep(*Object) {
|
|||||||
func (g *RogueGame) readCreateMonster(*Object) {
|
func (g *RogueGame) readCreateMonster(*Object) {
|
||||||
// Create a monster: first look in a circle around him, next try
|
// Create a monster: first look in a circle around him, next try
|
||||||
// his room, otherwise give up
|
// his room, otherwise give up
|
||||||
|
mp, ok := g.createMonsterSpot()
|
||||||
|
if !ok {
|
||||||
|
g.msg("you hear a faint cry of anguish in the distance")
|
||||||
|
} else {
|
||||||
|
tp := &Monster{}
|
||||||
|
g.newMonster(tp, g.randMonster(false), mp)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// createMonsterSpot reservoir-samples a legal spot around the hero for a
|
||||||
|
// created monster; ok is false when every neighbor is blocked (the scan
|
||||||
|
// of the C S_CREATE case).
|
||||||
|
func (g *RogueGame) createMonsterSpot() (Coord, bool) {
|
||||||
p := &g.Player
|
p := &g.Player
|
||||||
i := 0
|
i := 0
|
||||||
|
|
||||||
@@ -139,12 +160,7 @@ func (g *RogueGame) readCreateMonster(*Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
if i == 0 {
|
return mp, 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) {
|
func (g *RogueGame) readIdentify(obj *Object) {
|
||||||
@@ -166,45 +182,41 @@ func (g *RogueGame) readMagicMapping(*Object) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// revealSpot uncovers one map cell for magic mapping: secret doors and
|
// revealSpot uncovers one map cell for magic mapping and draws it (the
|
||||||
// passages become real, hidden traps show, and the visible character is
|
// loop body of the C SCR_MAP case).
|
||||||
// drawn (the loop body of the C SCR_MAP case).
|
|
||||||
func (g *RogueGame) revealSpot(y, x int) {
|
func (g *RogueGame) revealSpot(y, x int) {
|
||||||
pp := g.Level.At(y, x)
|
pp := g.Level.At(y, x)
|
||||||
|
|
||||||
|
ch := revealChar(pp)
|
||||||
|
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)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// revealChar decides what magic mapping shows at a cell, making secret
|
||||||
|
// doors, hidden passages, and hidden traps real as a side effect; ' '
|
||||||
|
// means show nothing (the switch of the C SCR_MAP loop).
|
||||||
|
func revealChar(pp *Place) byte {
|
||||||
ch := pp.Ch
|
ch := pp.Ch
|
||||||
pass := false
|
pass := false
|
||||||
|
|
||||||
switch ch {
|
switch ch {
|
||||||
case Door, Stairs:
|
case Door, Stairs:
|
||||||
case '-', '|':
|
case '-', '|':
|
||||||
if !pp.Flags.Has(FReal) {
|
ch = revealWall(pp)
|
||||||
ch = Door
|
|
||||||
pp.Ch = Door
|
|
||||||
pp.Flags.Set(FReal)
|
|
||||||
}
|
|
||||||
case ' ':
|
case ' ':
|
||||||
if pp.Flags.Has(FReal) {
|
pass = revealSolid(pp)
|
||||||
// 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:
|
case Passage:
|
||||||
pass = true
|
pass = true
|
||||||
case Floor:
|
case Floor:
|
||||||
if pp.Flags.Has(FReal) {
|
ch = revealFloor(pp)
|
||||||
ch = ' '
|
|
||||||
} else {
|
|
||||||
ch = Trap
|
|
||||||
pp.Ch = Trap
|
|
||||||
pp.Flags.Set(FSeen | FReal)
|
|
||||||
}
|
|
||||||
default:
|
default:
|
||||||
if pp.Flags.Has(FPassage) {
|
if pp.Flags.Has(FPassage) {
|
||||||
pass = true
|
pass = true
|
||||||
@@ -223,16 +235,47 @@ func (g *RogueGame) revealSpot(y, x int) {
|
|||||||
ch = Passage
|
ch = Passage
|
||||||
}
|
}
|
||||||
|
|
||||||
if ch != ' ' {
|
return ch
|
||||||
if tp := pp.Monst; tp != nil {
|
}
|
||||||
tp.OldCh = ch
|
|
||||||
if !g.Player.On(SenseMonsters) {
|
// revealWall handles a wall cell for magic mapping: a secret door
|
||||||
g.mvaddch(y, x, ch)
|
// becomes a real door (the '-'/'|' arm).
|
||||||
}
|
func revealWall(pp *Place) byte {
|
||||||
} else {
|
if !pp.Flags.Has(FReal) {
|
||||||
g.mvaddch(y, x, ch)
|
pp.Ch = Door
|
||||||
}
|
pp.Flags.Set(FReal)
|
||||||
|
|
||||||
|
return Door
|
||||||
}
|
}
|
||||||
|
|
||||||
|
return pp.Ch
|
||||||
|
}
|
||||||
|
|
||||||
|
// revealSolid handles a blank cell for magic mapping, reporting whether
|
||||||
|
// it is passage: hidden passages become real; hidden things in walls
|
||||||
|
// stay hidden (the ' ' arm).
|
||||||
|
func revealSolid(pp *Place) bool {
|
||||||
|
if pp.Flags.Has(FReal) {
|
||||||
|
return pp.Flags.Has(FPassage)
|
||||||
|
}
|
||||||
|
|
||||||
|
pp.Flags.Set(FReal)
|
||||||
|
pp.Ch = Passage
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
// revealFloor handles a floor cell for magic mapping: a hidden trap
|
||||||
|
// becomes a real, seen trap; real floor shows nothing (the FLOOR arm).
|
||||||
|
func revealFloor(pp *Place) byte {
|
||||||
|
if pp.Flags.Has(FReal) {
|
||||||
|
return ' '
|
||||||
|
}
|
||||||
|
|
||||||
|
pp.Ch = Trap
|
||||||
|
pp.Flags.Set(FSeen | FReal)
|
||||||
|
|
||||||
|
return Trap
|
||||||
}
|
}
|
||||||
|
|
||||||
func (g *RogueGame) readFoodDetection(*Object) {
|
func (g *RogueGame) readFoodDetection(*Object) {
|
||||||
|
|||||||
@@ -229,31 +229,46 @@ func (g *RogueGame) zapMagicMissile(*Object) bool {
|
|||||||
}
|
}
|
||||||
|
|
||||||
func (g *RogueGame) zapSpeed(obj *Object) bool {
|
func (g *RogueGame) zapSpeed(obj *Object) bool {
|
||||||
if tp := g.zapRayMonster(); tp != nil {
|
tp := g.zapRayMonster()
|
||||||
if obj.WandKind() == WandHasteMonster {
|
if tp == nil {
|
||||||
if tp.On(Slowed) {
|
return true
|
||||||
tp.Flags.Clear(Slowed)
|
|
||||||
} else {
|
|
||||||
tp.Flags.Set(Hasted)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
if tp.On(Hasted) {
|
|
||||||
tp.Flags.Clear(Hasted)
|
|
||||||
} else {
|
|
||||||
tp.Flags.Set(Slowed)
|
|
||||||
}
|
|
||||||
|
|
||||||
tp.Turn = true
|
|
||||||
}
|
|
||||||
|
|
||||||
g.Delta.Y = tp.Pos.Y
|
|
||||||
g.Delta.X = tp.Pos.X
|
|
||||||
g.runTo(g.Delta)
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if obj.WandKind() == WandHasteMonster {
|
||||||
|
hasteTarget(tp)
|
||||||
|
} else {
|
||||||
|
slowTarget(tp)
|
||||||
|
}
|
||||||
|
|
||||||
|
g.Delta.Y = tp.Pos.Y
|
||||||
|
g.Delta.X = tp.Pos.X
|
||||||
|
g.runTo(g.Delta)
|
||||||
|
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// hasteTarget cancels a slow or applies a haste (the WS_HASTE_M arm of
|
||||||
|
// do_zap).
|
||||||
|
func hasteTarget(tp *Monster) {
|
||||||
|
if tp.On(Slowed) {
|
||||||
|
tp.Flags.Clear(Slowed)
|
||||||
|
} else {
|
||||||
|
tp.Flags.Set(Hasted)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// slowTarget cancels a haste or applies a slow (the WS_SLOW_M arm of
|
||||||
|
// do_zap).
|
||||||
|
func slowTarget(tp *Monster) {
|
||||||
|
if tp.On(Hasted) {
|
||||||
|
tp.Flags.Clear(Hasted)
|
||||||
|
} else {
|
||||||
|
tp.Flags.Set(Slowed)
|
||||||
|
}
|
||||||
|
|
||||||
|
tp.Turn = true
|
||||||
|
}
|
||||||
|
|
||||||
func (g *RogueGame) zapBolt(obj *Object) bool {
|
func (g *RogueGame) zapBolt(obj *Object) bool {
|
||||||
var name string
|
var name string
|
||||||
|
|
||||||
@@ -286,9 +301,7 @@ func (g *RogueGame) drain() {
|
|||||||
var drainee []*Monster
|
var drainee []*Monster
|
||||||
|
|
||||||
for _, mp := range g.Level.Monsters {
|
for _, mp := range g.Level.Monsters {
|
||||||
if mp.Room == p.Room || mp.Room == corp ||
|
if g.drainReaches(mp, corp, inpass) {
|
||||||
(inpass && g.Level.Char(mp.Pos.Y, mp.Pos.X) == Door &&
|
|
||||||
&g.Level.Passages[*g.Level.FlagsAt(mp.Pos.Y, mp.Pos.X)&FPassNum] == p.Room) {
|
|
||||||
drainee = append(drainee, mp)
|
drainee = append(drainee, mp)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
@@ -312,6 +325,18 @@ func (g *RogueGame) drain() {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// drainReaches reports whether the drain-life wand reaches this monster:
|
||||||
|
// the hero's room, the passage behind the door he stands on, or — when
|
||||||
|
// he is in a passage — a door of that same passage (the drainee
|
||||||
|
// condition of sticks.c drain).
|
||||||
|
func (g *RogueGame) drainReaches(mp *Monster, corp *Room, inpass bool) bool {
|
||||||
|
p := &g.Player
|
||||||
|
|
||||||
|
return mp.Room == p.Room || mp.Room == corp ||
|
||||||
|
(inpass && g.Level.Char(mp.Pos.Y, mp.Pos.X) == Door &&
|
||||||
|
&g.Level.Passages[*g.Level.FlagsAt(mp.Pos.Y, mp.Pos.X)&FPassNum] == p.Room)
|
||||||
|
}
|
||||||
|
|
||||||
// fireBolt fires a bolt in a given direction from a specific starting
|
// fireBolt fires a bolt in a given direction from a specific starting
|
||||||
// place (sticks.c fire_bolt).
|
// place (sticks.c fire_bolt).
|
||||||
func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
||||||
|
|||||||
Reference in New Issue
Block a user