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
|
||||
g.Items.Weapons[WeaponFlame].Name = name
|
||||
|
||||
var dirch byte
|
||||
|
||||
switch dir.Y + dir.X {
|
||||
case 0:
|
||||
dirch = '/'
|
||||
case 1, -1:
|
||||
if dir.Y == 0 {
|
||||
dirch = '-'
|
||||
} else {
|
||||
dirch = '|'
|
||||
}
|
||||
case 2, -2:
|
||||
dirch = '\\'
|
||||
}
|
||||
|
||||
dirch := boltDirChar(*dir)
|
||||
pos := start
|
||||
hitHero := !fromHero
|
||||
used := false
|
||||
@@ -351,22 +337,9 @@ func (g *RogueGame) fireBolt(start Coord, dir *Coord, name string) {
|
||||
pos.Y += dir.Y
|
||||
pos.X += dir.X
|
||||
spotpos = append(spotpos, pos)
|
||||
|
||||
ch := g.Level.VisibleChar(pos.Y, pos.X)
|
||||
bounce := false
|
||||
|
||||
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 boltBounces(ch, p.Pos, pos) {
|
||||
if !changed {
|
||||
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 {
|
||||
hitHero = true
|
||||
changed = !changed
|
||||
|
||||
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))
|
||||
}
|
||||
}
|
||||
used = g.boltStrikesMonster(tp, bolt, pos, ch, name, fromHero)
|
||||
} else if hitHero && pos == p.Pos {
|
||||
hitHero = false
|
||||
changed = !changed
|
||||
|
||||
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)
|
||||
}
|
||||
used = g.boltStrikesHero(start, name, fromHero)
|
||||
}
|
||||
|
||||
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).
|
||||
func (g *RogueGame) fixStick(cur *Object) {
|
||||
if g.Items.WandType[cur.Which] == staffName {
|
||||
|
||||
Reference in New Issue
Block a user