#include "wand_head.h"

typedef struct { int d[2]; } direction;

#ifdef	LINT_ARGS	/* M001 */
direction new_direction(int, int, int, int);
#else
direction new_direction();
#endif

extern int debug_disp;
extern char screen[NOOFROWS][ROWLEN+1];

/* Add a spirit to the chain */
/* Maintain a doubly linked list to make reuse possible.
   tail_of_list is *NOT* the last monster allocated, but
   the last monster alloted to a screen.  start_of_list
   is a dummy entry to ease processing. last_of_list
   is the last entry allocated. */

extern struct mon_rec *last_of_list, *tail_of_list;
extern struct mon_rec start_of_list;

struct mon_rec *make_monster(x, y)
int x, y;
{
    char *malloc();
#define MALLOC (struct mon_rec *)malloc(sizeof(struct mon_rec))
    struct mon_rec *monster;
    if (tail_of_list->next == NULL) {
	if ((last_of_list = MALLOC) == NULL)
	    return NULL;
	tail_of_list->next = last_of_list;
	last_of_list->prev = tail_of_list;
	last_of_list->next = NULL;
    }
    monster = tail_of_list = tail_of_list->next;
    monster->x = x;
    monster->y = y;
    monster->mx = 1;	/* always start moving RIGHT. (fix later)  */
    monster->my = 0;
    monster->under = ' ';
    return monster;
}

/* 'follow lefthand wall' algorithm for baby monsters */

direction new_direction(x, y, bx, by)
int x, y, bx, by;
{
    direction out;

    if (viable((x+by),(y-bx))) {
	out.d[0] = by;
	out.d[1] = -bx;
	return out;
    }
    if (viable((x+bx),(y+by))) {
	out.d[0] = bx;
	out.d[1] = by;
	return out;
    }
    if (viable((x-by),(y+bx))) {
	out.d[0] = -by;
	out.d[1] = bx;
	return out;
    }
    if (viable((x-bx),(y-by))) {
	out.d[0] = -bx;
	out.d[1] = -by;
	return out;
    }
    out.d[0] = -bx;
    out.d[1] = -by;
    return out;
}

int move_monsters(mxp, myp, score, howdead, sx, sy, nf, bell, x, y, diamonds)
int *mxp, *myp, sx, sy, nf, bell, x, y, diamonds;
long *score;
char *howdead;
{
    int xdirection, ydirection, hd, vd;
    int deadyet = 0;
    int bx, by, nbx, nby, tmpx,tmpy;
    direction new_disp;
    struct mon_rec *monster,*current;
    char buffer[25];

/* big monster first */
    if (*mxp == -2) {		/* has the monster been killed ? */
	*score+=100;
	*mxp = *myp = -1;
	move(3,48);
	sprintf(buffer,"%ld\t %d\t",*score,nf);
	(void) addstr(buffer);
	draw_symbol(50,11,' ');
	move(12,56); addstr("              ");
	move(13,56); addstr("              ");
	move(16,0);
	refresh();
    }			/* if monster still alive */
    if (*mxp != -1) {	/* then move that monster ! */
	screen[*myp][*mxp] = ' ';
	if (*mxp > x)
	    xdirection = -1;
	else
	    xdirection = 1;
	if (!debug_disp) {
	    if ((*myp < (sy+4)) && (*myp > (sy-4)) && (*mxp < (sx+6)) &&
		(*mxp > (sx-6)))
		draw_symbol((*mxp-sx+5)*3,(*myp-sy+3)*2,' ');
	} else {
	    move(*myp+1,*mxp+1);
	    addch(' ');
	}
	if ((hd = (*mxp-x))<0)
	    hd = -hd;
	if ((vd = (*myp-y))<0)
	    vd = -vd;
	if ((hd > vd) && ((*mxp+xdirection) < ROWLEN) &&
	    ((screen[*myp][*mxp+xdirection] == ' ') ||
	    (screen[*myp][*mxp+xdirection] == '@')))
	    *mxp += xdirection;
	else {
	    if (*myp > y)
		ydirection = -1;
	    else
		ydirection = 1;
	    if (((*myp+ydirection) < NOOFROWS) &&
		((screen[*myp+ydirection][*mxp] == ' ') ||
		(screen[*myp+ydirection][*mxp] == '@')))
		*myp += ydirection;
	    else if (((*mxp+xdirection) < ROWLEN) &&
		(screen[*myp][*mxp+xdirection] == ' ') ||
		(screen[*myp][*mxp+xdirection] == '@'))
		*mxp += xdirection;
	}
	if (!debug_disp) {
	    if ((*myp < (sy+4)) && (*myp > (sy-4)) &&
		(*mxp < (sx+6)) && (*mxp > (sx-6)))
		draw_symbol((*mxp-sx+5)*3,(*myp-sy+3)*2,'M');
	} else {
	    move(*myp+1,*mxp+1);
	    addch('M');
	}
	if (screen[*myp][*mxp] == '@') {	/* ha! gottim! */
	    strcpy(howdead,"a hungry monster");
	    move(16,0);
	    refresh();
	    deadyet = 1;
	}
	screen[*myp][*mxp] = 'M';
	move(16,0);
	refresh();
    }

    current = &start_of_list;		/* baby monsters now */
    while ((current != tail_of_list) && (!deadyet)) {
	/* deal with those little monsters */
	monster = current->next;
	new_disp = new_direction(monster->x, monster->y, monster->mx, monster->my);
	if (monster->under != 'S') {	/* if on top of another baby */
	    screen[monster->y][monster->x] = monster->under;
	    if (!debug_disp) {
		if ((monster->y < (sy+4)) && (monster->y > (sy-4)) &&
		    (monster->x < (sx+6)) && (monster->x > (sx-6)))
		    draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,monster->under);
	    } else {
		move(monster->y+1,monster->x+1);
		addch(monster->under);
	    }
	    if (monster->under == ' ')
		deadyet += check(&*mxp,&*myp,monster->x,monster->y,new_disp.d[0],new_disp.d[1],sx,sy,howdead);
	} else
	    monster->under = ' ';
	monster->mx = new_disp.d[0];
	monster->my = new_disp.d[1];
	monster->x += monster->mx;
	monster->y += monster->my;
	monster->under = screen[monster->y][monster->x];
	screen[monster->y][monster->x] = 'S';	/* move into new space */
	if (!debug_disp) {
	    if ((monster->y < (sy+4)) && (monster->y > (sy-4)) &&
		(monster->x < (sx+6)) && (monster->x > (sx-6)))
		draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'S');
	} else {
	    move(monster->y+1,monster->x+1);
	    addch('S');
	}
	if (monster->under == '@') {	/* monster hit you? */
	    strcpy(howdead,"the little monsters");
	    move(16,0);
	    refresh();
	    deadyet = 1;
	    monster->under = ' ';
	}
	if (monster->under == '+') {	/* monster hit cage? */
#ifdef NOISY
	    if (bell) printf("\007");
#endif
	    *score += 20;
	    move(3,48);
	    sprintf(buffer,"%ld\t %d\t %d ",*score,nf,diamonds);
	    (void) addstr(buffer);
	    /* remove from chain, and insert at the end (at last_of_list) */
	    if (monster == tail_of_list)
		tail_of_list = tail_of_list->prev;
	    else {
		current->next = monster-> next;
		current->next->prev = current;
		monster->next = NULL;
		monster->prev = last_of_list;
		last_of_list->next = monster;
		last_of_list = monster;
	    }
	    screen[monster->y][monster->x] = '*';
	    if (!debug_disp) {
		if ((monster->y < (sy+4)) && (monster->y > (sy-4)) &&
		    (monster->x < (sx+6)) && (monster->x > (sx-6)))
		    draw_symbol((monster->x-sx+5)*3,(monster->y-sy+3)*2,'*');
	    } else {
		move(monster->y+1,monster->x+1);
		addch('*');
	    }
	} else
	    current = monster;
	move(16,0);
	refresh();
    }
    return deadyet;
}
