master
1package main
2
3import (
4 "fmt"
5 "github.com/fatih/color"
6)
7
8type Map struct {
9 Scores []PlayerScore
10 Turn int
11 AttackIndex int //TODO figure out what this is
12 Generals []int
13 MapArray []int
14 CitiesArray []int
15 Width int
16 Height int
17 Size int
18 Tiles [][]Tile
19}
20
21type Tile struct {
22 Owner int // Player Index
23 Armies int
24 Terrain TerrainType // Terrain Type
25 Seen bool
26 Fog bool
27}
28
29type TerrainType int
30
31const (
32 EMPTY TerrainType = iota + 1
33 MOUNTAIN
34 OBSTACLE
35 CITY
36 CAPITAL // game calls this a GENERAL
37)
38
39func (m *Map) Print() {
40 fmt.Printf("Turn: %d\n", m.Turn)
41 for i := 0; i < m.Height; i++ {
42 for j := 0; j < m.Width; j++ {
43 m.Tiles[i][j].Print()
44 }
45 fmt.Println()
46 }
47 fmt.Println()
48}
49
50func (m *Map) Patch(u Update) {
51 m.MapArray = patch(m.MapArray, u.MapDiff)
52 m.CitiesArray = patch(m.CitiesArray, u.CitiesDiff)
53 m.Generals = u.Generals
54 m.Turn = u.Turn
55 m.Scores = u.Scores
56 // Init
57 if m.Tiles == nil {
58 m.Width = m.MapArray[0]
59 m.Height = m.MapArray[1]
60 m.Tiles = make([][]Tile, m.Height)
61 m.Size = m.Width * m.Height
62 for i := 0; i < m.Height; i++ {
63 m.Tiles[i] = make([]Tile, m.Width)
64 }
65 // TODO - assign to each tile their neighbors / valid moves
66 }
67 // Apply patch to Map/Tiles
68 for i := 0; i < m.Height; i++ {
69 for j := 0; j < m.Width; j++ {
70 // can i skip this after init? updating map array should propigate to tiles?
71 // need to do *int instead?
72 // currently the append way of doing the patch messes up the underlying array / pointers
73 // patch would need rewritten to update the values (not create a new array)
74 // This is a performance upgrade for another day
75 m.Tiles[i][j].Armies = m.MapArray[(i*m.Width)+j+2]
76 m.Tiles[i][j].DecodeTerrain(m.MapArray[(i*m.Width)+j+2+m.Size])
77 for k := range m.Generals {
78 if i*m.Width+j == m.Generals[k] {
79 m.Tiles[i][j].Owner = k
80 m.Tiles[i][j].Terrain = CAPITAL
81 }
82 }
83 for l := range m.CitiesArray {
84 if i*m.Width+j == m.CitiesArray[l] {
85 m.Tiles[i][j].Terrain = CITY
86 }
87 }
88 }
89 }
90}
91
92func patch(old []int, diff []int) (new []int) {
93 i := 0
94 for i < len(diff) {
95 if diff[i] > 0 {
96 new = append(new, old[len(new):(len(new)+diff[i])]...)
97 }
98 i++
99 if i < len(diff) && diff[i] > 0 {
100 new = append(new, diff[i+1:(i+1+diff[i])]...)
101 i += diff[i]
102 }
103 i++
104 }
105 return new
106}
107
108func (t *Tile) DecodeTerrain(terrain int) {
109 switch terrain {
110 case GENIO_EMPTY:
111 t.Seen = true
112 t.Fog = false
113 t.Terrain = EMPTY
114 t.Owner = 0
115 case GENIO_MOUNTAIN:
116 t.Seen = true
117 t.Fog = false
118 t.Terrain = MOUNTAIN
119 case GENIO_FOG:
120 t.Fog = true
121 t.Terrain = EMPTY
122 case GENIO_FOG_OBSTACLE:
123 // Retain knowledge.
124 // Obstacle can become a Mountain or City,
125 // not the other way around
126 if t.Terrain == 0 {
127 t.Terrain = OBSTACLE
128 }
129 t.Fog = true
130 default: // player owned
131 t.Seen = true
132 t.Fog = false
133 t.Owner = terrain // Player index
134 }
135}
136
137func (t *Tile) Print() {
138 p := color.New(color.FgWhite)
139 if t.Fog {
140 if t.Seen {
141 p.Add(color.BgHiBlue)
142 } else {
143 p.Add(color.BgHiBlue)
144 }
145 }
146 switch t.Terrain {
147 case EMPTY:
148 if t.Fog || t.Armies == 0 {
149 p.Printf(" _")
150 } else {
151 // TODO if owner != PlayerID of bot = ReD
152 p.Printf("%3d", t.Armies)
153 }
154 case MOUNTAIN:
155 p.Printf(" M")
156 case OBSTACLE:
157 p.Printf(" ?")
158 case CITY:
159 p.Add(color.BgCyan)
160 p.Printf("%3d", t.Armies)
161 case CAPITAL:
162 p.Add(color.Bold, color.BgHiMagenta)
163 p.Printf("%3d", t.Armies)
164 default:
165 p.Add(color.FgRed)
166 p.Printf("%3d", t.Armies)
167 }
168
169}