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 - silenus

Pages: 1 ... 9 10 [11]
151
Design Lab / Re: meta programming and LPC etc
« on: July 25, 2007, 12:34:12 PM »
I think the SKOTOS for DGD had some similar scripting language on a scripting language called Merry and ended up writing alot of their lib in a modified script language. The file you posted also reminds me of the UNQ system in Phantasmal even though the goals for that a decidedly more modest (it's a data format like XML which is used to specify object data without having to add any setup code in  create per usual LPC development).

My goals for having a metaprogramable LPCish toy (at least generatively) are probably more modest. I actually wanted to be able to do dynamic metaprogramming of some sort in LPC but this is perhaps mostly impossible currently. I.e. i thought it would be nice to be able to interogate objects (reflectively) and update them on the fly such as adding new functions using LPC code but I ended up settling initially on just having generative style code.

To make it more robust I suspect I would have to do a better job of parsing through the LPC in the file.     

152
General / Re: Wikipedia article on LPmud
« on: July 25, 2007, 10:41:37 AM »
Aye you are correct. I guess digging out relevant references to reference materials has become so second nature to me that I even forgot to mention it  :o. I thought perhaps the historical section could become part of a larger article where perhaps you could get away with it by referencing everything else. There are actually some references in a related article on wiki on muds in general. This perhaps might be a good starting point for changing the article so that it has more appropriate content. This gives a broader historical outline and contextualizes mudding within the context of the rise of the MMORPGs. I was actually surprised that there are a number of research articles on muds in general in the literature including this one- http://www.ics.uci.edu/~jpd/publications/mud-intro.html.

   

153
Design Lab / Re: meta programming and LPC etc
« on: July 25, 2007, 09:49:49 AM »
I actually havent worked on this in some time and my version of the code is rather crude and more of a proof of concept thing rather than a robust implementation. It works for what I wanted it it to do but doesnt trap all exception cases properly I probably will go back and fix this. I did thing somewhat backwards from your suggestion initially which was to instead of have a document with embedded LPC tags was to add extra text function blocks which would be processed to create the metaprogrammed file.

Unfortunately unlike something like Ruby you cannot dynamically metaprogram most LPC variants. This would be alot nicer than this approach but I dont see a way to do this without writing your own server. Here is an example file of what I was working on- it's a bit ugly.

Code: [Select]
---VARSTAT(STAT)
private int $STAT$; private nosave int $STAT$_cache; private nosave function array $STAT$_bonuses = ({});
---

---SETSTAT(STAT, DEPENDS_BLOCK)
// need to update dependencies
public void set_$STAT$(int x)
{
$STAT$ = x;
$STAT$_cache = implode( map($STAT$_bonuses, (: evaluate($1, $($STAT$) ) :) ), (: $1 + $2 :), 0 );
}
---

---ADDSTATBONUS(STAT)
// need to update dependencies.....
public int add_$STAT$_bonus(function f)
{
$STAT$_cache += evaluate(f, $STAT$ );
for(int i = 0;i < sizeof( $STAT$_bonuses );++i)
if( $STAT$_bonuses[i] == 0)
{
$STAT$_bonuses[i] = f;
return i;
}
$STAT$_bonuses += ({ f });
return sizeof($STAT$_bonuses) - 1;
}
---

---REMOVESTATBONUS(STAT)
// need to update dependencies.....
public int remove_$STAT$_bonus(int i)
{
$STAT$_cache -= evaluate( $STAT$_bonuses[i], this_object(), $STAT$ );
$STAT$_bonuses[i] = 0;

}
---

---UPDATE(STAT, FORMULA)
public void update_$STAT$
{

}
---

---GETSTAT(STAT)
public int get_$STAT$()
{
return $STAT$_cache;
}
---

---GETSTATBASE(STAT)
public int get_$STAT$_base()
{
return $STAT$;
}
---

---GETSTATBONUS(STAT)
public int get_$STAT$_base()
{
return $STAT$_cache - $STAT$;
}
---

class stat
{
string formula;
string array depends on;
}


private mapping stats

private string array stats = ({"strength","stamina","agility","dexterity","intelligence","will","eloquence","empathy","constitution","appearance"});

string generate(string array args, function f)
{
return implode( map(args, (: evaluate($(f),$1) :) ), (: $1 + $2 :), "" );
}

string generate_code(mixed array args)
{
return generate(stats, (: VARSTAT($1) :) ) + generate(stats, (: SETSTAT($1) :) ) + generate(stats, (: ADDSTATBONUS($1) :) ) + generate(stats, (: GETSTAT($1) :) );
}

 

154
General / Re: Wikipedia article on LPmud
« on: July 25, 2007, 09:22:04 AM »
I am not sure who wrote the article but I would probably like to say the following. I think that the article isn't too well organized compared to some if the existing articles on wiki. I think the use of some of the terminology is a bit incorrect. For example I doubt most people would consider most mud drivers to be just virtual machines since it incorporates OS like features.

Unfortunately my writing skills aren't quite up to snuff and I am not so sure about the long history of LP since I came rather late to the scene in the early 1990's or I would volunteer to rewrite the article. I think some things people might consider is creating a general MUD article and have a shorter description of different mud types which could be expanded later. I think for example the article is hurt a bit because it fails to contrast the differences between LP, Diku's and things like MUSH and MOO. I think this sort of information would be critical for someone lay person to get a sense of what the whole mud scene is/was all about.



 

155
Intermud / Re: I4
« on: July 02, 2007, 06:28:32 AM »
How has this project been moving along? I would love to try implementing an updated I4 daemon for dgd with the network patch.
 



 

156
Drivers / Re: DGD 1.2.128 with network patch and intermud3
« on: June 17, 2007, 10:22:41 AM »
Thanks Jimorie. I saw your old posts in the mailing list archive. I guess maybe I will try requesting a newer patch again though I wonder if it's possible to just take the patch file and manually hack it back into the 1.2.128 sources sort of like they suggest you do with the ANSI diff.




157
Code Vault / Re: Almost full persistance under MudOS (DS)
« on: June 09, 2007, 04:24:53 PM »
In theory I feel the mechanism is capable like java serialization of saving almost any object graph. In this case however the saving is not into a serialized stream but into a registry in the persistence daemon. There are however two notable exceptions function pointers are still not saved nor are classes. Both these types are impossible to inspect through any mechanism in MudOS and thus are not easy to convert into a savable form.

The way so far I have been using the system is as an extended replacement for the old persist.c where graphs only related to the player object are saved. However I speculate that the system could be extended (I am not sure about the performance here) to save the whole state of a mud (minus the two items above) but then again if you went this far perhaps you might as well use something like DGD.



 

158
Code Vault / Almost full persistance under MudOS (DS)
« on: June 09, 2007, 03:02:31 PM »
Here is a prototype version of a rudimentary persistence mechanism I wrote for MudOS (DS). Currently it's not without it's flaws- specifically on a large mud with alot of objects the memory usage of the daemon is not optimized. I will add this feature in the future. The code consists of two files and requires some minor modifications to /lib/user/autosave.c to get it to work. Some of the other files need some minor modifications also since the new inheritable does not contain currently contain SetSaveRecurse() and SetSave() has been changed to return int instead of string array. Here is both the inheritable and the daemon. Hopefully someone will find it useful.

Code: [Select]
/*
        /lib/persist.c
  Silenus@Desperate Sorrows - 2007-06-10
Designed to work with the DeadSouls Library v2.4.x
Version : 0.001
*/

#include <daemons.h>

private static array Save = ({});

protected int AddSave(string array a)
{
Save += a;
return 1;
}

string array GetSave() { return copy(Save); }

void eventRestore(mapping m)
{
if( previous_object() != find_object(PERSIST_D) ) error("Illegal call to eventRestore()." + identify( previous_object(-1) ) );

foreach(string v in Save)
{
store_variable(v, m[v] );
}

foreach(object o in m["#inventory#"] )
{
o->eventMove( this_object() );
}
}

void eventSave()
{
PERSIST_D->SaveObject( this_object() );
}

int eventDestruct()
{
PERSIST_D->SaveObject( this_object() );
return destruct( this_object() );
}

mapping GetSaveMap()
{
// if( previous_object() != PERSIST_D ) error("Illegal call to GetSaveMap().");

mapping sMap = ([]);
foreach(mixed v in Save)
{
sMap[v] = fetch_variable(v);
}
sMap["#inventory#"] = ({});
foreach(object o in all_inventory( this_object() ) )
{
sMap["#inventory#"] += ({ o });
}

sMap["#base_name#"] = base_name( this_object() );
return sMap;
}

protected void create()
{
PERSIST_D->GetObjectID( this_object() );
}

Code: [Select]
/*
    /secure/daemon/persist_d.c
  Silenus@Desperate Sorrows - 2007-06-10
Designed to work with the DeadSouls Library v2.4.x
Version : 0.001
*/
 

#include <save.h>

string GetObjectID(object);
object GetObject(string);
mapping ConvertSaveMap(mapping);
mapping ConvertRestoreMap(mapping);
string array FindMapObjectIDs(mapping);
mixed ConvertSaveVariable(mixed);
mixed ConvertRestoreVariable(mixed);
string array FindVarObjectIDs(mixed);

private static mapping Objects = ([]);
private static mapping ObjectIDs = ([]);
private mapping SavedObjects = ([]);

private string GenerateObjectID(object o)
{
string baseName, objectID;
int n;

baseName = base_name(o);
if( file_name(o) == baseName )
{
objectID = baseName;
}
else
{
n = 0;
while( !undefinedp( SavedObjects[baseName + "#" + n] ) )
{
++n;
}
objectID = baseName + "#" + n;
}
ObjectIDs[o] = objectID;
Objects[ objectID ] = o;
SavedObjects[ objectID ] = ConvertSaveMap( o->GetSaveMap() );
return objectID;
}

string SaveObject(object o)
{
string objectID;

if( !inherits(LIB_PERSIST, o ) ) return 0;
if( undefinedp( ObjectIDs[o] ) )
return GenerateObjectID(o);

SavedObjects[ ObjectIDs[o] ] = ConvertSaveMap( o->GetSaveMap() );

return ObjectIDs[o];
}

string GetObjectID(object o)
{
string objectID;

if( !inherits(LIB_PERSIST, o ) ) return 0;
if( !undefinedp( ObjectIDs[o] ) ) return ObjectIDs[o];
// otherwise return a new reference not in the SavedObjects keys

return GenerateObjectID(o);
}

int RemoveObjectID(string s)
{
// might need to add a secure override here for stray references...
if( undefinedp( SavedObjects[s] ) ) return 0;
if( previous_object() != Objects[s] ) return 0;
map_delete( SavedObjects, s );
map_delete( Objects, s);
map_delete( ObjectIDs, previous_object() );
return 1;
}

varargs object GetObject(string s)
{
object o;

if( !undefinedp( Objects[s] ) || Objects[s] != 0 ) return Objects[s];

if( SavedObjects[s] )
{
if( SavedObjects[s]["#base_name#"][1] == s )
o = load_object(s);
else 
o = new( SavedObjects[s]["#base_name#"][1] );
// maybe add patching behavior here as well......
o->eventRestore( ConvertRestoreMap( SavedObjects[s] ) );

ObjectIDs[o] = s;
Objects[s] = o;


return o;
}
return 0;
}

mapping ConvertSaveMap(mapping m)
{
mapping cMap = ([]);
foreach( string v in keys(m) )
{
cMap[v] = ConvertSaveVariable( m[v] );
}
return cMap;
}

mapping ConvertRestoreMap(mapping m)
{
mapping cMap = ([]);
foreach( string v in keys(m) )
{
cMap[v] = ConvertRestoreVariable( m[v] );
}
return cMap;
}

string array FindMapObjectIDs(mapping m)
{
string array a = ({});
foreach(string v in keys(m) )
{
a += FindVarObjectIDs( m[v] );
}
return a;
}

mixed ConvertSaveVariable(mixed v)
{
mapping m;
switch ( typeof(v) )
{
case "int": case "float": case "string": case "function": case "class":
return ({ typeof(v), v });
case "object":
return ({ "object", GetObjectID(v) });
case "array" :
return ({ "array", map( v, (: ConvertSaveVariable($1) :) ) });
case "mapping" :
m = ([]);
foreach( mixed k in keys( v ) )
{
m[ k ] = ConvertSaveVariable( v[k] );
}
return ({"mapping", m});
}
}

mixed ConvertRestoreVariable(mixed v)
{
mapping m;
switch( v[0] )
{
case "int": case "float": case "string": case "function": case "class":
return v[1];
case "object":
return GetObject(v[1]);
case "array":
return map( v[1], (: ConvertRestoreVariable($1) :) );
case "mapping":
m = ([]);
foreach( mixed k in keys( v[1] ) )
{
m[ k ] = ConvertRestoreVariable( v[1][k] );
}
return m;
}
}

string array FindVarObjectIDs(mixed v)
{
string array a;
switch( v[0] )
{
case "int": case "float": case "string": case "function": case "class":
return ({});
case "object" :
return ({ v[1] });
case "array" :
return implode( map( v[1], (: FindVarObjectIDs($1) :) ), (: $1 + $2 :), ({}) );
case "mapping":
a = ({});
foreach( mixed k in keys( v[1] ) )
{
a += FindVarObjectIDs( v[1][k] );
}
return a;
}
}

void eventGarbageCollect()
{
//what is the terminal condition?

    mapping CheckedMap = ([]);
    mapping CheckMap = ([]); //until check list is empty
    string array CheckArr = ({});
    string Current;

foreach( string i in keys(SavedObjects) )
{
debug("a",i);
debug("b", SavedObjects[i]["#base_name#"] );
if(i == SavedObjects[i]["#base_name#"][1] )
{
debug("c", i );
CheckMap[i] = 1;
CheckArr += ({i});
}
}

while( sizeof(CheckArr) )
{
Current = CheckArr[0];

foreach( string i in FindMapObjectIDs( SavedObjects[ Current ] ) )
{
debug("hmmmm", i );
if( !CheckedMap[i] && !CheckMap[i] )
{
CheckMap[i] = 1;
CheckArr += ({i});
}
}

CheckArr = CheckArr[1..];
map_delete(CheckMap, Current);
CheckedMap[Current] = 1;
}

foreach( string j in keys(SavedObjects) )
{
if( !CheckedMap[j] ) map_delete(SavedObjects,j);
}
}

mapping GetSavedObjectsMap()
{
return copy(SavedObjects);
}

private int eventSave()
{
call_out( (: eventSave :), 1800 );
return save_object(SAVE_PERSIST, 1);
}

int eventDestruct()
{
save_object(SAVE_PERSIST, 1);
return destruct( this_object() );
}

static protected void create()
{
unguarded( (: restore_object, SAVE_PERSIST, 1 :) );
call_out( (: eventSave :), 1800 );
eventGarbageCollect();
}
 

159
Drivers / Re: DGD 1.2.128 with network patch and intermud3
« on: June 08, 2007, 02:21:59 PM »
Hi Crat.,

Thanks. I was aware that you could have the network patch work with the older version 1.1.experimental of the driver and thus perhaps I3 under the older version but thank you for looking it up. I just found the dgd mailing list so maybe I should inquire there since it still seems to be somewhat active.

Regards,

Silenus.

160
Drivers / Re: DGD 1.2.128 with network patch and intermud3
« on: June 05, 2007, 11:47:21 AM »
Hi Tricky,

Thanks. Does anyone have experience with the other issue i.e. Getting DGD experimental with latest patches to work with the network patch?

Regards

Silenus.


161
Drivers / DGD 1.2.128 with network patch and intermud3
« on: June 03, 2007, 04:04:00 PM »
Hi everyone,

I have been lately taking a look at DGD but would like some of the capabilities in the network patch (which is slightly out of date with respect to the experimental patches) and was wondering if anyone had any experience getting the latest experimental patches to work with the network patch. I am also wondering if the specification document for intermud3 is still out there somewhere.

Thanks in advance,

Silenus

162
Code Vault / Re: a pair function adapters for sort_array
« on: April 18, 2007, 04:33:06 AM »
I see those more as library type functions which you can use to help you sort objects if you need to. One possible application is perhaps in something like the who code where you need to sort something in blocks. I posted them more to illustrate the technique more than anything else. Here's maybe a brief example using DS style function calls-

Code: [Select]

// sorts array according to race then class then level then name...

mixed array who_sort()
{
    mixed array ar = map( users(), (: ({$1->GetName(), $1->GetLevel(), $1->GetRace(), $1->GetClass() }) :) ); 
    function f = tuple_comparator(
        ({ (: strcmp($1,$2) :), (: strcmp($1,$2) :), comparator( (: $1 >= $2 :) ), (: strcmp($1,$2) :) }),     
        ({2,3,1,0}) );
    return sort_array(ar, f);
}


163
Code Vault / a pair function adapters for sort_array
« on: April 17, 2007, 08:53:23 AM »
I wrote a pair of function adapters for sort array which came up in a problem in sorting and displaying list data. The first comparator() converts a binary "greater or equal than" comparison into the 3 value comparison needed by sort_array that returns 1,0, or -1 depending on if the value is greater, equal or less than the respective second value respectively for example to sort a list of integers with this function one would do the following:

sort_array(array_of_ints, comparator( (: $1 >= $2 :) ) )


The second function is for sorting tuples when you have to sort a list of items which consist of lists of data or tuples where each element at a given index is of the same type. i.e. ({"Silenus", 1, "orc", "warrior"}), ({"Cratylus", 1, "human", "mage"}) it creates a comparison function which gives priority to the indexes as ordered. An example usage might be (using the previous data)-

sort_array(array_of_tuples, tuple_comparator( ({ comparator( (: $1 >= $2 :) ), (: strcmp($1,$2) :) }), ({1,0}) ) )

which prioritizes the sort by level and if the levels are found to be equal sorts by name.

Both functions rely on tricks from functional programming in that they both create functions on the fly based on a function or functions passed in. The code might be a bit cryptic to those not use to this style but is illustrative of this approach.




/* Converts a greator or equal binary comparator into a 3 value comparator */
public function comparator(function f)
{
   return (: evaluate($(f), $1, $2) ? ( evaluate($(f), $2, $1) ? 0 : 1) : -1 :);
}


/*
    Compares two tuples in the order specified by the indices. If a comparator
    applied to an index early in the order results in equality, the next
    comparator is used on the next index on the list. 
*/
private function tuple_comparator_(function array, int array);

public function tuple_comparator(function array f, int array i)
{
   if( sizeof(f) != sizeof(i) ) error("Argument arrays must be of the same size.");
   return tuple_comparator_(f,i);
}

private function tuple_comparator_(function array f,int array i)
{   
   if( sizeof(f) == 0 ) return (: 0 :);
   return (: evaluate( $(f[0]), $1[$(i[0])], $2[$(i[0])] ) != 0 ? evaluate( $(f[0]), $1[$(i[0])], $2[$(i[0])] ) : evaluate( $(tuple_comparator_(f[1..],i[1..])), $1, $2 ) :);
}

 

   

164
Design Lab / meta programming and LPC etc
« on: April 09, 2007, 03:01:02 PM »
Hi folks,

I have been working on a meta programming tool for MudOS which so far seems to work on DS 2.4.1 but I am sure will work for the most part on other libraries for MudOS. The issue that I am wrestling with is how to further develop this tool. The basic idea I have so far implemented is quite simple-

The code simply hooks into compile_object with a slightly altered syntax. The file is parsed and converted into a generator LPC object which then is used to create the real LPC code which is compiled as an object and returned as object.

The issue here for me is my syntax so far is far from pretty. Currently @@@ tags are used to mark special regions and these are parsed as either text functions or copied wholesale into the constructed object file. The text functions are called by the user in a special block which is used to construct the remainder of the file. I wish however that this syntax could be a bit cleaner.

I am curious if there have been other projects for extending LPC in this manner which might have a nicer syntax I could perhaps emulate. Or if anyone has better ideas of how to mix LPC as data and LPC as generative functions in a single file.

Regards,

Silenus.


165
Code Vault / partition_array sefun
« on: April 04, 2007, 03:08:22 PM »
Someone mentioned a problem on intercre/ds channel(can't remember which) about grouping users with the same ip addresses into clusters and I thought of this as a possible solution and decided to post it. It's a bit more general and is based on the idea of partitions and equivalence classes though there is in this case only a partition function. I hope someone finds it useful. For example to solve the above problem would be quite easy once you have this function just do- partition_array( map( users(), (: query_ip_number($1) :) ) ) and implode the result as needed.

/*
   partitions an array into equivalence classes based on a partition function
    example usage- partition_array( ({1,2,3,4,5,6}), (: $1 % 2 :) ) would return
    ({ ({2, 4, 6}), ({1, 3, 5}) }).   
*/

varargs mixed array partition_array(mixed array ar, function f)
{
   mapping m = ([]);
   f = undefinedp(f) ? (: $1 :) : f;
   
   foreach(mixed elem in ar)
   {
      if( undefinedp( m[ evaluate(f, elem) ] ) ) m[ evaluate(f, elem) ] = ({ elem });
      else m[ evaluate(f, elem) ] += ({ elem });
   }
   return values( m );
}


Pages: 1 ... 9 10 [11]