/* -*- LPC -*- */
/*
* Crowd object
*/
#include <parse_command.h>
#include "path.h"
#define MAXATONCE 6
inherit "/std/object";
class member {
string file;
string short;
string *adjectives;
string *names;
string *plurals;
string long;
int *original_number;
}
int n_alive, n_crowd, n_selection, n_cloned, n_here, n_max=MAXATONCE;
/* This stores ints
member type in members array: (int>>2)
gender: int&3
*/
int *crowd,*selection;
mixed *here;
mixed *_m_names;
mixed *_m_plurals;
mixed *_m_adjectives;
mixed store=({});
int cnt=0;
mixed query_store() { return ({ store, cnt }); }
int lookflag=0;
int lastmatch=0;
int i_member=0;
mixed *members = ({
new(class member,
file : CROWD+"am_poor_beggar",
short : "poor beggar",
long : "This is a poor beggar. "
"Perhaps you should give $OBJ$ some money.\n"
"$PRO$ is in good shape.\n"
"$PRO$ is standing.\n",
original_number : ({ 0,13,15 }) ),
new(class member,
file : CROWD+"am_diseased_beggar",
short : "diseased beggar",
long : "This is a diseased beggar. "
"Looking at the running sores covering $POSS$ body makes your skin crawl.\n"
"$PRO$ is in good shape, considering.\n"
"$PRO$ is standing.\n",
original_number : ({ 0,17,2 }) ),
new(class member,
file : CROWD+"am_crippled_beggar",
short : "crippled beggar",
long : "This is a crippled beggar. "
"One of $POSS$ legs has wasted so that it ressembles a gnarled branch.\n"
"$PRO$ is in good shape.\n"
"$PRO$ is standing awkwardly.\n",
original_number : ({ 0,6,11 }) )
});
int *query_crowd() { return ({ selection, crowd }); }
int query_n_crowd() { return n_crowd; }
int query_visible() { return n_crowd; }
int group_object() { return n_crowd-1; }
string include_gender( string long, int gender ) {
switch ( gender ) {
case 2:
return
replace( long, ({ "$POSS$","her","$OBJ$","her","$PRO$","She" }) );
default:
return
replace( long, ({ "$POSS$","his","$OBJ$","him","$PRO$","He" }) );
}
} /* include_gender() */
string long(string word, int dark) {
int i;
string ret="";
// tell_creator("shaggy","flags: %O %O %O %O %O %O %O %O %O %O\n",word,dark,lookflag,lastmatch,query_verb(),sizeof(crowd),previous_object(), previous_object(1), previous_object(2), previous_object(3));
if ( !lookflag ) {
foreach (i in crowd) ret += include_gender( (members[i>>2])->long, i&3 );
return ret;
}
else if ( lastmatch == 0 ) {
foreach (i in selection )
ret += include_gender( (members[i>>2])->long, i&3 );
return ret;
}
else if ( lastmatch > 0 ) {
foreach (i in selection[0..(lastmatch-1)] )
ret += include_gender( (members[i>>2])->long, i&3 );
return ret;
}
else if (-lastmatch <= sizeof(selection)) { /* lastmatch < 0 */
i = selection[-lastmatch-1];
return include_gender( members[i>>2]->long, i&3 );
}
return ret;
} /* long() */
string a_short() {
string ret="";
int i,n_match;
string prev=file_name(previous_object(1));
// tell_creator("shaggy","flags: %O %O %O %O %O %O %O\n",lookflag,lastmatch,query_verb(),previous_object(), previous_object(1), previous_object(2), previous_object(3));
/* We need to make sure they are looking at the beggar(s)
rather than just the room -- different cases */
if ( prev == "/cmds/living/glance" ||
prev == "/cmds/living/l_ook" ) {
lookflag = 0;
i_member = 0;
selection = crowd;
n_selection = n_crowd;
}
else if ( file_name(previous_object()) != "/cmds/living/glance" ) {
lookflag = 0;
}
n_match = n_selection;
if (lookflag && lastmatch && lastmatch < n_match)
n_match = (lastmatch > 0 ? lastmatch : 1);
for (i=i_member;i<n_match;i++) {
ret+="$a_short:"+ file_name(load_object(members[selection[i]>>2]->file)) +"$";
}
if (lookflag) { ret = "$M$" + ret + "$M$"; }
// tell_creator("shaggy",ret+"\n");
// printf(ret+"\n");
return ret;
}
string the_short() {
string ret="";
int i;
// tell_creator("shaggy","It called the_short! Arg! %O %O \n",previous_object(),previous_object(1),previous_object(2));
for (i=0;i<n_crowd;i++)
ret+="$the_short:"+ file_name( this_object() ) +"$";
return ret;
}
string one_short() {
string ret="";
int i;
// tell_creator("shaggy","It called one_short! Arg! %O %O \n",previous_object(),previous_object(1),previous_object(2));
for (i=0;i<n_crowd;i++)
ret+="$one_short:"+ file_name( this_object() ) +"$";
return ret;
}
string poss_short() {
// tell_creator("shaggy","It called poss_short! Arg! %O %O \n",previous_object(),previous_object(1),previous_object(2));
return a_short();
}
varargs string short(int dark) {
// tell_creator("shaggy","It called short! Arg! %O %O \n",previous_object(),previous_object(1),previous_object(2));
// tell_creator("shaggy","i_member: %O %O\n",i_member,(members[crowd[i_member]>>2])->short);
// if (i_member<0 || i_member>=sizeof(crowd)) i_member=0;
// return (members[crowd[i_member++]>>2])->short;
return "crowd";
} /* short() */
void create() {
class member p;
int i,j,k;
string *tmp;
string *adjs = ({});
string *names = ({});
::create();
/* Make it a living */
set_name("beggar");
set_short("crowd of crowd.");
set_long("This is a crowd of people.");
enable_commands();
crowd = ({ });
for (j=0; j<sizeof(members);j++) {
p = members[j];
tmp = explode(p->short," ");
p->names = ({ tmp[<1] });
p->plurals = ({ pluralize(tmp[<1]) });
names += ({ tmp[<1] });
p->adjectives = tmp[0..<2];
adjs += tmp[0..<2];
for (k=0;k<sizeof(p->original_number);k++)
for (i=0; i<(p->original_number)[k]; i++) crowd += ({ (j<<2)+k });
}
crowd = shuffle(shuffle(crowd)); /* shuffle is crap */
n_crowd = sizeof(crowd);
n_alive = sizeof(crowd);
n_cloned = 0;
here = ({ });
n_here = 0;
_m_names = ({});
_m_plurals = ({});
while(sizeof(names)) {
_m_names += ({ names[0] });
_m_plurals += ({ pluralize(names[0]) });
names-= ({ names[0] });
}
_m_adjectives = ({});
while(sizeof(adjs)) {
_m_adjectives += ({ adjs[0] });
adjs-= ({ adjs[0] });
}
} /* create() */
void crowd_member_died( ) {
n_alive--;
n_cloned--;
if (!n_alive) dest_me();
}
void merge_crowd_member( object member ) {
// tell_creator("shaggy","%O is returning to the fold (%O)\n", member, this_object());
tell_room(environment(),"%^YELLOW%^"+sprintf("%O reabsorbed into %O", member, this_object())+"%^RESET%^\n");
if (member && environment(member)==environment() ) {
int i;
for (i=0;i<sizeof(members);i++) {
if ( base_name(member) == members[i]->file ) {
n_cloned--;
n_crowd++;
n_here--;
here -= ({ member->crowd_number() });
n_max = MAXATONCE - ((n_here + n_cloned) >> 2);
if ( n_max < 1 ) n_max = 1;
crowd = ({ (i<<2)+member->query_gender() }) + crowd;
member->dest_me();
}
}
}
// tell_creator("shaggy","Don't want %O\n", member );
} /* merge_crowd_member() */
object make_member() {
object frog;
int i,j;
if (i_member<0 || i_member>=sizeof(selection)) i_member=0;
i = selection[i_member];
j = member_array( i, crowd );
// tell_creator("shaggy","crowd: %O %O %O\n",sizeof(selection),i,n_crowd);
frog = clone_object(members[i>>2]->file);
if (frog) {
n_crowd--;
n_cloned++;
n_here++;
n_max = (n_max+1)>>1;
n_selection--;
crowd = crowd[0..j-1] + crowd[j+1..<1];
selection = selection[0..i_member-1]+selection[i_member+1..<1];
crowd = crowd[0..j-1] + crowd[j+1..<1];
here += ({ i });
tell_room(environment(),"%^YELLOW%^"+sprintf("Cloned %O : %i of %i selected (%i remaining)",frog,i_member+1,sizeof(selection)+1,n_crowd)+"%^RESET%^\n");
frog->fix_gender( i&3 );
frog->add_effect( CROWD+"crowd_merge_effect", ({ this_object(), i }) );
// tell_creator("shaggy","New one: %O %O %O %O %O %O %O %O\n", frog, previous_object(), previous_object(2), previous_object(3), previous_object(4), previous_object(5), previous_object(6), query_verb() );
frog->move( environment(this_object()) );
}
return frog;
} /* make_member() */
/** @ignore yes */
string *parse_command_id_list() {
// tell_creator("shaggy","id_list\n");
return _m_names;
}
/** @ignore yes */
string *parse_command_plural_id_list() {
// tell_creator("shaggy","plural_list\n");
return _m_plurals;
}
/** @ignore yes */
string *parse_command_adjectiv_id_list() {
// tell_creator("shaggy","adj_list\n");
return _m_adjectives;
}
/** @ignore yes */
/* Find match uses this to decide if it is a match or note.
parse_command uses the above functions.
If test is the output from parse_command
param arr = ({ num, str, 0, sizeof(array[i+1]), top, bot }) );
num = test[0];
if numeral > 0 then three, four, five etc were matched
if numeral < 0 then second, twentyfirst etc were matched
if numeral == 0 then 'all' or a generic plural form such as
'apples' were matched.
str = the string to be matched to objects
These seem to be absent some of the time, only there for frac matches:
0
array = some past objects referrable to as it, them, her, him
top = top of fraction
bot = bottom of fraction
#define P_THING 0
#define P_STR 1
#define P_CUR_NUM 2
#define P_MAX_NUM 3
#define P_TOP 4
#define P_BOT 5
*/
mixed query_parse_id(mixed *arr) {
string *bits, bat;
int i;
// tell_creator("shaggy","parse: %O %O %O %O %O %O\n",arr,query_verb(),previous_object(), previous_object(1), previous_object(2), previous_object(3));
selection = ({ });
i_member = 0;
if (!n_crowd) return 0;
lastmatch=arr[P_THING];
switch (query_verb()) {
case 0:
case "look":
case "glance":
case "destruct":
case "lose":
case "trans":
lookflag=1;
break;
default:
lookflag=0;
}
bits = explode(arr[P_STR]," ");
bat = bits[<1];
selection = copy(crowd);
if ( member_array( bat, _m_names ) != -1 ) {
for (i=0;i<sizeof(members);i++) {
if ( member_array( bat, members[i]->names ) == -1)
selection -= ({ (i<<2)+1, (i<<2)+2 });
}
while (sizeof(bits = bits[0..<2])) {
bat = bits[<1];
if ( member_array( bat, _m_adjectives ) != -1 ) {
for (i=0;i<sizeof(members);i++) {
if ( member_array( bat, members[i]->adjectives ) == -1)
selection -= ({ (i<<2)+1, (i<<2)+2 });
}
}
}
}
else if ( member_array( bat, _m_plurals ) != -1 ) {
for (i=0;i<sizeof(members);i++) {
if ( member_array( bat, members[i]->plurals ) == -1)
selection-= ({ (i<<2)+1, (i<<2)+2 });
}
while (sizeof(bits = bits[0..<2])) {
bat = bits[<1];
if ( member_array( bat, _m_adjectives ) != -1 ) {
for (i=0;i<sizeof(members);i++) {
if ( member_array( bat, members[i]->adjectives ) == -1)
selection -= ({ (i<<2)+1, (i<<2)+2 });
}
}
}
}
// tell_creator("shaggy","Selection: %O\n",selection);
if (!(n_selection = sizeof(selection))) return 0;
if (lookflag) {
if (lastmatch < 0) i_member = -lastmatch-1;
/* everything case */
if (arr[P_THING] == 0) return this_object();
if (arr[P_THING] < 0) { /* specific object case */
arr[P_THING]+=n_selection;
if (arr[P_THING] <0) {
return 0;
}
arr[P_THING] = -10321;
return this_object();
}
/* specific number of objects case */
if (arr[P_THING] != 1) {
i=arr[P_THING];
if (i>n_selection) i = n_selection;
arr[P_THING]-=i;
if (!arr[P_THING]) arr[P_THING] = -10101;
return this_object();
}
arr[P_THING] = -10101;
return this_object();
}
/* everything case */
if (arr[P_THING] == 0) {
object *things=({ });
i = n_max;
if (i>n_selection) i = n_selection;
while (i--) things += ({ make_member() });
return things;
}
if (arr[P_THING] < 0) { /* specific object case */
i_member = -arr[P_THING]-1;
arr[P_THING]+=n_selection;
if (arr[P_THING] <0) {
return 0;
}
arr[P_THING] = -10321;
return make_member();
}
/* specific number of objects case */
if (arr[P_THING] != 1) {
object *things=({ });
i=arr[P_THING];
if (i>n_selection) i = n_selection;
if (i>n_max) i = n_max;
while (i--) {
arr[P_THING]--;
things += ({ make_member() });
}
if (!arr[P_THING]) arr[P_THING] = -10101;
return things;
}
arr[P_THING] = -10101;
return make_member();
} /* query_parse_id() */
void event_enter( object ob, string message, object from ) {
if (from) {
object *things;
n_here = sizeof( things = filter(all_inventory( environment() ),
(: $1->crowd_object() == this_object() :) ));
here = ({ });
if ( n_here ) here = map( things, (: $1->crowd_number() :) );
n_max = MAXATONCE - ((n_here + n_cloned) >> 2);
if ( n_max < 1 ) n_max = 1;
tell_creator("shaggy","ENTER %O: n_here: %i n_cloned: %i n_alive: %i n_crowd:%i n_max: %i %O\n",from,n_here,n_cloned,n_alive,n_crowd,n_max, here);
}
}
void event_exit( object ob, string message, object to ) {
object *things;
n_here = sizeof( things = filter(all_inventory( environment() ),
(: $1->crowd_object() == this_object() :) ));
here = ({ });
if ( n_here ) here = map( things, (: $1->crowd_number() :) );
n_max = MAXATONCE - ((n_here + n_cloned) >> 2);
if ( n_max < 1 ) n_max = 1;
tell_creator("shaggy","EXIT: n_here: %i n_cloned: %i n_alive: %i n_crowd:%i n_max: %i %O\n",n_here,n_cloned,n_alive,n_crowd,n_max, here);
}