1.1 - Contributions and Development

This section is where user contributions will be run through the paces as they are considered for inclusion in the official release versions. Each and every line of code in the WARPEDcore will start its life here. This section is where MOST of the activity of this entire book SHOULD take place.

At the most basic explanation (as I am presently understanding this book format), the procedure should work something like this...

  • To contribute a module for consideration, use the 'create content' option on your account to create a 'book page' parented to THIS page (The WARPEDcore/The Code/Unofficial Contributions). It will go through the moderation process to be added as a page in the book. Then, it will be publicly evaluated and/or otherwise abused in discussion and tweaking via 'edits' and 'replies' (see below). And, eventually, will be considered for inclusion in the official release (at which time, it would be appropriately moved thereto).
  • To submit a patch or tweak, use the 'edit' tab (just below the title of this page) and include a comment in the 'log' window at the bottom, explaining what you did. It, too, will go through the moderation process before being approved for inclusion (it might also be a good idea to start out with a discussion thread, see below)
  • To make a suggestion or request (i.e., you know something is needed, but are uncertain if you'd be able to code it right, or whatever) or to otherwise discuss or comment upon existing code submissions, use the 'reply' option.

NOTE: Just because a contribution isn't immediately considered for inclusion in the official release does not necessarily mean it's been rejected therefrom. I suspect many contributions will go through a very long period of 'not quite ready'-ness, for whatever reason (maybe the core isn't really ready to deal with the larger implications of adding some specific module - whatever). Point being: don't be discouraged if your really cool idea version 42.b5 just hangs out here for a while in the 'debug, comment, and abuse' phase.

1.1.0 ~reboot


@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ WARPED      ~~~~~~~~~~~~~~~~                                           ~
@@        ~~~~~~~~~        ~~~~~~~~~              WARPEDcore             ~~
@@     ~~~~~~                    ~~~~~~             ~reboot            ~~~
@@   ~~~~          Adoption          ~~~~         200609250b         ~~~~
@@  ~~~              Date              ~~~~~~                    ~~~~~~
@@ ~~             2006.09.25              ~~~~~~~~~        ~~~~~~~~~
@@ ~                                           ~~~~~~~~~~~~~~~~        core
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================

1.1.1 ~cron


@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ WARPEDcore~cron Version 20070107a1
@@
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ LEGAL
@@
@@ This material is released under the terms of the
@@ WARPEDcore Softcode and Documentation License (WSDL).
@@ For details, see: http://community.pennmush.org
@@
@@ USE AT YOUR OWN RISK.
@@
@@ Copyright 2007, The WARPEDcore Project
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ SYSTEM REQUIREMENTS
@@
@@ * PennMUSH version 1.7.4p21 or newer.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ The 'cut' line.
@@
@@ It is safe to remove everything above the following line, before quoting
@@ this script into your MUSH.
@@
@@ ========================================================================
@@ . . . . C . . . u . . . t . . . . . . H . . . e . . . r . . . e . . . .
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ create ~cron
@@
@create ~cron
@set ~cron=NO_COMMAND
@describe ~cron=WARPEDcore~cron
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ legal reference and version
@@
&~`legal ~cron=http://community.pennmush.org
@@
&~`version ~cron=20070107a1
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ data
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ variables: configurable.
@@
@@ documentation is provided.
@@
&CONF`INTERVAL ~cron=300
&NOTE`CONF`INTERVAL ~cron=This value represents the frequency of emits in a number of SECONDS. Note, setting this to anything other than an appropriate multiple of sixty (60) will have very screwy results. Recommended values are the following: 60 300 600 900 1200 1800 3600 (1m 5m 10m 15m 20m 30m and 60m, respectively). Default: 300 (5m)
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ the code.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the loop.
@@
@@ fix this so that the emit is caculated before the final wait length.
@@
@STARTUP ~cron=@wait/until [cemit(~, if(gt(sub(secs(),convtime(starttime())),10),Re-)Started., 1)][setr(s, mul(setr(i, v(CONF`INTERVAL)), inc(div(secs(), %qi))))]=@tr me/TRIG`CRON`LOOP=%qs
@@
&NOTE`STARTUP ~cron=triggers TRIG.CRON.LOOP to start the cron
@@
@@
&TRIG`CRON`LOOP ~cron=@wait/until [cemit(~, ufun(UFUN`CEMIT,%0), 1)][setr(s, mul(setr(i, v(CONF`INTERVAL)), inc(div(secs(), %qi))))]=@tr me/TRIG`CRON`LOOP=%qs
@@
&NOTE`TRIG`CRON`LOOP ~cron=this cemits cron message and reinitiates loop.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ the functions
@@
&UFUN`CEMIT ~cron=[u(UFUN`TZ)][@@(UFUN`TZ sets and returns %qz - the timezone offset based on system configuration)]~%0~[u(UFUN`ETIMESTRING, %0)][@@(UFUN`ETIMESTRING sets and returns %qt - the enhanced time string value for %0)][if(hasattrval(me/UFUN`IC),~[u(UFUN`IC, %0)])][@@(does whatever you write UFUN`IC to do)]
@@
&NOTE`UFUN`CEMIT ~cron=this calculates, arranges, and returns the message for the cron cemit, using the subsequent UFUN.* attribs. %0 is the secs() value of the current emit sent to all subsequent functions.
@@
@@
&UFUN`TZ ~cron=[setr(z, div(sub(secs(), convtime(utctime())), 3600))]
@@
&NOTE`UFUN`TZ ~cron=determines sets %qz to the timezone offset in hours, based on your system's configuration.
@@
@@
&UFUN`ETIMESTRING ~cron=[setq(t, convsecs(%0))][inc(div(dec(elements(%qt, 3)), 7))][@@(<-- this calculates N for 'Nth <Weekday> of the month')][if(not(strmatch(elements(%qt, 2), elements(convsecs(add(%0, lmath(mul,60 60 24 7))), 2))), .0)][@@(<-- this appends '.0' to the previously calculated 'N' if and only if this is also the 'last <Weekday> of the month')] %qt
@@
&NOTE`UFUN`ETIMESTRING ~cron=sets %qt to the timestring value for %0 and emits %qt preceded by the <N[.0]> enhancement.
@@
@@
&UFUN`IC ~cron=
@@
&NOTE`UFUN`IC ~cron=write this for your IC cron data. it is sent %qs - the UTSECS value of current emit .
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ create the cron broadcast channel and configure its locks on the ~cron.
@@
@chan/add ~=object player quiet
@@
@dolist join speak see hide mod=@clock/## ~=@[num(~cron)]
@dolist Join Speak See Hide Mod=@lock/user:Chan##Lock ~cron=LOCK`CHAN`[ucstr(##)]/1
@@
@@
&LOCK`CHAN`JOIN ~cron=cor(orflags(owner(%#), Wr), not(t(member(iter(cwho(~), owner(%i0)), owner(%#)))), u(LOCK`CHAN`JOIN.CUSTOM))
@@
&NOTE`LOCK`CHAN`JOIN ~cron=join-locks the channel to wizards and royalty, mortal players who don't already have an object on channel, and whatever you write in LOCK`CHAN`JOIN.CUSTOM
@@
&LOCK`CHAN`JOIN.CUSTOM ~cron=0
@@
&NOTE`LOCK`CHAN`JOIN.CUSTOM ~cron=write your own truth value test here.
@@
@@
&LOCK`CHAN`SPEAK ~cron=strmatch(%#, num(me))
@@
@@
&LOCK`CHAN`SEE ~cron=1
@@
@@
&LOCK`CHAN`HIDE ~cron=strmatch(%#, num(me))
@@
@@
&LOCK`CHAN`MOD ~cron=0
@@
@@
@chan/on ~=~cron
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ Help
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ Help files
@@
&HELP`CRON ~cron=%r<~> <TZ>~<SECS>~<ETIMESTRING>~<IC>%r%r [ljust(<~>,12)] this is the channel name.%r [ljust(<TZ>,10)] TimeZone offset in hours>%r [ljust(<SECS>,12)] secs() of the current emit%r [ljust(<ETIMESTRING>,12)] includes <#wkday> and <time()> of current emit%r [ljust(<IC>,10)] includes whatever is custom written by the game gods%r%rexample...%r%r<~> -6 1067209500~4.0 Sun Oct 26 17:05:00 2003~<IC stuff>%r%rSee also the +help on: ic_time%r
@@
&HELP`IC_TIME ~cron=%rthe <IC> section of the ~cron includes whatever softcoded "IC time" data your local wizards have configured for this portion.%r%r[get(me/note`ufun`cron`ic)]
@@
@@
@@ The following regexp listen patterns were contributed by Mike @ M*U*S*H
@@ for some common listen intervals. Although it's not necessary to use
@@ regexp listen patterns, it can be very useful especially if you wanted
@@ to combine a few of the effects (e.g., opening a secret exit only
@@ on the third Wednesday of the month at precisely midnight).
@@
@@ In each one,
@@ %1 is <TZ~SECS>
@@ %2 is the <N>th Weekday of the month
@@ %3 is the Weekday itself,
@@ %4 the month,
@@ %5 the Day of the Month,
@@ %6 the HH,
@@ %7 the MM,
@@ %8 the SS,
@@ %9 the YYYY
@@ (%0 is the entire com message)
@@ if all the individual %<1-9> registers aren't needed, you can of course
@@ write shorter code.
@@
@@ These are untested, but I think they should work, with the caveat that
@@ if you ever broadcast at intervals of less than one minute,
@@ things will get nasty.
@@
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@
@@ &1M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(..):(..) (....)$:blah
@@ &2M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.[02468]):(..) (....)$:blah
@@ &5M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.[05]):(..) (....)$:blah
@@ &10M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(.0):(..) (....)$:blah
@@ &15M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(00|15|30|45):(..) (....)$:blah
@@ &20M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):([024]0):(..) (....)$:blah
@@ &30M foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):([03]0):(..) (....)$:blah
@@ &1H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (..):(00):(..) (....)$:blah
@@ &2H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (.[02468]):(00):(..) (....)$:blah
@@ &3H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|03|06|09|12|15|18|21):(00):(..) (....)$:blah
@@ &4H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|04|08|12|16|20):(00):(..) (....)$:blah
@@ &6H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|06|12|18):(00):(..) (....)$:blah
@@ &8H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|08|16):(00):(..) (....)$:blah
@@ &12H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00|12):(00):(..) (....)$:blah
@@ &24H foo=^^<~> (.+)~(.|.\.0) (...) (...) (..) (00):(00):(..) (....)$:blah
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ activate
@@
@restart ~cron
@@
@@ The End.

1.1.2 ~config

Below is a list of 'to do' items.

1. Get and maintain plain vanilla default master list (i.e., set up a new PennMUSH "out of the box" and separate the code for setting up defaults in &DATA`<category>`<item>`DEFAULT attributes).

KNOWN BUG: the do-options code, as written, generates a category called 'parameters'.
Mike pages: If you just stick setdiff(<foo>,@config parameters,|) in (where <foo> is the textentries(help,@config %0*,|) I believe) that should fix that bit.

KNOWN BUG: the 'tiny' category doesn't get a description set.

KNOWN ISSUE: Haven't yet finished the /diff switch for two reasons:
1. time
2. have only tested this on M*U*S*H (haven't ever done a plain vanilla, per the 'to do' above).

Here's the code to generate all of the data (not yet separated per 'vanilla' above).


@@
&CMND.DO-OPTIONS [v(~)]=$do-options:@pemit %#=Doing options.[null(u(list-options))]
@@
&list-options [v(~)]=localize(setq(0,,1,,2,,3,0,4,0,5,0)[null(iter(sort(textentries(help, @config %0*,|),,|), if(isint(right(%i0, 1)), setq(5, 0), if(%q3, u(save-option, %q2, %q0))[switch(inum(0), 1, , u(save-category, %q0, %q1))][setq(3, 0, 2, , 0, rest(%i0), 5, 1)])[setq(4, 1)][iter(textfile(help, %i0), switch(setr(9, squish(%i0)), , if(%q3,u(save-option, %q2, %q0)[setq(3, 0, 2, )]), *=*:*, switch(1, %q3, u(save-option, %q2, %q0))[setq(2, %q9, 3, 1)], switch(1, %q4, if(%q5, setq(1, %q9))[setq(4,0)], %q3, setq(2, %q2 %q9))), %r, %b)], |, %b))])
@@
&save-option [v(~)]=set(me, DATA`%1`[first(%0, =)]`DEFAULT:[config(first(%0, =))])[set(me, DATA`%1`[first(%0, =)]`TYPE:[before(after(%0, <), >)])][set(me, DATA`%1`[first(%0, =)]:[squish(after(%0, :))])]
@@
&save-category [v(~)]=set(me,DATA`%0:%1)
@@
&credit-options [v(~)]=code for generating all of the attributes and contents originally written by Mike @ M*U*S*H with attribute name adaptations by Trispis @ c.p.o.
@@

And here's the display code, as it presently exists


@@
&cmnd`config [v(~)]=$~config:@pemit %#=u(UFUN`DISP)
@@
&cmnd`config.diff [v(~)]=$~config/diff:@pemit %#=u(UFUN`DISP`DIFF)
@@
&cmnd`config.list_x [v(~)]=$~config/list *:@pemit %#=ifelse(setr(e, u(UFUN`ERRCK`CATY, %0)), %qe, u(UFUN`DISP`HEADER)[u(UFUN`DISP`CATY, %0)][u(UFUN`DISP`FOOTER)])
@@
&cmnd`config.show_x [v(~)]=$~config/show *:@pemit %#=ifelse(setr(e, u(UFUN`ERRCK`ITEM, %0)), %qe, u(UFUN`DISP`HEADER)[u(UFUN`DISP`ITEM,%0)][u(UFUN`DISP`FOOTER)])
@@
&ufun`disp [v(~)]=[u(UFUN`DISP`HEADER)][u(UFUN`DISP`SYNTAX)][iter(setr(l, lattr(me/DATA`))[setq(w, lmath(max, iter(%ql, strlen(last(%i0, `)))))], [align(%qw [sub(width(%#), sub(%qw, 2))], setr(c, lcstr(last(%i0, `))), v(%i0))], %b, %r)][u(UFUN`DISP`FOOTER)]
@@
&ufun`disp`diff [v(~)]=null(iter(config(), switch(v(lattr(me/DATA`*`%i0`DEFAULT)), config(%i0), setq(d, %qd %i0), #-*, setq(e, %qe %i0), setq(o, %qo %i0))))%rDiffering values: %qd%r%rErrors: %qe%r%rOther differences: %qo%r
@@
&ufun`disp`caty [v(~)]=Config Category: %0%rDescription: [v(DATA`%0)]%r[setq(n, lmath(max, iter(setr(l, iter(lattr(me/DATA`%0`), lcstr(last(%i0,`)))), inc(strlen(%i0)))))][table(%ql, %qn, width(%#))]
@@
&ufun`disp`item [v(~)]=ljust(Config Item: %0, setr(w, div(width(%#), 2)))Config Type: [v(%qi`type)]%r%rDescription: [v(%qi)]%r%r[ljust(Default Setting: [v(%qi`DEFAULT)], %qw)]Current Setting: [config(%0)]
@@
&ufun`errck`caty [v(~)]=ifelse(or(not(dec(words(%0))), hasattr(me, DATA`%0)), ,Unknown category: %0)
@@
&ufun`errck`item [v(~)]=ifelse(or(words(setr(i, lattr(me/DATA`*`%0))), not(dec(words(%0)))), , Unknown config item: %0)
@@
&ufun`disp`header [v(~)]=-[center(- WARPEDcore~config -, sub(width(%#), 6), =)]-%r
@@
&ufun`disp`footer [v(~)]=%r-[setr(f, repeat(=, div(sub(width(%#), 3), 2)))]-%qf-
@@
&~`legal [v(~)]=WARPED~core Softcode and Documentation License - http://community.pennmush.org
@@

PIGLet

PIGLet pieces.

It will be interesting to watch the differences between these two file types.

~let()


@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ========================================================================
@@ DISCLAIMER: Use at your own risk.
@@ This script is intended for the Pennmush server.
@@ Guaranteed to break if used in Rhost or MUX.
@@ See license at: http://community.pennmush.org/node/343
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ Announcement
@@
th ~> Script started.
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ UPDATE: To update an existing installation, set the following line to
@@ your let() function's #dbref. Otherwise, let it set a blank attribute to
@@ begin a fresh installation (i.e., leave it alone).
@@
&~ me=
@@
@@ Setting the above line is all you need to do. Make sure you did it
@@ and that you did it the way you wanted. No further changes needed.
@@
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ Update/Creation Announcement and Implementation...
@@
th ~> [ifelse(isdbref(v(~)), Updating, Installing[attrib_set(me/~, create(~let function))][attrib_set(v(~)/DATA, v(~))])]: [name(v(~))]...
@@
@@
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ Library
@@
th ~> [ifelse(dec(words(lparent(v(~)))), Checking, Creating [name(parent(v(~), setr(0, create(Font Library 1))))][attrib_set(%q0/describe, name(%q0))])]
@@
@@
@@ ------------------------------------------------------------------------
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ Preparation
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@ Credits.
@@
&CRED`COPYRIGHT [v(~)]=© Copyright 2007, Chuc McGuire
&CRED`LICENSE [v(~)]=WARPEDcore Softcode and Documentation License, http://community.pennmush.org/node/343
@@
@set [v(~)]=DATA`ANSIORDS:[iter(h H u U i I x X r R g G y Y b B m M c C w W, ord(%i0))]
@@
@@ Tweak ~let() with no args so that it lists installed fonts after the #dbref.
@@
@@ ~let()
@@ ~let(<font[:<ansi>]>, <string>)
@@
&UFUN`~LET [v(~)]=localize(ifelse(nor(words(%0), words(%1)), %! [iter(lattrp(me/FONT`), after(%i0, `))], switch(1, t(words(setr(e, u(UFUN`ERCK`FONT, setr(f, first(%0, :)))))), %qe, t(words(setr(e, u(UFUN`ERCK`STRING, setr(s, %1))))), %qe, setq(a, u(UFUN`ESET`ANSI, rest(%0, :)))[u(UFUN`DISP, %qf, %qa, %qs)])))
@@
&UFUN`DISP [v(~)]=map(UFUN`DISP2, lnum(1, words(v(FONT`%qf`032), |)), %b, %r)
&UFUN`DISP2 [v(~)]=setq(0, %0)[foreach(UFUN`DISP3, %qs)]
&UFUN`DISP3 [v(~)]=map(UFUN`DISP4, elements(v(FONT`%qf`[rjust(ord(%0), 3, 0)]), %q0, |), %b, )
&UFUN`DISP4 [v(~)]=ansi(%qa[first(%0, \, )], chr(rest(%0, \, )))
@@
@@
@@ &~letlen()
@@
&UFUN`~LETLEN [v(~)]=localize(switch(1, t(words(setr(e, u(UFUN`ERCK`FONT, setr(f, first(%0, :)))))), %qe, t(words(setr(e, u(UFUN`ERCK`STRING, setr(s, %1))))), %qe, lmath(add, foreach(#lambda/words(first(v(FONT`%qf`\[rjust(ord(\%0), 3, 0)\]), |))\%b, %qs))))
@@
&UFUN`ERCK`FONT [v(~)]=ifelse(hasattrp(me, FONT`%qf), , u(UFUN`EMSG-1, %qf))
@@
&UFUN`ERCK`STRING [v(~)]=localize(foreach(#lambda/\[ifelse(hasattrp(me, FONT`%qf`\[rjust(ord(\%0), 3, 0)\]), , setq(e, \%qe \%0))\], %0)[if(words(%qe), u(UFUN`EMSG-2, %qf, %qe))
@@
&UFUN`ESET`ANSI [v(~)]=foreach(#lambda/if(member(v(DATA`ANSIORDS), ord(\%0)), \%0), %0)
@@
&UFUN`EMSG-1 [v(~)]=#-1 No such font: %0
@@
&UFUN`EMSG-2 [v(~)]=#-2 Unsupported character(s) in font %0: %1
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
&HELP`~LET [v(~)]=%r~let()%r~let(<font\[:<ansi>\]>, <string>)%r%rwith no arguments returns the #dbref of the ~let function object, followed by a list of all installed fonts.%r%rif <font> (optional :<ansi>) and <string> are provided, it returns one of the following...%r%r#-1 if <font> does not exist.%r#-2 if there are characters in <string> which aren't supported in <font>%ror, <string> in <font> with optional <ansi> applied.%r%rFor example, see: +help ~let2
@@
&HELP`~let2 [v(~)]=%rExample: think ~let(isometricsm:bh, M U S H)%r[~let(isometricsm:bh, M U S H)]%r
@@
&HELP`~letlen [v(~)]=%r~letlen(<font>, <string>)%r%rreturns the actual screen width of <string> displayed in <font>, or the following errors%r%r#-1 if <font> does not exist.%r#-2 if there are characters in <string> which aren't supported in <font>%r
@@
@@ ========================================================================
@@ .:....1....:....2....:....3....:....4....:....5....:....6....:....7....:
@@ ------------------------------------------------------------------------
@@
@@ From Javelin: add the following to a wiz object's @startup
@@
@@ @function ~let=<#dbref>, ufun`~let
@@ @function ~letlen=<#dbref>, ufun`~letlen
@@