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.contacts.c,v 1.1.1.1 2005/01/11 21:18:14 kstevens Exp $
 *
 * Author: Markus Stenberg <fingon@iki.fi>
 *
 *  Copyright (c) 1996 Markus Stenberg
 *  Copyright (c) 1998-2002 Thomas Wouters
 *  Copyright (c) 2000-2002 Cord Awtry
 *       All rights reserved
 *
 * Last modified: Tue Oct  6 17:15:16 1998 fingon
 *
 */

#include <stdio.h>
#include <stdlib.h>
#include <math.h>
#include <sys/file.h>

#include "mech.h"
#include "mech.events.h"
#include "map.h"
#include "p.mech.utils.h"
#include "p.mech.los.h"

char *default_contactoptions = "!db";

static char *ac_desc[] = {
    "0 - See enemies and friends, long text, color",
    "1 - See enemies and friends, short text, color",
    "2 - See enemies only, long text, color",
    "3 - See enemies only, short text, color",
    "4 - See enemies and friends, short text, no color",
    "5 - See enemies only, short text, no color",

    "6 - Disabled"
};

static char *c_desc[] = {
    "0 - Very verbose",
    "1 - Short form, the usual one",
    "2 - Short form, the usual one, but do not see buildings",
    "3 - Shorter form"
};

void show_brief_flags(dbref player, MECH * mech)
{
    notify(player, tprintf("Brief status for %s:", GetMechToMechID(mech,
		mech)));
#ifdef ADVANCED_LOS
    notify(player, tprintf("    (A)utocontacts: %s",
	    ac_desc[mech->brief / 4]));
#endif
    notify(player, tprintf("    (C)ontacts:     %s",
	    c_desc[mech->brief % 4]));
}

void mech_brief(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data;
    char c;
    int v;

    cch(MECH_USUALSM);
    skipws(buffer);
    if (!*buffer) {
	show_brief_flags(player, mech);
	return;
    }
    c = *buffer;
    buffer++;
    skipws(buffer);
    DOCHECK(!*buffer, "Argument missing!");
    DOCHECK(Readnum(v, buffer), "Invalid number!");
    switch (toupper(c)) {
#ifdef ADVANCED_LOS
    case 'A':
	DOCHECK(v < 0 || v > 6, "Number out of range!");
	v = BOUNDED(0, v, 6);
	mech->brief = mech->brief % 4;
	mech->brief += v * 4;
	mech_notify(mech, MECHALL,
	    tprintf("Autocontact brevity set to %s.", ac_desc[v]));
	return;
#endif
    case 'C':
	DOCHECK(v < 0 || v > 3, "Number out of range!");
	v = BOUNDED(0, v, 3);
	mech->brief = ((mech->brief / 4) * 4) + v;
	mech_notify(mech, MECHALL, tprintf("Contact brevity set to %s.",
		c_desc[v]));
	return;
    }
}


#define SEE_DEAD	0x01
#define SEE_SHUTDOWN	0x02
#define SEE_ALLY	0x04
#define SEE_ENEMA	0x08
#define SEE_TARGET	0x10
#define SEE_BUILDINGS	0x20
#define SEE_NEGNEXT	0x80

char getWeaponArc(MECH * mech, int arc)
{
    if (arc & FORWARDARC)
    	return '*';
    else if (arc & TURRETARC)
    	return 't';
    else if (arc & RSIDEARC)
    	return 'r';
    else if (arc & LSIDEARC)
    	return 'l';
    else if (arc & REARARC)
    	return 'v';
    else
    	return '?';
}

/* who: 0 for friend, 1 for enemy, 2 for 'self' */
char *getStatusString(MECH * target, int who)
{
    static char statusstr[20];
    int sptr = 0;

    if (Destroyed(target))
	statusstr[sptr++] = 'D';

    if (Starting(target))
	statusstr[sptr++] = 's';
    else if (!Started(target))
	statusstr[sptr++] = 'S';

    if (Standing(target))
	statusstr[sptr++] = 'f';
    else if (Fallen(target))
	statusstr[sptr++] = 'F';

    if (ChangingHulldown(target))
	statusstr[sptr++] = 'h';
    else if (IsHulldown(target))
	statusstr[sptr++] = 'H';

    if (Towed(target))
	statusstr[sptr++] = 'T';
    else if (MechCarrying(target) > 0)
	statusstr[sptr++] = 't';

    if (Jumping(target))
	statusstr[sptr++] = 'J';

    if (OODing(target))
	statusstr[sptr++] = 'O';

    if (MechHeat(target))
	statusstr[sptr++] = '+';

    if (Jellied(target))
	statusstr[sptr++] = 'I';

    if (Burning(target))
	statusstr[sptr++] = 'B';

    if (MechLites(target))
	statusstr[sptr++] = 'L';

    if (MechLit(target))
	statusstr[sptr++] = 'l';

    if (MechSwarmTarget(target) > 0)
	statusstr[sptr++] = 'W';

    if (CarryingClub(target))
	statusstr[sptr++] = 'C';

    if (checkAllSections(target, NARC_ATTACHED) ||
	checkAllSections(target, INARC_HOMING_ATTACHED)) {
	if (who == 1)
	    statusstr[sptr++] = 'N';
	else
	    statusstr[sptr++] = 'n';
    }
    
#ifndef ECM_ON_CONTACTS
    if (who > 1) {
#endif
    if (AnyECCMActive(target))
    	statusstr[sptr++] = 'P';
    	
    if (AnyECMActive(target))
    	statusstr[sptr++] = 'E';
    	
    if (AnyECMProtected(target))
    	statusstr[sptr++] = 'p';
    	
    if (AnyECMDisturbed(target))
    	statusstr[sptr++] = 'e';
#ifndef ECM_ON_CONTACTS
    }
#endif
    
    if (Spinning(target))
    	statusstr[sptr++] = 'X';

#ifdef BT_MOVEMENT_MODES
    if (Sprinting(target))
	statusstr[sptr++] = 'M';
    if (Evading(target))
	statusstr[sptr++] = 'm';
#endif
    
    statusstr[sptr] = '\0';
    return statusstr;
}

char getStatusChar(MECH * mech, MECH * mechTarget, int wCharNum)
{
    char cRet = ' ';

    switch (wCharNum) {
    case 1:
	cRet = MechSwarmTarget(mechTarget) > 0 ? 'W' :
	    Towed(mechTarget) ? 'T' : MechCarrying(mechTarget) >
	    0 ? 't' : CarryingClub(mechTarget) ? 'C' :
#ifdef BT_MOVEMENT_MODES
	    Sprinting(mechTarget) ? 'M' : Evading(mechTarget) ? 'm' :
#endif
	    ' ';
	break;
    case 2:
	cRet = Destroyed(mechTarget) ? 'D' :
	    MechLites(mechTarget) ? 'L' : MechLit(mechTarget) ? 'l' : ' ';
	break;
    case 3:
	cRet = Jumping(mechTarget) ? 'J' : OODing(mechTarget) ? 'O' :
	    Fallen(mechTarget) ? 'F' : Standing(mechTarget) ? 'f' :
	    ChangingHulldown(mechTarget) ? 'h' : IsHulldown(mechTarget) ?
	    'H' : Spinning(mech) ? 'X' : ' ';
	break;
    case 4:
	cRet = Started(mechTarget) ?
	    (MechHeat(mechTarget) ? '+' :
	    Jellied(mechTarget) ? 'I' :
	    Burning(mechTarget) ? 'B' : ' ') :
	    Staggering(mechTarget) ? 'G' :
	    Starting(mechTarget) ? 's' : 'S';
	break;
    case 5:
	cRet = (checkAllSections(mechTarget, NARC_ATTACHED) ||
	    checkAllSections(mechTarget, INARC_HOMING_ATTACHED)) ?
	    (MechTeam(mechTarget) == MechTeam(mech) ? 'n' : 'N') :
#ifdef ECM_ON_CONTACTS
	    AnyECCMActive(mech) ? 'P' : 
	    AnyECMActive(mech) ? 'E' : AnyECMProtected(mech) ? 'p' : 
	    AnyECMDisturbed(mech) ? 'e' :
#endif
	    ' ';
	break;
    }

    return cRet;
}

void mech_contacts(dbref player, void *data, char *buffer)
{
    MECH *mech = (MECH *) data, *tempMech;
    MAP *mech_map = getMap(mech->mapindex), *tmp_map;
    mapobj *building;
    int loop, i, j, argc, bearing, buffindex = 0;
    char *args[1], bufflist[MAX_MECHS_PER_MAP][120], buff[100];
    int sbuff[MAX_MECHS_PER_MAP];
    float range, rangelist[MAX_MECHS_PER_MAP], fx, fy;
    int mechfound;
    char weaponarc;
    char *mech_name;
    char see_what;
    char *str;
    char move_type[30];
    char cStatus1, cStatus2, cStatus3, cStatus4, cStatus5;
    int losflag;
    int isvb;
    int inlos;
    int IsUsingHUD = 0;

    cch(MECH_USUAL);
    mechfound = 0;
    argc = mech_parseattributes(buffer, args, 1);

    isvb = (mech->brief % 4);
    if (argc > 0) {
	if (args[0][0] == 'h') {
	    IsUsingHUD = 1;
	    see_what =
		(SEE_DEAD | SEE_SHUTDOWN | SEE_ENEMA | SEE_ALLY |
		SEE_TARGET);
	} else {
	    if (args[0][0] == '+') {
		str = silly_atr_get(player, A_CONTACTOPT);
		if (!*str)
		    strcpy(buff, default_contactoptions);
		else {
		    strncpy(buff, str, 50);
		    buff[49] = 0;

		    if (strlen(buff) == 0)
			strcpy(buff, default_contactoptions);
		}
	    } else {
		strncpy(buff, args[0], 50);
		buff[49] = 0;
	    }

	    if (isvb == 1)
		see_what = SEE_BUILDINGS;
	    else
		see_what = 0x0;

	    for (loop = 0; loop < 50 && buff[loop]; loop++) {
		char c;

		c = buff[loop];

		if (c == 'd')

		    (see_what & SEE_NEGNEXT) ? (see_what &=
			~SEE_DEAD) : (see_what |= SEE_DEAD);
		else if (c == 's')
		    (see_what & SEE_NEGNEXT) ? (see_what &=
			~SEE_SHUTDOWN) : (see_what |= SEE_SHUTDOWN);
		else if (c == 'b')
		    (see_what & SEE_NEGNEXT) ? (see_what &=
			~SEE_BUILDINGS) : (see_what |= SEE_BUILDINGS);
		else if (c == 'e')
		    (see_what & SEE_NEGNEXT) ? (see_what &=
			~SEE_ENEMA) : (see_what |= SEE_ENEMA);
		else if (c == 'a')
		    (see_what & SEE_NEGNEXT) ? (see_what &=
			~SEE_ALLY) : (see_what |= SEE_ALLY);
		else if (c == 't')
		    (see_what & SEE_NEGNEXT) ? (see_what &=
			~SEE_TARGET) : (see_what |= SEE_TARGET);
		else if (c == '!') {
		    see_what =
			(SEE_NEGNEXT | SEE_DEAD | SEE_SHUTDOWN | SEE_ENEMA
			| SEE_ALLY | SEE_TARGET);
		} else
		    notify(player,
			tprintf("Ignoring %c as contact option.", c));
	    }
	}
    } else {
	see_what =
	    (SEE_DEAD | SEE_SHUTDOWN | SEE_ENEMA | SEE_ALLY | SEE_TARGET);
	if (isvb == 1)
	    see_what |= SEE_BUILDINGS;
    }

    if (IsUsingHUD)
	notify(player, "#HUDINFO:CON#Line of Sight Contacts:");
    else if (isvb <= 2)
	notify(player, "Line of Sight Contacts:");

    for (loop = 0; loop < mech_map->first_free; loop++) {
	if (!(mech_map->mechsOnMap[loop] != mech->mynum &&
		mech_map->mechsOnMap[loop] != -1))
	    continue;

	tempMech = (MECH *) FindObjectsData(mech_map->mechsOnMap[loop]);

	if (!tempMech)
	    continue;
	if (argc) {
	    if (!((MechSeemsFriend(mech, tempMech) ? (see_what & SEE_ALLY)
			: (see_what & SEE_ENEMA)) ||
		    ((see_what & SEE_TARGET) &&
			(tempMech->mynum == MechTarget(mech)))))
		continue;
	    if (!(((see_what & SEE_SHUTDOWN) || Started(tempMech)) ||
		    Destroyed(tempMech) || ((see_what & SEE_TARGET) &&
			(tempMech->mynum == MechTarget(mech)))))
		continue;
	    if (!(((see_what & SEE_DEAD) || !Destroyed(tempMech)) ||
		    ((see_what & SEE_TARGET) &&
			(tempMech->mynum == MechTarget(mech)))))
		continue;
	}
	range = FlMechRange(mech_map, mech, tempMech);
	if (!(losflag =
		InLineOfSight(mech, tempMech, MechX(tempMech),
		    MechY(tempMech), range)))
	    continue;
	if (Good_obj(tempMech->mynum)) {
	    if (!InLineOfSight_NB(mech, tempMech, MechX(tempMech),
		    MechY(tempMech), 0.0)) {
		mech_name = "something";
		inlos = 0;
	    } else {
		mech_name = silly_atr_get(tempMech->mynum, A_MECHNAME);
		inlos = 1;
	    }
	} else
	    continue;
	bearing =
	    FindBearing(MechFX(mech), MechFY(mech), MechFX(tempMech),
	    MechFY(tempMech));
	weaponarc = getWeaponArc(mech, InWeaponArc(mech, MechFX(tempMech),
						   MechFY(tempMech)));

	strcpy(move_type, GetMoveTypeID(MechMove(tempMech)));

	if (isvb) {
	    if (!inlos) {
		cStatus1 = ' ';
		cStatus2 = ' ';
		cStatus3 = ' ';
		cStatus4 = ' ';
		cStatus5 = ' ';
	    } else {
		cStatus1 = getStatusChar(mech, tempMech, 1);
		cStatus2 = getStatusChar(mech, tempMech, 2);
		cStatus3 = getStatusChar(mech, tempMech, 3);
		cStatus4 = getStatusChar(mech, tempMech, 4);
		cStatus5 = getStatusChar(mech, tempMech, 5);
	    }

	    if (!IsUsingHUD) {
#ifdef SIMPLE_SENSORS
		sprintf(buff,
		    "%s%c[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s",
#else
		sprintf(buff,
		    "%s%c%c%c[%s]%c %-12.12s x:%3d y:%3d z:%3d r:%4.1f b:%3d s:%5.1f h:%3d S:%c%c%c%c%c%s",
#endif
		    tempMech->mynum == MechTarget(mech) ? "%ch%cr" :
		    !MechSeemsFriend(mech, tempMech) ? "%ch%cy" : "",
#ifndef SIMPLE_SENSORS
		    (losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
		    (losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
		    weaponarc, MechIDS(tempMech,
			MechSeemsFriend(mech, tempMech)),
		    move_type[0], mech_name, MechX(tempMech),
		    MechY(tempMech), MechZ(tempMech), range, bearing,
		    MechSpeed(tempMech), MechVFacing(tempMech),
		    cStatus1,
		    cStatus2,
		    cStatus3,
		    cStatus4,
		    cStatus5,
		    (tempMech->mynum == MechTarget(mech) ||
			!MechSeemsFriend(mech, tempMech)) ? "%c" : "");
	    } else {
#ifdef SIMPLE_SENSORS
		sprintf(buff, "#HUDINFO:CON#%c,%c,%s,%c,%-12.12s,%3d,%3d,%3d,%4.1f,%3d,%4.1f,%3d,%c%c%c%c%c",	/* ) <- balance */
#else
		sprintf(buff,
		    "#HUDINFO:CON#%c,%c,%c,%c,%s,%c,%-12.12s,%3d,%3d,%3d,%4.1f,%3d,%4.1f,%3d,%c%c%c%c%c",
#endif
		    (tempMech->mynum == MechTarget(mech)) ? 'T' :
		    !MechSeemsFriend(mech, tempMech) ? 'E' : 'F',
#ifndef SIMPLE_SENSORS
		    (losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
		    (losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
		    weaponarc, MechIDS(tempMech,
			MechSeemsFriend(mech, tempMech)),
		    move_type[0], mech_name, MechX(tempMech),
		    MechY(tempMech), MechZ(tempMech), range, bearing,
		    MechSpeed(tempMech), MechVFacing(tempMech),
		    cStatus1, cStatus2, cStatus3, cStatus4, cStatus5);
	    }

	    rangelist[buffindex] = range;
	    rangelist[buffindex] +=
		(MechStatus(tempMech) & DESTROYED) ? 10000 : 0;
	    strcpy(bufflist[buffindex++], buff);
	} else {
	    sprintf(buff, "[%s] %-17s  Tonnage: %d", MechIDS(tempMech,
		    MechSeemsFriend(mech, tempMech)), mech_name,
		MechTons(tempMech));
	    notify(player, buff);
	    sprintf(buff, "      Range: %.1f hex\tBearing: %d degrees",
		range, bearing);
	    notify(player, buff);
	    sprintf(buff, "      Speed: %.1f KPH\tHeading: %d degrees",
		MechSpeed(tempMech), MechVFacing(tempMech));
	    notify(player, buff);
	    sprintf(buff, "      X, Y: %3d, %3d \tHeat: %.0f deg C.",
		MechX(tempMech), MechY(tempMech), MechHeat(tempMech));
	    notify(player, buff);
	    sprintf(buff, "      Movement Type: %s", move_type);
	    notify(player, buff);
	    notify(player, tprintf("      Mech is in %s Arc",
		    GetArcID(mech, InWeaponArc(mech, MechFX(tempMech),
			    MechFY(tempMech)))));
	    if (MechStatus(tempMech) & DESTROYED)
		notify(player, "      Mech Destroyed");
	    if (!(MechStatus(tempMech) & STARTED))
		notify(player, "      Mech Shutdown");
	    if (Fallen(tempMech))
		notify(player, "      Mech has Fallen!");
	    if (Jumping(tempMech))
		notify(player,
		    tprintf("      Mech is Jumping!\tJump Heading: %d",
			MechJumpHeading(tempMech)));
	    notify(player, " ");
	}
    }

    if (see_what & SEE_BUILDINGS) {
	for (building = first_mapobj(mech_map, TYPE_BUILD); building;
	    building = next_mapobj(building)) {

	    MapCoordToRealCoord(building->x, building->y, &fx, &fy);
	    range =
		FindRange(MechFX(mech), MechFY(mech), MechFZ(mech), fx, fy,
		ZSCALE * ((i =
			Elevation(mech_map, building->x,
			    building->y)) + 1));

	    losflag =
		InLineOfSight(mech, NULL, building->x, building->y, range);
	    if (!losflag || (losflag & MECHLOSFLAG_BLOCK))
		continue;

	    if (!(building->obj && (tmp_map = getMap(building->obj))))
		continue;
	    if (BuildIsInvis(tmp_map))
		continue;
	    if ((j = !can_pass_lock(mech->mynum, tmp_map->mynum, A_LENTER))
		&& BuildIsHidden(tmp_map))
		continue;
	    bearing = FindBearing(MechFX(mech), MechFY(mech), fx, fy);
	    weaponarc = getWeaponArc(mech, InWeaponArc(mech, fx, fy));

	    mech_name = silly_atr_get(building->obj, A_MECHNAME);
	    if (!mech_name || !*mech_name)
		mech_name = strip_ansi(Name(building->obj));

	    if (!IsUsingHUD) {
#ifdef SIMPLE_SENSORS
		sprintf(buff,
		    "%s%c %-23.23s x:%3d y:%3d z:%2d r:%4.1f b:%3d CF:%4d /%4d S:%c%c%s",
#else
		sprintf(buff,
		    "%s%c%c%c %-23.23s x:%3d y:%3d z:%2d r:%4.1f b:%3d CF:%4d /%4d S:%c%c%s",
#endif
		    j ? "%ch%cy" : "",
#ifndef SIMPLE_SENSORS
		    (losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
		    (losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
		    weaponarc, mech_name, building->x, building->y, i,
		    range, bearing, tmp_map->cf, tmp_map->cfmax,
		    (BuildIsSafe(tmp_map) || (j &&
			    BuildIsCS(tmp_map))) ? 'X' : j ? 'x' :
		    BuildIsCS(tmp_map) ? 'C' : ' ',
		    BuildIsHidden(tmp_map) ? 'H' : ' ', j ? "%c" : "");
	    } else {
#ifdef SIMPLE_SENSORS
		sprintf(buff, "#HUDINFO:CON#%c,%c,%-21.21s,%3d,%3d,%3d,%4.1f,%3d,%4d,%4d,%c%c",	/* ) <- balance */
#else
		sprintf(buff,
		    "#HUDINFO:CON#%c,%c,%c,%c,%-21.21s,%3d,%3d,%3d,%4.1f,%3d,%4d,%4d,%c%c",
#endif
		    j ? 'E' : 'F',
#ifndef SIMPLE_SENSORS
		    (losflag & MECHLOSFLAG_SEESP) ? 'P' : ' ',
		    (losflag & MECHLOSFLAG_SEESS) ? 'S' : ' ',
#endif
		    weaponarc, mech_name, building->x, building->y, i,
		    range, bearing, tmp_map->cf, tmp_map->cfmax,
		    (BuildIsSafe(tmp_map) || (j &&
			    BuildIsCS(tmp_map))) ? 'X' : j ? 'x' :
		    BuildIsCS(tmp_map) ? 'C' : ' ',
		    BuildIsHidden(tmp_map) ? 'H' : ' ');
	    }
	    rangelist[buffindex] = range + 20000;
	    strcpy(bufflist[buffindex++], buff);
	}
    }


    if (isvb) {
	for (i = 0; i < buffindex; i++)
	    sbuff[i] = i;
	/* print a sorted list of detected mechs */
	/* use the ever-popular bubble sort */
	for (i = 0; i < (buffindex - 1); i++)
	    for (j = (i + 1); j < buffindex; j++)
		if (rangelist[sbuff[j]] > rangelist[sbuff[i]]) {
		    loop = sbuff[i];
		    sbuff[i] = sbuff[j];
		    sbuff[j] = loop;
		}
	for (loop = 0; loop < buffindex; loop++)
	    notify(player, bufflist[sbuff[loop]]);
    }

    if (IsUsingHUD)
	notify(player, "#HUDINFO:CON#End Contact List");
    else if (isvb <= 2)
	notify(player, "End Contact List");
}

#undef SEE_DEAD
#undef SEE_SHUTDOWN
#undef SEE_ALLY
#undef SEE_ENEMA
#undef SEE_TARGET
#undef SEE_BUILDINGS
#undef SEE_NEGNEXT