Decompose score and wakeMonster (refactor step 7)

score splits into scoreInsert/scoreLines/showScores; wakeMonster gains
meanWakes/medusaCatches/medusaGaze predicates and effect. Behavior and
RNG call order unchanged.
This commit is contained in:
2026-07-22 22:01:03 +07:00
parent 3e1c30c787
commit 8895db530d
2 changed files with 144 additions and 93 deletions

View File

@@ -124,40 +124,14 @@ func (g *RogueGame) wakeMonster(y, x int) *Monster {
panic("can't find monster in wake_monster") panic("can't find monster in wake_monster")
} }
ch := tp.Type
// Every time he sees a mean monster, it might start chasing him // Every time he sees a mean monster, it might start chasing him
if !tp.On(Awake) && g.rnd(3) != 0 && tp.On(Mean) && !tp.On(Held) && if g.meanWakes(tp) {
!p.IsWearing(RingStealth) && !p.On(Levitating) {
tp.Dest = &p.Pos tp.Dest = &p.Pos
tp.Flags.Set(Awake) tp.Flags.Set(Awake)
} }
if ch == 'M' && !p.On(Blind) && !p.On(Hallucinating) && if g.medusaCatches(tp) {
!tp.On(Found) && !tp.On(Cancelled) && tp.On(Awake) { g.medusaGaze(tp, y, x)
rp := p.Room
if (rp != nil && !rp.Flags.Has(Dark)) ||
distance(y, x, p.Pos.Y, p.Pos.X) < LampDist {
tp.Flags.Set(Found)
if !g.save(VsMagic) {
if p.On(Confused) {
g.Lengthen(DUnconfuse, g.spread(HuhDuration))
} else {
g.Fuse(DUnconfuse, 0, g.spread(HuhDuration), After)
}
p.Flags.Set(Confused)
mname := g.setMname(tp)
g.addmsgf("%s", mname)
if mname != "it" {
g.addmsgf("'")
}
g.msg("s gaze has confused you")
}
}
} }
// Let greedy ones guard gold // Let greedy ones guard gold
if tp.On(Greedy) && !tp.On(Awake) { if tp.On(Greedy) && !tp.On(Awake) {
@@ -173,6 +147,60 @@ func (g *RogueGame) wakeMonster(y, x int) *Monster {
return tp return tp
} }
// meanWakes decides whether a sleeping mean monster starts the chase
// (monsters.c wake_monster). The waking roll happens for any sleeping
// monster, as in C.
func (g *RogueGame) meanWakes(tp *Monster) bool {
p := &g.Player
return !tp.On(Awake) && g.rnd(3) != 0 && tp.On(Mean) && !tp.On(Held) &&
!p.IsWearing(RingStealth) && !p.On(Levitating)
}
// medusaCatches reports an uncovered, awake medusa the hero can see
// (monsters.c wake_monster).
func (g *RogueGame) medusaCatches(tp *Monster) bool {
p := &g.Player
return tp.Type == 'M' && !p.On(Blind) && !p.On(Hallucinating) &&
!tp.On(Found) && !tp.On(Cancelled) && tp.On(Awake)
}
// medusaGaze confuses the hero when the medusa's gaze lands (the M
// block of monsters.c wake_monster).
func (g *RogueGame) medusaGaze(tp *Monster, y, x int) {
p := &g.Player
rp := p.Room
if (rp == nil || rp.Flags.Has(Dark)) &&
distance(y, x, p.Pos.Y, p.Pos.X) >= LampDist {
return
}
tp.Flags.Set(Found)
if g.save(VsMagic) {
return
}
if p.On(Confused) {
g.Lengthen(DUnconfuse, g.spread(HuhDuration))
} else {
g.Fuse(DUnconfuse, 0, g.spread(HuhDuration), After)
}
p.Flags.Set(Confused)
mname := g.setMname(tp)
g.addmsgf("%s", mname)
if mname != "it" {
g.addmsgf("'")
}
g.msg("s gaze has confused you")
}
// givePack gives a pack to a monster if it deserves one (monsters.c // givePack gives a pack to a monster if it deserves one (monsters.c
// give_pack). // give_pack).
func (g *RogueGame) givePack(tp *Monster) { func (g *RogueGame) givePack(tp *Monster) {

View File

@@ -107,61 +107,81 @@ func (g *RogueGame) score(amount, flags int, monst byte) {
topTen := g.rdScore() topTen := g.rdScore()
// Insert her in list if need be // Insert her in list if need be
ins := -1 ins := -1
if !g.NoScore && flags >= 0 { if !g.NoScore && flags >= 0 {
uid := os.Getuid() ins = g.scoreInsert(topTen, amount, flags, monst)
}
scp := len(topTen) lines, highlight := g.scoreLines(topTen, ins)
for i := range topTen { g.showScores(lines, highlight)
if amount > topTen[i].Score {
scp = i
break // Update the list file
} else if !g.AllScore && flags != 2 && if ins >= 0 {
topTen[i].UID == uid && topTen[i].Flags != 2 { g.wrScore(topTen)
// only one score per nowin uid }
scp = len(topTen) }
break // scoreInsert slots the new score into the top ten, honoring the
} // one-score-per-losing-uid rule; -1 means it did not place (the
} // insertion half of rip.c score).
func (g *RogueGame) scoreInsert(topTen []ScoreEnt, amount, flags int, monst byte) int {
uid := os.Getuid()
if scp < len(topTen) { scp := len(topTen)
sc2 := len(topTen) - 1 for i := range topTen {
if flags != 2 && !g.AllScore { if amount > topTen[i].Score {
for i := scp; i < len(topTen); i++ { scp = i
if topTen[i].UID == uid && topTen[i].Flags != 2 {
sc2 = i
break break
} } else if !g.AllScore && flags != 2 &&
} topTen[i].UID == uid && topTen[i].Flags != 2 {
} // only one score per nowin uid
scp = len(topTen)
for sc2 > scp { break
topTen[sc2] = topTen[sc2-1]
sc2--
}
lvl := g.Depth
if flags == 2 {
lvl = g.MaxDepth
}
topTen[scp] = ScoreEnt{
UID: uid,
Score: amount,
Flags: flags,
Monster: monst,
Name: g.Whoami,
Level: lvl,
Time: time.Now().Unix(),
}
ins = scp
} }
} }
// Build the list display if scp >= len(topTen) {
return -1
}
sc2 := len(topTen) - 1
if flags != 2 && !g.AllScore {
for i := scp; i < len(topTen); i++ {
if topTen[i].UID == uid && topTen[i].Flags != 2 {
sc2 = i
break
}
}
}
for sc2 > scp {
topTen[sc2] = topTen[sc2-1]
sc2--
}
lvl := g.Depth
if flags == 2 {
lvl = g.MaxDepth
}
topTen[scp] = ScoreEnt{
UID: uid,
Score: amount,
Flags: flags,
Monster: monst,
Name: g.Whoami,
Level: lvl,
Time: time.Now().Unix(),
}
return scp
}
// scoreLines formats the scoreboard, noting which display line holds
// the freshly inserted score (the display half of rip.c score).
func (g *RogueGame) scoreLines(topTen []ScoreEnt, ins int) ([]string, int) {
label := "Rogueists" label := "Rogueists"
if g.AllScore { if g.AllScore {
label = "Scores" label = "Scores"
@@ -194,32 +214,35 @@ func (g *RogueGame) score(amount, flags int, monst byte) {
lines = append(lines, line) lines = append(lines, line)
} }
if g.scr != nil && g.scr.term != nil { return lines, highlight
g.clear() }
for i, line := range lines { // showScores prints the scoreboard on the screen when there is one,
if i == highlight { // else to standard output (rip.c score).
g.standout() func (g *RogueGame) showScores(lines []string, highlight int) {
} if g.scr == nil || g.scr.term == nil {
g.mvaddstr(i, 0, line)
if i == highlight {
g.standend()
}
}
g.refresh()
} else {
for _, line := range lines { for _, line := range lines {
_, _ = fmt.Fprintln(os.Stdout, line) // CLI output _, _ = fmt.Fprintln(os.Stdout, line) // CLI output
} }
return
} }
// Update the list file g.clear()
if ins >= 0 {
g.wrScore(topTen) for i, line := range lines {
if i == highlight {
g.standout()
}
g.mvaddstr(i, 0, line)
if i == highlight {
g.standend()
}
} }
g.refresh()
} }
// ShowScores implements the -s command line option: print the scoreboard // ShowScores implements the -s command line option: print the scoreboard