btmux/autom4te.cache/
btmux/doc/.svn/
btmux/event/.svn/
btmux/game/.svn/
btmux/game/bin/.svn/
btmux/game/data/.svn/
btmux/game/logs/.svn/
btmux/game/maps/
btmux/game/maps/.svn/
btmux/game/maps/.svn/prop-base/
btmux/game/maps/.svn/props/
btmux/game/maps/.svn/text-base/
btmux/game/maps/.svn/wcprops/
btmux/game/mechs/
btmux/game/mechs/.svn/
btmux/game/mechs/.svn/prop-base/
btmux/game/mechs/.svn/props/
btmux/game/mechs/.svn/text-base/
btmux/game/mechs/.svn/wcprops/
btmux/game/text/.svn/
btmux/include/.svn/
btmux/misc/
btmux/misc/.svn/
btmux/misc/.svn/prop-base/
btmux/misc/.svn/props/
btmux/misc/.svn/text-base/
btmux/misc/.svn/wcprops/
btmux/python/
btmux/python/.svn/
btmux/python/.svn/prop-base/
btmux/python/.svn/props/
btmux/python/.svn/text-base/
btmux/python/.svn/wcprops/
btmux/src/.svn/prop-base/
btmux/src/.svn/props/
btmux/src/.svn/text-base/
btmux/src/.svn/wcprops/
btmux/src/hcode/.svn/
btmux/src/hcode/btech/
btmux/src/hcode/btech/.svn/
btmux/src/hcode/btech/.svn/prop-base/
btmux/src/hcode/btech/.svn/props/
btmux/src/hcode/btech/.svn/text-base/
btmux/src/hcode/btech/.svn/wcprops/
btmux/src/hcode/include/.svn/
/*
 * $Id: mech.c3.c,v 1.1.1.1 2005/01/11 21:18:11 kstevens Exp $
 *
 * Author: Cord Awtry <kipsta@mediaone.net>
 *
 *  Copyright (c) 2001 Cord Awtry
 *       All rights reserved
 */

#include "mech.h"
#include "mech.events.h"
#include "p.mech.c3.h"
#include "p.mech.c3.misc.h"
#include "p.mech.utils.h"
#include "p.mech.los.h"
#include "p.mech.contacts.h"

#define C3_POS_IN_NETWORK -1
#define C3_POS_NO_ROOM		-2

#define C3_MASTER_MECH_SIZE 5
#define C3_MASTER_OTHER_SIZE 1

int getC3MasterSize(MECH * mech)
{
    if (MechType(mech) == CLASS_MECH)
	return C3_MASTER_MECH_SIZE;
    else
	return C3_MASTER_OTHER_SIZE;
}

int isPartOfWorkingC3Master(MECH * mech, int section, int slot)
{
    int x = 0;
    int y, t;
    int wcWorkingSlots = 0;
    int wStartCheck = 0;
    int tDoBump;

    wStartCheck = MAX(0, slot - (getC3MasterSize(mech) - 1));

    while (x < CritsInLoc(mech, section)) {
	tDoBump = 0;

	if ((t = GetPartType(mech, section, x))) {
	    if (Special2I(t) == C3_MASTER) {
		if (x < wStartCheck) {
		    tDoBump = 1;
		} else {
		    /* We're within range of our slot, if not already on it */
		    for (y = x; y < (x + getC3MasterSize(mech)); y++) {
			if (y != slot) {
			    if (!PartIsNonfunctional(mech, section, y))
				wcWorkingSlots++;
			}
		    }
		}
	    }
	}

	if (tDoBump)
	    x += getC3MasterSize(mech);
	else
	    x++;
    }

    return (wcWorkingSlots == (getC3MasterSize(mech) - 1));
}

int countWorkingC3MastersOnMech(MECH * mech)
{
    int x, y, t;
    int wcSlots;
    int wcWorkingSlots;
    int wcMasters = 0;

    debugC3(tprintf("Counting working C3 masters for %d", mech->mynum));

    for (x = 0; x < NUM_SECTIONS; x++) {
	wcSlots = 0;
	wcWorkingSlots = 0;

	for (y = 0; y < CritsInLoc(mech, x); y++) {
	    if ((t = GetPartType(mech, x, y))) {
		if (Special2I(t) == C3_MASTER) {
		    debugC3(tprintf
			("...found a C3Master slot at section %d, slot %d on %d.",
			    x, y, mech->mynum));

		    wcSlots++;

		    if (!PartIsNonfunctional(mech, x, y)) {
			debugC3("......and the slot is functional.");
			wcWorkingSlots++;
		    }
		}
	    }

	    if (wcSlots == getC3MasterSize(mech)) {
		debugC3(tprintf
		    ("...found enough slots for a C3Master for %d.",
			mech->mynum));
		wcSlots = 0;

		if (wcWorkingSlots == getC3MasterSize(mech)) {
		    debugC3(tprintf
			("...there is even enough working slots to make the computer work on %d.",
			    mech->mynum));
		    wcMasters++;
		}
	    }
	}
    }

    debugC3(tprintf("Found %d working C3 masters on %d", wcMasters,
	    mech->mynum));

    return wcMasters;
}

int countTotalC3MastersOnMech(MECH * mech)
{
    int x, y, t;
    int wcSlots;
    int wcMasters = 0;

    debugC3(tprintf("Counting total C3 masters for %d", mech->mynum));

    for (x = 0; x < NUM_SECTIONS; x++) {
	wcSlots = 0;

	for (y = 0; y < CritsInLoc(mech, x); y++) {
	    if ((t = GetPartType(mech, x, y))) {
		if (Special2I(t) == C3_MASTER) {
		    debugC3(tprintf
			("...found a C3Master slot at section %d, slot %d on %d.",
			    x, y, mech->mynum));

		    wcSlots++;
		}
	    }

	    if (wcSlots == getC3MasterSize(mech)) {
		debugC3(tprintf
		    ("...found enough slots for a C3Master for %d.",
			mech->mynum));

		wcSlots = 0;
		wcMasters++;
	    }
	}
    }

    debugC3(tprintf("Found %d total C3 masters on %d", wcMasters,
	    mech->mynum));

    return wcMasters;
}

int countMaxC3Units(MECH * mech, dbref * myTempNetwork,
    int tempNetworkSize, MECH * targMech)
{
    dbref otherRef;
    MECH *otherMech;
    int i;
    int wcC3Masters = 0;
    int myMasters = 0;
    int maxC3Size;

    debugC3(tprintf("Counting max C3 units in %d's network", mech->mynum));

    if (targMech)
	debugC3(tprintf("...using %d as an additional mech",
		targMech->mynum));

    /* First we iterate over the list and find all the masters */
    for (i = 0; i < tempNetworkSize; i++) {
	otherRef = myTempNetwork[i];
	otherMech = getMech(otherRef);

	if (!otherMech)
	    continue;

	wcC3Masters += MechWorkingC3Masters(otherMech);

	debugC3(tprintf("...for %d, we add %d masters", otherMech->mynum,
		MechWorkingC3Masters(otherMech)));
    }

    /* Let's find out the max number of mechs in this network. Make sure we add in any slaves we can control */
    maxC3Size = (wcC3Masters * 4) - wcC3Masters;

    debugC3(tprintf("...we now have a max size of %d", maxC3Size));

    myMasters = MechWorkingC3Masters(mech);

    if (myMasters > 0)
	maxC3Size += (myMasters * 4) - myMasters;

    debugC3(tprintf
	("...and after adding in my masters, we now have a max size of %d",
	    maxC3Size));

    /* Let's see if a 2nd mech has been supplied to us */
    if (targMech) {
	myMasters = MechWorkingC3Masters(targMech);

	if (myMasters > 0)
	    maxC3Size += (myMasters * 4) - myMasters;
    }

    maxC3Size = MIN(maxC3Size, 11);

    debugC3(tprintf("...final max size of %d", maxC3Size));

    return maxC3Size;
}

int trimC3Network(MECH * mech, dbref * myTempNetwork, int tempNetworkSize)
{
    dbref otherRef;
    MECH *otherMech;
    int i;
    int newNetworkSize;
    int maxC3Size = 0;		/* This is calc'd based on the number of masters */
    dbref newNetwork[C3_NETWORK_SIZE];

    debugC3(tprintf("C3 TRIM: Trimming %d's C3 network", mech->mynum));

    /* Initialize our data */
    newNetworkSize = tempNetworkSize;

    for (i = 0; i < C3_NETWORK_SIZE; i++)
	newNetwork[i] = -1;

    /* Get our count of max units */
    maxC3Size =
	countMaxC3Units(mech, myTempNetwork, tempNetworkSize, NULL);

    debugC3(tprintf("C3 TRIM: Max C3 size: %d", maxC3Size));
    debugC3(tprintf("C3 TRIM: Current C3 size: %d", tempNetworkSize));

    /* Now we see if our network is oversized */
    if (maxC3Size < tempNetworkSize) {
	newNetworkSize = 0;

	/* First put our masters in */
	for (i = 0; i < tempNetworkSize; i++) {
	    otherRef = myTempNetwork[i];
	    otherMech = getMech(otherRef);

	    if (!otherMech)
		continue;

	    if (MechWorkingC3Masters(otherMech) > 0)
		newNetwork[newNetworkSize++] = otherRef;
	}

	/* Next we put in slaves up to the max amount */
	if (newNetworkSize < maxC3Size) {
	    for (i = 0; i < tempNetworkSize; i++) {
		otherRef = myTempNetwork[i];
		otherMech = getMech(otherRef);

		if (!otherMech)
		    continue;

		if (MechWorkingC3Masters(otherMech) == 0)
		    newNetwork[newNetworkSize++] = otherRef;

		if (newNetworkSize >= maxC3Size)
		    break;
	    }
	}

	/* Now, refill our other temp network */
	for (i = 0; i < newNetworkSize; i++)
	    myTempNetwork[i] = newNetwork[i];
    }

    return newNetworkSize;
}

int getFreeC3NetworkPos(MECH * mech, MECH * mechToAdd)
{
    int i;
    dbref otherRef;

    validateC3Network(mech);

    for (i = 0; i < C3_NETWORK_SIZE; i++) {
	otherRef = MechC3NetworkElem(mech, i);

	if (otherRef > 0) {
	    if (otherRef == mechToAdd->mynum)
		return C3_POS_IN_NETWORK;
	} else
	    return i;
    }

    return C3_POS_NO_ROOM;
}

void replicateC3Network(MECH * mechSrc, MECH * mechDest)
{
    int i;
    dbref otherRef;

    debugC3(tprintf("C3 REPLICATE: %d's C3 network to %d",
	    mechSrc->mynum, mechDest->mynum));

    clearC3Network(mechDest, 0);

    MechC3NetworkElem(mechDest, 0) = mechSrc->mynum;
    MechC3NetworkSize(mechDest) = 1;

    for (i = 0; i < C3_NETWORK_SIZE; i++) {
	otherRef = MechC3NetworkElem(mechSrc, i);

	if (otherRef != mechDest->mynum) {
	    MechC3NetworkElem(mechDest, MechC3NetworkSize(mechDest)) =
		otherRef;
	    MechC3NetworkSize(mechDest) += 1;
	}
    }

    validateC3Network(mechDest);
}

void addMechToC3Network(MECH * mech, MECH * mechToAdd)
{
    MECH *otherMech;
    MECH *otherNotifyMech;
    dbref otherRef;
    int i;
    int wPos = -1;

    debugC3(tprintf("C3 ADD: %d to the C3 network of %d",
	    mechToAdd->mynum, mech->mynum));

    /* Find a position to add the new mech into my network */
    wPos = getFreeC3NetworkPos(mech, mechToAdd);

    /* If we have a number that's less than 0, then we have an invalid position. Either we're already in the network or there's not enough room */
    if (wPos < 0)
	return;

    /* Well, we have a valid position, so let's put this mech in the network */
    debugC3(tprintf("C3 ADD: Position to add to %d's network is %d",
	    mech->mynum, wPos));

    MechC3NetworkElem(mech, wPos) = mechToAdd->mynum;
    MechC3NetworkSize(mech) += 1;

    mech_notify(mech, MECHALL,
	tprintf("%s connects to your C3 network.",
	    GetMechToMechID(mech, mechToAdd)));

    /* Now let's replicate the new network across the system so that everyone has the same network settings */
    for (i = 0; i < C3_NETWORK_SIZE; i++) {
	otherRef = MechC3NetworkElem(mech, i);

	otherMech = getOtherMechInNetwork(mech, i, 0, 0, 0, 1);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	if (otherRef != mechToAdd->mynum) {
	    otherNotifyMech = getOtherMechInNetwork(mech, i, 1, 1, 1, 1);

	    if (otherNotifyMech)
		mech_notify(otherNotifyMech, MECHALL,
		    tprintf("%s connects to your C3 network.",
			GetMechToMechID(otherNotifyMech, mechToAdd)));
	}

	replicateC3Network(mech, otherMech);
    }

    /* Last, but not least, one final validation of the network */
    validateC3Network(mech);
}

void clearMechFromC3Network(dbref refToClear, MECH * mech)
{
    int i;

    debugC3(tprintf("C3 CLEAR: %d from the C3 network of %d", refToClear,
	    mech->mynum));

    if (!MechC3NetworkSize(mech))
	return;

    for (i = 0; i < C3_NETWORK_SIZE; i++) {
	if (MechC3NetworkElem(mech, i) == refToClear)
	    MechC3NetworkElem(mech, i) = -1;
    }

    validateC3Network(mech);
}

void clearC3Network(MECH * mech, int tClearFromOthers)
{
    MECH *otherMech;
    int i;

    debugC3(tprintf("C3 CLEAR: %d's C3 network", mech->mynum));

    for (i = 0; i < C3_NETWORK_SIZE; i++) {
	otherMech = getOtherMechInNetwork(mech, i, 0, 0, 0, 1);

	MechC3NetworkElem(mech, i) = -1;

	if (tClearFromOthers) {
	    if (!otherMech)
		continue;

	    if (!Good_obj(otherMech->mynum))
		continue;

	    clearMechFromC3Network(mech->mynum, otherMech);
	}
    }

    MechC3NetworkSize(mech) = 0;
}

void validateC3Network(MECH * mech)
{
    MECH *otherMech;
    dbref myTempNetwork[C3_NETWORK_SIZE];
    int i;
    int networkSize = 0;

    debugC3(tprintf("C3 VALIDATE: %d's C3 network", mech->mynum));

    if (!HasC3(mech) || Destroyed(mech) || C3Destroyed(mech)) {
	clearC3Network(mech, 1);

	return;
    }

    if (MechC3NetworkSize(mech) < 0) {
	clearC3Network(mech, 1);

	return;
    }

    for (i = 0; i < C3_NETWORK_SIZE; i++) {
	otherMech = getOtherMechInNetwork(mech, i, 0, 0, 0, 1);

	if (!otherMech)
	    continue;

	if (!Good_obj(otherMech->mynum))
	    continue;

	debugC3(tprintf("C3 VALIDATE INFO: %d is now in %d's C3 network",
		otherMech->mynum, mech->mynum));

	myTempNetwork[networkSize] = otherMech->mynum;
	networkSize++;
    }

    clearC3Network(mech, 0);

    for (i = 0; i < networkSize; i++)
	MechC3NetworkElem(mech, i) = myTempNetwork[i];

    MechC3NetworkSize(mech) = networkSize;

    debugC3(tprintf
	("C3 VALIDATE INFO: (PreTrim) %d's C3 network is %d elements",
	    mech->mynum, MechC3NetworkSize(mech)));

    networkSize = trimC3Network(mech, myTempNetwork, networkSize);

    debugC3(tprintf
	("C3 VALIDATE INFO: (PostTrim) %d's C3 network has been trimmed to %d elements",
	    mech->mynum, networkSize));

    if (networkSize != MechC3NetworkSize(mech)) {
	clearC3Network(mech, 0);

	for (i = 0; i < networkSize; i++)
	    MechC3NetworkElem(mech, i) = myTempNetwork[i];

	MechC3NetworkSize(mech) = networkSize;
    }


}

void mech_c3_join_leave(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data, *target;
    MAP *objMap;
    char *args[2];
    dbref refTarget;
    int LOS = 1;
    float range = 0.0;
    int maxC3Size = 0;

    cch(MECH_USUALO);

    DOCHECK(mech_parseattributes(buffer, args, 2) != 1,
	"Invalid number of arguments to function!");

    DOCHECK(!HasC3(mech), "This unit is not equipped with C3!");
    DOCHECK(C3Destroyed(mech), "Your C3 system is destroyed!");
    DOCHECK(AnyECMDisturbed(mech),
	"Your C3 system is not currently operational!");

    validateC3Network(mech);

    /* Clear our C3 Network */
    if (!strcmp(args[0], "-")) {
	if (MechC3NetworkSize(mech) <= 0) {
	    mech_notify(mech, MECHALL,
		"You are not connected to a C3 network!");

	    return;
	}

	clearC3Network(mech, 1);

	mech_notify(mech, MECHALL, "You disconnect from the C3 network.");

	return;
    }

    /* Well, if we're here then we wanna connect to a network */
    /* Let's check to see if we're already in one... can't be in two at the same time */
    DOCHECK(MechC3NetworkSize(mech) > 0,
	"You are already in a C3 network!");

    objMap = getMap(mech->mapindex);

    /* Find who we're trying to connect to */
    refTarget = FindTargetDBREFFromMapNumber(mech, args[0]);
    target = getMech(refTarget);

    if (target)
	LOS =
	    InLineOfSight(mech, target, MechX(target), MechY(target),
	    range);
    else
	refTarget = 0;

    DOCHECK((refTarget < 1) ||
	!LOS, "That is not a valid targetID. Try again.");
    DOCHECK(MechTeam(mech) != MechTeam(target),
	"You can't use the C3 network of unfriendly units!");
    DOCHECK(mech->mynum == target->mynum,
	"You can't connect to yourself!");
    DOCHECK(Destroyed(target), "That unit is destroyed!");
    DOCHECK(!Started(target), "That unit is not started!");
    DOCHECK(!HasC3(target),
	"That unit does not appear to be equipped with C3!");

    /* validate the network of our target */
    validateC3Network(target);

    /* Let's see how much can actually fit in this network, based on the number of masters and slaves */
    maxC3Size =
	countMaxC3Units(mech, MechC3Network(target),
	MechC3NetworkSize(target), target);

    DOCHECK(maxC3Size < (MechC3NetworkSize(target) + 1),
	"That unit's C3 network is operating at maximum capacity!");

    /* Connect us up */
    mech_notify(mech, MECHALL, tprintf("You connect to %s's C3 network.",
	    GetMechToMechID(mech, target)));

    addMechToC3Network(target, mech);
}

void mech_c3_message(dbref player, MECH * mech, char *buffer)
{
    cch(MECH_USUALO);

    DOCHECK(!HasC3(mech), "This unit is not equipped with C3!");
    DOCHECK(C3Destroyed(mech), "Your C3 system is destroyed!");
    DOCHECK(AnyECMDisturbed(mech),
	"Your C3 system is not currently operational!");

    validateC3Network(mech);

    DOCHECK(MechC3NetworkSize(mech) <= 0,
	"There are no other units in your C3 network!");

    skipws(buffer);
    DOCHECK(!*buffer, "What do you want to send on the C3 Network?");

    sendNetworkMessage(player, mech, buffer, 1);
}

void mech_c3_targets(dbref player, MECH * mech, char *buffer)
{
    cch(MECH_USUALO);

    DOCHECK(!HasC3(mech), "This unit is not equipped with C3!");
    DOCHECK(C3Destroyed(mech), "Your C3 system is destroyed!");
    DOCHECK(AnyECMDisturbed(mech),
	"Your C3 system is not currently operational!");

    validateC3Network(mech);

    DOCHECK(MechC3NetworkSize(mech) <= 0,
	"There are no other units in your C3 network!");

    showNetworkTargets(player, mech, 1);
}

void mech_c3_network(dbref player, MECH * mech, char *buffer)
{
    cch(MECH_USUALO);

    DOCHECK(!HasC3(mech), "This unit is not equipped with C3!");
    DOCHECK(C3Destroyed(mech), "Your C3 system is destroyed!");
    DOCHECK(AnyECMDisturbed(mech),
	"Your C3 system is not currently operational!");

    validateC3Network(mech);

    DOCHECK(MechC3NetworkSize(mech) <= 0,
	"There are no other units in your C3 network!");

    showNetworkData(player, mech, 1);
}