/**
* 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.session;
import java.util.ArrayList;
import net.sourceforge.kolmafia.KoLAdventure;
import net.sourceforge.kolmafia.KoLCharacter;
import net.sourceforge.kolmafia.KoLConstants.MafiaState;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.RequestThread;
import net.sourceforge.kolmafia.objectpool.IntegerPool;
import net.sourceforge.kolmafia.persistence.AdventureDatabase;
import net.sourceforge.kolmafia.persistence.QuestDatabase;
import net.sourceforge.kolmafia.persistence.QuestDatabase.Quest;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.request.FightRequest;
import net.sourceforge.kolmafia.request.GenericRequest;
import net.sourceforge.kolmafia.request.TavernRequest;
import net.sourceforge.kolmafia.textui.command.CouncilCommand;
public class TavernManager
{
/**
* Completes the infamous tavern quest.
*/
// 1<--2<--3<--4<--5
// v
// 6 7-->8 9->10
// v ^ v ^ v
// 11 12 13 14 15
// v v ^ v
// 16 17 18->19 20
// v ^ \
// 21->22 23->24->25
private static Integer [] searchOrder = {
// IntegerPool.get( 5 ),
IntegerPool.get( 4 ), IntegerPool.get( 3 ), IntegerPool.get( 2 ),
IntegerPool.get( 1 ), IntegerPool.get( 6 ), IntegerPool.get( 11 ),
IntegerPool.get( 16 ), IntegerPool.get( 21 ), IntegerPool.get( 22 ),
IntegerPool.get( 17 ), IntegerPool.get( 23 ), IntegerPool.get( 24 ),
IntegerPool.get( 25 ), IntegerPool.get( 12 ), IntegerPool.get( 7 ),
IntegerPool.get( 8 ), IntegerPool.get( 13 ), IntegerPool.get( 18 ),
IntegerPool.get( 19 ), IntegerPool.get( 14 ), IntegerPool.get( 9 ),
IntegerPool.get( 10 ), IntegerPool.get( 15 ), IntegerPool.get( 20 ),
};
private static final int EXPLORE = 1;
private static final int FAUCET = 2;
private static final int BARON = 3;
private static final int FIGHT_BARON = 4;
private static int overrideSquare = -1;
public static int exploreTavern()
{
return TavernManager.exploreTavern( TavernManager.EXPLORE );
}
public static int locateTavernFaucet()
{
return TavernManager.exploreTavern( TavernManager.FAUCET );
}
public static int locateBaron()
{
return TavernManager.exploreTavern( TavernManager.BARON );
}
public static int fightBaron()
{
return TavernManager.exploreTavern( TavernManager.FIGHT_BARON );
}
public static String faucetSquare()
{
String layout = TavernRequest.tavernLayout();
int faucet = layout.indexOf( "3" );
return faucet == -1 ? "" : String.valueOf( faucet + 1 );
}
public static String baronSquare()
{
String layout = TavernRequest.tavernLayout();
int baron = layout.indexOf( "4" );
return baron == -1 ? "" : String.valueOf( baron + 1 );
}
private static int exploreTavern( final int goal )
{
if ( KoLCharacter.getLevel() < 3 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "You need to level up first." );
return -1;
}
// See if we've already found our goal within KoLmafia
String layout = TavernRequest.tavernLayout();
int faucet = layout.indexOf( "3" );
if ( goal == TavernManager.FAUCET && faucet != -1 )
{
TavernManager.logFaucetSquare( faucet );
return faucet + 1;
}
int baron = layout.indexOf( "4" );
if ( goal == TavernManager.BARON && baron != -1 )
{
TavernManager.logBaronSquare( baron );
return baron + 1;
}
int mansion = layout.indexOf( "6" );
if ( ( goal == TavernManager.BARON || goal == TavernManager.FIGHT_BARON ) && mansion != -1 )
{
TavernManager.logMansionSquare( mansion );
KoLmafia.updateDisplay( "You already defeated Baron von Ratsworth." );
return mansion + 1;
}
int unexplored = layout.indexOf( "0" );
if ( goal == TavernManager.EXPLORE && unexplored == -1 )
{
TavernManager.logFaucetSquare( faucet );
TavernManager.logBaronSquare( baron );
TavernManager.logMansionSquare( mansion );
KoLmafia.updateDisplay( "Entire cellar explored" );
return 0;
}
// No. Go look for it.
String message =
goal == TavernManager.FAUCET ?
"Searching for faucet..." :
goal == TavernManager.BARON ?
"Searching for Baron von Ratsworth..." :
goal == TavernManager.FIGHT_BARON ?
"Going after Baron von Ratsworth..." :
"Exploring rest of cellar...";
KoLmafia.updateDisplay( message );
// Make sure we have the quest from the council
RequestThread.postRequest( CouncilCommand.COUNCIL_VISIT );
// Make sure Bart Ender has given us access to the cellar
GenericRequest barkeep = new GenericRequest( "tavern.php?place=barkeep" );
RequestThread.postRequest( barkeep );
// *** Should look at response and make sure we got there
// Visit the tavern cellar to update the layout
RequestThread.postRequest( new GenericRequest( "cellar.php" ) );
// Refetch the current layout
layout = TavernRequest.tavernLayout();
// See if we've already found the goal outside KoLmafia
faucet = layout.indexOf( "3" );
if ( goal == TavernManager.FAUCET && faucet != -1 )
{
TavernManager.logFaucetSquare( faucet );
return faucet + 1;
}
baron = layout.indexOf( "4" );
if ( goal == TavernManager.BARON && baron != -1 )
{
TavernManager.logBaronSquare( baron );
return baron + 1;
}
mansion = layout.indexOf( "6" );
if ( ( goal == TavernManager.BARON || goal == TavernManager.FIGHT_BARON ) && mansion != -1 )
{
TavernManager.logMansionSquare( mansion );
KoLmafia.updateDisplay( "You already defeated Baron von Ratsworth." );
return mansion + 1;
}
unexplored = layout.indexOf( "0" );
if ( goal == TavernManager.EXPLORE && unexplored == -1 )
{
TavernManager.logFaucetSquare( faucet );
TavernManager.logBaronSquare( baron );
TavernManager.logMansionSquare( mansion );
KoLmafia.updateDisplay( "Entire cellar explored" );
return 0;
}
// If the goal has not yet been found, then explore
KoLAdventure adventure = AdventureDatabase.getAdventure( "The Typical Tavern Cellar" );
// Remember if we have already found the faucet
boolean hadFaucet = faucet != -1;
// Reset Baron's choice to automatically skip him the first time we find him
int oldBaronSetting = Preferences.getInteger( "choiceAdventure511" );
if ( oldBaronSetting != 2 )
{
Preferences.setInteger( "choiceAdventure511", 2 );
}
// Set preferences to automatically adjust the faucet
Preferences.setInteger( "choiceAdventure509", 1 );
Preferences.setInteger( "choiceAdventure1000", 1 );
while ( ( goal == TavernManager.FAUCET && faucet == -1 ||
goal == TavernManager.BARON && baron == -1 ||
goal == TavernManager.FIGHT_BARON && baron == -1 ||
goal == TavernManager.EXPLORE && unexplored != -1 ) &&
KoLmafia.permitsContinue() &&
KoLCharacter.getCurrentHP() > 0 &&
KoLCharacter.getAdventuresLeft() > 0 )
{
// Tell TavernRequest to visit the next unexplored square
TavernManager.overrideSquare = TavernManager.nextUnexploredSquare() - 1;
RequestThread.postRequest( adventure );
while ( FightRequest.inMultiFight && KoLmafia.permitsContinue() )
{
FightRequest.INSTANCE.run();
}
TavernManager.overrideSquare = -1;
// See what we discovered
layout = TavernRequest.tavernLayout();
faucet = layout.indexOf( "3" );
baron = layout.indexOf( "4" );
unexplored = layout.indexOf( "0" );
// If we just found the faucet for the first time, visit Bart Ender to claim reward
if ( !hadFaucet && faucet != -1 )
{
RequestThread.postRequest( barkeep );
hadFaucet = true;
}
}
// Restore Baron choice option setting.
if ( oldBaronSetting != 2 )
{
Preferences.setInteger( "choiceAdventure511", oldBaronSetting );
}
if ( goal == TavernManager.FAUCET )
{
if ( faucet == -1 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Unable to find faucet." );
return -1;
}
// Notify the user that the faucet has been found.
TavernManager.logFaucetSquare( faucet );
return faucet + 1;
}
if ( goal == TavernManager.BARON )
{
if ( baron == -1 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Unable to find baron." );
return -1;
}
// Notify the user that the baron has been found.
TavernManager.logBaronSquare( baron );
return baron + 1;
}
if ( goal == TavernManager.FIGHT_BARON )
{
if ( baron == -1 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Unable to find baron." );
return -1;
}
// Go fight Baron von Ratsworth
if ( oldBaronSetting != 1 )
{
Preferences.setInteger( "choiceAdventure511", 1 );
}
TavernManager.logBaronSquare( baron );
TavernManager.overrideSquare = baron;
RequestThread.postRequest( adventure );
TavernManager.overrideSquare = -1;
if ( oldBaronSetting != 1 )
{
Preferences.setInteger( "choiceAdventure511", oldBaronSetting );
}
layout = TavernRequest.tavernLayout();
mansion = layout.indexOf( "6" );
KoLmafia.updateDisplay( "Baron " + ( mansion == -1 ? "fought" : "defeated" ) + "." );
return baron + 1;
}
// Otherwise, we are exploring the rest of the tavern
if ( goal == TavernManager.EXPLORE )
{
if ( unexplored != -1 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Unable to finish exploring cellar." );
return -1;
}
// Notify the user that we are done
TavernManager.logFaucetSquare( faucet );
TavernManager.logBaronSquare( baron );
KoLmafia.updateDisplay( "Done exploring." );
return 0;
}
// What were we doing?
return -1;
}
private static void logFaucetSquare( final int faucet )
{
if ( faucet != -1 )
{
int faucetRow = faucet / 5 + 1;
int faucetColumn = faucet % 5 + 1;
KoLmafia.updateDisplay( "Faucet found in row " + faucetRow + ", column " + faucetColumn );
}
}
private static void logBaronSquare( final int baron )
{
if ( baron != -1 )
{
int baronRow = baron / 5 + 1;
int baronColumn = baron % 5 + 1;
KoLmafia.updateDisplay( "Baron found in row " + baronRow + ", column " + baronColumn );
}
}
private static void logMansionSquare( final int mansion )
{
if ( mansion != -1 )
{
int mansionRow = mansion / 5 + 1;
int mansionColumn = mansion % 5 + 1;
KoLmafia.updateDisplay( "Baron's empty mansion found in row " + mansionRow + ", column " + mansionColumn );
}
}
private static ArrayList<Integer> getSearchList( final String layout )
{
ArrayList<Integer> searchList = new ArrayList<Integer>();
for ( int i = 0; i < TavernManager.searchOrder.length; ++i )
{
searchList.add( TavernManager.searchOrder[ i ] );
}
for ( int i = layout.length() - 1; i >= 0; --i )
{
if ( layout.charAt( i ) == '0' )
{
continue;
}
// Remove explored square from searchlist
int index = searchList.indexOf( IntegerPool.get( i + 1 ) );
if ( index != -1 )
{
searchList.remove( index );
}
}
return searchList;
}
public static boolean shouldAutoFaucet()
{
if ( TavernManager.overrideSquare >= 0 )
{
return false;
}
// If we know where the faucet is, go there.
return TavernRequest.tavernLayout().indexOf( "3" ) >= 0;
}
public static int recommendSquare()
{
if ( TavernManager.overrideSquare >= 0 )
{
return TavernManager.overrideSquare + 1;
}
if ( KoLCharacter.getLevel() < 3 )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "You need to level up first." );
return 0;
}
// See if we know the faucet square
String layout = TavernRequest.tavernLayout();
int faucet = layout.indexOf( "3" );
if ( faucet >= 0 )
{
return faucet + 1;
}
// Otherwise, return the next unexplored square
return TavernManager.nextUnexploredSquare();
}
public static int nextUnexploredSquare()
{
// Get the tavern layout
String layout = TavernRequest.tavernLayout();
// See if any squares are unexplored
if ( layout.indexOf( "0" ) == -1 )
{
return 0;
}
// Some squares remain to be visited. Get a list of them in order.
ArrayList<Integer> searchList = TavernManager.getSearchList( layout );
if ( searchList.size() == 0 )
{
// Should never happen
return 0;
}
// Take the first square off of the list
Integer searchIndex = searchList.remove( 0 );
// That's the square we will visit.
return searchIndex.intValue();
}
public static void handleTavernChange( String responseText )
{
if ( responseText.contains( "have a few drinks on the house" ) ||
responseText.contains( "something that wasn't booze" ) ||
responseText.contains( "a round on the house" ) )
{
QuestDatabase.setQuestProgress( Quest.RAT, QuestDatabase.FINISHED );
}
}
}