aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorFlorian Fischer <florian.fischer@muhq.space>2025-08-06 09:34:33 +0200
committerFlorian Fischer <florian.fischer@muhq.space>2025-08-06 09:34:33 +0200
commit8aedaa204ced2eec921af6d1c28df5cbf8593363 (patch)
tree4160ec5e4eac61bfb38166032b695b97cff8e717
parentafbdb034287adf961d20761b941a94946760337b (diff)
downloadmuhqs-game-8aedaa204ced2eec921af6d1c28df5cbf8593363.tar.gz
muhqs-game-8aedaa204ced2eec921af6d1c28df5cbf8593363.zip
consider houses when determining damage for a tile
-rw-r--r--go/game/attack.go24
-rw-r--r--go/game/attack_test.go8
-rw-r--r--go/game/cardImplementations_test.go9
-rw-r--r--go/game/permanent.go1
4 files changed, 34 insertions, 8 deletions
diff --git a/go/game/attack.go b/go/game/attack.go
index e7d2e836..83ea6383 100644
--- a/go/game/attack.go
+++ b/go/game/attack.go
@@ -22,15 +22,27 @@ func (a Attack) Valid() bool {
}
// DamageForTile returns the damage inflicted by this attack to a tile
-func (a Attack) DamageForTile(u *Unit, t *Tile) (int, bool) {
+func (a Attack) DamageForTile(u *Unit, t *Tile) (d int, ok bool) {
+ o := u.Tile().Position
+ trgt := t.Position
+ dist := DistanceBetweenPositions(o, trgt)
+
if a.flexAttack != nil {
- return a.flexAttack(u, t)
+ d, ok = a.flexAttack(u, t)
+ } else {
+ d = a.DamageInRange(dist)
+ ok = IsPositionInRange(o, trgt, a.MaxRange())
}
- o := u.Tile().Position
- trgt := t.Position
- d := DistanceBetweenPositions(o, trgt)
- return a.DamageInRange(d), IsPositionInRange(o, trgt, a.MaxRange())
+ if !ok {
+ return
+ }
+
+ if dist > 1 && t.Type == TileTypes.House {
+ return 0, false
+ }
+
+ return
}
// MaxRange returns the biggest attackable range.
diff --git a/go/game/attack_test.go b/go/game/attack_test.go
index a13b4795..52ba41a0 100644
--- a/go/game/attack_test.go
+++ b/go/game/attack_test.go
@@ -75,6 +75,9 @@ func TestPikeAttack(t *testing.T) {
tile := &Tile{Position: Position{1, 2}}
enterTile(NewUnitFromPath("base/cavalry", tile, NewMockPlayer()), tile)
+ house := &Tile{Position: Position{2, 1}, Type: TileTypes.House, Raw: "house"}
+ enterTile(NewUnitFromPath("base/cavalry", house, NewMockPlayer()), house)
+
// This test is crooked because the attack of the attacking unit is checked in flexAttack and not a.
d, ok := a.DamageForTile(u, tile)
if !ok {
@@ -83,4 +86,9 @@ func TestPikeAttack(t *testing.T) {
if d != u.Attack.DamageInRange(u.Attack.MaxRange()) {
t.Fatal("unexpected damage: amount", d)
}
+
+ d, ok = a.DamageForTile(u, house)
+ if ok || d != 0 {
+ t.Fatal("protected cavalry in range for pike attack")
+ }
}
diff --git a/go/game/cardImplementations_test.go b/go/game/cardImplementations_test.go
index fc051f4e..b962677c 100644
--- a/go/game/cardImplementations_test.go
+++ b/go/game/cardImplementations_test.go
@@ -68,9 +68,10 @@ func TestPikemanRange(t *testing.T) {
mapDef := `map: |1-
SSS
SSS
- SSS
+ SHS
symbols:
S: street
+ H: house
`
s := NewLocalState()
@@ -82,7 +83,8 @@ symbols:
p := s.addNewUnit(NewCard("base/pikeman"), Position{0, 0}, player)
c := s.addNewUnit(NewCard("base/cavalry"), Position{0, 2}, opo)
- ca := s.addNewUnit(NewCard("base/cavalry_archer"), Position{1, 2}, opo)
+ prot := s.addNewUnit(NewCard("base/cavalry_archer"), Position{1, 2}, opo)
+ ca := s.addNewUnit(NewCard("base/cavalry_archer"), Position{2, 1}, opo)
k := s.addNewUnit(NewCard("base/knight"), Position{2, 0}, opo)
attackable := utils.TypedSliceToInterfaceSlice(p.AttackableEnemyPermanents())
@@ -95,6 +97,9 @@ symbols:
if utils.InterfaceSliceContains(attackable, k) {
t.Fatal("knight is attackable")
}
+ if utils.InterfaceSliceContains(attackable, prot) {
+ t.Fatal("cavalry is protected")
+ }
a := NewAttackAction(p)
err := a.Target().AddSelection(c)
diff --git a/go/game/permanent.go b/go/game/permanent.go
index 48656931..09a8829c 100644
--- a/go/game/permanent.go
+++ b/go/game/permanent.go
@@ -139,6 +139,7 @@ func (p *permanentBase) adjustDamage(damage int) {
p.damage = 0
}
}
+
func (p *permanentBase) fight(Permanent) {}
func (p *permanentBase) addTmpEffect(tmpEffect string) {