-
Notifications
You must be signed in to change notification settings - Fork 73
/
FightRequest.java
10249 lines (8759 loc) · 380 KB
/
FightRequest.java
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
698
699
700
701
702
703
704
705
706
707
708
709
710
711
712
713
714
715
716
717
718
719
720
721
722
723
724
725
726
727
728
729
730
731
732
733
734
735
736
737
738
739
740
741
742
743
744
745
746
747
748
749
750
751
752
753
754
755
756
757
758
759
760
761
762
763
764
765
766
767
768
769
770
771
772
773
774
775
776
777
778
779
780
781
782
783
784
785
786
787
788
789
790
791
792
793
794
795
796
797
798
799
800
801
802
803
804
805
806
807
808
809
810
811
812
813
814
815
816
817
818
819
820
821
822
823
824
825
826
827
828
829
830
831
832
833
834
835
836
837
838
839
840
841
842
843
844
845
846
847
848
849
850
851
852
853
854
855
856
857
858
859
860
861
862
863
864
865
866
867
868
869
870
871
872
873
874
875
876
877
878
879
880
881
882
883
884
885
886
887
888
889
890
891
892
893
894
895
896
897
898
899
900
901
902
903
904
905
906
907
908
909
910
911
912
913
914
915
916
917
918
919
920
921
922
923
924
925
926
927
928
929
930
931
932
933
934
935
936
937
938
939
940
941
942
943
944
945
946
947
948
949
950
951
952
953
954
955
956
957
958
959
960
961
962
963
964
965
966
967
968
969
970
971
972
973
974
975
976
977
978
979
980
981
982
983
984
985
986
987
988
989
990
991
992
993
994
995
996
997
998
999
1000
package net.sourceforge.kolmafia.request;
import java.io.File;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.Date;
import java.util.HashMap;
import java.util.Iterator;
import java.util.List;
import java.util.Map;
import java.util.Set;
import java.util.TimeZone;
import java.util.function.Function;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.kolmafia.AdventureResult;
import net.sourceforge.kolmafia.AdventureResult.AdventureLongCountResult;
import net.sourceforge.kolmafia.AreaCombatData;
import net.sourceforge.kolmafia.AscensionClass;
import net.sourceforge.kolmafia.EdServantData;
import net.sourceforge.kolmafia.FamiliarData;
import net.sourceforge.kolmafia.KoLAdventure;
import net.sourceforge.kolmafia.KoLCharacter;
import net.sourceforge.kolmafia.KoLConstants;
import net.sourceforge.kolmafia.KoLConstants.MafiaState;
import net.sourceforge.kolmafia.KoLConstants.Stat;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.KoLmafiaASH;
import net.sourceforge.kolmafia.KoLmafiaCLI;
import net.sourceforge.kolmafia.Modifiers;
import net.sourceforge.kolmafia.MonsterData;
import net.sourceforge.kolmafia.RequestEditorKit;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.RequestThread;
import net.sourceforge.kolmafia.combat.CombatActionManager;
import net.sourceforge.kolmafia.combat.Macrofier;
import net.sourceforge.kolmafia.combat.MonsterStatusTracker;
import net.sourceforge.kolmafia.moods.MPRestoreItemList;
import net.sourceforge.kolmafia.moods.RecoveryManager;
import net.sourceforge.kolmafia.objectpool.AdventurePool;
import net.sourceforge.kolmafia.objectpool.EffectPool;
import net.sourceforge.kolmafia.objectpool.FamiliarPool;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.objectpool.SkillPool;
import net.sourceforge.kolmafia.persistence.AdventureDatabase;
import net.sourceforge.kolmafia.persistence.AdventureSpentDatabase;
import net.sourceforge.kolmafia.persistence.BountyDatabase;
import net.sourceforge.kolmafia.persistence.ConsumablesDatabase;
import net.sourceforge.kolmafia.persistence.EffectDatabase;
import net.sourceforge.kolmafia.persistence.EquipmentDatabase;
import net.sourceforge.kolmafia.persistence.FamiliarDatabase;
import net.sourceforge.kolmafia.persistence.ItemDatabase;
import net.sourceforge.kolmafia.persistence.ItemFinder;
import net.sourceforge.kolmafia.persistence.MonsterDatabase;
import net.sourceforge.kolmafia.persistence.MonsterDatabase.Phylum;
import net.sourceforge.kolmafia.persistence.QuestDatabase;
import net.sourceforge.kolmafia.persistence.QuestDatabase.Quest;
import net.sourceforge.kolmafia.persistence.SkillDatabase;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.request.FamTeamRequest.PokeBoost;
import net.sourceforge.kolmafia.session.BanishManager;
import net.sourceforge.kolmafia.session.BatManager;
import net.sourceforge.kolmafia.session.BugbearManager;
import net.sourceforge.kolmafia.session.ClanManager;
import net.sourceforge.kolmafia.session.CrystalBallManager;
import net.sourceforge.kolmafia.session.DadManager;
import net.sourceforge.kolmafia.session.DreadScrollManager;
import net.sourceforge.kolmafia.session.EncounterManager;
import net.sourceforge.kolmafia.session.EquipmentManager;
import net.sourceforge.kolmafia.session.GoalManager;
import net.sourceforge.kolmafia.session.InventoryManager;
import net.sourceforge.kolmafia.session.IslandManager;
import net.sourceforge.kolmafia.session.Limitmode;
import net.sourceforge.kolmafia.session.LoginManager;
import net.sourceforge.kolmafia.session.MonsterManuelManager;
import net.sourceforge.kolmafia.session.QuestManager;
import net.sourceforge.kolmafia.session.ResponseTextParser;
import net.sourceforge.kolmafia.session.ResultProcessor;
import net.sourceforge.kolmafia.session.SpadingManager;
import net.sourceforge.kolmafia.session.TurnCounter;
import net.sourceforge.kolmafia.session.UnusualConstructManager;
import net.sourceforge.kolmafia.session.WumpusManager;
import net.sourceforge.kolmafia.textui.ScriptRuntime;
import net.sourceforge.kolmafia.utilities.HTMLParserUtils;
import net.sourceforge.kolmafia.utilities.PauseObject;
import net.sourceforge.kolmafia.utilities.StringUtilities;
import net.sourceforge.kolmafia.webui.DiscoCombatHelper;
import net.sourceforge.kolmafia.webui.HobopolisDecorator;
import net.sourceforge.kolmafia.webui.NemesisDecorator;
import net.sourceforge.kolmafia.webui.VillainLairDecorator;
import org.htmlcleaner.BaseToken;
import org.htmlcleaner.CleanerProperties;
import org.htmlcleaner.CommentNode;
import org.htmlcleaner.ContentNode;
import org.htmlcleaner.HtmlCleaner;
import org.htmlcleaner.TagNode;
public class FightRequest extends GenericRequest {
// Character-class permissions
private static final PauseObject PAUSER = new PauseObject();
public static final FightRequest INSTANCE = new FightRequest();
private static final AdventureResult AMNESIA = EffectPool.get(EffectPool.AMNESIA);
private static final AdventureResult CUNCTATITIS = EffectPool.get(EffectPool.CUNCTATITIS);
public static final AdventureResult ONTHETRAIL = EffectPool.get(EffectPool.ON_THE_TRAIL);
public static final AdventureResult BIRDFORM = EffectPool.get(EffectPool.FORM_OF_BIRD);
public static final AdventureResult MOLEFORM = EffectPool.get(EffectPool.SHAPE_OF_MOLE);
public static final AdventureResult INFERNO = EffectPool.get(EffectPool.TASTE_THE_INFERNO);
public static final AdventureResult COWRRUPTION = EffectPool.get(EffectPool.COWRRUPTION, 0);
public static final AdventureResult DICTIONARY1 = ItemPool.get(ItemPool.DICTIONARY, 1);
public static final AdventureResult DICTIONARY2 = ItemPool.get(ItemPool.FACSIMILE_DICTIONARY, 1);
private static final AdventureResult TEQUILA = ItemPool.get(ItemPool.TEQUILA, -1);
public static AdventureResult haikuEffect = EffectPool.get(EffectPool.HAIKU_STATE_OF_MIND);
public static AdventureResult anapestEffect = EffectPool.get(EffectPool.JUST_THE_BEST_ANAPESTS);
private static final int HEALTH = 0;
private static final int ATTACK = 1;
private static final int DEFENSE = 2;
private static int lastUserId = 0;
private static String lostInitiativeMessage = "";
private static String wonInitiativeMessage = "";
public static String lastMacroUsed = "";
private static final String lostBatfellowInitiativeMessage =
"Round 0: Batfellow loses initiative!";
private static final String wonBatfellowInitiativeMessage = "Round 0: Batfellow wins initiative!";
// Extra rounds used by KoLmafia doing special actions
private static int preparatoryRounds = 0;
// Index into current CCS section since last macro generated
private static int macroPrefixLength = 0;
private static String consultScriptThatDidNothing = null;
public static String combatFilterThatDidNothing = null;
public static boolean waitingForSpecial;
public static String lastResponseText = "";
public static String lastDecoratedResponseText = "";
public static String currentEncounter = "";
private static boolean transformed = false;
private static boolean haveFought = false;
private static boolean shouldRefresh = false;
private static boolean initializeAfterFight = false;
private static boolean isAutomatingFight = false;
private static boolean isUsingConsultScript = false;
private static int dreadWoodsKisses = 0;
private static int dreadVillageKisses = 0;
private static int dreadCastleKisses = 0;
private static int startingAttack = 0;
private static final Pattern COMBATITEM_PATTERN =
Pattern.compile("<option[^>]*?value=(\\d+)[^>]*?>[^>]*?\\((\\d+)\\)</option>");
private static final Pattern AVAILABLE_COMBATSKILL_PATTERN =
Pattern.compile("<option[^>]*?value=\"(\\d+)[^>]*?>(.*?) \\((\\d+)[^<]*</option>");
// fambattle.php?pwd&famaction[backstab-209]=Backstab
private static final Pattern FAMBATTLE_PATTERN = Pattern.compile("famaction.*?-(\\d+).*?=(.*)");
public static final Pattern SKILL_PATTERN = Pattern.compile("whichskill=(\\d+)");
private static final Pattern ITEM1_PATTERN = Pattern.compile("whichitem=(\\d+)");
private static final Pattern ITEM2_PATTERN = Pattern.compile("whichitem2=(\\d+)");
// <script>newpic("https://s3.amazonaws.com/images.kingdomofloathing.com/adventureimages/newt.gif", "a newt",100,100);</script>
private static final Pattern CLEESH_PATTERN =
Pattern.compile("newpic\\(\"(.*?)\", \"(.*?)\".*?\\);");
private static final Pattern WORN_STICKER_PATTERN =
Pattern.compile("A sticker falls off your weapon, faded and torn");
private static final Pattern BEEP_PATTERN = Pattern.compile("Your Evilometer beeps (\\d+) times");
private static final Pattern BALLROOM_SONG_PATTERN =
Pattern.compile("You hear strains of (?:(lively)|(mellow)|(lovely)) music in the distance");
private static final Pattern WHICHMACRO_PATTERN = Pattern.compile("whichmacro=(\\d+)");
private static final Pattern MACRO_PATTERN =
Pattern.compile(
"\\G.*?<!-- macroaction: *(\\w+) ++(\\d+)?,? *(\\d+)?.*?(?=$|<!-- macroaction)",
Pattern.DOTALL);
private static final Pattern FULLPAGE_PATTERN = Pattern.compile("^.*$", Pattern.DOTALL);
private static final Pattern MACRO_COMPACT_PATTERN =
Pattern.compile("(?:#.*?)?([;\\n])[\\s;\\n]*");
private static final Pattern INTERGNAT1_PATTERN =
Pattern.compile("used to be a ([A-Za-z0-9 '_]*?) but then I took");
private static final Pattern INTERGNAT2_PATTERN =
Pattern.compile("All your ([A-Za-z0-9 '_]*?) are belong to us");
private static final Pattern INTERGNAT3_PATTERN =
Pattern.compile("I'm a' chargin' mah ([A-Za-z0-9 '_]*?)!\" it shouts.");
private static final Pattern INTERGNAT4_PATTERN =
Pattern.compile("I made you a ([A-Za-z0-9 '_]*?) but I eated it!");
private static final Pattern NS_ML_PATTERN =
Pattern.compile(
"The Sorceress pauses for a moment\\, mutters some words under her breath\\, and straightens out her dress\\. Her skin seems to shimmer for a moment\\.");
private static final Pattern DETECTIVE_PATTERN =
Pattern.compile("I deduce that this monster has approximately (\\d+) hit points");
private static final Pattern YELLOW_WORD_PATTERN =
Pattern.compile("She said... <font color=yellow>(.*?)</font>...");
private static final Pattern BLUE_WORD_PATTERN =
Pattern.compile("drinks that don't exist, like <font color=blue>(.*?)</font>");
private static final Pattern SPACE_HELMET_PATTERN = Pattern.compile("Opponent HP: (\\d+)");
private static final Pattern SLIMED_PATTERN =
Pattern.compile(
"it blasts you with a massive loogie that sticks to your (.*?), pulls it off of you");
private static final Pattern MULTIFIGHT_PATTERN = Pattern.compile("href=\"?/?fight.php");
private static final Pattern FIGHTCHOICE_PATTERN = Pattern.compile("href=\"?choice.php");
private static final Pattern KEYOTRON_PATTERN = Pattern.compile("key-o-tron emits (\\d) short");
private static final Pattern DISCO_MOMENTUM_PATTERN = Pattern.compile("discomo(\\d).gif");
private static final Pattern SOULSAUCE_PATTERN = Pattern.compile("You absorb (\\d+) Soulsauce");
private static final Pattern THUNDER_PATTERN = Pattern.compile("swallow <b>(\\d+)</b> dB of it");
private static final Pattern RAIN_PATTERN = Pattern.compile("recovering <b>(\\d+)</b> drops");
private static final Pattern LIGHTNING_PATTERN =
Pattern.compile("recovering <b>(\\d+)</b> bolts");
private static final Pattern SEAHORSE_PATTERN =
Pattern.compile("I shall name you "(.*?)," you say.");
private static final Pattern TIMEPRANK_PATTERN =
Pattern.compile("A figure steps out from behind this morning and says, "(.*?)"");
private static final Pattern NANORHINO_CHARGE1_PATTERN = Pattern.compile("(\\d+)% charge");
private static final Pattern NANORHINO_CHARGE2_PATTERN = Pattern.compile("charge to (\\d+)%");
private static final Pattern NANORHINO_BUFF_PATTERN =
Pattern.compile("title=\\\"Nano(?:brawny|brainy|ballsy)\\\"");
private static final Pattern SHORT_ORDER_EXP_PATTERN =
Pattern.compile("and tosses a plate of food to (.*?), who gains ([0-9,]+) exp!");
private static final Pattern RED_BUTTON_PATTERN =
Pattern.compile("manage to find and recover all but (\\d+) of the buttons");
private static final Pattern PROSELYTIZATION_PATTERN =
Pattern.compile("^\\+1 ([^<]+) Proselytization$");
private static final Pattern CLOG_PATTERN =
Pattern.compile("Your oil extractor is (\\d+)% clogged up");
private static final Pattern SOURCE_INTERVAL_PATTERN =
Pattern.compile("var matrix_speed = (\\d+);");
private static final Pattern DECEASED_TREE_PATTERN =
Pattern.compile("Your crimbo tree has (\\d+) needle");
private static final Pattern BROKEN_CHAMPAGNE_PATTERN =
Pattern.compile("going wild with the (\\d+)");
private static final Pattern GARBAGE_SHIRT_PATTERN = Pattern.compile(" (\\d+) more useful scrap");
private static final Pattern SHARPEN_SAW_PATTERN =
Pattern.compile(
"You're really sharpening the old saw. Looks like you've done (\\d+) out of (\\d+)!");
private static final Pattern MASK_SWAP_PATTERN =
Pattern.compile("swap your mask for the monster's (.*?)<script>");
private static final Pattern BONERDAGON_BLOCK_PATTERN =
Pattern.compile("pulling the (.*?) out of your pocket");
private static final Pattern NS1_BLOCK1_PATTERN =
Pattern.compile("you pull the (.*?) out of your pocket");
private static final Pattern NS1_BLOCK2_PATTERN =
Pattern.compile("start to use the (.*?), but the Sorceress");
private static final Pattern NS1_BLOCK3_PATTERN =
Pattern.compile("grabs the (.*?) out of your hands");
private static final Pattern NS2_BLOCK1_PATTERN =
Pattern.compile("tears the (.*?) out of your hands");
private static final Pattern NS2_BLOCK2_PATTERN = Pattern.compile("the (.*?) is shattered");
private static final Pattern NS2_BLOCK3_PATTERN =
Pattern.compile("use the (.*?), a nasty-looking pseudopod");
private static final AdventureResult TOOTH = ItemPool.get(ItemPool.SEAL_TOOTH, 1);
private static final AdventureResult SPICES = ItemPool.get(ItemPool.SPICES, 1);
private static final AdventureResult MERCENARY = ItemPool.get(ItemPool.TOY_MERCENARY, 1);
private static final AdventureResult STOMPER = ItemPool.get(ItemPool.MINIBORG_STOMPER, 1);
private static final AdventureResult LASER = ItemPool.get(ItemPool.MINIBORG_LASER, 1);
private static final AdventureResult DESTROYER = ItemPool.get(ItemPool.MINIBORG_DESTROYOBOT, 1);
public static final AdventureResult ANTIDOTE = ItemPool.get(ItemPool.ANTIDOTE, 1);
private static final AdventureResult EXTRACTOR = ItemPool.get(ItemPool.ODOR_EXTRACTOR, 1);
private static final AdventureResult PUTTY_SHEET = ItemPool.get(ItemPool.SPOOKY_PUTTY_SHEET, 1);
private static final AdventureResult RAINDOH_BOX = ItemPool.get(ItemPool.RAIN_DOH_BOX, 1);
private static final AdventureResult CAMERA = ItemPool.get(ItemPool.CAMERA, 1);
private static final AdventureResult CRAPPY_CAMERA = ItemPool.get(ItemPool.CRAPPY_CAMERA, 1);
private static final AdventureResult SHAKING_CAMERA = ItemPool.get(ItemPool.SHAKING_CAMERA, 1);
private static final AdventureResult SHAKING_CRAPPY_CAMERA =
ItemPool.get(ItemPool.SHAKING_CAMERA, 1);
private static final AdventureResult PHOTOCOPIER = ItemPool.get(ItemPool.PHOTOCOPIER, 1);
private static final AdventureResult PHOTOCOPIED_MONSTER =
ItemPool.get(ItemPool.PHOTOCOPIED_MONSTER, 1);
private static final String TOOTH_ACTION = "item" + ItemPool.SEAL_TOOTH;
private static final String SPICES_ACTION = "item" + ItemPool.SPICES;
private static final String MERCENARY_ACTION = "item" + ItemPool.TOY_MERCENARY;
private static final String STOMPER_ACTION = "item" + ItemPool.MINIBORG_STOMPER;
private static final String LASER_ACTION = "item" + ItemPool.MINIBORG_LASER;
private static final String DESTROYER_ACTION = "item" + ItemPool.MINIBORG_DESTROYOBOT;
private static final String OLFACTION_ACTION = "skill" + SkillPool.OLFACTION;
private static boolean castNoodles = false;
private static boolean castClubFoot = false;
private static boolean castShellUp = false;
private static boolean castAccordionBash = false;
private static boolean castCleesh = false;
private static boolean castParaffinPrism = false;
private static boolean castTerracottaArmy = false;
private static boolean insultedPirate = false;
private static boolean usedFlyer = false;
private static boolean usedBasePair = false;
private static boolean jiggledChefstaff = false;
private static boolean handledCan = false;
private static boolean shotSixgun = false;
private static boolean squeezedStressBall = false;
private static boolean canOlfact = true;
private static boolean canStomp = false;
public static boolean haiku = false;
public static boolean anapest = false;
public static boolean machineElf = false;
public static boolean innerWolf = false;
public static boolean pokefam = false;
public static boolean papier = false;
public static int currentRound = 0;
public static boolean won = false;
public static boolean inMultiFight = false;
public static boolean choiceFollowsFight = false;
public static boolean fightFollowsChoice = false;
public static boolean fightingCopy = false;
private static String nextAction = null;
private static String macroErrorMessage = null;
private static AdventureResult desiredScroll = null;
private static final AdventureResult SCROLL_334 = ItemPool.get(ItemPool.SCROLL_334, 1);
private static final AdventureResult SCROLL_668 = ItemPool.get(ItemPool.SCROLL_668, 1);
private static final AdventureResult SCROLL_30669 = ItemPool.get(ItemPool.SCROLL_30669, 1);
private static final AdventureResult SCROLL_33398 = ItemPool.get(ItemPool.SCROLL_33398, 1);
private static final AdventureResult SCROLL_64067 = ItemPool.get(ItemPool.SCROLL_64067, 1);
private static final AdventureResult SCROLL_64735 = ItemPool.get(ItemPool.GATES_SCROLL, 1);
private static final AdventureResult SCROLL_31337 = ItemPool.get(ItemPool.ELITE_SCROLL, 1);
private static final Object[][] NEMESIS_WEAPONS = { // class, LEW, ULEW
{
AscensionClass.SEAL_CLUBBER,
ItemPool.get(ItemPool.HAMMER_OF_SMITING, 1),
ItemPool.get(ItemPool.SLEDGEHAMMER_OF_THE_VAELKYR, 1)
},
{
AscensionClass.TURTLE_TAMER,
ItemPool.get(ItemPool.CHELONIAN_MORNINGSTAR, 1),
ItemPool.get(ItemPool.FLAIL_OF_THE_SEVEN_ASPECTS, 1)
},
{
AscensionClass.PASTAMANCER,
ItemPool.get(ItemPool.GREEK_PASTA_OF_PERIL, 1),
ItemPool.get(ItemPool.WRATH_OF_THE_PASTALORDS, 1)
},
{
AscensionClass.SAUCEROR,
ItemPool.get(ItemPool.SEVENTEEN_ALARM_SAUCEPAN, 1),
ItemPool.get(ItemPool.WINDSOR_PAN_OF_THE_SOURCE, 1)
},
{
AscensionClass.DISCO_BANDIT,
ItemPool.get(ItemPool.SHAGADELIC_DISCO_BANJO, 1),
ItemPool.get(ItemPool.SEEGERS_BANJO, 1)
},
{
AscensionClass.ACCORDION_THIEF,
ItemPool.get(ItemPool.SQUEEZEBOX_OF_THE_AGES, 1),
ItemPool.get(ItemPool.TRICKSTER_TRIKITIXA, 1)
},
};
// Skills which require a shield
private static final Set<String> INVALID_WITHOUT_SHIELD = Set.of("2005", "skill shieldbutt");
private static final Set<String> INVALID_OUT_OF_WATER = Set.of("2024", "skill summon leviatuga");
private static final Set<String> GNOME_ADV_ACTIVATION =
Set.of(
"scrubs the mildew out of your grout",
"bundles your recycling for you",
"teaches you how to power-nap instead of sleeping all day",
"sharpens all your pencils and lines them up in a neat row",
"folds all your clean laundry",
"shows you how to shave a full minute off of your teeth brushing routine",
"organizes your sock drawer and alphabetizes your spice rack",
"hauls all of your scrap lumber to the dump",
"does all that tedious campsite cleaning you were going to do today");
private static final String[][] EVIL_ZONES = {
{
"The Defiled Alcove", "cyrptAlcoveEvilness",
},
{
"The Defiled Cranny", "cyrptCrannyEvilness",
},
{
"The Defiled Niche", "cyrptNicheEvilness",
},
{
"The Defiled Nook", "cyrptNookEvilness",
},
};
public enum SpecialMonster {
// Individual monsters
ANCIENT_PROTECTOR_SPIRIT("Ancient Protector Spirit"),
CONJOINED_ZMOMBIE("conjoined zmombie"),
CYRUS_THE_VIRUS("Cyrus the Virus"),
DAD_SEA_MONKEE("Dad Sea Monkee"),
DRIPPY_BAT("drippy bat"),
DRIPPY_REVELER("drippy reveler"),
FAMILY_OF_KOBOLDS("family of kobolds"),
GARGANTULIHC("gargantulihc"),
GIANT_OCTOPUS("giant octopus"),
GIANT_SKEELTON("giant skeelton"),
GLITCH_MONSTER("%monster%"),
HUGE_GHUOL("huge ghoul"),
PIRANHA_PLANT("piranha plant"),
PYGMY_JANITOR("pygmy janitor"),
PYGMY_WITCH_LAWYER("pygmy witch lawyer"),
SAUSAGE_GOBLIN("sausage goblin"),
TIME_SPINNER_PRANK("time-spinner prank"),
UNUSUAL_CONSTRUCT("unusual construct"),
// Categories of monsters
BEE("bee"),
DMT("Deep Machine Tunnels"),
EVENT("event monster"),
GINGERBREAD("Gingerbread City"),
HIPSTER("hipsters"),
HOLIDAY("holiday monster"),
NEMESIS("nemesis assassin"),
PORTSCAN("portscan.edu"),
RAIN("Heavy Rains"),
SEWER("Sewer Tunnel"),
TACO_ELF("taco elf"),
WAR_FRATBOY("War Fratboy"),
WAR_HIPPY("War Hippy"),
WITCHESS("witchess"),
WOL("West of Loathing");
private final String name;
SpecialMonster(String name) {
this.name = name;
}
@Override
public String toString() {
return this.name;
}
}
private static final Map<String, SpecialMonster> specialMonsters = new HashMap<>();
// When AdventureRequest initializes AreaCombatData, if calls methods in FightRequest
// When FightRequest initializes the above map, if calls methods in AdventureRequest
// Therefore, initialize this map only when it is actually accessed.
public static final SpecialMonster specialMonsterCategory(final MonsterData monster) {
FightRequest.initializeSpecialMonsters();
return FightRequest.specialMonsters.get(monster.getName());
}
public static final SpecialMonster specialMonsterCategory(final String name) {
FightRequest.initializeSpecialMonsters();
return FightRequest.specialMonsters.get(name);
}
private static void initializeSpecialMonsters() {
if (specialMonsters.size() > 0) {
return;
}
FightRequest.specialMonsters.put("%monster%", SpecialMonster.GLITCH_MONSTER);
FightRequest.specialMonsters.put(
"Ancient Protector Spirit", SpecialMonster.ANCIENT_PROTECTOR_SPIRIT);
FightRequest.specialMonsters.put("conjoined zmombie", SpecialMonster.CONJOINED_ZMOMBIE);
FightRequest.specialMonsters.put("Cyrus the Virus", SpecialMonster.CYRUS_THE_VIRUS);
FightRequest.specialMonsters.put("Dad Sea Monkee", SpecialMonster.DAD_SEA_MONKEE);
FightRequest.specialMonsters.put("drippy bat", SpecialMonster.DRIPPY_BAT);
FightRequest.specialMonsters.put("drippy reveler", SpecialMonster.DRIPPY_REVELER);
FightRequest.specialMonsters.put("family of kobolds", SpecialMonster.FAMILY_OF_KOBOLDS);
FightRequest.specialMonsters.put("gargantulihc", SpecialMonster.GARGANTULIHC);
FightRequest.specialMonsters.put("giant octopus", SpecialMonster.GIANT_OCTOPUS);
FightRequest.specialMonsters.put("giant skeelton", SpecialMonster.GIANT_SKEELTON);
FightRequest.specialMonsters.put("huge ghoul", SpecialMonster.HUGE_GHUOL);
FightRequest.specialMonsters.put("piranha plant", SpecialMonster.PIRANHA_PLANT);
FightRequest.specialMonsters.put("pygmy janitor", SpecialMonster.PYGMY_JANITOR);
FightRequest.specialMonsters.put("pygmy witch lawyer", SpecialMonster.PYGMY_WITCH_LAWYER);
FightRequest.specialMonsters.put("sausage goblin", SpecialMonster.SAUSAGE_GOBLIN);
FightRequest.specialMonsters.put("time-spinner prank", SpecialMonster.TIME_SPINNER_PRANK);
FightRequest.specialMonsters.put("unusual construct", SpecialMonster.UNUSUAL_CONSTRUCT);
FightRequest.specialMonsters.put("angry bassist", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("blue-haired girl", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("evil ex-girlfriend", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("peeved roommate", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("random scenester", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Beast", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Beetle", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Constellation", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Crimbo Elf", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Demon", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Elemental", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Fish", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Flower", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Frat Orc", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Goblin", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Golem", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Hippy", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Hobo", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Man", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Manloid", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Mer-kin", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Penguin", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Pirate", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Shambling Monstrosity", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Slime", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Spiraling Shape", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Black Crayon Undead Thing", SpecialMonster.HIPSTER);
FightRequest.specialMonsters.put("Witchess Bishop", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess King", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess Knight", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess Ox", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess Pawn", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess Queen", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess Rook", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("Witchess Witch", SpecialMonster.WITCHESS);
FightRequest.specialMonsters.put("beebee gunners", SpecialMonster.BEE);
FightRequest.specialMonsters.put("moneybee", SpecialMonster.BEE);
FightRequest.specialMonsters.put("mumblebee", SpecialMonster.BEE);
FightRequest.specialMonsters.put("beebee queue", SpecialMonster.BEE);
FightRequest.specialMonsters.put("bee swarm", SpecialMonster.BEE);
FightRequest.specialMonsters.put("buzzerker", SpecialMonster.BEE);
FightRequest.specialMonsters.put("Beebee King", SpecialMonster.BEE);
FightRequest.specialMonsters.put("bee thoven", SpecialMonster.BEE);
FightRequest.specialMonsters.put("Queen Bee", SpecialMonster.BEE);
FightRequest.specialMonsters.put("Performer of Actions", SpecialMonster.DMT);
FightRequest.specialMonsters.put("Thinker of Thoughts", SpecialMonster.DMT);
FightRequest.specialMonsters.put("Perceiver of Sensations", SpecialMonster.DMT);
FightRequest.specialMonsters.put("animal cracker", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread alligator", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread convict", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread finance bro", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread gentrifier", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread lawyer", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread mad dog", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread mugger", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread mutant", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread pigeon", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread rat", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread tech bro", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread vagrant", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread vigilante", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread welder robot", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("gingerbread wino", SpecialMonster.GINGERBREAD);
FightRequest.specialMonsters.put("Judge Fudge", SpecialMonster.GINGERBREAD);
// The following monster appears following a choice which already counted the turn
// FightRequest.specialMonsters.put( "GNG-3-R" , SpecialMonster.GINGERBREAD );
FightRequest.specialMonsters.put("Candied Yam Golem", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Malevolent Tofurkey", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Possessed Can of Cranberry Sauce", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Stuffing Golem", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Hammered Yam Golem", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Inebriated Tofurkey", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Plastered Can of Cranberry Sauce", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Soused Stuffing Golem", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Novio Cadáver", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Padre Cadáver", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Novia Cadáver", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Persona Inocente Cadáver", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("ambulatory pirate", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("migratory pirate", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("peripatetic pirate", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("giant pumpkin-head", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("large-headed werewolf", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("oddly-proportioned ghost", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("Cinco de Mayo reveler", SpecialMonster.HOLIDAY);
FightRequest.specialMonsters.put("sign-twirling Crimbo elf", SpecialMonster.TACO_ELF);
FightRequest.specialMonsters.put("tacobuilding elf", SpecialMonster.TACO_ELF);
FightRequest.specialMonsters.put("taco-clad Crimbo elf", SpecialMonster.TACO_ELF);
FightRequest.specialMonsters.put("depressing French accordionist", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("lively Cajun accordionist", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("quirky indie-rock accordionist", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("Possessed Can of Linguine-Os", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("Possessed Can of Creepy Pasta", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("Frozen Bag of Tortellini", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("Possessed Jar of Alphredo™", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("Box of Crafty Dinner", SpecialMonster.EVENT);
FightRequest.specialMonsters.put("menacing thug", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("Mob Penguin hitman", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("hunting seal", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("turtle trapper", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("evil spaghetti cult assassin", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("béarnaise zombie", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("flock of seagulls", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("mariachi bandolero", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("Argarggagarg the Dire Hellseal", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("Safari Jack, Small-Game Hunter", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("Yakisoba the Executioner", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("Heimandatz, Nacho Golem", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("Jocko Homo", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("The Mariachi With No Name", SpecialMonster.NEMESIS);
FightRequest.specialMonsters.put("alley catfish", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("aquaconda", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("freshwater bonefish", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("giant isopod", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("giant tardigrade", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("gourmet gourami", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("piranhadon", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("storm cow", SpecialMonster.RAIN);
FightRequest.specialMonsters.put("aggressive grass snake", SpecialMonster.WOL);
FightRequest.specialMonsters.put("emaciated rodeo clown", SpecialMonster.WOL);
FightRequest.specialMonsters.put("furious cow", SpecialMonster.WOL);
FightRequest.specialMonsters.put("furious giant cow", SpecialMonster.WOL);
FightRequest.specialMonsters.put("grizzled rodeo clown", SpecialMonster.WOL);
FightRequest.specialMonsters.put("king snake", SpecialMonster.WOL);
FightRequest.specialMonsters.put("menacing rodeo clown", SpecialMonster.WOL);
FightRequest.specialMonsters.put("prince snake", SpecialMonster.WOL);
FightRequest.specialMonsters.put("ungulith", SpecialMonster.WOL);
FightRequest.specialMonsters.put("Source Agent", SpecialMonster.PORTSCAN);
FightRequest.specialMonsters.put("Government agent", SpecialMonster.PORTSCAN);
FightRequest.addAreaMonsters("A Maze of Sewer Tunnels", SpecialMonster.SEWER);
FightRequest.addAreaMonsters("The Battlefield (Frat Uniform)", SpecialMonster.WAR_HIPPY);
FightRequest.addAreaMonsters("The Battlefield (Hippy Uniform)", SpecialMonster.WAR_FRATBOY);
}
private static void addAreaMonsters(String area, SpecialMonster category) {
AreaCombatData combatData = AdventureDatabase.getAreaCombatData(area);
if (combatData == null) {
RequestLogger.printLine(
"Invalid adventure area while initializing special monsters: \"" + area + "\"");
return;
}
for (MonsterData monster : combatData.getMonsters()) {
FightRequest.specialMonsters.put(monster.getName(), category);
}
for (MonsterData monster : combatData.getSuperlikelyMonsters()) {
FightRequest.specialMonsters.put(monster.getName(), category);
}
}
private static final SimpleDateFormat COMBAT_START = new SimpleDateFormat("yyyyMMddHHmmss");
static {
FightRequest.COMBAT_START.setTimeZone(TimeZone.getTimeZone("GMT"));
}
// Make an HTML cleaner
private static final HtmlCleaner cleaner = HTMLParserUtils.configureDefaultParser();
static {
CleanerProperties props = cleaner.getProperties();
// Need to parse the forms in a fambattle
// props.setPruneTags( "form" );
}
/**
* Constructs a new <code>FightRequest</code>. User settings will be used to determine the kind of
* action to be taken during the battle.
*/
private FightRequest() {
super("fight.php");
}
public static final void initialize() {}
public static final void resetKisses() {
FightRequest.dreadWoodsKisses = 0;
FightRequest.dreadVillageKisses = 0;
FightRequest.dreadCastleKisses = 0;
}
public static final int dreadKisses(final KoLAdventure location) {
return FightRequest.dreadKisses(location.getAdventureName());
}
public static final int dreadKisses(final String name) {
return name.endsWith("Woods")
? Math.max(FightRequest.dreadWoodsKisses, 1)
: name.endsWith("Village")
? Math.max(FightRequest.dreadVillageKisses, 1)
: name.endsWith("Castle") ? Math.max(FightRequest.dreadCastleKisses, 1) : 0;
}
public static final AdventureResult[] PAPIER_EQUIPMENT = {
ItemPool.get(ItemPool.PAPIER_MACHETE, 1),
ItemPool.get(ItemPool.PAPIER_MACHINE_GUN, 1),
ItemPool.get(ItemPool.PAPIER_MASK, 1),
ItemPool.get(ItemPool.PAPIER_MITRE, 1),
ItemPool.get(ItemPool.PAPIER_MACHURIDARS, 1),
};
private static boolean usingPapierEquipment() {
for (AdventureResult adventureResult : PAPIER_EQUIPMENT) {
if (KoLCharacter.hasEquipped(adventureResult)) {
return true;
}
}
return false;
}
@Override
protected boolean retryOnTimeout() {
return true;
}
@Override
protected boolean shouldFollowRedirect() {
// In Pokefam at least, this can happen as we redirect to fambattle.php
return true;
}
private static final Pattern CAN_STEAL_PATTERN =
Pattern.compile(
"value=\"(Pick (?:His|Her|Their|Its) Pocket(?: Again)?|Look for Shiny Objects)\"");
public static final boolean canStillSteal() {
// Return true if you can still steal during this battle.
// Must be a Moxie class character or any character in Birdform
// or have a tiny black hole equipped.in the offhand slot
if (!KoLCharacter.canPickpocket()) {
return false;
}
// Look for buttons that allow you to pickpocket
String responseText = FightRequest.lastResponseText;
Matcher matcher = FightRequest.CAN_STEAL_PATTERN.matcher(responseText);
return matcher.find();
}
public static final boolean canOlfact() {
return FightRequest.canOlfact
&& !KoLCharacter.inGLover()
&& !KoLConstants.activeEffects.contains(FightRequest.ONTHETRAIL);
}
public static final boolean isSourceAgent() {
MonsterData monster = MonsterStatusTracker.getLastMonster();
return monster != null && FightRequest.isSourceAgent(monster);
}
public static final boolean isSourceAgent(MonsterData monster) {
String name = monster.getName();
return name.equals("Source Agent") || name.equals("One Thousand Source Agents");
}
public static final boolean isPirate() {
return FightRequest.isPirate(MonsterStatusTracker.getLastMonster());
}
public static final boolean isPirate(MonsterData monster) {
return (AdventureDatabase.getAreaCombatData("The Obligatory Pirate's Cove").hasMonster(monster)
|| AdventureDatabase.getAreaCombatData("Barrrney's Barrr").hasMonster(monster)
|| AdventureDatabase.getAreaCombatData("The F'c'le").hasMonster(monster)
|| AdventureDatabase.getAreaCombatData("The Poop Deck").hasMonster(monster)
|| AdventureDatabase.getAreaCombatData("Belowdecks").hasMonster(monster));
}
public static final boolean canPirateInsult() {
return (InventoryManager.getCount(ItemPool.get(ItemPool.PIRATE_INSULT_BOOK, 1)) > 0
|| InventoryManager.getCount(ItemPool.get(ItemPool.MARAUDER_MOCKERY_MANUAL, 1)) > 0)
&& BeerPongRequest.countPirateInsults() != 8
&& FightRequest.insultedPirate == false
&& FightRequest.isPirate();
}
public static final boolean canJamFlyer() {
return KoLConstants.inventory.contains(ItemPool.get(ItemPool.JAM_BAND_FLYERS, 1))
&& Preferences.getInteger("flyeredML") < 10000
&& usedFlyer == false
&& !IslandManager.isBattlefieldMonster()
&& !QuestDatabase.isQuestFinished(QuestDatabase.Quest.ISLAND_WAR)
&& !KoLCharacter.inGLover();
}
public static final boolean canRockFlyer() {
return KoLConstants.inventory.contains(ItemPool.get(ItemPool.ROCK_BAND_FLYERS, 1))
&& Preferences.getInteger("flyeredML") < 10000
&& usedFlyer == false
&& !IslandManager.isBattlefieldMonster()
&& !QuestDatabase.isQuestFinished(QuestDatabase.Quest.ISLAND_WAR)
&& !KoLCharacter.inGLover();
}
public static void initializeAfterFight() {
FightRequest.initializeAfterFight = true;
}
public static boolean initializingAfterFight() {
return FightRequest.initializeAfterFight;
}
public static final boolean wonInitiative() {
return FightRequest.currentRound == 1
&& (FightRequest.pokefam || FightRequest.wonInitiative(FightRequest.lastResponseText));
}
public static final boolean wonInitiative(String text) {
// Regular encounter or on Seahorse underwater
if (text.toLowerCase().contains("you get the jump")) return true;
// Can Has Cyborger
if (text.contains("The Jump: ")) return true;
// Blavious Kloop
// You leap into combat, as quick as a wink,
// attacking the monster before he can blink!
if (text.contains("as quick as a wink")) return true;
// Who got the jump? Oh please, who, tell me, who?
// It wasn't your foe, so it must have been you!
if (text.contains("It wasn't your foe, so it must have been you")) return true;
// Your foe is so slow! So slow is your foe!
// Much slower than you, who are ready to go!
if (text.contains("Your foe is so slow")) return true;
// Haiku dungeon
// Before he sees you,
// you're already attacking.
// You're sneaky like that.
if (text.contains("You're sneaky like that.")) return true;
// You leap at your foe,
// throwing caution to the wind,
// and get the first strike.
if (text.contains("and get the first strike.")) return true;
// You jump at your foe
// and strike before he's ready.
// Nice and sportsmanlike.
if (text.contains("Nice and sportsmanlike.")) return true;
// The Deep Machine Tunnels
// It hesitates. It <vocalizes>. It <moves>.
if (text.contains("It hesitates.")) return true;
return false;
}
public static int getMacroPrefixLength() {
return FightRequest.macroPrefixLength;
}
public static void setMacroPrefixLength(final int lines) {
FightRequest.macroPrefixLength = lines;
}
private void skipRound() {
--FightRequest.preparatoryRounds;
this.nextRound(null);
}
private void nextRound(String desiredAction) {
if (KoLmafia.refusesContinue()) {
FightRequest.nextAction = "abort";
return;
}
// First round, KoLmafia does not decide the action.
// Update accordingly.
if (FightRequest.currentRound == 0) {
FightRequest.macroPrefixLength = 0;
FightRequest.nextAction = null;
return;
}
MonsterData monster = MonsterStatusTracker.getLastMonster();
String monsterName = monster != null ? monster.getName() : "";
// Always let the user see rare monsters
if (EncounterManager.isUltrarareMonster(monsterName)) {
KoLmafia.updateDisplay(MafiaState.ABORT, "You have encountered the " + this.encounter);
FightRequest.nextAction = "abort";
return;
}
// Desired action overrides any internal logic not related to macros
if (desiredAction != null && desiredAction.length() > 0) {
if (CombatActionManager.isMacroAction(desiredAction)) {
this.handleMacroAction(desiredAction);
return;
}
FightRequest.nextAction = CombatActionManager.getShortCombatOptionName(desiredAction);
} else {
// Fight automation is still considered automation.
// If the player drops below the threshold, then go
// ahead and halt the battle.
if (!RecoveryManager.runThresholdChecks()) {
FightRequest.nextAction = "abort";
return;
}
FightRequest.nextAction = null;
String macro = Macrofier.macrofy();
if (macro != null && macro.length() > 0) {
if (macro.contains("\n") || macro.contains(";")) {
this.handleMacroAction(macro);
return;
}
FightRequest.nextAction = CombatActionManager.getShortCombatOptionName(macro);
}
// Adding machine should override custom combat scripts as well,
// since it's conditions-driven.
else if (monsterName.equals("rampaging adding machine")
&& !KoLConstants.activeEffects.contains(FightRequest.BIRDFORM)
&& !FightRequest.waitingForSpecial) {
this.handleAddingMachine();
}
// Hulking Constructs also require special handling
else if (monsterName.equals("hulking construct")) {
if (problemFamiliar()) {
KoLmafia.updateDisplay(
MafiaState.ABORT,
"Aborting combat automation due to Familiar that can stop automatic item usage.");
return;
}
this.handleHulkingConstruct();
}
if (FightRequest.nextAction == null) {
String name = MonsterStatusTracker.getLastMonsterName();
int roundIndex = FightRequest.macroPrefixLength;
String combatAction = CombatActionManager.getCombatAction(name, roundIndex, false);
FightRequest.nextAction = CombatActionManager.getShortCombatOptionName(combatAction);
}
}
// If the person wants to use their own script,
// then this is where it happens.
if (FightRequest.nextAction.startsWith("consult")) {
FightRequest.isUsingConsultScript = true;
String scriptName = FightRequest.nextAction.substring("consult".length()).trim();
List<File> scriptFiles = KoLmafiaCLI.findScriptFile(scriptName);
ScriptRuntime consultInterpreter = KoLmafiaASH.getInterpreter(scriptFiles);
if (consultInterpreter != null) {
int initialRound = FightRequest.currentRound;
Object[] parameters = new Object[3];
parameters[0] = FightRequest.currentRound;
parameters[1] = MonsterStatusTracker.getLastMonster();
parameters[2] = FightRequest.lastResponseText;
File scriptFile = scriptFiles.get(0);
KoLmafiaASH.logScriptExecution(
"Starting consult script: ", scriptFile.getName(), consultInterpreter);
// Since we are automating, let the script execute without interruption