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.


Messages - Tricky

Pages: [1] 2 3 ... 14
1
Drivers / Re: Long standing bug in FluffOS
« on: September 03, 2013, 12:39:42 PM »
If you want an "undefined" value, add an actual real honest-to-god "undefined".  That's a good idea.  Other languages have such a value (often called nil or null... but not to be confused with C's NULL that's really just 0 again).

So, no... it's not because I couldn't think of a use for it.  It's because I'd rather not abuse what I consider to be a bug in the type system. :)
Code: [Select]
#define UNDEFINED ([ ])[0]

2
command only takes 1 (one) argument.

Code: [Select]
command - execute a command as if given by the object

int command( string str );

This efun is only available if NO_ADD_ACTION isn't defined.

Execute 'str' for the object this_object() as a command (matching against
add_actions and such).  The object must have called enable_commands() for
this to have any effect.
In case of failure, 0 is returned, otherwise a numeric value is returned,
which is the LPC "evaluation cost" of the command.  Bigger numbers mean
higher cost, but the whole scale is subjective and unreliable.

See also:
 add_action,
 enable_commands

3
Drivers / Re: https://github.com/fluffos/fluffos
« on: March 03, 2013, 10:17:28 PM »
I did, but it is hard to judge which should be imported which should not be.  Since the patch is on an different base and we had some conflicts.  It also contains incremental fixes (like the several commits of  RTHMALLOC (ideally there should be only one commit to apply). 

My changes are not clean either, I did a series of rebase and merged my commits into several distinct patches that can be applied separately.  I will take a more detailed look at your changes later today compare to 2.26, but it's usually easier for the originator (because you wrote it) to prepare a series of patch against main tree.
Ignore RTHMALLOC. It's experimental. What I'm trying to acheive with that malloc is less fragmentation.

4
Drivers / Re: https://github.com/fluffos/fluffos
« on: March 03, 2013, 09:35:02 PM »
As for a cleaner diff against v2.24??? I'm not sure what you are wanting.

I was hoping you can generate some diffs on the problem you've fixed that we don't have so it can be merged into next release.
A simple patch file is so much easier to follow than a git commit history.

DIFFS
Have you actually looked at the launchpad changes?

5
Drivers / Re: https://github.com/fluffos/fluffos
« on: March 02, 2013, 10:02:17 PM »
Tricky:

it seems we are getting some duplicated patch .... (like fixing compile warning and set std=c99) ..

and your history is kind of hard to read, any way for you to generate some cleaner diff against  2.24 ?

Cheers.
Umm... Some of the compile warnings I'd already fixed. I've been doing this since v2.11 and updating it to the Sapidlib mudlib for the past 4 1/2 years.

As for a cleaner diff against v2.24??? I'm not sure what you are wanting.

6
Drivers / Re: https://github.com/fluffos/fluffos
« on: March 01, 2013, 12:22:47 AM »
Like launchpad then.

Yeah, long time no see.

You might want to checkout some of the changes I've made over the past few years (ignore the  dates, I had a major disk crash and re-importing borked the real commit dates)...
mainly Cygwin stuff. DON'T use bsdmalloc under Cygwin, my implementation of brk() is borked. I need to put some checks in so that it errors out if you try to compile with that setting.

Oh yeah, it uses the configure system that Crat implemented for Dead Souls driver compiling. Just type ./configure to get help. (Second argument would be develop or debug if needed)

Ignore the fact it says junk, just means it is in my personal space and not given it's own project page.

Ah ha! Launchpad has just imported the git repos:
It had been setup by Tacitus (2 years ago) to import the CVS repos at servebeer. But that failed.

7
Drivers / Re: Porting old 2.4.5 lib to FluffOS
« on: April 25, 2012, 02:39:48 PM »
If you download ldmud (http://www.bearnip.com/ldmud/) and look in /mud/lp-245 you will find a version of 2.4.5 that has been converted to run on ldmud.

Quote from: README
This is the old LP 2.4.5 mudlib, slightly updated to run with LDMud 3.2.7
or newer. LP 2.4.5 is by all means a spartanic, if not to say primitive,
mudlib, but it also is small and easy to understand (not to mention the
historical value :-).

LP 2.4.5 is a compat-mode mudlib, but the provided simul_efun object provides
the necessary functions to let it run with a plain driver as well (just
the old parse_command() efun is not simulated).
For both modes the master object is 'obj/master.c'.

The topdirectory contains these files and directories:

  ACCESS.ALLOW: the usual access definition file
  WELCOME, NEWS, WIZNEWS: the messages printed on login
  WIZLIST     : the wizlist savefile

  doc/        : mudlib-specific documentation, to be complemented
                with the doc/ files from the driver distribution.
  log/        : logfiles generated by the mudlib
  obj/        : game objects
  players/    : player savefiles and wizard directories
  room/       : game rooms and include files
  sys/        : include files, including those from the driver distribution

Tricky

8
LPUniversity / Re: Is it dead?
« on: March 01, 2012, 08:43:55 AM »
The project I would say is dead.

The actual mudlib (Sapidlib) is still being developed by myself and a few others. Although to be honest I think it is really me at the moment.

I'm in no need of the lpuni.org domain as I have no real use for it.

Tricky

9
Code Vault / Re: Singularize and Pluralize sefuns...
« on: February 25, 2012, 01:23:37 PM »
correction:  most words ending in 'ch' get 'es' ending; just 's' is the exception:  lichs, lochs, stomachs, monarchs, bachs, epochs, machs, eunuchs, pentarch, R.*tych, yech, psych, synch, tech, R.*tech, R.*iarch, anarchs, oligarchs

Stop trying to complicate things. You just need 2 rules to catch the majority of words.

Code: [Select]
R.*tch          0       es
R.*ch           0       s

... in that order.

Those two rules will catch the above words you have quoted and practically anything else. Create exceptions for, well, exceptions.

Tricky

10
Code Vault / Re: Singularize and Pluralize sefuns...
« on: February 10, 2012, 07:00:07 PM »
nouns that remain the same between singular and plural:  apparel, cod, corps, halibut, means, offspring, perch, pliers, scissors, tongs, tuna, tweezers
Note the fish... Generally fish species are both plural and singular.

plural of box is 'boxes', not 'boxen', general-rule:  words ending in 'x' add 'es' to pluralize (e.g. foxes, boxes, poxes, sexes...)
Forgot I had box -> boxen in there. It's generally a joke plural form on the lines of vax -> vaxen.

words ending in 'z' get 'es' endings, too; blintzes, waltzes, quizzes ('z' doubled due to...what the heck rule is that?)
Not sure but maybe words that have a vowel before 'z' get pluralized with 'zes'.

problematic: 'attorney general' should be 'attorneys general' but it's got a whitespace...
I've got an idea for that... will look into it.

Tricky

11
Code Vault / Re: Soundex sefun
« on: February 05, 2012, 12:04:39 PM »
Simplified version based on Quix's version but re-written. I had problems with "trying to put int in string" errors.

The check for array input does recursive calls to soundex() tagging the result onto the end of the return array.

For DS libs, replace query_name() with GetName().

Code: [Select]
protected string _soundex(string word)
{
  mapping codex = ([
    "B": 1, "F": 1, "P": 1, "V": 1,
    "C": 2, "G": 2, "J": 2, "K": 2, "Q": 2, "S": 2, "X": 2, "Z" :2,
    "D": 3, "T": 3,
    "L": 4,
    "M": 5, "N": 5,
    "R": 6
  ]);
  string array letters = ({ });
  string ret;
  int match, current = 0, last = 0;

  if (!word || !stringp(word)) return "Z000";

  ret = word[0..0];
  letters = explode(word[1..<1], "");

  foreach (string letter in letters)
  {
    match = codex[letter];

    if (undefinedp(match)) continue;
    if (match == last) continue;

    last = match;
    current *= 10;
    current += match;

    if (current > 999) break;
  }

  ret += current + "000";

  return ret[0..3];
}


string array soundex(mixed data)
{
  string array ret = ({ });

  if (undefinedp(data) || !data) return ({ "Z000" });
  if (objectp(data)) return ({ _soundex(data->query_name()) });

  if (stringp(data))
  {
    mixed array assoc;
    int i, sz;

    /* Strip out whole words including hyphens and apostrophes. */
    assoc = reg_assoc(data, ({ "[A-Za-z'-]+", }), ({ 1, }), 0);

    for (i = 0, sz = sizeof(assoc[1]) ; i < sz ; i++)
    {
      if (!assoc[1][i]) continue;

      ret += ({ _soundex(upper_case(assoc[0][i])) });
    }
  }
  else
  if (arrayp(data))
    foreach(mixed datum in data)
      ret += soundex(datum);
  else
    ret += ({ "Z000" });

  return ret;
}

Tricky

12
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

13
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

14
Code Vault / Re: Singularize function.
« on: December 31, 2011, 09:46:27 PM »
Testing...

Code: [Select]
eval return singularize("raspberries")
Evaluating:
return singularize("raspberries")

Result = "raspberry"

That would have been handled by the line...
Code: [Select]
R.*ies 3 y

Tricky

15
Code Vault / Re: Singularize function.
« on: December 31, 2011, 09:06:44 PM »
I have expanded the code to use regular expressions (not PCRE) in the data file.

Note that the data file format has completely changed. It follows a similar format to the efun pluralize code with 'cut' and 'suffix'.

This means that you will have to replace all functions and the data file. trim(), ltrim() and rtrim() stay the same.

Code: (singularize) [Select]
/* Where to find the plural_exception file. */
#define PLURAL_EXCEPTIONS "/path/to/plural_exceptions"

nosave mapping pluralExceptions = ([ ]);
nosave mixed array re_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;
    int re = 0;

    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 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_pluralExceptions += ({ ([ ]) });
        re_pluralExceptions[re]["re"] = s_plural[1..<1];

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

          re_pluralExceptions[re]["suffix"] = s_suffix;
        }

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

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

          pluralExceptions[s_plural][1] = s_suffix;
        }
      }
    }
  }

  return pe_map_loaded;
}

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

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

  str = trim(str);

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

  if (!f_load_pluralExceptions(PLURAL_EXCEPTIONS)) {
    /* If we don't have a file of exceptions then we use the default set. */
    pluralExceptions = ([
      "is": ({ "*", "are" }),
      "blues": ({ 0, "" }),
      "buses": ({ 2, "" }),
      "bonuses": ({ 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, "" }),
      "monies": ({ 3, "ey" }),
      "mice": ({ 3, "ouse" }),
      "matrices": ({ 3, "x" }),
      "oxen": ({ 2, "" }),
      "pants": ({ 0, "" }),
      "remains": ({ 0, "" }),
      "staves": ({ 3, "ff" }),
      "thieves": ({ 3, "f" }),
      "teeth": ({ 4, "ooth" }),
      "vertices": ({ 4, "ex" }),
      "vaxen": ({ 2, "" }),
      "viruses": ({ 2, "" }),
      "were": ({ 3, "as" }),
    ]);

    re_pluralExceptions = ({
      ([ "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": "" ]),
    });
  }

  /* Same rules apply as in 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 pluralExceptions mapping. */
  exception = pluralExceptions[tmp];

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

    sz = sizeof(re_pluralExceptions);

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

      if (regexp(tmp, "^" + s_re + "$")) {
        exception = ({ re_pluralExceptions[re]["cut"], re_pluralExceptions[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) {
      single = tmp;
    } else if (stringp(cut) && cut == "*") {
      single = suffix;
    } else {
      int len = strlen(tmp);

      /* Cut out the required number of letters from the end. */
      single = tmp[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;

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

  return pre + single + post;
}

Code: (plural_exceptions) [Select]
# Plural 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: 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: 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: 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.
opus 2 era
sphinges 3 x

# 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.
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.
blues
glasses
pants
remains
deer
moose
sheep
bison
salmon
pike
trout
fish
swine
series
species

# No suffix to add on. Just cut off some letters.
appendixes 2
atlases 2
boxen 2
buses 2
bonuses 2
censuses 2
children 3
eyen 1
giraffes 1
hippopotamuses 2
housen 1
hosen 1
lotuses 2
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

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
# Make sure this is after 'da'.
R.*a 1 on

R.*ae 1

# 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

# Has to be last!
R.*s 1

Tricky

Pages: [1] 2 3 ... 14