/*
* $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);
}