/
order.v1/
order.v1/order/
/***************************************************************************
 *  Original Diku Mud copyright (C) 1990, 1991 by Sebastian Hammer,	   *
 *  Michael Seifert, Hans Henrik St{rfeldt, Tom Madsen, and Katja Nyboe.   *
 *									   *
 *  Merc Diku Mud improvments copyright (C) 1992, 1993 by Michael	   *
 *  Chastain, Michael Quan, and Mitchell Tse.				   *
 *									   *
 *  In order to use any part of this Merc Diku Mud, you must comply with   *
 *  both the original Diku license in 'license.doc' as well the Merc	   *
 *  license in 'license.txt'.  In particular, you may not remove either of *
 *  these copyright notices.						   *
 *									   *
 *  Much time and thought has gone into this software and you are	   *
 *  benefitting.  We hope that you share your changes too.  What goes	   *
 *  around, comes around.						   *
 ***************************************************************************/
/***************************************************************************
*       ROM 2.4 is copyright 1993-1995 Russ Taylor                         *
*       ROM has been brought to you by the ROM consortium                  *
*           Russ Taylor (rtaylor@pacinfo.com)                              *
*           Gabrielle Taylor (gtaylor@pacinfo.com)                         *
*           Brian Moore (rom@rom.efn.org)                                  *
*       By using this code, you have agreed to follow the terms of the     *
*       ROM license, in the file Rom24/doc/rom.license                     *
***************************************************************************/
/***************************************************************************  
*   MND is copyright 2000-2002 Charles Tillery (Muerte/Ao)                 *  
*   By using this code, you have agreed to follow the terms:               *  
*   This header is not to be removed, help entry will not be edited to     *  
*   remove the authors name and thanks. If you have any addition, mods, or *
*   bug reports, please e-mail muerte@acestar.org				   *
***************************************************************************/  

#include <sys/types.h>
#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include "merc.h"
#include "interp.h"

char *order_bit_name( int order_flags )
{
  static char buf[512];
  
  buf[0] = '\0';
  if ( order_flags & ORDER_ADDED  ) strcat( buf, " added"   );  
  if ( order_flags & ORDER_INDEPENDENT	) strcat( buf, " independent"	);
  if ( order_flags & ORDER_CHANGED	) strcat( buf, " changed"	);
  if ( order_flags & ORDER_DELETED	) strcat( buf, " deleted"	);
  
  return ( buf[0] != '\0' ) ? buf+1 : "none";
}

bool can_order(CHAR_DATA * ch)
{
    if (!ch->order)
	return FALSE;
    if (IS_IMMORTAL(ch) && !str_cmp(ch->name, ch->order_ptr->patron))
	return TRUE;

    return ch->order_ptr->ml[0];
}

bool can_deorder(CHAR_DATA * ch) 
{
    if (ch->order == 0)
	return FALSE;
    if (!str_cmp(ch->name, ch->order_ptr->patron))
        return TRUE;

    return ch->order_ptr->ml[1];
}

bool can_orderpromote(CHAR_DATA * ch)
{
    if (ch->order == 0)
	return FALSE;
    if (!str_cmp(ch->name, ch->order_ptr->patron))
        return TRUE;

    return ch->order_ptr->ml[2];
}

bool can_orderdemote(CHAR_DATA * ch)
{
    if (ch->order == 0)
	return FALSE;
    if (!str_cmp(ch->name, ch->order_ptr->patron))
        return TRUE;

    return ch->order_ptr->ml[3];
}

bool is_order(CHAR_DATA * ch)
{
    if (ch->order_ptr == NULL)
    	return FALSE;
    else
        return TRUE;
}

bool is_same_order(CHAR_DATA * ch, CHAR_DATA * victim)
{
    if (ch->order == victim->order)
	return TRUE;
    else
	return FALSE;
} 

char *player_orderrank(CHAR_DATA * ch)
{
    if (ch->order == NULL)
	return (char *)NULL;
    return 
	ch->order_ptr->rank[ch->orderrank].rankname;
} 

char *player_order(CHAR_DATA * ch)
{
    if (ch->order == 0)
	return '\0';
    return ch->order;
} 

void do_orderrank(CHAR_DATA * ch, char *argument)
{
    char arg1[MAX_INPUT_LENGTH];
    char arg2[MSL];
    char buf[MAX_STRING_LENGTH];
    CHAR_DATA *victim;
    ORDERMEM_DATA *ordermem = NULL;
    ORDER_DATA *pOrder;
    int cnt;

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);

    if (!can_orderpromote(ch))
    {
	send_to_char("huh?\n\r", ch);
	return;
    }

    if (arg1[0] == '\0' || arg2[0] == '\0')
    {
	send_to_char("Syntax: orderrank <name> <rank #>\n\r", ch);
	send_to_char("where rank is one of the following:\n\r", ch);

	for (cnt = 0; cnt < MAX_ORDERRANK; cnt++)
	{
	  sprintf(buf, "%2d] %s\n\r", cnt + 1,
 	    is_order(ch) ? ch->order_ptr->rank[cnt].rankname : "(None)");
	  send_to_char(buf, ch);
	}
	send_to_char("\n\r", ch);
	return;
    }			

    if ((victim = get_char_world(ch, arg1)) == NULL)
    {
	send_to_char("They aren't playing.\n\r", ch);
	return;
    }

    if (!is_order(victim))
    {
        send_to_char("They are not a ordermem of any orders!\n\r", ch);
        return;
    }

    if (!IS_IMMORTAL(ch) && !is_same_order(ch, victim))
    {
	send_to_char("They are a ordermem of a order different than yours!\n\r", ch);
	return;
    }

    cnt = atoi(arg2) - 1;
    if ((cnt < 0 || cnt > MAX_ORDERRANK -1 || victim->order_ptr->rank[cnt].rankname == NULL))
    {
        send_to_char("That rank does not exist!", ch);
        return;
    }

    if (cnt > victim->orderrank && ((ch == victim) && (!IS_IMMORTAL(ch))))
    {
	send_to_char("Nice try, you can not promote yourself.", ch);
	return;
    }

    if (cnt > victim->orderrank)
    {
	printf_to_char(victim, "You have been promoted to %s of %s by %s.\n\r", victim->order_ptr->rank[cnt].rankname, victim->order_ptr->patron, ch->name);
	printf_to_char(ch, "%s has been promoted to %s of %s by you.\n\r", victim->name, victim->order_ptr->rank[cnt].rankname, victim->order_ptr->patron);
    } 
    
    else if (cnt < victim->orderrank)
    {
        printf_to_char(victim, "You have been demoted to %s of %s by %s.\n\r", victim->order_ptr->rank[cnt].rankname, victim->order_ptr->patron, ch->name);
        printf_to_char(ch, "%s has been demoted to %s of %s by you.\n\r", victim->name, victim->order_ptr->rank[cnt].rankname, victim->order_ptr->patron);
    }		
    victim->orderrank = cnt;

    del_ordermem(victim->name);
    ordermem = alloc_mem(sizeof(*ordermem));
    ordermem->order = victim->order_ptr;
    ordermem->name = victim->name;
    ordermem->rank = cnt;
    ordermem->next = NULL;   
    add_ordermem(ordermem);

    sprintf(buf, victim->order);
    for (pOrder = order_first; pOrder; pOrder = pOrder->next)
    {
	if (pOrder->name == victim->order)
	    do_function(ch, &do_osave, buf);
    }

    return;
} 
void do_unpatron(CHAR_DATA * ch, char *argument)
{
    DESCRIPTOR_DATA *d;
    ORDERMEM_DATA *ordermem;
    char arg1[MSL];
    argument = one_argument(argument, arg1);

    if (IS_IMMORTAL(ch))
    {
        if (arg1[0] == '\0')
        {
            printf_to_char(ch, "Who do you want to remove from your order?\n\r");
            return;
        }
        for (ordermem = ordermem_first; ordermem; ordermem = ordermem->next)
        {
            if (!str_cmp(ordermem->name, arg1) && !str_cmp(ordermem->order->patron, ch->name))
            {
                for (d = descriptor_list; d != NULL; d = d->next)
                {
                    if (d->connected == CON_PLAYING && IS_IMMORTAL(d->character))
                    {
                        printf_to_char(d->character, "{WORDER: [{M%s{W] has been removed from %s by %s{x.\n\r", ordermem->name, ordermem->order->patron);
                    }
                }
                del_ordermem(ordermem->name);
            }
	    else
		printf_to_char(d->character, "{WORDER: arg1 %s ordermem->order->patron %s{x.\n\r", arg1, ordermem->order->patron);
        }
   	return;
    }
    else if (!IS_IMMORTAL(ch))
    {
        if (!ch->order)  
        {
            printf_to_char(ch, "You are not part of any order.\n\r");
            return;
        }
        printf_to_char(ch, "You have quit being a %s of %s. You are no longer a member of any order.\n\r", ch->order_ptr->rank[ch->orderrank].rankname, ch->order_ptr->patron);
        for (d = descriptor_list; d != NULL; d = d->next)
        {
                if (d->connected == CON_PLAYING && IS_IMMORTAL(d->character))
                {
                    printf_to_char(d->character, "{WORDER: [{M%s{W] has quit being a %s of %s{x.\n\r", ch->name, ch->order_ptr->rank[ch->orderrank].rankname, ch->order_ptr->patron);
                }
        }
        del_ordermem(ch->name);
        ch->order_ptr = NULL;
        ch->order = NULL;
        ch->orderrank = 0;  
	return;
    }
}

void do_patron(CHAR_DATA * ch, char *argument)
{
    char arg1[MAX_INPUT_LENGTH], arg2[MAX_INPUT_LENGTH];
    CHAR_DATA *victim;
    ORDERMEM_DATA *ordermem = NULL;

    argument = one_argument(argument, arg1);
    argument = one_argument(argument, arg2);

    if (!IS_IMMORTAL(ch) && arg1[0] == '\0')
    {
	send_to_char("Syntax: patron <god>\n\r", ch);
	return;
    }

    if (IS_IMMORTAL(ch) && arg1[0] == '\0')
    {
        send_to_char("Syntax: patron <mortal>\n\r", ch);              
        return;
    }

    if ((victim = get_char_world(ch, arg1)) == NULL && IS_IMMORTAL(ch))
    {
	send_to_char("They aren't playing.\n\r", ch);
	return;
    }

    if (!IS_IMMORTAL(ch) && !(ch->order_ptr = order_lookup(arg1)))
    {
	send_to_char("No such god exists.\n\r", ch);
	return;
    }
    else if (IS_IMMORTAL(ch) && !(victim->order_ptr = order_lookup(ch->name)))
    {
        send_to_char("You don't have an order to accept followers.\n\r", ch);
        return;
    }
 
    if (!IS_IMMORTAL(ch))
    {
	if (!(ch->order_ptr = order_lookup(arg1)))
        {
            send_to_char("No such god exists.\n\r", ch);
            return;
        }
    	ch->order = str_dup(ch->order_ptr->name);
    	ch->orderrank = 0;		/* lowest, default */
    	ordermem = alloc_mem(sizeof(*ordermem));
    	ordermem->order = ch->order_ptr;
    	ordermem->name = ch->name;
    	ordermem->rank = ch->orderrank;
    	ordermem->next = NULL;
    }

    else if (IS_IMMORTAL(ch))
    {
        victim->order = str_dup(ch->order_ptr->name);
        victim->orderrank = 0;          /* lowest, default */
        ordermem = alloc_mem(sizeof(*ordermem));
        ordermem->order = victim->order_ptr;
        ordermem->name = victim->name;
        ordermem->rank = victim->orderrank;
        ordermem->next = NULL;
    }

    add_ordermem(ordermem);
    do_function(ch, &do_osave, "orders");

    if (IS_IMMORTAL(ch)) 
    {
        printf_to_char(ch, "%s is now a %s of %s.\n\r", victim->name, victim->order_ptr->rank[victim->orderrank].rankname, victim->order_ptr->patron);
    	printf_to_char(victim, "You are now a %s of %s.\n\r", victim->order_ptr->rank[victim->orderrank].rankname, victim->order_ptr->patron);
    }
    else
    {
        printf_to_char(ch, "You are now a %s of %s.\n\r", ch->order_ptr->rank[ch->orderrank].rankname, ch->order_ptr->patron);
    }
    return;

} 

char strOrder[MSL];
ORDER_DATA *current_order;
ORDER_DATA *order_first;
ORDER_DATA *order_last;
ORDERMEM_DATA *ordermem_first = NULL;
ORDERMEM_DATA *ordermem_last = NULL; 
int top_order;

void load_order(FILE * fp)
{
    ORDER_DATA *pOrder;
    bool fMatch = FALSE;
    ORDERMEM_DATA *ordermem = NULL;
    char *word;
    int i;

    pOrder = alloc_perm(sizeof(ORDER_DATA)); 
    pOrder->file_name = fread_string(fp);

    pOrder->vnum = top_order;
    for (;;)
    {
        word = fread_word(fp);

	if (!str_cmp(word, "End"))
	    break;

        switch (UPPER(word[0]))
	{
        case '*':
            fMatch = TRUE;
            fread_to_eol(fp);
            break;

	case 'E':
	    if (!str_cmp(word, "End"))
            break;

        case 'F':
	    KEY("Flags", pOrder->flags, fread_flag(fp));	
            break;
              
  	case 'O':
            KEY("Order", pOrder->name, fread_string(fp));
	    break;

        case 'P':
            KEY("Patron", pOrder->patron, fread_string(fp));
            break;

	case 'R':
	    if (!str_cmp(word, "Rank"))
	    {
		i = fread_number(fp);
		pOrder->rank[i - 1].rankname = fread_string(fp);
	    }
	    break;

	case 'M':
	    if (!str_cmp(word, "Member"))
            {
  	        ordermem = alloc_mem(sizeof(*ordermem)); 
		ordermem->name = fread_string(fp);
		ordermem->rank = fread_number(fp);
		ordermem->next = NULL;
		ordermem->order = pOrder;
		add_ordermem(ordermem);
            }
	    if (!str_cmp(word, "ML"))
	    {
		for(i=0;i<4;i++)
	            pOrder->ml[i] = fread_number(fp);
	    }
            break;
	}
    }				

    if (!order_first)
	order_first = pOrder;
    if (order_last)
    {
	order_last->next = pOrder;
    }
    order_last = pOrder;
    pOrder->next = NULL;
    current_order = pOrder; 

    top_order++;
}

void load_orderlist()
{     
    FILE *fpList;
    FILE *fpOrder;
    char *word;
    char buf[MSL];

    if ((fpList = fopen(ORDER_LIST, "r")) == NULL)
    {
        perror(ORDER_LIST);
        exit(1);
    }
            
    for (;;)
    {
        word =  fread_word(fpList);
        strcpy(strOrder, ORDER_DIR);
        strcat(strOrder, word);

        if(word[0] == '$')
            break;

        if (word[0] == '-')
        {
            fpOrder = stdin;
        }
	else 
	{
            if ((fpOrder = fopen(strOrder, "r")) == NULL)
            {
                perror(strOrder);
                exit(1);
            }
        }

        current_order = NULL; 
        sprintf(buf, "Loading %s.", word);
        log_string(buf);            
	load_order(fpOrder);		
                
        if (fpOrder != stdin)
            fclose(fpOrder);
        fpOrder = NULL;
    }
    fclose(fpList);
}

ORDER_DATA *order_name(CHAR_DATA *ch)
{
    ORDER_DATA *order_current;
    for(order_current=order_first;order_current!=NULL;order_current=order_current->next)
    {
        if(!str_cmp(ch->order,order_current->name))
        {
           return order_current;
        }
    }
    if(order_current==NULL)
    {
        return '\0';
    }
    return '\0';
}

ORDER_DATA *order_lookup(const char *name)
{ 
    ORDER_DATA *order_current;
    for(order_current=order_first;order_current!=NULL;order_current=order_current->next)
    {
        if(!str_cmp(order_current->patron, name))
           return order_current;
    }
    if(order_current==NULL)
    {
        return NULL;
    }
    return NULL;
}

void do_followers(CHAR_DATA * ch, char *argument)
{
    ORDERMEM_DATA *ordermem;
    char arg[MAX_STRING_LENGTH];
    char class[MSL];
    int i = 0;
        
    argument = one_argument(argument, arg);

    sprintf(class, " ");
    if (IS_NPC(ch))
        return;

    if (ch->order)
    {
        printf_to_char(ch, "{W%s\n\r{Y[{c%-20s{Y]{x\n\r", ch->order, "member");
        for (ordermem = ordermem_first; ordermem; ordermem = ordermem->next)
        {
            if (!str_cmp(ordermem->order->name, ch->order_ptr->name)  || ch->order_ptr->patron == ordermem->order->patron)
            {
                i++;
                printf_to_char(ch, "    %s %s\n\r", ordermem->order->rank[ordermem->rank].rankname, ordermem->name);
            }
        }
	printf_to_char(ch,"\n\rTotal Order Members: {W%-3d\n\r", i);
	return;
    }
    if (!IS_IMMORTAL(ch))
    {
	send_to_char("You are not part of a order.\n\r", ch);
	return;
    }
    return;
}

int add_ordermem( ORDERMEM_DATA * mMemb)
{
    ORDERMEM_DATA *seek = NULL;

    printf("Loading name: %s\n\r", mMemb->name);
    if (ordermem_first == NULL)
    {
        ordermem_first = ordermem_last = mMemb; // head and tail same
        return 1;
    }
    for (seek = ordermem_first; seek && strcasecmp(seek->name, mMemb->name); seek = seek->next); 
    if (ordermem_last && !seek)
    {
        ordermem_last->next = mMemb;
        ordermem_last = mMemb;
        return 1;
    }
    else
        printf("Repetition\n\r");
    return 0;
}

int del_ordermem ( char * name_of_player ) 
{
    ORDERMEM_DATA * prev = NULL, * seek = NULL;
    char buf[MSL];

    sprintf(buf, "DELETE CHECK 1 %s", name_of_player);
    log_string(buf);
    if (!ordermem_first || !name_of_player) 
    {
        printf("No list to look into\n\r");
        return -1;
    }
    
    for ( seek = prev = ordermem_first;  seek && strcasecmp ( seek->name, name_of_player );  prev = seek, seek = seek->next);
	    
    if (seek) 
    {
        if (seek == ordermem_first) 
        {
            printf("Found member %s on the head of the list\n\r", name_of_player);
            if (ordermem_first == ordermem_last) 
            {
                printf("This is also the last ordermem of the list\n\r");
                ordermem_first = ordermem_last = ordermem_first->next;
            }
	    else 
                ordermem_first = ordermem_first->next;
        }
        else if (seek->next) 
        {
            printf("Found member %s at middle point of the list\n\r", name_of_player);
            prev->next = seek->next;
        }
        else if (seek == ordermem_last) 
        {
            printf("Found member %s at the end of the list\n\r", name_of_player);
            ordermem_last = prev;
            prev->next = NULL;
        }
            free_mem(seek, sizeof(ORDERMEM_DATA));
    } 
    else
        printf("member not found\n\r");
    return 0;
}