roh/conf/area/
roh/game/talk/
roh/help/
roh/monsters/ocean/
roh/objects/ocean/
roh/player/
roh/rooms/area/1/
roh/rooms/misc/
roh/rooms/ocean/
roh/src-2.44b/
/*
 * guilds.cpp
 *	 Player run guilds.
 *   ____            _
 *  |  _ \ ___  __ _| |_ __ ___  ___
 *  | |_) / _ \/ _` | | '_ ` _ \/ __|
 *  |  _ <  __/ (_| | | | | | | \__ \
 *  |_| \_\___|\__,_|_|_| |_| |_|___/
 *
 * Permission to use, modify and distribute is granted via the
 *  Creative Commons - Attribution - Non Commercial - Share Alike 3.0 License
 *    http://creativecommons.org/licenses/by-nc-sa/3.0/
 *
 * 	Copyright (C) 2007-2009 Jason Mitchell, Randi Mitchell
 * 	   Contributions by Tim Callahan, Jonathan Hseu
 *  Based on Mordor (C) Brooke Paul, Brett J. Vickers, John P. Freeman
 *
 */
#include <fcntl.h>
#include "mud.h"
#include "commands.h"
#include "move.h"
#include "guilds.h"
#include "property.h"
#include "dm.h"
#include "web.h"

//*********************************************************************
//						Guild
//*********************************************************************

Guild::Guild() {
	name = "";
	leader = "";
	num = 0;
	level = numMembers = pkillsIn = pkillsWon = 0;
	points = 0;
}

GuildCreation::GuildCreation() {
	name = "";
	leader = leaderIp = "";
	status = numSupporters = 0;
}


// Prototypes

void printGuildSyntax(Player* player) {
	player->printColor("Syntax: guild ^e<^xlist^e>\n");
	player->printColor("              ^e<^xfound^e>^x ^e<^cguild name^e>\n");
	if(gConfig->getWebserver() != "")
		player->printColor("              ^e<^xforum^e>^x ^e<^cforum account^e>^x - set the guildmaster of the forum board\n");
	player->printColor("              ^e<^xcancel^e>\n");
	player->printColor("              ^e<^xsupport^e>^x ^e<^cguild name^e>\n");
	player->printColor("              ^e<^xinvite^e>^x ^e<^cplayer name^e>\n");
	player->printColor("              ^e<^xremove^e>^x ^e<^cplayer name^e>\n");
	player->printColor("              ^e<^xabdicate^e>^x ^e<^cplayer name^e>\n");
	player->printColor("              ^e<^xaccept^e>\n");
	player->printColor("              ^e<^xreject^e>\n");
	player->printColor("              ^e<^xpromote^e>^x ^e<^cplayer name^e>^x ^e[^crank^e]\n");
	player->printColor("              ^e<^xdemote^e>^x ^e<^cplayer name^e>^x ^e[^crank^e]\n");
	player->printColor("              ^e<^xmembers^e>\n");
	player->printColor("              ^e<^xhall^e>\n");
}


//"              <disband>\n";
// Guild Ranks
//			Non Officer		Officer
//			4,  5,  6,		7,  8,  9     Invite flags
//			12, 13, 14,		17, 18, 19    Actual status

const int	GUILD_NONE = 0,
			GUILD_INVITED = 1,
			GUILD_INVITED_OFFICER = 5,
			GUILD_INVITED_BANKER = 6,

			GUILD_PEON = 11,
			GUILD_OFFICER = 15,
			GUILD_BANKER = 16,
			GUILD_MASTER = 20;

// What happened -- Used in adjusting guild level
const int   GUILD_JOIN = 0,
			GUILD_REMOVE = 1,
			GUILD_LEVEL = 2,
			GUILD_DIE = 3;

// Guild Creation Status variables
const int	GUILD_NEEDS_SUPPORT = 1,
			GUILD_AWAITING_APPROVAL = 2;

// level requirements
const int	GUILD_FOUND_LEVEL = 13,
			GUILD_SUPPORT_LEVEL = 10,
			GUILD_JOIN_LEVEL = 7;


//*********************************************************************
//						cmdGuild
//*********************************************************************
// Player command used to do various guild functions

int cmdGuild(Player* player, cmd* cmnd) {
	//Creature* target = NULL;
	int		len=0;
	//int len,i=0,j=0;
	//guildCreationPtr newGuildCreation;

	if(cmnd->num < 2) {
		printGuildSyntax(player);
		return(0);
	}

	len = strlen(cmnd->str[1]);

	// Found/Create a new guild
	if(!strncmp(cmnd->str[1], "found", len) ||
	        !strncmp(cmnd->str[1], "create", len)) {
		guildCreate(player, cmnd);
	}

	// Cancel the creation of a guild
	else if(!strncmp(cmnd->str[1], "cancel", len)) {
		guildCancel(player, cmnd);
	}

	// Create a forum for the guild
	else if(!strncmp(cmnd->str[1], "forum", len)) {
		guildForum(player, cmnd);
	}

	// Support the creation of a guild
	else if(!strncmp(cmnd->str[1], "support", len)) {
		guildSupport(player, cmnd);
	}

	// Invite someone into your guild
	else if(!strncmp(cmnd->str[1], "invite", len)) {
		guildInvite(player, cmnd);
	}

	// Transfer leadership of the guild to someone else
	else if(!strncmp(cmnd->str[1], "abdicate", len)) {
		guildAbdicate(player, cmnd);
	}

	// Remove someone from your guild
	else if(!strncmp(cmnd->str[1], "remove", len) ||
	        !strncmp(cmnd->str[1], "dismiss", len)) {
		guildRemove(player, cmnd);
	}

	// Accept an offer to join a guild
	else if(!strncmp(cmnd->str[1], "join", len) ||
	        !strncmp(cmnd->str[1], "accept", len)) {
		guildJoin(player, cmnd);
	}

	// Reject someone's offer to join a guild
	else if(!strncmp(cmnd->str[1], "reject", len)) {
		guildReject(player, cmnd);
	} else if(!strcmp(cmnd->str[1], "disband")) {
		guildDisband(player, cmnd);
	}

	// Promote someone
	else if(!strncmp(cmnd->str[1], "promote", len)) {
		guildPromote(player, cmnd);
	}

	// Demote someone
	else if(!strncmp(cmnd->str[1], "demote", len)) {
		guildDemote(player, cmnd);
	}

	// List current guilds
	else if(!strncmp(cmnd->str[1], "list", len)) {
		guildList(player, cmnd);
	} else if(!strncmp(cmnd->str[1], "members", len)) {
		guildMembers(player, cmnd);
	}

	// Guild Bank Stuff
	else if(!strncmp(cmnd->str[1], "deposit", len)) {
		guildDeposit(player, cmnd);
	} else if(!strncmp(cmnd->str[1], "withdraw", len)) {
		guildWithdraw(player, cmnd);
	} else if(!strncmp(cmnd->str[1], "transfer", len)) {
		guildTransfer(player, cmnd);
	} else if(!strncmp(cmnd->str[1], "statement", len)) {
		guildStatement(player, cmnd);
	} else if(!strncmp(cmnd->str[1], "balance", len)) {
		guildBalance(player, cmnd);

	} else if(!strncmp(cmnd->str[1], "hall", len)) {
		guildHall(player, cmnd);
	} else {
		// Default case
		printGuildSyntax(player);
	}

	return(0);
}


//*********************************************************************
//						guildCreate
//*********************************************************************

int guildCreate(Player* player, cmd* cmnd) {
	int len,i=0,j=0, a=0;
	GuildCreation* newGuildCreation;
	char guildName[41];

	if(player->getLevel() < GUILD_FOUND_LEVEL && !player->isDm()) {
		player->print("You must be level %d to found a guild.\n", GUILD_FOUND_LEVEL);
		return(0);
	}

	if(player->getGuild() > 0) {
		player->print("You may not create a guild because you already belong to one.\n");
		return(0);
	}

	// TODO: Check the awaiting approval list to see if they are supporting, or have a guild
	// on the approval list
	if(player->flagIsSet(P_CREATING_GUILD)) {
		player->print("You may only create one guild at a time.\n");
		return(0);
	}

	if(cmnd->num < 3) {
		printGuildSyntax(player);
		return(0);
	}

	len = strlen(cmnd->fullstr);

	// Kill the first 2 spaces
	while(i < len) {
		if(cmnd->fullstr[i] == ' ' && cmnd->fullstr[i+1] != ' ')
			j++;
		if(j==2)
			break;
		i++;
	}

	len = strlen(&cmnd->fullstr[i+1]);
	if(!len) {
		player->print("What would you like to call your guild?\n");
		return(0);
	}
	if(len > 40) {
		player->print("The guild name is too long.\n");
		return(0);
	}

	for(a=0;a<len;a++) {
		if(!isalpha(cmnd->fullstr[i+1+a]) && cmnd->fullstr[i+1+a] != ' ') {
			player->print("Name error: Characters other than letters are illegal.\n");
			player->print("Please attempt creation with a different name.\n");
			return(0);
		}
	}

	strcpy(guildName, &cmnd->fullstr[i+1]);
	if(gConfig->guildExists(guildName)) {
		player->print("A guild with that name already exists or is being considered for creation.\nPlease choose a different guild name.\n");
		return(0);
	}

	//	newGuild = gConfig->numGuilds + 1;
	//	if(newGuild >= gConfig->maxGuilds)
	//		expandGuildArray();

	newGuildCreation = new GuildCreation;
	newGuildCreation->name = guildName;
	newGuildCreation->leader = player->name;
	newGuildCreation->leaderIp = player->getSock()->getIp();
	newGuildCreation->status = GUILD_NEEDS_SUPPORT;
	newGuildCreation->numSupporters = 0;

	gConfig->addGuildCreation(newGuildCreation);
	player->setFlag(P_CREATING_GUILD);
	player->print("You attempting to create a guild with the name of '%s'\nGo find %d people to support your guild now.\n", guildName, SUPPORT_REQUIRED);
	broadcast(isCt, "^y%s is attempting to create the guild '%s'", player->name, guildName);
	gConfig->saveGuilds();
	return(0);
}

//*********************************************************************
//						guildCancel
//*********************************************************************

int guildCancel(Player* player, cmd* cmnd) {
	if(!player->flagIsSet(P_CREATING_GUILD)) {
		player->print("You aren't currently creating any guilds!\n");
		return(0);
	}
	player->clearFlag(P_CREATING_GUILD);
	bstring guildName = gConfig->removeGuildCreation(player->name);

	if(guildName != "") {
		player->print("You remove your bid to create '%s'.\n", guildName.c_str());
		return(0);
	}
	player->print("You aren't creating any guilds!\n");
	return(0);
}

//*********************************************************************
//						guildForum
//*********************************************************************
// calls the webserver - no work is done here (besides parsing)

int guildForum(Player* player, cmd* cmnd) {
	if(!player->getGuild() || player->getGuildRank() != GUILD_MASTER) {
		player->print("You are not a guildmaster.\n");
		return(0);
	}

	Guild* guild = gConfig->getGuild(player->getGuild());
	if(!guild || strstr(guild->name.c_str(), "&")) {
		player->print("Invalid guild!\n");
		return(0);
	}
	if(gConfig->getWebserver() == "") {
		player->print("The mud currently does not have a webserver configured.\n");
		return(0);
	}
	if(!cmnd->str[2][0] || strstr(cmnd->str[2], "&")) {
		player->print("You must specify a user.\n");
		return(0);
	}

	std::ostringstream url;
	player->printColor("Attempting to update guild forum with ^c%s^x as guildmaster.\n", cmnd->str[2]);
	url << "mud.php?type=guild&guild=" << guild->name << "&user=" << cmnd->str[2] << "&char=" << player->name;
	callWebserver(url.str());
	return(0);
}

//*********************************************************************
//						guildSupport
//*********************************************************************

int guildSupport(Player* player, cmd* cmnd) {
	GuildCreation *toSupport=0;
	char	guildName[41];
	int		len=0, i=0, j=0;

	if(player->getLevel() < GUILD_SUPPORT_LEVEL && !player->isDm()) {
		player->print("You must be level %d to support a guild!\n", GUILD_SUPPORT_LEVEL);
		return(0);
	}

	if(player->getGuild() > 0) {
		player->print("You may not support a guild because you already belong to one.\n");
		return(0);
	}
	if(player->flagIsSet(P_CREATING_GUILD)) {
		player->print("You may only support one guild at a time.\n");
		return(0);
	}

	if(cmnd->num < 3) {
		printGuildSyntax(player);
		return(0);
	}

	len = strlen(cmnd->fullstr);

	// Kill the first 2 spaces
	while(i < len) {
		if(cmnd->fullstr[i] == ' ' && cmnd->fullstr[i+1] != ' ')
			j++;
		if(j==2)
			break;
		i++;
	}

	len = strlen(&cmnd->fullstr[i+1]);
	if(!len) {
		player->print("Which guild would you like to support?\n");
		return(0);
	}
	if(len>40)
		cmnd->fullstr[40] = '\0';

	strcpy(guildName, &cmnd->fullstr[i+1]);
	toSupport = gConfig->findGuildCreation(guildName);
	if(toSupport == NULL) {
		player->print("'%s' is not currently up for creation.\n", guildName);
		return(0);
	}
	if(toSupport->status != GUILD_NEEDS_SUPPORT) {
		player->print("'%s' is not currently in need of support.\n", guildName);
		return(0);
	}


	// check the address
	bool sameIp = (player->getSock()->getIp() == toSupport->leaderIp);

	if(!sameIp) {
		std::map<bstring, bstring>::iterator sIt;
		for(sIt = toSupport->supporters.begin() ; sIt != toSupport->supporters.end() ; sIt++) {
			if((*sIt).second == player->getSock()->getIp()) {
				sameIp = true;
				break;
			}
		}
	}
	if(sameIp) {
		player->print("Someone from your IP address is already supporting this guild.\n");
		player->print("Remember, do not use alternate characters to support a guild.\n");
		return(0);
	}

	player->setFlag(P_CREATING_GUILD);

	player->print("You now supporting the creation of the guild '%s'.\n", guildName);
	broadcast(isCt, "^y%s is supporting the guild '%s'", player->name, guildName);
	toSupport->addSupporter(player);

	if(toSupport->numSupporters >= SUPPORT_REQUIRED) {
		Player* leader=0;

		toSupport->status = GUILD_AWAITING_APPROVAL;
		// We now have enough players to seek staff approval
		player->print("There are now enough people supporting the guild, it has been submitted for staff approval.\n");
		leader = gServer->findPlayer(toSupport->leader.c_str());
		if(leader)
			leader->print("There are now enough people supporting your guild, it has been submitted for staff approval.\n");
		broadcast(isCt, "^yThe guild '%s' is in need of staff approval.", guildName);
	}

	gConfig->saveGuilds();
	return(0);
}

//*********************************************************************
//						guildInvite
//*********************************************************************

int guildInvite(Player* player, cmd* cmnd) {
	Player	*target=0;

	if(!player->getGuild() || player->getGuildRank() < GUILD_OFFICER) {
		player->print("You are not an officer in a guild.\n");
		return(0);
	}

	if(cmnd->num < 3) {
		player->print("Invite who into your guild?\n");
		return(0);
	}

	lowercize(cmnd->str[2], 1);
	target = gServer->findPlayer(cmnd->str[2]);

	if(!target || !player->canSee(target)) {
		player->print("%s is not on.\n", cmnd->str[2]);
		return(0);
	}

	if(Move::tooFarAway(player, target, "invite into your guild"))
		return(0);

	if(target->getLevel() < GUILD_JOIN_LEVEL) {
		player->print("%s does not meet the minimum required level of %d to join a guild!\n",
			target->name, GUILD_JOIN_LEVEL);
		return(0);
	}

	if(target->getGuildRank() >= GUILD_INVITED && target->getGuildRank() < GUILD_PEON) {
		player->print("%s is currently considering joining a guild already.\n", target->name);
		return(0);
	}

	if(target->getGuild()) {
		player->print("%s is already in a guild.\n", target->name);
		return(0);
	}

	// Set this initially, change it if needed
	target->setGuildRank(GUILD_INVITED);
	target->setGuild(player->getGuild());

	if(player->getGuildRank() == GUILD_MASTER) {
		if(!strncmp(cmnd->str[3], "officer", strlen(cmnd->str[3])) && cmnd->num == 4) {
			player->print("You invite %s to join your guild as an officer.\n", target->name);
			target->print("You have been invited to join '%s' as an officer by %s.\n", getGuildName(player->getGuild()), player->name);
			target->setGuildRank(GUILD_INVITED_OFFICER);
		} else if(!strncmp(cmnd->str[3], "banker", strlen(cmnd->str[3])) && cmnd->num == 4) {
			player->print("You invite %s to join your guild as a banker.\n", target->name);
			target->print("You have been invited to join '%s' as a banker by %s.\n", getGuildName(player->getGuild()), player->name);
			target->setGuildRank(GUILD_INVITED_BANKER);
		} else {
			player->print("You invite %s to join your guild as a normal member.\n", target->name);
			target->print("You have been invited to join '%s' by %s.\n", getGuildName(player->getGuild()), player->name);
			target->setGuildRank(GUILD_INVITED);
		}
	} else {
		player->print("You invite %s to join your guild as a normal member.\n", target->name);
		target->print("You have been invited to join '%s' by %s.\n", getGuildName(player->getGuild()), player->name);
		target->setGuildRank(GUILD_INVITED);
	}
	target->print("To join type 'guild accept'\n");
	return(0);
}

//*********************************************************************
//						guildRemove
//*********************************************************************

void shopRemoveGuild(Property *p, Player* player, Room* shop, Room* storage);

int guildRemove(Player* player, cmd* cmnd) {
	Player	*target=0;

	if((!player->getGuild() || player->getGuildRank() < GUILD_OFFICER) && cmnd->num >= 3) {
		player->print("You are not an officer. You can't do that.\n");
		return(0);
	}
	if(!player->getGuild()) {
		player->print("You aren't in a guild!\n");
		return(0);
	}

	if(cmnd->num < 3) { // Remove yourself
		if(player->getGuildRank() != GUILD_MASTER) {
			int guildId;

			if(!canRemovePlyFromGuild(player)) {
				player->print("Guilds cannot drop below 3 players, the guild must be disbanded.\n");
				return(0);
			}
			updateGuild(player, GUILD_REMOVE);
			player->print("You remove yourself from your guild (%s).\n", getGuildName(player->getGuild()));
			guildId = player->getGuild();
			player->setGuild(0);
			broadcastGuild(guildId, 0, "%s has removed %sself from your guild.\n", player->name, player->himHer());
			player->setGuildRank(GUILD_NONE);
		} else {
			player->print("As a leader of the guild, you may not leave it.  Transfer ownership to someone else first or Disband.\n");
		}
		return(0);
	}
	lowercize(cmnd->str[2], 1);
	target = gServer->findPlayer(cmnd->str[2]);
	bool online = true;

	if(!target) {
		online = false;
		if(!loadPlayer(cmnd->str[2], &target)) {
			player->print("That player does not exist.\n");
			return(0);
		}
	}

	if(target->getGuild() != player->getGuild()) {
		player->print("%s is not in your guild!\n", target->name);
		return(0);
	}
	if(target->getGuildRank() >= player->getGuildRank()) {
		player->print("You may only remove members of lower rank than you.\n");
		return(0);
	}
	if(target->getGuildRank() < GUILD_PEON) {
		player->print("%s is not in your guild!\n", target->name);
		return(0);
	}
	if(!canRemovePlyFromGuild(target)) {
		player->print("Guilds cannot drop below 3 players; the guild must be disbanded.\n");
		return(0);
	}
	updateGuild(target, GUILD_REMOVE);
	target->setGuild(0);
	target->setGuildRank(GUILD_NONE);
	target->print("You have been removed from your guild by %s.\n", player->name);
	player->print("You remove %s from your guild.\n", target->name);
	broadcastGuild(player->getGuild(), 0, "%s has been removed from your guild by %s.", target->name, player->name);

	if(target->getForum() != "") {
		player->printColor("%s is associated with forum account ^C%s^x.\n", target->name, target->getForum().c_str());
		player->printColor("You may wish to consider removing this account from the forum guild.\n");
	}

	std::list<Property*>::iterator pt;
	for(pt = gConfig->properties.begin(); pt != gConfig->properties.end(); pt++) {
		if((*pt)->isOwner(target->name) && (*pt)->getGuild() == player->getGuild())
			shopRemoveGuild(*pt, target, 0, 0);
	}

	if(!online)
		free_crt(target);
	return(0);
}

//*********************************************************************
//						guildPromote
//*********************************************************************

int guildPromote(Player* player, cmd* cmnd) {
	Player	*target=0;
	int newRank;
	char rank[80];

	if(!player->getGuild() || player->getGuildRank() != GUILD_MASTER) {
		player->print("You are not a guild leader.\n");
		return(0);
	}
	if(cmnd->num < 3) {
		printGuildSyntax(player);
		return(0);
	}
	lowercize(cmnd->str[2], 1);
	target = gServer->findPlayer(cmnd->str[2]);
	if(!target || !player->canSee(target)) {
		player->print("%s is not on.\n", cmnd->str[2]);
		return(0);
	}
	if(target->getGuild() != player->getGuild() || target->getGuildRank() < GUILD_PEON) {
		player->print("%s is not in your guild!\n", target->name);
		return(0);
	}
	if(cmnd->num == 4) {
		if(!strncmp(cmnd->str[3], "banker", strlen(cmnd->str[3])) && cmnd->num == 4) {
			strcpy(rank, "banker");
			newRank = GUILD_BANKER;
		} else { // if(!strncmp(cmnd->str[3], "officer", strlen(cmnd->str[3])) && cmnd->num == 4) {
			strcpy(rank, "officer");
			newRank = GUILD_OFFICER;
		}
	} else {
		if(target->getGuildRank() == GUILD_PEON) {
			newRank = GUILD_OFFICER;
			strcpy(rank, "officer");
		} else if(target->getGuildRank() == GUILD_OFFICER) {
			strcpy(rank, "banker");
			newRank = GUILD_BANKER;
		} else {
			strcpy(rank, "officer");
			newRank = GUILD_OFFICER;
		}
	}

	if(newRank <= target->getGuildRank()) {
		player->print("Promotion means moving up in the ranks, go figure.\n");
		return(0);
	}
	target->setGuildRank(newRank);
	player->print("You promote %s to %s\n", target->name, rank);
	target->print("You have been promoted to %s by %s.\n", rank, player->name);
	broadcastGuild(player->getGuild(), 0, "%s has been promoted to the rank of %s by %s.", target->name, rank, player->name);
	return(0);
}

//*********************************************************************
//						guildDemote
//*********************************************************************

int guildDemote(Player* player, cmd* cmnd) {
	Player	*target=0;
	int newRank;
	char rank[80];

	if(!player->getGuild() || player->getGuildRank() != GUILD_MASTER) {
		player->print("You are not a guild leader.\n");
		return(0);
	}
	if(cmnd->num < 3) {
		printGuildSyntax(player);
		return(0);
	}
	lowercize(cmnd->str[2], 1);
	target = gServer->findPlayer(cmnd->str[2]);
	if(!target || !player->canSee(target)) {
		player->print("%s is not on.\n", cmnd->str[2]);
		return(0);
	}
	if(target->getGuild() != player->getGuild() || target->getGuildRank() < GUILD_PEON) {
		player->print("%s is not in your guild!\n", target->name);
		return(0);
	}
	if(cmnd->num == 4) {
		if(!strncmp(cmnd->str[3], "officer", strlen(cmnd->str[3])) && cmnd->num == 4) {
			strcpy(rank, "officer");
			newRank = GUILD_OFFICER;
		} else { // if(!strncmp(cmnd->str[3], "member", strlen(cmnd->str[3])) && cmnd->num == 4) {
			strcpy(rank, "member");
			newRank = GUILD_PEON;
		}
	} else {
		if(target->getGuildRank() == GUILD_BANKER) {
			newRank = GUILD_OFFICER;
			strcpy(rank, "officer");
		} else { //if(target->getGuildRank() == GUILD_OFFICER) {
			strcpy(rank, "member");
			newRank = GUILD_PEON;
		}

	}

	if(newRank >= target->getGuildRank()) {
		player->print("Demotion means moving down the ranks, go figure.\n");
		return(0);
	}
	target->setGuildRank(newRank);
	player->print("You demote %s to %s\n", target->name, rank);
	target->print("You have been demoted to %s rank by %s\n", rank, player->name);
	broadcastGuild(player->getGuild(), 0, "%s has been demoted to %s rank by %s.", target->name, rank, player->name);
	return(0);
}

//*********************************************************************
//						guildAbdicate
//*********************************************************************

int guildAbdicate(Player* player, cmd* cmnd) {
	Player	*target=0;
	int guildId;

	if((!player->getGuild() || player->getGuildRank() != GUILD_MASTER) && cmnd->num >= 3) {
		player->print("You are not the leader of a guild.\n");
		return(0);
	}

	if(cmnd->num < 3) {
		player->print("Abdicate to who?\n");
		return(0);
	}
	lowercize(cmnd->str[2], 1);
	target = gServer->findPlayer(cmnd->str[2]);

	if(!target || !player->canSee(target)) {
		player->print("%s is not on.\n", cmnd->str[2]);
		return(0);
	}

	if(target->getGuild() != player->getGuild() || target->getGuildRank() < GUILD_PEON) {
		player->print("%s is not in your guild!\n", target->name);
		return(0);
	}

	target->setGuildRank(GUILD_MASTER);
	player->setGuildRank(GUILD_OFFICER);
	target->print("You have been promoted to guild leader by %s.\n", player->name);
	target->print("Use the \"guild\" command to set your forum account as guildmaster of the guild board.\n");
	player->print("You promote %s to guild leader.\n", target->name);

	broadcastGuild(player->getGuild(), 0, "%s has been promoted to guild leader by %s.", target->name, player->name);
	guildId = player->getGuild();
	Guild* guild = gConfig->getGuild(guildId);

	guild->leader = target->name;
	gConfig->saveGuilds();
	return(0);

}

//*********************************************************************
//						guildJoin
//*********************************************************************

int guildJoin(Player* player, cmd *cmnd) {
	bstring name = "";
	if(!player->getGuildRank()) {
		player->print("You have not been invited to join any guilds!\n");
		return(0);
	}
	if(player->getGuildRank() >= GUILD_PEON) {
		player->print("You are already in a guild.\n");
		return(0);
	}

	if(player->getLevel() < GUILD_JOIN_LEVEL) {
		player->print("You must be at least level %d to join a guild.\n", GUILD_JOIN_LEVEL);
		return(0);
	}

	if(player->getGuildRank() == GUILD_INVITED_OFFICER) {
		broadcastGuild(player->getGuild(), 0, "%s has joined your guild as officer.", player->name);
		player->setGuildRank(GUILD_OFFICER);
	} else if(player->getGuildRank() == GUILD_INVITED_BANKER) {
		player->setGuildRank(GUILD_BANKER);
		broadcastGuild(player->getGuild(), 0, "%s has joined your guild as a banker.", player->name);
	} else { // Default to normal member
		broadcastGuild(player->getGuild(), 0, "%s has joined your guild as a normal member.", player->name);
		player->setGuildRank(GUILD_PEON);
	}
	updateGuild(player, GUILD_JOIN);
	name = getGuildName(player->getGuild());
	player->print("You have joined %s.\n", name.c_str());
	if(player->getForum() != "")
		callWebserver((bstring)"mud.php?type=autoguild&guild=" + name + "&user=" + player->getForum() + "&char=" + player->name);
	return(0);

}

//*********************************************************************
//						guildReject
//*********************************************************************

int guildReject(Player* player, cmd* cmnd) {
	if(!player->getGuild() || player->getGuildRank() >= GUILD_PEON) {
		player->print("You have no offer to reject.\n");
		return(0);
	}
	player->print("You reject the offer to join %s\n", getGuildName(player->getGuild()));
	player->setGuild(0);
	player->setGuildRank(0);
	return(0);
}

//*********************************************************************
//						guildDisband
//*********************************************************************

int guildDisband(Player* player, cmd* cmnd) {
	if(!player->getGuild() || player->getGuildRank() < GUILD_MASTER) {
		player->print("You are not the guildmaster.\n");
		return(0);
	}
	int guildId = player->getGuild();
	Guild* guild = gConfig->getGuild(guildId);


	if(!guild->bank.isZero()) {
		player->print("You quickly swipe the guild's funds of %s!\n", guild->bank.str().c_str());
		player->coins.add(guild->bank);
	}
	broadcastGuild(guildId, 0, "Your guild has been disbanded by %s.", player->name);
	std::pair<bstring, Player*> p;
	Player* ply;
	foreach(p, gServer->players) {
		ply = p.second;

		if(!ply->getGuild() || ply->getGuild() != guildId)
			continue;
		ply->setGuild(0);
		ply->setGuildRank(0);
	}
	gConfig->deleteGuild(guildId);
	return(0);
}

//*********************************************************************
//						guildHall
//*********************************************************************

int guildHall(Player* player, cmd* cmnd) {
	Property::manage(player, cmnd, PROP_GUILDHALL, !strcmp(cmnd->str[0], "gh"));
	return(0);
}

//*********************************************************************
//						guildCanBank
//*********************************************************************

bool canBank(Player* player);
bool bankerCanSee(Player* player);

Guild* guildCanBank(Player* player) {

	// can they use the bank?
	if(!canBank(player))
		return(0);

	if(!player->getGuild()  || player->getGuildRank() < GUILD_PEON) {
		player->print("You hail to no guild.\n");
		return(0);
	}

	Guild* guild = gConfig->getGuild(player->getGuild());
	if(!guild) {
		if(player->getRoom()->flagIsSet(R_BANK))
			player->print("The bank teller says, \"Your guild bank account is currently unavaiable. Try back later.\"\n");
		else
			player->print("The magic money machine reports that your guild bank account is currently unavaiable.\n");
		return(0);
	}

	return(guild);
}

//*********************************************************************
//						guildDeposit
//*********************************************************************

int guildDeposit(Player* player, cmd* cmnd) {
	BaseRoom *inRoom = player->getRoom();
	unsigned long amt=0;

	// can they use the bank?
	Guild* guild = guildCanBank(player);
	if(!guild)
		return(0);

	if(cmnd->num < 3) {
		player->print("The bank teller says, \"Well! How much do you want to deposit!\"\n");
		return(0);
	}

	if(!strcmp(cmnd->str[2], "all")) {
		amt = player->coins[GOLD];
		if(amt < 1) {
			if(inRoom->flagIsSet(R_BANK))
				player->print("The bank teller says, \"You ain't got no money I'm afraid!\"\n");
			else
				player->print("The magic money machine tells you, \"You ain't got no money I'm afraid!\"\n");
			return(0);
		}
		player->print("You deposit all your gold into the guild bank!\n");
	} else if(cmnd->str[2][0] != '$') {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"Well! How much do you want to deposit!\"\n");
		else
			player->print("The magic money machine tells you, \"How much do you wish to deposit?\"\n");
		return(0);
	} else {
		amt = atol(&cmnd->str[2][1]);
		if(amt < 1) {
			if(inRoom->flagIsSet(R_BANK))
				player->print("The bank teller says, \"You've got to be kidding\".\n");
			else
				player->print("The magic money machine tells you, \"You've got to be kidding\".\n");
			return(0);
		}
	}
	if(amt > player->coins[GOLD]) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"You can't deposit money you don't have!\".\n");
		else
			player->print("The magic money machine tell syou, \"You can't deposit money you don't have!\".\n");
		return(0);
	}

	player->unhide();

	if(!bankerCanSee(player))
		return(0);

	if(player->flagIsSet(P_MISTED) || player->isInvisible()) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"I don't deal with people I can't see!\"\n");
		else
			player->print("The magic money machine tells you, \"I can't see you!\".\n");
		return(0);
	}

	player->print("You deposit %ld gold coins into your guild's bank account.\n", amt);
	guild->bank.add(amt, GOLD);
	player->coins.sub(amt, GOLD);
	if(player->getGuildRank() >= GUILD_PEON) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"Your guild's balance is now %s.\"\n", guild->bank.str().c_str());
		else
			player->print("The magic money machine tells you, \"Your guild's balance is now %s.\"\n", guild->bank.str().c_str());
	}
	broadcast(player->getSock(), player->getRoom(), "%s deposits some gold into %s guild's account.", player->name, player->hisHer());
	guildBankLog(player->getGuild(), "DEPOSIT: %ld by %s [Balance: %s]\n", amt, player->name, guild->bank.str().c_str());
	gConfig->saveGuilds();
	return(0);
}

//*********************************************************************
//						guildWithdraw
//*********************************************************************

int guildWithdraw(Player* player, cmd* cmnd) {
	BaseRoom *inRoom = player->getRoom();
	unsigned long amt=0;

	// can they use the bank?
	Guild* guild = guildCanBank(player);
	if(!guild)
		return(0);

	if(player->getGuildRank() < GUILD_BANKER) {
		player->print("You are not authorized to withdraw funds from the guild bank account.\n");
		return(0);
	}

	if(cmnd->num < 3) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"Well! How much do you want to withdraw!\"\n");
		else
			player->print("The magic money machine tells you, \"How much do you want to withdraw!\"\n");
		return(0);
	}

	if(!strcmp(cmnd->str[2], "all")) {

		amt = guild->bank[GOLD];
		if(amt < 1) {
			if(inRoom->flagIsSet(R_BANK))
				player->print("The bank teller says, \"Your guild hasn't got any money saved up!\".\n");
			else
				player->print("The magic money machine tells you, \"Your guild's bank account is empty!\"\n");
			return(0);
		}
		if(player->getGuildRank() != GUILD_MASTER) {
			if(inRoom->flagIsSet(R_BANK))
				player->print("The bank teller says, \"Thief! Thief! You can't steal all of your guild's gold!\".\n");
			else
				player->print("The magic money machine tells you, \"You can't take all of your guild's money\"\n");
		}
		player->print("You withdraw your guild's savings.\n");
	} else if(cmnd->str[2][0] != '$') {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"Well! How much do you want to withdraw!\"\n");
		else
			player->print("The magic money machine tells you, \"How much do you want to withdraw!\"\n");
		return(0);
	} else {
		amt = atol(&cmnd->str[2][1]);
		if(amt < 1) {
			if(inRoom->flagIsSet(R_BANK))
				player->print("The bank teller says, \"You've got to be kidding\".\n");
			else
				player->print("The magic money machine tells you, \"You've got to be kidding\".\n");
			return(0);
		}
	}
	if(amt > guild->bank[GOLD]) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"You can't withdraw money your guild doesn't have!\".\n");
		else
			player->print("The magic money machine tells you, \"You can't withdraw money you guild doesn't have!\".\n");
		return(0);
	}

	player->unhide();

	if(player->flagIsSet(P_MISTED) || player->isInvisible()) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"I don't deal with people I can't see!\"\n");
		else
			player->print("The magic money machine tells you, \"I don't deal with people I can't see!\"\n");
		return(0);
	}
	if(inRoom->flagIsSet(R_BANK))
		player->print("The bank teller gives you %ld gold coins.\n", amt);
	else
		player->print("You get %ld gold coins from the magic money machine.\n", amt);
	guild->bank.sub(amt, GOLD);
	player->coins.add(amt, GOLD);
	if(inRoom->flagIsSet(R_BANK))
		player->print("The bank teller says, \"Your guild's balance is now %s.\"\n", guild->bank.str().c_str());
	else
		player->print("The magic money machine tells you, \"Your guild's current balance is: %s.\"\n", guild->bank.str().c_str());
	broadcast(player->getSock(), player->getRoom(), "%s withdrew some gold from %s guild's account.", player->name, player->hisHer());
	guildBankLog(player->getGuild(), "WITHDRAW: %ld by %s [Balance: %s]\n", amt, player->name, guild->bank.str().c_str());

	player->save(true);
	gConfig->saveGuilds();
	return(0);

}

//*********************************************************************
//						guildTransfer
//*********************************************************************

int guildTransfer(Player* player, cmd* cmnd) {
	BaseRoom *inRoom = player->getRoom();
	Player	*recipiant;
	unsigned long amt=0;
	char displayStr[50];
	bool	online=false;

	// can they use the bank?
	Guild* guild = guildCanBank(player);
	if(!guild)
		return(0);

	if(inRoom->flagIsSet(R_BANK))
		strcpy(displayStr, "The bank teller says");
	else
		strcpy(displayStr, "The magic money machine tells you");


	if(player->getGuildRank() < GUILD_BANKER) {
		player->print("You are not authorized to transfer guild funds.\n");
		return(0);
	}

	if(cmnd->num < 2) {
		player->print("%s, \"Well! How much do you want to transfer!\"\n", displayStr);
		return(0);
	}
	if(cmnd->str[2][0] != '$') {
		player->print("%s, \"Well! How much do you want to transfer!\"\n",displayStr);
		return(0);
	}
	if(cmnd->num < 4) {
		player->print("%s, \"And just who is this money going to?\"\n",displayStr);
		return(0);
	}

	amt = atol(&cmnd->str[2][1]);
	if(amt < 1) {
		player->print("%s, \"You've got to be kidding\".\n",displayStr);
		return(0);
	}
	if(amt < 500 && !player->isDm()) {
		player->print("%s, \"It's not worth it to transfer so few coins!\"\n",displayStr);
		return(0);
	}
	if(amt > guild->bank[GOLD]) {
		player->print("%s, \"You can't transfer money you don't have!\".\n",displayStr);
		return(0);
	}

	player->unhide();

	if(player->flagIsSet(P_MISTED) || player->isInvisible()) {
		player->print("%s, \"I don't deal with people I can't see!\"\n",displayStr);
		return(0);
	}

	// load up the guy if nessesarry
	cmnd->str[3][0] = up(cmnd->str[3][0]);

	recipiant = 0;
	recipiant = gServer->findPlayer(cmnd->str[3]);

	if(!recipiant) {
		if(!loadPlayer(cmnd->str[3], &recipiant)) {
			player->print("%s, \"I don't know who that is!\"\n",displayStr);
			return(0);
		}
	} else
		online = true;

	guild->bank.sub(amt, GOLD);
	player->print("You transfer %ld gold coins from your guild's account to %s's.\n", amt, recipiant->name);
	recipiant->bank.add(amt, GOLD);

	if(player->getClass() == CARETAKER)
		log_immort(true, player, "%s transferred %ld gold to %s. (Balance=%s)(%s)\n",player->name, amt, recipiant->name, guild->bank.str().c_str(), recipiant->bank.str().c_str());

	guildBankLog(player->getGuild(), "TRANSFER to %s by %s: %ld [Balance: %s]\n", recipiant->name, player->name, amt, guild->bank.str().c_str());
	banklog(recipiant->name, "TRANSFER from %s [GUILD ACCOUNT]: %ld [Balance: %s]\n", player->name, amt, recipiant->bank.str().c_str());
	if(online)
		recipiant->print("*** %s just transferred %ld gold to your account. [GUILD TRANSFER]\n",player->name, amt);

	if(recipiant->isPlayer())
		recipiant->save(online);
	if(!online)
		free_crt(recipiant);

	broadcast(player->getSock(), player->getRoom(), "%s transfers some guild gold.", player->name);
	player->print("%s, \"Your guild's balance is now %s.\"\n",displayStr, guild->bank.str().c_str());
	gConfig->saveGuilds();
	return(0);
}

//*********************************************************************
//						guildStatement
//*********************************************************************

int guildStatement(Player* player, cmd* cmnd) {
	char file[80];

	// can they use the bank?
	if(!guildCanBank(player))
		return(0);

	if(player->getGuildRank() < GUILD_PEON) {
		player->print("You don't have authorization to view the guild transaction history.\n");
		return(0);
	}

	if(player->getRoom()->flagIsSet(R_BANK))
		player->print("The bank teller shows you your guild's bank statement:\n");
	else
		player->print("The magic money machine displays your guild's bank statement:\n");

	sprintf(file, "%s/%d.txt", GUILDBANKDIR, player->getGuild());
	strcpy(player->getSock()->tempstr[3], "\0");
	viewFileReverse(player->getSock(), file);
	return(DOPROMPT);
}


//*********************************************************************
//						guildBalance
//*********************************************************************

int guildBalance(Player* player, cmd* cmnd) {
	BaseRoom *inRoom = player->getRoom();


	// can they use the bank?
	Guild* guild = guildCanBank(player);
	if(!guild)
		return(0);


	player->unhide();
	if(guild->bank.isZero()) {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"Your guild hasn't got a single coin in the bank!\"\n");
		else
			player->print("The magic money machine tells you, \"Your guild hasn't got a single coin in the bank.\"\n");
	} else {
		if(inRoom->flagIsSet(R_BANK))
			player->print("The bank teller says, \"The current balance for your guild is: %s.\"\n",
				guild->bank.str().c_str());
		else
			player->print("The magic money machine tells you, \"The current balance for your guild is: %s.\"\n",
				guild->bank.str().c_str());
		player->save(true);
	}
	return(0);
}

//*********************************************************************
//						doGuildSend
//*********************************************************************
// aka guildchat

void doGuildSend(Guild *guild, Player* player, bstring txt) {
	if(!guild) {
		player->print("Invalid guild!\n");
		return;
	}

	broadcastGuild(guild->num, 1, "### %s sent, \"%s\".",
		player->name, escapeColor(txt).c_str());
	txt = escapeColor(txt);
	broadcast(watchingEaves, "^E--- [%s] %s guild sent, \"%s\".",
		guild->name.c_str(), player->name, txt.c_str());
}

int guildSend(Player* player, cmd* cmnd) {
	bstring text = "";

	player->clearFlag(P_AFK);

	if(!player->ableToDoCommand())
		return(0);

	if(player->inJail()) {
		player->print("People in jail do not have that privilage.\n");
		return(0);
	}

	if(!player->getGuild() || player->getGuildRank() < GUILD_PEON) {
		player->print("You do not belong to a guild.\n");
		return(0);
	}

	text = getFullstrText(cmnd->fullstr, 1);
	if(text == "") {
		player->print("Send what?\n");
		return(0);
	}

	if(!player->canSpeak()) {
		player->printColor("^yYou are unable to do that right now.\n");
		return(0);
	}

	doGuildSend(gConfig->getGuild(player->getGuild()), player, text);
	return(0);
}

//*********************************************************************
//						dmApproveGuild
//*********************************************************************

int dmApproveGuild(Player* player, cmd* cmnd) {
	char guildName[41];
	GuildCreation * toApprove;
	int len,i=0,j=0;

	if(cmnd->num < 2) {
		player->print("Approve what guild?\n");
		return(0);
	}

	len = strlen(cmnd->fullstr);

	// Kill the first space
	while(i < len) {
		if(cmnd->fullstr[i] == ' ' && cmnd->fullstr[i+1] != ' ')
			j++;
		if(j==1)
			break;
		i++;
	}

	len = strlen(&cmnd->fullstr[i+1]);
	if(!len) {
		player->print("Approve what guild?\n");
		return(0);
	}

	if(len>40)
		cmnd->fullstr[40] = '\0';

	strcpy(guildName, &cmnd->fullstr[i+1]);
	toApprove = gConfig->findGuildCreation(guildName);
	if(toApprove == NULL) {
		player->print("'%s' is not currently up for creation.\n", guildName);
		return(0);
	}
	if(toApprove->status == GUILD_NEEDS_SUPPORT) {
		player->print("'%s' still needs support.\n", guildName);
		return(0);
	}
	player->print("You approve the guild '%s'.\n", guildName);
	broadcast(isCt, "^y%s just approved the guild %s", player->name, guildName);
	gConfig->creationToGuild(toApprove);
	// saved by above function
	//gConfig->saveGuilds();
	return(0);
}

//*********************************************************************
//						dmRejectGuild
//*********************************************************************

int dmRejectGuild(Player* player, cmd* cmnd) {
	char guildName[41];
	char *reason=0;
	GuildCreation * toReject;
	int len,i=0,j=0, iTmp=0, strLen;

	strLen = strlen(cmnd->fullstr);

	// This kills all leading whitespace
	while(i<strLen && isspace(cmnd->fullstr[i]))
		i++;

	// This kills the command itself
	while(i<strLen && !isspace(cmnd->fullstr[i]))
		i++;

	// This kills all the white space before the guild
	while(i<strLen && isspace(cmnd->fullstr[i]))
		i++;

	len = strlen(&cmnd->fullstr[i]);
	if(!len) {
		player->print("Reject what guild?\n");
		return(0);
	}
	// This finds out how long the guild is
	// Keep going untill we get to the end of the string or a -
	while(i+j < strLen && cmnd->fullstr[i+j] != '\0' && cmnd->fullstr[i+j] != '-')
		j++;
	j = MIN(j, 40);
	memcpy(guildName, &cmnd->fullstr[i], j);
	guildName[j] = '\0';
	// Kill trailling whitespace
	len = strlen(guildName);
	if(!len) {
		player->print("Reject what guild?\n");
		return(0);
	}
	while(isspace(guildName[len-1]))
		len--;
	guildName[len] = '\0';
	player->print("Trying to reject '%s'\n", guildName);
	i = i+j;
	j=0;
	len = strlen(&cmnd->fullstr[i+1]);

	reason = strstr(&cmnd->fullstr[i], "-r ");
	if(reason) { // There is a reason string then
		iTmp = i;
		while(iTmp < strLen && &cmnd->fullstr[iTmp] != reason)
			iTmp++;
		reason += 3;
		while(isspace(*reason))
			reason++;
		// Kill trailing whitespace
		len = strlen(reason);
		while(isspace(reason[len-1]))
			len--;
		reason[len] = '\0';
	}
	if(iTmp) { // We have a reason, everything else stops at the beginging of the -r
		strLen = iTmp;
		cmnd->fullstr[iTmp] = '\0';
	}
	if(reason != 0) {
		player->print("Reason '%s'\n", reason);
	}
	toReject = gConfig->findGuildCreation(guildName);
	if(toReject == NULL) {
		player->print("'%s' is not currently up for creation.\n", guildName);
		return(0);
	}
	player->print("You reject the guild '%s'.\n", guildName);
	broadcast(isCt, "^y%s just rejected the guild %s", player->name, guildName);
	rejectGuild(toReject, reason);
	gConfig->saveGuilds();
	return(0);
}

//*********************************************************************
//						showGuildsNeedingApproval
//*********************************************************************

void showGuildsNeedingApproval(Player* viewer) {
	GuildCreation *gcp;
	int num = 0;
	std::list<GuildCreation*>::iterator it;
	std::ostringstream oStr;

	for(it = gConfig->guildCreations.begin() ; it != gConfig->guildCreations.end() ; it++) {
		gcp = (*it);
		if(gcp->status != GUILD_AWAITING_APPROVAL)
			continue;

		num++;
		if(num == 1) {
			oStr << "\nGuilds needing approval:\n";
			oStr << "--------------------------------------------------------------------------------\n";
		}

		oStr << "^c" << num << ") " << gcp->name << " by " << gcp->leader << ".\n"
			 << "   " << gcp->numSupporters << " Supporter"
			 << (gcp->numSupporters != 1 ? "s" : "") << ":";

		std::map<bstring, bstring>::iterator sIt;
		for(sIt = gcp->supporters.begin() ; sIt != gcp->supporters.end() ; sIt++)
			oStr << " " << (*sIt).first;

		oStr << "\n";
	}

	viewer->printColor("%s", oStr.str().c_str());
}

//*********************************************************************
//						guildMembers
//*********************************************************************

int guildMembers(Player* player, cmd* cmnd) {
	int		i=0, j=0, len=0;

	if(cmnd->num < 3) {
		player->print("What guild were you looking for?\n");
		return(0);
	}

	len = strlen(cmnd->fullstr);

	// Kill the first 2 spaces
	while( i < len) {
		if(cmnd->fullstr[i] == ' ' && cmnd->fullstr[i+1] != ' ')
			j++;
		if(j==2)
			break;
		i++;
	}

	len = strlen(&cmnd->fullstr[i+1]);
	if(!len || len>40) {
		player->print("The guild you were looking for could not be found.\nNote that proper capitalization is required.\n");
		return(0);
	}

	Guild *guild = gConfig->getGuild(&cmnd->fullstr[i+1]);
	if(!guild) {
		player->print("The guild you were looking for could not be found.\nNote that proper capitalization is required.\n");
		return(0);
	}
	//if(!player->getGuild() || player->getGuildRank() < GUILD_BANKER) {
	//	player->print("You are not of a high enough rank in a guild to list its members.\n");
	//	return(0);
	//}

	player->print("Guild:   %s\nMembers: ", guild->name.c_str());

	std::list<bstring>::iterator it;
	bstring toPrint;
	for(it = guild->members.begin() ; it != guild->members.end() ; it++ ) {
		toPrint += (*it);
		toPrint += ", ";
	}
	toPrint[toPrint.length() - 2] = '.';
	player->printColor("^g%s^x\n", toPrint.c_str());
	return(0);
}

//*********************************************************************
//						guildList
//*********************************************************************

int guildList(Player* player, cmd* cmnd) {
	int num = 1;
	GuildCreation * gcp;

	player->printColor("^b    %-25s %-15s  Info\n", "Guild", "Leader");
	player->printColor("^b--------------------------------------------------------------------------------\n");

	std::map<int, Guild*>::iterator it;
	Guild *guild;
	for(it = gConfig->guilds.begin() ; it != gConfig->guilds.end() ; it++) {
		guild = (*it).second;

		player->printColor("%2d> ^c%-25s ^g%-15s ^x%2d Member(s)",
			num++, guild->name.c_str(), guild->leader.c_str(), guild->numMembers);
		if(guild->pkillsIn)
			player->printColor("^r (Pk:%3d%%)", pkillPercent(guild->pkillsWon, guild->pkillsIn));
		else
			player->printColor("^r (Pk: N/A)");
		player->printColor("^y Avg Lvl: %2d\n", guild->averageLevel());
	}
	std::list<GuildCreation*>::iterator gcIt;
	for(gcIt = gConfig->guildCreations.begin() ; gcIt != gConfig->guildCreations.end() ; gcIt++) {
		gcp = (*gcIt);
		if(gcp->status != GUILD_NEEDS_SUPPORT)
			continue;
		num ++;
		if(num == 1) {
			player->print("\nGuilds needing support\n");
			player->print("--------------------------------------------------------------------------------\n");
		}
		player->printColor("^c%d) %s by %s.\n", num, gcp->name.c_str(), gcp->leader.c_str());
		player->print("   %d Supporter%s: ", gcp->numSupporters, gcp->numSupporters != 1 ? "s" : "");

		std::map<bstring, bstring>::iterator sIt;
		for(sIt = gcp->supporters.begin() ; sIt != gcp->supporters.end() ; sIt++) {
			player->print("%s", (*sIt).first.c_str());
		}

		player->print("\n");
	}


	return(0);
}

//*********************************************************************
//						dmListGuilds
//*********************************************************************
// List currently created guilds, and guilds being opted for creation

int dmListGuilds(Player* player, cmd* cmnd) {
	GuildCreation * gcp;
	int		found = 0;

	player->print("Max Guild Id:  %d\n", gConfig->maxGuilds);
	player->print("Next Guild Id: %d\n\n", gConfig->nextGuildId);
	//	gp = firstGuild;

	//	while(gp) {
	std::map<int, Guild*>::iterator it;
	Guild *guild;
	for(it = gConfig->guilds.begin() ; it != gConfig->guilds.end() ; it++) {
		guild = (*it).second;

		player->printColor("^CGuild: ");
		player->printColor("^c%3d %-40s", guild->num, guild->name.c_str());
		player->print("Leader: %s\n", guild->leader.c_str());
		player->print("  NumMembers: %3d ", guild->numMembers);
		player->print(" Avg Level: %3d ", guild->averageLevel());
		player->print(" Total Levels %3d\n", guild->level);
		player->printColor("  Members: ^g");
		std::list<bstring>::iterator mIt;
		bstring toPrint;
		for(mIt = guild->members.begin() ; mIt != guild->members.end() ; mIt++ ) {
			toPrint += (*mIt);
			toPrint += ", ";
		}
		toPrint[toPrint.length() - 2] = '.';
		player->printColor("%s\n", toPrint.c_str());

		player->print("  Pkills: %d/%d (%d%%) ", guild->pkillsWon, guild->pkillsIn, pkillPercent(guild->pkillsWon, guild->pkillsIn));
		player->print(" Points: %d\n", guild->points);
		player->print("  GuildBank:   %s\n", guild->bank.str().c_str());
	}
	player->print("\nGuilds being supported by players for creation:\n");
	std::list<GuildCreation*>::iterator gcIt;
	for(gcIt = gConfig->guildCreations.begin() ; gcIt != gConfig->guildCreations.end() ; gcIt++) {
		gcp = (*gcIt);
		found++;
		player->printColor("%s%d) %s by %s.\n", gcp->status == GUILD_NEEDS_SUPPORT ? "^c" : "^g",
				found, gcp->name.c_str(), gcp->leader.c_str());
		player->print("   %d Supporter%s:", gcp->numSupporters, gcp->numSupporters != 1 ? "s" : "");
		std::map<bstring, bstring>::iterator sIt;
		for(sIt = gcp->supporters.begin() ; sIt != gcp->supporters.end() ; sIt++) {
			player->print(" %s", (*sIt).first.c_str());
		}
		player->print("\n");
	}
	if(found == 0)
		player->printColor("^x  None.\n");
	return(0);
}

//*********************************************************************
//						guild membership functions
//*********************************************************************

bool Guild::addMember(bstring memberName) {
	if(memberName != "") {
		members.push_back(memberName);
		return(true);
	}
	return(false);
}

bool Guild::delMember(bstring memberName) {
	std::list<bstring>::iterator mIt;

	for(mIt = members.begin() ; mIt != members.end() ; mIt++) {
		if(memberName == (*mIt)) {
			members.erase(mIt);
			return(true);
		}
	}
	return(false);
}

bool Guild::isMember(bstring memberName) {
	std::list<bstring>::iterator mIt;

	for(mIt = members.begin() ; mIt != members.end() ; mIt++) {
		if(memberName == (*mIt))
			return(true);
	}
	return(false);
}

void Guild::renameMember(bstring oldName, bstring newName) {
	std::list<bstring>::iterator mIt;

	if(leader == oldName)
		leader = newName;

	for(mIt = members.begin() ; mIt != members.end() ; mIt++) {
		if(oldName == (*mIt)) {
			(*mIt) = newName;
			break;
		}
	}
}


//*********************************************************************
//						addGuildCreation
//*********************************************************************

bool Config::addGuildCreation(GuildCreation* toAdd) {
	guildCreations.push_back(toAdd);
	return(true);
}

//*********************************************************************
//						supporter functions
//*********************************************************************

bool GuildCreation::addSupporter(Player* supporter) {
	if(supporter && supporters.find(supporter->name) == supporters.end()) {
		supporters[supporter->name] = supporter->getSock()->getIp();
		numSupporters++;
		return(true);
	}
	return(false);
}

bool GuildCreation::removeSupporter(bstring supporterName) {
	if(supporters.find(supporterName) != supporters.end()) {
		supporters.erase(supporterName);
		numSupporters--;
		return(true);
	}
	return(false);
}

void GuildCreation::renameSupporter(bstring oldName, bstring newName) {
	if(leader == oldName)
		leader = newName;

	if(supporters.find(oldName) != supporters.end()) {
		supporters[newName] = supporters[oldName];
		supporters.erase(oldName);
	}
}

void Config::guildCreationsRenameSupporter(bstring oldName, bstring newName) {
	std::list<GuildCreation*>::iterator gcIt;
	for(gcIt = guildCreations.begin(); gcIt != guildCreations.end(); gcIt++) {
		(*gcIt)->renameSupporter(oldName, newName);
	}
}



//*********************************************************************
//						findGuildCreation
//*********************************************************************

GuildCreation* Config::findGuildCreation(bstring creationName) {
	std::list<GuildCreation*>::iterator gcIt;
	GuildCreation* gcp;
	for(gcIt = guildCreations.begin(); gcIt != guildCreations.end(); gcIt++) {
		gcp = (*gcIt);
		if(gcp->name == creationName)
			return(gcp);
	}
	return(NULL);
}

//*********************************************************************
//						recalcLevel
//*********************************************************************
// this function is slow, so we don't want this to happen.

void Guild::recalcLevel() {
	std::list<bstring>::iterator mIt;
	Player* member=0;
	bool	online;

	broadcast(isCt, "\n^yError: Guild level for \"%s\" is being recalculated.\n", name.c_str());

	level = 0;
	for(mIt = members.begin() ; mIt != members.end() ; mIt++) {
		online = false;
		member = gServer->findPlayer((*mIt).c_str());
		if(!member) {
			if(!loadPlayer((*mIt).c_str(), &member))
				continue;
		} else
			online = true;

		level += member->getLevel();

		if(!online)
			free_crt(member);
	}

	gConfig->saveGuilds();
}

//*********************************************************************
//						averageLevel
//*********************************************************************

int Guild::averageLevel() {
	int cLevel, cMembers;

	if(!level)
		recalcLevel();

	cLevel = MAX(1, level);
	cMembers = MAX(1, numMembers);

	return(cLevel/cMembers);
}

//*********************************************************************
//						guildExists
//*********************************************************************

bool Config::guildExists(bstring guildName) {
	Guild* guild;
	guild = getGuild(guildName);
	if(guild)
		return(true);

	GuildCreation* gcp;
	gcp = findGuildCreation(guildName);
	if(gcp)
		return(true);

	return(false);
}

//*********************************************************************
//						getGuildName
//*********************************************************************

const char *getGuildName(int guildNum) {
	Guild* guild = gConfig->getGuild(guildNum);
	if(guild)
		return(guild->name.c_str());
	else
		return("Unknown Guild");
}


//*********************************************************************
//						canRemovePlyFromGuild
//*********************************************************************
// True only if the guild will still have 3 or more players in it
// otherwise it must be disbanded

bool canRemovePlyFromGuild(Player* player) {
	Guild* guild  = gConfig->getGuild(player->getGuild());
	if(guild == 0)
		return(false);
	if(guild->numMembers > 3)
		return(true);
	return(false);
}

//*********************************************************************
//						updateGuild
//*********************************************************************
// Updates level statistics based upon the player, and 'what' is happening

void updateGuild(Player* player, int what) {
	if(!player || !player->getGuild() || player->getGuildRank() < GUILD_PEON)
		return;

	Guild *guild = gConfig->getGuild(player->getGuild());
	if(!guild)
		return;
	if(what == GUILD_JOIN) {
		guild->level += player->getLevel();
		guild->numMembers++;
		guild->addMember(player->name);
	} else if(what == GUILD_REMOVE) {
		guild->level -= player->getLevel();
		guild->numMembers--;
		guild->delMember(player->name);

		// the guildmaster is leaving and did not abdicate their position!
		// find someone to take their place
		if(player->getGuildRank() == GUILD_MASTER) {
			Player* leader=0;
			bool online=false;

			do {
				guild->leader = guild->members.front();

				leader = gServer->findPlayer(guild->leader.c_str());
				if(leader)
					online = true;
				else {
					online = false;
					if(!loadPlayer(guild->leader.c_str(), &leader))
						leader = 0;
				}

				if(leader) {
					leader->setGuildRank(GUILD_MASTER);
					leader->save(online);

					Property* p = gConfig->getProperty(player, PROP_GUILDHALL);
					if(p) {
						p->setOwner(guild->leader);
						gConfig->saveProperties();
					}

					if(!online)
						free_crt(leader);
					break;
				}

				// If we couldn't load a member, we've got data integrity problems
				guild->level = 0;
				guild->leader = "";
				guild->numMembers--;
				guild->members.pop_front();
			} while(guild->members.size());
		}
	} else if(what == GUILD_LEVEL) {
		guild->level++;
	} else if(what == GUILD_DIE) {
		guild->level--;
	}
	gConfig->saveGuilds();
}

//*********************************************************************
//						creationToGuild
//*********************************************************************

void Config::creationToGuild(GuildCreation* toApprove) {
	std::map<bstring, bstring>::iterator sIt;
	Player *leader=0, *officer=0;
	int		guildId=0;
	bool	online=false;

	// The suicide/*dust commands will take care of leaders / supporters
	// suiciding. These are extra checks in case anyone somehow sneaks past.

	// If the leader doesn't exist, we delete the guild.
	leader = gServer->findPlayer(toApprove->leader.c_str());
	if(!leader) {
		if(!loadPlayer(toApprove->leader.c_str(), &leader)) {
			broadcast(isCt, "^yError creating guild '%s': Can't find the leader %s.\nThis guild is being erased.",
				toApprove->name.c_str(), toApprove->leader.c_str());
			removeGuildCreation(toApprove->leader);
			return;
		}
	} else
		online = true;


	// If they suicide and remake a character with the same name, don't
	// let a level 1 character become the leader of the guild.
	if(!leader->flagIsSet(P_CREATING_GUILD)) {
		broadcast(isCt, "^yError creating guild '%s': %s is not flagged as creating a guild.\nThis guild is being erased.^",
			toApprove->name.c_str(), toApprove->leader.c_str());
		removeGuildCreation(leader->name);
		if(!online)
			free_crt(leader);
		return;
	}


	// If we can't load the supporters
	for(sIt = toApprove->supporters.begin() ; sIt != toApprove->supporters.end() ; sIt++) {
		if(!gServer->findPlayer((*sIt).first.c_str())) {
			if(!loadPlayer((*sIt).first.c_str(), &officer)) {
				broadcast(isCt, "^yError loading guild supporter %s in guild %s.\nRemoving this person from the support list.", (*sIt).first.c_str(), toApprove->name.c_str());
				toApprove->removeSupporter((*sIt).first);
				return;
			}
			free_crt(officer);
		}
	}


	// Everything has checked out - create the guild.
	guildId = nextGuildId;
	nextGuildId++;
	numGuilds++;
	Guild* guild = new Guild;

	guild->name = toApprove->name;
	guild->leader = toApprove->leader;
	guild->num = guildId;
	guild->level = 0;
	guild->numMembers = 0;
	guild->pkillsWon = guild->pkillsIn = guild->points = 0;

	// Set the leader
	leader->setGuild(guildId);
	leader->setGuildRank(GUILD_MASTER);
	leader->clearFlag(P_CREATING_GUILD);
	leader->save(online);

	guild->numMembers++;
	guild->level += leader->getLevel();
	guild->addMember(leader->name);

	addGuild(guild);

	if(online)
		leader->print("You are now the leader of %s.\n", guild->name.c_str());

	for(sIt = toApprove->supporters.begin() ; sIt != toApprove->supporters.end() ; sIt++) {
		bool offOnline = false;
		officer = gServer->findPlayer((*sIt).first.c_str());
		if(!officer) {
			if(!loadPlayer((*sIt).first.c_str(), &officer)) {
				broadcast(isCt, "^yError making %s an officer in %s.", (*sIt).first.c_str(), guild->name.c_str());
				continue;
			}
		} else
			offOnline = true;
		officer->setGuild(guildId);
		officer->setGuildRank(GUILD_OFFICER);
		officer->clearFlag(P_CREATING_GUILD);
		officer->save(offOnline);

		guild->numMembers++;
		guild->level += officer->getLevel();
		guild->addMember(officer->name);
		if(!offOnline)
			free_crt(officer);
		else
			officer->print("You are now an officer of %s.\n", guild->name.c_str());
	}

	removeGuildCreation(leader->name);
	if(!online)
		free_crt(leader);
}


//*********************************************************************
//						rejectGuild
//*********************************************************************

void rejectGuild(GuildCreation * toReject, char *reason) {
	Player	*leader=0, *officer=0;
	bstring leaderName = "";
	int		error = 0, ff;
	char	Reason[250], file[80], outStr[1024], datestr[40];
	long	t;
	bool	online=false;


	if(reason == 0)
		strcpy(Reason, "No reason given.\n");
	else
		strcpy(Reason, reason);

	leader = gServer->findPlayer(toReject->leader.c_str());
	if(!leader) {
		if(!loadPlayer(toReject->leader.c_str(), &leader)) {
			broadcast(isCt, "^yError rejecting guild '%s': Can't find the leader %s.", toReject->name.c_str(), toReject->leader.c_str());
			error = 1;
		}
	} else
		online = true;

	if(error == 0) {
		leaderName = leader->name;
		leader->clearFlag(P_CREATING_GUILD);
		leader->save(online);

		if(!online) {
			// Send them a mudmail
			sprintf(file, "%s/%s.txt", POSTPATH, leader->name);
			ff = open(file, O_CREAT | O_APPEND | O_RDWR, ACC);
			if(ff > 0) {
				time(&t);
				strcpy(datestr, (char *) ctime(&t));
				datestr[strlen(datestr) - 1] = 0;
				sprintf(outStr, "\n--..__..--..__..--..__..--..__..--..__..--..__..--..__..--..__..--..__..--\n\nMail from System (%s):\n\nYour guild '%s' has been rejected.\nReason: %s\n", datestr, toReject->name.c_str(), Reason);
				write(ff, outStr, strlen(outStr));
				close(ff);
				leader->setFlag(P_UNREAD_MAIL);
			}
			free_crt(leader);
		} else
			leader->print("Your guild %s has been rejected.\nReason: %s\n", toReject->name.c_str(), Reason);

	} else
		error = 0;

	std::map<bstring, bstring>::iterator sIt;
	for(sIt = toReject->supporters.begin() ; sIt != toReject->supporters.end() ; sIt++) {
		online = false;
		officer = gServer->findPlayer((*sIt).first.c_str());
		if(!officer) {
			if(!loadPlayer((*sIt).first.c_str(), &officer))
				continue;
		} else
			online = true;
		officer->clearFlag(P_CREATING_GUILD);
		officer->save(online);
		if(!online)
			free_crt(officer);
	}

	gConfig->removeGuildCreation(leaderName);
}


//*********************************************************************
//						removeGuildCreation
//*********************************************************************

bstring Config::removeGuildCreation(bstring leaderName) {
	std::list<GuildCreation*>::iterator it;
	GuildCreation *gc;
	bstring toReturn = "";
	for(it = gConfig->guildCreations.begin() ; it != gConfig->guildCreations.end() ; it++) {
		gc = (*it);
		if(gc && gc->leader == leaderName) {
			// We found the one we want to erase
			guildCreations.erase(it);
			toReturn = gc->name;
			delete gc;
			saveGuilds();
			return(toReturn);
		}
	}
	return("");
}

//*********************************************************************
//						getGuild
//*********************************************************************

Guild* Config::getGuild(bstring guildName) {
	Guild* guild=0;
	std::map<int, Guild*>::iterator it;
	for(it = guilds.begin(); it != guilds.end(); it++) {
		guild = (*it).second;
		if(guild->name == guildName)
			return(guild);
	}
	return (NULL);
}

Guild* Config::getGuild(int guildId) {
	if(guilds.find(guildId) != guilds.end())
		return(guilds[guildId]);
	return(0);
}

//*********************************************************************
//						deleteGuild
//*********************************************************************

bool Config::deleteGuild(int guildId) {
	Guild* guild=0;

	if(guilds.find(guildId) != guilds.end()) {
		guild = guilds[guildId];
		guilds.erase(guildId);

		Player *player = gServer->findPlayer(guild->leader.c_str());
		bool online = true;
		if(!player) {
			online = false;
			if(!loadPlayer(guild->leader.c_str(), &player))
				player = 0;
		}

		if(player) {
			Property* p = gConfig->getProperty(player, PROP_GUILDHALL);
			if(p) {
				p->destroy();
				gConfig->saveProperties();
			}
			if(!online)
				free_crt(player);
		}

		delete guild;
		saveGuilds();
		return(true);
	}
	return(false);
}

//*********************************************************************
//						addGuild
//*********************************************************************

bool Config::addGuild(Guild* toAdd) {
	if(!toAdd || !toAdd->num)
		return(false);
	guilds[toAdd->num] = toAdd;
	return(true);
}


// Clears the global list of guilds
void Config::clearGuildList() {
	std::map<int, Guild*>::iterator it;
	Guild* guild;

	for(it = guilds.begin(); it != guilds.end(); it++) {
		guild = (*it).second;
		delete guild;
		//guilds.erase(it);
	}
	guilds.clear();

	std::list<GuildCreation*>::iterator gcIt;
	GuildCreation* gcp;
	while(!guildCreations.empty()) {
		gcp = guildCreations.front();
		delete gcp;
		guildCreations.pop_front();
	}
	guildCreations.clear();
}