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.

v0 source pure

Package engine is the pure, deterministic rules engine of a gunfight of two to four characters: plan parsing and vali...

Overview

Package engine is the pure, deterministic rules engine of a gunfight of two to four characters: plan parsing and validation, and the 5-segment resolution of a turn. It has no chain dependency so it can be unit-tested with gno test.

Constants 28

const StatusMove, StatusRun, StatusDown, StatusHead

1const (
2	StatusMove = 'M' // played a foot action or dropped this turn (13.61)
3	StatusRun  = 'R' // played a Run this turn (13.62)
4	StatusDown = 'D' // is DOWN (13.63)
5	StatusHead = 'H' // head counter shot at (13.64, not played)
6)
source

Target statuses a FIRE card may list (rule 13.6), as the letters of a card's status string.

const GunJams, GunExplodes

1const (
2	GunJams     = "jams"     // all shells crossed off; cannot fire until reloaded
3	GunExplodes = "explodes" // cannot fire for the rest of the game
4)
source

Second-draw penalties.

const HandGun, HandOther, HandBoth, HandGround

1const (
2	HandGun    = 0
3	HandOther  = 1
4	HandBoth   = 2
5	HandGround = 3
6)
source

Hand codes used in plan strings: 0 = gun hand, 1 = other hand, 2 = both hands; HandGround, "g" in a gun move, is the hex the character stands in.

const MaxPlanEntries, MaxPlanLen

1const (
2	// MaxPlanEntries bounds the number of actions in a plan; five 1-point
3	// actions already fill the budget.
4	MaxPlanEntries = MaxActionPoints
5	// MaxPlanLen bounds the plan string length.
6	MaxPlanLen = 128
7)
source

const OptCock, OptUncock, OptAim, OptShoot, OptNothing, OptThrow

 1const (
 2	OptCock    = "cock"
 3	OptUncock  = "uncock"
 4	OptAim     = "aim"
 5	OptShoot   = "shoot"
 6	OptNothing = "nothing"
 7	// OptThrow is what a Throw does instead of nothing (17.1), naming its
 8	// target like a shot ("6b:throw:@1"; a bare "6b" does nothing).
 9	OptThrow = "throw"
10)
source

Shoot options: what a Cock/Aim/Shoot does (11.3), or a Shoot (shoot or nothing). Aiming and shooting name their target (11.31): a hex of the aim zone ("5f:aim:A-F6", "7f:shoot:A-F6") or a character by seat ("5f:aim:@1", "7f:shoot:@1"). A shot at a hex hits the character standing there when it goes off, and is wasted otherwise.

const OptDamage, OptWield

1const (
2	OptDamage = "damage"
3	OptWield  = "wield"
4)
source

Strength options (20.2): a STRENGTH adds to the penalties ("7b:damage", also a bare "7b", what a STRENGTH does when its use is not stated) or to the wielding factor ("7b:wield") of the Throw it is played on top of.

const EvMove, EvTurn, EvFlip, EvDelay, EvCancel, EvDraw, EvLoad, EvCock, EvUncock, EvAim, EvLoseAim, EvNothing, EvShot, EvThrow, EvMalfunction, EvWildShot, EvWound, EvDirection, EvDropGun, EvMoveGun, EvPassOut, EvSeriousCheck, EvVP, EvRunAway

 1const (
 2	EvMove         = "move"          // From, To, Facing, Down, Action (Reason "stagger" when thrown by a hit)
 3	EvTurn         = "turn"          // Facing, Action (Reason "stagger" when thrown by a hit)
 4	EvFlip         = "flip"          // Down, Action (empty for a DROP penalty)
 5	EvDelay        = "delay"         // N gained, Reason, Card drawn (0 for crawl), Result penalty, Endurance crossed off, Delay = running total once this card is counted
 6	EvCancel       = "cancel"        // Action, Reason (To = the obstacle in the way for no_los)
 7	EvDraw         = "draw"          // Gun moved from From (holster, a hand, or "ground" with N = its ground id) to To (a hand) and cocked, unless jammed (Result "jammed")
 8	EvLoad         = "load"          // a shell loaded in the gun in both hands, N shells now, uncocked; Result "unjammed" when that completes a jammed gun
 9	EvCock         = "cock"          // Gun cocked
10	EvUncock       = "uncock"        // Gun uncocked
11	EvAim          = "aim"           // N = AIM points after aiming, To = the hex they sit on, Target = the seat they follow (-1 for a hex)
12	EvLoseAim      = "lose_aim"      // Reason (To = the obstacle in the way for no_los)
13	EvNothing      = "nothing"       // a Shoot used to do nothing, or a shot held at a hex nobody stands in (Reason empty_hex, To = the hex) or at a target out of sight (Reason no_los, To = its hex, Target = its seat) or out of the fight (Reason out_of_fight, To = its hex, Target = its seat): keeps the aim
14	EvShot         = "shot"          // Card, Target = the seat shot at (whoever stood in the hex named, for a shot at a hex), To = the hex shot at, Hit (final location or Miss), Range, N = aim time, Reason "" | out_of_zone | misfire
15	EvThrow        = "throw"         // like a shot: Card, Target, To = the hex thrown at, Hit, Range, N = aim time, Chart, Status, Gun, GunID, Reason "" | out_of_zone; the weapon then lands (EvDropGun, Reason throw)
16	EvMalfunction  = "malfunction"   // Card, Result (no_effect, misfire, jams, explodes, no_penalty), Gun, GunID
17	EvWildShot     = "wild_shot"     // Gun went off without hitting anything: uncocked, one shell less
18	EvWound        = "wound"         // Player hit: Result = penalty kind (Kill, Stun...), N
19	EvDirection    = "direction"     // Card drawn as a direction card: To = its HEX line
20	EvDropGun      = "drop_gun"      // Gun fell from From (hand) to the hex To, N = its ground id; Reason throw for a thrown weapon landing, gun_move for one let go (10.22)
21	EvMoveGun      = "move_gun"      // a gun move (10.22): Gun moved from From (both hands) to To (a hand), as it was
22	EvPassOut      = "pass_out"      // end of turn: more delay than endurance two turns in a row
23	EvSeriousCheck = "serious_check" // end of showdown: Card, N = DELAY + SERIOUS points (4 kills)
24	EvVP           = "vp"            // end of turn: victory points (rule 15), N = points (< 0 for a loss), Reason = the award (VPSurvive...)
25	EvRunAway      = "run_away"      // the character moved off the map (15.5): From = the edge hex it left, Facing = the way it went, Action
26)
source

Event kinds.

const ReasonCrawl, ReasonSprint, ReasonLeap, ReasonOccupied, ReasonFence, ReasonObstacle, ReasonDrop, ReasonStun, ReasonLight, ReasonSerious, ReasonLeg, ReasonTime, ReasonNoGun, ReasonNotInHand, ReasonNotBoth, ReasonGunDropped, ReasonHandFull, ReasonNoRoom, ReasonNotCocked, ReasonEmpty, ReasonJammed, ReasonFull, ReasonBroken, ReasonNoTarget, ReasonOutOfZone, ReasonNoLOS, ReasonReveal, ReasonTransfer, ReasonOwnHex, ReasonNoHex, ReasonShot, ReasonStagger, ReasonMisfire, ReasonEmptyHex, ReasonOutOfFight, ReasonOutOfRange, ReasonThrow, ReasonGunMove

 1const (
 2	ReasonCrawl      = "crawl"        // moving while down (rule 9.2)
 3	ReasonSprint     = "sprint"       // sprinting draws a delay card (rule 9.23)
 4	ReasonLeap       = "leap"         // leap/drop draws two delay cards (rule 9.4)
 5	ReasonOccupied   = "occupied"     // ending a move in an occupied hex (rule 9.24)
 6	ReasonFence      = "fence"        // moving or staggering across a fence (rule 35.2)
 7	ReasonObstacle   = "obstacle"     // moving or staggering onto or off an obstacle (rule 36.4)
 8	ReasonDrop       = "drop"         // a DROP penalty draws three delay cards (rule 14.11)
 9	ReasonStun       = "stun"         // a STUN draws wound cards (14.11)
10	ReasonLight      = "light"        // a LIGHT draws fatigue cards (14.11)
11	ReasonSerious    = "serious"      // fatigue cards at the start of the turn (14.12)
12	ReasonLeg        = "leg"          // fatigue cards per hex moved upright (14.12)
13	ReasonTime       = "time"         // not executed by the end of segment 5 (rule 7.53)
14	ReasonNoGun      = "no_gun"       // no gun in the box the action needs (11.3); a gun move of a gun the character no longer has
15	ReasonNotInHand  = "not_in_hand"  // a gun move dropping a gun that is not in a hand box (10.22)
16	ReasonNotBoth    = "not_both"     // a gun move to a hand of a gun that is not in both hands (10.22)
17	ReasonGunDropped = "gun_dropped"  // a gun move dropped the gun the character aims with: its AIM points go
18	ReasonHandFull   = "hand_full"    // the destination hand already holds a gun
19	ReasonNoRoom     = "no_room"      // the character already carries MaxGuns weapons
20	ReasonNotCocked  = "not_cocked"   // shooting an uncocked gun (13.1)
21	ReasonEmpty      = "empty"        // shooting a gun without shells (13.1)
22	ReasonJammed     = "jammed"       // shooting or cocking a jammed gun not completely reloaded yet (13.31)
23	ReasonFull       = "full"         // loading a gun already holding its Ammo limit (10.42)
24	ReasonBroken     = "broken"       // using or loading an exploded gun (13.31)
25	ReasonNoTarget   = "no_target"    // the character named is out of the fight (12.6), or is the shooter, or no such seat
26	ReasonOutOfZone  = "out_of_zone"  // the target is in the blind zone (8.32, 12.41)
27	ReasonNoLOS      = "no_los"       // no line of sight to the target, an obstacle in the way by the heights (31): an aim is cancelled, a shot is held, AIM points are lost
28	ReasonReveal     = "reveal"       // revealing an action other than Turn or a gun action (12.44)
29	ReasonTransfer   = "transfer"     // a new target more than one hex from the markers (12.5)
30	ReasonOwnHex     = "own_hex"      // a new target moving the markers into or out of the character's own hex (12.5)
31	ReasonNoHex      = "no_hex"       // aiming at a hex that is not on the board
32	ReasonShot       = "shot"         // aim spent by a shot (12.43)
33	ReasonStagger    = "stagger"      // thrown by a STAGGER penalty
34	ReasonMisfire    = "misfire"      // the shot was cancelled by a MALFUNCTION
35	ReasonEmptyHex   = "empty_hex"    // a shot at a hex nobody stood in: held (EvNothing)
36	ReasonOutOfFight = "out_of_fight" // a shot at a character killed, passed out, surrendered or run away: held (EvNothing)
37	ReasonOutOfRange = "out_of_range" // a throw farther than the weapon's wielding factor (17.2)
38	ReasonThrow      = "throw"        // aim spent by a throw (16.13); a thrown weapon landing (17.4)
39	ReasonGunMove    = "gun_move"     // a gun move dropping the gun in the hex (10.22)
40)
source

Delay and cancel reasons.

const MalfNoEffect, MalfMisfire, MalfNoPenalty

1const (
2	MalfNoEffect  = "no_effect"  // discarded, another card drawn (13.3)
3	MalfMisfire   = "misfire"    // the shot is cancelled (13.3)
4	MalfNoPenalty = "no_penalty" // second draw was a FIRE: the gun is fine (13.32)
5)
source

Malfunction results.

const StepShots, StepEnd, StepAction

1const (
2	StepShots  = 1
3	StepEnd    = 2
4	StepAction = 3 // + the seat acting
5)
source

Steps of a segment, in the order they resolve: the shots (7.52), each seat's action in seat order, then the end of the segment (the occupied-hex penalty, combat results, aims out of the zone). Events of one step happened together; a replay shows the steps one after the other. Turn-start and end-of-turn events have no step (0).

const MaxActionPoints, Segments, EndOfTurn, MinPlayers, MaxPlayers

 1const (
 2	// MaxActionPoints is the time points a plan may spend in a turn (rule 7.3).
 3	MaxActionPoints = 5
 4	// Segments is the number of segments in a turn (rule 4.1).
 5	Segments = 5
 6	// EndOfTurn is the Seg of events recorded after segment 5 (cancelled
 7	// actions, passing out, the end-of-showdown check); turn-start events
 8	// (SERIOUS fatigue, aim lost on the first reveal) have Seg 0.
 9	EndOfTurn = Segments + 1
10	// MinPlayers and MaxPlayers bound the seats of a game: the showdown's
11	// characters (Setups) fill the seats in order, each a side of its own.
12	MinPlayers = 2
13	MaxPlayers = 4
14)
source

const VPSurvive, VPHoldField, VPSurrender, VPCaptured, VPKilled, VPKill, VPKnockOut, VPRunAway

 1const (
 2	VPSurvive   = "survive"         // +2: conscious and unsurrendered at the end (15.62)
 3	VPHoldField = "hold_field"      // +2: the only side with survivors (15.63)
 4	VPSurrender = "surrender"       // -2 (15.41)
 5	VPCaptured  = "captured"        // -4: passed out or surrendered when the enemy holds the field (15.63, 15.7)
 6	VPKilled    = "killed"          // -8 (15.2)
 7	VPKill      = "kill_enemy"      // +2: the enemy who killed him (15.2)
 8	VPKnockOut  = "knock_out_enemy" // +1: the enemy who crossed off most of his endurance boxes (15.3, 15.41)
 9	VPRunAway   = "run_away"        // -2: moved off the map (15.5); no end-of-showdown points (15.6)
10)
source

Victory point awards (rule 15), for showdowns where each character is a side of its own: there are no allies (no "Ally killed"), and no special rule captures or kills anyone.

const ActionGunMove

1const ActionGunMove cards.Code = "gun_move"
source

ActionGunMove names a gun move in its cancel event.

const DeckSize

1const DeckSize = 108
source

DeckSize is the number of result cards.

const DrawJammed

1const DrawJammed = "jammed"
source

DrawJammed is the Result of a Draw & Cock that moves a jammed gun: it is not cocked (13.31).

const LoadUnjammed

1const LoadUnjammed = "unjammed"
source

LoadUnjammed is the Result of a load that completes a jammed gun (13.31).

const MaxAim

1const MaxAim = 8
source

MaxAim is the most AIM points a character can hold on a target (12.3).

const MaxGuns

1const MaxGuns = 3
source

MaxGuns is how many guns a character can carry (hands and holsters).

const NoSeat

1const NoSeat = -1
source

NoSeat is the seat value for "nobody": AIM markers on a hex, a wound or a death nobody inflicted.

const StartEndurance

1const StartEndurance = 20
source

StartEndurance is the endurance boxes a character starts with (14.2).

const VPSharedKill

1const VPSharedKill = 1
source

VPSharedKill is what each enemy gets when several KILLs land in the same segment: 15.2 shares the "Kill enemy" points, kept whole here.

const NoGun, Colt45

1const (
2	// NoGun marks an empty gun slot.
3	NoGun GunType = ""
4	// Colt45 is the one-handed six-shooter every character starts with.
5	Colt45 GunType = "colt45"
6)
source

const Kill, Stun, Stagger, Serious, DropGunHand, GunArm, DropOtherHand, OtherArm, LegWound, Light, LoseAimHit

 1const (
 2	Kill          PenaltyKind = "kill"       // killed, out of the game
 3	Stun          PenaltyKind = "stun"       // draws N wound cards and loses aim
 4	Stagger       PenaltyKind = "stagger"    // thrown to a hex and facing drawn on two direction cards, then drops
 5	Serious       PenaltyKind = "serious"    // N fatigue cards at the start of every turn; may kill at the end
 6	DropGunHand   PenaltyKind = "gun_hand"   // the weapon in the gun hand drops in the hex
 7	GunArm        PenaltyKind = "gun_arm"    // -N aim time with the gun hand
 8	DropOtherHand PenaltyKind = "other_hand" // the weapon in the other hand drops in the hex
 9	OtherArm      PenaltyKind = "other_arm"  // -N aim time with the other hand
10	LegWound      PenaltyKind = "leg"        // N fatigue cards per hex moved while upright
11	Light         PenaltyKind = "light"      // draws N fatigue cards
12	LoseAimHit    PenaltyKind = "lose_aim"   // loses the aim (STRIKING TABLE)
13)
source

const LoseAim, WildShot, Drop

 1const (
 2	// LoseAim: the character loses its aim (no aim is tracked yet).
 3	LoseAim Result = -1
 4	// WildShot: every cocked gun goes off without hitting anything, is
 5	// uncocked and loses a shell; the aim is lost.
 6	WildShot Result = -2
 7	// Drop: an upright character turns DOWN, draws 3 delay cards and loses
 8	// its aim; no effect when already DOWN.
 9	Drop Result = -3
10)
source

const Alive, Out, Killed, PassedOut, RanAway

 1const (
 2	// Alive characters plan and act.
 3	Alive Status = iota
 4	// Out characters (surrendered, or out of time) are skipped by Resolve.
 5	Out
 6	// Killed characters are out of the game (14.6).
 7	Killed
 8	// PassedOut characters carried more delay than endurance for two turns (14.2).
 9	PassedOut
10	// RanAway characters moved off the map (15.5): out of the showdown,
11	// their hex the edge hex they left from.
12	RanAway
13)
source

Variables 4

var Cards

1var Cards = buildCards()
source

Cards is the result deck in card order, index 0 = card 1.

var CharKeys

 1var CharKeys = []string{
 2	"andy", "axe", "banker", "barkeep", "border_rider", "cattle_baron",
 3	"chief", "clerk", "driver", "dude", "eagle", "el_jefe", "fast_draw",
 4	"fast_eddie", "floozy", "foreman", "gambler", "guard", "gun_artist",
 5	"happy", "hawk", "ike", "innocente", "john_henry", "lady", "lightning",
 6	"ling_ho", "little_ernie", "lucky", "marshal", "mountain_man", "nco",
 7	"old_man", "owner", "prospector", "quiet_man", "reb", "running_boy",
 8	"slim", "smith", "sodbuster", "texas", "the_drifter", "the_kid",
 9	"u_s_scout", "veteran", "woman", "yankee",
10}
source

CharKeys are the 48 character tokens a player can pick.

var Setups

1var Setups = []CharSetup{
2	{Char: "marshal", Hexes: []string{"A-D5", "A-D6", "A-D7", "A-E6", "A-E7"}, Facing: hex.SE},
3	{Char: "the_kid", Hexes: []string{"A-H5", "A-H6", "A-H7", "A-G6", "A-G7"}, Facing: hex.NW},
4	{Char: "reb", Hexes: []string{"A-E8", "A-F7", "A-F8", "A-G8"}, Facing: hex.N},
5	{Char: "yankee", Hexes: []string{"A-E5", "A-F5", "A-F4", "A-G5"}, Facing: hex.S},
6}
source

Setups is the showdown played, one character per seat in seat order, each a side of its own, around the middle of the corral: the Marshal on the west side in D5-D7, E6 and E7, the Kid on the east side in H5-H7, G6 and G7, Reb to the south in E8, F7, F8 and G8, Yankee to the north in E5, F5, F4 and G5. They face the middle: a flat-top grid has no west or east, so the Marshal looks south-east and the Kid north-west; Reb looks north, Yankee south. A character with no entry is not in the showdown; a game of n seats uses the first n.

var VPPoints

 1var VPPoints = map[string]int{
 2	VPSurvive:   2,
 3	VPHoldField: 2,
 4	VPSurrender: -2,
 5	VPCaptured:  -4,
 6	VPKilled:    -8,
 7	VPKill:      2,
 8	VPKnockOut:  1,
 9	VPRunAway:   -2,
10}
source

VPPoints is what each award is worth (the VICTORY POINTS schedule, 15.11). Passing out is worth 0 and makes no award.

Functions 34

func AliveCount

1func AliveCount(s State) int
source

AliveCount counts the characters still in the fight.

func CanSetUp

1func CanSetUp(charKey, id string) bool
source

CanSetUp reports whether charKey may set up in hex id: one of its hexes.

func DecodeInts

1func DecodeInts(s string) []int
source

DecodeInts unpacks what EncodeInts produced.

func EncodeCharacter

1func EncodeCharacter(c Character) string
source

EncodeCharacter packs a character, guns included; DecodeCharacter unpacks it.

func EncodeChars

1func EncodeChars(cs []Character) string
source

EncodeChars packs the characters of a state (a turn's starting snapshot), seats in order; DecodeChars unpacks them.

func EncodeEvents

1func EncodeEvents(evs []Event) string
source

EncodeEvents packs events into one string; DecodeEvents unpacks it.

func EncodeGround

1func EncodeGround(ground []GroundGun) string
source

EncodeGround packs the weapons lying on the board (a turn's ground at its start), ';'-separated records of id, hex and gun ("1|A-G6|1:colt45:0:0:6:0:0"); DecodeGround unpacks them, skipping a malformed record.

func EncodeInts

1func EncodeInts(ns []int) string
source

EncodeInts packs numbers (the cards drawn in a turn); DecodeInts unpacks them.

func EndShowdown

1func EndShowdown(s State, d Drawer) (State, []Event)
source

EndShowdown is the end-of-game check (14.5): every character with SERIOUS wounds draws a result card and is killed when its DELAY number plus the wound points reaches four; the enemy who gave the most SERIOUS points gets the kill, enemies tied for the most share it (15.21). The state given is left as it is.

func EndTurn

1func EndTurn(s State) (State, []Event)
source

EndTurn is the end-of-turn upkeep (rule 5.6): half of the delay points are removed, rounded up, the per-turn flags are cleared, and a character left with more delay than endurance for the second turn in a row passes out (14.2; checked after the halving). The state given is left as it is.

func IsCharKey

1func IsCharKey(s string) bool
source

IsCharKey reports whether s names one of the character tokens.

func Resolve

1func Resolve(board *hex.Board, st State, plans []Plan, d Drawer) (State, []Event)
source

Resolve plays the plans, one per seat, over the five segments of a turn (rules 5.5, 6, 7, 9, 12, 13, 14), deterministic for a given Drawer; the state given is left as it is. Choices were committed up front and are resolved against each character's live state as the stacks play out.

Each segment, every alive character whose next action is due (usedTime + cost + delay <= segment) executes it once, shots first (7.52), in seat order. Delay gained during a segment and the results of hits take effect from the end of the segment ([H6], 14.1). Actions still pending after segment 5 are cancelled.

func SeatChar

1func SeatChar(seat int) string
source

SeatChar is the character of a seat, "" for a seat the showdown does not have.

func Seed

1func Seed(parts ...string) [32]byte
source

Seed hashes the given parts into shuffle seed material.

func ShowdownChars

1func ShowdownChars() []string
source

ShowdownChars lists the characters of the showdown, seats in order.

func VPTotals

1func VPTotals(awards []Award, n int) []int
source

VPTotals adds the awards up per seat, for n seats.

func EndVictoryPoints

1func EndVictoryPoints(s State) []Award
source

EndVictoryPoints scores the end of the showdown (15.6): a character still up survives, and holds the field when it is the only one (15.62, 15.63); Out stands for a surrendered character, who loses the "Surrender" points and, like passing out, gives "Knock out enemy" to the enemy who crossed off most of its endurance boxes (15.41); passed out or surrendered, a character is captured when an enemy holds the field (15.63, 15.7).

func TurnVictoryPoints

1func TurnVictoryPoints(before, after State) []Award
source

TurnVictoryPoints scores what a turn did, from the characters before and after it: a character killed loses the "Killed" points and the enemy whose hit killed it gets "Kill enemy" (15.2, Character.Killers), or, when several enemies share the kill, 1 point each (kept whole); one who passed out gets nothing and the enemy who crossed off most of its endurance boxes "Knock out enemy" (15.3, Character.Hurt). A character who is not up cannot be hit, so a knocked-out one is never killed afterwards.

func SetupOf

1func SetupOf(charKey string) *CharSetup
source

SetupOf returns the set up of a character, nil when it is not in the showdown.

func CloneChars

1func CloneChars(cs []Character) []Character
source

CloneChars copies the characters field by field. A plain copy of the slice is not enough on a node: a character written earlier in the same transaction stays shared with the live state, so a turn's stored start would show its end position.

func DecodeCharacter

1func DecodeCharacter(s string) Character
source

DecodeCharacter unpacks what EncodeCharacter produced.

func DecodeChars

1func DecodeChars(s string) []Character
source

DecodeChars unpacks what EncodeChars produced.

func NewDeck

1func NewDeck(seed [32]byte) *Deck
source

NewDeck shuffles the 108 cards with the seed.

func DecodeEvents

1func DecodeEvents(s string) []Event
source

DecodeEvents unpacks what EncodeEvents produced.

func VPEvents

1func VPEvents(awards []Award) []Event
source

VPEvents are the awards as end-of-turn events of the turn's log.

func DecodeGround

1func DecodeGround(s string) []GroundGun
source

DecodeGround unpacks what EncodeGround produced.

func HandLocation

1func HandLocation(code int) (GunLocation, bool)
source

HandLocation maps a plan hand code to the location it designates.

func StrikingBullseye

1func StrikingBullseye(line byte) HitLoc
source

StrikingBullseye is where a thrower's bullseye lands, its choice (the summary of actions): the location of the weapon's STRIKING TABLE line that hurts most, the HEAD for line B (LIGHT 6 and LOSE AIM).

func Impact

1func Impact(line byte, loc HitLoc) []Penalty
source

Impact is the IMPACT TABLE: the penalties a hit location inflicts for a gun's table line (rule 13.8). Only line B, the Colt 45's, is transcribed (from the VASSAL module's table); other lines come with their guns.

func Strengthen

1func Strengthen(pens []Penalty, n int) []Penalty
source

Strengthen adds a STRENGTH's damage to each GUN ARM, OTHER ARM, LEG, SERIOUS, LIGHT and STUN penalty of a hit (20.21); the others are left as they are.

func Striking

1func Striking(line byte, loc HitLoc) []Penalty
source

Striking is the STRIKING TABLE (16.23): the penalties a throw (or, later, an attack) inflicts for a weapon's table line and the hit location. Only line B, the one-handed guns' (with the pail, dynamite, bottle and ammo sources), is transcribed; other lines come with their weapons.

func ParsePlan

1func ParsePlan(s string) (Plan, error)
source

ParsePlan parses the plan string. It checks the syntax and that every card side exists; Validate checks the game rules.

func Card

1func Card(n int) ResultCard
source

Card returns result card n (1 to 108).

func NewState

1func NewState(n int) State
source

NewState is a showdown of n characters before anyone set up: each upright with its starting guns and endurance, standing nowhere yet (Hex "") until SetUp gives it its hex and facing ([H3], setup.gno).

Types 28

type Action

struct
 1type Action struct {
 2	Card   int
 3	Side   byte // cards.FrontSide or cards.BackSide
 4	Code   cards.Code
 5	Cost   int
 6	Dir    hex.Rel // committed relative direction, "" when the side takes none
 7	Gun    int     // id of the character's gun for a gun choice (Draw & Cock), 0 when none
 8	Ground int     // id of the gun on the ground to pick up (Draw & Cock, "g<id>"), 0 when none
 9	Hand   int     // destination hand code for a gun choice (HandGun...), -1 when the side takes none
10	Opt    string  // option of Cock/Aim/Shoot, Shoot and Throw (OptCock...) or Strength (OptDamage, OptWield), "" when the side takes none
11	Hex    string  // the hex named by an aim, a shot or a throw at a hex
12	Target int     // the seat named by an aim, a shot or a throw at a character; -1 otherwise
13	// Wield and Damage are what the STRENGTHs played on top of a Throw add
14	// to the weapon's wielding factor and to the penalties (20.2), set by
15	// Combine.
16	Wield  int
17	Damage int
18	// Moves are the gun moves done when the action is revealed (10.22),
19	// written before it in the plan string.
20	Moves []GunMove
21}
source

Action is one card side chosen for the turn, with its committed choice.

Methods on Action

func AimTime

method on Action
1func (a Action) AimTime(oneHanded bool) int
source

AimTime is the aim time printed on a shooting action or a Throw for a one- or two-handed weapon (13.52, 17.3).

func IsShot

method on Action
1func (a Action) IsShot() bool
source

IsShot reports whether the action fires the gun.

func IsThrow

method on Action
1func (a Action) IsThrow() bool
source

IsThrow reports whether the action throws the weapon in hand (17.1).

type Award

struct
1type Award struct {
2	Player int
3	Reason string // one of the VP* names
4	Points int
5}
source

Award is victory points a character earns (Points > 0) or loses.

type Band

struct
1type Band struct{ Lo, Hi int }
source

Band is an inclusive range of aim times or ranges; Hi < 0 is open-ended.

Methods on Band

func Contains

method on Band
1func (b Band) Contains(n int) bool
source

Contains reports whether n falls in the band.

type CharSetup

struct
1type CharSetup struct {
2	Char   string
3	Hexes  []string
4	Facing hex.Dir
5}
source

CharSetup is where a character of the showdown sets up: the hexes it may stand in, and the way it faces unless its player turns it.

type Character

struct
 1type Character struct {
 2	Hex    string
 3	Facing hex.Dir
 4	Down   bool
 5	Delay  int // delay points on the sheet (rule 6)
 6	Status Status
 7	// PlayedFoot and PlayedRun record whether the current turn's plan holds
 8	// a foot action / a Run, whether or not it executes ([H12], rules 13.61-62).
 9	PlayedFoot bool
10	PlayedRun  bool
11	// RanLastTurn is PlayedRun carried over from the previous turn: Sprint
12	// needs a Run on the previous turn as well (rule 9.23, "build up speed").
13	RanLastTurn bool
14	// Dropped records a DROP penalty this turn ("Move" target status, 13.61).
15	Dropped bool
16	// Guns carried (section 10).
17	Guns Guns
18	// Aim is the AIM points on the target (12.2). AimAt is the seat of the
19	// character the markers follow, wherever it goes (12.3), NoSeat when
20	// they sit on the hex AimHex. Both are meaningless while Aim is 0.
21	Aim    int
22	AimAt  int
23	AimHex string
24	// Endurance is the boxes left on the sheet (14.2); wound and fatigue
25	// cards cross them off.
26	Endurance int
27	// Exhausted counts the consecutive turn ends with more delay than
28	// endurance; two in a row pass the character out (14.2).
29	Exhausted int
30	// Permanent wounds (14.12): fatigue cards per turn, aim time penalties
31	// per hand, fatigue cards per hex moved upright.
32	Serious  int
33	GunArm   int
34	OtherArm int
35	Leg      int
36	// Who did it, for the victory points (15.2, 15.21, 15.3), by seat: the
37	// seats credited with the kill (several when their KILLs landed in the
38	// same segment, or tied for the most SERIOUS points), the SERIOUS and
39	// LEG points each seat's wounds gave (the fatigue those wounds cost
40	// later is put down to it), and the endurance boxes each seat's hits
41	// crossed off.
42	Killers     [MaxPlayers]bool
43	SeriousFrom [MaxPlayers]int
44	LegFrom     [MaxPlayers]int
45	Hurt        [MaxPlayers]int
46}
source

Character is the mutable state of one gunslinger.

type Chart

struct
1type Chart struct {
2	Cols []Band
3	Rows []ChartRow
4}
source

Chart is the hit chart of a FIRE card: a hit location per aim-time row and range column.

Methods on Chart

func Lesser

method on Chart
1func (c *Chart) Lesser() HitLoc
source

Lesser is the hit the card's Target Status entries name: the chart's hit location other than a bullseye (every card has exactly one).

func Lookup

method on Chart
1func (c *Chart) Lookup(aim, rng int) HitLoc
source

Lookup is the preliminary hit location for an aim time and a range; off the chart is a miss (rule 13.5).

type ChartRow

struct
1type ChartRow struct {
2	Aim   Band
3	Cells []HitLoc
4}
source

ChartRow is one aim-time row of a Chart.

type Deck

struct
1type Deck struct {
2	r     *rand.Rand
3	order [DeckSize]int // card numbers in deal order
4	next  int
5	drawn []int // every card dealt so far, in order
6}
source

Deck is the result deck shuffled once from a seed and dealt in order (rule 5.7: the deck is reshuffled when exhausted). The same seed always deals the same cards, so a turn can be replayed from its stored seed.

Methods on Deck

func Draw

method on Deck
1func (d *Deck) Draw() ResultCard
source

Draw implements Drawer: the next card of the shuffle, reshuffling the whole deck once every card has been dealt.

func Drawn

method on Deck
1func (d *Deck) Drawn() []int
source

Drawn returns the numbers of every card dealt so far, in order: the trace of a turn's draws.

func Order

method on Deck
1func (d *Deck) Order() [DeckSize]int
source

Order returns the card numbers in the order the deck deals them.

type Drawer

interface
1type Drawer interface {
2	// Draw returns the next result card.
3	Draw() ResultCard
4}
source

Drawer hands out result cards to Resolve.

type Event

struct
 1type Event struct {
 2	Seg       int
 3	Player    int
 4	Kind      string
 5	Action    cards.Code
 6	From      string
 7	To        string
 8	Facing    hex.Dir
 9	Down      bool
10	N         int
11	Delay     int
12	Reason    string
13	Card      int     // the result card drawn (0 when none)
14	Result    string  // a card's penalty, a malfunction result or a wound's penalty kind
15	Endurance int     // endurance boxes crossed off by a wound or fatigue card
16	Target    int     // the seat shot at, for shots
17	Hit       string  // the final hit location of a shot (Miss "-")
18	Range     int     // the range of a shot, in hexes
19	Gun       GunType // the gun's model, for gun events
20	GunID     int     // the gun's id, for gun events
21	Step      int     // which part of the segment it belongs to (StepShots, StepEnd, StepAction+seat), 0 outside the segments
22	Chart     string  // a shot's preliminary hit read on the FIRE card's chart, before Target Status ("" when no chart was read)
23	Status    string  // the Target Status letters (StatusMove...) that changed a shot's hit, "" when none did
24}
source

Event is one thing that happened during resolution, in order. Seg is 0 for turn-start events and EndOfTurn for those after segment 5.

type Fixed

ident
1type Fixed int
source

Fixed is a Drawer that always deals the same card; tests use Fixed(37) (DELAY 1) to match the BGA reference engine's stub.

Methods on Fixed

func Draw

method on Fixed
1func (f Fixed) Draw() ResultCard
source

Draw implements Drawer.

type GroundGun

struct
1type GroundGun struct {
2	ID  int
3	Hex string
4	Gun Gun
5}
source

GroundGun is a weapon lying in a hex (10.21). ID identifies it on the ground for the whole game (plans refer to it as "g<ID>"); the gun's own ID was its previous owner's and is reassigned when picked up.

type Gun

struct
1type Gun struct {
2	ID       int
3	Type     GunType
4	Location GunLocation
5	Cocked   bool
6	Shells   int
7	Jammed   bool // every shell crossed off; fires again once completely reloaded (13.31)
8	Exploded bool // cannot fire for the rest of the game (13.31)
9}
source

Gun is one weapon carried by a character. ID identifies it for the whole game (plans refer to it), even among several guns of the same model.

Methods on Gun

func CanFireFrom

method on Gun
1func (g Gun) CanFireFrom() bool
source

CanFireFrom reports whether the gun is in a box it can shoot from (13.1): a one-handed gun in the gun hand or both hands, a two-handed one in both hands.

type GunLocation

ident
1type GunLocation int
source

GunLocation is where a character keeps a gun (the boxes of the sheet).

Methods on GunLocation

func String

method on GunLocation
1func (l GunLocation) String() string
source

String returns the location name used in JSON views.

type GunMove

struct
1type GunMove struct {
2	Gun int // id of the gun on the character's sheet
3	To  int // HandGun, HandOther or HandGround
4}
source

GunMove is what a character may do with its guns, for free, each time it reveals an action (10.22): move the gun in BOTH HANDS to one hand, or drop a gun from a hand box into its hex. The other hand, like Draw & Cock's, comes with a second gun: Validate refuses it for now. Its plan string entry, "h<gun id>:<to>", comes before the action it goes with: To is HandGun (0) or HandOther (1), or "g" (HandGround) to drop it ("h1:g,1f:ahead": drop the Colt as the Advance is revealed). Whether the gun is there, where the move needs it, is checked when it is done: it may be one picked up earlier in the plan.

Methods on GunMove

func String

method on GunMove
1func (m GunMove) String() string
source

String is the move's plan string entry.

type GunSpec

struct
1type GunSpec struct {
2	Name      string
3	Capacity  int
4	OneHanded bool
5	Impact    byte // its line of the IMPACT TABLE (see Impact)
6	Wielding  int  // its wielding factor: how far it can be thrown (16.21, 17.2)
7	Striking  byte // its line of the STRIKING TABLE (see Striking)
8}
source

GunSpec is the static data of a gun model (rules section 10 and the WEAPON LISTS).

type GunType

ident
1type GunType string
source

GunType identifies a weapon model.

Methods on GunType

func Spec

method on GunType
1func (t GunType) Spec() GunSpec
source

Spec returns the model's static data.

type Guns

array
1type Guns [MaxGuns]Gun
source

Guns is a character's weapons; empty slots have Type NoGun.

Methods on Guns

func At

method on Guns
1func (g Guns) At(loc GunLocation) int
source

At returns the slot of the gun held at a location, or -1.

func Blocked

method on Guns
1func (g Guns) Blocked(loc GunLocation, except int) bool
source

Blocked reports whether a gun other than the one in slot except holds loc, or a hand box overlapping it: BOTH HANDS takes the gun hand and the other hand, and either hand is taken by a gun in BOTH HANDS.

func Count

method on Guns
1func (g Guns) Count() int
source

Count is the number of guns carried.

func Find

method on Guns
1func (g Guns) Find(id int) int
source

Find returns the slot of the gun with the given id, or -1.

func Firing

method on Guns
1func (g Guns) Firing() int
source

Firing returns the slot of the gun held in a box it can shoot from (rule 11.3), or -1.

func Free

method on Guns
1func (g Guns) Free() int
source

Free returns an empty slot, or -1 when the character carries MaxGuns.

func NextID

method on Guns
1func (g Guns) NextID() int
source

NextID is a free id for a gun added to this character.

type HitLoc

ident
1type HitLoc string
source

HitLoc is a hit location on a FIRE card's hit chart (rule 13.5).

type Malfunction

struct
1type Malfunction struct {
2	Storebought bool // misfire with storebought shells
3	Handloaded  bool // misfire with handloaded shells (the Colt 45's)
4	CapAndBall  bool // misfire with cap-and-ball shells
5	Second      string
6}
source

Malfunction is the upper block of cards 101-108 (rule 13.3): whether the shot misfires per shell type, and the gun's fate on a second malfunction drawn after a misfire (13.31).

type Penalty

struct
1type Penalty struct {
2	Kind PenaltyKind
3	N    int
4}
source

Penalty is one combat result, with its number when the kind takes one.

type PenaltyKind

ident
1type PenaltyKind string
source

PenaltyKind names the combat results of the IMPACT TABLE (rules 14.11, 14.12).

type Plan

slice
1type Plan []Action
source

Plan is the ordered stack of actions a player committed for the turn.

Its string form, used as the transaction argument, is a comma-separated list of entries "<card><f|b>[:<choice>]", the choice being a relative direction for move and turn cards ("1f:ahead_left"), for Draw & Cock a gun and the hand it goes to ("9f:1:0": the character's gun 1 to the gun hand, "9f:g2:0": the gun lying in its hex with ground id 2; hand codes: 0 gun hand, 1 other hand, 2 both hands), or for Cock/Aim/Shoot and Shoot the option ("5f:aim:A-F6", "7f:shoot:@1"; a bare "7f" does nothing), for Throw the same ("6b:throw:@1", a bare "6b" does nothing), for Strength its use ("7b:damage", "7b:wield"), e.g. "1f:ahead_left,2f:ahead,3f"; gun moves ("h1:g", GunMove) come before the action they go with and do not count as actions. An empty string is a pass.

Methods on Plan

func Combine

method on Plan
1func (p Plan) Combine() Plan
source

Combine folds each run of STRENGTHs into the Throw it is played on top of (20.1): treated as part of that action, revealed with it, their time points added to its own, their bonuses in its Wield and Damage, their gun moves done as it is revealed. Validate has checked that each STRENGTH comes just before a Throw; one that does not is dropped.

func Cost

method on Plan
1func (p Plan) Cost() int
source

Cost is the total time points of the plan.

func Has

method on Plan
1func (p Plan) Has(code cards.Code) bool
source

Has reports whether the plan holds the action.

func PlayedFoot

method on Plan
1func (p Plan) PlayedFoot() bool
source

PlayedFoot reports whether the plan holds any foot action ([H12]).

func String

method on Plan
1func (p Plan) String() string
source

String is the canonical plan string, parseable by ParsePlan.

func Validate

method on Plan
1func (p Plan) Validate(c Character) error
source

Validate checks the plan against the selection rules for the character that will play it (port of the BGA actConfirmPlan checks).

type Result

ident
1type Result int
source

Result is one line of a result card: a number of points, or a named penalty (rules 14.1, 14.21). Points are 0 or more; penalties are negative.

Methods on Result

func IsPoints

method on Result
1func (r Result) IsPoints() bool
source

IsPoints reports whether the line is a number of points.

func String

method on Result
1func (r Result) String() string
source

String returns the penalty name used in events and JSON, or "" for points.

type ResultCard

struct
1type ResultCard struct {
2	N      int
3	Delay  Result
4	Wound  Result
5	Hex    hex.Rel
6	Fire   *Chart       // the hit chart of a FIRE card, nil on a MALFUNCTION
7	Status string       // Target Status letters of a FIRE card (StatusMove...)
8	Malf   *Malfunction // the block of a MALFUNCTION card, nil on a FIRE card
9}
source

ResultCard is one of the 108 result cards (rule 2.4): N is its number on the card. Delay and Wound are the DELAY and WOUND lines and Hex the HEX line (direction cards, 14.3: a relative direction, hex.Same or hex.Long). The upper block is either a FIRE hit chart with its Target Status letters (cards 1-100, see fire.gno) or a MALFUNCTION block (cards 101-108). The TAC line (optional rule 9) is not used by this game.

Methods on ResultCard

func IsFire

method on ResultCard
1func (c ResultCard) IsFire() bool
source

IsFire reports whether the card is a FIRE card (13.2).

type Sequence

slice
1type Sequence []int
source

Sequence is a Drawer dealing the given card numbers in order, then the last one forever; for tests.

Methods on Sequence

func Draw

method on Sequence
1func (s *Sequence) Draw() ResultCard
source

Draw implements Drawer.

type State

struct
1type State struct {
2	Chars     []Character
3	Ground    []GroundGun
4	GroundSeq int // last ground id handed out
5}
source

State is the whole game state the engine acts on: one character per seat, in seat order.

Methods on State

func Budget

method on State
1func (s State) Budget(p int) int
source

Budget is the time points seat p may plan this turn: the carried delay counts against the 5 points ([H5], rule 7.3).

func SetUp

method on State
1func (s *State) SetUp(p int, id string, f hex.Dir)
source

SetUp stands seat p's character upright in hex id facing f; the rest of its sheet is left as it is.

type Status

ident
1type Status int
source

Status is the participation state of a character.

Methods on Status

func String

method on Status
1func (s Status) String() string
source

String returns the status name used in JSON views.

Dependencies

Source Files 13