master
Raw Download raw file
  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}