Ian says, "For example, how do you add together numbers with commands?" Ian says, "So, commands alone aren't generally sufficient to softcode things that display intricate or well-formatted bits of information... Like a +who, +where, +finger, etc.." Ian says, "For information processing, generally one resorts to functions." Ian says, "Commands have very free looking syntaxes besides starting with the command name. Typically a command will look like " Ian says, "Functions have a very strict syntax." funcname(arg1,arg2,arg3,...) Ian says, "Commands can be useful by themselves in any action list..." Ian says, "But, in general, functions are only useful in certain places." Ian says, "Typically, that means embedded in an argument of a command." Ian gives an example. Ian types -=> say time() Ian says, "Wed Aug 03 19:39:04 2005" Ian says, "You'll note that time() is a function that takes no arguments (just as the 'look' command can take no arguments)" Ian says, "You'll also note that all I did was put it where I might normally type my own text to speak." Ian says, "And the MU parser picked it up and "returned" a value." Ian says, "Within function arguments can be other functions. (called nesting)" Ian types -=> say add(1,mul(2,3)) Ian says, "7" Ian says, "That is, 1 + (2*3)." Ian says, "Some functions take a variable number of arguments (like add())" Ian types -=> say add(1,2) Ian says, "3" Ian types -=> say add(1,2,3) Ian says, "6" Ian says, "The key thought to functions is that they're embedded into commands. And commands demand string input. So, functions are really string mechanisms." Ian says, "So, what do I do if I want to have the output of two functions next to eachother?" Ian says, "The most intuitive solution would be to put one function call after the other." Ian types -=> say time()time() Ian says, "Wed Aug 03 19:44:09 2005time()" Ian says, "Yet, it's easy to reveal that this doesn't work as one may haveh oped." have hoped* Ian says, "Here's why.." Ian says, "Or, here's how, excuse me." Ian says, "Enclose the second function call in brackets ([])" Ian types -=> say time()[time()] Ian says, "Wed Aug 03 19:46:10 2005Wed Aug 03 19:46:10 2005" Ian says, "What if one wants to have a function call directly after some text?" Ian types -=> say pie time() Ian says, "pie time()" Ian types -=> say pie [time()] Ian says, "pie Wed Aug 03 19:47:12 2005" Ian says, "Again, brackets." Ian says, "In general, if a function does not start an argument of a command or another function, it needs brackets around it to be evaluated." Ian says, "So, we know we can put functions into arguments of commands.. We know we can nest functions.. And we know how to concatenate their results." Ian says, "This is the basis of most globals coding syntax (besides substitutions which were discussed last talk)." Ian says, "The hard part is learning how to use all the functions. ;-)" Ian says, "Sooo, I'll try to build several things that progressively use a larger variety of functions." Ian says, "First thing I'll build is an OOC time command." Ian dropped Blobject. Vadiv has arrived. Ian says, "With most globals commands, you'll only want to display something to the person who triggered the command.. And that'll almost always be the enactor.." Ian says, "You'll recall that the enactor's #dbref is readily available via the %# substitution?" Ian says, "So, many global commands start with: @pemit %#= OR @pe %#=" Ian says, "An important note.. It is usually a bad idea to use @pemit *%n=" Ian says, "Hypotherical case: If I made a puppet named Brazil and typed a command that used @pemit *%n=, what would happen?" Ian ers, Hypothetical. ;-) Odin says, "It would fail, since *Odin only works on players." Odin says, "Eh. ;)" Odin says, "You get the drift anyways." Ian says, "But Brazil is a player." Ian says, "So, he'd see the message instead of my puppet. ;-)" Ian says, "So, anyways.. We were making that OOC time command." Ian types -=> &c.time blobject=$+ooctime:@pemit %#=time() Geo has left. Odin says, "So %n refers to the player controlling the object triggering the action queue, while %# would refer to the puppet?" Ian says, "%n is the name of the object which triggered the code." Ian says, "%# is the #dbref of the object which triggered the code." Ian says, "But *%n refers to "the player that has the name of the object which triggered the code."" Odin says, "Oh, sorry. I didn't pay attention to the name of the puppet. ;)" Ian nods, NP. Ian says, "So, we'll note that this command look very bland when typed. It just gives the standard-issue format of what time the MU thinks it is." Ian says, "If one types 'help time()', information on the time function can be viewed and one sees it can accept more arguments, but there's nothing we can do with them that helps us spruce this up. So, maybe we should say on the output that it's OOC time." Ian types -=> &C.TIME Blobject=$+ooctime:@pemit %#=OOC Time: [time()] Ian says, "Note that I bracketed the function now since it doesn't begin the argument of the command anymore." TIME() FUNCTION: time([][, ]) The optional parameter may be "utc" or "local". If no is given, "local" is assumed. local - Gives you the current local time string of the machine the MUX is running on. This time is affected by the daylight savings time (or 'summer') rules in force at the server's location. utc - Gives you the time string for the UTC time zone. determines the number of fractional seconds shown. By default, no fractional seconds are shown. Example: > say time() You say "Fri May 05 13:05:39 2000" > say time(utc,3) You say "Fri May 05 20:05:39.667 2000" Related Topics: convsecs(), convtime(), secs(). Ian types -=> +ooctime Ian sees: OOC Time: Wed Aug 03 19:57:21 2005 Ian says, "Again, this is rather dry." Ian says, "But suppose I wanted to display the _IC_ time." Ian says, "And that every second of IC time was equivalent to every second of OOC time.. Except, the year 2000 OOC was the year 2050 IC." Ian says, "For that we need a few new functions." Ian says, "We'll want to somehow 'add' an period to the current time.." Ian says, "But addition is easiest with numbers." Ian says, "Note that at the bottom of the helpfile on time() is a "Related Topics:" line." Ian says, "And within that is secs().. for seconds.." Ian says, "And seconds are very easy to manipulate with math functions like add()." Ian says, "So.. We'll do something like add(secs(),)" Ian says, "But the question is.. add how much?" Odin says, "Bring out your mul()s. ;)" Ian says, "Well, if we knew how many 'seconds' were between two equivalent dates were in IC and OOC time..." Ian says, "Then we could just add that." Ian says, "So, looking at the bottom of time() again we see convtime() and convsecs(). convtime() converts time into seconds. Convsecs() does precisely the opposite." Ian types -=> say sub(convtime(Wed Aug 03 20:00:45 2050),convtime(Wed Aug 03 20:00:45 2000)) Ian says, "1577836800" Ian says, "That is.. I convert the time fifty years from a certain date in 2000 to seconds.. And I convert the time of the same certain date in 2000 to seconds... And I subtract one from the other to get the difference." Ian says, "Is this really fifty years?" Ian types -=> say fdiv(1577836800,mul(24,60,60,365)) Ian says, "50.032876712328765" Ian says, "Hm, well, it's.. almost right. But why the funky fraction?" Ian says, "Remember, there's leap years and all of that. ;-)" Ian says, "So, this is only 'about right' -- close enough for IC time purposes." Ian says, "Thus far, I want add(secs(),1577836800)... But I want that to be displayed as a time rather than in seconds." Ian says, "So I use convsecs() to convert seconds to time." Ian --> convsecs(add(secs(),1577836800)) Ian types -=> &c.ictime blobject=$+ictime:@Pemit %#=IC Time: [convsecs(add(secs(),1577836800))] Ian types -=> +ictime Ian sees: IC Time: Tue Aug 03 20:05:51 2055 Ian says, "Any questions / comments thus far?" Ian moves onto some formatting stuff. Ian says, "Often you'll have a list of items (such as players or objects) which you'll want to display information about. Again, the big ticket globals come to mind: +who, +where, +staff/+admin" Ian says, "Typically you'll want information about each item on its own line, but you want the columns for each line to line up." E.g. One Two Three Four Ian says, "Enforcing the width of a string varies slightly from codebase to codebase, but in any codebase, there's three primary functions:" ljust(), rjust(), and center() Ian says, "The heart of its syntax is ljust(,)" Ian types -=> @emit E.g.%r[ljust(One,20)][ljust(Two,20)]%r[ljust(Three,20)][ljust(Four,20)] E.g. One Two Three Four Ian says, "One might ask.. What if is over ?" Ian says, "This is where MUX and Penn differ." Odin was going to. :P Ian says, "We're on MUX." Ian types -=> @emit [ljust(pies_taste_so_yum,10)] pies_taste Ian says, "As you can see, MUX truncates it." Ian says, "Penn, OTOH, does not truncate it." Odin says, "(Neither does TinyMUSH)" Ian says, "To truncate or, in general, cut out a certain chunk of a string, you can use mid()." Ian nods to Odin. Ian says, "So, in Penn, if you want to enforce truncation, you can use something like: ljust(mid(pies_taste_so_yum,0,10),10)" Ian says, "And such code won't have any adverse effects in MUX, either." Ian says, "There's actually one more argument to those three functions, and that's the "fill"" Ian says, "That is, instead of spaces, what should I pad the text with?" Ian types -=> @emit ljust(Text,20,-) Text---------------- Ian types -=> @emit rjust(Text,20,-) ----------------Text Ian types -=> @emit center(Text,20,-) --------Text-------- Odin says, "There is also strtrunc()" Ian says, "strtrunc() is not supported in Penn, so I tend not to use it." Odin makes that "there /might/ also be strtrunc()" ;) Ian chuckles. ;-) Ian says, "MUX and Penn now support ANSI in the filler argument, BTW." Ian says, "Very handy." Ian hasn't really talked about ANSI.. He'll get into that later this session, prolly. Ian says, "With center() some nifty effects can be achieved." Ian types -=> @emit center(Text,30,-) -------------Text------------- Ian types -=> @emit center(%bText%b,30,-) ------------ Text ------------ Ian types -=> @emit center(<%bText%b>,30,-) -----------< Text >----------- Ian types -=> @emit center(<%bText%b>,30,~-) ~-~-~-~-~-~< Text >-~-~-~-~-~- Ian types -=> @emit <[center(<%bText%b>,30,~-)]> <~-~-~-~-~-~< Text >-~-~-~-~-~-> Ian says, "You get the idea. ;-)" Ian says, "Often, you'll have a block of space you just want to fill." Ian says, "Use space() for this." Ian types -=> @emit space(20)Hi[space(20)]there Hi there Ian says, "Sometimes you'll want it to be something other than a space..." Ian types -=> @emit repeat(-,20)Hi[repeat(-,20)]there --------------------Hi--------------------there Ian says, "Sometimes you'll want it to have more than one character..." Ian types -=> @emit repeat(-~,20)Hi[repeat(-~,20)]there -~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~Hi-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~-~there Ian says, "But repeat() is a rather literal interpretation.." Ian says, "So, if you're repeating a string of length two 20 times.. You get a string of 2*20=40." Ian says, "One possible workaround..." Ian types -=> @emit rjust(,20,-~)Hi[rjust(,20,-~)]there -~-~-~-~-~-~-~-~-~-~Hi-~-~-~-~-~-~-~-~-~-~there Ian says, "So, we know how we can more easily align things horizontally now.." Ian says, "But that doesn't help us unless we can walk through a list of data and do something for each item on that list." (Remember, we're floating towards +who) Ian says, "So, first of all, what is a 'list' exactly in MU*land?" Ian says, "It's an ordered collection of strings seperated by a delimiting character (just called a delimiter)" Ian says, "For example.." we|are|the|pie Ian says, "That could be a pipe (|) delimited list." we are the pie Ian says, "That could be space delimited." Ian says, "Or.." Ian says, "It could be 'e'-delimited. It all depends on the code's interpretation of it." Ian says, "The 'e' delimited list would be: we are the pie" Ian says, "Note that after the last 'e' is also an 'item'.. Just a blank item." Ian says, "Also note that MUSHes treat space-delimited lists special. There are no blank items in space delimited lists (typically) because double-spaces are clumped together automatically." Ian says, "So, we know what a list is. What good is that?!" Ian says, "Well, there's lots of things one could do with a list (ohboy).." Ian says, "Like, count how many items are in it." Ian says, "For this, one uses the words() function." Ian says, "words() is somewhat misnamed, sadly.. ;-)" Ian types -=> say words(we are the pie) Ian says, "4" Ian types -=> say words(we|are|the|pie,|) Ian says, "4" Ian types -=> say words(we|are|the|pie,,e) Ian says, "#-1 FUNCTION (WORDS) EXPECTS BETWEEN 0 AND 2 ARGUMENTS" Ian bahs. Nice job, Ian. ;-) Ian types -=> say words(we|are|the|pie,e) Ian says, "5" Ian types -=> say words(we|are|the|pie|,) Ian says, "1" Ian types -=> say words(we|are|the|pie|,|) Ian says, "5" Ian types -=> say words(we|are|the|pie,|) Ian says, "4" Ian says, "So, again.." Ian types -=> say words(we|are|the||pie,|) Ian says, "5" Ian says, "You can have zero-length items in your list." Ian says, "But, really, what we wanted to do in the first place with a list.. was to go through it.. and do something with each item." Ian says, "In otherwords, we want to iterate over the list." Ian says, "For that, there's the suitably-named iter()" Ian says, "Its syntax is roughly as follows.." iter(,,,) Ian is going to give an example first. Then he'll explain what's going on. Ian types -=> say iter(we are the pies yummy,strlen(itext(0))) Ian says, "2 3 3 4 5" Ian says, "So, the list in this case is "we are the pies yummy"" Ian says, "We don't specify any special delimiter, so the input and output delimiters are assumed to both be spaces." Ian types -=> say iter(we are the pies yummy,strlen(itext(0)),e) Ian says, "1 3 3 3 7" Ian says, "Note how if I specify an input delimiter, the output delimiter is still a space by default for THIS function." Ian says, "Have to be careful with that, though.. Not all functions are like that." Ian grins. Yes, we are very 13337. Ian says, "So, the list is pretty clear, IMO.. What's not so clear is the second argument: strlen(itext(0))" Odin says, "Hm. I do not completely unterstand ze itext() resultses. :P" Ian says, "strlen(), as per the helpfiles, returns the visual length of a string." Ian types -=> say strlen(12345) Ian says, "5" Ian says, "itext(), however, is not so clear." Ian says, "The cryptic looking name, I believe, means "iter-text"." Ian says, "That is, the morsel of text that iter() is feeding it." Ian says, "Let's make it a little more clear." Ian types -=> say iter(we are the pies yummy,|[itext(0)]|) Ian says, "|we| |are| |the| |pies| |yummy|" Ian says, "Since you could have more than one iter() in itself, it is desirable to specify to itext() which iter() you wanted information from." Ian says, "It starts counting at 0.. And 0 roughly means "the last iter seen"." Ian says, "Clear as mud, right?" [>>Public] Right brainers rule! Faolin has connected. Faolin has arrived. Ian gives an example of nested iters.. Faolin waves to all. Ian types -=> say iter(one two,iter(A B,itext(0):[itext(1)])) Ian says, "A:one B:one A:two B:two" Ian says, "In this case, the 'last seen iter()' that itext(0) refers to is the one containing A B... And the 'second to last' is the one containing 'one two'." Ian says, "There's two more functions that are special to iter()." Ian says, "inum(): How far are we in the list?" Ian says, "ilev(): How many iter()s deep are we?" Ian will show examples. People can figure them out on their own, hopefully. ;-) Ian types -=> say iter(A B C,inum(0):[itext(0)]) Ian says, "1:A 2:B 3:C" Ian types -=> say iter(A B C,ilev():[itext(0)]) Ian says, "0:A 0:B 0:C" Ian types -=> say iter(A B C,iter(one two three,ilev())) Ian says, "1 1 1 1 1 1 1 1 1" Ian types -=> say iter(A B C,ilev():[iter(one two three,ilev(),,-)]) Ian says, "0:1-1-1 0:1-1-1 0:1-1-1" Ian says, "A brief reminder.. Interrupt me if you have a question." Ian says, "Chances are someone else would benefit from it. ;-)" Ian says, "Understanding iter() is very important. Any questions?" Faolin raises her hand, "Is it just me or does the first letter in your name keep changing colors?" :) Ian says, "It does." Ian says, "Must be a bug in MUX.." Ian whistles. Faolin nods, "Sure...tell me another one." :) Ian says, "We've got all the basic programming tools we need. Now all we have to do is fill in and get data." Ian says, "So, we want a +who.." Ian says, "What should +who display? A list of people connected, of course!" Ian says, "And for that list of people connected, there's lwho().. "List-who" is the way I think of that, but I don't really know what it means. ;-)" Ian types -=> say lwho() Ian says, "#50 #203 #452 #775 #693 #4 #317 #205 #437 #898 #632 #925 #794 #440 #364 #883 #142 #11 #885 #752 #2 #389 #567 #397 #13 #12 #9 #8" Ian says, "It returns a space-delimited list of connected players." Ian says, "The first thing we'll want are their names." [>>Public] Sirene has connected. Ian ponders.. "But before that.. For purposes of not getting spammed everytime I type an example.." Ian says, "We're going to shorten that list down.. And we can do that with the extract() function.. extract() is like mid(), except instead of getting chunks of characters, you get chunks of items from a list." Ian says, "Example.." Ian types -=> say extract(we are the pies are the pies are yummy,3,2) Ian says, "the pies" Ian says, "So, we're going to use extract() to get the first five items of lwho()." Ian types -=> say extract(lwho(),1,5) Ian says, "#962 #50 #203 #452 #775" Ian says, "So, we want this to be a list of names.. How do you find out what the name of something is? Via name()!" Ian types -=> say name(#50) Ian says, "Faolin" Ian types -=> say iter(extract(lwho(),1,5),name(itext(0))) Ian says, "Sirene Faolin exoteris Odin bjbkk" Ian says, "This is nice and all, but we'd like each name to be on its own line so we can pack more data in later.." Ian says, "Getting things on their own line is easy.." Faolin says, "Question, you have numbers at the end of your lwho(), what do they do?" Ian says, "But there's a few gotcha's to it all." Ian says, "the lwho() is in an extract()" Ian says, "And extract() allows one to get a chunk of items from a list.." Ian says, "In this case, we start with the first item, and we get five items." Ian is doing that for example purposes so when things are on their own line, we don't get spammed with the numerous examples. Faolin says, "Oh, I get it." Ian says, "One generall makes a newline with %r.." Ian says, "But %r happens to be more than one character.. And back in the day, delimiters could not be more than one character.. And back in the day wasn't so long ago. ;-)" Ian says, "For the most part, you can use %r as an output delimiter anymore. So, we'll do that here." Ian types -=> @emit iter(extract(lwho(),1,5),name(itext(0)),,%r) Sirene Faolin exoteris Odin bjbkk Ian says, "Notice how I completely left the input delimiter out.. and the MU* assumed the default delimiter of space." Ian says, "So, this isn't a bad start." Ian says, "But we want more information than that." Ian says, "We want, say.. People's gender." Ian says, "Nicely formatted gender, too. ;-)" Ian says, "Genders are usually publically accessible via the 'sex' attribute.. So, the question is, how do we get attributes from objects?" Ian says, "With get() or xget()" Ian says, "The two are nearly identical. Here's an example of their uses." Ian types -=> @emit get(#13/sex) Male Ian types -=> @emit get(#13,sex) #-1 FUNCTION (GET) EXPECTS 1 ARGUMENTS Ian bahs. Ian types -=> @emit get(#13/sex) Male Ian types -=> @emit xget(#13,sex) Male Ian says, "There's reasons for using xget() habitually which I won't discuss now, but it's sufficient to say that I recommend it over get()." Ian says, "So I'll use it in my examples." Ian types -=> @emit iter(extract(lwho(),1,5),name(itext(0)) [xget(itext(0),sex)],,%r) Sirene Flabulous dahlink. Faolin Female exoteris Odin Male bjbkk Ian says, "So, I just slapped in the xget() on the end.. But, doh, it looks ugly!" Ian should probably ensure that people's names take up a certain amount of space each time. Ian types -=> @emit iter(extract(lwho(),1,5),ljust(name(itext(0)),20,-) [xget(itext(0),sex)],,%r) Sirene-------------- Flabulous dahlink. Faolin-------------- Female exoteris------------ Odin---------------- Male bjbkk--------------- Ian says, "Like, say.. That." Ian says, "Now for a useful hint when coding.." Ian says, "Notice how I didn't fill with spaces.. I filled with dashes." Ian says, "That's useful for seeing where your fields are and how things line up. You can change them back to spaces later when you're done." Ian types -=> @emit iter(extract(lwho(),1,5),ljust(name(itext(0)),20,-) [xget(itext(0),sex)]|,,%r) Sirene-------------- Flabulous dahlink.| Faolin-------------- Female| exoteris------------ | Odin---------------- Male| bjbkk--------------- | Ian often puts a pipe at the end like that to see where his lines end.. Because often he'll want his line ends to all line up so they don't display improperly on narrow screens. Ian says, "Okay, so we've got the start of some columns.. But those genders aren't what we had hoped for because people can set their gender attributes to anything." [>>Public] Sirene has disconnected. Ian says, "We want to 'sanatize' people's genders so they display as.. hmm... Male, Female, or Neuter?" Ian says, "The classic way of doing this.. if it starts with M, male. If it starts with F, female. Otherwise, Neuter." Ian says, "For this, we'll introduce yet another function." Ian says, "Wildcards often come into play with recognizing strings.." Ian says, "And you'll recall that last time, we used @switch.. and @switch allows for matching with wildcards." Ian says, "Paralleling @switch, there's a switch() function." Ian says, "It works much the same." switch(,,,,,...,) Ian says, "Remember, patterns (designated by pat#) can be wildcard patterns." Ian says, "Now, a note about the text# arguments.." Ian says, "The text# arguments are ONLY considered if the corresponding pattern matches ." Ian says, "And by considered, this means that the code is looked at and evaluated." Ian says, "This may be somewhat expected, as @switch only entered action lists it contained if the corresponding pattern to an action list matched its selector string." Ian says, "Soooo.. Some examples of switch()." Ian types -=> say switch(dog,cat,meow,dog,woof,not domesticated) Ian says, "woof" Ian types -=> say switch(turnip,cat,meow,dog,woof,not domesticated) Ian says, "not domesticated" Ian types -=> say switch(cat,cat,meow,dog,woof,not domesticated) Ian says, "meow" Ian types -=> say switch(fat cat,cat,meow,dog,woof,not domesticated) Ian says, "not domesticated" Ian says, "Hmm.. Well, using wildcard patterns, we can get away with a lot." Ian types -=> say switch(fat cat,*cat,meow,*dog,woof,not domesticated) Ian says, "meow" Ian types -=> say switch(ugly dog,*cat,meow,*dog,woof,not domesticated) Ian says, "woof" Ian types -=> say switch(scat,*cat,meow,*dog,woof,not domesticated) Ian says, "meow" Ian ponders.. That's probably not what we had hoped. Ian says, "So, we can seperate the case of *cat into 'cat' and '* cat' to ensure that it either has a space.. or it's exactly cat." Ian types -=> say switch(scat,cat,meow,* cat,meow,*dog,woof,not domesticated) Ian says, "not domesticated" Ian says, "So, how does that apply to our situation?" Ian says, "Any takers, or should I go through the numbers? :)" Ian says, "Well, let's see.." Ian says, "So, if we see anything starting with m.. it should return 'male'" Ian says, "Otherwise, Neuter." Ian types -=> say switch(MUX,m*,Male,Neuter) Ian says, "Male" Ian types -=> say switch(Feline,m*,Male,Neuter) Ian says, "Neuter" Ian says, "Hmm, well, if it begins with F like Feline does.. Should say Female..." Ian types -=> say switch(Feline,f*,Female,m*,Male,Neuter) Ian says, "Female" Ian types -=> say switch(Feline,f*,Female,m*,Male,Neuter) Ian says, "Female" Ian acks, sorry. Ian types -=> say switch(MAnLY,f*,Female,m*,Male,Neuter) Ian says, "Male" Ian says, "There's all sorts of cute uses of switch() that save a lot of effort." Ian says, "That's one of them. ;-)" Ian says, "So, putting this into our code.." Ian says, "We had.." Ian types -=> @emit iter(extract(lwho(),1,5),ljust(name(itext(0)),20,-) [xget(itext(0),sex)]|,,%r) Faolin-------------- Female| exoteris------------ | Odin---------------- Male| bjbkk--------------- | Bonn---------------- | Ian says, "And now.." Ian types -=> @emit iter(extract(lwho(),1,5),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male,Neuter)]|,,%r) Faolin-------------- Female| exoteris------------ Neuter| Odin---------------- Male| bjbkk--------------- Neuter| Bonn---------------- Neuter| Ian says, "Much better." Ian says, "As a side note, notice how the ends of our lines almost add up!" Ian says, "Except for the case of 'Male'.." Ian says, "We could use ljust() here.." Ian says, "Or, we could just make male() take up two more spaces.." Ian says, "And I'd go with that route, because then the MU* doesn't have to parse another function. As a general rule of thumb, substitutions are blazing fast compared to functions." Ian types -=> @emit iter(extract(lwho(),1,5),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)]|,,%r) Faolin-------------- Female| exoteris------------ Neuter| Odin---------------- Male | bjbkk--------------- Neuter| Bonn---------------- Neuter| Ian says, "Now it all lines up. :)" Ian says, "So, let's see.. What kind of other stuff would we want to include.. Hmm. ;-)" Ian says, "Typical stuff is how long people have been connected.." Ian says, "How long they've been idle.." Ian says, "Their alias.." Ian says, "And where they are." (Location) Ian says, "Alias is very similar to sex, except we don't have to do all the sanatizing. It's just an attribute, so you can get it with xget() or get(). I'm not going to go through it. Anyone mind?" Faolin doesn't mind. Ian :) Ian says, "So, let's move onto connection and idle time." Odin says, "Nah, skip ahead. :)" Ian says, "You can get how long someone has been connected or idle for with conn() and idle(), respectively." Ian types -=> say idle(%!) [idle(*Odin)] Ian says, "0 27" Ian says, "idle(%!) returns 0 because %! is my #dbref.. And I'm not idle when I'm entering that command." Ian says, "So, I've been idle for zero seconds." Ian says, "So, putting this into our code.." Ian types -=> @emit iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [idle(itext(0))][conn(itext(0))]|,,%r) Faolin-------------- Female 82109| exoteris------------ Neuter 41975513| Odin---------------- Male 8718594| bjbkk--------------- Neuter 21327698| Ian bahs. ;-) Faolin says, "Question." Ian types -=> @emit iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [idle(itext(0))]/[conn(itext(0))]|,,%r) Faolin-------------- Female 1/2120| exoteris------------ Neuter 4208/5524| Odin---------------- Male 98/18606| bjbkk--------------- Neuter 224/27709| Ian nods? Ian says, "Faolin? :-)" Faolin says, "You have [idle(*Odin)]...Hm, I think I see the answer in your example. the *Odin was just an example." Ian ahs, sorry. Ian nods. Faolin says, "Sorry, typing in the dark and my keys don't light up. :)" Ian says, "We didn't really cover asterisks syntax last time, though." Ian's keys light up, but they tell him to kill himself! Ian says, "So I stopped looking at them." Ian whews. Faolin grins Ian says, "But the number of seconds returned by idle() and conn() look very ugly." Odin likes the pretty ints. Ian says, "It'd be nice to put that into, say.. minutes.. But people are often idle for more than 60 minutes.. So maybe we want hours and minutes.." Ian says, "But there's always a good chance that someone idles for a whole day!" Odin says, "And more. ;)" Ian says, "When writing globals, you're faced with a very serious challenge." Ian . o O ( Oh, Lord, do I remember the days of hellspawn. ) Odin says, "Like Narilka. ;)" Odin . o O ( DWR, Ian. DWR. :) ) Ian says, "DWR? Where's that? Imposter!" Ian says, "Er, anyways.." Ian says, "You want to pack as much info as you can into a global.. which means you want to save space.. but it should still be easy to read." Ian says, "Somewhat conflicting goals." Ian says, "A common solution is the 'single time' type of format." Ian says, "Up to 59 seconds is displayed as #s (for example, 5s for 5 seconds)" Ian says, "Up to 59 minutes, #m" Ian says, "Up to 23 hours, #h" Ian has to be careful, though. Ian types -=> say singletime(59) Ian says, "59s" Ian types -=> say singletime(119) Ian says, "1m" Ian types -=> say singletime(120) Ian says, "2m" Ian says, "Is 119 seconds really one minute? No, but it's rounded down to the nearest minute." Ian says, "Like wise, 3599 seconds is 59 minutes and 59 seconds.. But for display purposes, that's 59 minutes." Ian says, "And likewise for 86399 23 hours. ;-)" Ian says, "In MUX, there's an easy way of formatting it for this display type." Ian just showed it.. singletime() Ian says, "There's also digittime() which mimics the 'on for' part of WHO" Ian says, "Where singletime() mimics the 'idle' column of WHO." Ian isn't sure what the best way to do that is in Penn. Ian says, "So, if someone could donate that piece of information, I'd be very thankful. ;-)" Ian just did a quick check. Ian says, "One possible solution is first(timestring())" Odin says, "Another is the time-honored way of recursive switches and mul/div/rest()s." Ian notes first() returns the first item in a list like before() does. rest() or after() returns everything else. last() gets the last item in a list. Ian says, "Ah, yes." Ian says, "Back in the day.." Ian says, "We didn't have any of those counfoundin' easy time formatting functions!" Ian ... "Thank God it's not back in the day." Ian says, "For educational purposes, here's what it would look like.." Faolin says, "Ack! The +who on my game is f'ugly." Ian laughs. Ian says, "Actually, I can't really show you what it looks like without stack argument substitutions in functional expressions.." Faolin says, "Looks like we have a separate attr for each special section on the +who" Ian says, "You should. Makes it easier to understand and code." Ian says, "So, we'll just use singletime() for now." Grey says, "Unless you you're one of the few like me who likes to code offline in a formatted version. ;)" Ian has some choice words for you. Faolin says, "Did you want to see how our coder did the time for our game? We're running Penn, that's why I looked." Ian types -=> @emit iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)]/[rjust(singletime(conn(itext(0))),3)]|,,%r) Faolin-------------- Female 0s/48m| exoteris------------ Neuter 1h/ 1h| Odin---------------- Male 15s/ 5h| bjbkk--------------- Neuter 1m/ 7h| Ian says, "Probably ought to take out the /. It looks ugly." Faolin-------------- Female 20s 48m| exoteris------------ Neuter 1h 1h| Odin---------------- Male 35s 5h| bjbkk--------------- Neuter 2m 7h| Ian says, "There we go." Ian says, "So, eh, what other info do we want on this beast?" Ian notes to Faolin, "Not right now. ;-)" Ian says, "Thanks for the offer, though!" Malakite needs to get in the top 5 connected sometime :) Faolin nods, "No problem." Ian ponders. We could do that. Ian says, "I think the last thing I'll include is location." Ian says, "To get where something is.. Use where()." Grey says, "Maybe a IC/OOC note, showing if the player is set IC or OOC at the time." Ian says, "For example." Ian says, "Not a bad idea, Grey. Hm. I like that, so I'll talk a little about it after location." Ian says, "Example of where().." Ian types -=> say where(*Odin) Ian says, "#399" Ian types -=> say where(here) Ian says, "#-1" Ian notes that here is a room.. And a room can't be in anything. ;-) Odin says, "Oh noes! The room is nowhere!" Ian says, "So it returns an impossible #dbref as an error." Ian says, "So.. We don't just want where someone is.." Ian says, "We want the name of where they are." Ian types -=> say name(where(*Odin)) Ian says, "The Lecture Hall" Ian says, "Which we already covered.. with name(). :)" Ian says, "But there's a few sticky notes here." Ian says, "Dealing with information is a dangerous business.. You want to be sure not to leak anything important.." Ian says, "Like displaying dark people to mortals.." Ian says, "Or showing people where UNFINDABLE people are." Ian says, "The code you make has the powers of whatever object it's on." Odin drumrolls for... objeval()? Ian says, "Nah, we're going with findable() on this one." Ian says, "findable() returns a boolean. True if can find . False otherwise." Ian says, "So, we'll need to know how MU*s handle booleans." Ian says, "#-1 and 0 are considered to be false." Ian says, "Anything beginning with #-1 is false, actually." Ian says, "Most other strings are true -- with VERY few exceptions dependent on codebase." Ian says, "For example, in MUX, the string "NaN" is false. NaN represents "Not a Number"" Ian says, "Onwards.." Ian says, "Findable() isn't something anyone can use on any objects, though." Ian says, "Findable() _requires_ that the person trying to use it "controls" ." Grey is Ronan. Ian says, "In MUX, there's 6 rules of controlling. You control anything you own. Anything set INHERIT that you own controls anything you own including you. Etc, etc.. wizards control everything. Type 'help control' for the full thing (in MUX)." Ian says, "So, if we use findable(), our code will REALLY only work if our object has wizard powers." Ian says, "But if we give it wizard powers.. then lwho() shows dark people. Hmm. ;-)" Ian says, "Let's get location out of the way, and then we'll deal with dark people." Ian says, "So, we can use findable(%#,itext(0)) to find out if %# can find itext(0).. This will return 1 if they can, 0 if they can't." Ian says, "We could make this the selector string of a switch().. But, there's a special function for booleans that's faster." Ian says, "It's called ifelse()." Ian says, "if true, do this.. otherwise, do that." Ian says, "Sorry, IRL interruption. Back now." Ian says, "ifelse() looks like this.." Ian hehs, oops. ifelse(,,) Ian says, "As in switch(), only one case has its code evaluated." Ian says, "So, so far.." ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *) Ian says, "We have.." Ian types -=> @emit iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)]|,,%r) Faolin-------------- Female 25s 1h| exoteris------------ Neuter 1h 2h| Odin---------------- Male 5m 5h| bjbkk--------------- Neuter 1m 8h| Ian now puts in the location stuff. Ian types -=> @emit iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *)]|,,%r) Faolin-------------- Female 57s 1h The Lecture Hall| exoteris------------ Neuter 1h 2h The Lecture Hall| Odin---------------- Male 21s 5h The Lecture Hall| bjbkk--------------- Neuter 2m 8h Cram it in your bjbkk hole| Ian says, "So far, so good.." Ian says, "We've done a lot. Any questions so far?" Odin shakeshakes. Grey says, "Nope." Faolin says, "None here." Ian says, "At this point, you might be wondering "just how wide is this?"" Ian types -=> @emit iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *)]|,,%r)%r[repeat(1234567890,8)] Faolin-------------- Female 24s 1h The Lecture Hall| exoteris------------ Neuter 1h 2h The Lecture Hall| Odin---------------- Male 38s 5h The Lecture Hall| bjbkk--------------- Neuter 4m 8h Cram it in your bjbkk hole| 12345678901234567890123456789012345678901234567890123456789012345678901234567890 Ian says, "Looks like 62 wide so far because of how far bjbkk's location extends to." Odin sagely informs it is 123456789012345678901234567890123456789012345678901234567890123 wide. Ian says, "Oh, but remember, the | isn't counted. ;-)" Ian says, "It's just there to show us where the end is." Ian says, "So, now for Grey's suggestion.." Ian says, "IC/OOC status." Faolin asks a stupid question, "Well...why would we need the loc() in the +who if we might also have a +where?" Ian says, "Personal preferences." Ian gives an example.. Ian says, "The game that I co-god, +who sorts by player names. +who sorts by room name, and displays multiple players in each room." E.g. : Odin thinks he means +where for the second +who. Ian is afraid he doesn't understand then. Grey says, "Odin meant you, Ian." Odin says, "No no. /You/ said.. Yeah. ;)" Ian ohs. Ian says, "But I'm infallible! Conspiracy!" Grey hax0red your computer and did the dirty deed. Ian grins, "But, yes, +who. Thank you." Odin says, "The MUX did it." Odin says, "No. +Where. :P" Ian is confused, gives up, moves on. ;-) Ian says, "The way IC/OOC status is handled depends a good deal on the way that the +ic and +ooc commands are coded." Ian says, "Actually, this is a pretty important issue." Ian says, "So, for now, let's store the +who code and move to IC/OOC status." Ian types -=> &c.+who blobject=@pemit %#=iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *)]|,,%r) Ian types -=> &c.+who blobject=$+testwho:@pemit %#=iter(extract(lwho(),1,4),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *)]|,,%r) Ian makes it +testwho so it doesn't conflict with +who. Ian says, "People want their +ic/+ooc commands to work different ways.. But the root of the problem is.. knowing if someone's in character or not." Ian says, "And this is kind of tricky." Ian has seem places make an 'IC' flag and set IC rooms IC.. And if a player is in a room marked IC, they're considered in character. Ian ers, seen, rather. Ian has seen an attribute used.. So, if the room they're in has a certain attribute, they're considered IC.. Ian says, "Or, rooms are zoned to IC zone objects.." Ian says, "Or parented to certain parents.." Ian says, "The point is, you have to mark IC or OOC rooms _somehow_." Ian says, "Well, if you want a reliable status. ;-)" Odin also notes some make the IC/OOC distinction by attributes on the player. Ian says, "Well, some try.." Ian says, "But it's not all that fullproof." Ian says, "Or foolproof." Ian;-) Grey says, "Or a combo of both. IE the player must be be set IC via his attrib /and/ be in a room marked IC to be considered IC." Ian says, "Depends on what you want +ic or +ooc to do." Ian says, "Some places want +ic and +ooc to mark only status.. And people can wander the grid while OOC." Ian says, "A lot of places don't want that to occur." Ian says, "So, if you're in an IC room, you're IC." Ian has seem most places this way. Ian ers, seen. Odin has both heard, and possesses different views, but they don't relate to the issue at hand. :) Ian will stop typoing that, now. "I can't really say how a certain place will want it, or how they'll mark IC/OOC status, though." Ian says, "The demonstration here is, though, that the way you _store_ data is a matter of logistics." Ian says, "You want it to be. 1. Correct/secure. 2. Convenient. 3. Efficient. In that order, too. ;-)" Ian says, "Often, the "STATUS" attribute on players will be used and locked so code can set "OOC" or "IC" or maybe even stuff like "Head Wiz"." Ian says, "And then, with xget() or similar, you can see what that status attribute is.." Ian says, "And display it on their line of the +who." Ian says, "Along those lines, specifying certain attribute names that only wizard powered objects can use is important." Ian says, "You don't want players to modify certain things for whatever the reason." Ian says, "Or it needs to be modified a certain way, so they should have to use some code to do it that ensures proper formatting." Ian says, "Restricting use of attributes can be done with the @attribute command on both Penn and MUX." Ian notes under MUX it's 'wizhelp @attribute' (but only wizards can use wizhelp by default).. Ian says, "Under Penn it's 'help @attribute'" Ian gives an example of its use.. @attribute/access MYDATA=wizard !hidden Ian says, "The '!' in '!hidden' means 'not' (like flags) for 'not hidden' (people can see this attribute accounting for normal permissions)" Ian says, "'wizard' allows only wizards to change the attribute value." Ian says, "A relatively new standard in MUX is to use attribute names starting with _." Ian says, "Normally attribute names must start with a letter.." Ian says, "But attribute names starting with _ are both wizard and hidden by default." Ian says, "Penn doesn't do this by default.. And, honestly, I'm not sure if Penn can easily be set up to do this. I know it has attribute trees, but those work a tad differently." Ian takes a nice deep relaxing breath. Ian says, "Let's finish off +testwho." Ian says, "Then I'll open it up to whatever people want to talk about." Ian says, "So, we have the basic columns of a +who like info command last time we left off.." Ian says, "For now, we won't add status or anything else." Ian says, "What we WILL do is finish off the command. There's some things left that we want to display." Ian ponders, "But before that, a note about screenwidth.." Ian says, "The 'standard' screen width is 80 text columns." Ian says, "However, due to some client issues, this isn't safe. 79 tends to be safe." Ian says, "Right now we haven't bounded how long the output from location name can be.. So if someone is in a location with a long name.." Ian says, "The +who gets uglified." Ian says, "Before we do anything else, we ought to make sure that the width is proper." Ian types -=> @emit iter(extract(lwho(),1,1),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *)]|,,%r)[repeat(1234567890,8)] Faolin-------------- Female 1m 1h The Lecture Hall|12345678901234567890123456789012345678901234567890123456789012345678901234567890 Ian oops. Ian types -=> @emit iter(extract(lwho(),1,1),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *)]|,,%r)%r[repeat(1234567890,8)] Faolin-------------- Female 1m 1h The Lecture Hall| 12345678901234567890123456789012345678901234567890123456789012345678901234567890 Ian says, "So, if we look at where the location name begins.." Ian says, "Looks like at 37.." Ian says, "And we want to go to 79.." Ian says, "Sooo, that's 42 character widths." Ian types -=> @emit iter(extract(lwho(),1,1),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ljust(ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *),42)]|,,%r)%r[repeat(1234567890,8)] Faolin-------------- Female 3m 1h The Lecture Hall | 12345678901234567890123456789012345678901234567890123456789012345678901234567890 Ian says, "Looks like I was wrong.. I was off by one. Oops. ;-)" Ian counted the widths, not the positions. My'bad. Ian says, "Remember, the | is just showing us where the end is, so we want it on the '0' so the row actually ends at 79." Ian makes the correction.. "Alrighty, so there's two major parts left.." Ian says, "It'd be nice if we labelled the columns and had some sort of header.." Ian says, "And if we had some sort of footer to say "hey, we're done with this list!"" Ian says, "And for that.." Ian says, "We'll introduce u()." Odin says, "Hm. u() and me()? ;)" Ian says, "One could easily see coding a command such as this.. and having it grow.. and grow.. and getting so big that it becomes unmanagable." Ian says, "Furthermore, one may wish to reuse a piece of code elsewhere." Ian says, "A piece of _function_ based code, that is." Ian says, "u() is the @tr of functions." Ian says, "That is, if you have an expression that you want to evaluate, use u().. (or get_eval(), but that's slightly different)" Ian says, "An example.." Ian types -=> &bla me=time() Ian types -=> say u(me/bla) Ian says, "Wed Aug 03 22:05:21 2005" Ian types -=> &bla me=time() Idle: [singletime(idle(%!))] Conn: [singletime(conn(%!))] Ian types -=> say u(me/bla) Ian says, "Wed Aug 03 22:05:42 2005 Idle: 0s Conn: 1w" Ian says, "But, there's something lacking from this.." Ian says, "What if we want to pass special data.. Like we do with arguments to functions?" Ian says, "For example.. I might want u(me/bla,*Odin) to display that information about Odin." Ian says, "For that, we use the stack argument substitutions.. That is, %0 through %9." Ian --> u(me/bla,,,...,) Ian types -=> &bla me=[name(%0)] --> Idle: [singletime(idle(%0))]%b %b Conn: [singletime(conn(%0))] Ian types -=> say u(bla,*Odin) Ian says, "Odin --> Idle: 1m Conn: 6h" Ian types -=> say u(bla,*nails) Ian says, "nails --> Idle: 1h Conn: 1w" Ian says, "Now I can effectively put expressions in their own attribute, pass them some data, and reuse them like that later." Ian says, "If I name the attributes useful things.. like who.header or who.footer.. it makes it easier to find and modify code." Ian says, "And also it makes it easier to think about code. I don't have to worry about much else if I'm in my own attribute. ;-)" Ian says, "So, back to labelling the columns." Ian types -=> @emit iter(extract(lwho(),1,3),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ljust(ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *),43)]|,,%r) Minion-------------- Neuter 1m 6m Somewhere Else | Faolin-------------- Female 11m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | Ian says, "We'll use the labels: Name, Gender, Idl, Con, and Location." Ian says, "This involves a lot of counting." Ian says, "I look at the code.. I see names take up 20 spaces plus an exdtra space between names and sex.. (notice ljust(nameblabla,20-)" Ian ers, ljust(nameblabla,20,-) Ian is going to stick the code an the object. Ian types -=> &c.+who blobject=$+testwho:@emit u(who.header)[iter(extract(lwho(),1,3),ljust(name(itext(0)),20,-) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ljust(ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *),43)]|,,%r)][u(who.footer)] Ian types -=> +testwho Minion-------------- Neuter 4m 9m Somewhere Else | Faolin-------------- Female 1m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | Ian says, "Notice how empty attributes are silently ignored by u()." Ian says, "Or non-existant attributes, for that matter." Ian says, "So, who.header should start with a 'Name' label taking up 21 spaces." Ian says, "Or, easier to think of that as 20 spaces plus one separating space." Ian types -=> &who.header blobject=ljust(Name,20)%b%r Ian says, "Note that I put a %r after it because we'll want a new line for the list to be displayed starting on." Ian types -=> +testwho Name Minion-------------- Neuter 1m 11m Somewhere Else | Faolin-------------- Female 3m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | Ian says, "So far, so good." Ian types -=> &who.header blobject=ljust(Name,20)%bGender %bIdl%bCon%bLocation%r Ian says, "The rest is so close together, I think I can get away with just using spaces directly." Ian types -=> +testwho Name Gender Idl Con Location Minion-------------- Neuter 2m 12m Somewhere Else | Faolin-------------- Female 5m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | [>>Public] lain has disconnected. Ian says, "Oops, _almost_ lined up right.. But I put in one space too many before Idl." Ian types -=> &who.header blobject=ljust(Name,20) Gender Idl Con Location%r Ian types -=> +testwho Name Gender Idl Con Location Minion-------------- Neuter 3m 13m Somewhere Else | Faolin-------------- Female 5m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | Ian says, "Looks good.. But.. It's missing something.. It needs to seperate the labels somehow from the list." Ian types -=> &who.header blobject=ljust(Name,20) Gender Idl Con Location%r[repeat(-,79)]%r Ian types -=> +testwho Name Gender Idl Con Location ------------------------------------------------------------------------------- Minion-------------- Neuter 3m 13m Somewhere Else | Faolin-------------- Female 5m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | Ian says, "That looks more suitable." Ian says, "And now for the one of the last pieces.. The footer.." Ian types -=> &who.footer blob=%r[repeat(-,79)] Ian types -=> +testwho Name Gender Idl Con Location ------------------------------------------------------------------------------- Minion-------------- Neuter 4m 14m Somewhere Else | Faolin-------------- Female 6m 1h The Lecture Hall | exoteris------------ Neuter 2h 2h The Lecture Hall | ------------------------------------------------------------------------------- Ian is going to remove all the dashes and |'s since we're not using those anymore, really, for width alignment. Ian types -=> &C.+WHO Blobject=$+testwho:@emit u(who.header)[iter(extract(lwho(),1,3),ljust(name(itext(0)),20) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ljust(ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *),43)],,%r)][u(who.footer)] Ian says, "It kind of seems like wasted space to have the footer just be a bar.." Ian says, "You'll see a lot of places that say in that bar." Ian thinks we'll do that here.. But before we get there, a there's still that nagging problem of dark people. Ian says, "We'd like people to see lwho() with their own powers.. And for that, we can use objeval(). objeval(), like findable(), requires that you control an object to use objeval() on it. (See help control for more info)" Ian gives an example.. Ian ers, actually, syntax first. objeval(,) Ian says, "That evaluates from 's point of view." Odin says, "He means victim. :)" Odin, personal Ian spellchecker. [>>Public] King has connected. Ian says, "Phonics is a disservice to the written language." Ian can know the spelling for something, but spell it phonetically anyways. Ian bahs. "So, in this case, we want to evaluate lwho() from the victim's point of view." Ian says, "The victim being %# (the thing triggering the command)" Ian --> objeval(%#,lwho()) Ian types -=> &C.+WHO Blobject=$+testwho:@emit u(who.header)[iter(extract(objeval(%#,lwho()),1,3),ljust(name(itext(0)),20) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ljust(ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *),43)],,%r)][u(who.footer)] Ian types -=> +testwho Name Gender Idl Con Location ------------------------------------------------------------------------------- King Male 17s 2m Highlow Park Central Minion Neuter 11s 20m Somewhere Else Faolin Female 12m 1h The Lecture Hall ------------------------------------------------------------------------------- Ian says, "So, now for our finishing touch.." Ian says, "The "X many players connect" bar at the bottom." Ian ers, display at the bottom, rather. Ian types -=> &WHO.FOOTER Blobject=%r[center(X players connected.,79,-)] Ian says, "Question is.. What do we want for X.." Ian says, "Well, we know we can count how many items are in a list with words().." Ian says, "And we know objeval(%#,lwho()) are all the players connected.." Ian says, "So, we could se words(objeval(%#,lwho()))" Ian says, "Could use. ;-)" Ian types -=> +testwho Name Gender Idl Con Location ------------------------------------------------------------------------------- King Male 2m 4m Highlow Park Central Minion Neuter 2m 22m Somewhere Else Faolin Female 14m 1h The Lecture Hall ---------------------------< 29 players connected. >--------------------------- Ian says, "But, then we're re-evaluating something we already did." Ian says, "And sometimes that 'something' can be expensive." E.g. Takes a long time, etc.. Ian says, "There's a way of storing a bit of data temporarily.." Or hits the function invocation limit. Ian says, "Called a register." Ian says, "Please say text unless you're me. ;-P" Odin was the culprit. ;) Ian is nospoof. ;-) Ian says, "You may be familiar with registers.." Ian says, "In CPUs.." Ian says, "MUSHes have similar gadgets." Ian says, "You can set a register with the setq() or setr() functions.." Odin . o O ( #-1 OUT OF CIGARETTES error. Must debug, brb. ) Ian says, "You can get the contents of a register with %q# where # is the register name." Ian says, "In modern MUX and Penn (and MUSH3) there are 36 (or more, depending on codebase) registers.." Ian says, "Named 0 through 9.. a through z." [>>Public] lain has connected. Faolin says, "Oh no! setq()s!" Ian says, "setq() a register silently." Ian says, "setr() sets a register but returns its contents." Ian says, "The easiest way to think about how registers work are left to right. You can't access a register left of anyplace you set it (generally)." Ian says, "In reality, it's a matter of evaluation order." Ian gives examples.. Ian types -=> say setq(a,pie) Ian says, "" Ian types -=> say setr(a,pie) Ian says, "pie" Ian types -=> say setq(a,pie) A is set to: %qa Ian says, " A is set to: pie" Ian says, "u() does NOT localize registers. For that, use localize() or ulocal() (which will not be talked about now)." Ian says, "So, here's the register using version.." Ian types -=> &C.+WHO Blobject=$+testwho:@emit u(who.header)[iter(extract(setr(0,objeval(%#,lwho())),1,3),ljust(name(itext(0)),20) [switch(xget(itext(0),sex),f*,Female,m*,Male %b,Neuter)] [rjust(singletime(idle(itext(0))),3)] [rjust(singletime(conn(itext(0))),3)] [ljust(ifelse(findable(%#,itext(0)),name(where(itext(0))),* Unfindable *),43)],,%r)][u(who.footer)] Ian types -=> &WHO.FOOTER Blobject=%r[center(< [words(%q0)] players connected. >,79,-)] Ian types -=> +testwho Name Gender Idl Con Location ------------------------------------------------------------------------------- lain Female 3m 3m Highlow Park King Male 9m 11m Highlow Park Central Minion Neuter 3m 28m Somewhere Else ---------------------------< 30 players connected. >--------------------------- Ian thinks he's done with +who more or less. Questions? Ian says, "E.g. How do you make things colored" Ian has one wrap-up thing.. Ian says, "There's a lot of functions." Ian says, "Finding them can be hard." Ian --> help function classes Ian says, "Look through that helpfile sometime." Ian says, "Just browse around. See what there is. What things do. Experiment. Etc.." Ian says, "If you're not sure if a function does or doesn't do something.. test it! You don't have to ask someone _everytime_. ;-)" Ian says, "But.. since we're here.." Ian says, "Ask away if you have _any_ questions." Ian says, "Or any issues you'd like me to address." Ian guesses we're done, then. Ian says, "Next week, I'm hoping to move onto an assortment of topics.." Grey says, "Like coding a weather and time system? ;)" Ian says, "Various limitations of MU*s... Some issues involving security.. Etc.." Ian hehs, "If you want to bring it up, sure." Ian says, "Since next week's talk night will be so assorted.." Ian says, "Are there any specific issues anyone wants to see addressed then?" Grey is joking. I think that's a little heavy for a talk. Ian says, "Depends, Ronan, on the complexity desired. ;-)" Ian says, "Time is typically pretty simple in comparison to a lot of things." Ian ers, wasn't that vague enough? Ian says, "Tiem is typically pretty simple in comparison to the 'average' complexity of MU*-spanning systems." Ian says, "The weather stuff.. well, that could be doable within 3 hours depending on what people want. ;-)" Ian says, "Alrighty.. So, in closing.. Thanks for coming, all.. Next talk night, more advanced coding.. buffer limits, attribute limits, function invocation limits, command limits, quotas, parents, zones, whatever we have time for. And any questions people may have. It'll hopefully be less lecture-like and more "this is what I'm interested in, talk to me about it some."" Ian says, "And, as usual, feel free to invite people." [>>Public] Sirene has connected. Ian presses the stop button on the Tape Recorder. The Tape Recorder clicks and its spindles stop turning. Tape Recorder has left. Blobject has left. Ian waves, "'Night." Ian has left. Faolin returns to the Forum. Faolin has left. Bonn has disconnected. [>>Public] Bonn has disconnected. [>>Public] Sirene has disconnected.