<!--
Randomly picks one object from the given object list.
-->
<function name="PickOneObj" parameters="lst" type="object">
index = GetRandomInt(0, ListCount(lst) - 1)
return (ObjectListItem(lst, index))
</function>
<!--
Randomly picks one string from the given string list.
Alternatively, if sent a string, it will randomly pick a substring of it.
Substrings should be separated by a semi-colon eg:
randomnumber = PickOneStr("one;two;three")
-->
<function name="PickOneStr" parameters="lst" type="string">
if (TypeOf(lst) = "string") {
lst = Split(lst, ";")
}
index = GetRandomInt(0, ListCount(lst) - 1)
return (StringListItem(lst, index))
</function>
<!--
Randomly picks one of the direct children objects of the given object.
For example, if you sent it a room, it will pick an object in that room
(which could be the player, if it is the current room).
NOTE: You must also have PickOneObj.
-->
<function name="PickFromObject" parameters="obj" type="object">
return (PickOneObj(GetDirectChildren(obj)))
</function>
<!--
Randomly picks one object of the given type from the given room.
The type should be specified as a string.
Note that editor_room and editor_object will be removed from your game
when it is pubished, so do not used them!
randomman = PickOneOfType(player.parent, "male")
-->
<function name="PickOneOfType" parameters="room, objtype" type="object">
l = NewObjectList()
foreach (o, GetDirectChildren(room)) {
if (DoesInherit(o, objtype)) {
list add (l, o)
}
}
return (PickOneObj(l))
</function>
<!--
This function will tell you which attribute of an object is the highest.
The first parameter is the object, the second parameter must be a list of integer parameters.
It returns the name of the attribute.
s = GetHighestAtt(hat, list)
specialisation = GetHighestAtt(player, Split("strength|agility|intelligence", "|"))
If any attribute is not set or is not a number you will get an error!
-->
<function name="GetHighestAtt" parameters="obj, atts" type="string"><![CDATA[
highest = StringListItem(atts, 0)
foreach (s, atts) {
if (GetInt(obj, s) > GetInt(obj, highest)) {
highest = s
}
}
return (highest)
]]></function>
<!--
This function will return the next object in the list after the given object.
If the given object is at the end,it will return the first object.
If the given object is not in the list, null is returned.
The first parameter is the list, the second parameter the given object.
--> <function name="NextInList" parameters="l, obj" type="object">
flag = false
foreach (o, l) {
if (flag) {
return (o)
}
if (o = obj) {
flag = true
}
}
if (flag) {
return (ObjectListItem(l, 0))
}
return (null)
</function>
<!--
Returns the given number as a string, in Roman numerals. It can handle numbers from one up to a few thousand
(there was no zero or negative numbers in those days).
-->
<function name="Roman" parameters="n" type="string">
arabic = Split("1000,900,500,400,100,90,50,40,10,9,5,4,1", ",")
roman = Split("M,CM,D,CD,C,XC,L,XL,X,IX,V,IV,I", ",")
result = ""
for(i, 0, 12) {
a = ToInt(StringListItem(arabic, i))
r = StringListItem(roman, i)
while (n >= a) {
result = result + r
n = n - a
}
}
return (result)
</function>
<!--
Returns the given number as a string, in words. It can handle numbers from -1999 to 1999.
Note that it consists of an object and a function.
-->
<object name="pix_string_struct">
<number_units type="simplestringlist">zero;one;two;three;four;five;six;seven;eight;nine;ten;eleven;twelve;thirteen;fourteen;fifteen;sixteen;seventeen;eighteen;nineteen;twenty</number_units>
<number_tens type="simplestringlist">twenty;thirty;forty;fifty;sixty;seventy;eighty;ninety</number_tens>
</object>
<function name="ToWords" parameters="number" type="string"><![CDATA[
if (not TypeOf(number) = "int") {
error ("NumberInWords can only handle ints")
}
s = ""
if (number < 0) {
s = "minus "
number = -number
}
if (number <= 1999) {
hundreds = number / 100
number = number % 100
if (hundreds > 0) {
s = s + StringListItem(pix_string_struct.number_units, hundreds) + " hundred "
if (number > 0) {
s = s + "and "
}
}
if (number < 20) {
if (not number = 0 or s = "") {
s = s + StringListItem(pix_string_struct.number_units, number)
}
}
else {
units = number % 10
tens = (number / 10) % 10
s = s + StringListItem(pix_string_struct.number_tens, tens - 2)
if (not units = 0) {
s = s + StringListItem(pix_string_struct.number_units, units)
}
}
}
else {
s = ToString(number)
}
return (Trim(s))
]]></function>
<!--
Provides a string of spaces, of the given length. HTML collapses white space, so a simple string of five
spaces will be reduced to a single space in the Quest output. This function offers a work-around.
-->
<function name="Whitespaces" parameters="number" type="string"><![CDATA[
game.command_successful = True
text = ""
for (x, 1, number) {
text = text+ " "
}
return (text)
]]></function>
<!--
Returns a list of exits for the given room.
An alternative to ScopeExitsForRoom that will only get the
exits for the given room that are unlocked.
-->
<function name="ScopeUnlockedExitsForRoom" parameters="room" type="objectlist">
result = NewObjectList()
foreach (exit, AllExits()) {
if (exit.parent = room) {
if (exit.visible and not exit.locked) {
if (GetBoolean(room, "darklevel")) {
if (GetBoolean(exit, "lightsource")) {
list add (result, exit)
}
}
else {
list add (result, exit)
}
}
}
}
return (result)
</function>
<!--
Returns a room picked at random from the rooms that can be directly accessed from this room
(i.e., there is an exit from this room to it).
The returned room could be the other side of a locked door.
Returns the given room if there are no such room.
-->
<function name="RandomNextRoom" parameters="currentroom" type="object">
exts = ScopeExitsForRoom (currentroom)
if (ListCount(exts) = 0) {
return (currentroom)
}
exit = ObjectListItem(exts, GetRandomInt(0, ListCount(exts) - 1))
return (exit.to)
</function>
<!--
Returns a room picked at random from the rooms that can be directly accessed from this room
(i.e., there is an exit from this room to it).
Rooms behind locked doors will not be returned.
Returns the given room if there are no such room.
-->
<function name="RandomNextUnlockedRoom" parameters="currentroom" type="object">
exts = ScopeUnlockedExitsForRoom (currentroom)
if (ListCount(exts) = 0) {
return (currentroom)
}
exit = ObjectListItem(exts, GetRandomInt(0, ListCount(exts) - 1))
return (exit.to)
</function>
<!--
Picks the next object in the list after the given, or the first object
if the last is given.
Returns null if the given object is not in the list.
-->
<function name="NextInList" parameters="l, obj" type="object">
flag = false
foreach (o, l) {
if (flag) {
return (o)
}
if (o = obj) {
flag = true
}
}
if (flag) {
return (ObjectListItem(l, 0))
}
return (null)
</function>
<!--
Returns the given object list as a string in the form a one, a two, a three.
Note this is two functions.
-->
<function name="List" parameters="ol" type="string"><![CDATA[
if (ListCount(ol) = 0) return ("nothing")
strings = (TypeOf(ol) = "stringlist")
if (ListCount(ol) = 1 and strings) return (StringListItem(ol, 0))
if (ListCount(ol) = 1) return (Indefinite(ObjectListItem(ol, 0)))
if (strings) {
sl = ol
s2 = StringListItem(ol, ListCount(ol) - 1)
}
else {
sl = NewStringList()
foreach (o, ol) {
s2 = Indefinite(o)
list add (sl, s2)
}
}
list remove (sl, s2)
s = LCase(Join(sl, ", ") + " and " + s2)
return (s)
]]></function>
<function name="Indefinite" parameters="o" type="string"><![CDATA[
if (DoesInherit(o, "plural")) {
return (LCase("some " + o.alias))
}
else {
return (LCase("a " + o.alias))
}
]]></function>
<!--
Two functions that return a list of exits to the given room, excluding invisble exits.
The first also excludes locked exits.
-->
<function name="ScopeUnlockedExitsTo" parameters="loc" type="objectlist">
l = NewObjectList()
foreach (o, AllExits ()) {
if (o.to = loc and o.visible and not o.locked) {
list add (l, o)
}
}
return (l)
</function>
<function name="ScopeAllExitsTo" parameters="loc" type="objectlist">
l = NewObjectList()
foreach (o, AllExits ()) {
if (o.to = loc and o.visible) {
list add (l, o)
}
}
return (l)
</function>