/**
* Copyright (c) 2005-2017, KoLmafia development team
* http://kolmafia.sourceforge.net/
* All rights reserved.
*
* Redistribution and use in source and binary forms, with or without
* modification, are permitted provided that the following conditions
* are met:
*
* [1] Redistributions of source code must retain the above copyright
* notice, this list of conditions and the following disclaimer.
* [2] Redistributions in binary form must reproduce the above copyright
* notice, this list of conditions and the following disclaimer in
* the documentation and/or other materials provided with the
* distribution.
* [3] Neither the name "KoLmafia" nor the names of its contributors may
* be used to endorse or promote products derived from this software
* without specific prior written permission.
*
* THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS
* "AS IS" AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT
* LIMITED TO, THE IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS
* FOR A PARTICULAR PURPOSE ARE DISCLAIMED. IN NO EVENT SHALL THE
* COPYRIGHT OWNER OR CONTRIBUTORS BE LIABLE FOR ANY DIRECT, INDIRECT,
* INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES (INCLUDING,
* BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR SERVICES;
* LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) HOWEVER
* CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
* LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN
* ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
* POSSIBILITY OF SUCH DAMAGE.
*/
package net.sourceforge.kolmafia.persistence;
import java.io.BufferedReader;
import java.util.ArrayList;
import java.util.Arrays;
import java.util.HashMap;
import java.util.List;
import java.util.Map.Entry;
import java.util.StringTokenizer;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.java.dev.spellcast.utilities.LockableListModel;
import net.sourceforge.kolmafia.AdventureResult;
import net.sourceforge.kolmafia.AreaCombatData;
import net.sourceforge.kolmafia.KoLAdventure;
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.MonsterData;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.StaticEntity;
import net.sourceforge.kolmafia.objectpool.AdventurePool;
import net.sourceforge.kolmafia.objectpool.IntegerPool;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.persistence.BountyDatabase;
import net.sourceforge.kolmafia.persistence.MonsterDatabase.Element;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.request.ClanRumpusRequest;
import net.sourceforge.kolmafia.request.GenericRequest;
import net.sourceforge.kolmafia.request.RelayRequest;
import net.sourceforge.kolmafia.request.RichardRequest;
import net.sourceforge.kolmafia.session.EncounterManager;
import net.sourceforge.kolmafia.session.EncounterManager.EncounterType;
import net.sourceforge.kolmafia.session.InventoryManager;
import net.sourceforge.kolmafia.utilities.FileUtilities;
import net.sourceforge.kolmafia.utilities.StringArray;
import net.sourceforge.kolmafia.utilities.StringUtilities;
public class AdventureDatabase
{
private static final Pattern SNARF_PATTERN = Pattern.compile( "snarfblat=(\\d+)" );
private static final Pattern MINE_PATTERN = Pattern.compile( "mine=(\\d+)" );
private static final LockableListModel<KoLAdventure> adventures = new LockableListModel<KoLAdventure>();
private static final AdventureArray allAdventures = new AdventureArray();
public static final ArrayList<String> PARENT_LIST = new ArrayList<String>();
public static final HashMap<String, String> PARENT_ZONES = new HashMap<String, String>();
public static final HashMap<String, String> ZONE_DESCRIPTIONS = new HashMap<String, String>();
private static final StringArray[] adventureTable = new StringArray[ 4 ];
private static final HashMap<String, AreaCombatData> areaCombatData = new HashMap<String, AreaCombatData>();
private static final HashMap<String, KoLAdventure> adventureLookup = new HashMap<String, KoLAdventure>();
private static final HashMap<String, String> environmentLookup = new HashMap<String, String>();
private static final HashMap<String, String> zoneLookup = new HashMap<String, String>();
private static final HashMap<String, String> conditionLookup = new HashMap<String, String>();
private static final HashMap<String, String> bountyLookup = new HashMap<String, String>();
private static final HashMap<String, Integer> statLookup = new HashMap<String, Integer>();
private static final HashMap<String, Integer> waterLevelLookup = new HashMap<String, Integer>();
static
{
for ( int i = 0; i < AdventureDatabase.adventureTable.length; ++i )
{
AdventureDatabase.adventureTable[ i ] = new StringArray();
}
AdventureDatabase.refreshZoneTable();
AdventureDatabase.refreshAdventureTable();
AdventureDatabase.refreshCombatsTable();
AdventureDatabase.refreshAdventureList();
}
public static final AdventureResult[] WOODS_ITEMS = new AdventureResult[ 12 ];
static
{
for ( int i = 0; i < 12; ++i )
{
AdventureDatabase.WOODS_ITEMS[ i ] = ItemPool.get( i + 1 );
}
}
// Some adventures don't actually cost a turn
public static final String[] FREE_ADVENTURES =
{
"Rock-a-bye larva",
"Cobb's Knob lab key"
};
public static final void refreshZoneTable()
{
if ( !AdventureDatabase.ZONE_DESCRIPTIONS.isEmpty() )
{
return;
}
BufferedReader reader = FileUtilities.getVersionedReader( "zonelist.txt", KoLConstants.ZONELIST_VERSION );
if ( reader == null )
{
return;
}
String[] data;
while ( ( data = FileUtilities.readData( reader ) ) != null )
{
if ( data.length >= 3 )
{
String zone = new String( data[ 0 ] );
String parent = new String( data[ 1 ] );
String description = new String( data[ 2 ] );
AdventureDatabase.PARENT_ZONES.put( zone, parent );
if ( !AdventureDatabase.PARENT_LIST.contains( parent ) )
{
AdventureDatabase.PARENT_LIST.add( parent );
}
AdventureDatabase.ZONE_DESCRIPTIONS.put( zone, description );
}
}
try
{
reader.close();
}
catch ( Exception e )
{
// This should not happen. Therefore, print
// a stack trace for debug purposes.
StaticEntity.printStackTrace( e );
}
}
public static final void refreshAdventureTable()
{
BufferedReader reader = FileUtilities.getVersionedReader( "adventures.txt", KoLConstants.ADVENTURES_VERSION );
if ( reader == null )
{
return;
}
for ( int i = 0; i < AdventureDatabase.adventureTable.length; ++i )
{
AdventureDatabase.adventureTable[ i ].clear();
}
String[] data;
while ( ( data = FileUtilities.readData( reader ) ) != null )
{
if ( data.length <= 3 )
{
continue;
}
String zone = new String( data[ 0 ] );
String[] location = data[ 1 ].split( "=" );
String environment = null;
int stat = -1;
int waterLevel = -1;
StringTokenizer tokens = new StringTokenizer( data[ 2 ], " " );
while ( tokens.hasMoreTokens() )
{
String option = tokens.nextToken();
if ( option.equals( "Env:" ) )
{
environment = tokens.nextToken();
}
else if ( option.equals( "Stat:" ) )
{
stat = StringUtilities.parseInt( tokens.nextToken() );
}
else if ( option.equals( "Level:" ) )
{
waterLevel = StringUtilities.parseInt( tokens.nextToken() );
}
}
String name = new String( data[ 3 ] );
if ( environment == null )
{
RequestLogger.printLine( "Adventure area \"" + name + "\" is missing environment data" );
}
if ( AdventureDatabase.PARENT_ZONES.get( zone ) == null )
{
RequestLogger.printLine( "Adventure area \"" + name + "\" has invalid zone: \"" + zone + "\"" );
continue;
}
AdventureDatabase.zoneLookup.put( name, zone );
AdventureDatabase.adventureTable[ 0 ].add( zone );
AdventureDatabase.adventureTable[ 1 ].add( location[ 0 ] + ".php" );
AdventureDatabase.adventureTable[ 2 ].add( new String( location[ 1 ] ) );
AdventureDatabase.adventureTable[ 3 ].add( name );
AdventureDatabase.environmentLookup.put( name, environment );
AdventureDatabase.statLookup.put( name, stat );
// Build base water level if not specified
if ( waterLevel == -1 )
{
if ( environment == null || environment.equals( "outdoor" ) || environment.equals( "none" ) )
{
waterLevel = 1;
}
else if ( environment.equals( "indoor" ) )
{
waterLevel = 3;
}
else if ( environment.equals( "underground" ) )
{
waterLevel = 5;
}
if ( stat >= 40 )
{
waterLevel++;
}
if ( "underwater".equals( environment ) )
{
waterLevel = 0;
}
}
AdventureDatabase.waterLevelLookup.put( name, waterLevel );
if ( data.length <= 4 )
{
continue;
}
if ( !data[ 4 ].equals( "" ) )
{
AdventureDatabase.conditionLookup.put( name, new String( data[ 4 ] ) );
}
}
try
{
reader.close();
}
catch ( Exception e )
{
// This should not happen. Therefore, print
// a stack trace for debug purposes.
StaticEntity.printStackTrace( e );
}
}
public static final void refreshCombatsTable()
{
AdventureDatabase.areaCombatData.clear();
BufferedReader reader = FileUtilities.getVersionedReader( "combats.txt", KoLConstants.COMBATS_VERSION );
if ( reader == null )
{
return;
}
String[] data;
while ( ( data = FileUtilities.readData( reader ) ) != null )
{
if ( data.length > 1 )
{
if ( !AdventureDatabase.validateAdventureArea( data[ 0 ] ) )
{
RequestLogger.printLine( "Invalid adventure area: \"" + data[ 0 ] + "\"" );
continue;
}
int combats = StringUtilities.parseInt( data[ 1 ] );
// There can be an ultra-rare monster even if
// there are no other combats
AreaCombatData combat = new AreaCombatData( data[0], combats );
for ( int i = 2; i < data.length; ++i )
{
String monsterName = data[ i ];
combat.addMonster( monsterName );
// Does it drop a bounty, if so add it to the bounty lookup by area
// Trim any trailing ":" and following text
int colonIndex = data[ i ].indexOf( ":" );
if ( colonIndex > 0 )
{
monsterName = monsterName.substring( 0, colonIndex );
}
String bountyName = BountyDatabase.getNameByMonster( monsterName );
if ( bountyName != null )
{
AdventureDatabase.bountyLookup.put( data[ 0 ], bountyName );
}
}
AdventureDatabase.areaCombatData.put( data[ 0 ], combat );
}
}
try
{
reader.close();
}
catch ( Exception e )
{
// This should not happen. Therefore, print
// a stack trace for debug purposes.
StaticEntity.printStackTrace( e );
}
}
public static final void refreshAdventureList()
{
AdventureDatabase.adventures.clear();
AdventureDatabase.allAdventures.clear();
AdventureDatabase.adventureLookup.clear();
for ( int i = 0; i < AdventureDatabase.adventureTable[ 0 ].size(); ++i )
{
AdventureDatabase.addAdventure( AdventureDatabase.getAdventure( i ) );
}
}
public static final void addAdventure( final KoLAdventure location )
{
AdventureDatabase.adventures.add( location );
AdventureDatabase.allAdventures.add( location );
GenericRequest request = location.getRequest();
// This will force the URLstring to be reconstructed and the
// correct password hash inserted when the request is run
request.removeFormField( "pwd" );
String url = request.getURLString();
AdventureDatabase.adventureLookup.put( url, location );
if ( url.contains( "snarfblat=" ) )
{
// The map of the Bat Hole has a bogus URL for the Boss Bat's lair
if ( url.contains( "snarfblat=34" ) )
{
AdventureDatabase.adventureLookup.put( url + ";", location );
}
url = StringUtilities.singleStringReplace( url, "snarfblat=", "adv=" );
AdventureDatabase.adventureLookup.put( url, location );
}
}
public static final LockableListModel<KoLAdventure> getAsLockableListModel()
{
if ( AdventureDatabase.adventures.isEmpty() )
{
AdventureDatabase.refreshAdventureList();
}
return AdventureDatabase.adventures;
}
public static final KoLAdventure getAdventureByURL( String adventureURL )
{
if ( AdventureDatabase.adventureLookup.isEmpty() )
{
AdventureDatabase.refreshAdventureList();
}
if ( adventureURL.startsWith( "/" ) )
{
adventureURL = adventureURL.substring( 1 );
}
// Barrel smashes count as adventures.
if ( adventureURL.startsWith( "barrel.php" ) )
{
return AdventureDatabase.adventureLookup.get( "barrel.php" );
}
// Visiting the basement counts as an adventure
if ( adventureURL.startsWith( "basement.php" ) )
{
return AdventureDatabase.adventureLookup.get( "basement.php" );
}
// Visiting the tavern cellar might count as an adventure
if ( adventureURL.startsWith( "cellar.php" ) )
{
// action=explore or action=autofaucet
String action = GenericRequest.extractField( adventureURL, "action" );
if ( action == null )
{
return null;
}
return AdventureDatabase.adventureLookup.get( "cellar.php" );
}
// Mining in disguise count as adventures.
if ( adventureURL.startsWith( "mining.php" ) )
{
String mine = GenericRequest.extractField( adventureURL, "mine" );
if ( mine == null )
{
return null;
}
return AdventureDatabase.adventureLookup.get( "mining.php?" + mine );
}
if ( adventureURL.startsWith( "place.php" ) )
{
// Adventuring in the Lower Chamber
if ( adventureURL.contains( "action=pyramid_state" ) )
{
return AdventureDatabase.getAdventure( "The Lower Chambers" );
}
if ( adventureURL.contains( "whichplace=nstower" ) )
{
if ( adventureURL.contains( "action=ns_01_crowd2" ) )
{
String stat = Preferences.getString( "nsChallenge1" );
String adventure =
stat.equals( Stat.MUSCLE.toString() ) ?
"Strongest Adventurer Contest" :
stat.equals( Stat.MYSTICALITY.toString() ) ?
"Smartest Adventurer Contest" :
stat.equals( Stat.MOXIE.toString() ) ?
"Smoothest Adventurer Contest" :
"A Crowd of (Stat) Adventurers";
return AdventureDatabase.getAdventure( adventure );
}
if ( adventureURL.contains( "action=ns_01_crowd3" ) )
{
String element = Preferences.getString( "nsChallenge2" );
String adventure =
element.equals( Element.HOT.toString() ) ?
"Hottest Adventurer Contest" :
element.equals( Element.COLD.toString() ) ?
"Coldest Adventurer Contest" :
element.equals( Element.SPOOKY.toString() ) ?
"Spookiest Adventurer Contest" :
element.equals( Element.STENCH.toString() ) ?
"Stinkiest Adventurer Contest" :
element.equals( Element.SLEAZE.toString() ) ?
"Sleaziest Adventurer Contest" :
"A Crowd of (Element) Adventurers";
return AdventureDatabase.getAdventure( adventure );
}
}
// place.php?whichplace=manor4&action=manor4_chamber
// place.php?whichplace=manor4&action=manor4_chamberboss
// place.php?whichplace=manor4&action=manor4_chamberwall
// Adventuring in the Summoning Chamber
if ( adventureURL.contains( "action=manor4_chamberboss" ) )
{
return AdventureDatabase.getAdventure( "Summoning Chamber" );
}
// place.php?whichplace=beanstalk&action=stalk_eincursion
// place.php?whichplace=bordertown&action=bordertown_eincursion
// place.php?whichplace=bordertown&action=bordertown_eincursion2
// place.php?whichplace=cemetery&action=cem_eincursion
// place.php?whichplace=desertbeach&action=db_eincursion
// place.php?whichplace=forestvillage&action=fv_eincursion
// place.php?whichplace=giantcastle&action=castle_eincursion
// place.php?whichplace=manor1&action=manor1_eincursion
// place.php?whichplace=mclargehuge&action=mlh_eincurions
// place.php?whichplace=mountains&action=mts_eincursion
// place.php?whichplace=plains&action=plains_eincursion
// place.php?whichplace=thesea&action=thesea_zenicursio
// place.php?whichplace=town&action=town_eincursion
// place.php?whichplace=town&action=town_eincursion2
// place.php?whichplace=town&action=town_eincursion3
// place.php?whichplace=town_market&action=townmarket_eincursion
// place.php?whichplace=town_wrong&action=townrwong_eincursion
// place.php?whichplace=woods&action=woods_eincursion
if ( adventureURL.contains( "action=town_eincursion" )
// Main town fissure first, others alphabetically
// Disable all the secondary fissures for now
/*
|| adventureURL.contains( "action=bordertown_eincursion" )
|| adventureURL.contains( "action=bordertown_eincursion2" )
|| adventureURL.contains( "action=castle_eincursion" )
|| adventureURL.contains( "action=cem_eincursion" )
|| adventureURL.contains( "action=db_eincursion" )
|| adventureURL.contains( "action=fv_eincursion" )
|| adventureURL.contains( "action=manor1_eincursion" )
|| adventureURL.contains( "action=mlh_eincurions" )
|| adventureURL.contains( "action=mts_eincursion" )
|| adventureURL.contains( "action=plains_eincursion" )
|| adventureURL.contains( "action=stalk_eincursion" )
|| adventureURL.contains( "action=thesea_zenicursio" )
|| adventureURL.contains( "action=town_eincursion2" )
|| adventureURL.contains( "action=town_eincursion3" )
|| adventureURL.contains( "action=townmarket_eincursion" )
|| adventureURL.contains( "action=townrwong_eincursion" )
|| adventureURL.contains( "action=woods_eincursion" )
*/
)
{
return AdventureDatabase.getAdventure( "An Eldritch Fissure" );
}
if ( adventureURL.contains( "action=townwrong_tunnel" ) )
{
return AdventureDatabase.getAdventure( "The Tunnel of L.O.V.E." );
}
if ( adventureURL.contains( "action=town_eicfight2" ) )
{
return AdventureDatabase.getAdventure( "An Eldritch Horror" );
}
// place.php?whichplace=ioty2014_wolf&action=wolf_houserun
if ( adventureURL.contains( "action=wolf_houserun" ) )
{
return AdventureDatabase.getAdventure( "Unleash Your Inner Wolf" );
}
}
// Adventuring in the barracks after the Nemesis has been defeated
if ( adventureURL.startsWith( "volcanoisland.php" ) && adventureURL.contains( "action=tuba" ) )
{
return AdventureDatabase.getAdventure( "The Island Barracks" );
}
adventureURL = RelayRequest.removeConfirmationFields( adventureURL );
adventureURL = GenericRequest.removeField( adventureURL, "pwd" );
adventureURL = GenericRequest.removeField( adventureURL, "blech" );
adventureURL = StringUtilities.singleStringReplace( adventureURL, "action=ignorewarning&whichzone", "snarfblat" );
KoLAdventure location = AdventureDatabase.adventureLookup.get( adventureURL );
if ( location == null )
{
return null;
}
// *** Why exclude these?
return location.getRequest() instanceof ClanRumpusRequest ||
location.getRequest() instanceof RichardRequest
? null : location;
}
public static final KoLAdventure getAdventure( final String adventureName )
{
if ( AdventureDatabase.adventureLookup.isEmpty() )
{
AdventureDatabase.refreshAdventureList();
}
if ( adventureName == null || adventureName.equals( "" ) )
{
return null;
}
return AdventureDatabase.allAdventures.find( adventureName );
}
private static final KoLAdventure getAdventure( final int tableIndex )
{
return new KoLAdventure(
AdventureDatabase.adventureTable[ 0 ].get( tableIndex ),
AdventureDatabase.adventureTable[ 1 ].get( tableIndex ),
AdventureDatabase.adventureTable[ 2 ].get( tableIndex ),
AdventureDatabase.adventureTable[ 3 ].get( tableIndex ) );
}
public static final String getZone( final String location )
{
return zoneLookup.get( location );
}
public static final AdventureResult getBounty( final KoLAdventure adventure )
{
String adventureName = adventure.getAdventureName();
String bounty = AdventureDatabase.bountyLookup.get( adventureName );
if ( bounty == null || bounty.equals( "" ) )
{
return null;
}
int count = BountyDatabase.getNumber( bounty );
return new AdventureResult( bounty, count );
}
public static final String getDefaultConditions( final KoLAdventure adventure )
{
if ( adventure == null )
{
return "none";
}
// If you're currently doing a bounty, +1 filthy lucre.
String adventureName = adventure.getAdventureName();
String bounty = AdventureDatabase.bountyLookup.get( adventureName );
if ( bounty != null && !bounty.equals( "" ) )
{
String easyBountyId = Preferences.getString( "currentEasyBountyItem" );
if ( !easyBountyId.equals( "" ) )
{
if ( bounty.equals( easyBountyId.substring( 0, easyBountyId.indexOf( ":" ) ) ) )
{
return "+1 filthy lucre";
}
}
String hardBountyId = Preferences.getString( "currentHardBountyItem" );
if ( !hardBountyId.equals( "" ) )
{
if ( bounty.equals( hardBountyId.substring( 0, hardBountyId.indexOf( ":" ) ) ) )
{
return "+1 filthy lucre";
}
}
String specialBountyId = Preferences.getString( "currentSpecialBountyItem" );
if ( !specialBountyId.equals( "" ) )
{
if ( bounty.equals( specialBountyId.substring( 0, specialBountyId.indexOf( ":" ) ) ) )
{
return "+1 filthy lucre";
}
}
}
String def = "none";
// Pull the condition out of the table and return it.
String conditions = AdventureDatabase.conditionLookup.get( adventureName );
if ( conditions == null || conditions.equals( "" ) )
{
return def;
}
if ( !def.equals( "none" ) )
{
conditions = def + "|" + conditions;
}
return conditions;
}
public static final LockableListModel<String> getDefaultConditionsList( final KoLAdventure adventure, LockableListModel<String> list )
{
String string = AdventureDatabase.getDefaultConditions( adventure );
String [] conditions = string.split( "\\|" );
if ( list == null )
{
list = new LockableListModel<String>();
}
else
{
list.clear();
}
for ( int i = 0; i < conditions.length; ++i )
{
list.add( conditions[i] );
}
return list;
}
public static final boolean isFreeAdventure( final String text )
{
for ( int i = 0; i < AdventureDatabase.FREE_ADVENTURES.length; ++i )
{
if ( text.contains( AdventureDatabase.FREE_ADVENTURES[ i ] ) )
{
return true;
}
}
return false;
}
public static final boolean validateAdventureArea( final String area )
{
StringArray areas = AdventureDatabase.adventureTable[ 3 ];
for ( int i = 0; i < areas.size(); ++i )
{
if ( area.equals( areas.get( i ) ) )
{
return true;
}
}
return false;
}
public static final AreaCombatData getAreaCombatData( String area )
{
// Strip out zone name if present
int index = area.indexOf( ":" );
if ( index != -1 )
{
area = area.substring( index + 2 );
}
// Get the combat data
return AdventureDatabase.areaCombatData.get( area );
}
public static final ArrayList<String> getAreasWithMonster( MonsterData monster )
{
ArrayList<String> zones = new ArrayList<String>();
for ( Entry<String,AreaCombatData> entry : AdventureDatabase.areaCombatData.entrySet() )
{
AreaCombatData area = entry.getValue();
if ( area.hasMonster( monster ) )
{
zones.add( entry.getKey() );
}
}
return zones;
}
public static final String getUnknownName( final String urlString )
{
if ( urlString.startsWith( "adventure.php" ) )
{
Matcher matcher = AdventureDatabase.SNARF_PATTERN.matcher( urlString );
if ( matcher.find() )
{
String name = "Unknown Adventure #" + matcher.group(1);
String message = name + " = " + urlString;
RequestLogger.printLine( message );
RequestLogger.updateSessionLog( message );
return name;
}
return null;
}
if ( urlString.startsWith( "cave.php" ) )
{
if ( urlString.contains( "action=sanctum" ) )
{
return "Nemesis Cave: Inner Sanctum";
}
return null;
}
if ( urlString.startsWith( "guild.php?action=chal" ) )
{
return "Guild Challenge";
}
if ( urlString.startsWith( "mining.php" ) )
{
if ( urlString.contains( "intro=1" ) )
{
return null;
}
Matcher matcher = AdventureDatabase.MINE_PATTERN.matcher( urlString );
return matcher.find() ? "Unknown Mine #" + matcher.group(1) : null;
}
if ( urlString.startsWith( "place.php" ) )
{
if ( urlString.contains( "whichplace=ioty2014_rumple" ) )
{
if ( urlString.contains( "action=workshop" ) )
{
return "Rumpelstiltskin's Workshop";
}
return null;
}
return null;
}
if ( urlString.startsWith( "sea_merkin.php" ) )
{
if ( urlString.contains( "action=temple" ) )
{
return "Mer-kin Temple";
}
return null;
}
if ( urlString.startsWith( "town.php" ) )
{
if ( urlString.contains( "action=trickortreat" ) )
{
return "Trick-or-Treating";
}
return null;
}
return null;
}
public static final Object [][] FISTCORE_SCROLLS =
{
// Adventure Zone
// Adventure ID
// Setting
{
"The Haiku Dungeon",
IntegerPool.get( AdventurePool.HAIKU_DUNGEON ),
"fistTeachingsHaikuDungeon",
},
{
"The Poker Room",
IntegerPool.get( AdventurePool.POKER_ROOM ),
"fistTeachingsPokerRoom",
},
{
"A Barroom Brawl",
IntegerPool.get( AdventurePool.BARROOM_BRAWL ),
"fistTeachingsBarroomBrawl",
},
{
"The Haunted Conservatory",
IntegerPool.get( AdventurePool.HAUNTED_CONSERVATORY ),
"fistTeachingsConservatory",
},
{
"The Bat Hole Entrance",
IntegerPool.get( AdventurePool.BAT_HOLE_ENTRYWAY ),
"fistTeachingsBatHole",
},
{
"The \"Fun\" House",
IntegerPool.get( AdventurePool.FUN_HOUSE ),
"fistTeachingsFunHouse",
},
{
"Cobb's Knob Menagerie Level 2",
IntegerPool.get( AdventurePool.MENAGERIE_LEVEL_2 ),
"fistTeachingsMenagerie",
},
{
"Pandamonium Slums",
IntegerPool.get( AdventurePool.PANDAMONIUM_SLUMS ),
"fistTeachingsSlums",
},
{
"Frat House",
IntegerPool.get( AdventurePool.FRAT_HOUSE ),
"fistTeachingsFratHouse",
},
{
"Road to the White Citadel",
IntegerPool.get( AdventurePool.ROAD_TO_WHITE_CITADEL ),
"fistTeachingsRoad",
},
{
"Lair of the Ninja Snowmen",
IntegerPool.get( AdventurePool.NINJA_SNOWMEN ),
"fistTeachingsNinjaSnowmen",
},
};
private static int fistcoreDataLocation( final Object[] data )
{
return ( data == null ) ? -1 : ((Integer) data[1] ).intValue();
}
private static String fistcoreDataSetting( final Object[] data )
{
return ( data == null ) ? null : ((String) data[2] );
}
private static Object[] fistcoreLocationToData( final int location )
{
for ( int i = 0; i < FISTCORE_SCROLLS.length; ++i )
{
Object [] data = FISTCORE_SCROLLS[i];
int loc = fistcoreDataLocation( data );
if ( location == loc )
{
return data;
}
}
return null;
}
public static String fistcoreLocationToSetting( final int location )
{
return fistcoreDataSetting( fistcoreLocationToData( location ) );
}
/**
* Returns whether or not the user has a ten-leaf clover in inventory.
*
* @return <code>true</code>
*/
private static boolean hasClover()
{
return InventoryManager.getCount(ItemPool.TEN_LEAF_CLOVER ) > 0;
}
public static boolean isPotentialCloverAdventure( String adventureName )
{
String encounter = EncounterManager.findEncounterForLocation( adventureName, EncounterType.CLOVER );
return AdventureDatabase.hasClover() && encounter != null;
}
public static final String getEnvironment( String adventureName )
{
String env = AdventureDatabase.environmentLookup.get( adventureName );
return env == null ? "none" : env;
}
public static final int getRecommendedStat( String adventureName )
{
Integer stat = AdventureDatabase.statLookup.get( adventureName );
if ( stat == null )
{
return -1;
}
return stat;
}
public static final int getWaterLevel( String adventureName )
{
Integer waterLevel = AdventureDatabase.waterLevelLookup.get( adventureName );
if ( waterLevel == null )
{
return -1;
}
return waterLevel;
}
public static class AdventureArray
{
private String[] nameArray = new String[0];
private final ArrayList<String> nameList = new ArrayList<String>();
private final ArrayList<KoLAdventure> internalList = new ArrayList<KoLAdventure>();
public KoLAdventure get( final int index )
{
if ( index < 0 || index > this.internalList.size() )
{
return null;
}
return this.internalList.get( index );
}
public void add( final KoLAdventure value )
{
this.nameList.add( StringUtilities.getCanonicalName( value.getAdventureName() ) );
this.internalList.add( value );
}
public KoLAdventure find( String adventureName )
{
if ( nameArray.length != nameList.size() )
{
nameArray = new String[ nameList.size() ];
nameList.toArray( nameArray );
Arrays.sort( nameArray );
}
List matchingNames = StringUtilities.getMatchingNames( nameArray, adventureName );
if ( matchingNames.size() > 1 )
{
for ( int i = 0; i < matchingNames.size(); ++i )
{
RequestLogger.printLine( (String) matchingNames.get( i ) );
}
KoLmafia.updateDisplay( MafiaState.ERROR, "Multiple matches against " + adventureName + "." );
return null;
}
if ( matchingNames.size() == 1 )
{
String match = (String) matchingNames.get( 0 );
return this.get( nameList.indexOf( match ) );
}
return null;
}
public void clear()
{
this.nameList.clear();
this.internalList.clear();
}
public int size()
{
return this.internalList.size();
}
}
}