From 540fe10fa530e6537b8ba549a34eeb041a3445c2 Mon Sep 17 00:00:00 2001 From: TRT <> Date: Thu, 25 Nov 2021 09:52:06 +0100 Subject: [PATCH 1/5] Moraug: improve AI --- forge-ai/src/main/java/forge/ai/AiController.java | 1 + forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt | 2 +- 2 files changed, 2 insertions(+), 1 deletion(-) diff --git a/forge-ai/src/main/java/forge/ai/AiController.java b/forge-ai/src/main/java/forge/ai/AiController.java index 659179520c0..1024f65a9ee 100644 --- a/forge-ai/src/main/java/forge/ai/AiController.java +++ b/forge-ai/src/main/java/forge/ai/AiController.java @@ -1622,6 +1622,7 @@ public class AiController { Map params = t.getMapParams(); if ("ChangesZone".equals(params.get("Mode")) && params.containsKey("ValidCard") + && (!params.containsKey("AILogic") || !params.get("AILogic").equals("SafeToHold")) && !params.get("ValidCard").contains("nonLand") && ((params.get("ValidCard").contains("Land")) || (params.get("ValidCard").contains("Permanent"))) && "Battlefield".equals(params.get("Destination"))) { diff --git a/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt b/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt index 105983e0e91..c26b816da3f 100644 --- a/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt +++ b/forge-gui/res/cardsfolder/m/moraug_fury_of_akoum.txt @@ -4,7 +4,7 @@ Types:Legendary Creature Minotaur Warrior PT:6/6 S:Mode$ Continuous | Affected$ Creature.YouCtrl | AddPower$ AffectedX | Description$ Each creature you control gets +1/+0 for each time it has attacked this turn. SVar:AffectedX:Count$CardNumAttacksThisTurn -T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | PlayerTurn$ True | Phase$ Main1,Main2 | Execute$ TrigAddPhase | TriggerDescription$ Landfall - Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. +T:Mode$ ChangesZone | Origin$ Any | Destination$ Battlefield | AILogic$ SafeToHold | ValidCard$ Land.YouCtrl | TriggerZones$ Battlefield | PlayerTurn$ True | Phase$ Main1,Main2 | Execute$ TrigAddPhase | TriggerDescription$ Landfall - Whenever a land enters the battlefield under your control, if it's your main phase, there's an additional combat phase after this phase. At the beginning of that combat, untap all creatures you control. SVar:TrigAddPhase:DB$ AddPhase | ExtraPhase$ Combat | ConditionPhases$ Main1,Main2 | ExtraPhaseDelayedTrigger$ DelTrigUntap | ExtraPhaseDelayedTriggerExcute$ TrigUntapAll SVar:DelTrigUntap:Mode$ Phase | Phase$ BeginCombat | ValidPlayer$ You | TriggerDescription$ At the beginning of that combat, untap all creatures you control. SVar:TrigUntapAll:DB$ UntapAll | ValidCards$ Creature.YouCtrl From 8ebbaa395ad8e7d333b9cf1468904de013ef244f Mon Sep 17 00:00:00 2001 From: TRT <> Date: Thu, 25 Nov 2021 10:25:58 +0100 Subject: [PATCH 2/5] Clean up --- .../forge/ai/ability/ChooseEvenOddAi.java | 4 +--- .../java/forge/ai/ability/ChooseNumberAi.java | 3 +-- .../java/forge/ai/ability/ChooseSourceAi.java | 3 +-- .../forge/ai/ability/CopySpellAbilityAi.java | 3 +-- .../main/java/forge/ai/ability/CounterAi.java | 6 ++--- .../main/java/forge/ai/ability/PumpAllAi.java | 23 ++++++++++--------- .../java/forge/ai/ability/TwoPilesAi.java | 3 +-- .../java/forge/ai/ability/UnattachAllAi.java | 4 +--- 8 files changed, 20 insertions(+), 29 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java index 2a6e465865a..67872d6fa44 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseEvenOddAi.java @@ -14,8 +14,7 @@ public class ChooseEvenOddAi extends SpellAbilityAi { if (!sa.hasParam("AILogic")) { return false; } - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); if (sa.canTarget(opp)) { @@ -34,4 +33,3 @@ public class ChooseEvenOddAi extends SpellAbilityAi { } } - diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java index 06d132f5347..8cb8daae886 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseNumberAi.java @@ -44,8 +44,7 @@ public class ChooseNumberAi extends SpellAbilityAi { return ownCreatureCount > oppMaxCreatureCount + 2 || ownCreatureCount < Math.min(oppMaxCreatureCount, maxChoiceLimit); } - TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); Player opp = AiAttackController.choosePreferredDefenderPlayer(aiPlayer); if (sa.canTarget(opp)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java b/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java index 7e2805a9add..13c71d9cedb 100644 --- a/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/ChooseSourceAi.java @@ -52,8 +52,7 @@ public class ChooseSourceAi extends SpellAbilityAi { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); if (sa.canTarget(opp)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java b/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java index c24df2a5c39..5d8aed259bb 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CopySpellAbilityAi.java @@ -58,8 +58,7 @@ public class CopySpellAbilityAi extends SpellAbilityAi { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { // Filter AI-specific targets if provided if ("OnlyOwned".equals(sa.getParam("AITgts"))) { if (!top.getActivatingPlayer().equals(aiPlayer)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java index b93c01d40a3..f90e93d43ac 100644 --- a/forge-ai/src/main/java/forge/ai/ability/CounterAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/CounterAi.java @@ -63,8 +63,7 @@ public class CounterAi extends SpellAbilityAi { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { final SpellAbility topSA = ComputerUtilAbility.getTopSpellAbilityOnStack(game, sa); if (!CardFactoryUtil.isCounterableBy(topSA.getHostCard(), sa) || topSA.getActivatingPlayer() == ai || ai.getAllies().contains(topSA.getActivatingPlayer())) { @@ -246,10 +245,9 @@ public class CounterAi extends SpellAbilityAi { @Override protected boolean doTriggerAINoCost(Player ai, SpellAbility sa, boolean mandatory) { - final TargetRestrictions tgt = sa.getTargetRestrictions(); final Game game = ai.getGame(); - if (tgt != null) { + if (sa.usesTargeting()) { if (game.getStack().isEmpty()) { return false; } diff --git a/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java b/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java index e240f51cd27..3321511c07a 100644 --- a/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/PumpAllAi.java @@ -57,19 +57,20 @@ public class PumpAllAi extends PumpAiBase { } } - final TargetRestrictions tgt = sa.getTargetRestrictions(); final Player opp = ai.getStrongestOpponent(); - if (tgt != null && sa.canTarget(opp) && sa.isCurse()) { - sa.resetTargets(); - sa.getTargets().add(opp); - return true; - } - - if (tgt != null && sa.canTarget(ai) && !sa.isCurse()) { - sa.resetTargets(); - sa.getTargets().add(ai); - return true; + if (sa.usesTargeting()) { + if (sa.canTarget(opp) && sa.isCurse()) { + sa.resetTargets(); + sa.getTargets().add(opp); + return true; + } + + if (sa.canTarget(ai) && !sa.isCurse()) { + sa.resetTargets(); + sa.getTargets().add(ai); + return true; + } } final int power = AbilityUtils.calculateAmount(source, sa.getParam("NumAtt"), sa); diff --git a/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java b/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java index 9fafd25f28d..2f30d26968e 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TwoPilesAi.java @@ -28,8 +28,7 @@ public class TwoPilesAi extends SpellAbilityAi { final Player opp = AiAttackController.choosePreferredDefenderPlayer(ai); - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt != null) { + if (sa.usesTargeting()) { sa.resetTargets(); if (sa.canTarget(opp)) { sa.getTargets().add(opp); diff --git a/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java b/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java index 2bd45aa83ca..945300dc311 100644 --- a/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/UnattachAllAi.java @@ -48,7 +48,6 @@ public class UnattachAllAi extends SpellAbilityAi { return chance; } - /* (non-Javadoc) * @see forge.card.abilityfactory.SpellAiLogic#doTriggerAINoCost(forge.game.player.Player, java.util.Map, forge.card.spellability.SpellAbility, boolean) */ @@ -57,8 +56,7 @@ public class UnattachAllAi extends SpellAbilityAi { final Card card = sa.getHostCard(); // Check if there are any valid targets List targets = new ArrayList<>(); - final TargetRestrictions tgt = sa.getTargetRestrictions(); - if (tgt == null) { + if (!sa.usesTargeting()) { targets = AbilityUtils.getDefinedObjects(sa.getHostCard(), sa.getParam("Defined"), sa); } From 894350e8bba46cbd4c7905f9cee21192507ac7c6 Mon Sep 17 00:00:00 2001 From: TRT <> Date: Thu, 25 Nov 2021 12:09:20 +0100 Subject: [PATCH 3/5] Fix a TODO --- forge-ai/src/main/java/forge/ai/ability/DebuffAi.java | 3 +-- forge-ai/src/main/java/forge/ai/ability/TapAllAi.java | 2 +- forge-ai/src/main/java/forge/ai/ability/UntapAi.java | 8 ++++---- 3 files changed, 6 insertions(+), 7 deletions(-) diff --git a/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java b/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java index 6acb3b2cc2a..832c1313dce 100644 --- a/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/DebuffAi.java @@ -91,8 +91,7 @@ public class DebuffAi extends SpellAbilityAi { @Override public boolean chkAIDrawback(SpellAbility sa, Player ai) { if (!sa.usesTargeting()) { - // TODO - copied from AF_Pump.pumpDrawbackAI() - what should be - // here? + // TODO - copied from AF_Pump.pumpDrawbackAI() - what should be here? } else { return debuffTgtAI(ai, sa, sa.hasParam("Keywords") ? Arrays.asList(sa.getParam("Keywords").split(" & ")) : null, false); } diff --git a/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java b/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java index 831c5c702d1..bfa6105413f 100644 --- a/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/TapAllAi.java @@ -29,7 +29,7 @@ public class TapAllAi extends SpellAbilityAi { // or during upkeep/begin combat? final Card source = sa.getHostCard(); - final Player opp = ai.getWeakestOpponent(); + final Player opp = ai.getStrongestOpponent(); final Game game = ai.getGame(); if (game.getPhaseHandler().getPhase().isAfter(PhaseType.COMBAT_BEGIN)) { diff --git a/forge-ai/src/main/java/forge/ai/ability/UntapAi.java b/forge-ai/src/main/java/forge/ai/ability/UntapAi.java index cc038b3c7a4..0bdd0f39fe1 100644 --- a/forge-ai/src/main/java/forge/ai/ability/UntapAi.java +++ b/forge-ai/src/main/java/forge/ai/ability/UntapAi.java @@ -125,11 +125,11 @@ public class UntapAi extends SpellAbilityAi { private static boolean untapPrefTargeting(final Player ai, final SpellAbility sa, final boolean mandatory) { final Card source = sa.getHostCard(); - Player targetController = ai; - + final PlayerCollection targetController = new PlayerCollection(); if (sa.isCurse()) { - // TODO search through all opponents, may need to check if different controllers allowed - targetController = AiAttackController.choosePreferredDefenderPlayer(ai); + targetController.addAll(ai.getOpponents()); + } else { + targetController.add(ai); } CardCollection list = CardLists.getTargetableCards(targetController.getCardsIn(ZoneType.Battlefield), sa); From b4348754f0a883b6206a3b1af5c5be6c42bc3c99 Mon Sep 17 00:00:00 2001 From: TRT <> Date: Thu, 25 Nov 2021 12:44:49 +0100 Subject: [PATCH 4/5] Refactor Number$ChosenNumber --- forge-game/src/main/java/forge/game/ability/AbilityUtils.java | 4 ---- forge-gui/res/cardsfolder/m/mindblaze.txt | 2 +- forge-gui/res/cardsfolder/s/sanctum_prelate.txt | 2 +- forge-gui/res/cardsfolder/s/squees_revenge.txt | 2 +- forge-gui/res/cardsfolder/v/void.txt | 2 +- forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt | 2 +- 6 files changed, 5 insertions(+), 9 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java index 603c4cc99a0..7fa9903317a 100644 --- a/forge-game/src/main/java/forge/game/ability/AbilityUtils.java +++ b/forge-game/src/main/java/forge/game/ability/AbilityUtils.java @@ -1689,10 +1689,6 @@ public class AbilityUtils { // accept straight numbers if (l[0].startsWith("Number$")) { final String number = l[0].substring(7); - if (number.equals("ChosenNumber")) { // TODO remove in favor of Count ChosenNumber - int x = c.getChosenNumber() == null ? 0 : c.getChosenNumber(); - return doXMath(x, expr, c, ctb); - } return doXMath(Integer.parseInt(number), expr, c, ctb); } diff --git a/forge-gui/res/cardsfolder/m/mindblaze.txt b/forge-gui/res/cardsfolder/m/mindblaze.txt index ec564b4f87e..fe089006aa1 100644 --- a/forge-gui/res/cardsfolder/m/mindblaze.txt +++ b/forge-gui/res/cardsfolder/m/mindblaze.txt @@ -9,7 +9,7 @@ SVar:DBShuffle:DB$ Shuffle | Defined$ ParentTarget | SubAbility$ DBCleanup SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True SVar:X:TargetedPlayer$CardsInLibrary SVar:Y:Remembered$Valid Card.NamedCard -SVar:Z:Number$ChosenNumber +SVar:Z:Count$ChosenNumber AI:RemoveDeck:All AI:RemoveDeck:Random SVar:Picture:http://www.wizards.com/global/images/magic/general/mindblaze.jpg diff --git a/forge-gui/res/cardsfolder/s/sanctum_prelate.txt b/forge-gui/res/cardsfolder/s/sanctum_prelate.txt index 42b01216808..f6790b0a40d 100644 --- a/forge-gui/res/cardsfolder/s/sanctum_prelate.txt +++ b/forge-gui/res/cardsfolder/s/sanctum_prelate.txt @@ -5,7 +5,7 @@ PT:2/2 K:ETBReplacement:Other:ChooseNumber SVar:ChooseNumber:DB$ ChooseNumber | Defined$ You | SpellDescription$ As CARDNAME enters the battlefield, choose a number. S:Mode$ CantBeCast | ValidCard$ Card.nonCreature+cmcEQX | Description$ Noncreature spells with mana value equal to the chosen number can't be cast. -SVar:X:Number$ChosenNumber +SVar:X:Count$ChosenNumber AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/sanctum_prelate.jpg Oracle:As Sanctum Prelate enters the battlefield, choose a number.\nNoncreature spells with mana value equal to the chosen number can't be cast. diff --git a/forge-gui/res/cardsfolder/s/squees_revenge.txt b/forge-gui/res/cardsfolder/s/squees_revenge.txt index b0a6633ee24..93a082646a4 100644 --- a/forge-gui/res/cardsfolder/s/squees_revenge.txt +++ b/forge-gui/res/cardsfolder/s/squees_revenge.txt @@ -10,7 +10,7 @@ SVar:IncrementLoss:DB$ StoreSVar | SVar$ Loss | Type$ CountSVar | Expression$ Lo SVar:SetFilpsDone:DB$ StoreSVar | SVar$ FlipsDone | Type$ CountSVar | Expression$ TimesToFlip # Draw Cards SVar:DrawIfWin:DB$ Draw | Defined$ You | NumCards$ CardsToDraw | ConditionCheckSVar$ Loss | ConditionSVarCompare$ EQ0 -SVar:TimesToFlip:Number$ChosenNumber +SVar:TimesToFlip:Count$ChosenNumber SVar:FlipsDone:Number$0 SVar:Loss:Number$0 SVar:CardsToDraw:Count$ChosenNumber/Times.2 diff --git a/forge-gui/res/cardsfolder/v/void.txt b/forge-gui/res/cardsfolder/v/void.txt index 620eb8340ad..3c647a1ea7e 100644 --- a/forge-gui/res/cardsfolder/v/void.txt +++ b/forge-gui/res/cardsfolder/v/void.txt @@ -4,7 +4,7 @@ Types:Sorcery A:SP$ ChooseNumber | Cost$ 3 B R | SubAbility$ DBVoidDestroyAll | SpellDescription$ Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number. SVar:DBVoidDestroyAll:DB$ DestroyAll | ValidCards$ Artifact.cmcEQX,Creature.cmcEQX | SubAbility$ DBVoidRevealDiscard SVar:DBVoidRevealDiscard:DB$ Discard | ValidTgts$ Player | TgtPrompt$ Select target player | Mode$ RevealDiscardAll | DiscardValid$ Card.nonLand+cmcEQX -SVar:X:Number$ChosenNumber +SVar:X:Count$ChosenNumber AI:RemoveDeck:All SVar:Picture:http://www.wizards.com/global/images/magic/general/void.jpg Oracle:Choose a number. Destroy all artifacts and creatures with mana value equal to that number. Then target player reveals their hand and discards all nonland cards with mana value equal to the number. diff --git a/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt b/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt index 14d7bc542a7..65f887fd54c 100644 --- a/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt +++ b/forge-gui/res/cardsfolder/y/yusri_fortunes_flame.txt @@ -11,7 +11,7 @@ SVar:DBDamage:DB$ DealDamage | NumDmg$ Damage | Defined$ You SVar:DBEffect:DB$ Effect | StaticAbilities$ MayPlay | Stackable$ False | ConditionCheckSVar$ Y | ConditionSVarCompare$ EQ5 | SubAbility$ DBCleanup SVar:MayPlay:Mode$ Continuous | EffectZone$ Command | Affected$ Card.nonLand+YouOwn | MayPlay$ True | MayPlayWithoutManaCost$ True | AffectedZone$ Hand | Description$ You may cast spells from your hand this turn without paying their mana costs. SVar:DBCleanup:DB$ Cleanup | ClearRemembered$ True -SVar:X:Number$ChosenNumber +SVar:X:Count$ChosenNumber SVar:Y:Count$RememberedNumber SVar:Damage:SVar$Losses/Times.2 Oracle:Flying\nWhenever Yusri, Fortune's Flame attacks, choose a number between 1 and 5. Flip that many coins. For each flip you win, draw a card. For each flip you lose, Yusri deals 2 damage to you. If you won five flips this way, you may cast spells from your hand this turn without paying their mana costs. From 4411d0775d01f0ce42c922d022a4a807a251f0cb Mon Sep 17 00:00:00 2001 From: TRT <> Date: Thu, 25 Nov 2021 12:49:15 +0100 Subject: [PATCH 5/5] Clean up --- .../java/forge/game/ability/effects/ChangeZoneEffect.java | 6 ++---- 1 file changed, 2 insertions(+), 4 deletions(-) diff --git a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java index b196ba0fd08..31fd27cb327 100644 --- a/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java +++ b/forge-game/src/main/java/forge/game/ability/effects/ChangeZoneEffect.java @@ -272,8 +272,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { sb.append("."); } else if (origin.equals("Battlefield")) { // TODO Expand on this Description as more cards use it - // for the non-targeted SAs when you choose what is returned on - // resolution + // for the non-targeted SAs when you choose what is returned on resolution sb.append("Return ").append(num).append(" ").append(type).append(" card(s) "); sb.append(" to your ").append(destination); } @@ -361,8 +360,7 @@ public class ChangeZoneEffect extends SpellAbilityEffect { sb.append(fromGraveyard); } - // this needs to be zero indexed. Top = 0, Third = 2, -1 = - // Bottom + // this needs to be zero indexed. Top = 0, Third = 2, -1 = Bottom final int libraryPosition = sa.hasParam("LibraryPosition") ? AbilityUtils.calculateAmount(host, sa.getParam("LibraryPosition"), sa) : 0; if (libraryPosition == -1) {