/* Header: them.c,v 7.0.1.5 86/12/12 17:05:41 lwall Exp */

/* Log:	them.c,v
 * Revision 7.0.1.5  86/12/12  17:05:41  lwall
 * Baseline for net release.
 *
 * Revision 7.0.1.4  86/10/20  12:32:38  lwall
 * Wasn't clearing FRIENDLY flag on pirate creation.
 *
 * Revision 7.0.1.3  86/10/20  12:15:33  lwall
 * Was trying to create pirates from cloaked pirates.
 *
 * Revision 7.0.1.2  86/10/17  10:03:44  lwall
 * Fixed Romulan writing spaces while cloaked.
 *
 * Revision 7.0.1.1  86/10/16  10:53:39  lwall
 * Added Damage.  Fixed random bugs.
 *
 * Revision 7.0  86/10/08  15:14:15  lwall
 * Split into separate files.  Added amoebas and pirates.
 *
 */

#include "EXTERN.h"
#include "warp.h"
#include "bang.h"
#include "object.h"
#include "move.h"
#include "score.h"
#include "term.h"
#include "us.h"
#include "util.h"
#include "weapon.h"
#include "INTERN.h"
#include "them.h"

void
them_init(void)
{
    ;
}

void
their_smarts(void)
{
    OBJECT *curkl;
    OBJECT *obj = NULL;
    int prob;
    int count;
    int y = 0;
    int x = 0;

    if (numcrushes && (obj=movers)->type == Crusher) {
	if (numamoebas) {
	    y = obj->posy;
	    x = (obj->posx+(obj->image=='<'?1:-1)+XSIZE00)%XSIZE;
	    if (amb[y][x] == '~') {
		obj->velx = 0;		/* stop and munch amoeba */
		modify_amoeba(y,x,1,' ',(int)rand_mod(5+ambsize/10)+1);
		if (occupant[y][x] == nuke)	/* except go for nucleus */
		    obj->velx = (obj->image=='<' ? 1 : -1);
	    }
	    else if (!obj->velx) {
		if (!rand_mod(4))
		    obj->image = rand_mod(2) ? '<' : '>';
		obj->velx = obj->image == '<' ? 1 : -1;
	    }
	}
	obj->vely += (rand_mod(222) - 111) / 100;
	if (!(rand_mod(100))) {
	    setimage(obj, (obj->velx *= -1) < 0 ? '>' : '<');
	}
    }
    if (numamoebas) {
	if (!rand_mod(3))
	    nuke->velx = nuke->vely = 0;
	if (nuke->strategy && ambsize < 90 && !rand_mod(200-smarts))
	    modify_amoeba(0,0,0,'~',(int)rand_mod(10));
	if (ambsize > 200 || (ambsize > 100 && !rand_mod(15)))
	    modify_amoeba(yamblast,xamblast,2,' ',(ambsize-100)/5);
    }
    for (curkl = enemies; curkl->type == Enemy; curkl = curkl->next) {
	if ((curkl->flags & (CLOAKS|FRIENDLY)) == CLOAKS &&
	    (curkl->image != ' ') &&
	    (curkl->energy > 300 || massacre) ) {
	    setimage(curkl, ' ');
	}
	if (madgorns)
	    prob = 3;
	else if (curkl->vely || curkl->velx)
	    prob = massacre?10:20;
	else if ((curkl->flags & (PIRATE|FRIENDLY)) == PIRATE) {
				/* pirates want to sit sometimes */
	    if (curkl->strategy) {
		if ((obj = lookimg(curkl->posy, curkl->posx, '@')) ||
		    (obj = lookimg(curkl->posy, curkl->posx, 'B')) ) {
		    make_plink(obj->posy, obj->posx);
		    if (!--curkl->strategy) {	/* clock ran down */
			if (obj->image == '@') {
			    obj->image = '*';
			    numinhab--;
			    if (obj->flags & STATIC)
				mvaddch(obj->posy+1,obj->posx*2,obj->image);
			    if (curkl->energy < 20000)
				curkl->energy += 5000;
			}
			prob = 2;	/* our work here is done */
		    }
		    else if (obj->image == 'B') {
			btorp -= rand_mod(50);
			if (btorp < 0)
			    btorp = 0;
			obj->energy -= rand_mod(500);
			if (obj->energy < 0)
			    obj->energy = 0;
			prob = 10000;		/* stay here */
		    }
		    else
			prob = 10000;
		}
		else {		/* it went away--go elsewhere */
		    prob = 4;
		    curkl->strategy = 0;
		}
	    }
	    else if (lookimg(curkl->posy, curkl->posx, '@') ||
		     lookimg(curkl->posy, curkl->posx, 'B')) {
		curkl->strategy = rand_mod(15)+5;
		prob = 10000;
	    }
	    else
		prob = 4;
	}
	else if (curkl->image == 'M') {	/* Mudd wants to sit sometimes */
	    if ((obj = lookimg(curkl->posy, curkl->posx, 'E')) ||
		(obj = lookimg(curkl->posy, curkl->posx, 'B')) ) {
		if (obj->image == 'B') {
		    btorp -= rand_mod(40);
		    if (btorp < 0)
			btorp = 0;
		    obj->energy -= rand_mod(100);
		    if (obj->energy < 0)
			obj->energy = 0;
		}
		else if (!obj->vely && !obj->velx) {
		    etorp -= rand_mod(10);
		    if (etorp < 0)
			etorp = 0;
		    obj->energy -= rand_mod(20);
		    if (obj->energy < 0)
			obj->energy = 0;
		}
		prob = 10000;		/* stay here */
	    }
	    else		/* it went away--go elsewhere */
		prob = 4;
	}
	else if (curkl->flags & FRIENDLY) {
	    if (curkl->energy < 10000 &&
	      lookimg(curkl->posy, curkl->posx, '@') ) {
		curkl->energy += 100;
		prob = 20;	/* do some loading */
	    }
	    else
		prob = 4;
	}
	else if (curkl->image == '&') {
	    if (curkl->flags & COUNTDOWN) {
		if (curkl->strategy)
		    curkl->strategy--;
		else
		    curkl->flags &= ~COUNTDOWN;
		prob = 100;	/* someone's feeding us, so sit still */
	    }
	    else
		prob = 4;
	}
	else
	    prob = 4;			/* don't sit still too long */
	count = 11;
	for (;;) {
	    if (--count <= 0)		/* no opening, just ram something */
		break;

#ifdef lint
	    prob = prob;
#endif
	    if (!(rand_mod(prob)))	/* turn randomly occasionally */
		goto accell;

	    y=(curkl->posy+curkl->vely+YSIZE00)%YSIZE;	/* find prospective */
	    x=(curkl->posx+curkl->velx+XSIZE00)%XSIZE;	/*   new position */

	    if (numamoebas) {
		if (curkl == nuke) {
		    if (amb[y][x] != '~')
			goto accell;	/* never move nucleus from protoplasm */
		}
		else {
		    if (amb[y][x] == '~' && rand_mod(2)) {
			yamblast = y;
			xamblast = x;
			goto accell;
		    }
		}
	    }

	    obj = occupant[y][x];
	    if (!obj) break;		/* is anyone there? */

	    switch (obj->type) {
	    case Star:
		if (obj->image == '@' && (curkl->flags & PIRATE)) {
		    if (curkl->image != 'P' && curkl->image != ' ') {
			if (curkl->flags & FRIENDLY) {
			    curkl->flags &= ~FRIENDLY;
			    curkl->energy += 1000;
			    possiblescore += curkl->mass;
			    inumfriends--;
			    numfriends--;
			    inumenemies++;
			    numenemies++;
			}
			curkl->image = 'P';
		    }
		    break;		/* go ahead and ram the star */
		}
		goto accell;		/* try not to ram stars */
	    case Torp:
		if (!obj->vely && !obj->velx && (rand_mod(100) <= smarts) &&
		  (obj->image == 'o' || obj->image == 'O' || obj->image == 'X'))
		    goto accell;	/* try not to ram "friendly" torps */
		break;
	    case Web:
		if (curkl->image != 'T')
		    goto accell;	/* non-Tholians shouldn't ram web */
		if (count <= 5)
		    break;		/* Tholians retrace web if desperate */
		if (obj->image ==
		    (curkl->vely?
		     (curkl->velx?
		      (curkl->velx==curkl->vely?
		       '\\'
		      :
		       '/'
		      )
		     :
		      '|'
		     )
		    :
		     '-'
		    )
		   ) goto accell;	/* Tholians try not to retrace web */
		break;			/* No problem with crossing web */
	    }
	    break;			/* okay to move over object */

	accell:
	    /* determine maximum velocity */
	    if (massacre && curkl->image != 'T') {
		curkl->vely = rand_mod(7) - 3;
		curkl->velx = rand_mod(7) - 3;
	    }
	    else if (curkl->image == '&') {
		if (rand_mod(2)) {
		    curkl->vely = rand_mod(3) - 1;
		    curkl->velx = rand_mod(3) - 1;
		}
		else {
		    curkl->vely = curkl->strategy & 3;
		    if (curkl->vely & 2)
			curkl->vely = -1;
		    curkl->velx = (curkl->strategy >> 2) & 3;
		    if (curkl->velx & 2)
			curkl->velx = -1;
		}
	    }
	    else if (curkl->energy >= 2500 && curkl->image != 'T') {
		curkl->vely = rand_mod(5) - 2;
		curkl->velx = rand_mod(5) - 2;
	    }
	    else {
		curkl->vely = rand_mod(3) - 1;
		curkl->velx = rand_mod(3) - 1;
	    }
	}
	if (count != 10) {
	    if (curkl->image == ' ') {
		setimage(curkl, curkl->flags & PIRATE ? 'P' : 'R');
	    }
	    if (!count) {
		curkl->vely = 0;
		curkl->velx = 0;
	    }
	}
	if (curkl->image == 'G' && (base||ent) &&
	    !rand_mod((103-smarts)*10) ) {
	    int xxx,yyy;

	    for (xxx = -1; xxx<=1; xxx++)
		for (yyy = -1; yyy<=1; yyy++)
		    if ((xxx||yyy) && rand_mod(2))
			fire_torp(curkl,yyy,xxx);
	}
	else if (curkl->image == 'T' && (curkl->velx || curkl->vely)) {
	    make_object(Web,
            curkl->vely?
	     (curkl->velx?
	      (curkl->velx==curkl->vely?
	       '\\'
	      :
	       '/'
	      )
	     :
	      '|'
	     )
	    :
	     '-',
	    curkl->posy,curkl->posx,0,0,32767L,32767L,&root);
	    if (obj && obj->type == Web) {
		unmake_object(obj);
		occupant[y][x] = NULL;
	    }
	}
    }
    /* klingon-style fighting */
    if (numamoebas)
	attack(nuke);
    attack(base);
    if (ent && (!cloaked || ent->image=='E' || ent->image=='e'))
	attack(ent);
}

void
modify_amoeba(int y, int x, int where, int ch, int quant)
{
    int dy;
    int dx;
    int count = 15;

    if (!numamoebas)
	return;
    if (!where || (where==1 && rand_mod(2))) {
	y = nuke->posy;
	x = nuke->posx;
    }
    if (nuke->strategy && rand_mod(3)) {
	dy = nuke->strategy & 3;
	if (dy & 2)
	    dy = -1;
	dx = (nuke->strategy >> 2) & 3;
	if (dx & 2)
	    dx = -1;
	if (ch == ' ') {		/* take from the tail */
	    dy = -dy;
	    dx = -dx;
	}
	if (!rand_mod(100))
	    nuke->strategy = rand_mod(256);
    }
    else {
	dy = rand_mod(3) - 1;
	dx = rand_mod(3) - 1;
    }
    if (!dy && !dx)
	return;
    do {
	if (--count < 0)
	    return;
	y = (y + dy + YSIZE00) % YSIZE;
	x = (x + dx + XSIZE00) % XSIZE;
    } while (amb[y][x] != ' ');
    if (ch == ' ') {
	y = (y - dy + YSIZE00) % YSIZE;
	x = (x - dx + XSIZE00) % XSIZE;
    }
    if (ambsize > 100 && quant > 2) {
	quant >>= (ambsize/100);
    }
    if ((nuke->energy += quant << 6) > 32767)
	nuke->energy = 32767;
    count = quant << 3;		/* endless loop catcher */
    while (count-- > 0 && quant > 0) {
	if (amb[y][x] != ch) {
	    quant--;
	    amb[y][x] = ch;
	    if (ch == '~') {
		ambsize++;
		yblasted[y] |= 2;
		xblasted[x] |= 2;
		blasted = true;
	    }
	    else
		ambsize--;
	    if (!occupant[y][x])
		mvaddch(y+1,x*2,ch);
	}
	y = (y + rand_mod(3) + YSIZE99) % YSIZE;
	x = (x + rand_mod(3) + XSIZE99) % XSIZE;
    }
}
