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:
2026-07-07 02:53:09 +02:00
parent 1a25beead8
commit ebe477ba28
3 changed files with 176 additions and 99 deletions

View File

@@ -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 {

View File

@@ -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) {

View File

@@ -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) {