/** * 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.CoinmasterData; import net.sourceforge.kolmafia.KoLAdventure; 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.objectpool.ItemPool; import net.sourceforge.kolmafia.persistence.AdventureDatabase; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.session.IslandManager; import net.sourceforge.kolmafia.session.IslandManager.Quest; import net.sourceforge.kolmafia.session.ResultProcessor; import net.sourceforge.kolmafia.utilities.StringUtilities; public class IslandRequest extends GenericRequest { private static final Pattern OPTION_PATTERN = Pattern.compile( "option=(\\d+)" ); public static final AdventureResult GUNPOWDER = ItemPool.get( ItemPool.GUNPOWDER, 1 ); public static final String[][] HIPPY_CONCERTS = { { "Moon'd", "+5 Stat(s) Per Fight" }, { "Dilated Pupils", "Item Drop +20%" }, { "Optimist Primal", "Familiar Weight +5" }, }; public static final String[][] FRATBOY_CONCERTS = { { "Elvish", "All Attributes +10%" }, { "Winklered", "Meat Drop +40%" }, { "White-boy Angst", "Initiative +50%" }, }; private static int effectToConcertNumber( final String completer, final String effect ) { String [][] array = completer.equals( "hippies" ) ? HIPPY_CONCERTS : completer.equals( "fratboys" ) ? FRATBOY_CONCERTS : null; if ( array == null ) { return 0; } String compare = effect.toLowerCase(); for ( int i = 0; i < array.length; ++i ) { if ( array[i][0].toLowerCase().startsWith( compare ) ) { return i + 1; } } return 0; } private Quest quest; public IslandRequest() { super( IslandManager.currentIsland() ); this.quest = Quest.NONE; } public static IslandRequest getConcertRequest( final int option ) { IslandRequest request = new IslandRequest(); if ( request.getPath().equals( "bogus.php" ) ) { return null; } if ( option < 0 || option > 3 ) { return null; } request.quest = Quest.ARENA; request.addFormField( "action", "concert" ); request.addFormField( "option", String.valueOf( option ) ); return request; } public static IslandRequest getConcertRequest( final String effect ) { String completer = IslandManager.questCompleter( "sidequestArenaCompleted" ); int option = IslandRequest.effectToConcertNumber( completer, effect ); return ( option == 0 ) ? null : IslandRequest.getConcertRequest( option ); } public static String concertError( final String arg ) { if ( IslandManager.warProgress().equals( "unstarted" ) ) { return "You have not started the island war yet."; } String completer = IslandManager.questCompleter( "sidequestArenaCompleted" ); if ( completer.equals( "none" ) ) { return "The arena is not open."; } String loser = Preferences.getString( "sideDefeated" ); if ( loser.equals( completer ) || loser.equals( "both" ) ) { return "The arena's fans were defeated in the war."; } if ( Character.isDigit( arg.charAt( 0 ) ) ) { // Raw concert number int option = StringUtilities.parseInt( arg ); if ( option < 0 || option > 3 ) { return "Invalid concert number."; } } else { // Effect name int option = IslandRequest.effectToConcertNumber( completer, arg ); if ( option == 0 ) { return "The \"" + arg + "\" effect is not available to " + completer; } } return ""; } public static IslandRequest getPyroRequest() { IslandRequest request = new IslandRequest(); if ( request.getPath().equals( "bogus.php" ) ) { return null; } request.quest = Quest.LIGHTHOUSE; request.addFormField( "place", "lighthouse" ); request.addFormField( "action", "pyro" ); return request; } public static final String getPyroURL() { return IslandManager.currentIsland() + "?place=lighthouse&action=pyro"; } public static IslandRequest getFarmerRequest() { IslandRequest request = new IslandRequest(); if ( request.getPath().equals( "bogus.php" ) ) { return null; } request.quest = Quest.FARM; request.addFormField( "place", "farm" ); request.addFormField( "action", "farmer" ); return request; } public static IslandRequest getNunneryRequest() { IslandRequest request = new IslandRequest(); if ( request.getPath().equals( "bogus.php" ) ) { return null; } request.quest = Quest.NUNS; request.addFormField( "place", "nunnery" ); request.addFormField( "action", "nuns" ); return request; } @Override protected boolean retryOnTimeout() { return true; } @Override public void run() { switch ( this.quest ) { case ARENA: KoLmafia.updateDisplay( "Visiting the Mysterious Island Arena..." ); break; case LIGHTHOUSE: KoLmafia.updateDisplay( "Visiting the Lighthouse Keeper..." ); break; case FARM: KoLmafia.updateDisplay( "Visiting the Farmer..." ); break; } super.run(); } @Override public void processResults() { if ( this.responseText == null || this.responseText.equals( "" ) ) { KoLmafia.updateDisplay( MafiaState.ERROR, "You can't find the Mysterious Island." ); return; } IslandRequest.parseResponse( this.getURLString(), this.responseText ); switch ( this.quest ) { case ARENA: // Unfortunately, you think you've pretty much tapped out this // event's entertainment potential for today // // You're all rocked out. if ( this.responseText.contains( "pretty much tapped out" ) || this.responseText.contains( "You're all rocked out" ) ) { KoLmafia.updateDisplay( "You can only visit the Mysterious Island Arena once a day." ); return; } // The stage at the Mysterious Island Arena is empty if ( this.responseText.contains( "The stage at the Mysterious Island Arena is empty" ) ) { KoLmafia.updateDisplay( "Nobody is performing." ); return; } if ( !this.responseText.contains( "You acquire an effect" ) ) { KoLmafia.updateDisplay( "You couldn't get to the Mysterious Island Arena." ); return; } KoLmafia.updateDisplay( "A music lover is you." ); break; case LIGHTHOUSE: KoLmafia.updateDisplay( "Done visiting the Lighthouse Keeper." ); break; case FARM: KoLmafia.updateDisplay( "Done visiting the Farmer." ); break; } } public static final void parseResponse( final String location, final String responseText ) { // Let the Island Manager deduce things about the state of the // island based on the responseText IslandManager.parseIsland( location, responseText ); // Do things that depend on actual actions String action = GenericRequest.getAction( location ); if ( action == null ) { return; } if ( action.equals( "concert" ) ) { if ( responseText.contains( "You acquire an effect" ) || responseText.contains( "pretty much tapped out" ) || responseText.contains( "You're all rocked out" ) ) { Preferences.setBoolean( "concertVisited", true ); } return; } if ( action.equals( "pyro" ) ) { // "The Lighthouse Keeper's eyes light up as he sees your // gunpowder.<p>"Big boom! Big big boom! Give me those, // <i>bumpty-bump</i>, and I'll make you the big // boom!"<p>He takes the gunpowder into a back room, and // returns with an armload of big bombs." if ( responseText.contains( "eyes light up" ) ) { int count = IslandRequest.GUNPOWDER.getCount( KoLConstants.inventory ); ResultProcessor.processItem( ItemPool.GUNPOWDER, -count ); } return; } } private static final Pattern CAMP_PATTERN = Pattern.compile( "whichcamp=(\\d+)" ); public static CoinmasterData findCampMaster( final String urlString ) { Matcher campMatcher = IslandRequest.CAMP_PATTERN.matcher( urlString ); if ( !campMatcher.find() ) { return null; } String camp = campMatcher.group(1); if ( camp.equals( "1" ) ) { return DimemasterRequest.HIPPY; } if ( camp.equals( "2" ) ) { return QuartersmasterRequest.FRATBOY; } return null; } static public CoinmasterData lastCampVisited = null; public static final boolean registerRequest( final String urlString ) { if ( !urlString.startsWith( "bigisland.php" ) && !urlString.startsWith( "postwarisland.php" ) ) { return false; } String action = GenericRequest.getAction( urlString ); if ( urlString.startsWith( "bigisland.php" ) ) { // You can only visit the two camps during the war CoinmasterData data = IslandRequest.findCampMaster( urlString ); if ( data != null ) { IslandRequest.lastCampVisited = data; return CoinMasterRequest.registerRequest( data, urlString ); } if ( action != null && action.equals( "bossfight" ) ) { // You can only get here by visiting a specific // camp first. We saved that above. KoLAdventure location = null; String headquarters = null; if ( IslandRequest.lastCampVisited == DimemasterRequest.HIPPY ) { headquarters = "Hippy Camp"; location = AdventureDatabase.getAdventure( "The Battlefield (Frat Uniform)" ); } else if ( IslandRequest.lastCampVisited == QuartersmasterRequest.FRATBOY ) { headquarters = "Frat House"; location = AdventureDatabase.getAdventure( "The Battlefield (Hippy Uniform)" ); } else { // This shouldn't happen; you can't get to the // boss fight without visiting a camp first. headquarters = "Headquarters"; location = AdventureDatabase.getAdventure( "The Battlefield (Hippy Uniform)" );; } // Remember that this counts as a battlefield fight, // even if the player just went somewhere else. KoLAdventure.lastVisitedLocation = location; RequestLogger.registerLocation( headquarters ); return true; } } String message = null; boolean gcli = false; if ( action == null ) { String place = GenericRequest.getPlace( urlString ); // place=concert // place=junkyard // place=orchard // place=farm // place=nunnery // place=lighthouse // Most of these are containers and simply visiting the // place does nothing; you can either adventure in a // location or visit an NPC with action=xxx // Visiting the arena before you have started the quest // grants you advertising flyers if ( place.equals( "concert" ) ) { message = "Visiting the Mysterious Island Arena"; RequestLogger.updateSessionLog(); RequestLogger.updateSessionLog( message ); } return true; } if ( action.equals( "concert" ) ) { Matcher matcher = OPTION_PATTERN.matcher( urlString ); if ( !matcher.find() ) { return true; } message = "concert " + matcher.group( 1 ); } else if ( action.equals( "junkman" ) ) { message = "Visiting Yossarian"; } else if ( action.equals( "stand" ) ) { message = "Visiting The Organic Produce Stand"; gcli = true; // Part of Breakfast } else if ( action.equals( "farmer" ) ) { message = "Visiting Farmer McMillicancuddy"; gcli = true; // Part of Breakfast } else if ( action.equals( "nuns" ) ) { message = "Visiting Our Lady of Perpetual Indecision "; } else if ( action.equals( "pyro" ) ) { int count = IslandRequest.GUNPOWDER.getCount( KoLConstants.inventory ); message = "Visiting the lighthouse keeper with " + count + " barrel" + ( count == 1 ? "" : "s" ) + " of gunpowder."; gcli = true; // Part of Breakfast } if ( message == null ) { // Log URL of unknown actions return false; } if ( gcli ) { RequestLogger.printLine( message ); } RequestLogger.updateSessionLog(); RequestLogger.updateSessionLog( message ); return true; } }