/**
* 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.regex.Matcher;
import java.util.regex.Pattern;
import net.sourceforge.kolmafia.KoLConstants;
import net.sourceforge.kolmafia.RequestLogger;
import net.sourceforge.kolmafia.objectpool.ItemPool;
import net.sourceforge.kolmafia.preferences.Preferences;
import net.sourceforge.kolmafia.utilities.StringUtilities;
public class DreadScrollManager
{
public enum ClueType
{
LIBRARY1,
HEALSCROLL,
DEEP_DARK_VISIONS,
KNUCKLEBONE,
KILLSCROLL,
LIBRARY2,
WORKTEA,
LIBRARY3
}
// You can't make heads or tails of the contents of the book, but
// somebody has scrawled "<clue>" on the inside of the front cover in
// what appears to be blood. Spooky.
private static final Pattern LIBRARY1_PATTERN = Pattern.compile( "somebody has scrawled "<b>(.*?)</b>"" );
// You flip through the book, finding almost nothing of actual
// interest. You do notice, however, that there seem to be a lot of
// references to <clue> creatures. Curious.
private static final Pattern LIBRARY2_PATTERN = Pattern.compile( "a lot of references to <b>(.*?)</b> creatures." );
// You flip through the book, and find very little in the way of useful
// information. There is one curious chapter, though, which just
// consists of the phrase <clue> over and over, hundreds of
// times. Creepy.
private static final Pattern LIBRARY3_PATTERN = Pattern.compile( "consists of the phrase <b>(.*?)</b> over and over" );
public static final void handleLibrary( String responseText )
{
Matcher matcher = LIBRARY1_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.LIBRARY1, matcher.group( 1 ) );
return;
}
matcher = LIBRARY2_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.LIBRARY2, matcher.group( 1 ) );
return;
}
matcher = LIBRARY3_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.LIBRARY3, matcher.group( 1 ) );
return;
}
}
// You sound out the strange text on the scroll. As you finish, you're
// bathed in a hideous green glow. Horrific images begin to dance in
// your mind -- three-lidded eyes in the darkness, tentacles squirming
// along the ocean floor, a magnificent <clue>, smiling warmly in the
// distance, publicity stills from Battlefield Earth... Your mind reels
// at the horror, but your body feels strangely replenished...
private static final Pattern HEALSCROLL_PATTERN = Pattern.compile( "a magnificent <b>(.*?)</b>" );
public static final void handleHealscroll( String responseText )
{
Matcher matcher = HEALSCROLL_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.HEALSCROLL, matcher.group( 1 ) );
}
}
// Something about the words on that scroll sticks in your mind. You
// actually did recognize one of them: '<clue>'. Strange.
private static final Pattern KILLSCROLL_PATTERN = Pattern.compile( "recognize one of them: <b>"(.*?)"</b>" );
public static final void handleKillscroll( String responseText )
{
Matcher matcher = KILLSCROLL_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.KILLSCROLL, matcher.group( 1 ) );
}
}
// You roll the bone, over and over, and every time it hits the ground,
// it bounces straight <direction>. You get so weirded out by it that
// you throw it away.
private static final Pattern KNUCKLEBONE_PATTERN = Pattern.compile( "it bounces straight <b>(.*?)</b>." );
public static final void handleKnucklebone( String responseText )
{
Matcher matcher = KNUCKLEBONE_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.KNUCKLEBONE, matcher.group( 1 ) );
}
}
// <b><clue></b>
private static final Pattern DEEP_DARK_VISIONS_PATTERN = Pattern.compile( "You close your eyes and let Deep visions wash over you.*?<b>(.*?)</b>.*itemimages/hp.gif" );
public static final void handleDeepDarkVisions( String responseText )
{
Matcher matcher = DEEP_DARK_VISIONS_PATTERN.matcher( responseText );
if ( matcher.find() )
{
DreadScrollManager.setClue( ClueType.DEEP_DARK_VISIONS, matcher.group( 1 ) );
}
}
// You manage to inadvertently drink a cup of that gross Mer-kin tea
// while you're eating the sushi. And hey, look -- the leaves in the
// bottom look just like <b>an eel</b>!
private static final Pattern WORKTEA_PATTERN = Pattern.compile( "the leaves in the bottom look just like <b>([^<]*)</b>" );
public static final void handleWorktea( String responseText )
{
Matcher matcher = DreadScrollManager.WORKTEA_PATTERN.matcher( responseText );
if ( !matcher.find() )
{
return;
}
String clue = matcher.group(1);
DreadScrollManager.setClue( ClueType.WORKTEA, clue );
Preferences.setString( "workteaClue", clue );
ResultProcessor.processItem( ItemPool.MERKIN_WORKTEA, -1 );
}
public static final String[][][] CLUE_DATA =
{
{
{ "Mer-kin Library 1", "dreadScroll1" },
{ "LONELY", "lonely" },
{ "DOUBLED", "doubled" },
{ "THRICE-CURSED", "thrice-cursed" },
{ "FOURTH", "fourth" },
},
{
{ "Mer-kin healscroll", "dreadScroll2" },
{ "starfish" },
{ "moonfish" },
{ "sunfish" },
{ "planetfish" },
},
{
{ "Deep Dark Visions", "dreadScroll3" },
{ "The House of Cards", "Cards" },
{ "The House of Blues", "Blues" },
{ "The House of Pancakes", "Pancakes" },
{ "The House of Pain", "Pain" },
},
{
{ "Mer-kin knucklebone", "dreadScroll4" },
{ "north", "Northern" },
{ "south", "Southern" },
{ "east", "Eastern" },
{ "west", "Western" },
},
{
{ "Mer-kin killscroll", "dreadScroll5" },
{ "red", "as red as blood" },
{ "black", "as black as ink" },
{ "green", "as green as bile" },
{ "yellow", "as yellow as piss" },
},
{
{ "Mer-kin Library 2", "dreadScroll6" },
{ "blind" },
{ "giant" },
{ "finless" },
{ "two-headed" },
},
{
{ "Mer-kin worktea", "dreadScroll7" },
{ "an eel", "eel" },
{ "a turtle", "turtle" },
{ "a shark", "shark" },
{ "a whale", "whale" },
},
{
{ "Mer-kin Library 3", "dreadScroll8" },
{ "one thousand squirming young" },
{ "two and twenty stillborn spawn" },
{ "conjoined triplets" },
{ "a brand new dance craze" },
},
};
private static final void setClue( ClueType clue, String value )
{
int index = clue.ordinal();
String [][] data = CLUE_DATA[ index ];
String setting = data[0][1];
for ( int i = 1; i <= 4; ++i )
{
if ( value.equals( data[i][0] ) )
{
Preferences.setInteger( setting, i );
break;
}
}
String message = data[0][0] + " clue: " + value;
RequestLogger.printLine( message );
RequestLogger.updateSessionLog( message );
}
private static final String cluePhrase( ClueType clue )
{
int index = clue.ordinal();
String [][] data = CLUE_DATA[ index ];
String setting = data[0][1];
int value = Preferences.getInteger( setting );
if ( value < 1 || value > 4 )
{
return "???";
}
String [] option= data[value];
return option.length > 1 ? option[1] : option[0];
}
private static final void clueStatus( StringBuilder buffer, ClueType clue )
{
int index = clue.ordinal();
String [][] data = CLUE_DATA[ index ];
String setting = data[0][1];
int value = Preferences.getInteger( setting );
buffer.append( setting );
buffer.append( " (" );
buffer.append( data[0][0] );
buffer.append( "): " );
buffer.append( String.valueOf( value ) );
buffer.append( " (" );
buffer.append( value == 0 ? "unknown" : data[value][0] );
buffer.append( ")" );
buffer.append( KoLConstants.LINE_BREAK );
}
public static final String getClues()
{
StringBuilder buffer = new StringBuilder();
clueStatus( buffer, ClueType.LIBRARY1 );
clueStatus( buffer, ClueType.HEALSCROLL );
clueStatus( buffer, ClueType.DEEP_DARK_VISIONS );
clueStatus( buffer, ClueType.KNUCKLEBONE );
clueStatus( buffer, ClueType.KILLSCROLL );
clueStatus( buffer, ClueType.LIBRARY2 );
clueStatus( buffer, ClueType.WORKTEA );
clueStatus( buffer, ClueType.LIBRARY3 );
return buffer.toString();
}
// When the <thrice-cursed> <moonfish> is in the <House of Cards>,
// and the <Northern> Current runs as <red as blood>,
// when a <blind> <shark> births <two and twenty stillborn spawn>,
// the Elder shall awaken.
public static final String getScrollText()
{
StringBuilder buffer = new StringBuilder();
buffer.append( "When the " );
buffer.append( cluePhrase( ClueType.LIBRARY1 ) );
buffer.append( " " );
buffer.append( cluePhrase( ClueType.HEALSCROLL ) );
buffer.append( " is in the House of " );
buffer.append( cluePhrase( ClueType.DEEP_DARK_VISIONS ) );
buffer.append( "," );
buffer.append( KoLConstants.LINE_BREAK );
buffer.append( "and the " );
buffer.append( cluePhrase( ClueType.KNUCKLEBONE ) );
buffer.append( " Current runs " );
buffer.append( cluePhrase( ClueType.KILLSCROLL ) );
buffer.append( "," );
buffer.append( KoLConstants.LINE_BREAK );
buffer.append( "when a " );
buffer.append( cluePhrase( ClueType.LIBRARY2 ) );
buffer.append( " " );
buffer.append( cluePhrase( ClueType.WORKTEA ) );
buffer.append( " births " );
buffer.append( cluePhrase( ClueType.LIBRARY3 ) );
buffer.append( "," );
buffer.append( KoLConstants.LINE_BREAK );
buffer.append( "the Elder shall awaken. " );
return buffer.toString();
}
public static final void decorate( final StringBuffer buffer )
{
StringUtilities.globalStringDelete( buffer, " selected" );
for ( int pro = 1; pro <= 8; ++pro )
{
String[][] data = CLUE_DATA[ pro - 1];
String setting = data[0][1];
int value = Preferences.getInteger( setting );
if ( value == 0 )
{
continue;
}
String [] option = data[value];
String key = option.length > 1 ? option[1] : option[0];
String find = ">" + key;
String replace = " selected>-->" + key + "<--";
StringUtilities.globalStringReplace( buffer, find, replace );
}
}
}