Skip to content Search Apps Documentation Source Content File Folder Download Copy Actions State String Boolean Number Struct Map Slice Pointer Function Closure Reference Nil Package Type Interface Unknown

Community realm. Read the code first. Community realm, deployed by its author. Read the code before you interact or send coins.

guns.gno

4.48 Kb · 193 lines
  1package engine
  2
  3// GunType identifies a weapon model.
  4type GunType string
  5
  6const (
  7	// NoGun marks an empty gun slot.
  8	NoGun GunType = ""
  9	// Colt45 is the one-handed six-shooter every character starts with.
 10	Colt45 GunType = "colt45"
 11)
 12
 13// GunSpec is the static data of a gun model (rules section 10 and the
 14// WEAPON LISTS).
 15type GunSpec struct {
 16	Name      string
 17	Capacity  int
 18	OneHanded bool
 19	Impact    byte // its line of the IMPACT TABLE (see Impact)
 20	Wielding  int  // its wielding factor: how far it can be thrown (16.21, 17.2)
 21	Striking  byte // its line of the STRIKING TABLE (see Striking)
 22}
 23
 24// Spec returns the model's static data.
 25func (t GunType) Spec() GunSpec {
 26	switch t {
 27	case Colt45:
 28		return GunSpec{Name: "Colt 45", Capacity: 6, OneHanded: true, Impact: 'B', Wielding: 4, Striking: 'B'}
 29	}
 30	return GunSpec{}
 31}
 32
 33// GunLocation is where a character keeps a gun (the boxes of the sheet).
 34type GunLocation int
 35
 36const (
 37	Holstered GunLocation = iota
 38	GunHand
 39	OtherHand
 40	BothHands
 41)
 42
 43// Hand codes used in plan strings: 0 = gun hand, 1 = other hand, 2 = both
 44// hands; HandGround, "g" in a gun move, is the hex the character stands in.
 45const (
 46	HandGun    = 0
 47	HandOther  = 1
 48	HandBoth   = 2
 49	HandGround = 3
 50)
 51
 52// HandLocation maps a plan hand code to the location it designates.
 53func HandLocation(code int) (GunLocation, bool) {
 54	switch code {
 55	case HandGun:
 56		return GunHand, true
 57	case HandOther:
 58		return OtherHand, true
 59	case HandBoth:
 60		return BothHands, true
 61	}
 62	return 0, false
 63}
 64
 65// String returns the location name used in JSON views.
 66func (l GunLocation) String() string {
 67	switch l {
 68	case Holstered:
 69		return "holstered"
 70	case GunHand:
 71		return "gun_hand"
 72	case OtherHand:
 73		return "other_hand"
 74	case BothHands:
 75		return "both_hands"
 76	}
 77	return "?"
 78}
 79
 80// Gun is one weapon carried by a character. ID identifies it for the whole
 81// game (plans refer to it), even among several guns of the same model.
 82type Gun struct {
 83	ID       int
 84	Type     GunType
 85	Location GunLocation
 86	Cocked   bool
 87	Shells   int
 88	Jammed   bool // every shell crossed off; fires again once completely reloaded (13.31)
 89	Exploded bool // cannot fire for the rest of the game (13.31)
 90}
 91
 92// CanFireFrom reports whether the gun is in a box it can shoot from (13.1):
 93// a one-handed gun in the gun hand or both hands, a two-handed one in both
 94// hands.
 95func (g Gun) CanFireFrom() bool {
 96	if g.Type == NoGun {
 97		return false
 98	}
 99	if g.Type.Spec().OneHanded {
100		return g.Location == GunHand || g.Location == BothHands
101	}
102	return g.Location == BothHands
103}
104
105// MaxGuns is how many guns a character can carry (hands and holsters).
106const MaxGuns = 3
107
108// Guns is a character's weapons; empty slots have Type NoGun.
109type Guns [MaxGuns]Gun
110
111// Find returns the slot of the gun with the given id, or -1.
112func (g Guns) Find(id int) int {
113	for i, gun := range g {
114		if gun.Type != NoGun && gun.ID == id {
115			return i
116		}
117	}
118	return -1
119}
120
121// NextID is a free id for a gun added to this character.
122func (g Guns) NextID() int {
123	n := 0
124	for _, gun := range g {
125		if gun.Type != NoGun && gun.ID > n {
126			n = gun.ID
127		}
128	}
129	return n + 1
130}
131
132// At returns the slot of the gun held at a location, or -1.
133func (g Guns) At(loc GunLocation) int {
134	for i, gun := range g {
135		if gun.Type != NoGun && gun.Location == loc {
136			return i
137		}
138	}
139	return -1
140}
141
142// Firing returns the slot of the gun held in a box it can shoot from
143// (rule 11.3), or -1.
144func (g Guns) Firing() int {
145	for i, gun := range g {
146		if gun.CanFireFrom() {
147			return i
148		}
149	}
150	return -1
151}
152
153// Blocked reports whether a gun other than the one in slot except holds
154// loc, or a hand box overlapping it: BOTH HANDS takes the gun hand and the
155// other hand, and either hand is taken by a gun in BOTH HANDS.
156func (g Guns) Blocked(loc GunLocation, except int) bool {
157	for i, gun := range g {
158		if i == except || gun.Type == NoGun || gun.Location == Holstered {
159			continue
160		}
161		if gun.Location == loc || gun.Location == BothHands || loc == BothHands {
162			return true
163		}
164	}
165	return false
166}
167
168// Free returns an empty slot, or -1 when the character carries MaxGuns.
169func (g Guns) Free() int {
170	for i, gun := range g {
171		if gun.Type == NoGun {
172			return i
173		}
174	}
175	return -1
176}
177
178// Count is the number of guns carried.
179func (g Guns) Count() int {
180	n := 0
181	for _, gun := range g {
182		if gun.Type != NoGun {
183			n++
184		}
185	}
186	return n
187}
188
189// startingGuns is the fixed loadout at game creation: a loaded, uncocked
190// Colt 45 in the holster, gun 1.
191func startingGuns() Guns {
192	return Guns{{ID: 1, Type: Colt45, Location: Holstered, Cocked: false, Shells: 6}}
193}