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.
155 lines
4.6 KiB
Go
155 lines
4.6 KiB
Go
package game
|
|
|
|
// ObjectKind is the category of an item. In C this was the o_type byte,
|
|
// which doubled as the character drawn on the map; the port separates the
|
|
// category (ObjectKind) from its display character (Glyph).
|
|
type ObjectKind int
|
|
|
|
const (
|
|
KindNone ObjectKind = iota
|
|
KindPotion
|
|
KindScroll
|
|
KindFood
|
|
KindWeapon
|
|
KindArmor
|
|
KindRing
|
|
KindWand // a "stick": wand or staff
|
|
KindAmulet
|
|
KindGold
|
|
)
|
|
|
|
// Prompt-filter pseudo-kinds for item selection (rogue.h CALLABLE and
|
|
// R_OR_S): they never appear on an Object, only as getItem filters.
|
|
const (
|
|
KindCallable ObjectKind = -1
|
|
KindRingOrStick ObjectKind = -2
|
|
)
|
|
|
|
// kindGlyphs maps each kind to the character Rogue draws for it.
|
|
var kindGlyphs = [...]byte{
|
|
KindNone: ' ',
|
|
KindPotion: Potion,
|
|
KindScroll: Scroll,
|
|
KindFood: Food,
|
|
KindWeapon: Weapon,
|
|
KindArmor: Armor,
|
|
KindRing: Ring,
|
|
KindWand: Stick,
|
|
KindAmulet: Amulet,
|
|
KindGold: Gold,
|
|
}
|
|
|
|
// Glyph returns the map/display character for this kind of object.
|
|
func (k ObjectKind) Glyph() byte {
|
|
if k < 0 || int(k) >= len(kindGlyphs) {
|
|
return ' '
|
|
}
|
|
return kindGlyphs[k]
|
|
}
|
|
|
|
// String names the category the way the C type_name() did.
|
|
func (k ObjectKind) String() string {
|
|
switch k {
|
|
case KindPotion:
|
|
return "potion"
|
|
case KindScroll:
|
|
return "scroll"
|
|
case KindFood:
|
|
return "food"
|
|
case KindWeapon:
|
|
return "weapon"
|
|
case KindArmor:
|
|
return "suit of armor"
|
|
case KindRing:
|
|
return "ring"
|
|
case KindWand:
|
|
return "wand or staff"
|
|
case KindAmulet:
|
|
return "amulet"
|
|
case KindGold:
|
|
return "gold"
|
|
case KindRingOrStick:
|
|
return "ring, wand or staff"
|
|
}
|
|
return "bizarre thing"
|
|
}
|
|
|
|
// objectKindForGlyph is the reverse of Glyph: what category of item does a
|
|
// map character denote. Returns KindNone for non-item characters.
|
|
func objectKindForGlyph(ch byte) ObjectKind {
|
|
for k, g := range kindGlyphs {
|
|
if g == ch && ObjectKind(k) != KindNone {
|
|
return ObjectKind(k)
|
|
}
|
|
}
|
|
return KindNone
|
|
}
|
|
|
|
// MergesInPack reports whether picking up another of this kind merges into
|
|
// an existing pack entry's count (rogue.h ISMULT).
|
|
func (k ObjectKind) MergesInPack() bool {
|
|
return k == KindPotion || k == KindScroll || k == KindFood
|
|
}
|
|
|
|
// 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 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
|
|
// same non-zero defaults the C code relies on.
|
|
func newObject() *Object {
|
|
return &Object{Launch: noWeapon}
|
|
}
|
|
|
|
// PotionKind returns Which as a potion kind; valid only for KindPotion.
|
|
func (o *Object) PotionKind() PotionKind { return PotionKind(o.Which) }
|
|
|
|
// ScrollKind returns Which as a scroll kind; valid only for KindScroll.
|
|
func (o *Object) ScrollKind() ScrollKind { return ScrollKind(o.Which) }
|
|
|
|
// RingKind returns Which as a ring kind; valid only for KindRing.
|
|
func (o *Object) RingKind() RingKind { return RingKind(o.Which) }
|
|
|
|
// WandKind returns Which as a wand kind; valid only for KindWand.
|
|
func (o *Object) WandKind() WandKind { return WandKind(o.Which) }
|
|
|
|
// WeaponKind returns Which as a weapon kind; valid only for KindWeapon.
|
|
func (o *Object) WeaponKind() WeaponKind { return WeaponKind(o.Which) }
|
|
|
|
// ArmorKind returns Which as an armor kind; valid only for KindArmor.
|
|
func (o *Object) ArmorKind() ArmorKind { return ArmorKind(o.Which) }
|
|
|
|
// attachObj is list.c attach(): push item onto the front of a list.
|
|
func attachObj(list *[]*Object, item *Object) {
|
|
*list = append([]*Object{item}, *list...)
|
|
}
|
|
|
|
// detachObj is list.c detach(): remove item (by identity) from a list.
|
|
func detachObj(list *[]*Object, item *Object) {
|
|
for i, o := range *list {
|
|
if o == item {
|
|
*list = append((*list)[:i], (*list)[i+1:]...)
|
|
return
|
|
}
|
|
}
|
|
}
|