Give item categories and subtypes real types (refactor step 2)
ObjectKind separates what an item is from how it draws: Object.Type (a byte that doubled as the map character) becomes Kind ObjectKind, with Glyph() producing the display character and objectKindForGlyph converting back at the map boundary. KindWand covers the C 'stick' category. The magic-missile bolt uses KindGold, matching C's literal o_type='*' trick, with a comment. PotionKind, ScrollKind, RingKind, WandKind, WeaponKind, ArmorKind and TrapKind are now iota enums with Stringer (names come from the base info tables); Object gains typed accessors (obj.RingKind(), ...) and Launch is typed WeaponKind. beTrapped returns TrapKind. The getItem/inventory/whatis prompt filters take ObjectKind, with KindCallable/KindRingOrStick replacing the C CALLABLE/R_OR_S sentinels; wizard.c's type_name table is subsumed by ObjectKind.String(). IsRing/IsWearing/initWeapon/doPot signatures are typed accordingly. The save format version becomes 5.4.4-go2: the gob field rename would otherwise silently zero Kind when reading old saves. No behavior change; full suite green.
This commit is contained in:
135
game/object.go
135
game/object.go
@@ -1,20 +1,111 @@
|
||||
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 {
|
||||
Type byte // what kind of object it is (Potion, Scroll, Weapon, ...)
|
||||
Pos Coord // where it lives on the screen
|
||||
Text string // what it says if you read it
|
||||
Launch int // what you need to launch it (weapon index, -1 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
|
||||
HPlus int // plusses to hit
|
||||
DPlus int // plusses to damage
|
||||
Arm int // armor protection — overloaded as in C (see Charges/GoldVal)
|
||||
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
|
||||
@@ -23,7 +114,7 @@ type Object struct {
|
||||
// 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: -1}
|
||||
return &Object{Launch: noWeapon}
|
||||
}
|
||||
|
||||
// Charges is the o_charges alias for Arm on wands and staffs.
|
||||
@@ -38,6 +129,24 @@ 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) }
|
||||
|
||||
// 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...)
|
||||
|
||||
Reference in New Issue
Block a user