/** * 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.KoLCharacter; import net.sourceforge.kolmafia.RequestLogger; import net.sourceforge.kolmafia.objectpool.ItemPool; import net.sourceforge.kolmafia.persistence.ConcoctionDatabase; import net.sourceforge.kolmafia.persistence.QuestDatabase; import net.sourceforge.kolmafia.persistence.QuestDatabase.Quest; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.session.ResultProcessor; import net.sourceforge.kolmafia.utilities.StringUtilities; public class TavernRequest extends GenericRequest { private static final Pattern GOOFBALL_PATTERN = Pattern.compile( "Buy some goofballs \\((\\d+),000 Meat\\)" ); // tavern.php?place=barkeep // store.php?whichstore=v&buying=Yep.&phash&whichitem=xxx&howmany=y // tavern.php?place=susguy // action=buygoofballs // tavern.php?place=pooltable // action=pool&opponent=1&wager=50 // action=pool&opponent=2&wager=200 // action=pool&opponent=3&wager=500 // cellar.php // action=explore&whichspot=4 public TavernRequest( final int itemId ) { super( "tavern.php" ); switch (itemId ) { case ItemPool.GOOFBALLS: this.addFormField( "action", "buygoofballs" ); break; case ItemPool.OILY_GOLDEN_MUSHROOM: this.addFormField( "sleazy", "1" ); break; default: this.addFormField( "place", "susguy" ); break; } } @Override public void processResults() { TavernRequest.parseResponse( this.getURLString(), this.responseText ); } public static final void parseResponse( final String location, final String responseText ) { if ( !location.startsWith( "tavern.php" ) ) { return; } if ( location.contains( "place=barkeep" ) ) { if ( responseText.contains( "have a few drinks on the house" ) || responseText.contains( "something that wasn't booze" ) || responseText.contains( "a round on the house" ) || responseText.contains( "grab some mugs and pour yourself some tavern swill" ) ) { QuestDatabase.setQuestProgress( Quest.RAT, QuestDatabase.FINISHED ); } else { QuestDatabase.setQuestIfBetter( Quest.RAT, "step1" ); ConcoctionDatabase.setRefreshNeeded( false ); } } if ( location.contains( "place=susguy" ) ) { if ( !responseText.contains( "Take some goofballs (for free!)") ) { Preferences.setInteger( "lastGoofballBuy", KoLCharacter.getAscensions() ); } } if ( location.contains( "action=buygoofballs" ) ) { // Here you go, man. If you get caught, you didn't get // these from me, man. Preferences.setInteger( "lastGoofballBuy", KoLCharacter.getAscensions() ); if ( !responseText.contains( "If you get caught" ) ) { return; } Matcher matcher = GOOFBALL_PATTERN.matcher( responseText ); if ( !matcher.find() ) { return; } int cost = 1000 * Integer.parseInt( matcher.group( 1 ) ) - 1000; if ( cost > 0 ) { ResultProcessor.processMeat( -cost ); } return; } if ( location.contains( "sleazy=1" ) ) { // The suspicious-looking guy takes your gloomy black // mushroom and smiles that unsettling little smile // that makes you nervous. "Sweet, man. Here ya go." if ( responseText.contains ("takes your gloomy black mushroom" ) ) { ResultProcessor.processItem( ItemPool.GLOOMY_BLACK_MUSHROOM, -1 ); } return; } } private static final Pattern MAP_PATTERN = Pattern.compile( "alt=\"([^\"]*) \\(([\\d]*),([\\d]*)\\)\"" ); private static final void parseCellarMap( final String text ) { String oldLayout = TavernRequest.tavernLayout(); StringBuilder layout = new StringBuilder( oldLayout ); Matcher matcher = TavernRequest.MAP_PATTERN.matcher( text ); while ( matcher.find() ) { int col = StringUtilities.parseInt( matcher.group(2) ); int row = StringUtilities.parseInt( matcher.group(3) ); int square = ( row - 1 ) * 5 + ( col - 1 ); if ( square < 0 || square >= 25 ) { continue; } char code = layout.charAt( square ); String type = matcher.group(1); if ( type.startsWith( "Darkness" ) ) { code = '0'; } else if ( type.startsWith( "Explored" ) ) { if ( code == '1' || code == '2' || code == '5' ) { continue; } code = '1'; } else if ( type.startsWith( "A Rat Faucet" ) ) { code = '3'; } else if ( type.startsWith( "A Tiny Mansion" ) ) { code = text.contains( "mansion2.gif" ) ? '6' : '4'; } else if ( type.startsWith( "Stairs Up" ) ) { code = '1'; } else { continue; } layout.setCharAt( square, code ); } String newLayout = layout.toString(); if ( !oldLayout.equals( newLayout ) ) { Preferences.setString( "tavernLayout", newLayout ); } } private static final Pattern SPOT_PATTERN = Pattern.compile( "whichspot=([\\d,]+)" ); private static final int getSquare( final String urlString ) { // cellar.php?action=explore&whichspot=4 if ( !urlString.startsWith( "cellar.php" ) || !urlString.contains( "action=explore") ) { return 0; } Matcher matcher = TavernRequest.SPOT_PATTERN.matcher( urlString ); if ( !matcher.find() ) { return 0; } return StringUtilities.parseInt( matcher.group( 1 ) ); } public static final String cellarLocationString( final String urlString ) { int square = TavernRequest.getSquare( urlString ); if ( square == 0 ) { if ( !urlString.contains( "action=autofaucet" ) ) { return "The Typical Tavern Cellar"; } String layout = TavernRequest.tavernLayout(); int faucet = layout.indexOf( "3" ); if ( faucet == -1 ) { return "The Typical Tavern Cellar (Faucet)"; } square = faucet + 1; } int row = ( ( square - 1 ) / 5 ) + 1; int col = ( ( square - 1 ) % 5 ) + 1; return "The Typical Tavern Cellar (row " + row + ", col " + col + ")"; } public static final void validateFaucetQuest() { int lastAscension = Preferences.getInteger( "lastTavernAscension" ); if ( lastAscension < KoLCharacter.getAscensions() ) { Preferences.setInteger( "lastTavernSquare", 0 ); Preferences.setInteger( "lastTavernAscension", KoLCharacter.getAscensions() ); Preferences.setString( "tavernLayout", "0000000000000000000000000" ); } } public static final String tavernLayout() { TavernRequest.validateFaucetQuest(); String layout = Preferences.getString( "tavernLayout" ); if ( layout.length() != 25 ) { layout = "0000000000000000000000000"; Preferences.setString( "tavernLayout", layout ); } return layout; } public static final void preTavernVisit( final GenericRequest request ) { TavernRequest.validateFaucetQuest(); String urlString = request.getURLString(); int square = TavernRequest.getSquare( urlString ); if ( square == 0 ) { return; } Preferences.setInteger( "lastTavernSquare", square ); } public static final void postTavernVisit( final GenericRequest request ) { String urlString = request.getURLString(); String responseText = request.responseText; if ( urlString.equals( "cellar.php" ) ) { TavernRequest.parseCellarMap( responseText ); return; } if ( KoLCharacter.getAdventuresLeft() == 0 || KoLCharacter.getCurrentHP() == 0 || KoLCharacter.getInebriety() > KoLCharacter.getInebrietyLimit() ) { return; } if ( urlString.startsWith( "fight.php" ) ) { int square = Preferences.getInteger( "lastTavernSquare" ); char replacement = responseText.contains( "Baron" ) ? '4' : '1'; TavernRequest.addTavernLocation( square, replacement ); return; } int square = urlString.startsWith( "choice.php" ) ? Preferences.getInteger( "lastTavernSquare" ) : TavernRequest.getSquare( urlString ); if ( square == 0 ) { return; } char replacement = '1'; if ( responseText.contains( "Those Who Came Before You" ) ) { // Dead adventurer replacement = '2'; } else if ( responseText.contains( "Of Course!" ) || responseText.contains( "Hot and Cold Running Rats" ) || responseText.contains( "Everything in Moderation" ) || responseText.contains( "Hot and Cold Dripping Rats" ) ) { // Rat faucet, before and after turning off replacement = '3'; QuestDatabase.setQuestIfBetter( Quest.RAT, "step2" ); } else if ( responseText.contains( "is it Still a Mansion" ) ) { // Baron von Ratsworth replacement = '4'; } // The little mansion is silent and empty, you having slain the // man... er... the rat of the house. else if ( responseText.contains( "little mansion is silent and empty" ) ) { // Defeated Baron von Ratsworth replacement = '6'; } else if ( responseText.contains( "whichchoice" ) ) { // Various Barrels replacement = '5'; } TavernRequest.addTavernLocation( square, replacement ); Preferences.setInteger( "lastTavernSquare", square ); } public static final void addTavernLocation( final char value ) { int square = Preferences.getInteger( "lastTavernSquare" ); TavernRequest.addTavernLocation( square, value ); } private static final void addTavernLocation( final int square, final char value ) { StringBuilder layout = new StringBuilder( TavernRequest.tavernLayout() ); layout.setCharAt( square - 1, value ); Preferences.setString( "tavernLayout", layout.toString() ); } public static final boolean registerRequest( final String urlString ) { if ( !urlString.startsWith( "tavern.php" ) ) { return false; } String message; if ( urlString.contains( "action=buygoofballs" ) ) { message = "Buying goofballs from the suspicious looking guy"; } else if ( urlString.contains( "sleazy=1" ) ) { message = "Trading a gloomy black mushroom for an oily golden mushroom"; } else if ( urlString.contains( "sleazy=2" ) ) { // Keeping your gloomy black mushroom return true; } else if ( urlString.contains( "place=susguy" ) ) { RequestLogger.printLine( "" ); RequestLogger.updateSessionLog(); message = "Visiting the suspicious looking guy"; } else if ( urlString.contains( "place=barkeep" ) ) { RequestLogger.printLine( "" ); RequestLogger.updateSessionLog(); message = "Visiting Bart Ender"; } else { return false; } RequestLogger.printLine( message ); RequestLogger.updateSessionLog( message ); return true; } }