diff options
| author | Florian Fischer <florian.fischer@muhq.space> | 2023-02-15 13:13:06 +0100 |
|---|---|---|
| committer | Florian Fischer <florian.fischer@muhq.space> | 2025-01-27 16:43:49 +0100 |
| commit | f9ab2cfdb25eb3fcd85868a2e375326a9c8b6022 (patch) | |
| tree | b96f16e6cf4a6dcf93b9557a7219179ab2f46c8d /go/game/targets.go | |
| parent | 805cbf397589e5cb861f866713c2eb4bec9ce40b (diff) | |
| download | muhqs-game-f9ab2cfdb25eb3fcd85868a2e375326a9c8b6022.tar.gz muhqs-game-f9ab2cfdb25eb3fcd85868a2e375326a9c8b6022.zip | |
intermediate commit
* fix a lot of target and action bugs
* check target selection before adding it to the prompt
* use the store view for stores on the map
* fix card highlighting in CardGrid
* Only prompt for Upkeep-/DiscardActions if appropriate
* Add helper for areaEffects granting new FullActions
* Add Target() helper selecting the first target to the Action interface
* Fix BuyAction and DiscardAction targets
* Remember the stores a player has seen
Diffstat (limited to 'go/game/targets.go')
| -rw-r--r-- | go/game/targets.go | 99 |
1 files changed, 71 insertions, 28 deletions
diff --git a/go/game/targets.go b/go/game/targets.go index 99ba5085..440d8922 100644 --- a/go/game/targets.go +++ b/go/game/targets.go @@ -93,6 +93,19 @@ func (d *TargetDesc) requirement() TargetRequirement { case "*": return TargetRequirement{0, -1} default: + if strings.Contains(d.req, "-") { + tokens := strings.SplitN(d.req, "-", 2) + min, err := strconv.Atoi(tokens[0]) + if err != nil { + log.Fatalf("failed to parse target requirement %s: %v", d.req, err) + } + max, err := strconv.Atoi(tokens[1]) + if err != nil { + log.Fatalf("failed to parse target requirement %s: %v", d.req, err) + } + return TargetRequirement{min, max} + } + x, err := strconv.Atoi(d.req) if err != nil { log.Fatalf("failed to parse target requirement %s: %v", d.req, err) @@ -101,10 +114,17 @@ func (d *TargetDesc) requirement() TargetRequirement { } } -func (t *Target) RequireSelection() bool { - return len(t.sel) < t.requirement.min +func (t *Target) AddSelection(sel interface{}) (err error) { + if err = t.constraint(sel); err == nil { + t.sel = append(t.sel, sel) + } + return } +func (t *Target) RequireSelection() bool { return len(t.sel) < t.requirement.min } +func (t *Target) HasSelection() bool { return len(t.sel) > 0 } +func (t *Target) ClearSelection() { t.sel = []interface{}{} } + func (t *Target) Options() (options []interface{}) { candidates := targetCandidates(t.desc, t.s) @@ -116,22 +136,6 @@ func (t *Target) Options() (options []interface{}) { return options } -func (t *Targets) Options() (options []interface{}) { - return t.ts[t.idx].Options() -} - -func (t *Target) AddSelection(sel interface{}) { - t.sel = append(t.sel, sel) -} - -func (t *Targets) AddSelection(sel interface{}) { - t.ts[t.idx].AddSelection(sel) -} - -func (t *Targets) Next() { - t.idx++ -} - func (t *Target) CheckSelection(s *State) error { if t.RequireSelection() { return fmt.Errorf("Number of selected targets and required ones does not match") @@ -151,6 +155,25 @@ func (t *Target) CheckSelection(s *State) error { return nil } +func (t *Targets) AddSelection(sel interface{}) error { return t.ts[t.idx].AddSelection(sel) } + +func (t *Targets) HasSelections() bool { + for _, t := range t.ts { + if !t.HasSelection() { + return false + } + } + return true +} + +func (t *Targets) ClearSelections() { + for _, t := range t.ts { + t.ClearSelection() + } +} +func (t *Targets) Options() (options []interface{}) { return t.ts[t.idx].Options() } +func (t *Targets) Next() { t.idx++ } + func (t *Targets) CheckTargets(s *State) error { for _, target := range t.ts { if err := target.CheckSelection(s); err != nil { @@ -240,22 +263,26 @@ func attackableTargetConstraint(action Action) TargetConstraintFunc { } } -func rangeTargetConstraint(source interface{}, r int) TargetConstraintFunc { - var sourcePos Position - switch source := source.(type) { +func posFromTileOrPermanent(tileOrPermanent interface{}) Position { + switch obj := tileOrPermanent.(type) { case *Tile: - sourcePos = source.Position + return obj.Position case Permanent: - sourcePos = source.Tile().Position + return obj.Tile().Position default: - log.Fatalf("Unhandled source type %T in rangeTargetConstraint", source) + log.Fatalf("Unhandled source type %T in posFromTileOrPermanent", tileOrPermanent) + return INVALID_POSITION() } +} + +func rangeTargetConstraint(source interface{}, r int) TargetConstraintFunc { + sourcePos := posFromTileOrPermanent(source) return func(t interface{}) (err error) { - p, _ := t.(Permanent) - if !IsPositionInRange(sourcePos, p.Tile().Position, r) { + targetPos := posFromTileOrPermanent(t) + if !IsPositionInRange(sourcePos, targetPos, r) { err = fmt.Errorf("Position %v of target %v not in range %d of source's position %v", - p.Tile().Position, t, r, sourcePos) + targetPos, t, r, sourcePos) } return } @@ -419,6 +446,16 @@ func parseTileTargetConstraint(desc string, s *State, action Action) []TargetCon constraints = append(constraints, rangeTargetConstraint(action.Source(), 1)) } + if strings.Contains(desc, "free") { + constraints = append(constraints, func(t interface{}) (err error) { + tile := t.(*Tile) + if tile.IsFree() { + return nil + } + return fmt.Errorf("tile %v is occupied by %v", tile, tile.Permanent) + }) + } + return constraints } @@ -461,7 +498,13 @@ func parseCardTargetConstraint(desc string, s *State, action Action) []TargetCon case "hand": pocs = append(pocs, p.Hand) case "store": - pocs = append(pocs, p.Store) + if p.gameState.Map.HasStores() { + for _, s := range p.AvailableStores() { + pocs = append(pocs, s) + } + } else { + pocs = append(pocs, p.Store) + } case "discard pile": pocs = append(pocs, p.DiscardPile) } |
