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:
2026-07-06 23:07:57 +02:00
parent c75af2ec22
commit 2eff377a73
28 changed files with 268 additions and 186 deletions

View File

@@ -94,21 +94,24 @@ func (k ObjectKind) MergesInPack() bool {
// Object is the _o arm of the C THING union: anything that can lie on the
// floor or ride in a pack.
type Object struct {
Kind ObjectKind // what kind of object it is (o_type)
Pos Coord // where it lives on the screen
Text string // what it says if you read it
Launch WeaponKind // what you need to launch it (noWeapon if none)
PackCh byte // what character it is in the pack
Damage string // damage if used like sword
HurlDmg string // damage if thrown
Count int // count for plural objects
Which int // which object of a type it is (index for the Kind's table)
HPlus int // plusses to hit
DPlus int // plusses to damage
Arm int // armor protection — overloaded as in C (see Charges/GoldVal)
Flags ObjFlags
Group int // group number for this object
Label string // label for object
Kind ObjectKind // what kind of object it is (o_type)
Pos Coord // where it lives on the screen
Text string // what it says if you read it
Launch WeaponKind // what you need to launch it (noWeapon if none)
PackCh byte // what character it is in the pack
Damage DiceSpec // damage if used like sword
HurlDmg DiceSpec // damage if thrown
Count int // count for plural objects
Which int // which object of a type it is (index for the Kind's table)
HPlus int // plusses to hit
DPlus int // plusses to damage
ArmorClass int // armor protection (armor only)
Charges int // charges remaining (wands and staffs only)
GoldValue int // worth (gold piles only)
Bonus int // magic bonus (rings only: protection, add strength, ...)
Flags ObjFlags
Group int // group number for this object
Label string // label for object
}
// newObject is list.c new_item() for objects: a zeroed Object with the
@@ -117,18 +120,6 @@ func newObject() *Object {
return &Object{Launch: noWeapon}
}
// Charges is the o_charges alias for Arm on wands and staffs.
func (o *Object) Charges() int { return o.Arm }
// SetCharges stores a charge count in the overloaded Arm field.
func (o *Object) SetCharges(n int) { o.Arm = n }
// GoldVal is the o_goldval alias for Arm on gold piles.
func (o *Object) GoldVal() int { return o.Arm }
// SetGoldVal stores a gold value in the overloaded Arm field.
func (o *Object) SetGoldVal(n int) { o.Arm = n }
// PotionKind returns Which as a potion kind; valid only for KindPotion.
func (o *Object) PotionKind() PotionKind { return PotionKind(o.Which) }