diff options
Diffstat (limited to 'go/game/map.go')
| -rw-r--r-- | go/game/map.go | 180 |
1 files changed, 180 insertions, 0 deletions
diff --git a/go/game/map.go b/go/game/map.go index f2cf1c53..a83f4984 100644 --- a/go/game/map.go +++ b/go/game/map.go @@ -7,6 +7,7 @@ import ( "net/http" "os" "path" + "strconv" "strings" "golang.org/x/exp/slices" @@ -315,3 +316,182 @@ func (m *Map) HasStores() bool { func (m *Map) StoreOn(p Position) *Store { return m.Stores[p] } + +type randomMapDef struct { + types []TileType + stores int + farms int + players int + x, y int +} + +var mapGens = []func(*rand.Rand, randomMapDef) *Map{ + randomMapGen, + dotSymRandomMapGen, +} + +func randomMapGen(r *rand.Rand, def randomMapDef) *Map { + log.Debug("random map gen", "def", def) + m := &Map{ + Tiles: make([][]Tile, 0, def.y), + ResourceGain: DEFAULT_RESOURCE_GAIN, + StartDeckList: DEFAULT_START_DECK, + WinCondition: KingGame, + Stores: make(map[Position]*Store), + } + m.Prepare = func(s *LocalState) { + for _, t := range m.AllTiles() { + if t.Type != spawn { + continue + } + card := NewCard("misc/king") + tokens := strings.Split(t.Raw, " ") + id, _ := strconv.Atoi(tokens[len(tokens)-1]) + owner := s.PlayerById(id) + // TODO: Fix position index base. + s.addNewUnit(card, t.Position, owner) + } + } + + for y := range def.y { + m.Tiles = append(m.Tiles, make([]Tile, 0, def.x)) + for x := range def.x { + s := def.types[rand.Intn(len(def.types))].String() + t, _ := NewTileFromString(s, Position{x, y}) + m.Tiles[y] = append(m.Tiles[y], t) + } + } + + spawns := []Position{ + Position{0, 0}, + Position{def.x - 1, def.y - 1}, + Position{0, def.y - 1}, + Position{def.x - 1, 0}, + } + + // Prepare spawn tiles + for n := range def.players { + pos := spawns[n] + log.Debug("add spawn", "pos", pos) + t, _ := NewTileFromString(fmt.Sprintf("spawn player %d", n+1), pos) + m.Tiles[pos.Y][pos.X] = t + } + + // Place stores on non spawn tiles + if def.stores > 0 { + for range def.stores { + var pos Position + for { + pos = Position{r.Intn(def.x), r.Intn(def.y)} + if m.TileAt(pos).Type != spawn { + break + } + } + log.Debug("place store at", "pos", pos) + t, _ := NewTileFromString("store", pos) + m.Tiles[pos.Y][pos.X] = t + m.Stores[pos] = NewStore() + } + } + + // Place stores on non spawn tiles + if def.farms > 0 { + for range def.farms { + var pos Position + for { + pos = Position{r.Intn(def.x), r.Intn(def.y)} + tt := m.TileAt(pos).Type + if tt != spawn && tt != store { + break + } + } + log.Debug("place farm at", "pos", pos) + t, _ := NewTileFromString("farm", pos) + m.Tiles[pos.Y][pos.X] = t + } + } + + return m +} + +func dotSymRandomMapGen(r *rand.Rand, def randomMapDef) *Map { + def.x = def.x / 2 + // We place the stores symmetrically + def.stores = 0 + m := randomMapGen(r, def) + log.Debug("random map has dimensions", "x", len(m.Tiles[0]), "y", len(m.Tiles)) + + // point reflection + // max tiles to reflect in this row + mY := len(m.Tiles) - 1 + mX := len(m.Tiles[0]) - 1 + for y := mY; y >= 0; y = y - 1 { + for x := mX; x >= 0; x = x - 1 { + t := m.Tiles[y][x] + // Remove spawns at edge of reflection + if x == mX && t.Type == spawn { + t, _ = NewTileFromString("neutral", t.Position) + m.Tiles[y][x] = t + } + + rY := mY - y + rRow := m.Tiles[rY] + + rX := len(rRow) + rp := Position{rX, rY} + + log.Debug("reflect", "o", t.Position, "r", rp) + rt, _ := NewTileFromString(t.Raw, rp) + m.Tiles[rY] = append(rRow, rt) + } + } + + // prepare spawns + spawns := []Position{ + Position{len(m.Tiles[0]) - 1, def.y - 1}, + Position{len(m.Tiles[0]) - 1, 0}, + } + + for i := 2; i <= def.players; i = i + 2 { + pos := spawns[i/2-1] + spawn, _ := NewTileFromString(fmt.Sprintf("spawn player %d", i), pos) + m.Tiles[pos.Y][pos.X] = spawn + } + + // TODO: prepare stores + // centerX := def.x + + return m +} + +func RandomMapFromDef(seed int64, def randomMapDef) *Map { + r := rand.New(rand.NewSource(seed)) + n := rand.Intn(len(mapGens)) + return mapGens[n](r, def) +} + +func RandomMap(seed int64, players int) *Map { + n := rand.Intn(10) + 3 + types := []TileType{neutral, neutral} + exclude := []TileType{spawn, docks, gate, wall, tower, farm} + for range n { + for { + t := TileType(rand.Intn(9) + 1) + if !slices.Contains(exclude, t) { + types = append(types, t) + break + } + } + } + + def := randomMapDef{ + types: types, + players: players, + stores: rand.Intn(2), + farms: rand.Intn(2) * players, + x: rand.Intn(6) + 6, + y: rand.Intn(6) + 6, + } + + return RandomMapFromDef(seed, def) +} |
