diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2025-08-06 15:20:15 +0200 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-08-06 15:20:43 +0200 |
| commit | a0345c11f8035b300330e6b7c59a654c1e1e231d (patch) | |
| tree | 9dab905deb708b3c7a2675ee7a95d6d43087b286 | |
| parent | 0cff8c7704187224053a068a1b3a6c166ddfdd6d (diff) | |
| download | muhqs-game-a0345c11f8035b300330e6b7c59a654c1e1e231d.tar.gz muhqs-game-a0345c11f8035b300330e6b7c59a654c1e1e231d.zip | |
add more challenges
| -rw-r--r-- | go/client/challenges.go | 76 | ||||
| -rw-r--r-- | go/client/startMenu.go | 17 | ||||
| -rw-r--r-- | go/game/artifact.go | 1 | ||||
| -rw-r--r-- | go/game/challenge.go | 78 | ||||
| -rw-r--r-- | go/game/winCondition.go | 11 |
5 files changed, 155 insertions, 28 deletions
diff --git a/go/client/challenges.go b/go/client/challenges.go new file mode 100644 index 00000000..7a9e1ace --- /dev/null +++ b/go/client/challenges.go @@ -0,0 +1,76 @@ +package main + +import ( + "muhq.space/muhqs-game/go/activities" + "muhq.space/muhqs-game/go/game" + "muhq.space/muhqs-game/go/ui" +) + +type challenges struct { + ui.Collection + app *app + + playerName string +} + +func NewChallengesMenu(app *app, playerName string) *challenges { + m := &challenges{app: app, playerName: playerName} + m.Width = app.windowWidth + m.Height = app.windowHeight + + return m +} + +var availChallenges map[string]func(string) *game.LocalState + +func init() { + availChallenges = make(map[string]func(string) *game.LocalState) + availChallenges["Missionary"] = game.NewMissionaryChallenge + availChallenges["Cav. Archer"] = game.NewCavArcherChallenge + availChallenges["Random"] = game.NewRandomChallenge +} + +func (m *challenges) build() { + i := 0 + for ch, f := range availChallenges { + + m.AddWidget(ui.NewSimpleButton( + (m.Width-START_BUTTON_WIDTH)/2, + i*START_BUTTON_HEIGHT+50+i*25, + START_BUTTON_WIDTH, + START_BUTTON_HEIGHT, + ch, + func(*ui.SimpleButton) { + s := f(m.playerName) + m.startChallenge(s) + })) + i = i + 1 + } +} + +func (m *challenges) Update() error { + if m.Widgets() == nil { + m.build() + } + + if err := ui.Update(); err != nil { + return err + } + + return m.Collection.Update() +} + +func (m *challenges) Layout(width, height int) (int, int) { + return m.Width, m.Height +} + +func (m *challenges) 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/client/startMenu.go b/go/client/startMenu.go index 2c3225b9..aef43ab0 100644 --- a/go/client/startMenu.go +++ b/go/client/startMenu.go @@ -137,11 +137,9 @@ func (m *startMenu) build() { deckInput.Y+deckInput.Height+4*START_BUTTON_HEIGHT, START_BUTTON_WIDTH, START_BUTTON_HEIGHT, - "Challenge", + "Challenges", func(*ui.SimpleButton) { - m.playerName = playerInput.Text() - s := game.NewRandomChallenge(m.playerName) - m.startChallenge(s) + activities.PushActivity(NewChallengesMenu(m.app, playerInput.Text())) })) } @@ -189,14 +187,3 @@ 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/artifact.go b/go/game/artifact.go index 35c05893..d3b9f0b2 100644 --- a/go/game/artifact.go +++ b/go/game/artifact.go @@ -1,6 +1,5 @@ package game - type Artifact struct { permanentBase Solid int diff --git a/go/game/challenge.go b/go/game/challenge.go index b27ef162..6e314b26 100644 --- a/go/game/challenge.go +++ b/go/game/challenge.go @@ -5,25 +5,34 @@ import ( "math/rand" ) -func NewRandomChallenge(name string) *LocalState { +func prepState(playerName, mapName string) *LocalState { s := NewLocalState() - maps := []string{"2P-ring-street", "2P-river-king"} - if m, err := GetMap(maps[rand.Intn(len(maps))]); err != nil { + if m, err := GetMap(mapName); err != nil { log.Panic(err) } else { s.SetMap(m) } // Prepare the players - s.AddNewPlayer(name, NewDeck()) + s.AddNewPlayer(playerName, NewDeck()) // Add Opponent ai := s.AddNewPlayer("opponent", NewDeck()) ai.Ctrl = NewSimpleAiControl(ai) - switch rand.Intn(2) { + 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) @@ -85,20 +94,65 @@ func prepCavArcherChallenge(s *LocalState) *LocalState { 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) - } + 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 } - return winners + + _, 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) diff --git a/go/game/winCondition.go b/go/game/winCondition.go index d08f4135..ded9b0ca 100644 --- a/go/game/winCondition.go +++ b/go/game/winCondition.go @@ -43,3 +43,14 @@ func KingGame(s *LocalState) []*Player { } return winners } + +// DeathMatch returns the players without enemy &nits. +func DeathMatch(s *LocalState) []*Player { + winners := []*Player{} + for _, p := range s.players { + if len(s.EnemyUnits(p)) == 0 { + winners = append(winners, p) + } + } + return winners +} |
