@@ -60,7 +60,7 @@ protected AiAbilityDecision checkApiLogic(Player ai, SpellAbility sa) {
6060 * bonus choice(s) for the AI otherwise it might be too hard to ever fulfil
6161 * minimum choice requirements with canPlayAi() alone.
6262 */
63- chosenList = min > 1 ? chooseMultipleOptionsAi (choices , ai , min )
63+ chosenList = min > 1 ? chooseMultipleOptionsAi (sa , choices , ai , min )
6464 : chooseOptionsAi (sa , choices , ai , timingRight , num , min );
6565 }
6666
@@ -92,12 +92,11 @@ protected AiAbilityDecision checkApiLogic(Player ai, SpellAbility sa) {
9292 }
9393
9494 private List <AbilitySub > chooseOptionsAi (SpellAbility sa , List <AbilitySub > choices , final Player ai , boolean isTrigger , int num , int min ) {
95- List <AbilitySub > chosenList = Lists .newArrayList ();
95+ List <AbilitySub > chosen = Lists .newArrayList ();
9696 AiController aic = ((PlayerControllerAi ) ai .getController ()).getAi ();
9797 // TODO unused for now, the AI doesn't know how to effectively handle repeated choices
9898 boolean allowRepeat = sa .hasParam ("CanRepeatModes" );
9999
100- // Pawprint
101100 final int pawprintLimit = sa .hasParam ("Pawprint" ) ? AbilityUtils .calculateAmount (sa .getHostCard (), sa .getParam ("Pawprint" ), sa ) : 0 ;
102101 if (pawprintLimit > 0 ) {
103102 // try to pay for the more expensive subs first
@@ -107,6 +106,7 @@ private List<AbilitySub> chooseOptionsAi(SpellAbility sa, List<AbilitySub> choic
107106
108107 // First pass using standard canPlayAi() for good choices
109108 for (AbilitySub sub : choices ) {
109+ handleDependentModes (sa , chosen , sub );
110110 sub .setActivatingPlayer (ai );
111111 // TODO refactor to obtain the AiAbilityDecision instead, then we can check all to sort by value
112112 if (AiPlayDecision .WillPlay == aic .canPlaySa (sub )) {
@@ -117,42 +117,45 @@ private List<AbilitySub> chooseOptionsAi(SpellAbility sa, List<AbilitySub> choic
117117 }
118118 pawprintAmount += curPawprintAmount ;
119119 }
120- chosenList .add (sub );
121- if (chosenList .size () == num ) {
120+ chosen .add (sub );
121+ if (chosen .size () == num ) {
122122 // maximum choices reached
123- return chosenList ;
123+ break ;
124124 }
125125 }
126126 }
127- if (isTrigger && chosenList .size () < min ) {
127+ if (isTrigger && chosen .size () < min ) {
128128 // Second pass using doTrigger(false) to fulfill minimum choice
129- choices .removeAll (chosenList );
129+ choices .removeAll (chosen );
130130 for (AbilitySub sub : choices ) {
131+ handleDependentModes (sa , chosen , sub );
131132 if (aic .doTrigger (sub , false )) {
132- chosenList .add (sub );
133- if (chosenList .size () == min ) {
134- return chosenList ;
133+ chosen .add (sub );
134+ if (chosen .size () == min ) {
135+ break ;
135136 }
136137 }
137138 }
138139 // Third pass using doTrigger(true) to force fill minimum choices
139- if (chosenList .size () < min ) {
140- choices .removeAll (chosenList );
140+ if (chosen .size () < min ) {
141+ choices .removeAll (chosen );
141142 for (AbilitySub sub : choices ) {
143+ handleDependentModes (sa , chosen , sub );
142144 if (aic .doTrigger (sub , true )) {
143- chosenList .add (sub );
144- if (chosenList .size () == min ) {
145+ chosen .add (sub );
146+ if (chosen .size () == min ) {
145147 break ;
146148 }
147149 }
148150 }
149151 }
150152 }
151- if (chosenList .size () < min ) {
153+ if (chosen .size () < min ) {
152154 // not enough choices
153- chosenList .clear ();
155+ chosen .clear ();
154156 }
155- return chosenList ;
157+ sa .setSubAbility (null );
158+ return chosen ;
156159 }
157160
158161 private List <AbilitySub > chooseTriskaidekaphobia (List <AbilitySub > choices , final Player ai ) {
@@ -242,32 +245,43 @@ else if (aiLife < 13 || ((aiLife - 13) % 2) == 1) {
242245 return chosenList ;
243246 }
244247
245- // Choice selection for charms that require multiple choices (eg. Cryptic Command, DTK commands )
246- private List <AbilitySub > chooseMultipleOptionsAi (List <AbilitySub > choices , final Player ai , int min ) {
248+ // Choice selection for charms that require multiple choices (e.g. Cryptic Command)
249+ private List <AbilitySub > chooseMultipleOptionsAi (SpellAbility sa , List <AbilitySub > choices , final Player ai , int min ) {
247250 AbilitySub goodChoice = null ;
248- List <AbilitySub > chosenList = Lists .newArrayList ();
251+ List <AbilitySub > chosen = Lists .newArrayList ();
249252 AiController aic = ((PlayerControllerAi ) ai .getController ()).getAi ();
250253 for (AbilitySub sub : choices ) {
254+ handleDependentModes (sa , chosen , sub );
251255 sub .setActivatingPlayer (ai );
252256 // Assign generic good choice to fill up choices if necessary
253257 if ("Good" .equals (sub .getParam ("AILogic" )) && aic .doTrigger (sub , false )) {
254258 goodChoice = sub ;
255259 } else if (AiPlayDecision .WillPlay == aic .canPlaySa (sub )) {
256- chosenList .add (sub );
257- if (chosenList .size () == min ) {
260+ chosen .add (sub );
261+ if (chosen .size () == min ) {
258262 break ; // enough choices
259263 }
260264 }
261265 }
262266 // Add generic good choice if one more choice is needed
263- if (chosenList .size () == min - 1 && goodChoice != null ) {
264- chosenList .add (0 , goodChoice ); // hack to make Dromoka's Command fight targets work
267+ if (chosen .size () == min - 1 && goodChoice != null ) {
268+ chosen .add (0 , goodChoice ); // hack to make Dromoka's Command fight targets work
265269 }
266- if (chosenList .size () != min ) {
267- chosenList .clear ();
270+ if (chosen .size () != min ) {
271+ chosen .clear ();
268272 }
269- return chosenList ;
270- }
273+ sa .setSubAbility (null );
274+ return chosen ;
275+ }
276+
277+ private void handleDependentModes (SpellAbility sa , List <AbilitySub > chosen , AbilitySub sub ) {
278+ if (sub .hasParam ("TargetUnique" ) && !chosen .isEmpty ()) {
279+ // support "Each mode must target a different..."
280+ sa .setSubAbility (null );
281+ CharmEffect .chainAbilities (sa , chosen );
282+ sa .appendSubAbility (sub );
283+ }
284+ }
271285
272286 @ Override
273287 public Player chooseSinglePlayer (Player ai , SpellAbility sa , Iterable <Player > opponents , Map <String , Object > params ) {
0 commit comments