aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2025-07-24 12:17:26 -0400
committerFlorian Fischer <florian.fischer@muhq.space>2025-07-28 18:03:10 +0200
commit749dc58ced17662d9f6dd40bb44d315d12d3d48b (patch)
tree170a957d296dc82467310b7b22f66d2ad440dff7
parentce875a8454265ac4a17be25eeaa6e0b136936a56 (diff)
downloadmuhqs-game-749dc58ced17662d9f6dd40bb44d315d12d3d48b.tar.gz
muhqs-game-749dc58ced17662d9f6dd40bb44d315d12d3d48b.zip
add random challange aupport to the client
-rw-r--r--go/client/game.go8
-rw-r--r--go/client/startMenu.go22
-rw-r--r--go/game/challenge.go100
-rw-r--r--go/game/map.go6
4 files changed, 134 insertions, 2 deletions
diff --git a/go/client/game.go b/go/client/game.go
index 71fa6b4c..fdb72683 100644
--- a/go/client/game.go
+++ b/go/client/game.go
@@ -117,12 +117,16 @@ func (g *Game) loadMap(mapName string) *Game {
log.Fatal(err)
}
g.gameState.SetMap(m)
+ g.initMapUi()
+ return g
+}
+
+func (g *Game) initMapUi() {
g.mapView = ui.NewMapView(g.gameState)
g.AddWidget(g.mapView)
- storeTiles := m.FilterTiles(func(t *game.Tile) bool { return t.Type == game.TileTypes.Store })
+ storeTiles := g.gameState.Map().FilterTiles(func(t *game.Tile) bool { return t.Type == game.TileTypes.Store })
g.storesOnMap = len(storeTiles) > 0
- return g
}
func (g *Game) addActivePlayer(name string, deckList string) *Game {
diff --git a/go/client/startMenu.go b/go/client/startMenu.go
index a9ee5c48..2c3225b9 100644
--- a/go/client/startMenu.go
+++ b/go/client/startMenu.go
@@ -132,6 +132,17 @@ func (m *startMenu) build() {
m.startDeck = deckInput.Text()
m.startGame()
}))
+ m.AddWidget(ui.NewSimpleButton(
+ (m.Width-START_BUTTON_WIDTH)/2,
+ deckInput.Y+deckInput.Height+4*START_BUTTON_HEIGHT,
+ START_BUTTON_WIDTH,
+ START_BUTTON_HEIGHT,
+ "Challenge",
+ func(*ui.SimpleButton) {
+ m.playerName = playerInput.Text()
+ s := game.NewRandomChallenge(m.playerName)
+ m.startChallenge(s)
+ }))
}
func (m *startMenu) Update() error {
@@ -178,3 +189,14 @@ func (m *startMenu) startGame() {
activities.PushActivity(g.Start())
}
+
+func (m *startMenu) startChallenge(state game.State) {
+ g := newGame(m.app, state)
+
+ g.initMapUi()
+ p := state.PlayerByName(m.playerName)
+ g.activePlayerId = p.Id
+ g.initPlayerUi(p)
+
+ activities.PushActivity(g.Start())
+}
diff --git a/go/game/challenge.go b/go/game/challenge.go
new file mode 100644
index 00000000..9ce4515e
--- /dev/null
+++ b/go/game/challenge.go
@@ -0,0 +1,100 @@
+package game
+
+import (
+ "log"
+ "math/rand"
+)
+
+func NewRandomChallenge(name string) *LocalState {
+ s := NewLocalState()
+ maps := []string{"2P-ring-street", "2P-river-king"}
+ if m, err := GetMap(maps[rand.Intn(len(maps))]); err != nil {
+ log.Panic(err)
+ } else {
+ s.SetMap(m)
+ }
+
+ // Prepare the players
+ s.AddNewPlayer(name, NewDeck())
+ // Add Opponent
+ ai := s.AddNewPlayer("opponent", NewDeck())
+ ai.Ctrl = NewSimpleAiControl(ai)
+
+ switch rand.Intn(2) {
+ // Cavalry Archer Challenge
+ case 0:
+ return prepCavArcherChallenge(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(2) + 4
+ units := make([]*Card, 0, nUnits)
+ // 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))]
+ ai := s.PlayerById(2)
+ s.addNewUnit(u, tile.Position, ai)
+ }
+
+ s._map.WinCondition = func(*LocalState) []*Player {
+ winners := []*Player{}
+ for _, p := range s.players {
+ if len(s.EnemyUnits(p)) == 0 {
+ winners = append(winners, p)
+ }
+ }
+ return winners
+ }
+ }
+
+ return s
+}
+
+func prepBaseChallenge(s *LocalState) *LocalState {
+ p := s.PlayerById(1)
+ nCards := rand.Intn(6)
+ nCards = nCards + 3
+ NewRandomDeck(nCards, []SetIdentifier{Sets.Base, Sets.Magic, Sets.Equipments}).MoveInto(p.Store)
+
+ ai := s.PlayerById(2)
+ ai.Deck = NewRandomDeck(nCards, []SetIdentifier{Sets.Base})
+
+ return s
+}
diff --git a/go/game/map.go b/go/game/map.go
index 2b0bebd7..be541cdd 100644
--- a/go/game/map.go
+++ b/go/game/map.go
@@ -285,6 +285,12 @@ func (m *Map) FreeTiles() []*Tile {
return m.FilterTiles(func(t *Tile) bool { return t.IsFree() })
}
+func (m *Map) AvailableTilesFor(c *Card) []*Tile {
+ return m.FilterTiles(func(t *Tile) bool {
+ return t.IsAvailableForCard(c)
+ })
+}
+
func (m *Map) distributeStoreCards(cards PileOfCards, rand *rand.Rand) {
nStores := len(m.Stores)
stores := make([]*Store, 0, nStores)