/*
general.m Subprogram to cheezmud.
Copyright (C) 1995 David Flater.
This program is free software; you can redistribute it and/or modify
it under the terms of the GNU General Public License as published by
the Free Software Foundation; either version 2 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU General Public License for more details.
You should have received a copy of the GNU General Public License
along with this program; if not, write to the Free Software
Foundation, Inc., 675 Mass Ave, Cambridge, MA 02139, USA.
*/
#include "cheezmud.h"
/* Find something. */
id
global_find (char *name, int number)
{
return generic_find (world, name, number);
}
int
global_number (char *name, id what)
{
return generic_number (world, name, what);
}
/* Support multiple cascaded finds. */
id
generic_find_creturn (id wherein, char *name, int *number)
{
int i,m;
BOOL flag = YES;
id victim = NULL;
/* Guard against underflow, or else some dork will crash the mud asking */
/* for the -maxint sword. */
if (*number <= 0)
return NULL;
for(i=0,m=[wherein size];(i<m) && flag;i++) {
id whatever = [wherein at:i];
if (!strcmp ([whatever mudname], name)) {
if (!(--(*number))) {
flag = NO;
victim = whatever;
}
}
}
return victim;
}
/* Find something. */
id
generic_find (id wherein, char *name, int number)
{
return generic_find_creturn (wherein, name, &number);
}
/* This is kind of the opposite of generic_find. */
int
generic_number (id wherein, char *name, id what)
{
int i,m,n = 0;
BOOL flag = YES;
for(i=0,m=[wherein size];(i<m) && flag;i++) {
id whatever = [wherein at:i];
if (!strcmp ([whatever mudname], name)) {
n++;
if (what == whatever)
flag = NO;
}
}
if (flag == NO)
return n;
return 0;
}
/* Find something, preserving the count over two separate containers. */
id
generic_find_cascade (id wherein1, id wherein2, char *name, int number)
{
id victim = NULL;
victim = generic_find_creturn (wherein1, name, &number);
if (victim)
return victim;
return generic_find_creturn (wherein2, name, &number);
}
int
generic_number_cascade (id wherein1, id wherein2, char *name, id what)
{
int i,m,n = 0;
BOOL flag = YES;
for(i=0,m=[wherein1 size];(i<m) && flag;i++) {
id whatever = [wherein1 at:i];
if (!strcmp ([whatever mudname], name)) {
n++;
if (what == whatever)
flag = NO;
}
}
if (flag == NO)
return n;
for(i=0,m=[wherein2 size];(i<m) && flag;i++) {
id whatever = [wherein2 at:i];
if (!strcmp ([whatever mudname], name)) {
n++;
if (what == whatever)
flag = NO;
}
}
if (flag == NO)
return n;
return 0;
}
/* This assumes that t1 >= t2 and that they are not that far apart. Return */
/* value is in microseconds. */
long
difftimeval (struct timeval *t1, struct timeval *t2)
{
return ((t1->tv_sec - t2->tv_sec) * 1000000 + t1->tv_usec) - t2->tv_usec;
}
/* Return number of microseconds since last heartbeat. */
/* As an auxilliary duty, this function stabilizes things if the system clock */
/* takes a flying leap. */
long
timesincelastheartbeat ()
{
struct timeval t;
gettimeofday (&t, NULL);
/* Has the clock run backwards? Is it way ahead of us (10 seconds)? */
if (((t.tv_sec < lastheartbeat.tv_sec) ||
(t.tv_sec == lastheartbeat.tv_sec &&
t.tv_usec < lastheartbeat.tv_usec)) ||
(t.tv_sec - lastheartbeat.tv_sec > 9)) {
/* Arrrgh! Fix it! */
lastheartbeat.tv_sec = t.tv_sec;
lastheartbeat.tv_usec = t.tv_usec;
return 0;
}
return difftimeval (&t, &lastheartbeat);
}
char *
capitalize (char *a)
{
static char b[80];
strcpy (b, a);
if (b[0] >= 'a' && b[0] <= 'z')
b[0] = b[0] - 'a' + 'A';
return b;
}
id
get_random_member (id from)
{
id r = nil;
BOOL flag = YES;
int i,m,c, n;
if (!(c = [from size]))
return NULL;
n = random() % c;
for(i=0,m=[from size];(i<m) && flag;i++) {
id whatever = [from at:i];
if (!(n--)) {
flag = NO;
r = whatever;
}
}
return r;
}
/* This is preferable to cat_text_file since it will work for non-players. */
/* However, lines will be cut off at 1000 chars. */
void
echo_text_file (id who, char *fname)
{
FILE *fp;
if ((fp = fopen (fname, "r")))
{
char buf[1000];
while (fgets (buf, 1000, fp))
[who echo: noeol (buf)];
fclose (fp);
}
}
/* Save all players immediately. */
void
checkpoint ()
{
int i,m;
for(i=0,m=[world size];i<m;i++) {
id whatever = [world at:i];
if ([whatever isKindOf: [Player class]])
[whatever save];
}
}