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 {
|
||||
g.addch(mp.OldCh)
|
||||
}
|
||||
} else {
|
||||
if !canSee {
|
||||
g.standout()
|
||||
}
|
||||
|
||||
if !g.Player.On(Hallucinating) {
|
||||
g.addch(mp.Type)
|
||||
} else {
|
||||
g.addch(g.randomMonsterLetter())
|
||||
}
|
||||
|
||||
if !canSee {
|
||||
g.standend()
|
||||
|
||||
addNew = true
|
||||
}
|
||||
} else if g.showSensed(mp, canSee) {
|
||||
addNew = true
|
||||
}
|
||||
}
|
||||
|
||||
@@ -326,6 +312,29 @@ func (g *RogueGame) turnSee(turnOff bool) bool {
|
||||
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
|
||||
// seen_stairs).
|
||||
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) {
|
||||
// Hold monster scroll. Stop all monsters within two spaces from
|
||||
// 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
|
||||
held := 0
|
||||
|
||||
@@ -81,24 +106,7 @@ func (g *RogueGame) readHoldMonster(*Object) {
|
||||
}
|
||||
}
|
||||
|
||||
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")
|
||||
}
|
||||
return held
|
||||
}
|
||||
|
||||
func (g *RogueGame) readSleep(*Object) {
|
||||
@@ -113,6 +121,19 @@ func (g *RogueGame) readSleep(*Object) {
|
||||
func (g *RogueGame) readCreateMonster(*Object) {
|
||||
// Create a monster: first look in a circle around him, next try
|
||||
// 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
|
||||
i := 0
|
||||
|
||||
@@ -139,12 +160,7 @@ func (g *RogueGame) readCreateMonster(*Object) {
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
}
|
||||
return mp, i != 0
|
||||
}
|
||||
|
||||
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
|
||||
// passages become real, hidden traps show, and the visible character is
|
||||
// drawn (the loop body of the C SCR_MAP case).
|
||||
// revealSpot uncovers one map cell for magic mapping and draws it (the
|
||||
// loop body of the C SCR_MAP case).
|
||||
func (g *RogueGame) revealSpot(y, x int) {
|
||||
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
|
||||
pass := false
|
||||
|
||||
switch ch {
|
||||
case Door, Stairs:
|
||||
case '-', '|':
|
||||
if !pp.Flags.Has(FReal) {
|
||||
ch = Door
|
||||
pp.Ch = Door
|
||||
pp.Flags.Set(FReal)
|
||||
}
|
||||
ch = revealWall(pp)
|
||||
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
|
||||
}
|
||||
pass = revealSolid(pp)
|
||||
case Passage:
|
||||
pass = true
|
||||
case Floor:
|
||||
if pp.Flags.Has(FReal) {
|
||||
ch = ' '
|
||||
} else {
|
||||
ch = Trap
|
||||
pp.Ch = Trap
|
||||
pp.Flags.Set(FSeen | FReal)
|
||||
}
|
||||
ch = revealFloor(pp)
|
||||
default:
|
||||
if pp.Flags.Has(FPassage) {
|
||||
pass = true
|
||||
@@ -223,16 +235,47 @@ func (g *RogueGame) revealSpot(y, x int) {
|
||||
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)
|
||||
}
|
||||
return ch
|
||||
}
|
||||
|
||||
// revealWall handles a wall cell for magic mapping: a secret door
|
||||
// becomes a real door (the '-'/'|' arm).
|
||||
func revealWall(pp *Place) byte {
|
||||
if !pp.Flags.Has(FReal) {
|
||||
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) {
|
||||
|
||||
@@ -229,31 +229,46 @@ func (g *RogueGame) zapMagicMissile(*Object) bool {
|
||||
}
|
||||
|
||||
func (g *RogueGame) zapSpeed(obj *Object) bool {
|
||||
if tp := g.zapRayMonster(); tp != nil {
|
||||
if obj.WandKind() == WandHasteMonster {
|
||||
if tp.On(Slowed) {
|
||||
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)
|
||||
tp := g.zapRayMonster()
|
||||
if tp == nil {
|
||||
return true
|
||||
}
|
||||
|
||||
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
|
||||
}
|
||||
|
||||
// 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 {
|
||||
var name string
|
||||
|
||||
@@ -286,9 +301,7 @@ func (g *RogueGame) drain() {
|
||||
var drainee []*Monster
|
||||
|
||||
for _, mp := range g.Level.Monsters {
|
||||
if 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) {
|
||||
if g.drainReaches(mp, corp, inpass) {
|
||||
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
|
||||
// place (sticks.c fire_bolt).
|
||||
func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
||||
|
||||
Reference in New Issue
Block a user