board.gno
2.93 Kb · 105 lines
1package hex
2
3import "sort"
4
5// Board is the adjacency table of one game board. ids is sorted so lookups
6// can binary-search it; nbr[i][d] is the index in ids of the neighbour of
7// ids[i] in direction d, or -1 when the board edge lies that way.
8//
9// Boards are generated by scripts/gen_board_data.py and never mutated, so
10// sharing *Board values is safe.
11type Board struct {
12 name string
13 ids []string
14 nbr [][6]int
15 qr [][2]int // axial coordinates (q, r) of ids[i], see geom.gno
16 fence []uint8 // fenced hexsides of ids[i]: bit d for direction d (rule 35)
17 obstacles []int // indices of the obstacle hexes (rule 36)
18 // between lists the hex pairs an obstacle lies between for the line of
19 // sight (rule 31), computed by the generator from the printed coordinates
20 // and the obstacle's outline on the board image: {a, b, o} with a < b
21 // indices in ids and o an index in obstacles, sorted by (a, b, o).
22 between [][3]int
23}
24
25// Name returns the board letter, e.g. "A".
26func (b *Board) Name() string { return b.name }
27
28// Size returns the number of hexes.
29func (b *Board) Size() int { return len(b.ids) }
30
31// Index returns the position of id in the sorted id list, or -1.
32func (b *Board) Index(id string) int {
33 i := sort.SearchStrings(b.ids, id)
34 if i < len(b.ids) && b.ids[i] == id {
35 return i
36 }
37 return -1
38}
39
40// Has reports whether id is a hex of this board.
41func (b *Board) Has(id string) bool { return b.Index(id) >= 0 }
42
43// Neighbor returns the hex adjacent to id in direction d. ok is false when
44// id is unknown, d is invalid, or the board edge lies in that direction.
45func (b *Board) Neighbor(id string, d Dir) (nb string, ok bool) {
46 i := b.Index(id)
47 if i < 0 || !d.Valid() {
48 return "", false
49 }
50 j := b.nbr[i][d]
51 if j < 0 {
52 return "", false
53 }
54 return b.ids[j], true
55}
56
57// Neighbors returns the six neighbours of id in direction order; an empty
58// string marks the board edge. An unknown id yields six empty strings.
59func (b *Board) Neighbors(id string) [6]string {
60 var out [6]string
61 i := b.Index(id)
62 if i < 0 {
63 return out
64 }
65 for d, j := range b.nbr[i] {
66 if j >= 0 {
67 out[d] = b.ids[j]
68 }
69 }
70 return out
71}
72
73// Fenced reports whether a fence or hitching post (rule 35) runs along the
74// hexside of id in direction d, so that moving or staggering across it
75// costs two delay cards.
76func (b *Board) Fenced(id string, d Dir) bool {
77 i := b.Index(id)
78 if i < 0 || !d.Valid() || i >= len(b.fence) {
79 return false
80 }
81 return b.fence[i]&(1<<uint(d)) != 0
82}
83
84// Obstacle reports whether id is an obstacle hex (rule 36: a trough, a
85// table...), so that moving or staggering onto or off it costs two delay
86// cards.
87func (b *Board) Obstacle(id string) bool {
88 i := b.Index(id)
89 if i < 0 {
90 return false
91 }
92 for _, o := range b.obstacles {
93 if o == i {
94 return true
95 }
96 }
97 return false
98}
99
100// IDs returns a copy of the sorted hex ids.
101func (b *Board) IDs() []string {
102 out := make([]string, len(b.ids))
103 copy(out, b.ids)
104 return out
105}