Skip to content

Commit

Permalink
fix #241 and #242
Browse files Browse the repository at this point in the history
  • Loading branch information
AlexNisnevich committed May 22, 2023
1 parent 81a25c1 commit 8df6b84
Show file tree
Hide file tree
Showing 4 changed files with 36 additions and 3 deletions.
24 changes: 24 additions & 0 deletions src/main/scala/wordbots/AstValidator.scala
Original file line number Diff line number Diff line change
Expand Up @@ -16,6 +16,7 @@ case class AstValidator(mode: ValidationMode = ValidateUnknownCard) {
val baseRules: Seq[AstRule] = Seq(
NoUnimplementedRules,
NoChooseOrRewriteInTriggeredAction,
NoPayEnergyInTriggeredAction,
NoModifyingCostOfObjects,
OnlyRestoreHealth,
OnlyThisObjectPlayed,
Expand Down Expand Up @@ -89,6 +90,7 @@ object NoChooseOrRewriteInTriggeredAction extends AstRule {
node match {
case ChooseC(_, _) => Failure(ValidationError("Choosing targets not allowed for triggered actions."))
case ChooseO(_, _) => Failure(ValidationError("Choosing targets not allowed for triggered actions."))
case ChooseT(_, _) => Failure(ValidationError("Choosing targets not allowed for triggered actions."))
case RewriteText(_, _) => Failure(ValidationError("Rewriting text not allowed for triggered actions."))
case n: AstNode => validateChildren(this, n)
}
Expand All @@ -104,6 +106,28 @@ object NoChooseOrRewriteInTriggeredAction extends AstRule {
}
}

/**
* Disallow paying energy within triggered abilities,
* because there's no gameplay support for "rolling back" the action triggered if there's not enough energy to pay.
*/
object NoPayEnergyInTriggeredAction extends AstRule {
object NoPayEnergy extends AstRule {
override def validate(node: AstNode): Try[Unit] = {
node match {
case PayEnergy(_, _) => Failure(ValidationError("Paying energy is not supported within triggered abilities."))
case n: AstNode => validateChildren(this, n)
}
}
}

override def validate(node: AstNode): Try[Unit] = {
node match {
case TriggeredAbility(_, _) => validateChildren(NoPayEnergy, node)
case n: AstNode => validateChildren(this, n)
}
}
}

object NoModifyingCostOfObjects extends AstRule {
override def validate(node: AstNode): Try[Unit] = {
node match {
Expand Down
5 changes: 3 additions & 2 deletions src/main/scala/wordbots/Lexicon.scala
Original file line number Diff line number Diff line change
Expand Up @@ -82,7 +82,8 @@ object Lexicon {
(NP/N, λ {c: CardType => AllC(CardsInHand(AllPlayers, c))}),
(NP/NP, λ {c: CardCollection => AllC(c)}),
(NP/NP, λ {c: Collection => c}),
(NP/PP, λ {c: Collection => c})
(NP/PP, λ {c: Collection => c}),
((NP/PP)/N, λ {o: ObjectType => λ {c: ObjectCondition => ObjectsMatchingConditions(o, Seq(c))}})
)) +
("all" /?/ Seq("attributes", "stats") -> (N, AllAttributes: Sem)) +
("all energy" -> (NP, AllEnergy: Sem)) +
Expand Down Expand Up @@ -635,7 +636,7 @@ object Lexicon {
)) +
("within" -> Seq(
(PP/NP, λ {s: Spaces => WithinDistanceOf(s.num, ThisObject)}),
((PP/PP)/NP, λ {s: Spaces => λ {t: TargetObject => WithinDistanceOf(s.num, t)}}),
((PP/PP)/NP, λ {s: Spaces => λ {t: TargetObjectOrTile => WithinDistanceOf(s.num, t)}}),
((NP\NP)/NP, λ {s: Spaces => λ {c: ObjectsMatchingConditions => ObjectsMatchingConditions(c.objectType, c.conditions :+ WithinDistanceOf(s.num, ThisObject))}})
)) +
(Seq("you", "yourself") -> Seq(
Expand Down
2 changes: 1 addition & 1 deletion src/main/scala/wordbots/Semantics.scala
Original file line number Diff line number Diff line change
Expand Up @@ -182,7 +182,7 @@ object Semantics {
case class HasProperty(property: Property) extends ObjectCondition
case class NotC(cond: ObjectCondition) extends ObjectCondition
case object Unoccupied extends ObjectCondition
case class WithinDistanceOf(distance: Number, obj: TargetObject) extends ObjectCondition
case class WithinDistanceOf(distance: Number, obj: TargetObjectOrTile) extends ObjectCondition

sealed trait GlobalCondition extends AstNode
case class CollectionCountComparison(coll: Collection, comparison: Comparison) extends GlobalCondition
Expand Down
8 changes: 8 additions & 0 deletions src/test/scala/wordbots/ParserSpec.scala
Original file line number Diff line number Diff line change
Expand Up @@ -295,6 +295,9 @@ class ParserSpec extends FlatSpec with Matchers {
DealDamage(ChooseO(ObjectsMatchingConditions(Robot, List(ControlledBy(Opponent), WithinDistanceOf(Scalar(3), ObjectsMatchingConditions(Kernel ,List(ControlledBy(Self))))))), Scalar(3))
parse("Pay all your energy") shouldEqual PayEnergy(Self, EnergyAmount(Self))
parse("Spawn a copy of this object on an adjacent tile") shouldEqual SpawnObject(CopyOfC(ThisObject), ChooseT(TilesMatchingConditions(List(AdjacentTo(They))), Scalar(1)), Self)

// beta v0.20.2
parse("Deal 1 damage to all objects within 1 space of a tile") shouldEqual DealDamage(ObjectsMatchingConditions(AllObjects, Seq(WithinDistanceOf(Scalar(1), ChooseT(AllTiles)))), Scalar(1))
}

it should "treat 'with' as 'that has'" in {
Expand Down Expand Up @@ -716,5 +719,10 @@ class ParserSpec extends FlatSpec with Matchers {
it should "disallow choosing targets after a random target has been selected" in {
parse("Move a random robot 1 space") shouldBe a[Failure[_]] // Failure[ValidationError]
}

it should "disallow paying energy inside an ability" in {
parse("When this object deals damage, pay 1 energy to draw a card") shouldEqual
Failure(ValidationError("Paying energy is not supported within triggered abilities."))
}
}
// scalastyle:on line.size.limit

0 comments on commit 8df6b84

Please sign in to comment.