Feature - Implemented Spring 2017 Challenge: Gelatinous Noob!

Darzil

Developer
I need to report a bug. KoLmafia is not recognizing the council quest for level 2. The html when I get the quest from the council is this:

HTML:
<p><p>Okay, you're in luck, because I found a quest that's perfect for an adventurer of your... stature. We need you to go out to the marshy part of the Spooky Forest, and bring us back a mosquito larva. I bet you get mosquitoes trying to breed in you all the time, so this should be really easy for you. In case you aren't actually from the Spooky Forest, I'll mark it on your map -- it's in the Distant Woods. Hang on, let me find a real long pencil that I don't care about.

r17882, looks like TPTB fixed a text bug which broke this.
 

ckb

Minion
Staff member
You fell for it. Just as I'd planned. :D

Its not perfect or pretty, but it is functional. Ironically, I wrote it all from scratch before I re-read that you had already written a function to resort them.

Code:
buffer NoobSkis(buffer page) {
	matcher mnsk = create_matcher("<div class=\"sk\".+?value=\"(\\d+?)\".+?</div>",page);
	string[int] skops;
	
	while (find(mnsk)) {
		int num = to_int(group(mnsk,1));
		skops[num] = group(mnsk);
		page.replace_string(group(mnsk),"");
	}
	
	string newski = "";
	int ln=0;
	foreach nn,ss in skops {
		newski += ss;
		
		if (nn%5==0) {
			newski += "<br><hr><br>";
			ln=nn;
		}
	}
	
	page.replace_string("this time around!","this time around!<center>"+newski+"</center>");
	page.replace_string("float: left; ","float: clear; ");
	
	return page;
}

void main() {
	buffer page;
	page.append(visit_url());
	
	if (page.contains_text("bgcolor=blue><b>Welcome to the Kingdom, Gelatinous Noob")) {
		page = NoobSkis(page);
	}
	write(page);
	
}
 

Bale

Minion
Its not perfect or pretty, but it is functional. Ironically, I wrote it all from scratch before I re-read that you had already written a function to resort them.

Ah well. Your does almost exactly the same thing as mine (with a little bit of formatting) except the code is a little clunkier. I was really hoping you'd actually make it look like the wiki page.

One critique: If the character doesn't have all the skills, the horizontal rules might be skipped.
 

ckb

Minion
Staff member
Ah well. Your does almost exactly the same thing as mine (with a little bit of formatting) except the code is a little clunkier. I was really hoping you'd actually make it look like the wiki page.
One critique: If the character doesn't have all the skills, the horizontal rules might be skipped.

As I said, not perfect or pretty. It was more a quick start to a proof of concept of how to get the skills sequenced and ordered and separated. If I had noticed your (less clunky) code first, I would have started there.

That said, as I have been thinking about this more, I realize that I don't need a formatted list as much as I need a convenient and easy to use list. With that in mind, I might re-write mine with a hardcoded skill order where all the skills I want to take are at the top. I take the same skills every time, and I don't see why this would change much once I convince myself that my strategy is sound.
Maybe it will just list N skills, where N is the number or perms you have available.
Or it will list N at the top, then the rest in another section.
 

Bale

Minion
That's a pretty good idea! I wrote something up for it.


Next time I ascend, I'll have to test this...
Code:
static {
	skill [int] bestGelnoob;
	foreach sk in $skills[Subcutaneous Fat,Profound Shame,Work Ethic,Arrogance,Central Hypothalamus,Rudimentary Alimentary Canal,Small Intestine,Stomach-Like Thing,Large Intestine,Right Eyeball,Optic Nerves,Saccade Reflex,Visual Cortex,Thumbs,Pathological Greed,Beating Human Heart]
		bestGelnoob[ to_int(sk) ] = sk;
}

buffer gelnoob(buffer page) {
	int i = index_of(page, '<div class="sk">');
	if(i >= 0) {
		buffer result;
		string [int] gelskill;
		matcher sk = create_matcher('<div class="sk">.+?value="(\\d+)".+?</div>', page);
		while(sk.find())
			gelskill[ to_int(sk.group(1)) ] = sk.group(0);
		result.append(page.substring(0,i));
		
		// First the skills that are on the approved list
		foreach x,gel in gelskill
			if(bestGelnoob contains x) {
				result.append(gel);
				remove gelskill[x];
			}
		result.append("<br><hr><br>");
		// It's safe to assume the player learned at least one of those skills in a previous ascension
		
		// Now the rest of the skills. In order.
		foreach x,gel in gelskill
			result.append(gel);
		
		
		if((i = index_of(page,'<div style="clear:both;')) >= 0)
			result.append(page.substring(i));
		return result;
	}
	return page;
}

buffer special_pages(buffer page) {
	if(page.contains_text("Welcome to the Kingdom, Gelatinous Noob"))
		return gelnoob(page);
	return page;
}


void main() {
	visit_url().special_pages().write();
}
 
Last edited:

ckb

Minion
Staff member
That's a pretty good idea! I wrote something up for it.

Yes! This is exactly what I had in mind. My skill order is a tad different, but the result looks as I imagined it. I'll check it out in my next ascension too. Sweet.
 

Bale

Minion
There are only 16 skills on that list so far. I'm not sure what to choose for the remaining 4 since a lot of other high priority skills are so easy to get with readily available items. Perhaps I should add Sunglasses (+25 Moxie) since it will save me 1000 meat for a tenderizing hammer? Sweat Glands and Kneecaps are also a bit out of the way to learn so they might take precedence over more powerful skills.

Strategy suggestions welcome.

Edit: my first absorbs after cheating for stats and meat are...
  • Sense of Purpose: ( +5 exp ) - interesting clod of dirt
  • Basic Self-Worth ( +3 exp ) - seal tooth
  • Olfactory Cortex ( Stench +3 ) - wooden figurine
  • Sense of Pride ( +5 exp ) - cog and sprocket assembly
  • Left Eyeball ( Item +20 ) - all-purpose flower
  • Sense of Entitlement ( Meat +60 )- fermenting powder
  • Sunglasses ( Moxie +25 ) - tenderizing hammer


So much good stuff and so easy to learn. Bad idea to remember those despite their utility.
 
Last edited:

Bale

Minion
That's an excellent question. I'm not entirely sure how it ended up on the list. I must have had trouble fighting the ghost of Oily McBindle or Jim Unfortunato and gotten so annoyed that I put the skill on the list without much vetting. Or maybe I mixed it up with another skill. Or maybe it fell in when I was figuring out which skills were hard to get during a serious run.

Of course it's good to have a little bit of all elemental resistance when you fight Lord Spookyraven, but that's a long way from turn 1 and I'd probably survive with only +2 res.

Does not belong there.
 
Last edited:

Magus_Prime

Well-known member
@Bale - I tried your choice override today and it properly grouped and ordered the skills when starting a run. Thank you!
 

Bale

Minion
I'm really glad to hear that! I'll share the current state of that code for people who care. I've added more skills and removed one. For no particular reason I still have Profound Shame on the list, but you can always choose not to learn that.

Code:
buffer gelnoob(buffer page) {
	skill [int] bestGelnoob; // These skills are listed at the top of the order
	foreach sk in $skills[Subcutaneous Fat,Profound Shame,Sweat Glands,
		Central Hypothalamus,Rudimentary Alimentary Canal,Small Intestine,Stomach-Like Thing,Large Intestine,
		Work Ethic,Sense of Purpose,Sense of Pride,Arrogance,
		Vacuoles,Golgi Apparatus,
		Right Eyeball,Optic Nerves,Saccade Reflex,Visual Cortex,
		Pathological Greed,Kneecaps,Beating Human Heart,
		Middle Fingers,Index Fingers,
		Sunglasses,Ice Water In Your Veins]
			bestGelnoob[ to_int(sk) ] = sk;

	int i = index_of(page, '<div class="sk">');
	if(i >= 0) {
		buffer result;
		string [int] gelskill;
		matcher sk = create_matcher('<div class="sk">.+?value="(\\d+)".+?</div>', page);
		while(sk.find())
			gelskill[ to_int(sk.group(1)) ] = sk.group(0);
		result.append(page.substring(0,i));
		
		// First the skills that are on the approved list
		foreach x,gel in gelskill
			if(bestGelnoob contains x) {
				result.append(gel);
				remove gelskill[x];
			}
		
		// It's safe to assume the player learned at least one of those skills in a previous ascension, so lets add a line break
		result.append("<br><hr><br>");
		
		// Now the rest of the skills. In order.
		foreach x,gel in gelskill
			result.append(gel);
		
		if((i = index_of(page,'<div style="clear:both;')) >= 0)
			result.append(page.substring(i));
		return result;
	}
	return page;
}

buffer special_pages(buffer page) {
	if(page.contains_text("Welcome to the Kingdom, Gelatinous Noob"))
		return gelnoob(page);
	return page;
}


void main() {
	visit_url().special_pages().write();
}
 

ckb

Minion
Staff member
I'm really glad to hear that! I'll share the current state of that code for people who care. I've added more skills and removed one. For no particular reason I still have Profound Shame on the list, but you can always choose not to learn that.

Did this work for you as expected? It did not for me, so I made some changes.

I believe that due to how the page uses skill numbers, you need this:
bestGelnoob[ to_int(sk)-23000 ] = sk;

Also, by using a map of skill [int] bestGelnoob; it will auto-sort based on the [int]. This results in the top skills being all in the top, but not necessarily in order of priority. I use a $ints[] list of skills which keeps its order to make my perm order the same as the skill order on the page. This does not matter when you are up to 20 perms, but I'm not there yet.

Code:
buffer NoobSkis(buffer page) {
	print("NoobSkis choice","green");
	
	boolean[int] bestgelnoob;
	bestgelnoob = $ints[45,46,70,69,67,60,41,47,66,80,50,49,48,95,73,68,38,44,39,79];
	
	int ii = index_of(page,"<div class=\"sk\">");
	if (ii >= 0) {
		buffer result;
		string [int] gelskill;
		matcher sk = create_matcher("<div class=\"sk\">.+?value=\"(\\d+)\".+?</div>",page);
		while (sk.find()) {
			gelskill[to_int(sk.group(1))] = sk.group(0);
		}
		result.append(page.substring(0,ii));
		result.append("<center>");
		
		//First the skills that are on the approved list, in order
		foreach zz in bestgelnoob {
			if (gelskill contains zz) {
				result.append(gelskill[zz]);
				remove gelskill[zz];
			}
		}
		
		result.append("<br><hr><br>");
		// It's safe to assume the player learned at least one of those skills in a previous ascension
		
		// Now the rest of the skills, in order.
		foreach xx,gel in gelskill {
			result.append(gel);
		}
		
		result.append("</center>");
		if ((ii = index_of(page,"<div style=\"clear:both;")) >= 0) {
			result.append(page.substring(ii));
		}
		result.replace_string("float: left; ","float: clear; ");
		
		return result;
	}
	return page;
}

Also, still tweaking the skills order, but this is what I am using for this run (8 perms).
 
Last edited:

Veracity

Developer
Staff member
Also, by using a map of skill [int] bestGelnoob; it will auto-sort based on the [int]. This results in the top skills being all in the top, but not necessarily in order of priority. I use a $ints[] list of skills which keeps its order to make my perm order the same as the skill order on the page. This does not matter when you are up to 20 perms, but I'm not there yet.
You can use a map whose index is an int and whose value is (something to do with a skill).

Code:
static string [ int ] bestgelnoob {
    1 : "Arrogance",
    2 : "Central Hypothalamus",
    3 : "Visual Cortex",
    4 : "Saccade Reflex",
    5 : "Optic Nerves",
    6 : "Beating Human Heart",
    7 : "Work Ethic",
    8 : "Rudimentary Alimentary Canal",
    9 : "Left Eyeball",
    10 : "Large Intestine",
    11 : "Small Intestine",
    12 : "Stomach-Like Thing",
    13 : "Right Eyeball",
    14 : "Pathological Greed",
    15 : "Middle Fingers",
    16 : "Sunglasses",
    17 : "Kneecaps",
    18 : "Sense of Pride",
    19 : "Achilles Tendons",
    20 : "Subcutaneous"
};
Obviously you could have skillId or skillId - 23000, or a $skill[] constant, or whatever.
I think having the actual skill name is a lot clearer than a skillId. Hence, a string or a $skill.
If you want to change the order of skills, obviously you have to manually change the indices.

Use it like this:

Code:
	// First the skills that are on the approved list, in order
	foreach index, name in bestgelnoob {
	    int zz = name.to_skill().to_int() - 23000;
	    if (gelskill contains zz) {
		result.append(gelskill[zz]);
		remove gelskill[zz];
	    }
	}
 

Magus_Prime

Well-known member
@Bale - I tried the last iteration of the choice.ash routine in post 114. It still sorted the skills but did not automatically choose any of the listed skills.
 

Bale

Minion
Yeah, there was a small bug that ckb pointed out. I ran it earlier today with the bug fixed and it worked:

Code:
buffer gelnoob(buffer page) {
	skill [int] bestGelnoob; // These skills are listed at the top of the order
	foreach sk in $skills[Subcutaneous Fat,Profound Shame,Sweat Glands,
		Central Hypothalamus,Rudimentary Alimentary Canal,Small Intestine,Stomach-Like Thing,Large Intestine,
		Work Ethic,Sense of Purpose,Sense of Pride,Arrogance,
		Vacuoles,Golgi Apparatus,
		Right Eyeball,Optic Nerves,Saccade Reflex,Visual Cortex,
		Pathological Greed,Kneecaps,Beating Human Heart,
		Middle Fingers,Index Fingers,
		Sunglasses,Ice Water In Your Veins]
			bestGelnoob[ to_int(sk) - 23000 ] = sk;

	int i = index_of(page, '<div class="sk">');
	if(i >= 0) {
		buffer result;
		string [int] gelskill;
		matcher sk = create_matcher('<div class="sk">.+?value="(\\d+)".+?</div>', page);
		while(sk.find())
			gelskill[ to_int(sk.group(1)) ] = sk.group(0);
		result.append(page.substring(0,i));
		
		// First the skills that are on the approved list
		foreach x,gel in gelskill
			if(bestGelnoob contains x) {
				result.append(gel);
				remove gelskill[x];
			}
		
		// It's safe to assume the player learned at least one of those skills in a previous ascension, so lets add a line break
		# result.append("<br><hr><br>");
		
		// Now the rest of the skills. In order.
		foreach x,gel in gelskill
			result.append(gel);
		
		if((i = index_of(page,'<div style="clear:both;')) >= 0)
			result.append(page.substring(i));
		return result;
	}
	return page;
}


buffer special_pages(buffer page) {
	if(page.contains_text("Welcome to the Kingdom, Gelatinous Noob"))
		return gelnoob(page);
	return page;
}


void main() {
	visit_url().special_pages().write();
}
 

Ezandora

Member
r17901

Obscure bug. Numeric_modifier() takes into account familiar weight modification:
Code:
> ash numeric_modifier($familiar[jumpsuited hound dog], "item drop", 1, $item[none])

Returned: 6.5415619758885

> ash numeric_modifier($familiar[jumpsuited hound dog], "item drop", 1, $item[astral pet sweater])

Returned: 38.25

> ash my_path()

Returned: Gelatinous Noob
In gelatinous noob, familiar equipment won't help the familiar.

Code:
> ash numeric_modifier($familiar[trick-or-treating tot], "item drop", 1, $item[none])

Returned: 0.0

> ash numeric_modifier($familiar[trick-or-treating tot], "item drop", 1, $item[li'l ninja costume])

Returned: 150.0
Same with trick-or-treating tot equipment.
 

Magus_Prime

Well-known member
I've notice that, when using the absorb command from the gCLI, when an outfit switch is called for to fulfill the request, the prior outfit is not restored after completion of the command.

For example: "absorb grapefruit" with none in inventory, equips the filthy hippy disguise, purchases a grapefruit, absorbs it, and leaves the filthy hippy disguise equipped.

Would it be reasonable and feasible for mafia to make a checkpoint prior to the equipment change and to restore equipped items after fulfilling the absorb request?
 
Top