/******************************************************************************
*									      *
*	(C) 1993 by K. Ballueder					      *
*									      *
*	See README and COPYING for details.				      *
*									      *
*	Please feel free to contact me:					      *
*		kballued@charon.physik.uni-osnabrueck.de		      *
*		kballued@jupiter.rz.uni-osnabrueck.de			      *
*									      *
******************************************************************************/


/**********************************************************************

movers.c:  Moving and "Living" of all non-static objects/fields

*****************************************************end of header*****/
#include "bdash.h"

#ifdef OS_DOS
#	include <alloc.h>
#	include <bios.h>  /* biostime() */
#endif
#include <stdlib.h>

#include "graphic.h"
#include "movers.h"
#include "react.h"
#include "game.h"


#include "Queue.h"
#include "Mover.h"
#include "torqueMover.h"
#include "randomMover.h"
#include "updownMover.h"
#include "lrMover.h"
#include "cheeseMover.h"

#include "io.h"	/* debug_printf */

/*
 * all objects which have to be moved are saved in a linear list:
 */
#define MINLEN	10

static void *mover_list = NULL;

/* add new object to list: */
void add_object(int x, int y, int type, int imagenum, int dir)
{
	void 		* new_mover;
	const void	 *otype ;

	debug_printf("add_object\n");
	switch(type)		/* quick'n dirty KB */
	{	case 0: otype = torqueMover; break;
		case 1: otype = Mover; break;
		case 2: otype = randomMover; break;
		case 3: otype = updownMover; break;
		case 4: otype = lrMover; break;
		case 5: otype = cheeseMover; break;
		default:	otype = Mover; break;
	}
	new_mover = new(otype, figur[imagenum], x, y, type, dir);
	debug_printf("\tnew_mover = %p\n", new_mover);
	debug_printf("\t\tx = %d  y = %d  type = %d  dir = %d\n",
			x,y,type, dir);
	debug_printf("\tmover_list = %p\n", mover_list);
	if(mover_list == NULL)	/* the 1st time... */
	{	debug_printf("\tcreating new list\n");
		mover_list = new(Queue, MINLEN);
	}
	if(new_mover)
	{	add(mover_list, new_mover);	
		debug_printf("\tadded new mover\n");
	}
}

/* remove object from list: */

void kill_object(unsigned x, unsigned y)
{
	void 	*new_list	= new(Queue, MINLEN);
	void 	*obj 		= take(mover_list);

	debug_printf("kill_object\n");
	while(obj) /* not NULL */
	{	debug_printf("\tprocessing %p\n", obj);
		if(getxpos(obj) == x && getypos(obj) == y)
		{	debug_printf("\tdeleting %p\n", obj);
			delete(obj);
		}
		else
			add(new_list,obj);
		obj = take(mover_list);
	}
	delete(mover_list);
	mover_list = new_list;
}

void movers_cleanup(void)
{
	void *obj;

	debug_printf("kill_all_objects\n");
	if(! mover_list)
	return;

	obj = take(mover_list);

	while(obj) /* not NULL */
	{	debug_printf("\tkilling: %p\n", obj);
		delete(obj);
		obj = take(mover_list); 
	}
	delete(mover_list);
	mover_list = NULL; 	/* for safety reasons */
	debug_printf("end of kill_all_objects\n");
}


static int delay_movers(void)
{
#ifdef OS_DOS
	static long lasttime = 0L;	/* time of last movement */
	if(biostime(0,0)-lasttime < bdash_speed)
		return 1;
	lasttime = biostime(0,0);
#else
	static long count = 0L;
/* 	debug_printf("delay_movers: count=%ld, bdash_speed: %ld\n", count, */
/* 			(long) bdash_speed); */
	if(count ++ < bdash_speed)
		return 1;
	count = 0L;
#endif
	return 0;
}



/*
 * each time this routine is called, it moves every object one step further
 */
void move_objects(void)
{
	void *obj;

	int x,y;
	int n = 0;

	debug_printf("move_objects\n");
	if(mover_list == NULL)	/* no movers! */
		return;
	debug_printf("\tmover_list != NULL\n");
	if(delay_movers())
		return;
	debug_printf("\tOK, now moving\n");
	obj = lookAt(mover_list,n++);
	debug_printf("\tobj = %p\n", obj);

	while(obj) /* not NULL */
	{	debug_printf("\tmoving.%p\n", obj);
		x = getxpos(obj), y = getypos(obj);
		bearbeite_feld(x,y);
		if(x)	bearbeite_feld(x-1,y);
		if(y)	bearbeite_feld(x,y-1);
		if(x < level_x_size-1)	bearbeite_feld(x+1,y);
		if(y < level_y_size-1)	bearbeite_feld(x,y+1);
		debug_printf("\tcalling move_funct #%d\n", gettype(obj));
		animate(obj);
		obj = lookAt(mover_list,n++);
	}
	update_graphics();
}
