Decompose fireBolt (refactor step 7)
The fire_bolt loop splits into boltDirChar, boltBounces, boltStrikesMonster, and boltStrikesHero; loop state (hitHero/changed/ used) stays in fireBolt. Effect order and RNG calls unchanged.
This commit is contained in:
181
game/sticks.go
181
game/sticks.go
@@ -326,21 +326,7 @@ func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
|||||||
bolt.DPlus = 0
|
bolt.DPlus = 0
|
||||||
g.Items.Weapons[WeaponFlame].Name = name
|
g.Items.Weapons[WeaponFlame].Name = name
|
||||||
|
|
||||||
var dirch byte
|
dirch := boltDirChar(*dir)
|
||||||
|
|
||||||
switch dir.Y + dir.X {
|
|
||||||
case 0:
|
|
||||||
dirch = '/'
|
|
||||||
case 1, -1:
|
|
||||||
if dir.Y == 0 {
|
|
||||||
dirch = '-'
|
|
||||||
} else {
|
|
||||||
dirch = '|'
|
|
||||||
}
|
|
||||||
case 2, -2:
|
|
||||||
dirch = '\\'
|
|
||||||
}
|
|
||||||
|
|
||||||
pos := start
|
pos := start
|
||||||
hitHero := !fromHero
|
hitHero := !fromHero
|
||||||
used := false
|
used := false
|
||||||
@@ -351,22 +337,9 @@ func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
|||||||
pos.Y += dir.Y
|
pos.Y += dir.Y
|
||||||
pos.X += dir.X
|
pos.X += dir.X
|
||||||
spotpos = append(spotpos, pos)
|
spotpos = append(spotpos, pos)
|
||||||
|
|
||||||
ch := g.Level.VisibleChar(pos.Y, pos.X)
|
ch := g.Level.VisibleChar(pos.Y, pos.X)
|
||||||
bounce := false
|
if boltBounces(ch, p.Pos, pos) {
|
||||||
|
|
||||||
switch ch {
|
|
||||||
case Door:
|
|
||||||
// this code is necessary if the hero is on a door and he
|
|
||||||
// fires at the wall the door is in, it would otherwise loop
|
|
||||||
// infinitely
|
|
||||||
if p.Pos != pos {
|
|
||||||
bounce = true
|
|
||||||
}
|
|
||||||
case '|', '-', ' ':
|
|
||||||
bounce = true
|
|
||||||
}
|
|
||||||
|
|
||||||
if bounce {
|
|
||||||
if !changed {
|
if !changed {
|
||||||
hitHero = !hitHero
|
hitHero = !hitHero
|
||||||
}
|
}
|
||||||
@@ -384,57 +357,11 @@ func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
|||||||
if tp := g.Level.MonsterAt(pos.Y, pos.X); !hitHero && tp != nil {
|
if tp := g.Level.MonsterAt(pos.Y, pos.X); !hitHero && tp != nil {
|
||||||
hitHero = true
|
hitHero = true
|
||||||
changed = !changed
|
changed = !changed
|
||||||
|
used = g.boltStrikesMonster(tp, bolt, pos, ch, name, fromHero)
|
||||||
tp.OldCh = g.Level.Char(pos.Y, pos.X)
|
|
||||||
if !g.saveThrow(VsMagic, &tp.Stats) {
|
|
||||||
bolt.Pos = pos
|
|
||||||
used = true
|
|
||||||
|
|
||||||
if tp.Type == 'D' && name == "flame" {
|
|
||||||
g.addmsgf("the flame bounces")
|
|
||||||
|
|
||||||
if !g.Options.Terse {
|
|
||||||
g.addmsgf(" off the dragon")
|
|
||||||
}
|
|
||||||
|
|
||||||
g.endmsg()
|
|
||||||
} else {
|
|
||||||
g.hitMonster(pos, bolt)
|
|
||||||
}
|
|
||||||
} else if ch != 'M' || tp.Disguise == 'M' {
|
|
||||||
if fromHero {
|
|
||||||
g.runTo(pos)
|
|
||||||
}
|
|
||||||
|
|
||||||
if g.Options.Terse {
|
|
||||||
g.msg("%s misses", name)
|
|
||||||
} else {
|
|
||||||
g.msg("the %s whizzes past %s", name, g.setMname(tp))
|
|
||||||
}
|
|
||||||
}
|
|
||||||
} else if hitHero && pos == p.Pos {
|
} else if hitHero && pos == p.Pos {
|
||||||
hitHero = false
|
hitHero = false
|
||||||
changed = !changed
|
changed = !changed
|
||||||
|
used = g.boltStrikesHero(start, name, fromHero)
|
||||||
if !g.save(VsMagic) {
|
|
||||||
if p.Stats.HP -= g.roll(6, 6); p.Stats.HP <= 0 {
|
|
||||||
if fromHero {
|
|
||||||
g.death('b')
|
|
||||||
} else {
|
|
||||||
g.death(g.Level.MonsterAt(start.Y, start.X).Type)
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
used = true
|
|
||||||
|
|
||||||
if g.Options.Terse {
|
|
||||||
g.msg("the %s hits", name)
|
|
||||||
} else {
|
|
||||||
g.msg("you are hit by the %s", name)
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
g.msg("the %s whizzes by you", name)
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
g.mvaddch(pos.Y, pos.X, dirch)
|
g.mvaddch(pos.Y, pos.X, dirch)
|
||||||
@@ -446,6 +373,104 @@ func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// boltDirChar picks the character a traveling bolt is drawn with for its
|
||||||
|
// direction (the dirch switch of sticks.c fire_bolt).
|
||||||
|
func boltDirChar(dir Coord) byte {
|
||||||
|
switch dir.Y + dir.X {
|
||||||
|
case 0:
|
||||||
|
return '/'
|
||||||
|
case 1, -1:
|
||||||
|
if dir.Y == 0 {
|
||||||
|
return '-'
|
||||||
|
}
|
||||||
|
|
||||||
|
return '|'
|
||||||
|
case 2, -2:
|
||||||
|
return '\\'
|
||||||
|
}
|
||||||
|
|
||||||
|
return 0 // unreachable for the eight legal directions, as in C
|
||||||
|
}
|
||||||
|
|
||||||
|
// boltBounces reports whether a bolt bounces off this spot: walls, and
|
||||||
|
// any door except the one the hero stands on (which would otherwise loop
|
||||||
|
// infinitely, per the C comment in fire_bolt).
|
||||||
|
func boltBounces(ch byte, heroPos, pos Coord) bool {
|
||||||
|
switch ch {
|
||||||
|
case Door:
|
||||||
|
return heroPos != pos
|
||||||
|
case '|', '-', ' ':
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// boltStrikesMonster resolves a bolt arriving on a monster's square (the
|
||||||
|
// monster arm of the fire_bolt loop). It reports whether the bolt was
|
||||||
|
// used up.
|
||||||
|
func (g *RogueGame) boltStrikesMonster(tp *Monster, bolt *Object, pos Coord, ch byte, name string, fromHero bool) bool {
|
||||||
|
tp.OldCh = g.Level.Char(pos.Y, pos.X)
|
||||||
|
if !g.saveThrow(VsMagic, &tp.Stats) {
|
||||||
|
bolt.Pos = pos
|
||||||
|
|
||||||
|
if tp.Type == 'D' && name == "flame" {
|
||||||
|
g.addmsgf("the flame bounces")
|
||||||
|
|
||||||
|
if !g.Options.Terse {
|
||||||
|
g.addmsgf(" off the dragon")
|
||||||
|
}
|
||||||
|
|
||||||
|
g.endmsg()
|
||||||
|
} else {
|
||||||
|
g.hitMonster(pos, bolt)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
|
if ch != 'M' || tp.Disguise == 'M' {
|
||||||
|
if fromHero {
|
||||||
|
g.runTo(pos)
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Options.Terse {
|
||||||
|
g.msg("%s misses", name)
|
||||||
|
} else {
|
||||||
|
g.msg("the %s whizzes past %s", name, g.setMname(tp))
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
// boltStrikesHero resolves a bolt arriving on the hero (the hero arm of
|
||||||
|
// the fire_bolt loop). It reports whether the bolt was used up.
|
||||||
|
func (g *RogueGame) boltStrikesHero(start Coord, name string, fromHero bool) bool {
|
||||||
|
p := &g.Player
|
||||||
|
if g.save(VsMagic) {
|
||||||
|
g.msg("the %s whizzes by you", name)
|
||||||
|
|
||||||
|
return false
|
||||||
|
}
|
||||||
|
|
||||||
|
if p.Stats.HP -= g.roll(6, 6); p.Stats.HP <= 0 {
|
||||||
|
if fromHero {
|
||||||
|
g.death('b')
|
||||||
|
} else {
|
||||||
|
g.death(g.Level.MonsterAt(start.Y, start.X).Type)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if g.Options.Terse {
|
||||||
|
g.msg("the %s hits", name)
|
||||||
|
} else {
|
||||||
|
g.msg("you are hit by the %s", name)
|
||||||
|
}
|
||||||
|
|
||||||
|
return true
|
||||||
|
}
|
||||||
|
|
||||||
// fixStick sets up a new wand or staff (sticks.c fix_stick).
|
// fixStick sets up a new wand or staff (sticks.c fix_stick).
|
||||||
func (g *RogueGame) fixStick(cur *Object) {
|
func (g *RogueGame) fixStick(cur *Object) {
|
||||||
if g.Items.WandType[cur.Which] == staffName {
|
if g.Items.WandType[cur.Which] == staffName {
|
||||||
|
|||||||
Reference in New Issue
Block a user