<?xml version="1.0"?>
<feed xmlns="http://www.w3.org/2005/Atom" xml:lang="en">
	<id>https://wiki.kolmafia.us/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=That+FN+Ninja</id>
	<title>Kolmafia - User contributions [en]</title>
	<link rel="self" type="application/atom+xml" href="https://wiki.kolmafia.us/api.php?action=feedcontributions&amp;feedformat=atom&amp;user=That+FN+Ninja"/>
	<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Special:Contributions/That_FN_Ninja"/>
	<updated>2026-04-25T02:01:23Z</updated>
	<subtitle>User contributions</subtitle>
	<generator>MediaWiki 1.44.0</generator>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Pulls_remaining&amp;diff=4026</id>
		<title>Pulls remaining</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Pulls_remaining&amp;diff=4026"/>
		<updated>2011-07-07T16:20:29Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: pulls_remaining returns -1 if you can_interact()&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{&lt;br /&gt;
#vardefine:name|pulls_remaining}}{{&lt;br /&gt;
#vardefine:return_type|int}}{{&lt;br /&gt;
&lt;br /&gt;
FunctionPage|&lt;br /&gt;
name={{#var:name}}|&lt;br /&gt;
&lt;br /&gt;
function1={{Function|&lt;br /&gt;
name={{#var:name}}|&lt;br /&gt;
aggregate={{#var:aggregate}}|&lt;br /&gt;
return_type={{#var:return_type}}|&lt;br /&gt;
return_also={{#var:return_also}}|&lt;br /&gt;
}}|&lt;br /&gt;
&lt;br /&gt;
function_description=Returns the number of pulls remaining for the day for characters in-Ronin, 0 if you are in hardcore, and -1 otherwise.|&lt;br /&gt;
&lt;br /&gt;
code1={{CodeSample|&lt;br /&gt;
title=Code Sample|&lt;br /&gt;
description=The following checks to see if you&#039;ve forgotten to use up your daily pulls.|&lt;br /&gt;
code=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
if (pulls_remaining() &amp;gt; 0) {&lt;br /&gt;
   print(&amp;quot;You still have &amp;quot; + pulls_remaining() + &amp;quot; pulls you can make today.&amp;quot;);&lt;br /&gt;
} else {&lt;br /&gt;
   print(&amp;quot;You&#039;re all set on daily pulls.&amp;quot;);&lt;br /&gt;
}&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}|&lt;br /&gt;
special=Returns 0 when not logged in.&lt;br /&gt;
}}&lt;br /&gt;
&lt;br /&gt;
[[Category:Item Management]]&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Talk:CLI_Reference&amp;diff=6303</id>
		<title>Talk:CLI Reference</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Talk:CLI_Reference&amp;diff=6303"/>
		<updated>2010-07-15T16:10:58Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;should we add that Csend will add make it&#039;s own message to the recipient if it is not given?--[[User:Icon315|Icon315]] 21:47, 21 April 2010 (UTC)&lt;br /&gt;
:That&#039;s the kind of detail that should go on it&#039;s own page if the command is important enough to get its own page. --[[User:Bale|Bale]] 01:03, 22 April 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
I agree with Bale. My thoughts so far on CLI commands;&lt;br /&gt;
* Obvious stuff that anyone can figure out by looking at this table doesn&#039;t warrant it&#039;s own page.&lt;br /&gt;
* Stuff that behaves &#039;&#039;exactly&#039;&#039; the same as an ASH command should probably say so and link to the function page&lt;br /&gt;
** If it isn&#039;t &#039;&#039;exactly&#039;&#039; the same, but close enough that a line or two of explanation will clarify the difference, still link to the function but edit the function&#039;s CLI section to explain the difference.&lt;br /&gt;
** Said functions don&#039;t need their own pages&lt;br /&gt;
* Stuff that has a similar or identically named ASH function, but behaves &#039;&#039;significantly&#039;&#039; differently on the CLI, should have it&#039;s own page (with the command as a link).&lt;br /&gt;
** If the command names are the same, the cli command should be &amp;quot;command (CLI)&amp;quot; (ie &amp;quot;eat (CLI)&amp;quot;, if eat needed its own page)&lt;br /&gt;
** If the command has no ASH function with the same name, the &amp;quot;(CLI)&amp;quot; part can be omitted (we can always move a page later if an ASH equiv. is added)&lt;br /&gt;
* Create page names with alphanumeric characters when at all possible. Ie don&#039;t use &amp;quot;!&amp;quot; but rather &amp;quot;bang&amp;quot;&lt;br /&gt;
&lt;br /&gt;
All additional thoughts on this are welcome. --[[User:StDoodle|StDoodle (#1059825)]] 03:17, 22 April 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
: My thought is that you&#039;ve covered everything perfectly. This should be our bible for CLI pages. --[[User:Bale|Bale]] 03:38, 22 April 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
Bale recently explained a limitation with the acquire command that I was previously unaware of in [http://kolmafia.us/showthread.php?4575 this thread]. Perhaps acquire needs it&#039;s own page to account for this information? --[[User:That FN Ninja|That FN Ninja]] 16:10, 15 July 2010 (UTC)&lt;br /&gt;
 &lt;br /&gt;
==FYI==&lt;br /&gt;
&lt;br /&gt;
You can&#039;t simply copypasta stuff into these wiki tables; remember, the pipe character (&amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt;) is treated special in templates! Use &amp;lt;nowiki&amp;gt;{{!}}&amp;lt;/nowiki&amp;gt; instead, or &amp;lt;nowiki&amp;gt;&amp;lt;nowiki&amp;gt;&amp;lt;/nowiki&amp;gt;&#039;&#039;Stuff&#039;&#039;&amp;lt;nowiki&amp;gt;&amp;lt;/&amp;lt;/nowiki&amp;gt;&amp;lt;nowiki&amp;gt;nowiki&amp;gt;&amp;lt;/nowiki&amp;gt; tags. (P.S. You should see the source for this fyi...) This, by the way, is the reason a lot of parameter options appear to be missing. --[[User:StDoodle|StDoodle (#1059825)]] 03:26, 22 April 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
Ugh, what a mess. Sometimes, &amp;lt;nowiki&amp;gt;{{!}}&amp;lt;/nowiki&amp;gt; results in a &amp;lt;nowiki&amp;gt;&amp;lt;pre&amp;gt;&amp;lt;/nowiki&amp;gt; tag or something inside of wiki tables. On the other hand, similar FUBARS happen when using &amp;lt;nowiki&amp;gt;&amp;amp;amp;#124;&amp;lt;/nowiki&amp;gt; &#039;&#039;outside&#039;&#039; of tables on a wiki. Long story short; inside of a table, use &amp;lt;nowiki&amp;gt;&amp;amp;amp;#124;&amp;lt;/nowiki&amp;gt; for &amp;lt;nowiki&amp;gt;|&amp;lt;/nowiki&amp;gt; and outside of a table use &amp;lt;nowiki&amp;gt;{{!}}&amp;lt;/nowiki&amp;gt;. Messy enough for you? --[[User:StDoodle|StDoodle (#1059825)]] 03:59, 2 May 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=File_talk:Item_category.png&amp;diff=6925</id>
		<title>File talk:Item category.png</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=File_talk:Item_category.png&amp;diff=6925"/>
		<updated>2010-07-04T19:33:27Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: KoLmafia uses tradeable spelled with an &amp;#039;e&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;I like the new image. Nice work. However, since the ASH function KoLmafia uses for is_tradeable() is spelled with an &#039;e&#039;, the image should probably use tradeable spelled with an &#039;e&#039; as well for consistency and to prevent confusion. --[[User:That FN Ninja|That FN Ninja]] 19:33, 4 July 2010 (UTC)&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Data_Structures&amp;diff=3196</id>
		<title>Data Structures</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Data_Structures&amp;diff=3196"/>
		<updated>2010-07-02T04:06:02Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: The &amp;quot;Declarations&amp;quot; section was listed twice. Deleted the duplicate.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;{{TOCright}}&lt;br /&gt;
&lt;br /&gt;
KoLmafia supports complex data structures such as maps and records made from simple [[Data Types|data types]].&lt;br /&gt;
&lt;br /&gt;
== Maps ==&lt;br /&gt;
Most of this information was copied directly from ASH Maps Tutorial, by Veracity (http://kolmafia.sourceforge.net/advanced.html#maps)&lt;br /&gt;
&lt;br /&gt;
A map is indexed by one data type (the key) and associates that key with another (or the same) data type (the value). The key can be any ASH simple data type: boolean, int, float, string, item, location, class, stat, skill, effect, familiar, slot, or monster. The value can be any ASH data type at all: a simple type, a record, or can be another map. This effectively allows multi-dimensional maps and. In fact, that&#039;s how the syntax we provide for multi-dimensional maps actually operate: maps of maps of maps ...&lt;br /&gt;
&lt;br /&gt;
You can declare a map any time you can declare a variable: as a top level (global) variable, as a function parameter, or as a local variable in any scope.&lt;br /&gt;
&lt;br /&gt;
You can fetch data from a map any time you can provide a data value: in an expression, as a function parameter, on the right side of an assignment statement, from a &amp;quot;return&amp;quot; statement, as so on. You can pass around entire maps, individual elements, or intermediate maps: &amp;quot;slices&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
=== Declarations ===&lt;br /&gt;
&lt;br /&gt;
The syntax for declaring the data type of a map:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;data type&amp;gt; [ &amp;lt;key type&amp;gt;, ... ] &amp;lt;aggregate_name&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For example:&lt;br /&gt;
&lt;br /&gt;
{{CodeSample&lt;br /&gt;
|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
string [item] map1;&lt;br /&gt;
float [class, string, int] another_map;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== Assignments ===&lt;br /&gt;
&lt;br /&gt;
If you use a map on the left side of an assignment, you set the whole map at once to the new value.&lt;br /&gt;
&lt;br /&gt;
{{CodeSample&lt;br /&gt;
|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int [item] my_pricelist;&lt;br /&gt;
int [item] new_pricelist;&lt;br /&gt;
&lt;br /&gt;
/* Some code that updates new_pricelist */&lt;br /&gt;
&lt;br /&gt;
my_pricelist = new_pricelist;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
If you specify a map and a complete set of indices (of the correct types) on the left side of an assignment statement, you set a single element.&lt;br /&gt;
&lt;br /&gt;
{{CodeSample&lt;br /&gt;
|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
int [item] my_pricelist;&lt;br /&gt;
my_pricelist[ $item[ pail ] ] = 1000;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
If you specify a map and a prefix of indices (of the correct type), you directly set one of the intermediate maps, a &amp;quot;slice&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
{{CodeSample&lt;br /&gt;
|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
float [string, int, string] my_map;&lt;br /&gt;
float [int, string] slice1;&lt;br /&gt;
&lt;br /&gt;
/* Some code that fills slice1 */&lt;br /&gt;
my_map[ &amp;quot;slice1&amp;quot; ] = slice1;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== References ===&lt;br /&gt;
&lt;br /&gt;
The syntax for referencing an element (or slice) of a map:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;aggregate name&amp;gt;[ &amp;lt;key expression&amp;gt;, ... ]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
All the key expressions will be evaluated at run time. If you specify all the keys the map expects, you fetch data of the type specified by the map. If you specify fewer keys than the map expects, you get an intermediate map, a &amp;quot;slice&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
As an example:&lt;br /&gt;
{{&lt;br /&gt;
CodeSample|&lt;br /&gt;
code=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
boolean [string, string] props; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
might be used to hold &amp;quot;properties&amp;quot; associated with names.&lt;br /&gt;
{{&lt;br /&gt;
CodeSample|&lt;br /&gt;
code=&lt;br /&gt;
&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
props[ &amp;quot;dog&amp;quot;, &amp;quot;mammal&amp;quot; ] = true; &lt;br /&gt;
props[ &amp;quot;dog&amp;quot;, &amp;quot;pet&amp;quot; ] = true; &lt;br /&gt;
props[ &amp;quot;dog&amp;quot;, &amp;quot;fun&amp;quot; ] = false;&lt;br /&gt;
props[ &amp;quot;turtle&amp;quot;, &amp;quot;mammal&amp;quot; ] = false;&lt;br /&gt;
props[ &amp;quot;turtle&amp;quot;, &amp;quot;pet&amp;quot; ] = true;&lt;br /&gt;
props[ &amp;quot;turtle&amp;quot;, &amp;quot;fun&amp;quot; ] = false;&lt;br /&gt;
props[ &amp;quot;aardvark&amp;quot;, &amp;quot;mammal&amp;quot; ] = true;&lt;br /&gt;
props[ &amp;quot;aardvark&amp;quot;, &amp;quot;pet&amp;quot; ] = false;&lt;br /&gt;
props[ &amp;quot;aardvark&amp;quot;, &amp;quot;fun&amp;quot; ] = true; &lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
 &lt;br /&gt;
&lt;br /&gt;
references:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
props[ &amp;quot;dog&amp;quot;, &amp;quot;mammal&amp;quot;] =&amp;gt; true&lt;br /&gt;
boolean [string] animal = props[ &amp;quot;turtle&amp;quot; ];&lt;br /&gt;
animal[ &amp;quot;fun&amp;quot; ] =&amp;gt; false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Contains ===&lt;br /&gt;
&lt;br /&gt;
You can test the presence of a key in a map using the &amp;quot;contains&amp;quot; operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
&amp;lt;aggregate reference expression&amp;gt; contains &amp;lt;key expression&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Where &amp;lt;aggregate reference expression&amp;gt; must evaluate at run time to a map or slice, and must evaluate at run time to a key of the appropriate type. (Note that that is enforced at parse time; ASH can tell the datatype any expression will produce).&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
props contains &amp;quot;dog&amp;quot; =&amp;gt; true&lt;br /&gt;
props contains &amp;quot;elephant&amp;quot; =&amp;gt; false&lt;br /&gt;
props[ &amp;quot;aardvark&amp;quot; ] contains &amp;quot;fun&amp;quot; =&amp;gt; true&lt;br /&gt;
animal contains &amp;quot;pet&amp;quot; =&amp;gt; true&lt;br /&gt;
animal contains &amp;quot;favorite food&amp;quot; =&amp;gt; false&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Remove ===&lt;br /&gt;
&lt;br /&gt;
You can remove a key-value association from a map using the &amp;quot;remove&amp;quot; unary operator:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
remove &amp;lt;aggregate reference&amp;gt;&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
For clarification, an aggregate reference is &amp;quot;&amp;lt;map name&amp;gt;[ &amp;lt;index 1&amp;gt; ... &amp;lt;index n&amp;gt; ]&amp;quot; where &amp;lt;map name&amp;gt;[ &amp;lt;index 1&amp;gt; ... &amp;lt;index n-1&amp;gt; ] specifies the &amp;quot;slice&amp;quot; and &amp;lt;index n&amp;gt; specifies the &amp;quot;key&amp;quot;. Which is just what you expect, if you fully specify the indices; for a single dimensional map, &amp;quot;map[10]&amp;quot; -&amp;gt; &amp;quot;map&amp;quot; is the slice and 10 is the key. The &amp;quot;remove&amp;quot; operator removes the &amp;quot;key&amp;quot; from the &amp;quot;slice&amp;quot;. For example:&lt;br /&gt;
&lt;br /&gt;
{{CodeSample|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
string [int] map1;&lt;br /&gt;
map1[5] = &amp;quot;foo&amp;quot;;&lt;br /&gt;
print( count( map1 ) + &amp;quot; &amp;quot; + map1 contains 5 + &amp;quot; &amp;quot; + map1[5] );&lt;br /&gt;
print( &amp;quot;remove: &amp;quot; + remove map1[5] );&lt;br /&gt;
print( count( map1 ) + &amp;quot; &amp;quot; + map1 contains 5 + &amp;quot; &amp;quot;  + map1[5] );&lt;br /&gt;
print( &amp;quot;remove: &amp;quot; + remove map1[5] );&lt;br /&gt;
int [string, string] map2;&lt;br /&gt;
map2[&amp;quot;me&amp;quot;,&amp;quot;you&amp;quot;] = 17;&lt;br /&gt;
print( count( map2[&amp;quot;me&amp;quot;] ) + &amp;quot; &amp;quot; + map2[&amp;quot;me&amp;quot;] contains &amp;quot;you&amp;quot; + &amp;quot; &amp;quot; + map2[&amp;quot;me&amp;quot;,&amp;quot;you&amp;quot;] );&lt;br /&gt;
print( &amp;quot;remove: &amp;quot; + remove map2[&amp;quot;me&amp;quot;, &amp;quot;you&amp;quot;] );&lt;br /&gt;
print( count( map2[&amp;quot;me&amp;quot;] ) + &amp;quot; &amp;quot; + map2[&amp;quot;me&amp;quot;] contains &amp;quot;you&amp;quot; + &amp;quot; &amp;quot; + map2[&amp;quot;me&amp;quot;,&amp;quot;you&amp;quot;] );&lt;br /&gt;
print( &amp;quot;remove: &amp;quot; + remove map2[&amp;quot;me&amp;quot;, &amp;quot;you&amp;quot;] );&lt;br /&gt;
print( count( map2 ) + &amp;quot; &amp;quot; + map2[&amp;quot;me&amp;quot;] );&lt;br /&gt;
print( &amp;quot;remove: &amp;quot; + remove map2[&amp;quot;me&amp;quot;] );&lt;br /&gt;
print( count( map2 ) + &amp;quot; &amp;quot; + map2[&amp;quot;me&amp;quot;] );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
yields:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;pre&amp;gt;&lt;br /&gt;
1 true foo&lt;br /&gt;
remove: foo&lt;br /&gt;
0 false&lt;br /&gt;
remove:&lt;br /&gt;
1 true 17&lt;br /&gt;
remove: 17&lt;br /&gt;
0 false 0&lt;br /&gt;
remove: 0&lt;br /&gt;
1 aggregate int [string]&lt;br /&gt;
remove: aggregate int [string]&lt;br /&gt;
0 aggregate int [string]&lt;br /&gt;
&amp;lt;/pre&amp;gt;&lt;br /&gt;
&lt;br /&gt;
=== Clear ===&lt;br /&gt;
&lt;br /&gt;
You can remove all &amp;lt;code&amp;gt;key =&amp;gt; value&amp;lt;/code&amp;gt; entries from a map using the following syntax:&lt;br /&gt;
&lt;br /&gt;
{{CodeSample|code=&amp;lt;syntaxhighlight&amp;gt;clear &amp;lt;aggregate&amp;gt;;&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
=== Sort ===&lt;br /&gt;
&lt;br /&gt;
From http://kolmafia.us/showthread.php?t=1738&lt;br /&gt;
&lt;br /&gt;
The syntax is:&lt;br /&gt;
{{CodeSample|code=&amp;lt;syntaxhighlight&amp;gt;sort aggregate by keyExpr;&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&amp;lt;code&amp;gt;aggregate&amp;lt;/code&amp;gt; is a reference to the object to be sorted - arrays are probably the most useful things to sort, but any mapping type can be used (even multidimensional maps, but note that you can only sort along a single dimension at a time). The reference must not be enclosed in parentheses, as that would look like a call to a function named &amp;lt;code&amp;gt;sort()&amp;lt;/code&amp;gt; - which is still perfectly valid, &amp;quot;sort&amp;quot; has not become a [[Reserved Words|reserved word]].&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;keyExpr&amp;lt;/code&amp;gt; is an arbitrary expression that defines how the items should be ordered. It is evaluated once for every entry in the aggregate, in a scope with two additional variables implicitly defined: &#039;&amp;lt;code&amp;gt;index&amp;lt;/code&amp;gt;&#039; and &#039;&amp;lt;code&amp;gt;value&amp;lt;/code&amp;gt;&#039;, holding the details of that entry. The value of the &amp;lt;code&amp;gt;keyExpr&amp;lt;/code&amp;gt; is used as the sort key; typically it would be an &amp;lt;code&amp;gt;int&amp;lt;/code&amp;gt; or &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt;, but can be any ASH type that can be compared via &amp;quot;&amp;lt;&amp;quot; and the other relational operators.&lt;br /&gt;
&lt;br /&gt;
The most basic form of sorting would therefore be &amp;quot;&amp;lt;code&amp;gt;sort ... by value&amp;lt;/code&amp;gt;&amp;quot;, but many useful things can be done with the use of a more complex &amp;lt;code&amp;gt;keyExpr&amp;lt;/code&amp;gt; - the only real restriction is that the expression should not modify the object you&#039;re sorting. For example, if you had an array of items, you could sort it &amp;quot;&amp;lt;code&amp;gt;by autosell_price(value)&amp;lt;/code&amp;gt;&amp;quot;. An array of weapon items could be sorted &amp;quot;&amp;lt;code&amp;gt;by -get_power(value)&amp;lt;/code&amp;gt;&amp;quot; to put it in decreasing order of power. If the elements of your aggregate are records, you&#039;d need to use something like &amp;quot;&amp;lt;code&amp;gt;by value.fieldName&amp;lt;/code&amp;gt;&amp;quot;, since the records themselves can&#039;t be meaningfully compared.&lt;br /&gt;
&lt;br /&gt;
After the sort statement, the aggregate will have exactly the same sets of keys and values as before (even if the keys weren&#039;t consecutive), and the iteration order of the keys will be the same, but the values will likely be associated with different keys. The sort is stable - in other words, elements with sort keys that compare as equal will remain in the same order. This means that you can sort on multiple criteria by simply performing separate sorts for each of the criteria, in increasing order of significance.&lt;br /&gt;
&lt;br /&gt;
A few more examples of things you can do:&lt;br /&gt;
* &amp;quot;&amp;lt;code&amp;gt;by -value&amp;lt;/code&amp;gt;&amp;quot; sorts integers in decreasing order (there&#039;s no similar trick for &amp;lt;code&amp;gt;string&amp;lt;/code&amp;gt; values).&lt;br /&gt;
* &amp;quot;&amp;lt;code&amp;gt;by -index&amp;lt;/code&amp;gt;&amp;quot; reverses the existing order of an array (or map with integer keys).&lt;br /&gt;
* &amp;quot;&amp;lt;code&amp;gt;by random(1000000)&amp;lt;/code&amp;gt;&amp;quot; shuffles into a random order.&lt;br /&gt;
* &amp;quot;&amp;lt;code&amp;gt;by otherArray[index]&amp;lt;/code&amp;gt;&amp;quot; uses values from a parallel array as the sort keys (you&#039;d then need to do &amp;quot;&amp;lt;code&amp;gt;sort otherArray by value;&amp;lt;/code&amp;gt;&amp;quot; if you wanted the two arrays to remain in sync).&lt;br /&gt;
&lt;br /&gt;
== Records ==&lt;br /&gt;
&lt;br /&gt;
(copy-pasted from Veracity&#039;s post introducing the record [http://kolmafia.us/showthread.php?t=280])&lt;br /&gt;
&lt;br /&gt;
Starting with SVN revision 1311 of KoLmafia, ASH now supports a new kind of structured data: the record. Here is a little example of how you declare a record and variables of the new type you&#039;ve created by doing so.&lt;br /&gt;
&lt;br /&gt;
{{CodeSample|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
record my_type {&lt;br /&gt;
  	int ifield;&lt;br /&gt;
	string sfield;&lt;br /&gt;
	record {&lt;br /&gt;
		int first;&lt;br /&gt;
		int second;&lt;br /&gt;
	} rfield;&lt;br /&gt;
	int [int, int] mfield;&lt;br /&gt;
};&lt;br /&gt;
&lt;br /&gt;
my_type rvar;&lt;br /&gt;
my_type [int] mrvar;&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
What I&#039;ve done with the above is declare a new data type which I&#039;ve named &amp;quot;my_type&amp;quot;. Having declared the new type, I can use it (almost) anywhere that I can use a built-in type name. I declared a variable, &amp;quot;rvar&amp;quot;, of that type, and I defined a map, &amp;quot;mrvar&amp;quot;, which maps keys of type integer to values of type my_type.&lt;br /&gt;
&lt;br /&gt;
The new type, &amp;quot;my_type&amp;quot; is a &amp;quot;composite&amp;quot; type. It contains four fields. &amp;quot;ifield&amp;quot; is an integer. &amp;quot;sfield&amp;quot; is a string. &amp;quot;rfield&amp;quot; is another composite field: an anonymous record containing two integers named &amp;quot;first&amp;quot; and &amp;quot;second&amp;quot;. Finally, &amp;quot;mfield&amp;quot; is a map from [int, int] to int.&lt;br /&gt;
&lt;br /&gt;
As you can see, a record can combine data of all the types ASH supports: primitive, aggregate, and composite.&lt;br /&gt;
&lt;br /&gt;
Having defined the new data type and several variables using it, here are some examples of how to access the fields.&lt;br /&gt;
&lt;br /&gt;
{{CodeSample|code=&amp;lt;syntaxhighlight&amp;gt;&lt;br /&gt;
rvar.ifield = 10;&lt;br /&gt;
rvar.sfield = &amp;quot;secret&amp;quot;;&lt;br /&gt;
rvar.rfield.first = 1000;&lt;br /&gt;
rvar.sfield.second = 2000;&lt;br /&gt;
rvar.mfield[ 2, 3 ] = 12;&lt;br /&gt;
&lt;br /&gt;
mrvar[ 1 ] = rvar;&lt;br /&gt;
&lt;br /&gt;
foreach key in mrvar&lt;br /&gt;
	foreach key1, key2 in mrvar[key].mfield&lt;br /&gt;
		print( &amp;quot;val = &amp;quot; + mrvar[key].mfield[key1,key2] );&lt;br /&gt;
&amp;lt;/syntaxhighlight&amp;gt;}}&lt;br /&gt;
&lt;br /&gt;
&lt;br /&gt;
As you can see, if you have a variable that is a record, you access the fields of the record by following the variable name with &amp;quot;.&amp;amp;lt;field name&amp;amp;gt;&amp;quot;. The resulting value will be of whatever type you declared in the definition of the record. If the value is a map, you can give a list of keys within [], just like any other map. If the value is another record, you can access the fields of the nested record by using another &amp;quot;.&amp;amp;lt;field name&amp;amp;gt;&amp;quot;.&lt;br /&gt;
&lt;br /&gt;
If you are familiar with Pascal &amp;quot;records&amp;quot; or C/C++ &amp;quot;structs&amp;quot;, this should all be comfortably familiar.&lt;br /&gt;
&lt;br /&gt;
Finally, if you create a map whose values is a record, the file_to_map and map_to_file built-in ASH functions will Do The Right Thing; they will efficiently and reliably save and restore your data.&lt;br /&gt;
{{RFI|I, for one, don&#039;t have a good handle on multi-dimensional maps. Any effort to clarify how they are defined &amp;amp; accessed would be greatly appreciated.|Don&#039;t worry about formatting for now; I&#039;ll get to that once the info is there, unless you&#039;re feeling super-ambitious.}}&lt;br /&gt;
{{Format}}&lt;br /&gt;
&lt;br /&gt;
[[Category:ASH Scripting]]&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Talk:Adventure&amp;diff=6353</id>
		<title>Talk:Adventure</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Talk:Adventure&amp;diff=6353"/>
		<updated>2010-06-26T21:39:01Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;jasonharper said we can supply a macro as the third parameter; any ideas on usage? KoL macros require line breaks in a picky manner, but setting my string to have &amp;quot;\n&amp;quot; doesn&#039;t work... or am I sup&#039;d to use a macro&#039;s name? --[[User:StDoodle|StDoodle (#1059825)]] 21:21, 29 April 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
:I think he means to use the macro&#039;s name. Try it. --[[User:Bale|Bale]] 21:23, 29 April 2010 (UTC)&lt;br /&gt;
&lt;br /&gt;
Wow!! The wiki has come a long ways since I was last on here in December. It&#039;s beautiful! I don&#039;t know if this is the right place for this, but I think it would be helpful to have a list of special events that cause adventure to stop and return false besides conditions being satisfied. Demon name and hobo glyph are already listed, but I think there are a lot more. I don&#039;t know that many, but looking over Zarqon&#039;s MacGuffin script I saw several. I just tested out the Sietch in Time adventure. adventure(my_adventures(), $location[desert (ultrahydrated)]) stopped adventuring and returned false when I received the Sietch in Time adventure. What do you guys think?&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=In_hardcore&amp;diff=2224</id>
		<title>In hardcore</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=In_hardcore&amp;diff=2224"/>
		<updated>2009-12-23T05:16:06Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[boolean]] [[in_hardcore()]]&lt;br /&gt;
&lt;br /&gt;
This function returns &#039;&#039;true&#039;&#039; if the logged-in character is currently subject to Hardcore restrictions.  If not subject to such restrictions this function returns &#039;&#039;false&#039;&#039;.&lt;br /&gt;
&lt;br /&gt;
The following example attempts to pull items from storage if the character is in Ronin:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  if (![[can_interact()]] &amp;amp;&amp;amp; ![[in_hardcore()]] &amp;amp;&amp;amp; [[storage_amount()|storage_amount]]($[[item]][not-a-pipe]) &amp;gt; 0) &lt;br /&gt;
    [[take_storage()|take_storage]](1,$[[item]][not-a-pipe]);&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Category:Your Character | In hardcore()]]&lt;br /&gt;
[[Category:Ash Functions |In hardcore()]]&lt;br /&gt;
&lt;br /&gt;
When not logged in, this function returns &#039;&#039;false&#039;&#039;.&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=My_spleen_use&amp;diff=3255</id>
		<title>My spleen use</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=My_spleen_use&amp;diff=3255"/>
		<updated>2009-12-23T05:06:57Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: Created page with &amp;#039;int my_spleen_use()  Returns the logged-in character&amp;#039;s current spleen damage as an int.&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[int]] [[my_spleen_use()]]&lt;br /&gt;
&lt;br /&gt;
Returns the logged-in character&#039;s current spleen damage as an [[int]].&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Spleen_limit&amp;diff=3246</id>
		<title>Spleen limit</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Spleen_limit&amp;diff=3246"/>
		<updated>2009-12-23T05:05:17Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[int]] [[spleen_limit()]]&lt;br /&gt;
&lt;br /&gt;
Returns the logged-in character&#039;s maximum spleen damage as an [[int]]. For most characters, the returned value will be 15. The number is raised by 5 for characters with Spleen of Steel.&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Spleen_limit&amp;diff=3245</id>
		<title>Spleen limit</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Spleen_limit&amp;diff=3245"/>
		<updated>2009-12-23T05:00:55Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: &lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[int]] [[spleen_limit()]]&lt;br /&gt;
&lt;br /&gt;
This function returns the logged-in character&#039;s maximum spleen amount as an [[int]].&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=Spleen_limit&amp;diff=3244</id>
		<title>Spleen limit</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=Spleen_limit&amp;diff=3244"/>
		<updated>2009-12-23T05:00:10Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: Created page with &amp;#039;int spleen_limit()  This function returns the logged-in character&amp;#039;s maximum fullness level as an int.&amp;#039;&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[int]] [[spleen_limit()]]&lt;br /&gt;
&lt;br /&gt;
This function returns the logged-in character&#039;s maximum fullness level as an [[int]].&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
	<entry>
		<id>https://wiki.kolmafia.us/index.php?title=My_name&amp;diff=1645</id>
		<title>My name</title>
		<link rel="alternate" type="text/html" href="https://wiki.kolmafia.us/index.php?title=My_name&amp;diff=1645"/>
		<updated>2009-12-23T04:42:29Z</updated>

		<summary type="html">&lt;p&gt;That FN Ninja: my_name() is not case sensative.&lt;/p&gt;
&lt;hr /&gt;
&lt;div&gt;[[string]] [[my_name()]]&lt;br /&gt;
&lt;br /&gt;
This function returns the logged-in character&#039;s name as a [[string]].&lt;br /&gt;
&lt;br /&gt;
This example imports different breakfast scripts depending on which character is running the script.&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  if ([[my_name()]] == &amp;quot;zammywarrior&amp;quot;) {&lt;br /&gt;
    [[import]] &amp;lt;Zammy Morning.ash&amp;gt;;&lt;br /&gt;
  }&lt;br /&gt;
  else if ([[my_name()]] == &amp;quot;hippymon&amp;quot;) {&lt;br /&gt;
    [[import]] &amp;lt;Hippy Morning.ash&amp;gt;;&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
Note that capitalization is not strictly adhered to. When using [[my_name()]] the following examples are functionally equivalent:&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  if ([[my_name()]] == &amp;quot;That FN Ninja&amp;quot;) {&lt;br /&gt;
     [[comments| // code]]&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
&lt;br /&gt;
&amp;lt;code&amp;gt;&lt;br /&gt;
  if ([[my_name()]] == &amp;quot;that fn ninja&amp;quot;) {&lt;br /&gt;
     [[comments|// code]]&lt;br /&gt;
  }&lt;br /&gt;
&amp;lt;/code&amp;gt;&lt;br /&gt;
[[Category:Your Character | My name()]]&lt;br /&gt;
[[Category:Ash Functions | My name()]]&lt;br /&gt;
&lt;br /&gt;
When not logged in, this function returns an empty string.&lt;/div&gt;</summary>
		<author><name>That FN Ninja</name></author>
	</entry>
</feed>