
/*
 * Copyright (c) 1991    Jon Wesener 
 * Gaming Software
 *
 * Permission to use, copy, modify, and distribute this
 * software and its documentation for any purpose and without
 * fee is hereby granted, provided that the above copyright
 * notice appear in all copies and that both that copyright
 * notice and this permission notice appear in supporting
 * documentation.  No representations are made about the
 * suitability of this software for any purpose.  It is
 * provided "as is" without express or implied warranty.
 *
 */

#ident	"@(#)heat.c	1.7 :/usr/key/jojow/X/src/guts/SCCS/s.heat.c 3/19/91 10:15:51 "

/* heat.c - routines for handling heat seekers */

#include "server.h"


#define HEATRANGE		10

checkheats()
{
	register heat_t *hp;
	heat_t *hr;

	for( hp = Hvalid ; hp ; hp = hr ) {

		hr = hp->h_next;

		/* is it time to move the shell */
		if( ++(hp->h_pri) < HEATPRI )
			continue;

		hp->h_pri = 0;

		moveheat(hp);
		Servstate |= SSCUDFRC;
	}
}


static int xmv[] = {0,1,0,-1};
static int ymv[] = {-1,0,1,0};

moveheat(hp)
	register heat_t *hp;
{
	int nx, ny;
	int dead = 0;
	tank_t *tp;


	nx = hp->h_x + xmv[hp->h_dir];
	ny = hp->h_y + ymv[hp->h_dir];
		
	/* aged missile */
	if( ++(hp->h_life) >= HEATLIFE ) 
		dead = 1;
	/* hit a wall? */
	else if( field[nx][ny] == FWALL ) {

		/* randomly change direction */
		if( rand() & 0x2)
			hp->h_dir++;
		else
			hp->h_dir += 3;

		hp->h_dir %= MAXDIR;
		nx = hp->h_x;
		ny = hp->h_y;
	}
	/* hit a tank? */
	else if( field[nx][ny] == FTANK ) {

		tp = (tank_t *)fpts[nx][ny];
		if( !TANKSAFE(tp)   ) {
			dead = 1;

			explode(tp,hp->h_own,Heatdmg,nx,ny);
		}
	}
	/* change direction for other reasons? */
	else {
		int d = HEATRANGE, nd, dx, dy, dxs, dys;
		tank_t *ts = NULL;


		for( tp = Tvalid ; tp ; tp = tp->t_next ) {
			/* can we seek this tank? */
			if( (hp->h_own == tp) || TANKHID(tp) )
				continue;

			/* find the distance */
			nd = abs( dx = (tp->t_x - nx) ) + abs( dy = (tp->t_y - ny) );
			if( nd >= d )
				continue;

			d = nd;
			ts = tp;
			dxs = dx;
			dys = dy;
		}

		if( ts ) {
			int xdir, ydir, odir;

			xdir = ( dxs > 0 ) ? 1 : 3;
			ydir = ( dys > 0 ) ? 2 : 0;

			odir = hp->h_dir;

			if( !dxs )
				hp->h_dir = ydir;
			else if( !dys )
				hp->h_dir = xdir;
			else if( (xdir != odir) && (ydir != odir) )
				hp->h_dir = (abs(dxs) > abs(dys))? ydir: xdir;

#if NOTDEF
			/* see if changing the direction dead ends the missile */
			if( field[nx+xmv[hp->h_dir]][ny+ymv[hp->h_dir]] == FWALL )
				hp->h_dir = odir;
#endif /* NOTDEF */
		}
	}

	if( !dead ) {
		hp->h_x = nx;
		hp->h_y = ny;
	}
	/* shell gone? */
	else  {
		heat_t *hr;


		hp->h_own->t_heatf--;

		/* kill it */
		if( Hvalid == hp )
			Hvalid = hp->h_next;
		else {
			for( hr = Hvalid ; hr->h_next != hp ; hr = hr->h_next );
			hr->h_next = hp->h_next;
		}

		hp->h_next = Hfree;
		Hfree = hp;
	}
}


fire_heat(tp)
	register tank_t *tp;
{
	heat_t *hp;


	/* any shells to fire? */
	if( tp->t_energy < Heatcost )
		return;

	tp->t_energy -= Heatcost;
	Totenergy += Heatcost;

	hp = Hfree;
	Hfree = hp->h_next;

	tp->t_heatf++;

	hp->h_x = tp->t_x;
	hp->h_y = tp->t_y;
	hp->h_dir = tp->t_dir;
	hp->h_pri = 0;
	hp->h_life = 0;
	hp->h_own = tp;

	hp->h_next = Hvalid;
	Hvalid = hp;
}


rm_heats(tp)
	tank_t *tp;
{
	heat_t *hp, *hr, *hn;
	
	/* remove all the mines belonging to tp */
	for( hp = Hvalid ; hp ; hp = hn ) {

		hn = hp->h_next;

		if( hp->h_own != tp )
			continue;

		/* kill it */
		if( Hvalid == hp )
			Hvalid = hp->h_next;
		else {
			for( hr = Hvalid ; hr->h_next != hp ; hr = hr->h_next );
			hr->h_next = hp->h_next;
		}

		hp->h_next = Hfree;
		Hfree = hp;
	}
}


heatdest()
{
	register heat_t *hp, *hr;


	/* Walk down the list and remove them */
	for( hr = hp = Hvalid ; hp ; hp = hp->h_next ) {
		hr = hp;

		hp->h_own->t_heatf--;
	}

	if( Hvalid ) {
		hr->h_next = Hfree;
		Hfree = Hvalid;
		Hvalid = NULL;
	}
}


/* Lint Output
*/
