#include <sys/types.h>
#include <stdio.h>
#include <stdlib.h>
#include "define.h"
#include "struct.h"
#define RECOG_INTRODUCE 16
#define RECOG_RECOGNIZE 17
#define RECOG_BEFRIEND 18
#define RECOG_FILTER 19
#define RECOG_CONSENT 20
bool in_character = TRUE;
/*
* CLASS KNOWN_DATA
*/
Recognize_Data :: Recognize_Data( int i )
{
record_new( sizeof( recognize_data ), MEM_RECOGNIZE );
record_new( i*sizeof( int ), -MEM_RECOGNIZE );
size = i;
list = new int[i];
};
Recognize_Data :: ~Recognize_Data( )
{
record_delete( sizeof( recognize_data ), MEM_RECOGNIZE );
record_delete( size*sizeof( int ), -MEM_RECOGNIZE );
delete [] list;
};
/*
* LOCAL FUNCTIONS
*/
bool display ( char_data*, int, const char* );
bool is_recognize_set ( recognize_data*, int, int );
bool remove_recognize_bit ( recognize_data*&, int, int );
void set_recognize_bit ( char_data*, int, int );
void sort ( recognize_data* );
void insert ( recognize_data*&, int, int );
/*
* SEARCH ROUTINES
*/
void sort( recognize_data* recognize )
{
int* list;
int size;
int i;
bool found;
if( recognize == NULL )
return;
list = recognize->list;
size = recognize->size;
found = TRUE;
for( ; found; ) {
found = FALSE;
for( i = 0; i < size-1; i++ ) {
if( ( list[i] & 0xffff ) > ( list[i+1] & 0xffff ) ) {
swap( list[i], list[i+1] );
found = TRUE;
}
}
}
}
void insert( recognize_data*& recognize, int value, int pos )
{
if( recognize == NULL ) {
recognize = new recognize_data( 1 );
recognize->list[0] = value;
return;
}
insert( recognize->list, recognize->size, value, pos );
record_new( sizeof( int ), -MEM_RECOGNIZE );
}
void remove( recognize_data*& recognize, int pos )
{
if( pos < 0 )
return;
record_delete( sizeof( int ), -MEM_RECOGNIZE );
if( recognize->size == 1 ) {
delete recognize;
recognize = NULL;
return;
}
remove( recognize->list, recognize->size, pos );
}
int search( recognize_data* recognize, int ident )
{
int element;
int min;
int max;
int value;
if( recognize == NULL )
return -1;
min = 0;
max = recognize->size-1;
for( ; ; ) {
if( max < min )
return -min-1;
element = (max+min)/2;
value = ( recognize->list[element] & 0xffff );
if( ident == value )
break;
if( ident > value )
min = element+1;
else
max = element-1;
}
return element;
}
/*
* ALTERING KNOWLEDGE ROUTINES
*/
bool is_recognize_set( recognize_data* recognize, int ident, int bit )
{
int pos;
pos = search( recognize, ident );
return( pos >= 0 && IS_SET( recognize->list[pos], bit ) );
}
bool remove_recognize_bit( recognize_data*& recognize, int ident, int bit )
{
int pos;
pos = search( recognize, ident );
if( pos >= 0 && is_set( &recognize->list[pos], bit ) ) {
remove_bit( &recognize->list[pos], bit );
if( ( recognize->list[pos] & 0xffff0000 ) == 0 )
remove( recognize, pos );
return TRUE;
}
return FALSE;
}
void set_recognize_bit( char_data* ch, int ident, int bit )
{
recognize_data* recognize = ch->pcdata->recognize;
int pos;
pos = search( recognize, ident );
if( pos >= 0 ) {
set_bit( &recognize->list[pos], bit );
return;
}
set_bit( &ident, bit );
insert( ch->pcdata->recognize, ident, -pos-1 );
return;
}
/*
* LOGIN ROUTINE
*/
void reconcile_recognize( char_data* ch )
{
recognize_data* recog_ch;
recognize_data* recog_vict;
player_data* victim;
int pos_ch;
int pos_vict;
int flag_ch;
int flag_vict;
int i;
if( ( recog_ch = ch->pcdata->recognize ) != NULL ) {
for( i = recog_ch->size-1; i >= 0; i-- )
if( get_pfile( recog_ch->list[i] & 0xffff ) == NULL )
remove( recog_ch, i );
sort( recog_ch );
}
for( i = 0; i < player_list; i++ ) {
victim = player_list[i];
if( !victim->Is_Valid( ) || victim == ch )
continue;
recog_vict = victim->pcdata->recognize;
pos_ch = search( recog_ch, victim->pcdata->pfile->ident );
pos_vict = search( recog_vict, ch->pcdata->pfile->ident );
flag_ch = ( pos_ch >= 0 ? recog_ch->list[pos_ch] : 0 );
flag_vict = ( pos_vict >= 0 ? recog_vict->list[pos_vict] : 0 );
if( ( is_set( &flag_ch, RECOG_RECOGNIZE )
!= is_set( &flag_vict, RECOG_INTRODUCE ) )
|| ( is_set( &flag_vict, RECOG_RECOGNIZE )
!= is_set( &flag_ch, RECOG_INTRODUCE ) ) ) {
remove( recog_ch, pos_ch );
remove( victim->pcdata->recognize, pos_vict );
}
}
ch->pcdata->recognize = recog_ch;
}
/*
* DISPLAY LIST WITH BIT SET
*/
bool display( char_data* ch, int bit, const char* title )
{
recognize_data* recognize = ch->pcdata->recognize;
pfile_data* pfile;
int i, j;
bool found = FALSE;
if( recognize == NULL )
return FALSE;
for( i = j = 0; i < recognize->size; i++ ) {
if( ( pfile = get_pfile( recognize->list[i] & 0xffff ) ) == NULL
|| !is_set( &recognize->list[i], bit ) )
continue;
if( !found ) {
page( ch, "%s:\n\r", title );
found = TRUE;
}
page( ch, "%17s%s", pfile->name, ++j%4 == 0 ? "\n\r" : "" );
}
if( j%4 != 0 )
page( ch, "\n\r" );
return found;
}
pfile_data* remove_name( recognize_data*& recognize, char* name, int bit )
{
pfile_data* pfile;
if( ( pfile = find_pfile( name ) ) != NULL
&& remove_recognize_bit( recognize, pfile->ident, bit ) )
return pfile;
return NULL;
}
/*
* INTRODUCTION FUNCTIONS
*/
bool char_data :: Recognizes( char_data *victim )
{
if( pcdata == NULL )
return FALSE;
if( victim->species != NULL ) {
if( victim->descr == victim->species->descr || victim->leader != this
|| victim->descr->singular[0] == '\0' )
return FALSE;
return TRUE;
}
if( victim == this || shdata->level >= LEVEL_APPRENTICE
|| victim->shdata->level >= LEVEL_APPRENTICE )
return TRUE;
return is_recognize_set( pcdata->recognize,
victim->pcdata->pfile->ident, RECOG_RECOGNIZE );
}
void do_introduce( char_data *ch, char *argument )
{
char_data* victim;
if( is_confused_pet( ch ) )
return;
if( *argument == '\0' ) {
send( ch, "Who do you want to introduce yourself to?\n\r" );
return;
}
if( ( victim = one_character( ch, argument, "introduce",
ch->array ) ) == NULL )
return;
if( ch == victim ) {
send( ch, "You unfortunately already recognize yourself.\n\r" );
return;
}
if( victim->fighting != NULL ) {
send( ch,
"They are too busy fighting for you to introduce yourself.\n\r" );
return;
}
if( victim->position < POS_RESTING ) {
send( ch, "They aren't in a good state for introductions.\n\r" );
return;
}
if( victim->species != NULL ) {
send( ch, "Introducing yourself to npcs will do nothing useful.\n\r" );
return;
}
if( !associate( ch, victim ) )
return;
if( victim->Recognizes( ch ) ) {
send( ch, "%s already recognizes you.\n\r", victim );
return;
}
if( !ch->Seen( victim ) ) {
send( ch, "%s cannot see you.\n\r", victim );
return;
}
if( !can_talk( ch, "introduce yourself" ) )
return;
leave_shadows( ch );
leave_camouflage( ch );
if( skill_language( victim, ch->pcdata->speaking ) == 0 ) {
fsend( ch, "You attempt to introduce yourself to %s, but %s\
does not seem to understand a word you are saying.\n\r",
victim, victim->He_She( ) );
return;
}
fsend( ch, "You introduce yourself to %s.\n\r", victim );
fsend( victim, "%s greets you and introduces %sself as '%s'.\n\r",
ch, ch->Him_Her( ), ch->descr->name );
fsend_seen( ch, "%s introduces %sself to %s.\n\r",
ch, ch->Him_Her( ), victim );
set_recognize_bit( victim, ch->pcdata->pfile->ident, RECOG_RECOGNIZE );
set_recognize_bit( ch, victim->pcdata->pfile->ident, RECOG_INTRODUCE );
}
/*
* BEFRIEND FUNCTIONS
*/
bool Char_Data :: Befriended( pfile_data* pfile )
{
if( pcdata == NULL )
return FALSE;
return is_recognize_set( pcdata->recognize,
pfile->ident, RECOG_BEFRIEND );
}
bool Char_Data :: Befriended( char_data* ch )
{
if( pcdata == NULL || ch->pcdata == NULL )
return FALSE;
return is_recognize_set( pcdata->recognize,
ch->pcdata->pfile->ident, RECOG_BEFRIEND );
}
void do_befriend( char_data* ch, char* argument )
{
char tmp [ MAX_INPUT_LENGTH ];
char_data* victim;
pfile_data* pfile;
if( is_confused_pet( ch ) )
return;
if( argument[0] == '\0' ) {
if( !display( ch, RECOG_BEFRIEND, "Befriend List" ) )
send( "You have befriended no one.\n\r", ch );
return;
}
if( ( pfile = remove_name( ch->pcdata->recognize, argument,
RECOG_BEFRIEND ) ) != NULL ) {
sprintf( tmp, "You no longer consider %s a friend.\n\r", pfile->name );
send( tmp, ch );
return;
}
if( ( victim = one_character( ch, argument, "befriend",
ch->array ) ) == NULL )
return;
if( ch == victim ) {
send( ch, "Befriending yourself is a waste of time.\n\r" );
return;
}
if( IS_NPC( victim ) ) {
send( ch, "Befriending npcs will do nothing useful.\n\r" );
return;
}
if( !ch->Recognizes( victim ) ) {
fsend( ch, "You cannot befriend %s without first knowing %s name.",
victim, victim->His_Her( ) );
return;
}
if( !victim->Recognizes( ch ) ) {
fsend( ch,
"You cannot befriend %s until you have introduced yourself to %s.",
victim, victim->Him_Her( ) );
return;
}
if( ch->Befriended( victim ) ) {
send( ch, "You already think %s is your friend.\n\r", victim );
return;
}
send( ch, "You now consider %s a friend.\n\r", victim );
set_recognize_bit( ch, victim->pcdata->pfile->ident, RECOG_BEFRIEND );
return;
}
/*
* IGNORE ROUTINES
*/
bool Char_Data :: Ignoring( char_data* victim )
{
if( pcdata == NULL || victim->pcdata == NULL
|| victim->shdata->level >= LEVEL_APPRENTICE )
return FALSE;
if( !is_set( pcdata->pfile->flags, PLR_APPROVED )
&& has_permission( victim, PERM_APPROVE ) )
return FALSE;
int level = level_setting( &pcdata->pfile->settings, SET_IGNORE );
switch( level ) {
case 0 : return FALSE;
case 1 : return !victim->Recognizes( this );
case 2 : return !Befriended( victim );
}
return TRUE;
}
bool Char_Data :: Filtering( char_data *victim )
{
if( this == NULL || pcdata == NULL || victim->pcdata == NULL )
return FALSE;
return is_recognize_set( pcdata->recognize,
victim->pcdata->pfile->ident, RECOG_FILTER );
}
void do_filter( char_data* ch, char* argument )
{
char_data* victim;
pfile_data* pfile;
if( is_confused_pet( ch ) )
return;
if( *argument == '\0' ) {
if( !display( ch, RECOG_FILTER, "Filter List" ) )
send( ch, "You are filtering noone.\n\r" );
return;
}
if( ( pfile = remove_name( ch->pcdata->recognize,
argument, RECOG_FILTER ) ) != NULL ) {
send( ch, "You will no longer filter %s.\n\r", pfile->name );
return;
}
in_character = FALSE;
if( ( victim = one_player( ch, argument, "filter",
(thing_array*) &player_list ) ) == NULL )
return;
if( victim == ch ) {
send( ch,
"Ignoring yourself might be wise, but it is also pointless.\n\r" );
}
else if( victim->shdata->level >= LEVEL_APPRENTICE ) {
send( ch, "You may not filter immortals.\n\r" );
}
else if( ch->Filtering( victim ) ) {
send( ch, "You are already filtering them.\n\r" );
}
else {
set_recognize_bit( ch, victim->pcdata->pfile->ident, RECOG_FILTER );
send( ch, "You are now filtering %s.\n\r", victim );
}
}
/*
* ROUTINES
*/
bool consenting( char_data* victim, char_data* ch, const char* word )
{
if( ch == victim || ch->shdata->level >= LEVEL_APPRENTICE )
return TRUE;
if( ch->pcdata != NULL && victim->pcdata != NULL
&& is_recognize_set( victim->pcdata->recognize,
ch->pcdata->pfile->ident, RECOG_CONSENT ) )
return TRUE;
if( word != empty_string ) {
fsend( ch, "Since %s does not automatically consent to your actions\
the %s fails.", victim, word );
send( victim, "You automatically disrupt %s.\n\r", word );
}
return FALSE;
}
void do_consent( char_data* ch, char* argument )
{
char_data* victim;
pfile_data* pfile;
if( is_confused_pet( ch ) )
return;
if( *argument == '\0' ) {
if( !display( ch, RECOG_CONSENT, "Consent List" ) )
send( ch, "You have consented noone.\n\r" );
return;
}
if( ( pfile = remove_name( ch->pcdata->recognize,
argument, RECOG_CONSENT ) ) != NULL ) {
send( ch, "You no longer automatically consent %s.\n\r", pfile->name );
return;
}
if( ( victim = one_player( ch, argument, "consent",
ch->array, (thing_array*) &player_list ) ) == NULL )
return;
if( victim == ch ) {
send( ch, "That you agree with your own actions is assumed.\n\r" );
return;
}
if( !ch->Recognizes( victim ) ) {
send( ch, "You may only consent someone whom you recognize.\n\r" );
return;
}
if( victim->pcdata == NULL ) {
send( ch, "Consent only matters with players.\n\r" );
return;
}
if( consenting( ch, victim ) ) {
send( ch, "%s is already listed for automatic consent.\n\r", victim );
return;
}
set_recognize_bit( ch, victim->pcdata->pfile->ident, RECOG_CONSENT );
send( ch, "You now automatically consent to the actions of %s.\n\r",
victim );
}