Show Posts

This section allows you to view all posts made by this member. Note that you can only see posts made in areas you currently have access to.


Topics - Tricky

Pages: [1] 2
1
Dead Souls Support / Timezones
« on: January 26, 2012, 06:28:15 PM »
I noticed that some of the time-zones in Dead Souls were wrong, so I decided to do a bit of research and try come up with some sort of definitive list.

An example would be Moscow time which changed on the 27th March 2011 to be UTC+4.

Code: [Select]
# Timezones
#
# <Timezone Abbreviation>:<Offset from UTC in hours>:<Timezone Description>
#
# There are various timezone abbreviations that are replicated for different
# areas. CST is a good example, used in Australia, China and North America.
# How you deal with them is up to you.

LINT:14:Line Islands Time

CHADT:13.75:Chatham Islands Daylight Time

NZDT:13:New Zealand Daylight Time
PHOT:13:Phoenix Islands Time

CHAST:12.75:Chatham Islands Standard Time

IDLE:12:International Date Line East
GILT:12:Gilbert Islands Time
FJT:12:Fiji Time
NZST:12:New Zealand Standard Time
PETT:12:Kamchatka Time
MAGT:12:Magadan Time

NFT:11.5:Norfolk Island Time

AEDT:11:Australian Eastern Daylight Time
SBT:11:Solomon Islands Time
VLAT:11:Vladivostok Time

ACDT:10.5:Australian Central Daylight Time
LHST:10.5:Lord Howe Standard Time

AEST:10:Australian Eastern Standard Time
CHST:10:Chamorro Standard Time
GST:10:Guam Standard Time
YAKT:10:Yakutsk Time

ACST:9.5:Australian Central Standard Time
CST:9.5:Central Standard Time (Australia)

AWDT:9:Australian Western Daylight Time
JST:9:Japan Standard Time
KST:9:Korea Standard Time
IRKT:9:Irkutsk Time

AWST:8:Australian Western Standard Time
WST:8:Western Standard Time (Australia)
SST:8:Singapore Standard Time
SGT:8:Singapore Time
PST:8:Philippine Time
MST:8:Malaysian Standard Time
MYT:8:Malaysia Time
HKT:8:Hong Kong Time
BDT:8:Brunei Time
ACT:8:ASEAN Common Time
CT:8:China Time
CST:8:China Standard Time
KRAT:8:Krasnoyarsk Time

THA:7:Thailand Standard Time
ICT:7:Indochina Time
CXT:7:Christmas Island Time
OMST:7:Omsk Time

CCT:6.5:Cocos Islands Time
MST:6.5:Myanmar Standard Time

BIOT:6:British Indian Ocean Time
BST:6:Bangladesh Standard Time
BTT:6:Bhutan Time
YEKT:6:Yekaterinburg Time

NPT:5.75:Nepal Time

IST:5.5:Indian Standard Time
SLT:5.5:Sri Lanka Time

PKT:5:Pakistan Standard Time
HMT:5:Heard and McDonald Islands Time
AMST:5:Armenia Summer Time

AFT:4.5:Afghanistan Time

RET:4:Réunion Time
SCT:4:Seychelles Time
AZST:4:Azerbaijan Time
GET:4:Georgia Standard Time
AST:4:Arabian Standard Time
AMT:4:Armenia Time
AZT:4:Azerbaijan Time
MUT:4:Mauritius Time
GST:4:Gulf Standard Time
MSK:4:Moskow Time

IRST:3.5:Iran Standard Time

AST:3:Arab Standard Time
AST:3:Arabic Standard Time
EEST:3:Eastern European Summer Time
EEDT:3:Eastern European Daylight Time
EAT:3:East Africa Time
IDT:3:Israeli Daylight Time
USZ1:3:Kaliningrad Time

IST:2:Israel Standard Time
CEST:2:Central European Summer Time
CEDT:2:Central European Daylight Time
CAT:2:Central Africa Time
EET:2:Eastern European Time
SAST:2:South African Standard Time
HAEC:2:Heure Avancée d'Europe Centrale

WEST:1:Western European Summer Time
WAT:1:West Africa Time
DFT:1:AIX specific equivalent of Central European Time
BST:1:British Summer Time
CET:1:Central European Time
IST:1:Irish Summer Time
WEDT:1:Western European Daylight Time

WET:0:Western European Time
GMT:0:Greenwich Mean Time
UTC:0:Coordinated Universal Time

AZOST:-1:Azores Standard Time
CVT:-1:Cape Verde Time

UYST:-2:Uruguay Summer Time
GST:-2:South Georgia and the South Sandwich Islands

NDT:-2.5:Newfoundland Daylight Time

UYT:-3:Uruguay Standard Time
FKST:-3:Falkland Islands Summer Time
GFT:-3:French Guiana Time
BRT:-3:Brasilia Time
CLST:-3:Chile Summer Time
ART:-3:Argentina Time
ADT:-3:Atlantic Daylight Time

NST:-3.5:Newfoundland Standard Time
NT:-3.5:Newfoundland Time

BOT:-4:Bolivia Time
FKT:-4:Falkland Islands Time
EDT:-4:Eastern Daylight Time (North America)
GYT:-4:Guyana Time
AST:-4:Atlantic Standard Time
COST:-4:Colombia Summer TimeColombia Summer Time
ECT:-4:Eastern Caribbean Time (does not recognise DST)
CLT:-4:Chile Standard Time

VET:-4.5:Venezuelan Standard Time

ECT:-5:Ecuador Time
EST:-5:Eastern Standard Time (North America)
CDT:-5:Central Daylight Time (North America)
COT:-5:Colombia Time

EAST:-6:Easter Island Standard Time
GALT:-6:Galapagos Time
MDT:-6:Mountain Daylight Time (North America)
CST:-6:Central Standard Time (North America)

MST:-7:Mountain Standard Time (North America)
PDT:-7:Pacific Daylight Time (North America)

CIST:-8:Clipperton Island Standard Time
PST:-8:Pacific Standard Time (North America)
AKDT:-8:Alaska Daylight Time

HADT:-9:Hawaii-Aleutian Daylight Time
AKST:-9:Alaska Standard Time
GIT:-9:Gambier Island Time

MIT:-9.5:Marquesas Islands Time

HAST:-10:Hawaii-Aleutian Standard Time
CKT:-10:Cook Island Time
TAHT:-10:Tahiti Time
HST:-10:Hawaii Standard Time

SST:-11:Samoa Standard Time

BIT:-12:Baker Island Time
IDLW:-12:International Date Line West

# Timezones based on Moscow time.
MSK+8:12:Magadan Time
MSK+7:11:Vladivostok Time
MSK+6:10:Yakutsk Time
MSK+5:9:Irkutsk Time
MSK+4:8:Krasnoyarsk Time
MSK+3:7:Omsk Time
MSK+2:6:Yekaterinburg Time
MSK-1:3:Kaliningrad Time

I hope this is some sort of use to someone.

Tricky

2
Code Vault / Singularize and Pluralize sefuns...
« on: January 02, 2012, 02:38:19 PM »
I extended my singularize code to also do pluralize. It uses the same format as the singularize exception file and therefore is quite flexible.

Again the the format of the code has changed, but the configuration files have stayed the same.

License: See my sig below.

Code: (sefun code) [Select]
/* parser.c
 *
 * Tricky @ LPUniversity
 * 27-DEC-2011
 * simul_efun
 *
 */

/* This is from my global.h file. */
#ifdef __SENSIBLE_MODIFIERS__
#define privatef protected
#define privatev nosave

#define staticf protected
#define staticv nosave
#else
#define privatef static
#define privatev static

#define staticf static
#define staticv static

/* Just in-case someone really wants to use these. */
#define protected private
#define nosave    static
#endif

/* Where to find the exception file for singularize(). */
#define S_EXCEPTIONS "/path/to/singularize.conf"

/* Where to find the exception file for pluralize(). */
#define P_EXCEPTIONS "/path/to/pluralize.conf"

privatev mapping Exceptions = ([
  "singularize": ([
    "is": ({ "*", "are" }),
    "blues": ({ 0, "" }),
    "bonuses": ({ 2, "" }),
    "buses": ({ 2, "" }),
    "children": ({ 3, "" }),
    "dice": ({ 2, "e" }),
    "dies": ({ 1, "" }),
    "feet": ({ 3, "oot" }),
    "geese": ({ 4, "oose" }),
    "has": ({ 1, "ve" }),
    "indices": ({ 4, "ex" }),
    "lice": ({ 3, "ouse" }),
    "lotuses": ({ 2, "" }),
    "matrices": ({ 3, "x" }),
    "mice": ({ 3, "ouse" }),
    "monies": ({ 3, "ey" }),
    "oxen": ({ 2, "" }),
    "pants": ({ 0, "" }),
    "remains": ({ 0, "" }),
    "staves": ({ 3, "ff" }),
    "teeth": ({ 4, "ooth" }),
    "thieves": ({ 3, "f" }),
    "vaxen": ({ 2, "" }),
    "vertices": ({ 4, "ex" }),
    "viruses": ({ 2, "" }),
    "were": ({ 3, "as" }),
  ]),
  "pluralize": ([
    "are": ({ "*", "is" }),
    "blues": ({ 0, "" }),
    "bonus": ({ 0, "es" }),
    "bus": ({ 0, "es" }),
    "child": ({ 0, "ren" }),
    "die": ({ 1, "ce" }),
    "foot": ({ 3, "eet" }),
    "goose": ({ 4, "eese" }),
    "have": ({ 2, "s" }),
    "index": ({ 2, "ices" }),
    "lotus": ({ 0, "es" }),
    "louse": ({ 4, "ice" }),
    "matrix": ({ 1, "ces" }),
    "money": ({ 2, "ies" }),
    "mouse": ({ 4, "ice" }),
    "ox": ({ 0, "en" }),
    "pants": ({ 0, "" }),
    "remains": ({ 0, "" }),
    "staff": ({ 2, "ves" }),
    "thief": ({ 1, "ves" }),
    "tooth": ({ 4, "eeth" }),
    "vax": ({ 0, "en" }),
    "vertex": ({ 2, "ices" }),
    "virus": ({ 0, "es" }),
    "was": ({ 2, "ere" }),
  ])
]);

privatev mapping re_Exceptions = ([
  "singularize": ({
    ([ "re": ".*s'", "cut": 1, "suffix": "" ]),
    ([ "re": ".*s's", "cut": 2, "suffix": "" ]),
    ([ "re": ".*[aeiou]ss", "cut": 0, "suffix": "" ]),
    /* 'es' endings. */
    ([ "re": ".*[cglpt]es", "cut": 1, "suffix": "" ]),
    ([ "re": ".*ies", "cut": 3, "suffix": "y" ]),
    ([ "re": ".*oes", "cut": 2, "suffix": "" ]),
    /* Vowel before 'ses'. */
    ([ "re": ".*[aeiou]ses", "cut": 1, "suffix": "" ]),
    /* Otherwise no vowel. */
    ([ "re": ".*ses", "cut": 2, "suffix": "" ]),
    /* Vowel before 'ves'. */
    ([ "re": ".*[aeiou]ves", "cut": 1, "suffix": "" ]),
    /* Otherwise no vowel. */
    ([ "re": ".*ves", "cut": 3, "suffix": "" ]),
    ([ "re": ".*men", "cut": 2, "suffix": "an" ]),
    /* Has to be last! */
    ([ "re": ".*s", "cut": 1, "suffix": "" ]),
  }),
  "pluralize": ({
    ([ "re": ".*[aeiou]ss", "cut": 0, "suffix": "" ]),
    ([ "re": ".*[os]", "cut": 0, "suffix": "es" ]),
    ([ "re": ".*[cglpt]e", "cut": 0, "suffix": "s" ]),
    ([ "re": ".*y", "cut": 1, "suffix": "ies" ]),
    ([ "re": ".*[aeiou]ve", "cut": 0, "suffix": "s" ]),
    ([ "re": ".*man", "cut": 2, "suffix": "en" ]),
    ([ "re": ".*ma", "cut": 0, "suffix": "s" ]),
    ([ "re": ".*a", "cut": 0, "suffix": "e" ]),
    ([ "re": ".*um", "cut": 2, "suffix": "a" ]),
    ([ "re": ".*on", "cut": 2, "suffix": "a" ]),
    ([ "re": ".*us", "cut": 0, "suffix": "es" ]),
  })
]);

privatev mixed *ExceptionsLoaded = ({ });

/* This function is private to the simul efun object. */
varargs privatef int f_load_Exceptions(string fname, string tag) {
  if (!stringp(tag) || tag == "") tag = "__EXCEPTION__";

  if (file_size(fname) > 0 && member_array(tag, ExceptionsLoaded) == -1) {
    string array lines;
    string exceptions;
    int re = 0;

    /* Initialize the private vars. */
    if (!mapp(Exceptions)) Exceptions = ([ ]);
    if (!mapp(re_Exceptions)) re_Exceptions = ([ ]);
    if (!arrayp(ExceptionsLoaded)) ExceptionsLoaded = ({ });

    /* Reset the Exception tags. */
    Exceptions[tag] = ([ ]);
    re_Exceptions[tag] = ({ });
    ExceptionsLoaded += ({ tag });

    exceptions = read_file(fname);
    lines = explode(exceptions, "\n");

    /* Ignore empty lines and '#' remarks. */
    lines = filter(lines, (: $1[0..0] != "#" && sizeof(trim($1)) :) );

    foreach (string line in lines) {
      string s_plural, s_cut, s_suffix;
      int ret;

      line = trim(line);
      ret = sscanf(line, "%s%*([ \t]+)%s%*([ \t]+)%s", s_plural, s_cut, s_suffix);

      if (s_plural[0..0] == "R") {
        re_Exceptions[tag] += ({ allocate_mapping(3) });
        re_Exceptions[tag][re]["re"] = s_plural[1..<1];

        if (ret == 1) {
          re_Exceptions[tag][re]["cut"] = 0;
          re_Exceptions[tag][re]["suffix"] = "";
        } else if (ret == 3) {
          re_Exceptions[tag][re]["cut"] = to_int(s_cut);
          re_Exceptions[tag][re]["suffix"] = "";
        } else if (ret == 5) {
          if (s_cut != "*")
            re_Exceptions[tag][re]["cut"] = to_int(s_cut);
          else
            re_Exceptions[tag][re]["cut"] = "*";

          re_Exceptions[tag][re]["suffix"] = s_suffix;
        }

        re++;
      } else {
        if (!mapp(Exceptions[tag][s_plural])) Exceptions[tag][s_plural] = allocate(2);

        if (ret == 1) {
          Exceptions[tag][s_plural][0] = 0;
          Exceptions[tag][s_plural][1] = "";
        } else if (ret == 3) {
          Exceptions[tag][s_plural][0] = to_int(s_cut);
          Exceptions[tag][s_plural][1] = "";
        } else if (ret == 5) {
          if (s_cut != "*")
            Exceptions[tag][s_plural][0] = to_int(s_cut);
          else
            Exceptions[tag][s_plural][0] = "*";

          Exceptions[tag][s_plural][1] = s_suffix;
        }
      }
    }
  }

  /* Did we load the configuration file? */
  return (member_array(tag, ExceptionsLoaded) != -1);
}

/* This can be used to check contents of the Exceptions. */
mapping query_Exceptions() { return copy(Exceptions); }
mapping query_re_Exceptions() { return copy(re_Exceptions); }
mixed array query_ExceptionsLoaded() { return copy(ExceptionsLoaded); }

string singularize(string str) {
  mixed array exception;
  string array tmp_arr;
  string tmp = "", pre = "", plural = "", post = "", single = "";

  str = trim(str);

  if (str == "") return "";

  /* Don't really care about the return value. */
  f_load_Exceptions(S_EXCEPTIONS, "singularize");

  /* Same rules apply as in efun::pluralize. 'X of Y' -> 'X' is singularized. */
  if (sscanf(str, "%s of %s", plural, post) != 2) plural = str;
  else post = " of " + post;

  tmp_arr = explode(plural, " ");

  /* Pick out the last word on the line. */
  plural = tmp_arr[<1];
  tmp = lower_case(plural);

  if (sizeof(tmp_arr) > 1) pre = implode(tmp_arr[0..<2], " ");

  /* Check the Exceptions mapping. */
  exception = Exceptions["singularize"][tmp];

  /* If not found then check the regular expressions. */
  if (!arrayp(exception)) {
    int re, sz;

    sz = sizeof(re_Exceptions["singularize"]);

    for (re = 0 ; re < sz ; re++) {
      string s_re = re_Exceptions["singularize"][re]["re"];

      if (regexp(tmp, "^" + s_re + "$")) {
        exception = ({
          re_Exceptions["singularize"][re]["cut"],
          re_Exceptions["singularize"][re]["suffix"]
        });
        break;
      }
    }
  }

  /* If we have found an exception then apply it. */
  if (arrayp(exception)) {
    mixed cut = exception[0];
    string suffix = exception[1];

    if (intp(cut) && cut == 0 && stringp(suffix) && suffix == "") {
      single = tmp;
    } else if (stringp(cut) && cut == "*") {
      single = suffix;
    } else {
      single = tmp;

      /* Cut out the required number of letters from the end. */
      if (intp(cut) && cut != 0) {
        int len = strlen(single);

        single = single[0..(len - 1) - cut];
      }

      /* Add on the suffix if available. */
      if (suffix != "") single += suffix;
    }
  }

  /* No exception found so just return the original. */
  if (single == "") single = tmp;

  if (pre != "") pre += " ";
  if (plural != tmp) single = capitalize(single);

  /* Stitch everything together. */
  return pre + single + post;
}

/* Overrides the driver's efun. */
string pluralize(string str) {
  mixed array exception;
  string array tmp_arr;
  string tmp = "", pre = "", singular = "", post = "", single = "";

  str = trim(str);

  if (str == "") return "";

  /* Don't really care about the return value. */
  f_load_Exceptions(P_EXCEPTIONS, "pluralize");

  /* Same rules apply as in efun::pluralize. 'X of Y' -> 'X' is pluralized. */
  if (sscanf(str, "%s of %s", singular, post) != 2) singular = str;
  else post = " of " + post;

  tmp_arr = explode(singular, " ");

  /* Pick out the last word on the line. */
  singular = tmp_arr[<1];
  tmp = lower_case(singular);

  if (sizeof(tmp_arr) > 1) pre = implode(tmp_arr[0..<2], " ");

  /* Check the Exceptions mapping. */
  exception = Exceptions["pluralize"][tmp];

  /* If not found then check the regular expressions. */
  if (!arrayp(exception)) {
    int re, sz;

    sz = sizeof(re_Exceptions["pluralize"]);

    for (re = 0 ; re < sz ; re++) {
      string s_re = re_Exceptions["pluralize"][re]["re"];

      if (regexp(tmp, "^" + s_re + "$")) {
        exception = ({
          re_Exceptions["pluralize"][re]["cut"],
          re_Exceptions["pluralize"][re]["suffix"]
        });
        break;
      }
    }
  }

  /* If we have found an exception then apply it. */
  if (arrayp(exception)) {
    mixed cut = exception[0];
    string suffix = exception[1];

    if (intp(cut) && cut == 0 && stringp(suffix) && suffix == "") {
      single = tmp;
    } else if (stringp(cut) && cut == "*") {
      single = suffix;
    } else {
      single = tmp;

      /* Cut out the required number of letters from the end. */
      if (intp(cut) && cut != 0) {
        int len = strlen(single);

        single = single[0..(len - 1) - cut];
      }

      /* Add on the suffix if available. */
      if (suffix != "") single += suffix;
    }
  }

  /* No exception found so add on an 's'. */
  if (single == "") single = tmp + "s";

  if (pre != "") pre += " ";
  if (singular != tmp) single = capitalize(single);

  /* Stitch everything together. */
  return pre + single + post;
}

Code: (singularize.conf) [Select]
# Exception file for singuralize.
#
# File format
# ===========
# <plural> <cut> <suffix>
#
# Fields
# ======
# plural - The plural word to singularize.
# cut - Number of characters to cut off the end.
#   A '*' indicates change everything.
#   A blank entry indicates no change.
# suffix - The suffix to add on the end.
#   A blank entry indicates no suffix.
#
# If the plural field begins with an upper-case 'R' then the rest
# of the field is a regexp string which will be encased in ^ $
# The order of the expressions IS significant.

# Whitespace is tolerated at the start and end of the lines.

# This list does not have to be in alphabetical order and is by
# no means complete.

# If the whole plural word will change then use a '*' in the cut field.
# For instance 'is' changes to 'are'
is * are
kine * cow
kye * cow

# All 3 of these for octopus are correct.
# See http://en.wikipedia.org/wiki/Octopus#Etymology_and_pluralization
#
# The original and most commonly used.
octopuses 2
# Greek. Correct but rarely used.
octopodes 4 us
# Latin. Incorrect. NB: the efun pluralize returns this for octopus.
octopi 1 us

# Original Latin word for octopus is polypus from the Greek polypous.
# Greek. The correct usage.
polypodes 4 us
# Latin. Incorrect. NB: the efun pluralize returns this for polypus.
polypi 1 us

# Again for platypus. This is a Greek word not Latin.
# Biologist version. Like sheep and fish.
platypus
# Most commonly used by scientists and laypersons.
platypuses 2
# Latin. Incorrect. NB: the efun pluralize returns this for platypus.
platypi 1 us
# Greek form but not well-attested.
platypodes 4 us

# Botanical Latin.
# Other forms of cactus plural are handled elsewhere.
cactuses 2

# These I never knew about.
opera 3 us
sphinges 3 x

# Medical term.
phalanges 3 x
# Military term.
phalanxes 2

# Technically this is correct if a little confusing.
# Second version is the stamp used for molding.
# Remember pluralizing die will return dice.
dice 2 e
dies 1

# Latin or Greek. Can never remember.
bacteria 1 um
consortia 1 um
data 1 um
fora 1 um
media 1 um
millenia 1 um
spectra 1 um
symposia 1 um
corpora 3 us
genera 3 us
loti 1 us
viscera 3 us

# Remember pluralizing virus will return 'viruses'
# The correct form when used for biological infectious agents.
viruses 2
# As in computer virus. Not generally used anymore.
# See http://www.ofb.net/~jlm/virus.html
viri 1 us
virii 2 us

# No change between plural and singular.
benshi
bison
blues
cattle
clothes
deer
fish
glasses
measles
moose
news
otaku
pants
pike
remains
salmon
samurai
series
sheep
species
swine
# thanks
trout

# Balls.
billiard
# The game.
billiards

# No suffix to add on. Just cut off some letters.
appendixes 2
atlases 2
boxen 2
buses 2
bonuses 2
canoes 1
censuses 2
children 3
eyen 1
giraffes 1
hippopotamuses 2
housen 1
hosen 1
insignias 1
lotuses 2
operas 1
oxen 2
prospectuses 2
syllabuses 2
terminuses 2
unixes 2
uteruses 2
vaxen 2

# Cut off some letters and add on the suffix.
indices 4 ex
vertices 4 ex

crises 2 is
testes 2 is

geese 4 oose
mongeese 4 oose

lice 3 ouse
mice 3 ouse

atlantes 4 s
elvii 1 s

appendices 3 x
matrices 3 x
unices 3 x

brethren 6 other
sistren 3 er

panini 1 o
insignia 2 e
feet 3 oot
has 1 ve
monies 3 ey
shoon 2 e
staves 3 ff
thieves 3 f
teeth 4 ooth
were 3 as

# This will try to catch anything else.
# Remember that the order is significant.
# Regex (NOT PCRE) plural search.
R.*s' 1
R.*s's 2
R.*[aeiou]ss

# 'es' endings.
R.*[cglpt]es 1
R.*ies 3 y
R.*oes 2
# Vowel before 'ses'.
R.*[aeiou]ses 1
# Otherwise no vowel.
R.*ses 2
# Vowel before 'ves'.
R.*[aeiou]ves 1
# Otherwise no vowel.
R.*ves 3

R.*men 2 an
R.*mata 2
R.*mas 1

R.*da 1 um
R.*ra 1 um
# Needs to be after 'da' and 'ra'.
R.*a 1 on
R.*das 2 um
R.*ras 2 um

R.*ae 1

R.*[tz]i 1 o

# See octopus, polypus and platypus above.
# These will catch some common Latin plurals.
R.*us
R.*ii 2 us
# Needs to be after 'ii'.
R.*i 1 us

# French origin.
R.*eau[sx] 1

# Inuktitut orign.
R.*uit 2 k

# Has to be last!
R.*s 1

Code: (pluralize.conf) [Select]
# Exception file for pluralize.
#
# File format
# ===========
# <singular> <cut> <suffix>
#
# Fields
# ======
# singular - The singular word to pluralize.
# cut - Number of characters to cut off the end.
#   A '*' indicates change everything.
#   A blank entry indicates no change.
# suffix - The suffix to add on the end.
#   A blank entry indicates no suffix.
#
# If the singular field begins with an upper-case 'R' then the rest
# of the field is a regexp string which will be encased in ^ $
# The order of the expressions IS significant.

# Whitespace is tolerated at the start and end of the lines.

# This list does not have to be in alphabetical order and is by
# no means complete.

# If the whole singular word will change then use a '*' in the cut field.
# For instance 'are' changes to 'is'
are * is

# See http://en.wikipedia.org/wiki/Octopus#Etymology_and_pluralization
#
# The original and most commonly used.
octopus 0 es

# Original Latin word for octopus is polypus from the Greek polypous.
# Greek. The correct usage.
polypus 2 odes

# Again for platypus. This is a Greek word not Latin.
# Most commonly used by scientists and laypersons.
platypus 0 es

# Botanical Latin.
cactus

# These I never knew about.
opus 2 era
sphinx 1 ges

# Pick which one you want to use.
# Military term.
phalanx 0 es
# Medical term.
# phalanx 1 ges

# Replace with the second form if that is required.
die 1 ce
# die 0 s

# Latin or Greek. Can never remember.
consortium 2 a
datum 2 a
forum 2 a
medium 2 a
millenium 2 a
spectrum 2 a
symposium 2 a
corpus 2 ora
genus 2 era
viscus 2 era

# The correct form when used for biological infectious agents.
# See http://www.ofb.net/~jlm/virus.html
virus 0 es

# Joke Latin form.
elvis 1 i

# No change between singular and plural.
benshi
bison
blues
cattle
clothes
deer
fish
glasses
measles
moose
news
otaku
pants
pike
remains
salmon
samurai
series
sheep
species
swine
thanks
trout

# Balls.
billiard
# The game.
billiards

# Just add a suffix.
atlas 0 es
box 0 en
bus 0 es
bonus 0 es
census 0 es
child 0 ren
giraffe 0 s
hippopotamus 0 es
human 0 s
igloo 0 s
kangaroo 0 s
lotus 0 es
ox 0 en
pizza 0 s
prospectus 0 es
syllabus 0 es
terminus 0 es
unix 0 es
uterus 0 es
vax 0 en

# Cut of some letters and add a suffix.
appendix 1 ces
matrix 1 ces

index 2 ices
vertex 2 ices

crisis 2 es
testis 2 es

goose 4 eese

louse 4 ice
mouse 4 ice

staff 2 ves
thief 1 ves

panino 1 i
opera 0 s
insigne 1 ia
insignia 0 s
foot 3 eet
have 2 s
money 2 ies
tooth 4 eeth
was 2 ere

# This will try to catch anything else.
# Remember that the order is significant.
# Regex (NOT PCRE) singular search.

R.*[aeiou]ss
R.*[tz]o 1 i
R.*[os] 0 es
R.*[cglpt]e 0 s
R.*y 1 ies
R.*[aeiou]ve 0 s
R.*man 2 en
R.*ma 0 s
R.*a 0 e
R.*um 2 a
R.*on 2 a
R.*us 0 es
R.*eau 0 x
R.*uk 1 it

Tricky

3
Code Vault / Singularize function.
« on: December 30, 2011, 03:11:56 AM »
The other day I noted someone on I3 mentioning that the efun singularize() does not exist.

This is something I created a few years ago and should really be in the driver as an efun. This also goes for the trim(), ltrim() and rtrim() functions.

Place this in any directory you think appropriate.
Code: (plural_exceptions) [Select]
# Plural Exception file for singuralize.
#
# The singularize function uses a hashing technique based on the first
# letter of the plural word.
#
# *<plural> <singular>
# Indicates that the 'singular' word does NOT start with the same
# letter as the 'plural' word and therefore should be replaced entirely.
#
# <plural> <new suffix>
# The 'new suffix' is added onto the starting letter
# of the 'plural' word.
#
# Whitespace is tolerated at the start and end of the lines.

# If the whole plural word will change then prefix it with a '*'
# For instance 'is' changes to 'are'
*is are

# All 3 of these are correct.
# See http://en.wikipedia.org/wiki/Octopus#Etymology_and_pluralization
#
# The original and most commonly used.
octopuses ctopus
# Greek. Correct but rarely used.
octopodes ctopus
# Latin. Incorrect. NB: pluralize returns this for octopus.
octopi ctopus

# Original Latin word for octopus is polypus from the Greek polypous.
# Greek. The correct usage.
polypodes olypus
# Latin. Incorrect. NB: pluralize returns this for polypus.
polypi olypus

# These I never knew about.
opus pera
sphinges phinx

# Technically this is correct if a little confusing.
# Second version is the stamp used for molding.
# Remember pluralizing die will return dice.
dice ie
dies ie

# Latin or Greek. Can never remember.
data atum
fora orum

# Remember pluralizing virus will return 'viruses'
# The correct form when used for biological infectious agents.
viruses irus
# As in computer virus.
viri irus
virii irus

# These are general exceptions. It is by no means complete.
# This list does not have to be in alphabetical order.
blues lues
buses us
bonuses onus
children hild
feet oot
geese oose
giraffes iraffe
glasses lasses
has ave
indices ndex
lice ouse
lotuses otus
monies oney
mice ouse
matrices atrix
oxen x
pants ants
remains emains
staves taff
thieves hief
teeth ooth
vertices ertex
vaxen ax
were as

I place this in my sefun directory and make sure that the lib is aware of it. Remember to change the #define to point to the full file path of the plural_exceptions file.
Code: (singularize functions) [Select]
/* trim() is used in the singularize functions so I have included their definitions here. */

/* Similar to the PHP function ltrim */
varargs string ltrim(string line, string charlist) {
  string *whitelist;

  if (!stringp(line) || !sizeof(line)) return "";

  if (undefinedp(charlist)) whitelist = ({ " ", "\t", "\n", "\r" });
  else whitelist = explode(charlist, "");

  while (1) {
    if (!sizeof(line)) break;

    if (member_array(line[0..0], whitelist) == -1) break;
    else line = line[1..<1];
  }

  return line;
}

/* Similar to the PHP function rtrim */
varargs string rtrim(string line, string charlist) {
  string *whitelist;

  if (!stringp(line) || !sizeof(line)) return "";

  if (undefinedp(charlist)) whitelist = ({ " ", "\t", "\n", "\r" });
  else whitelist = explode(charlist, "");

  while (1) {
    if (!sizeof(line)) break;

    if (member_array(line[<1..<1], whitelist) == -1) break;
    else line = line[0..<2];
  }

  return line;
}

/* Similar to the PHP function trim */
varargs string trim(string line, string charlist) {

  if (!stringp(line) || !sizeof(line)) return "";

  line = ltrim(line, charlist);
  line = rtrim(line, charlist);

  return line;
}

/* Where to find the plural_exception file. */
#define PLURAL_EXCEPTIONS "/path/to/plural_exceptions"

nosave mapping pluralExceptions = ([ ]);
nosave int pe_map_loaded = 0;

protected int f_load_pluralExceptions(string fname) {
  if (file_size(fname) > 0 && !pe_map_loaded) {
    string array lines;
    string pe;

    pluralExceptions = ([ ]);
    pe_map_loaded = 1;

    pe = read_file(fname);
    lines = explode(pe, "\n");
    lines = filter(lines, (: $1[0..0] != "#" && sizeof(trim($1)) :) );

    foreach (string line in lines) {
      string plural_word, singular_word;

      sscanf(line, "%s%*([ \t]+)%s", plural_word, singular_word);

      if (plural_word[0] == '*') {
        if (!mapp(pluralExceptions["*"])) pluralExceptions["*"] = ([ ]);

        pluralExceptions["*"] += ([ plural_word[1..<1]: singular_word ]);
      } else {
        if (!mapp(pluralExceptions[plural_word[0..0]])) pluralExceptions[plural_word[0..0]] = ([ ]);

        pluralExceptions[plural_word[0..0]] += ([ plural_word[1..<1]: singular_word ]);
      }
    }
  }

  return pe_map_loaded;
}

/* This can be used to check contents of the mapping. */
mapping query_pluralExceptions() { return copy(pluralExceptions); }

string singularize(string str) {
  mapping exceptions;
  string array tmp_arr;
  string array vowels = ({ "a", "e", "i", "o", "u" });
  string tmp = "", pre = "", plural = "", rest = "", single = "";
  int found = 0;

  if (!f_load_pluralExceptions(PLURAL_EXCEPTIONS)) {
    /* If we don't have a file of exceptions then we use the default set. */
    pluralExceptions = ([
      "*": ([ "is": "are" ]),
      "b": ([ "uses": "us", "onuses": "onus", ]),
      "c": ([ "hildren": "hild", ]),
      "d": ([ "ice": "ie", "ies": "ie", ]),
      "f": ([ "eet": "oot", ]),
      "g": ([ "eese": "oose", ]),
      "h": ([ "as": "ave", ]),
      "i": ([ "ndices": "ndex", ]),
      "l": ([ "ice": "ouse", "otuses": "otus", ]),
      "m": ([ "onies": "oney", "ice": "ouse", "atrices": "atrix", ]),
      "o": ([ "xen": "x", ]),
      "p": ([ "ants": "ants", ]),
      "r": ([ "emains": "emains", ]),
      "s": ([ "taves": "taff", ]),
      "t": ([ "hieves": "hief", "eeth": "ooth", ]),
      "v": ([ "ertices": "ertex", "axen": "ax", "iruses": "irus", ]),
      "w": ([ "ere": "as", ]),
    ]);
  }

  str = trim(str);

  if (str == "") return "";

  /* Same rules apply as in pluralize. 'X of Y' -> 'X' is singularized. */
  if (sscanf(str, "%s of %s", plural, rest) != 2) plural = str;
  else rest = " of " + rest;

  tmp_arr = explode(plural, " ");

  /* Pick out the last word on the line. */
  plural = tmp_arr[<1];
  tmp = lower_case(plural);

  if (sizeof(tmp_arr) > 1) pre = implode(tmp_arr[0..<2], " ");

  /* Check the pluralExceptions mapping. */
  exceptions = pluralExceptions["*"];

  if (mapp(exceptions) && stringp(exceptions[tmp])) {
    single = exceptions[tmp];
    found = 1;
  } else {
    exceptions = pluralExceptions[tmp[0..0]];

    if (mapp(exceptions) && stringp(exceptions[tmp[1..<1]])) {
      single = tmp[0..0] + exceptions[tmp[1..<1]];
      found = 1;
    }
  }

  /* Try to guess what it should be if nothing has been found so far. */
  if (!found) {
    if (tmp[<2..<1] == "s'")
      single = tmp[0..<2];
    else if (tmp[<3..<1] == "s's")
      single = tmp[0..<3];
    else if (tmp[<2..<1] == "ss" && member_array(tmp[<3..<3], vowels) != -1)
      single = tmp;
    else if (tmp[<3..<1] == "ies")
      single = tmp[0..<4] + "y";
    else if (tmp[<3..<1] == "ves") {
      if (member_array(tmp[<4..<4], vowels) != -1)
        single = tmp[0..<4] + "ve";
      else
        single = tmp[0..<4] + "f";
    } else if (tmp[<3..<1] == "oes")
      single = tmp[0..<3];
    else if (   tmp[<2..<1] == "ae"
             || tmp[<3..<1] == "pes"
             || tmp[<3..<1] == "ges"
             || tmp[<3..<1] == "tes"
             || tmp[<3..<1] == "ces"
             || tmp[<3..<1] == "les")
      single = tmp[0..<2];
    else if (tmp[<3..<1] == "ses") {
      if (member_array(tmp[<4..<4], vowels) != -1)
        single = tmp[0..<2];
      else
        single = tmp[0..<3];
    } else if (tmp[<2..<1] == "es") {
      if (   member_array(tmp[0..0], vowels) != -1
          || member_array(tmp[<4..<4], vowels) != -1
          || member_array(tmp[<3..<3], vowels) != -1)
        single = tmp[0..<2];
      else
        single = tmp[0..<3];
    } else if (tmp[<3..<1] == "men")
      single = tmp[0..<3] + "an";
    else if (tmp[<1..<1] == "s")
      single = tmp[0..<2];
    else single = tmp;
  }

  /* Stitch everything together. */
  if (pre != "") pre += " ";
  if (plural != tmp) single = capitalize(single);

  return pre + single + rest;
}

Tricky

4
Design Lab / Timing test
« on: October 13, 2009, 09:17:12 PM »
I'd like you test this code for me. Report back with results and platforms + mudlibs and drivers used.

Hint for DS users, change int main(string args) to int cmd(string args)

Place in your command path and type, timetest

Code: (timetest.c) [Select]
#define TIMEMAX 250000

/* Taken from Dead Souls lib. */
string RateScore(int i)
{
    string ret;

    if (!i) ret = "No score available.";
    else if (i < 51) ret = "Spectacular.";
    else if (i < 101) ret = "Excellent.";
    else if (i < 201) ret = "Very good.";
    else if (i < 301) ret = "Good.";
    else if (i < 401) ret = "Fair.";
    else if (i < 501) ret = "Poor.";
    else if (i < 601) ret = "Very poor.";
    else if (i < 701) ret = "Bad.";
    else ret = "Execrable.";

    return ret;
}

int main(string args)
{
#ifdef __HAS_RUSAGE__
    mapping before, after;
#endif
    float r;
    int l, a, t;

/* Start time_expression { } test. */
    l = 1;
    t = 0;

    while (t < TIMEMAX)
    {
        a = l;

        t = time_expression
        {
            while (l--) { }
        };

        if (t < TIMEMAX)
            l = a * 2;
    }

    r = to_float(t) / to_float(a);

    printf("*** START TEST ***\n");
    printf("time_expression {} test...\n");
    printf("loops done = %i\n" ,a);
    printf("time taken = %i us\n", t);
    printf("ratio = %.3f (time taken / loops done)\n", r);
    printf("Rating: %s\n", RateScore(to_int(r * 1000)));

#ifdef __HAS_RUSAGE__
/* Start rusage() test. */
    l = 1;
    t = 0;

    while (t < TIMEMAX)
    {
        a = l;
        before = rusage();

        while (l--) { }

        after = rusage();
        t = (after["utime"] - before["utime"]) * 1000;

        if (t < TIMEMAX)
            l = a * 2;
    }

    r = to_float(t) / to_float(a);

    printf("*** START TEST ***\n");
    printf("rusage() test...\n");
    printf("loops done = %i\n" ,a);
    printf("time taken = %i us\n", t);
    printf("ratio = %.3f (time taken / loops done)\n", r);
    printf("Rating: %s\n", RateScore(to_int(r * 1000)));
#endif

    return 1;
}

Thankyou,

Tricky

5
Code Vault / A JSON to LPC convertor.
« on: August 25, 2009, 07:54:57 PM »
Code: [Select]
/*
 * json.c
 *
 * mixed processJSON(string message)
 *
 * Creates an LPC variable from a JSON message.
 * Input: A JSON message.
 * Return: An LPC variable.
 */

#define STRING "\"([^\"\n])*\""
#define NUMBER "[0-9]+"
#define LITERAL "(false|null|true)"
#define NAME_SEPARATOR ":"
#define VALUE_SEPARATOR ","
#define ARRAY_BEGIN "[[]"
#define ARRAY_END "[]]"
#define OBJECT_BEGIN "{"
#define OBJECT_END "}"
#define WS "( |\t|\r|\n)+"

#define TOK_DEFAULT 0
#define TOK_STRING 1
#define TOK_NUMBER 2
#define TOK_LITERAL 3
#define TOK_NAME_SEPARATOR 4
#define TOK_VALUE_SEPARATOR 5
#define TOK_ARRAY_BEGIN 6
#define TOK_ARRAY_END 7
#define TOK_OBJECT_BEGIN 8
#define TOK_OBJECT_END 9
#define TOK_WS 10

mixed processJSON(string message)
{
    mixed *assoc;
    string tmp = "";
    int i, sz;

    assoc = reg_assoc(
        message,
        ({
            STRING,
            NUMBER,
            LITERAL,
            NAME_SEPARATOR,
            VALUE_SEPARATOR,
            ARRAY_BEGIN,
            ARRAY_END,
            OBJECT_BEGIN,
            OBJECT_END,
            WS,
        }),
        ({
            TOK_STRING,
            TOK_NUMBER,
            TOK_LITERAL,
            TOK_NAME_SEPARATOR,
            TOK_VALUE_SEPARATOR,
            TOK_ARRAY_BEGIN,
            TOK_ARRAY_END,
            TOK_OBJECT_BEGIN,
            TOK_OBJECT_END,
            TOK_WS,
        }),
        TOK_DEFAULT
    );

    sz = sizeof(assoc[0]);

    for (i = 0 ; i < sz ; i++)
    {
        switch (assoc[1][i])
        {
            /* No idea what to do with this currently. */
            /* Convert into a string and leave for the programmer to translate. */
            case TOK_LITERAL:
                assoc[0][i] = "\"" + assoc[0][i] + "\"";
                break;
            case TOK_ARRAY_BEGIN:
                assoc[0][i] = "({";
                break;
            case TOK_ARRAY_END:
                assoc[0][i] = ",})";
                break;
            case TOK_OBJECT_BEGIN:
                assoc[0][i] = "([";
                break;
            case TOK_OBJECT_END:
                assoc[0][i] = ",])";
                break;
            case TOK_DEFAULT:
                /* Basically an illegal literal so we turn it into a string. */
                if (assoc[0][i] != "")
                    assoc[0][i] = "\"" + assoc[0][i] + "\"";

                break;
            case TOK_WS:
                assoc[0][i] = "";
                break;
        }

        tmp += assoc[0][i];
    }

    return restore_variable(tmp);
}

void test()
{
    string message = @JSON_MSG
{
    "facebook_url": "http://www.facebook.com/sharer.php?u=http://0.gp/bZO",
    "stat_url": "http://0.gp/bZO+",
    "twitter_url": "http://twitter.com/home?status=http://0.gp/bZO",
    "error":
    {
        "msg": "OK",
        "code": 0
    },
    "url": "http://0.gp/bZO",
    "target_host": "ebspso.dnsalias.org",
    "host": "http://0.gp/"
}
JSON_MSG;

    printf("%s\n\n", message);
    printf("%O\n", processJSON(message));
}

Tricky

6
Code Vault / Name generator
« on: September 23, 2008, 03:28:14 PM »
The other day I decided to code a sefun that created a name that could be pronounced more easily by my self. This is the result.

To use, place the file in the sefun directory and #include it in /secure/sefun/sefun.c (DS lib), update /secure/sefun/sefun. Now it is ready to use.

generate_name(pair, num, ind);

The parameters are all optional.

 * pair - Which of the letter-pair sets to use. (0 - 4)
 * num - Which of the 8 sets of generated names to use. (1 - 8)
 * ind - Which name to use. (0 - 255)

The function returns a capitalized name.

Code: [Select]
/* /secure/sefun/names.c
 *
 * A general purpose name generator based on digraphs/letter-pairs.
 *
 * The original concept comes from the space trading game Elite.
 * Ian Bell (one of the original coders of Elite) converted the 6502
 * assembly source code into a C version (minus graphics).
 *
 * This is an LPC conversion that just uses the name generation code.
 *
 * The original source can be found here...
 *   http://www.iancgbell.clara.net/elite/text/index.htm
 *
 * --------------------------------------------------------------------
 * Unless I specify in file headers, all my stuff I release will be
 * Public Domain. Do as you want with it or not. The choice is yours.
 *
 * If I want to be paid for code, then I will pimp myself to a company.
 *
 * Tricky
 */

#define RTH_MAX_NAMES 256

private static string *rth_pairs_arr = ({
/* Planets from the original Elite */
  "..lexegezacebiso" +
  "usesarmaindirea." +
  "eratenberalaveti" +
  "edorquanteisrion",
/* Lorem ipsum */
  "..qupeaudidoliut" +
  "viadaedupasotoa." +
  "loaregelpufridhe" +
  "geimmeneninopier",
/* War and Peace */
  "..hethineranrena" +
  "ouonedneathatoa." +
  "isenitasteesaror" +
  "lenistverineseli",
/* Front page of Boing Boing (including HTML) */
  "..indiennatehaiv" +
  "bonereanasthoia." +
  "celaeterpariryte" +
  "atlehesetaarcoes",
/* The Little Prince (Chapters 1-5, English version) */
  "..thheanerinhaat" +
  "reouisittoonvea." +
  "histedleennamees" +
  "nenoofearoseorar",
});

private static string rth_pairs;

private static mapping rth_seed = ([
  "w0": 0,
  "w1": 0,
  "w2": 0,
]);

private static int rth_rotatel(int x)
{
    x = (x & 255) * 2;
    if(x > 255) x -= 255;
    return x;
}

private static int rth_twist(int x)
{
    return (rth_rotatel(x >> 8) << 8) + rth_rotatel(x & 255);
}

private static void rth_next()
{
    rth_seed["w0"] = rth_twist(rth_seed["w0"]);
    rth_seed["w1"] = rth_twist(rth_seed["w1"]);
    rth_seed["w2"] = rth_twist(rth_seed["w2"]);
}

private static void rth_tweakseed()
{
    int tmp;

    tmp = rth_seed["w0"] + rth_seed["w1"] + rth_seed["w2"];
    tmp &= 65535;

    rth_seed["w0"] = rth_seed["w1"];
    rth_seed["w1"] = rth_seed["w2"];
    rth_seed["w2"] = tmp;
}

private static string rth_makename()
{
    string name;
    int pair1, pair2, pair3, pair4;
    int longname = rth_seed["w0"] & 64;

    /* Always 4 iterations of random number */
    pair1 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair2 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair3 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();
    pair4 = 2 * ((rth_seed["w2"] >> 8) & 31); rth_tweakseed();

    name  = sprintf("%c", rth_pairs[pair1]);
    name += sprintf("%c", rth_pairs[pair1 + 1]);
    name += sprintf("%c", rth_pairs[pair2]);
    name += sprintf("%c", rth_pairs[pair2 + 1]);
    name += sprintf("%c", rth_pairs[pair3]);
    name += sprintf("%c", rth_pairs[pair3 + 1]);

    /* bit 6 of ORIGINAL w0 flags a four-pair name */
    if (longname)
    {
        name += sprintf("%c", rth_pairs[pair4]);
        name += sprintf("%c", rth_pairs[pair4 + 1]);
    }

    /* Remove any '.' in the name and capitalize the result */
    name = capitalize(replace_string(name, ".", ""));

    return name;
}

varargs string generate_name(int pair, int num, int ind)
{
    string array names = allocate(RTH_MAX_NAMES);

    if(undefinedp(pair) || !intp(pair)) pair = random(sizeof(rth_pairs_arr));
    if(pair < 0 || pair >= sizeof(rth_pairs_arr)) pair = 0;

    rth_pairs = rth_pairs_arr[pair];

    if(undefinedp(num) || !intp(num)) num = random(8) + 1;
    if(num < 1 || num > 8) num = 1;

    rth_seed["w0"] = 0x5a4a;
    rth_seed["w1"] = 0x0248;
    rth_seed["w2"] = 0xb753;

    for (int i = 1 ; i < num ; ++i) rth_next();

    for (int i = 0 ; i < RTH_MAX_NAMES ; ++i)
        names[i] = rth_makename();

    if (undefinedp(ind) || !intp(ind)) ind = random(RTH_MAX_NAMES);
    if (ind < 0 || ind >= RTH_MAX_NAMES) ind = 0;

    return names[ind];
}

Tricky

7
General / Mud client poll
« on: September 03, 2008, 07:15:08 PM »
I thought I'd ask this to get a general consenus as to what people use.

Tricky

Edit: I use Tinyfugue

8
Dead Souls Support / Remote who formatting for DIKU mudlib types.
« on: August 21, 2008, 10:59:19 AM »
DIKU derivatives return remote who information in a way that breaks formatting for DS libs. This bit of code will deal with them.

Find the function eventReceiveWhoReply in /daemon/services/who.c and replace it with this...

Code: [Select]
void eventReceiveWhoReply(mixed *packet) {
    mapping mudlist;
    string list, *who, tmp;
    object ob;

    if( file_name(previous_object()) != INTERMUD_D ) return;
    if( !packet[5] || !(ob = find_player(convert_name(eventLookupUser(packet[5])))) ) return;
    list = "%^MAGENTA%^Remote who information from " + packet[2] + ":%^RESET%^\n";
    mudlist = INTERMUD_D->GetMudList();
    foreach(who in packet[6]){
        mixed wtf;
        if(intp(who[1])) wtf = to_int(who[1]);

        /* Emerald MUD */
        if( who[1] == "never" )
            list += implode(explode(who[2], "\n")[1..<1], "\n") + "%^RESET%^\n";
        /* AFK I3 Driver who-reply */
        else if( wtf < 0 )
            list += who[0] + " " + who[2] + "%^RESET%^\n";
        else if( wtf == 9999 )
            list += who[0] + " " + who[2] + "%^RESET%^\n\n";
        else if( wtf == 2 * 9999 )
            list += "\n" + who[0] + " " + who[2] + "%^RESET%^\n";
        else if( wtf == 3 * 9999 )
            list += "\n" + who[0] + " " + who[2] + "%^RESET%^\n\n";
        /* Check for names with a <SPC> in them. Generally means it is a header in who[2]. */
        else if( strsrch(who[0], " ") != -1
          && ( strsrch(lower_case(mudlist[packet[2]][5]), "circle") != -1
           ||  strsrch(lower_case(mudlist[packet[2]][7]), "afkmud") != -1 ) )
            list += "* %^BOLD%^" + who[2] + "%^RESET%^\n";
        /* Regular I3 who-reply */
        else{
            if(wtf < 6) tmp = "not";
            else tmp = time_elapsed(wtf);
            list +=  who[0] + " (" + tmp + " idle): " + who[2] +"\n";
        }
    }
    ob->eventPrint(list);
    tn("eventReceiveWhoReply: "+identify(packet),"blue");
}

Then just reload the lib with a warmboot (warn your users of course :) ).

Tricky

9
Open Chat / Post #100
« on: March 17, 2008, 09:34:00 PM »
Wow! It's taken me over 2 years to get to this milestone.  ;D

Tricky

10
Code Vault / Bit counter
« on: March 11, 2008, 08:03:27 PM »
On 32bit machines, 0xdeadbeef and 0xcafebabe both return as 0x7fffffff and 31 bits. Knocking off the top bit (last two examples) works as expected.

Code: (bitcount.c) [Select]
/* bitcount.c
 *
 * Unless I specify in file headers, all my stuff I release will be
 * Public Domain. Do as you want with it or not. The choice is yours.
 *
 * If I want to be paid for code, then I will pimp myself to a company.
 *
 * Tricky
 */

#define BITCOUNT(x)     (((BX_(x)+(BX_(x)>>4)) & 0x0F0F0F0F) % 255)
#define BX_(x)          ((x) - (((x)>>1)&0x77777777)                    \
                             - (((x)>>2)&0x33333333)                    \
                             - (((x)>>3)&0x11111111))

int main(string args)
{
  int a = 0xffffffff;
  int b = 0x00ffffff;
  int c = 0x0000ffff;
  int d = 0x000000ff;
  int x;

  printf("11111111 11111111 11111111 11111111\n");
  printf("a = 0x%08x, bc = %i\n\n", a, BITCOUNT(a));

  printf("00000000 11111111 11111111 11111111\n");
  printf("b = 0x%08x, bc = %i\n\n", b, BITCOUNT(b));

  printf("00000000 00000000 11111111 11111111\n");
  printf("c = 0x%08x, bc = %i\n\n", c, BITCOUNT(c));

  printf("00000000 00000000 00000000 11111111\n");
  printf("d = 0x%08x, bc = %i\n\n", d, BITCOUNT(d));

  x = 0xdeadbeef;
  printf("11011110 10101101 10111110 11101111\n");
  printf("x = 0x%08x, bc = %i\n\n", x, BITCOUNT(x));

  x = 0xcafebabe;
  printf("11001010 11111110 10111010 10111110\n");
  printf("x = 0x%08x, bc = %i\n\n", x, BITCOUNT(x));

  x = 0x5eadbeef;
  printf("01011110 10101101 10111110 11101111\n");
  printf("x = 0x%08x, bc = %i\n\n", x, BITCOUNT(x));

  x = 0x4afebabe;
  printf("01001010 11111110 10111010 10111110\n");
  printf("x = 0x%08x, bc = %i\n", x, BITCOUNT(x));

  return 1;
}

Tricky

11
Code Vault / Simple maze generator
« on: March 10, 2008, 08:31:42 PM »
Some of you may remember me spamming the test channels with the output of this.

This works on the LPUni codebase. It makes use of the array reserved name and also ref for passing references between the caller and the function. For some reason the array variable is a global so using ref is totally redundant. I must have had a reason for doing it that way at the time. 8)

This is setup as a command. To use (if you manage to port it), call as:

> maze [<width> <height> [percentage]]

Called with no arguments a default maze of width 5, height 5 and 40% of the maze used for paths will be created.

width and height are integers.
percentage is a float.

Minimum size is 5 x 5, maximum size is 19 x 19. Percentage can be anything from 0.0 to 100.0 but setting it too small will cause a *Too long evaluation error.

This command just outputs the maze to the client. With a little thought you can use it as a dynamic area creator.

Code: (maze.c) [Select]
/* maze.c
 *
 * Unless I specify in file headers, all my stuff I release will be
 * Public Domain. Do as you want with it or not. The choice is yours.
 *
 * If I want to be paid for code, then I will pimp myself to a company.
 *
 * Tricky
 */

/* Colour defines for non-LPUni codebases */
#define YEL "%^YELLOW%^"
#define HIR "%^BOLD%^%^RED%^"
#define BRED "%^B_RED%^"
#define BBLU "%^B_BLUE%^"
#define NOR "%^RESET%^"

/* Maximum and minimum width and height */
#define MAXW 19
#define MAXH 19
#define MINW 5
#define MINH 5

/* Array manipulation defines */
#define POKE(pm, px, py, val) pm[py][px] = val
#define PEEK(pm, px, py) pm[py][px]

/* Global variables. Some of these could possibly be removed */
mixed array m;
int x, y, xm, ym, ok;

/* Functions */
void makeMaze(mixed array ref maze, int w, int h, float perc)
{
    mapping d = ([
      0: ({ 0, 1, 0, -1, }),
      1: ({ 1, 0, -1, 0, }),
    ]);
    int xx, yy;
    int i, j, n, rnd;
    int ok;

    x = 1;
    y = 1;
    xm = x + 1;
    ym = y + 1;

    maze = ({ });

    for (j = 0 ; j < h + 2 ; j++)
    {
        maze += ({ ({ }) });

        for (i = 0 ; i < w + 2 ; i++) maze[j] += ({ 0 });
    }

    POKE(maze, x, y, 1);

    for (n = 0 ; n < to_int((float)(w * h) * (perc / 100.0)) ; n++)
    {

        while (1)
        {
            ok = 1;

            while (1)
            {
                rnd = random(4);

                xx = x + d[0][rnd];
                yy = y + d[1][rnd];

                if (xx > 0 && xx < ((w + 3) >> 1)
                 && yy > 0 && (yy < (h + 3) >> 1)) break;
            }

            if (PEEK(maze, (xx * 2) - 1, (yy * 2) - 1) != 0)
            {
                ok = 0;

                while (1)
                {
                    x = random(xm) + 1;
                    y = random(ym) + 1;

                    if (PEEK(maze, (x * 2) - 1, (y * 2) - 1) != 0) break;
                }

            }

            if (ok) break;
        }

        POKE(maze, x * 2 + 0 * d[0][rnd] - 1, y * 2 + 0 * d[1][rnd] - 1, 1);
        POKE(maze, x * 2 + 1 * d[0][rnd] - 1, y * 2 + 1 * d[1][rnd] - 1, 1);

        x = xx;
        y = yy;

        if (x > xm) xm = x;
        if (y > ym) ym = y;
    }

}

int makeGates(mixed array ref maze, int w, int h)
{
    int gates = 0, count = 0;

    while (count < 50)
    {
        count++;
        x = random(w);

        if (PEEK(maze, x + 1, 1) != 0) count = 51;
    }

    if (count == 51)
    {
        POKE(maze, x + 1, 0, 2);
        gates++;
    }

    count = 0;

    while (count < 50)
    {
        count++;
        x = random(w);

        if (PEEK(maze, x + 1, h) != 0) count = 51;
    }

    if (count == 51)
    {
        POKE(maze, x + 1, h + 1, 3);
        gates++;
    }

    count = 0;

    while (count < 50)
    {
        count++;
        y = random(h);

        if (PEEK(maze, 1, y + 1) != 0) count = 51;
    }

    if (count == 51)
    {
        POKE(maze, 0, y + 1, 4);
        gates++;
    }

    count = 0;

    while (count < 50)
    {
        count++;
        y = random(h);

        if (PEEK(maze, w, y + 1) != 0) count = 51;
    }

    if (count == 51)
    {
        POKE(maze, w + 1, y + 1, 5);
        gates++;
    }

    return gates;
}

int main(string args)
{
    string msg = "";
    float perc;
    int w, h, ok = 1;

    w = h = 5;
    perc = 40.0;

    if (!undefinedp(args) && args != "")
        if (sscanf(args, "%d %d %f", w, h, perc) != 3)
            sscanf(args, "%d %d", w, h);

    if (!(w & 1)) w++;
    if (!(h & 1)) h++;

    if (w < MINW) w = MINW;
    if (h < MINH) h = MINH;
    if (w > MAXW) w = MAXW;
    if (h > MAXH) h = MAXH;

    while (ok < 4)
    {
        makeMaze(ref m, w, h, perc);
        ok = makeGates(ref m, w, h);
    }

    for (int j = 0 ; j < h + 2 ; j++)
    {
        msg += " ";

        for (int i = 0 ; i < w + 2 ; i++)
            switch (PEEK(m, i, j))
            {
                case 0: msg += BRED + HIR + "#" + NOR; break;
                case 1: msg += "."; break;
                case 2: msg += BBLU + YEL + "N" + NOR; break;
                case 3: msg += BBLU + YEL + "S" + NOR; break;
                case 4: msg += BBLU + YEL + "W" + NOR; break;
                case 5: msg += BBLU + YEL + "E" + NOR; break;
                default: msg += "*"; break;
            }

        msg += NOR + "\n";
    }

    foreach (string line in explode(msg + "\n", "\n"))
        write(line + "\n");

    return 1;
}

Tricky

12
LPUniversity / LPUniMudlib FINAL-0802-R8 released
« on: March 10, 2008, 03:31:34 PM »
FINAL-0802-R8
 
After a long haitus in the wilderness and much to most people's suprise, the LPUniversity Mudlib is back for a final outing. This release is a bugfix of ALPHA-0610-R7. There are still many problems with the mudlib but it was decided that it should be released for future developers to use and fix. Current mudlib development is now focused upon the Sapidlib trunk. Occasional fixes will be released for this version but only on an ad-hoc basis.
 
Included in this release:

  • Conference room
  • access command now functional
  • Various bugs were fixed

Since this is only the 8th release, there are bound to be many more bugs and issues. Please report them to LPUni Final to help make the LPUniversity Mudlib better.

Downloads available from:


For further information, please look at our website LPUniversity
 
The LPUniversity Mudlib team

13
Dead Souls Support / Fix to show real sender of faked IMC2 socials
« on: January 23, 2008, 09:04:33 PM »
Find the function channel_in in /decure/daemon/imc2.c and change it to...

Code: [Select]
      void channel_in(string fromname, string frommud, mapping data){
          string sender;
          string localchan;

          int emote=0;

          sender=fromname+"@"+frommud;
          if(data["sender"]) sender = data["sender"];
          if(data["realfrom"]) sender = data["realfrom"];
          if(intp(data["text"])) data["text"]=sprintf("%d",data["text"]);
          if(data["emote"]) emote = data["emote"];
          //Following fix courtesy of Tricky
          if (emote == 1 && strsrch(data["text"], "$N") == -1)
              data["text"] = "$N " + data["text"];

          if (emote == 2 && strsrch(data["text"], sender) == -1)
              data["text"] = data["text"] + " (" + sender + ")";

          data["text"] = imc2_to_pinkfish(data["text"]);
          localchan = CHANNEL_BOT->GetLocalChannel(data["channel"]);
          CHANNEL_BOT->eventSendChannel(sender, localchan, data["text"], emote, "", "");
      }

The fix is a simple check to see if the sender's name is in the social

Code: [Select]
          if (emote == 2 && strsrch(data["text"], sender) == -1)
              data["text"] = data["text"] + " (" + sender + ")";

It isn't perfect but it should make you more aware of who is really sending stuff. It does fall down if their name is referenced in the social but the message makes it look like it came from someone else.

Tricky

14
Dead Souls Support / imc2_to_pinkfish patch
« on: January 09, 2008, 05:01:59 PM »
I noticed that the IMC2 daemon wasn't converting colour codes into their respective pinkfish. So I added the following to the function channel_in.

Code: [Select]
          data["text"] = imc2_to_pinkfish(data["text"]);

Code: (/secure/daemon/imc2.c) [Select]
      void channel_in(string fromname, string frommud, mapping data){
          string sender;
          string localchan;

          int emote=0;

          sender=fromname+"@"+frommud;
          if(data["sender"]) sender = data["sender"];
          if(data["realfrom"]) sender = data["realfrom"];
          if(intp(data["text"])) data["text"]=sprintf("%d",data["text"]);
          if(data["emote"]) emote = data["emote"];
          //Following fix courtesy of Tricky
          if (emote == 1 && strsrch(data["text"], "$N") == -1)
              data["text"] = "$N " + data["text"];

          data["text"] = imc2_to_pinkfish(data["text"]);
          localchan = CHANNEL_BOT->GetLocalChannel(data["channel"]);
          CHANNEL_BOT->eventSendChannel(sender, localchan, data["text"], emote, "", "");
      }

Tricky

15
Dead Souls Support / IMC2 emote bug fix
« on: November 23, 2007, 01:52:55 PM »
Here is a small fix to make emotes show the name of the sender...

Code: (/secure/daemon/imc2.c) [Select]
      void channel_in(string fromname, string frommud, mapping data){
          string sender;
          string localchan;

          int emote=0;

          sender=fromname+"@"+frommud;
          if(data["sender"]) sender = data["sender"];
          if(data["realfrom"]) sender = data["realfrom"];
          if(intp(data["text"])) data["text"]=sprintf("%d",data["text"]);

          if(data["emote"]) emote = data["emote"];
          if(emote && strsrch(data["text"], "$N") == -1) data["text"] = "$N " + data["text"];

          localchan = CHANNEL_BOT->GetLocalChannel(data["channel"]);
          CHANNEL_BOT->eventSendChannel(sender, localchan, data["text"], emote, "", "");
      }

The specfic line that I added is...

Code: [Select]
          if(emote && strsrch(data["text"], "$N") == -1) data["text"] = "$N " + data["text"];

Tricky

Pages: [1] 2