Un-overload Object fields and pre-parse damage dice (refactor step 3)
Object.Arm carried four meanings in C (o_arm/o_charges/o_goldval plus
ring bonuses); it is now four fields: ArmorClass, Charges, GoldValue,
and Bonus. Stats.Arm becomes Stats.ArmorClass. The Charges()/GoldVal()
accessor pair is gone.
Damage dice strings ("1x4/1x2") are parsed once into DiceSpec — at
table definition for the bestiary and weapon tables, at creation for
items — instead of re-parsed with atoi on every swing as fight.c
roll_em did. ParseDice preserves the C parse semantics exactly,
including the junk-tolerant "%%%x0" bestiary placeholder and the
"000x0" flytrap reset (regression-tested in dice_test.go); the
flytrap's growing grip becomes DiceSpec{{VfHit, 1}}.
Save format bumps to 5.4.4-go3 (field renames and retypes would
silently zero under gob's match-by-name decoding).
No behavior change; full suite green.
This commit is contained in:
@@ -1,10 +1,6 @@
|
||||
package game
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strconv"
|
||||
"strings"
|
||||
)
|
||||
import "strconv"
|
||||
|
||||
// fight.c — all the fighting gets done here.
|
||||
|
||||
@@ -245,7 +241,7 @@ func (g *RogueGame) attack(mp *Monster) int {
|
||||
// Venus Flytrap stops the poor guy from moving
|
||||
p.Flags.Set(Held)
|
||||
p.VfHit++
|
||||
g.Monsters['F'-'A'].Stats.Dmg = fmt.Sprintf("%dx1", p.VfHit)
|
||||
g.Monsters['F'-'A'].Stats.Dmg = DiceSpec{{Count: p.VfHit, Sides: 1}}
|
||||
if p.Stats.HP--; p.Stats.HP <= 0 {
|
||||
g.death('F')
|
||||
}
|
||||
@@ -322,34 +318,34 @@ func (g *RogueGame) rollEm(thatt, thdef *Creature, weap *Object, hurl bool) bool
|
||||
p := &g.Player
|
||||
att := &thatt.Stats
|
||||
def := &thdef.Stats
|
||||
var cp string
|
||||
var attacks DiceSpec
|
||||
var hplus, dplus int
|
||||
if weap == nil {
|
||||
cp = att.Dmg
|
||||
attacks = att.Dmg
|
||||
} else {
|
||||
hplus = weap.HPlus
|
||||
dplus = weap.DPlus
|
||||
if weap == p.CurWeapon {
|
||||
if p.IsRing(Left, RingIncreaseDamage) {
|
||||
dplus += p.CurRing[Left].Arm
|
||||
dplus += p.CurRing[Left].Bonus
|
||||
} else if p.IsRing(Left, RingDexterity) {
|
||||
hplus += p.CurRing[Left].Arm
|
||||
hplus += p.CurRing[Left].Bonus
|
||||
}
|
||||
if p.IsRing(Right, RingIncreaseDamage) {
|
||||
dplus += p.CurRing[Right].Arm
|
||||
dplus += p.CurRing[Right].Bonus
|
||||
} else if p.IsRing(Right, RingDexterity) {
|
||||
hplus += p.CurRing[Right].Arm
|
||||
hplus += p.CurRing[Right].Bonus
|
||||
}
|
||||
}
|
||||
cp = weap.Damage
|
||||
attacks = weap.Damage
|
||||
if hurl {
|
||||
if weap.Flags.Has(Missile) && p.CurWeapon != nil &&
|
||||
WeaponKind(p.CurWeapon.Which) == weap.Launch {
|
||||
cp = weap.HurlDmg
|
||||
attacks = weap.HurlDmg
|
||||
hplus += p.CurWeapon.HPlus
|
||||
dplus += p.CurWeapon.DPlus
|
||||
} else if weap.Launch < 0 {
|
||||
cp = weap.HurlDmg
|
||||
attacks = weap.HurlDmg
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -358,40 +354,28 @@ func (g *RogueGame) rollEm(thatt, thdef *Creature, weap *Object, hurl bool) bool
|
||||
if !thdef.Flags.Has(Awake) {
|
||||
hplus += 4
|
||||
}
|
||||
defArm := def.Arm
|
||||
defArm := def.ArmorClass
|
||||
if def == &p.Stats {
|
||||
if p.CurArmor != nil {
|
||||
defArm = p.CurArmor.Arm
|
||||
defArm = p.CurArmor.ArmorClass
|
||||
}
|
||||
if p.IsRing(Left, RingProtection) {
|
||||
defArm -= p.CurRing[Left].Arm
|
||||
defArm -= p.CurRing[Left].Bonus
|
||||
}
|
||||
if p.IsRing(Right, RingProtection) {
|
||||
defArm -= p.CurRing[Right].Arm
|
||||
defArm -= p.CurRing[Right].Bonus
|
||||
}
|
||||
}
|
||||
didHit := false
|
||||
for cp != "" {
|
||||
ndice := cAtoi(cp)
|
||||
xi := strings.IndexByte(cp, 'x')
|
||||
if xi < 0 {
|
||||
break
|
||||
}
|
||||
cp = cp[xi+1:]
|
||||
nsides := cAtoi(cp)
|
||||
for _, atk := range attacks {
|
||||
if g.swing(att.Lvl, defArm, hplus+strPlus[att.Str]) {
|
||||
proll := g.roll(ndice, nsides)
|
||||
proll := g.roll(atk.Count, atk.Sides)
|
||||
damage := dplus + proll + addDam[att.Str]
|
||||
if damage > 0 {
|
||||
def.HP -= damage
|
||||
}
|
||||
didHit = true
|
||||
}
|
||||
si := strings.IndexByte(cp, '/')
|
||||
if si < 0 {
|
||||
break
|
||||
}
|
||||
cp = cp[si+1:]
|
||||
}
|
||||
return didHit
|
||||
}
|
||||
@@ -531,7 +515,7 @@ func (g *RogueGame) killed(tp *Monster, pr bool) {
|
||||
case 'F':
|
||||
p.Flags.Clear(Held)
|
||||
p.VfHit = 0
|
||||
g.Monsters['F'-'A'].Stats.Dmg = "000x0"
|
||||
g.Monsters['F'-'A'].Stats.Dmg = dice("000x0")
|
||||
case 'L':
|
||||
pos, ok := g.fallpos(tp.Pos)
|
||||
if ok {
|
||||
@@ -540,9 +524,9 @@ func (g *RogueGame) killed(tp *Monster, pr bool) {
|
||||
if ok && g.Depth >= g.MaxDepth {
|
||||
gold := newObject()
|
||||
gold.Kind = KindGold
|
||||
gold.SetGoldVal(g.goldCalc())
|
||||
gold.GoldValue = g.goldCalc()
|
||||
if g.save(VsMagic) {
|
||||
gold.Arm += g.goldCalc() + g.goldCalc() + g.goldCalc() + g.goldCalc()
|
||||
gold.GoldValue += g.goldCalc() + g.goldCalc() + g.goldCalc() + g.goldCalc()
|
||||
}
|
||||
attachObj(&tp.Pack, gold)
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user