/**
* 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.request;
import java.util.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.kolmafia.AdventureResult;
import net.sourceforge.kolmafia.KoLCharacter;
import net.sourceforge.kolmafia.KoLConstants;
import net.sourceforge.kolmafia.KoLConstants.MafiaState;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.moods.MoodManager;
import net.sourceforge.kolmafia.moods.RecoveryManager;
import net.sourceforge.kolmafia.objectpool.ConcoctionPool;
import net.sourceforge.kolmafia.objectpool.EffectPool;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.objectpool.OutfitPool;
import net.sourceforge.kolmafia.persistence.ConcoctionDatabase;
import net.sourceforge.kolmafia.persistence.EquipmentDatabase;
import net.sourceforge.kolmafia.persistence.ItemDatabase;
import net.sourceforge.kolmafia.persistence.NPCStoreDatabase;
import net.sourceforge.kolmafia.persistence.QuestDatabase;
import net.sourceforge.kolmafia.persistence.QuestDatabase.Quest;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.session.EquipmentManager;
import net.sourceforge.kolmafia.session.ResultProcessor;
import net.sourceforge.kolmafia.utilities.StringUtilities;
public class NPCPurchaseRequest
extends PurchaseRequest
{
private static final AdventureResult TROUSERS = ItemPool.get( ItemPool.TRAVOLTAN_TROUSERS, 1 );
private static final AdventureResult FLEDGES = ItemPool.get( ItemPool.PIRATE_FLEDGES, 1 );
private final static AdventureResult SUPER_SKILL = EffectPool.get( EffectPool.SUPER_SKILL );
private final static AdventureResult SUPER_STRUCTURE = EffectPool.get( EffectPool.SUPER_STRUCTURE );
private final static AdventureResult SUPER_VISION = EffectPool.get( EffectPool.SUPER_VISION );
private final static AdventureResult SUPER_SPEED = EffectPool.get( EffectPool.SUPER_SPEED );
private final static AdventureResult SUPER_ACCURACY = EffectPool.get( EffectPool.SUPER_ACCURACY );
public static final Pattern PIRATE_EPHEMERA_PATTERN =
Pattern.compile( "pirate (?:brochure|pamphlet|tract)" );
private static final Pattern NPCSHOPID_PATTERN = Pattern.compile( "whichshop=([^&]*)" );
private final String npcStoreId;
private final String quantityField;
private final int row;
/**
* Constructs a new <code>NPCPurchaseRequest</code> which retrieves things from NPC stores.
*/
public NPCPurchaseRequest( final String storeName, final String storeId, final int itemId, final int row, final int price )
{
this( storeName, storeId, itemId, row, price, PurchaseRequest.MAX_QUANTITY );
}
public NPCPurchaseRequest( final String storeName, final String storeId, final int itemId, final int row, final int price, final int quantity )
{
super( NPCPurchaseRequest.pickForm( storeId ) );
this.isMallStore = false;
this.item = ItemPool.get( itemId );
this.shopName = storeName;
this.npcStoreId = storeId;
this.row = row;
this.quantity = quantity;
this.price = price;
this.limit = this.quantity;
this.canPurchase = true;
this.timestamp = 0L;
if ( this.row != 0 )
{
this.addFormField( "whichshop", storeId );
this.addFormField( "action", "buyitem" );
this.addFormField( "whichrow", String.valueOf( row ) );
this.addFormField( "ajax", "1" );
this.hashField = "pwd";
this.quantityField = "quantity";
return;
}
this.addFormField( "whichitem", String.valueOf( itemId ) );
if ( storeId.equals( "town_giftshop.php" ) )
{
this.addFormField( "action", "buy" );
this.hashField = "pwd";
this.quantityField = "howmany";
}
else if ( storeId.equals( "fdkol" ) )
{
this.addFormField( "whichshop", storeId );
this.addFormField( "action", "buyitem" );
this.addFormField( "ajax", "1" );
this.hashField = "pwd";
this.quantityField = "quantity";
}
else
{
this.addFormField( "whichstore", storeId );
this.addFormField( "buying", "1" );
this.addFormField( "ajax", "1" );
this.hashField = "phash";
this.quantityField = "howmany";
}
}
public static String pickForm( final String shopId )
{
if ( shopId.contains( "." ) )
{
return shopId;
}
return "shop.php";
}
public static String getShopId( final String urlString )
{
Matcher m = NPCPurchaseRequest.NPCSHOPID_PATTERN.matcher( urlString );
return m.find() ? m.group( 1 ) : null;
}
public String getStoreId()
{
return this.npcStoreId;
}
/**
* Retrieves the price of the item being purchased.
*
* @return The price of the item being purchased
*/
@Override
public int getPrice()
{
long factor = 100;
if ( this.shopName.equals( "Doc Galaktik's Medicine Show" ) && QuestDatabase.isQuestFinished( Quest.DOC ) )
{
// This is before the subtractions on purpose. It is possible that KoL
// will change and this will need to be moved down.
// The exact multiplier is 2/3 but with rounding this will give
// the desired result.
factor = 67;
}
if ( NPCPurchaseRequest.usingTrousers() ) factor -= 5;
if ( KoLCharacter.hasSkill( "Five Finger Discount" ) ) factor -= 5;
return (int) ( ( this.price * factor ) / 100 );
}
private static boolean usingTrousers()
{
return EquipmentManager.getEquipment( EquipmentManager.PANTS ).equals( NPCPurchaseRequest.TROUSERS );
}
@Override
public void run()
{
this.addFormField( this.quantityField, String.valueOf( this.limit ) );
super.run();
}
@Override
public boolean ensureProperAttire()
{
if ( this.npcStoreId.equals( "fdkol" ) )
{
// Travoltan trousers do not give a discount
return true;
}
int neededOutfit = OutfitPool.NONE;
if ( this.npcStoreId.equals( "bugbear" ) )
{
neededOutfit = OutfitPool.BUGBEAR_COSTUME;
}
else if ( this.npcStoreId.equals( "bartlebys" ) )
{
if ( !KoLCharacter.hasEquipped( NPCPurchaseRequest.FLEDGES ) )
{
neededOutfit = OutfitPool.SWASHBUCKLING_GETUP;
}
}
else if ( this.npcStoreId.equals( "hippy" ) )
{
if ( this.shopName.equals( "Hippy Store (Pre-War)" ) )
{
neededOutfit = OutfitPool.HIPPY_OUTFIT;
}
else if ( QuestLogRequest.isHippyStoreAvailable() )
{
neededOutfit = OutfitPool.NONE;
}
else if ( this.shopName.equals( "Hippy Store (Hippy)" ) )
{
neededOutfit = OutfitPool.WAR_HIPPY_OUTFIT;
}
else if ( this.shopName.equals( "Hippy Store (Fratboy)" ) )
{
neededOutfit = OutfitPool.WAR_FRAT_OUTFIT;
}
}
// Only switch outfits if the person is not currently wearing the outfit and if they
// have that outfit.
if ( neededOutfit != OutfitPool.NONE )
{
if ( EquipmentManager.isWearingOutfit( neededOutfit ) )
{
return true;
}
if ( !EquipmentManager.hasOutfit( neededOutfit ) )
{
return false;
}
}
// If you have a buff from Greatest American Pants and have it set to keep the buffs,
// disallow outfit changes.
if ( Preferences.getBoolean( "gapProtection" ) )
{
if ( KoLConstants.activeEffects.contains( NPCPurchaseRequest.SUPER_SKILL ) ||
KoLConstants.activeEffects.contains( NPCPurchaseRequest.SUPER_STRUCTURE ) ||
KoLConstants.activeEffects.contains( NPCPurchaseRequest.SUPER_VISION ) ||
KoLConstants.activeEffects.contains( NPCPurchaseRequest.SUPER_SPEED ) ||
KoLConstants.activeEffects.contains( NPCPurchaseRequest.SUPER_ACCURACY ) )
{
if ( neededOutfit != OutfitPool.NONE )
{
KoLmafia.updateDisplay(
MafiaState.ERROR,
"You have a Greatest American Pants buff and buying the necessary " + getItemName() + " would cause you to lose it." );
return false;
}
return true;
}
}
// If the recovery manager is running, do not change equipment as this has the potential
// for an infinite loop.
if ( RecoveryManager.isRecoveryActive() && !MoodManager.isExecuting() )
{
if ( neededOutfit != OutfitPool.NONE )
{
KoLmafia.updateDisplay(
MafiaState.ERROR,
"Aborting implicit outfit change due to potential infinite loop in auto-recovery. Please buy the necessary " + getItemName() + " manually." );
return false;
}
return true;
}
// If there's an outfit that you need to use, change into it.
if ( neededOutfit != OutfitPool.NONE )
{
( new EquipmentRequest( EquipmentDatabase.getOutfit( neededOutfit ) ) ).run();
return true;
}
// Otherwise, maybe you can put on some Travoltan Trousers to decrease the cost of the
// purchase, but only if auto-recovery isn't running.
if ( !NPCPurchaseRequest.usingTrousers() && KoLConstants.inventory.contains( NPCPurchaseRequest.TROUSERS ) )
{
( new EquipmentRequest( NPCPurchaseRequest.TROUSERS, EquipmentManager.PANTS ) ).run();
}
return true;
}
@Override
public void processResults()
{
String urlString = this.getURLString();
if ( urlString.startsWith( "shop.php" ) )
{
NPCPurchaseRequest.parseShopResponse( urlString, this.responseText );
}
int quantityAcquired = this.item.getCount( KoLConstants.inventory ) - this.initialCount;
if ( quantityAcquired > 0 )
{
// Normal NPC stores say "You spent xxx Meat" and we
// have already parsed that.
if ( !urlString.startsWith( "shop.php" ) )
{
ResultProcessor.processMeat( -1 * this.getPrice() * quantityAcquired );
KoLCharacter.updateStatus();
}
return;
}
}
public static final boolean registerRequest( final String urlString )
{
if ( !urlString.startsWith( "town_giftshop.php" ) )
{
return false;
}
Matcher itemMatcher = TransferItemRequest.ITEMID_PATTERN.matcher( urlString );
if ( !itemMatcher.find() )
{
return true;
}
Matcher quantityMatcher = TransferItemRequest.HOWMANY_PATTERN.matcher( urlString );
if ( !quantityMatcher.find() )
{
return true;
}
int itemId = StringUtilities.parseInt( itemMatcher.group( 1 ) );
String itemName = ItemDatabase.getItemName( itemId );
int quantity = StringUtilities.parseInt( quantityMatcher.group( 1 ) );
int priceVal = NPCStoreDatabase.price( itemId );
Matcher m = NPCPurchaseRequest.NPCSHOPID_PATTERN.matcher(urlString);
String shopId = m.find() ? NPCStoreDatabase.getStoreName( m.group(1) ) : null;
String shopName = shopId != null ? shopId : "an NPC Store";
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "buy " + quantity + " " + itemName + " for " + String.valueOf( priceVal ) + " each from " + shopName );
return true;
}
public static final void parseShopRowResponse( final String urlString, final String responseText )
{
Matcher rowMatcher = GenericRequest.WHICHROW_PATTERN.matcher( urlString );
if ( !rowMatcher.find() )
{
return;
}
int row = StringUtilities.parseInt( rowMatcher.group( 1 ) );
int itemId = ConcoctionPool.rowToId( row );
CreateItemRequest item = CreateItemRequest.getInstance( itemId, false );
if ( item == null )
{
return; // this is an unknown item
}
int quantity = 1;
if ( urlString.contains( "buymax=" ) )
{
quantity = item.getQuantityPossible();
}
else
{
Matcher quantityMatcher = GenericRequest.QUANTITY_PATTERN.matcher( urlString );
if ( quantityMatcher.find() )
{
String quantityString = quantityMatcher.group( 1 ).trim();
quantity = quantityString.length() == 0 ? 1 : StringUtilities.parseInt( quantityString );
}
}
AdventureResult[] ingredients = ConcoctionDatabase.getIngredients( itemId );
for ( int i = 0; i < ingredients.length; ++i )
{
ResultProcessor.processResult(
ingredients[ i ].getInstance( -1 * ingredients[ i ].getCount() * quantity ) );
}
}
private static final Pattern ITEM_PATTERN = Pattern.compile( "<tr rel=\\\"(\\d+).*?descitem.(\\d+)\\)'><b>(.*?)(?:<font.*)?</b>.*?title=\\\"(.*?)\\\">.*?<b>(.*?)</b>.*?whichrow=(\\d+)", Pattern.DOTALL );
private static final Pattern SHOP_NAME_PATTERN = Pattern.compile( "bgcolor=blue><b>(.*?)</b>" , Pattern.DOTALL );
private static final Pattern BLOOD_MAYO_PATTERN = Pattern.compile( "blood mayonnaise concentration: (\\d+) mayograms" );
public static final void parseShopResponse( final String urlString, final String responseText )
{
if ( !urlString.startsWith( "shop.php" ) )
{
return;
}
String shopId = NPCPurchaseRequest.getShopId( urlString );
if ( shopId == null )
{
return;
}
// Learn new items by simply visiting a store
Matcher matcher = ITEM_PATTERN.matcher( responseText );
while ( matcher.find() )
{
int id = StringUtilities.parseInt( matcher.group(1) );
String desc = matcher.group(2);
String name = matcher.group(3);
String data = ItemDatabase.getItemDataName( id );
if ( data == null || !data.equals( name ) )
{
// Unknown item in shop
String currency = matcher.group(4);
String cost = matcher.group(5).replaceAll( ",", "" );
String row = matcher.group(6);
String shopName = "";
Matcher nameMatcher = SHOP_NAME_PATTERN.matcher( responseText );
if ( nameMatcher.find() )
{
shopName = nameMatcher.group(1);
}
if ( currency.equals( "Meat" ) )
{
String printMe;
// Print what goes in npcstores.txt
printMe = "--------------------";
RequestLogger.printLine( printMe );
RequestLogger.updateSessionLog( printMe );
printMe = shopName + "\t" + shopId + "\t" + name + "\t" + cost + "\tROW" + row;
RequestLogger.printLine( printMe );
RequestLogger.updateSessionLog( printMe );
printMe = "--------------------";
RequestLogger.printLine( printMe );
RequestLogger.updateSessionLog( printMe );
}
else
{
String printMe;
// Print what goes in coinmasters.txt
printMe = "--------------------";
RequestLogger.printLine( printMe );
RequestLogger.updateSessionLog( printMe );
printMe = shopName + "\tbuy\t" + cost + "\t" + name + "\tROW" + row;
RequestLogger.printLine( printMe );
RequestLogger.updateSessionLog( printMe );
printMe = "--------------------";
RequestLogger.printLine( printMe );
RequestLogger.updateSessionLog( printMe );
}
ItemDatabase.registerItem( id, name, desc );
}
}
// Quest tracker update
if ( shopId.equals( "junkmagazine" ) )
{
if ( !QuestDatabase.isQuestLaterThan( Quest.HIPPY, "step1" ) )
{
QuestDatabase.setQuestProgress( Quest.HIPPY, "step2" );
}
}
// The following trade collections of ingredients for an item
if ( shopId.equals( "airport" ) ||
shopId.equals( "beergarden" ) ||
shopId.equals( "crimbo16" ) ||
shopId.equals( "grandma" ) ||
shopId.equals( "junkmagazine" ) ||
shopId.startsWith( "kolhs_" ) ||
shopId.equals( "mystic" ) ||
shopId.equals( "rumple" ) ||
shopId.equals( "snowgarden" ) ||
shopId.equals( "spant" ) ||
shopId.equals( "starchart" ) )
{
NPCPurchaseRequest.parseShopRowResponse( urlString, responseText );
return;
}
if ( shopId.equals( "sugarsheets" ) )
{
SugarSheetRequest.parseResponse( urlString, responseText );
return;
}
// The following does too, but is limited and needs extra parsing
if ( shopId.equals( "still" ) )
{
StillRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "5dprinter" ) )
{
FiveDPrinterRequest.parseResponse( urlString, responseText );
return;
}
// The following does too, but wants a special message
if ( shopId.equals( "jarl" ) )
{
JarlsbergRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "chateau" ) )
{
ChateauRequest.parseShopResponse( urlString, responseText );
return;
}
if ( shopId.equals( "mayoclinic" ) )
{
boolean refreshConcoctions = false;
AdventureResult currentWorkshed = CampgroundRequest.getCurrentWorkshedItem();
if ( currentWorkshed == null || currentWorkshed.getItemId() != ItemPool.MAYO_CLINIC )
{
refreshConcoctions = true;
}
CampgroundRequest.setCurrentWorkshedItem( ItemPool.MAYO_CLINIC );
if ( urlString.contains( "ajax=1" ) )
{
return;
}
Matcher mayoMatcher = BLOOD_MAYO_PATTERN.matcher( responseText );
if ( mayoMatcher.find() )
{
Preferences.setString( "mayoLevel", mayoMatcher.group( 1 ) );
}
if ( !urlString.contains( "buyitem" ) )
{
if ( responseText.contains( "miracle whip" ) )
{
Preferences.setBoolean( "_mayoDeviceRented", false );
Preferences.setBoolean( "itemBoughtPerAscension8266", false );
}
else if ( responseText.contains( "mayo lance" ) )
{
Preferences.setBoolean( "_mayoDeviceRented", false );
Preferences.setBoolean( "itemBoughtPerAscension8266", true );
}
else
{
Preferences.setBoolean( "_mayoDeviceRented", true );
Preferences.setBoolean( "itemBoughtPerAscension8266", true );
}
}
Preferences.setBoolean( "_mayoTankSoaked", !responseText.contains( "Soak in the Mayo Tank" ) );
if ( refreshConcoctions )
{
ConcoctionDatabase.refreshConcoctions();
}
return;
}
if ( shopId.equals( "hiddentavern" ) )
{
// If Hidden Tavern not already unlocked, new items available
if ( Preferences.getInteger( "hiddenTavernUnlock" ) != KoLCharacter.getAscensions() )
{
// Unlock Hidden Tavern
Preferences.setInteger( "hiddenTavernUnlock", KoLCharacter.getAscensions() );
ConcoctionDatabase.setRefreshNeeded( true );
}
return;
}
// The following are coinmasters
if ( shopId.equals( "arcade" ) )
{
TicketCounterRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "armory" ) )
{
ArmoryAndLeggeryRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "blackmarket" ) )
{
// If Black Market not already unlocked, unlock it
if ( !QuestLogRequest.isBlackMarketAvailable() )
{
QuestDatabase.setQuestProgress( Quest.MACGUFFIN, "step1" );
ConcoctionDatabase.setRefreshNeeded( true );
}
BlackMarketRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "damachine" ) )
{
VendingMachineRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "shore" ) )
{
ShoreGiftShopRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "dv" ) )
{
TerrifiedEagleInnRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "trapper" ) )
{
TrapperRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "cindy" ) )
{
BoutiqueRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "fdkol" ) )
{
FDKOLRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "elvishp1" ) ||
shopId.equals( "elvishp2" ) ||
shopId.equals( "elvishp3" ) )
{
SpaaaceRequest.parseResponse( urlString, responseText );
return;
}
// Spring Break Beach shops
if ( shopId.equals( "sbb_jimmy" ) )
{
BuffJimmyRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "sbb_taco" ) )
{
TacoDanRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "sbb_brogurt" ) )
{
BrogurtRequest.parseResponse( urlString, responseText );
return;
}
// Conspiracy Island shops
if ( shopId.equals( "si_shop1" ) )
{
SHAWARMARequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "si_shop2" ) )
{
CanteenRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "si_shop3" ) )
{
ArmoryRequest.parseResponse( urlString, responseText );
return;
}
// That 70s Volcano shops
if ( shopId.equals( "infernodisco" ) )
{
DiscoGiftCoRequest.parseResponse( urlString, responseText );
return;
}
// Dinsey Landfill shops
if ( shopId.equals( "landfillstore" ) )
{
DinseyCompanyStoreRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "toxic" ) )
{
ToxicChemistryRequest.parseResponse( urlString, responseText );
return;
}
// The Glaciest shops
if ( shopId.equals( "glaciest" ) )
{
WalMartRequest.parseResponse( urlString, responseText );
return;
}
// Twitch Shops
if ( shopId.equals( "caveshop" ) )
{
NeandermallRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "shoeshop" ) )
{
ShoeRepairRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "applestore" ) )
{
AppleStoreRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "nina" ) )
{
NinjaStoreRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "shakeshop" ) )
{
YeNeweSouvenirShoppeRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "conmerch" ) )
{
MerchTableRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "topiary" ) )
{
NuggletCraftingRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "fishbones" ) )
{
FishboneryRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.startsWith( "crimbo14" ) )
{
Crimbo14Request.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "edunder_shopshop" ) )
{
EdShopRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "batman_cave" ) )
{
BatFabricatorRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "batman_chemicorp" ) )
{
ChemiCorpRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "batman_orphanage" ) )
{
GotporkOrphanageRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "batman_pd" ) )
{
GotporkPDRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "ltt" ) )
{
LTTRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "bacon" ) )
{
MemeShopRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "detective" ) )
{
PrecinctRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "thankshop" ) )
{
ThankShopRequest.parseResponse( urlString, responseText );
return;
}
if ( shopId.equals( "spacegate" ) )
{
SpacegateFabricationRequest.parseResponse( urlString, responseText );
return;
}
// When we purchase items from NPC stores using ajax, the
// response tells us nothing about the contents of the store.
if ( urlString.contains( "ajax=1" ) )
{
return;
}
// These shops have variable offerings
if ( shopId.equals( "bartlebys" ) )
{
Matcher m = PIRATE_EPHEMERA_PATTERN.matcher( responseText );
if ( m.find() )
{
Preferences.setInteger( "lastPirateEphemeraReset", KoLCharacter.getAscensions() );
Preferences.setString( "lastPirateEphemera", m.group( 0 ) );
}
return;
}
if ( shopId.equals( "hippy" ) )
{
// Check to see if any of the items offered in the
// hippy store are special.
String side = "none";
if ( responseText.contains( "peach" ) &&
responseText.contains( "pear" ) &&
responseText.contains( "plum" ) )
{
Preferences.setInteger( "lastFilthClearance", KoLCharacter.getAscensions() );
side = "hippy";
}
else if ( responseText.contains( "bowl of rye sprouts" ) &&
responseText.contains( "cob of corn" ) &&
responseText.contains( "juniper berries" ) )
{
Preferences.setInteger( "lastFilthClearance", KoLCharacter.getAscensions() );
side = "fratboy";
}
Preferences.setString( "currentHippyStore", side );
Preferences.setString( "sidequestOrchardCompleted", side );
if ( responseText.contains( "Oh, hey, boss! Welcome back!" ) )
{
Preferences.setBoolean( "_hippyMeatCollected", true );
}
return;
}
}
public static final boolean registerShopRowRequest( final String urlString )
{
Matcher rowMatcher = GenericRequest.WHICHROW_PATTERN.matcher( urlString );
if ( !rowMatcher.find() )
{
return true;
}
int row = StringUtilities.parseInt( rowMatcher.group( 1 ) );
int itemId = ConcoctionPool.rowToId( row );
CreateItemRequest item = CreateItemRequest.getInstance( itemId, false );
if ( item == null )
{
return true; // this is an unknown item
}
int quantity = 1;
if ( urlString.contains( "buymax=" ) )
{
quantity = item.getQuantityPossible();
}
else
{
Matcher quantityMatcher = GenericRequest.QUANTITY_PATTERN.matcher( urlString );
if ( quantityMatcher.find() )
{
String quantityString = quantityMatcher.group( 1 ).trim();
quantity = quantityString.length() == 0 ? 1 : StringUtilities.parseInt( quantityString );
}
}
if ( quantity > item.getQuantityPossible() )
{
return true; // attempt will fail
}
StringBuilder buffer = new StringBuilder();
buffer.append( "Trade " );
AdventureResult[] ingredients = ConcoctionDatabase.getIngredients( itemId );
for ( int i = 0; i < ingredients.length; ++i )
{
if ( i > 0 )
{
buffer.append( ", " );
}
buffer.append( ingredients[ i ].getCount() * quantity );
buffer.append( " " );
buffer.append( ingredients[ i ].getName() );
}
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( buffer.toString() );
return true;
}
public static final boolean registerShopRequest( final String urlString, boolean meatOnly )
{
if ( !urlString.startsWith( "shop.php" ) )
{
return false;
}
String shopId = NPCPurchaseRequest.getShopId( urlString );
if ( shopId == null )
{
return false;
}
String shopName = NPCStoreDatabase.getStoreName( shopId );
int itemId = -1;
Matcher m = TransferItemRequest.ITEMID_PATTERN.matcher( urlString );
if ( m.find() )
{
itemId = StringUtilities.parseInt( m.group( 1 ) );
}
else
{
m = GenericRequest.WHICHROW_PATTERN.matcher( urlString );
if ( m.find() )
{
int row = StringUtilities.parseInt( m.group( 1 ) );
itemId = NPCStoreDatabase.itemIdByRow( shopId, row );
}
}
if ( itemId == -1 )
{
// Just visiting the shop
return true;
}
String itemName = ItemDatabase.getItemName( itemId );
int priceVal = NPCStoreDatabase.price( itemId );
// A "shop" can have items for Meat and also for tokens.
// If there is no Meat price, let correct class claim it.
if ( priceVal == 0 )
{
// If we've already checked tokens, this is an unknown item
if ( meatOnly )
{
return false;
}
// The following trade collections of ingredients for an item
if ( shopId.equals( "5dprinter" ) ||
shopId.equals( "airport" ) ||
shopId.equals( "beergarden" ) ||
shopId.equals( "crimbo16" ) ||
shopId.equals( "grandma" ) ||
shopId.equals( "junkmagazine" ) ||
shopId.startsWith( "kolhs_" ) ||
shopId.equals( "mystic" ) ||
shopId.equals( "rumple" ) ||
shopId.equals( "snowgarden" ) ||
shopId.equals( "spant" ) )
{
return NPCPurchaseRequest.registerShopRowRequest( urlString );
}
// The following does too, but always makes a single item
if ( shopId.equals( "starchart" ) )
{
return StarChartRequest.registerRequest( urlString );
}
if ( shopId.equals( "sugarsheets" ) )
{
return SugarSheetRequest.registerRequest( urlString );
}
// The following does too, but may be limited
if ( shopId.equals( "still" ) )
{
return StillRequest.registerRequest( urlString );
}
// The following does too, but wants a special message
if ( shopId.equals( "jarl" ) )
{
return JarlsbergRequest.registerRequest( urlString );
}
// The following are coinmasters
if ( shopId.equals( "armory" ) )
{
return ArmoryAndLeggeryRequest.registerRequest( urlString, true );
}
if ( shopId.equals( "blackmarket" ) )
{
return BlackMarketRequest.registerRequest( urlString, true );
}
if ( shopId.equals( "damachine" ) )
{
return VendingMachineRequest.registerRequest( urlString );
}
if ( shopId.equals( "shore" ) )
{
return ShoreGiftShopRequest.registerRequest( urlString );
}
if ( shopId.equals( "dv" ) )
{
return TerrifiedEagleInnRequest.registerRequest( urlString );
}
if ( shopId.equals( "trapper" ) )
{
return TrapperRequest.registerRequest( urlString );
}
if ( shopId.equals( "cindy" ) )
{
return BoutiqueRequest.registerRequest( urlString );
}
if ( shopId.equals( "fdkol" ) )
{
return FDKOLRequest.registerRequest( urlString, true );
}
// Spring Break Beach shops
if ( shopId.equals( "sbb_jimmy" ) )
{
return BuffJimmyRequest.registerRequest( urlString );
}
if ( shopId.equals( "sbb_taco" ) )
{
return TacoDanRequest.registerRequest( urlString );
}
if ( shopId.equals( "sbb_brogurt" ) )
{
return BrogurtRequest.registerRequest( urlString );
}
// Conspiracy Island shops
if ( shopId.equals( "si_shop1" ) )
{
return SHAWARMARequest.registerRequest( urlString );
}
if ( shopId.equals( "si_shop2" ) )
{
return CanteenRequest.registerRequest( urlString );
}
if ( shopId.equals( "si_shop2" ) )
{
return ArmoryRequest.registerRequest( urlString );
}
// That 70s Volcano shops
if ( shopId.equals( "infernodisco" ) )
{
return DiscoGiftCoRequest.registerRequest( urlString );
}
// Dinsey Landfill shops
if ( shopId.equals( "landfillstore" ) )
{
return DinseyCompanyStoreRequest.registerRequest( urlString );
}
if ( shopId.equals( "toxic" ) )
{
return ToxicChemistryRequest.registerRequest( urlString );
}
// The Glaciest shops
if ( shopId.equals( "glaciest" ) )
{
return WalMartRequest.registerRequest( urlString );
}
// Twitch Shops
if ( shopId.equals( "caveshop" ) )
{
return NeandermallRequest.registerRequest( urlString );
}
if ( shopId.equals( "shoeshop" ) )
{
return ShoeRepairRequest.registerRequest( urlString );
}
if ( shopId.equals( "applestore" ) )
{
return AppleStoreRequest.registerRequest( urlString );
}
if ( shopId.equals( "nina" ) )
{
return NinjaStoreRequest.registerRequest( urlString );
}
if ( shopId.equals( "shakeshop" ) )
{
return YeNeweSouvenirShoppeRequest.registerRequest( urlString );
}
if ( shopId.equals( "conmerch" ) )
{
return MerchTableRequest.registerRequest( urlString );
}
if ( shopId.equals( "arcade" ) )
{
return TicketCounterRequest.registerRequest( urlString );
}
if ( shopId.equals( "fishbones" ) )
{
return FishboneryRequest.registerRequest( urlString );
}
if ( shopId.equals( "topiary" ) )
{
return NuggletCraftingRequest.registerRequest( urlString );
}
if ( shopId.startsWith( "crimbo14" ) )
{
return Crimbo14Request.registerRequest( urlString );
}
if ( shopId.equals( "edunder_shopshop" ) )
{
return EdShopRequest.registerRequest( urlString );
}
if ( shopId.equals( "batman_cave" ) )
{
return BatFabricatorRequest.registerRequest( urlString );
}
if ( shopId.equals( "batman_chemicorp" ) )
{
return ChemiCorpRequest.registerRequest( urlString );
}
if ( shopId.equals( "batman_orphanage" ) )
{
return GotporkOrphanageRequest.registerRequest( urlString );
}
if ( shopId.equals( "batman_pd" ) )
{
return GotporkPDRequest.registerRequest( urlString );
}
if ( shopId.equals( "ltt" ) )
{
return LTTRequest.registerRequest( urlString );
}
if ( shopId.equals( "bacon" ) )
{
return MemeShopRequest.registerRequest( urlString );
}
if ( shopId.equals( "detective" ) )
{
return PrecinctRequest.registerRequest( urlString );
}
if ( shopId.equals( "thankshop" ) )
{
return ThankShopRequest.registerRequest( urlString );
}
if ( shopId.equals( "spacegate" ) )
{
return SpacegateFabricationRequest.registerRequest( urlString );
}
return false;
}
Matcher quantityMatcher = TransferItemRequest.QUANTITY_PATTERN.matcher( urlString );
if ( !quantityMatcher.find() )
{
return true;
}
int quantity = StringUtilities.parseInt( quantityMatcher.group( 1 ) );
RequestLogger.updateSessionLog();
RequestLogger.updateSessionLog( "buy " + quantity + " " + itemName + " for " + String.valueOf( priceVal ) + " each from " + shopName );
return true;
}
}