/**
* 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.textui.command;
import net.sourceforge.kolmafia.AdventureResult;
import net.sourceforge.kolmafia.KoLCharacter;
import net.sourceforge.kolmafia.KoLConstants.MafiaState;
import net.sourceforge.kolmafia.KoLmafia;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.RequestThread;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.request.UseItemRequest;
import net.sourceforge.kolmafia.session.InventoryManager;
public class GongCommand
extends AbstractCommand
{
public GongCommand()
{
this.usage = " [buy | set] manual | bird | mole | roach [<effect> [<stat> [<stat>]]]";
}
// These are all the possible paths that start with The Gong Has Been Bung.
public static final String[] GONG_PATHS =
{
"show in browser",
"bird",
"mole",
"roach (in browser)",
"musc, musc, +30% musc",
"musc, mox, +30% musc",
"musc, MP, +30% musc",
"myst, musc, +30% myst",
"myst, myst, +30% myst",
"myst, MP, +30% myst",
"mox, myst, +30% mox",
"mox, mox, +30% mox",
"mox, MP, +30% mox",
"musc, musc, +10% all",
"myst, musc, +10% all",
"musc, mox, +10% all",
"myst, myst, +10% all",
"mox, mox, +10% all",
"mox, MP, +10% all",
"musc, musc, +50% items",
"myst, musc, +50% items",
"musc, MP, +50% items",
"mox, myst, +50% items",
"myst, MP, +50% items",
"mox, MP, +50% items",
"musc, mox, +30 ML",
"musc, MP, +30 ML",
"myst, myst, +30 ML",
"mox, myst, +30 ML",
"myst, MP, +30 ML",
"mox, mox, +30 ML",
};
// These are the choice adventure settings corresponding to GONG_PATHS.
// Encoding: 2 bits per choice adv, starting with #276 in the low bits,
// continuing thru #290 for a total of 30 bits used.
private static final int[] GONG_CHOICES =
{
0x00000004,
0x00000007,
0x00000006,
0x00000005,
0x00004095,
0x00001055,
0x000100d5,
0x00300225,
0x00040125,
0x00800325,
0x08000835,
0x02000435,
0x10000c35,
0x00008095,
0x00200225,
0x00002055,
0x000c0125,
0x03000435,
0x20000c35,
0x0000c095,
0x00100225,
0x000200d5,
0x0c000835,
0x00c00325,
0x30000c35,
0x00003055,
0x000300d5,
0x00080125,
0x04000835,
0x00400325,
0x01000435
};
// These are the precalculated roach paths for achieving the closest possible
// approximation to any desired effect & stat boosts.
// Index: primary desired stat (musc=0, myst, mox, MP)
// + 4 * secondary desired stat (musc=0, myst, mox, MP)
// + 16 * mainstat (musc=0, myst, mox) as a tiebreaker
// Values: six 5-bit fields, containing indexes into the arrays above for each
// possible effect (+mus%=low bits, +mys%, +mox%, +all%, +item, +ML)
private static final int[] GONG_SEARCH =
{
0x3336a8e4,
0x374728e4,
0x3367ace5,
0x35593126,
0x334728e4,
0x37482904,
0x3967a8e5,
0x3b793126,
0x3337ace5,
0x396728e5,
0x3d68ace5,
0x35893126,
0x3556b0e6,
0x3b772926,
0x33893125,
0x35593126,
0x3336a8e4,
0x374728e4,
0x3367a8e5,
0x35593126,
0x334728e4,
0x37482904,
0x3968a905,
0x3b793126,
0x3347a8e5,
0x39682905,
0x3d68ad05,
0x3b893126,
0x355730e6,
0x3b782926,
0x39893125,
0x3b793126,
0x3336ace4,
0x394728e5,
0x3367ace5,
0x35593126,
0x334728e5,
0x37682905,
0x3968a905,
0x3b793126,
0x3337ace5,
0x39682905,
0x3d68ace5,
0x35893126,
0x3557b0e6,
0x3b782926,
0x3d893125,
0x35893126
};
@Override
public void run( final String command, final String parameters )
{
String[] parameterList = parameters.split( "\\s+" );
int pos = 0;
int len = parameterList.length;
boolean buy = false;
boolean set = false;
if ( pos < len && parameterList[ pos ].equalsIgnoreCase( "buy" ) )
{
buy = true;
++pos;
}
else if ( pos < len && parameterList[ pos ].equalsIgnoreCase( "set" ) )
{
set = true;
++pos;
}
if ( pos >= len || parameterList[ pos ].equals( "" ) )
{
RequestLogger.printLine( "Usage: gong" + this.usage );
RequestLogger.printLine( "buy - use a gong even if you have to buy one." );
RequestLogger.printLine( "set - don't use a gong, just set choices." );
RequestLogger.printLine( "manual - show choices in browser." );
RequestLogger.printLine( "bird | mole | roach - path to take." );
RequestLogger.printLine( "'roach' can be followed by 1, 2, or 3 of:" );
RequestLogger.printLine( "mus | mys | mox | all | item | ML - effect to get (20 turns)." );
RequestLogger.printLine( "(You can also use the first word of the effect name.)" );
RequestLogger.printLine( "mus | mys | mox | MP - stat to boost." );
RequestLogger.printLine( "mus | mys | mox | MP - another stat to boost." );
RequestLogger.printLine( "(If a stat is not specified, or is impossible due to other choices, your mainstat will be boosted if possible." );
return;
}
int path = GongCommand.parse( parameterList, pos++ , "manual bird mole roach" );
if ( path == 3 && pos < len )
{
int effect =
GongCommand.parse( parameterList, pos++ , "mus ack mys alc mox rad all new item ext ml unp" ) / 2;
int primary, secondary, main;
primary = secondary = main = KoLCharacter.getPrimeIndex();
if ( pos < len )
{
primary = GongCommand.parse( parameterList, pos++ , "mus mys mox mp" );
}
if ( pos < len )
{
secondary = GongCommand.parse( parameterList, pos++ , "mus mys mox mp" );
}
path = GongCommand.GONG_SEARCH[ primary + 4 * secondary + 16 * main ];
path = path >> 5 * effect & 0x1F;
}
if ( !KoLmafia.permitsContinue() )
{
return;
}
if ( pos < len )
{
KoLmafia.updateDisplay(
MafiaState.ERROR, "Unexpected text after command, starting with: " + parameterList[ pos ] );
return;
}
KoLmafia.updateDisplay( "Gong path: " + GongCommand.GONG_PATHS[ path ] );
GongCommand.setPath( path );
if ( set )
{
return;
}
AdventureResult gong = ItemPool.get( ItemPool.GONG, 1 );
if ( buy && !InventoryManager.hasItem( gong ) )
{
BuyCommand.buy( "1 llama lama gong" );
}
RequestThread.postRequest( UseItemRequest.getInstance( gong ) );
}
private static int parse( final String[] parameters, final int pos, final String optionString )
{
if ( pos >= parameters.length )
{
KoLmafia.updateDisplay( MafiaState.ERROR, "Expected one of: " + optionString );
return 0;
}
String[] options = optionString.split( " " );
String param = parameters[ pos ].toLowerCase();
for ( int i = 0; i < options.length; ++i )
{
if ( param.startsWith( options[ i ] ) )
{
return i;
}
}
KoLmafia.updateDisplay( MafiaState.ERROR, "Found '" + param + "', but expected one of: " + optionString );
return 0;
}
public static void setPath( int path )
{
if ( path < 0 || path > GongCommand.GONG_PATHS.length )
{
return;
}
Preferences.setInteger( "gongPath", path );
path = GongCommand.GONG_CHOICES[ path ];
for ( int i = 276; i <= 290; ++i )
{
Preferences.setString( "choiceAdventure" + i, String.valueOf( path & 0x03 ) );
path >>= 2;
}
}
}