package game import ( "log" "math/rand" ) func prepState(playerName, mapName string) *LocalState { s := NewLocalState() if m, err := GetMap(mapName); err != nil { log.Panic(err) } else { s.SetMap(m) } // Prepare the players s.AddNewPlayer(playerName, NewDeck()) // Add Opponent ai := s.AddNewPlayer("opponent", NewDeck()) ai.Ctrl = NewSimpleAiControl(ai) return s } func NewRandomChallenge(name string) *LocalState { maps := []string{"2P-ring-street", "2P-river-king"} m := maps[rand.Intn(len(maps))] s := prepState(name, m) switch rand.Intn(3) { // Cavalry Archer Challenge case 0: return prepCavArcherChallenge(s) case 1: return prepMissionaryChallenge(s) // Random Base Challenge default: return prepBaseChallenge(s) } } func prepCavArcherChallenge(s *LocalState) *LocalState { // Override old Prepare to prevent Kings from beeing spawned s._map.Prepare = func(*LocalState) { u := NewCard("base/cavalry_archer") tiles := s._map.AvailableTilesFor(u) tile := tiles[rand.Intn(len(tiles))] p := s.PlayerById(1) p.Deck = NewDeck() s.addNewUnit(u, tile.Position, p) // Prepare the opponent's units nUnits := rand.Intn(3) + 2 // add support equipment if nUnits > 3 { candidates := NewDeckFromCardPaths(Sets.Base.CardPaths()).FilterCards(func(c *Card) bool { return c.Type == CardTypes.Equipment }) e := NewCard(candidates[rand.Intn(len(candidates))].Path()) tiles := s._map.AvailableTilesFor(e) tile := tiles[rand.Intn(len(tiles))] s.addNewEquipment(e, tile.Position, p) } units := make([]*Card, 0, nUnits) ai := s.PlayerById(2) // Only use Melee Units candidates := NewDeckFromCardPaths(Sets.Base.CardPaths()).FilterCards(func(c *Card) bool { if c.Type != CardTypes.Unit { return false } // Disallow armor since the cavalry archer can not penetrate it. if _, err := c.getXEffect("armor"); err == nil { return false } var attack Attack if attackDesc, found := c.Values["attack"]; found { attack = parseAttack(attackDesc) return attack.MaxRange() == 1 } return false }) for range nUnits { units = append(units, NewCard(candidates[rand.Intn(len(candidates))].Path())) } for _, u := range units { tiles := s._map.AvailableTilesFor(u) tile := tiles[rand.Intn(len(tiles))] s.addNewUnit(u, tile.Position, ai) } s._map.WinCondition = DeathMatch } return s } func NewCavArcherChallenge(playerName string) *LocalState { maps := []string{"2P-ring-street", "2P-river-king"} m := maps[rand.Intn(len(maps))] return prepCavArcherChallenge(prepState(playerName, m)) } func prepMissionaryChallenge(s *LocalState) *LocalState { // Override old Prepare to prevent Kings from beeing spawned s._map.Prepare = func(*LocalState) { u := NewCard("base/missionary") tiles := s._map.AvailableTilesFor(u) tile := tiles[rand.Intn(len(tiles))] p := s.PlayerById(1) p.Deck = NewDeck() s.addNewUnit(u, tile.Position, p) // Prepare the opponent's units nUnits := rand.Intn(2) + 2 units := make([]*Card, 0, nUnits) ai := s.PlayerById(2) // Only spawn aggressive Units candidates := NewDeckFromCardPaths(Sets.Base.CardPaths()).FilterCards(func(c *Card) bool { if c.Type != CardTypes.Unit { return false } _, found := c.Values["attack"] return found }) for range nUnits { units = append(units, NewCard(candidates[rand.Intn(len(candidates))].Path())) } for _, u := range units { tiles := s._map.AvailableTilesFor(u) tile := tiles[rand.Intn(len(tiles))] s.addNewUnit(u, tile.Position, ai) } s._map.WinCondition = DeathMatch } return s } func NewMissionaryChallenge(playerName string) *LocalState { maps := []string{"2P-ring-street", "2P-river-king"} m := maps[rand.Intn(len(maps))] return prepMissionaryChallenge(prepState(playerName, m)) } func prepBaseChallenge(s *LocalState) *LocalState { p := s.PlayerById(1) nCards := rand.Intn(6) nCards = nCards + 3 d := NewRandomDeck(nCards, []SetIdentifier{Sets.Base, Sets.Magic, Sets.Equipments}) p.Store.AddCards(d.FilterCards(func(c *Card) bool { return c.IsBuyable() })) ai := s.PlayerById(2) ai.Deck = NewRandomDeck(nCards, []SetIdentifier{Sets.Base}) return s }