/** * 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.KoLmafia; import net.sourceforge.kolmafia.RequestLogger; import net.sourceforge.kolmafia.persistence.ItemDatabase; import net.sourceforge.kolmafia.persistence.SkillDatabase; import net.sourceforge.kolmafia.preferences.Preferences; import net.sourceforge.kolmafia.utilities.StringUtilities; public class AfterLifeRequest extends GenericRequest { private static final Pattern ITEM_PATTERN = Pattern.compile( "<span onclick='descitem\\(([\\d]+)\\)'>([^<]*)<.*?name=whichitem value=([\\d]+)>", Pattern.DOTALL ); private static final Pattern KARMA_PATTERN = Pattern.compile( "You gain ([0123456789,]+) Karma", Pattern.DOTALL ); private AfterLifeRequest() { super( "afterlife.php" ); } @Override public void processResults() { AfterLifeRequest.parseResponse( this.getURLString(), this.responseText ); } public static boolean parseResponse( final String urlString, final String responseText ) { if ( !urlString.startsWith( "afterlife.php" ) ) { return false; } // If this is our first visit to the afterlife - we are outside // the pearly gates - refresh the charpane if ( urlString.equals( "afterlife.php" ) ) { return true; } // Learn new astral items simply by visiting an astral vendor // afterlife.php?place=permery // afterlife.php?place=deli // afterlife.php?place=armory // afterlife.php?place=reincarnate Matcher matcher = ITEM_PATTERN.matcher( responseText ); while ( matcher.find() ) { String descId = matcher.group(1); String itemName = matcher.group(2); int itemId = StringUtilities.parseInt( matcher.group(3) ); String data = ItemDatabase.getItemDataName( itemId ); if ( data == null || !data.equals( itemName ) ) { ItemDatabase.registerItem( itemId, itemName, descId ); } } String action = GenericRequest.getAction( urlString ); // No need to refresh if simply visiting a vendor if ( action == null ) { return false; } if ( action.equals( "pearlygates" ) ) { int karma = Preferences.getInteger( "bankedKarma" ); RequestLogger.updateSessionLog( "You have " + karma + " banked Karma." ); // <td valign=center>You gain 311 Karma</td> matcher = KARMA_PATTERN.matcher( responseText ); while ( matcher.find() ) { int delta = StringUtilities.parseInt( matcher.group( 1 ) ); RequestLogger.updateSessionLog( "You gain " + delta + " Karma" ); karma += delta; } RequestLogger.updateSessionLog( "Your new Karma balance is " + karma ); Preferences.setInteger( "bankedKarma", karma ); return true; } int delta = 0; if ( action.equals( "scperm" ) ) { // afterlife.php?action=scperm&whichskill=6027 // <td valign=center>You spend 100 Karma</td> if ( responseText.contains( "don't have enough Karma for that" ) ) { RequestLogger.updateSessionLog( "You don't have enough Karma to perm that skill" ); } else { delta = -100; } } else if ( action.equals( "hcperm" ) ) { // afterlife.php?action=hcperm&whichskill=6027 // <td valign=center>You spend 200 Karma</td> if ( responseText.contains( "don't have enough Karma for that" ) ) { RequestLogger.updateSessionLog( "You don't have enough Karma to perm that skill" ); } else { delta = -200; } } else if ( action.equals( "returnskill" ) ) { // afterlife.php?action=returnskill&classid=6&skillid=27&hc=1 // <td>Skill permanence returned.</td> delta = urlString.indexOf( "hc=1" ) == -1 ? 100 : 200; } else if ( action.equals( "buydeli" ) ) { // afterlife.php?action=buydeli&whichitem=5045 // <td valign=center>You spend 1 Karma</td> delta = -1; } else if ( action.equals( "delireturn" ) ) { // afterlife.php?action=delireturn&whichitem=5045 // <td valign=center>You gain 1 Karma</td> delta = 1; } else if ( action.equals( "buyarmory" ) ) { // afterlife.php?action=buyarmory&whichitem=5041 // <td valign=center>You spend 10 Karma</td> delta = -10; } else if ( action.equals( "armoryreturn" ) ) { // afterlife.php?action=armoryreturn&whichitem=5041 // <td valign=center>You gain 10 Karma</td> delta = 10; } if ( delta != 0 ) { Preferences.increment( "bankedKarma", delta ); String message = ( delta < 0 ) ? ( "You spend " + (-delta) + " Karma" ) : ( "You gain " + delta + " Karma" ); RequestLogger.updateSessionLog( message ); } return true; } public static final Pattern SKILL_PATTERN = Pattern.compile( "whichskill=([^&]*)" ); public static final Pattern CLASSID_PATTERN = Pattern.compile( "classid=([^&]*)" ); public static final Pattern SKILLID_PATTERN = Pattern.compile( "skillid=([^&]*)" ); public static final Pattern HC_PATTERN = Pattern.compile( "hc=([^&]*)" ); public static final Pattern SIGN_PATTERN = Pattern.compile( "whichsign=([^&]*)" ); public static final Pattern GENDER_PATTERN = Pattern.compile( "gender=([^&]*)" ); public static final Pattern CLASS_PATTERN = Pattern.compile( "whichclass=([^&]*)" ); public static final Pattern PATH_PATTERN = Pattern.compile( "whichpath=([^&]*)" ); public static final Pattern TYPE_PATTERN = Pattern.compile( "asctype=([^&]*)" ); public static boolean registerRequest( final String urlString ) { if ( !urlString.startsWith( "afterlife.php" ) ) { return false; } String action = GenericRequest.getAction( urlString ); // Visiting the Permery // afterlife.php?place=permery // Visiting the Deli // afterlife.php?place=deli // Visiting the Armory // afterlife.php?place=armory // Visiting the Bureau of Reincarnation // afterlife.php?place=reincarnate // No need to refresh if simply visiting a vendor if ( action == null ) { return true; } String message = null; int karma = Preferences.getInteger( "bankedKarma" ); // Walking through the Pearly Gates // afterlife.php?action=pearlygates if ( action.equals( "pearlygates" ) ) { message = "Welcome to Valhalla!"; } // Perming a skill // afterlife.php?action=scperm&whichskill=6027 // afterlife.php?action=hcperm&whichskill=6027 else if ( action.equals( "scperm" ) || action.equals( "hcperm" ) ) { Matcher m = SKILL_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int skillId = StringUtilities.parseInt( m.group( 1 ) ); boolean hc = action.startsWith( "hc" ); String skill = SkillDatabase.getSkillName( skillId ); String type = hc ? "Hard" : "Soft"; String cost = hc ? "200" : "100"; String name = ( skill != null ) ? skill : ( "Skill #" + skillId ); message = type + "core perm " + name + " for " + cost + " Karma (initial balance = " + karma + ")"; } // Returning a skill // afterlife.php?action=returnskill&classid=6&skillid=27&hc=1 else if ( action.equals( "returnskill" ) ) { Matcher m = CLASSID_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int classId = StringUtilities.parseInt( m.group( 1 ) ); m = SKILLID_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int skillId = StringUtilities.parseInt( m.group( 1 ) ); m = HC_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } boolean hc = m.group( 1 ).equals( "1" ); int id = ( classId * 1000 ) + skillId; String skill = SkillDatabase.getSkillName( id ); String type = hc ? "Hard" : "Soft"; String cost = hc ? "200" : "100"; String name = ( skill != null ) ? skill : ( "Skill #" + id ); message = "Return " + type + "core Skill " + name + " for " + cost + " Karma (initial balance = " + karma + ")"; } // Buying from the Deli // afterlife.php?action=buydeli&whichitem=5045 // Buying an item // afterlife.php?action=buyarmory&whichitem=5041 else if ( action.equals( "buydeli" ) || action.equals( "buyarmory" ) ) { Matcher m = GenericRequest.WHICHITEM_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int itemId = StringUtilities.parseInt( m.group( 1 ) ); String itemName = ItemDatabase.getItemName( itemId ); String cost = action.equals( "buydeli" ) ? "1" : "10"; message = "Buy " + itemName + " for " + cost + " Karma (initial balance = " + karma + ")"; } // Returning an item to the Deli // afterlife.php?action=delireturn&whichitem=5045 // Returning an item // afterlife.php?action=armoryreturn&whichitem=5041 else if ( action.equals( "delireturn" ) || action.equals( "armoryreturn" ) ) { Matcher m = GenericRequest.WHICHITEM_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int itemId = StringUtilities.parseInt( m.group( 1 ) ); String itemName = ItemDatabase.getItemName( itemId ); String cost = action.startsWith( "deli" ) ? "1" : "10"; message = "Return " + itemName + " for " + cost + " Karma (initial balance = " + karma + ")"; } // Ascending // afterlife.php?action=ascend&asctype=3&whichclass=4&gender=2&whichpath=4&whichsign=2 // Confirming Ascension // afterlife.php?action=ascend&confirmascend=1&whichsign=2&gender=2&whichclass=4&whichpath=4&asctype=3 else if ( action.equals( "ascend" ) ) { if ( urlString.indexOf( "confirmascend=1" ) == -1 ) { return true; } Matcher m = TYPE_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int type = StringUtilities.parseInt( m.group( 1 ) ); StringBuilder builder = new StringBuilder(); builder.append( "Ascend as a " ); switch ( type ) { case 1: builder.append( "Casual" ); break; case 2: builder.append( "Normal" ); break; case 3: builder.append( "Hardcore" ); break; default: builder.append( "(Type " ); builder.append( String.valueOf( type ) ); builder.append( ")" ); break; } m = GENDER_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int gender = StringUtilities.parseInt( m.group( 1 ) ); builder.append( " " ); switch ( gender ) { case 1: builder.append( "Male" ); break; case 2: builder.append( "Female" ); break; default: builder.append( "(Gender " ); builder.append( String.valueOf( gender ) ); builder.append( ")" ); break; } m = CLASS_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int pclass = StringUtilities.parseInt( m.group( 1 ) ); builder.append( " " ); switch ( pclass ) { case 1: builder.append( "Seal Clubber" ); break; case 2: builder.append( "Turtle Tamer" ); break; case 3: builder.append( "Pastamancer" ); break; case 4: builder.append( "Sauceror" ); break; case 5: builder.append( "Disco Bandit" ); break; case 6: builder.append( "Accordion Thief" ); break; case 11: builder.append( "Avatar of Boris" ); break; case 12: builder.append( "Zombie Master" ); break; case 14: builder.append( "Avatar of Jarlsberg" ); break; case 15: builder.append( "Avatar of Sneaky Pete" ); break; case 17: builder.append( "Ed" ); break; case 18: builder.append( "Cow Puncher" ); break; case 19: builder.append( "Beanslinger" ); break; case 20: builder.append( "Snake Oiler" ); break; case 23: builder.append( "Gelatinous Noob" ); break; default: builder.append( "(Class " ); builder.append( String.valueOf( pclass ) ); builder.append( ")" ); break; } m = SIGN_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } builder.append( " under the " ); int sign = StringUtilities.parseInt( m.group( 1 ) ); if ( sign >= 1 && sign <= KoLCharacter.ZODIACS.length ) { builder.append( KoLCharacter.ZODIACS[ sign - 1 ] ); } else if ( sign == 10 ) { builder.append( "Bad Moon" ); } else { builder.append( "(Sign " ); builder.append( String.valueOf( sign ) ); builder.append( ")" ); } builder.append( " sign" ); m = PATH_PATTERN.matcher( urlString ); if ( !m.find() ) { return true; } int path = StringUtilities.parseInt( m.group( 1 ) ); builder.append( " on " ); switch ( path ) { case 0: builder.append( "no" ); break; case 1: builder.append( "a Boozetafarians" ); break; case 2: builder.append( "a Teetotaler" ); break; case 3: builder.append( "an Oxygenarian" ); break; case 4: builder.append( "a Bees Hate You" ); break; case 6: builder.append( "a Way of the Surprising Fist" ); break; case 7: builder.append( "a Trendy" ); break; case 8: builder.append( "an Avatar of Boris" ); break; case 9: builder.append( "a Bugbear Invasion" ); break; case 10: builder.append( "a Zombie Slayer" ); break; case 11: builder.append( "a Class Act" ); break; case 12: builder.append( "an Avatar of Jarlsberg" ); break; case 14: builder.append( "a BIG!" ); break; case 15: builder.append( "a KOLHS" ); break; case 16: builder.append( "a Class Act II: A Class For Pigs" ); break; case 17: builder.append( "an Avatar of Sneaky Pete" ); break; case 18: builder.append( "a Slow and Steady" ); break; case 19: builder.append( "a Heavy Rains" ); break; case 21: builder.append( "a Picky" ); break; case 22: builder.append( "the Standard" ); break; case 23: builder.append( "an Actually Ed the Undying" ); break; case 24: builder.append( "the One Crazy Random Summer" ); break; case 25: builder.append( "a Community Service" ); break; case 26: builder.append( "an Avatar of West of Loathing" ); break; case 27: builder.append( "a The Source" ); break; case 28: builder.append( "a Nuclear Autumn" ); break; case 29: builder.append( "a Gelatinous Noob" ); break; default: builder.append( "(Path " ); builder.append( String.valueOf( path ) ); builder.append( ")" ); break; } builder.append( " path," ); builder.append( " banking " ); builder.append( String.valueOf( karma ) ); builder.append( " Karma." ); message = builder.toString(); } if ( message == null ) { // Something New! return false; } KoLmafia.updateDisplay( "" ); RequestLogger.updateSessionLog( "" ); KoLmafia.updateDisplay( message ); RequestLogger.updateSessionLog( message ); return true; } }