#include <math.h>
#include <allegro.h>
#include <stdlib.h>
#include <stdio.h>
//#include <time.h>
#include <string.h>






//					**HELPER FUNCTIONS**

extern FILE *debug;

extern int frame;

void message(char *s) {
	//alert(s, NULL, NULL, "OK", NULL, NULL, NULL);
	fprintf(debug, s);
}






//					**PHYSICS**

#define REPULSESTRENGTH .25
#define LINKSTRENGTH .31
#define FLUIDFRICTION 0.9995
#define FRICTION 0.0005
#define GRAVITY .008
#define MAXBOXX 304
#define MAXBOXY 64
#define MAXATOMS 10000
#define MAXLINKS 80000
#define MAXPOLYS 10000
#define MAXOBJECTS 200
#define MAXRIGIDBODIES 10
#define MAXRATOMS 300
#define MAXDEBRIS 5000
#define MAXLEVELS 20
#define BPMULT 1.04
#define DELTAT 1
#define PIXW 10

//#define MVTDRAIN 0.005
//#define DEADZONE 0.5

float DIAGRL, DIAGBP, STRBP;
int COMPFRAMES;

int green, black, white, magenta, gray, yellow;

extern BITMAP *buf;
extern BITMAP *bg;
extern BITMAP *sky;
extern BITMAP *scorch;
extern BITMAP *debris1;
extern BITMAP *debriso1;
extern BITMAP *debrisr[4];
extern BITMAP *debrisrm[4];
extern BITMAP *explosionsmallanim[24];
extern BITMAP *splashanim[6];
BITMAP *thold;
BITMAP *tmp;

extern SAMPLE *explodesmall;
extern SAMPLE *explode;
extern SAMPLE *splash;
extern int numsplashes;

extern int path[4000];
extern int debrislev[4000];

extern float lx, rx;

int expc;
extern int waterlevel;

extern float convk;

int forcetable_repulse_x[20][20];
int forcetable_repulse_y[20][20];

typedef struct atom atom;
typedef struct link link;
typedef struct poly poly;
typedef struct debrisitem debrisitem;
typedef struct rigidbody rigidbody;

void adddebris(atom *, bool);
void addtrailanim(atom *a, BITMAP **anim, int frames, int mod, int modoff, int life, float dy, int rand, bool trans, int delay);
void addanimation(BITMAP **newframes, int newnumframes, int newx, int newy, bool trans, float dy, int delay, int rand);
void dopanvol(float x, float k);

extern int pan, vol;

struct atom {
	float x, y;
	float ox, oy;
	float ix, iy;
	float oix, oiy;
	float mx, my;
	float mass;
	float rmdt;
	int bx, by;
	link *l[8];
	int lc;
	int color;
	bool draw;
	bool fixed;
	bool on;
	bool debris;
	bool transdeb;
	bool nullstate;
	debrisitem *d;
	rigidbody *r;
	BITMAP *bmp;
	float mvt;
	int st;
	float *damage;
	float dmult;
	float dtmult;
	bool draw2;
	int life;

	int level;
	bool levels[MAXLEVELS];

	atom() {
		init();
	}

	void init() {
		int i;

		st = 0;
		x = y = 400;
		ox = oy = 400;
		ix = iy = 0;
		oix = oiy = 20;
		mass = 1;
		rmdt = 1;
		bx = by = 0;
		mx = my = 0;
		l[0] = l[1] = l[2] = l[3] = l[4] = l[5] = l[6] = l[7] = NULL;
		for(i = 1; i < MAXLEVELS; i++) {
			levels[i] = true;
		}
		levels[0] = false;
		lc = 0;
		color = 0;
		draw = true;
		fixed = false;
		on = false;
		level = 0;
		debris = false;
		bmp = NULL;
		transdeb = false;
		d = NULL;
		r = NULL;
		mvt = 0;
		nullstate = false;
		damage = NULL;
		dmult = 1;
		dtmult = 1;
		draw2 = true;
		life = -5;
	}
};

atom atoms[MAXATOMS];
int numatoms;

atom *structure[100][100];

struct debrisitem {
	atom *me;
	bool on;
	int offx, offy;
	int eoffx, eoffy, ew, eh;
	float angle;
	bool drew;
	bool accrue;

	debrisitem() {
		init();
	}

	void init() {
		me = NULL;
		on = false;
		offx = -5;
		offy = -5;
		eoffx = -12; eoffy = -12; ew = 24; eh = 24;
		angle = 0;
		drew = false;
		accrue = true;
	}

	void draw() {
		if(me->on == false) {
			on = false;
			return;
		}
		if(me->x - 5 > lx && me->x + 5 < rx) {
			if(me->bmp == NULL) return;

			if(me->ix > .1 || me->iy > .1) {
				angle = atan2(me->iy, me->ix);
				angle *= convk;
			}
			rotate_sprite(buf, me->bmp, me->x + offx, me->y + offy, itofix(angle));
			drew = true;
		}
	}

	void erase() {
		if(!drew) return;
		if(me->bmp == NULL) return;
		blit(bg, buf, me->x + eoffx, me->y + eoffy, me->x + eoffx, me->y + eoffy, ew, eh);	
		drew = false;
	}

	void kill() {
		erase();
		on = false;
	}
};

debrisitem debris[MAXDEBRIS];

struct box {
	atom *list[200];
	int count;

	box() {
		count = 0;
	}
};

box boxes[MAXBOXX][MAXBOXY];
//10x10 boxes

struct link {
	atom *a, *b;

	float rl;
	float bp;

	bool draw;
	bool drew;
	bool on;

	int color;

	poly *p[4];

	link() {
		init();
	}

	void init() {
		draw = true;
		on = false;
		p[0] = p[1] = p[2] = p[3] = NULL;
		color = 0;
		bp = 00;
		rl = 10;
		a = NULL;
		b = NULL;
		drew = false;
	}
};

link links[MAXLINKS];
int numlinks;

struct poly {
	atom *a, *b, *c;
	float *ax, *bx, *cx, *ay, *by, *cy;
	link *l1, *l2, *l3;
	
	bool trans;
	bool on;
	bool drew;
	int type;
	
	BITMAP **tmap;
	BITMAP **transmap;
	//BITMAP *thold;
	V3D_f *v1,*v2,*v3;

	poly() {
		init();
	}

	void init() {
		ax = bx = cx = 0;
		ay = by = cy = 0;
		trans = false;
		on = false;
		drew = false;
		type = 0;
	}
};

poly polys[MAXPOLYS];
int numpolys;

struct object {
	BITMAP *obj;
	BITMAP *origobj;
	BITMAP *transmap;
	float x, y;

	object() {
		x = 0;
		y = 0;
		obj = NULL;
		origobj = NULL;
		transmap = NULL;
	}

	void reset() {
		if(origobj != NULL) destroy_bitmap(origobj);
		if(transmap != NULL) destroy_bitmap(transmap);
		origobj = NULL;
		obj = NULL;
		transmap = NULL;
		//if(transmap != NULL) destroy_bitmap(transmap);
		//transmap = NULL;
	}
};

object objects[MAXOBJECTS];
int numobjects;

struct rigidbody {
	float offset[MAXRATOMS][2];			//Maximum of 100 atoms, each with a 2 coordinate offset vector
	float ouv[MAXRATOMS][2];			//Stored ***ORTHOGONAL to OFFSET*** unit vectors. Used because the projection of the force vector onto this direction will give the effective force
	float ol[MAXRATOMS];				//Stored length of offets, for use in computing torque
	atom *atomlist[MAXRATOMS];
	int mynumatoms;
	poly *polylist[MAXATOMS];
	int mynumpolys;
	float x, y, ix, iy, mx, my;
	float ox, oy;
	float ang, ia;
	float rm, ram;
	float gmult;	//gravity multiplier
	float afric;	//angular friction
	float gfric;	//ground friction (not implemented)
	float grmult;	//ground multiplier
	float gmmult;	//ground instamove mult (to make less bouncy)
	float imult;	//incline multiplier
	bool on;
	float turning;
	float polylistx[100];
	float polylisty[100];
	float grounddamagethreshold;
	int pathoffset;	//distance above / below the ground - 20 is normal

	rigidbody() {
		init();
	}

	void init() {
		int a, c;
		mynumatoms = 0;
		mynumpolys = 0;
		x = y = ix = iy = mx = my = ang = ia = ox = oy = 0;
		x = -1;
		rm = 0.006;
		ram = 0.00001;
		gmult = 180;
		grmult = 1;
		gmmult = 1;
		imult = 1;
		grounddamagethreshold = 1.5;

		for(a = 0; a < MAXRATOMS; a++) {
			ol[a] = 0;
			for(c = 0; c < 2; c++) {
				offset[a][c] = 0;
				ouv[a][c] = 0;
			}
		}
		on = false;
		afric = 0.95;
		gfric = 0.001;
		turning = 1;
		pathoffset = 23;
	}

	void addatom(atom *a) {
		atomlist[mynumatoms] = a;
		mynumatoms++;
	}

	void addpoly(poly *p) {
		polylist[mynumpolys] = p;
		mynumpolys++;
	}

	void complete() {
		int i;
		float dx, dy, dist, m, om, ox, oy, od;
		atom *a;
		
		//fprintf(debug, "s: x = %f, y = %f\n", x, y);
		//if(x != -1) fprintf(debug, "Would not have run\n");
		//if(x == -1) {
		float nx, ny;
		float tx, ty;
		float tm;
		tx = ty = tm = 0;
		for(i = 0; i < mynumatoms; i++) {
			tx += atomlist[i]->x * atomlist[i]->mass;
			ty += atomlist[i]->y * atomlist[i]->mass;
			tm += atomlist[i]->mass;
		}
		nx = tx / tm;
		ny = ty / tm;
		x = nx;
		y = ny;
		//}
		//fprintf(debug, "e: x = %f, y = %f\n", x, y);
		ox = x;
		oy = y;
		//x = 530;
		//y = 370;

		for(i = 0; i < mynumatoms; i++) {
			a = atomlist[i];

			dx = a->x - x;
			dy = a->y - y;
			offset[i][0] = dx;
			offset[i][1] = dy;
			dist = sqrt(dx * dx + dy * dy);
			ol[i] = dist;
			m = dy / dx;
			if(m != 0) {
				om = (-1) / m;
				ox = 1;
				oy = om;
			}
			else {
				om = 0;
				ox = 0;
				oy = 1;
			}
			od = sqrt(1 + oy * oy);
			ox = ox / od;
			oy = oy / od;
			if(dy > 0) {
				ox = -ox;
				oy = -oy;
			}
			ouv[i][0] = ox;
			ouv[i][1] = oy;
			a->r = this;
		}
		on = true;
	}

	void update() {
		if(!on) return;
		int i;
		//atom **ap;
		//float (*o)[2];
		atom *a;
		
		int j;
		int nbx, nby;
		int gy;
		float ca, sa;
		float x1, y1;
		float f, d;
		int gx;
		float dist, dx, dy;
		float force, fx, fy;
		box *b;
		const float FK1 = 4;
		const float FK2 = 50;
		const float FK3 = 1;
		float igmult;

		igmult = gmult / mynumatoms;

		ca = cos(ang);
		sa = sin(ang);

		for(i = 0; i < mynumatoms; i++) {
			a = atomlist[i];
			d = ol[i];

			for(int j = 0; j < 100; j++) {
				for(int g = 0; g < 100; g++) {
					float r = 1004.24214 / 123023.34;
				}
			}

			ix += a->ix;
			iy += a->iy;
			mx += a->mx;
			my += a->my;

			x1 = ouv[i][0];
			y1 = ouv[i][1];
			f = (a->ix * (x1 * ca - y1 * sa) + a->iy * (x1 * sa + y1 * ca)) * d;
			ia += f;

			a->ix = 0;
			a->iy = 0;
			a->mx = 0;
			a->my = 0;
		}
			
		//if(fabs(ix) < .1) ix = 0;
		//if(fabs(my) < .1) mx = 0;
		//if(fabs(iy) < .2) iy = 0;
		//if(fabs(my) < .2) my = 0;

		ox = x;
		oy = y;
		x += (ix + mx) * rm;
		y += (iy + my) * rm;
		mx = 0;
		my = 0;
		ix *= FLUIDFRICTION;
		iy *= FLUIDFRICTION;
		//ia *= 0.95;//FLUIDFRICTION;
		ia *= afric;
		if(afric == 0.95) {
			if(ia * ram > .02) ia = 0.02 / ram;
			if(ia * ram < -.02) ia = -0.02 / ram;
			if(fabs(ia * ram) < 0.002) ia = 0;
		}
		ang += ia * ram;
		//ang = 0;

		ca = cos(ang);
		sa = sin(ang);

		/*
		if(y < waterlevel) {
			iy += gmult * GRAVITY;
		}
		else {
			iy -= gmult * GRAVITY;
			//iy *= 0.99;
			//ix *= 0.999;
		}
		*/

		for(i = 0; i < mynumatoms; i++) {
			a = atomlist[i];

			a->iy += GRAVITY * igmult * a->mass;

			x1 = offset[i][0];
			y1 = offset[i][1];
			//a->x = (int)(x + (x1*ca - y1*sa));
			//a->y = (int)(y + (x1*sa + y1*ca));
			a->x = x + (x1*ca - y1*sa);
			a->y = y + (x1*sa + y1*ca);

			if(mynumpolys != 0) {
				x1 = offset[i][0] * turning;
				y1 = offset[i][1];
				polylistx[i] = x + (x1*ca - y1*sa);
				polylisty[i] = y + (x1*sa + y1*ca);
			}

			/* Botched attempt at water friction
			if(a->y > waterlevel - 10) {
				a->ix -= 0.002 * ix;
				ix -= 0.0001 * ix;
				a->iy -= 0.001 * fabs(ix);
				//iy -= 1 * fabs(ix);
			}
			*/
			

			/*
			gfric = 0.997;

			if(a->y > path[(int)a->x] + 0) {
				ix *= gfric;
				circlefill(buf, a->x, a->y, 5, magenta);
			}
			*/

			if(a->y > path[(int)a->x]) {

				gx = (int)(a->x) + 3;
				gy = path[gx] + pathoffset;
				
				dx = ((int)(a->x) - gx);
				dy = (a->y - gy);

				force = 0;

				if(dx < 20 && dy < 20 && dx > -20 && dy > -20) {
					dist = (float)(sqrt(dx * dx + dy * dy));
					if(dist < 20 && dist != 0) {
						force = (20 - dist) * REPULSESTRENGTH * grmult;
						fx = (dx / dist) * force;
						fy = (dy / dist) * force;
						//if(fabs(fx) > 0.2) {
							//FIRST
							a->ix += FK1*fx;
							a->iy += FK3*fy;
							a->mx += FK2*fx*imult *gmmult;
							a->my += FK3*fy *gmmult;
							if(force > grounddamagethreshold && a->damage != NULL) {
								*(a->damage) += force * 10;
							}
						//}
						a->ix += -ix * gfric;
					}
				}

				gx = (int)(a->x) - 3;
				gy = path[gx] + pathoffset;
				
				dx = ((int)(a->x) - gx);
				dy = (a->y - gy);


				if(dx < 20 && dy < 20 && dx > -20 && dy > -20) {
					dist = (float)(sqrt(dx * dx + dy * dy));
					if(dist < 20 && dist != 0) {
						force = (20 - dist) * REPULSESTRENGTH * grmult;
						fx = (dx / dist) * force;
						fy = (dy / dist) * force;
						//if(fabs(fx) > 0.2) {
							//SECOND
							a->ix += FK1*fx;
							a->iy += FK3*fy;
							a->mx += FK2*fx *imult *gmmult;
							a->my += FK3*fy *gmmult;
							if(force > grounddamagethreshold && a->damage != NULL) {
								*(a->damage) += force * 10;
							}
						//}
						a->ix += -ix * gfric;
					}
				}

				/*
				if(force != 0) {					
					if(a->ix > gfric)
						a->ix -= gfric;
					else if(a->ix < -gfric)
						a->ix += gfric;
					else
						a->ix = 0;
				}
				*/

				if(a->x < 0) {
					x++;
					ix = -ix * 0.5;
					gy = 800;
				}
				if(a->x > buf->w - 2) {
					x -= 2;
					ix = -ix * 0.5;
				}		
				if(a->y < 0) {
					y++;
					iy = -iy * 0.5;
				}
				if(a->y > buf->h - 1) {
					y--;
					iy = -iy * 0.5;
				}

				/*
				gy = path[(int)(a->x)];
				if(a->x - 5 > 0 && a->x - 5 < buf->w - 1) {
					gl = path[(int)(a->x - 5)];
				}
				else gl = 0;
				if(a->x + 5 > 0 && a->x + 5 < buf->w - 1) {
					gr = path[(int)(a->x + 5)];
				}
				else gl = 0;
				*/
			}

			nbx = ((int)(a->x) / 10) + 2;
			nby = ((int)(a->y) / 10) + 2;

			if(nbx != a->bx || nby != a->by) {
				b = &(boxes[a->bx][a->by]);
				j = 0;
				b->count--;
				while(j < b->count && b->list[j] != a) j++;
				b->list[j] = b->list[b->count];

				b = &(boxes[nbx][nby]);
				if(b->count < 195) {
					b->list[b->count] = a;
					b->count++;
				}
				a->bx = nbx;
				a->by = nby;
			}
		}
	}
};

rigidbody rigidbodies[MAXRIGIDBODIES];
int numrigidbodies;

rigidbody *addrigidbody(float rm, float ram, float gmult) {
	rigidbody *r;
	r = &(rigidbodies[numrigidbodies]);
	r->rm = rm;
	r->ram = ram;
	r->gmult = gmult;
	r->x = -1;
	numrigidbodies++;

	return r;
}

void destroyvehiclerigidbody(rigidbody *r) {
	int i;
	float mult;
	atom *a;
	poly *p;
	mult = 1 / (r->gmult * 0.125);
	for(i = 0; i < r->mynumatoms; i++) {
		a = r->atomlist[i];
		a->r = NULL;	
		a->rmdt = 0.5;
		a->mass = 1;
		a->ix = r->ix * mult * 0.1;
		a->iy = r->iy * mult;
		//if(r->obj == tankd || r->obj == tankde) a->iy -= 1;
		//a->iy -= 0.2 * ((rand() % 10) * 0.1 - 0.5) + 0.1;
		//a->ix += 0.2 * ((rand() % 10) * 0.1 - 0.5);
	}
	for(i = 0; i < r->mynumpolys; i++) {
		p = r->polylist[i];
		p->ax = &(p->a->x);
		p->ay = &(p->a->y);
		p->bx = &(p->b->x);
		p->by = &(p->b->y);
		p->cx = &(p->c->x);
		p->cy = &(p->c->y);
	}
	r->on = false;
}

void destroyrigidbody(rigidbody *r) {
	int i;
	atom *a;
	for(i = 0; i < r->mynumatoms; i++) {
		a = r->atomlist[i];
		a->r = NULL;
	}
	r->on = false;
}

void updaterigidbodies() {
	rigidbody *r;
	int i;
	r = &(rigidbodies[0]);
	for(i = 0; i < numrigidbodies; i++) {
		r->update();
		r++;
	}
}

atom *addatom(float x, float y, bool levels[MAXLEVELS], int level) {
	atom *a;
	box *b;
	int nbx, nby, i;
	link **l;

	a = &(atoms[0]);
	while(a->on) a++;

	//a->init();
	
	l = &(a->l[0]);
	for(i = 0; i < 8; i++) {
		*l = NULL;
		l++;
	}

	for(i = 0; i < MAXLEVELS; i++) {
		a->levels[i] = levels[i];
	}

	a->level = level;

	a->x = x;
	a->y = y;
	a->dmult = 1;
	a->life = -5;

	a->debris = false;
	nbx = (int)a->x / 10 + 2;
	nby = (int)a->y / 10 + 2;
	b = &(boxes[nbx][nby]);
	b->list[b->count] = a;
	b->count++;
	a->bx = nbx;
	a->by = nby;
	a->rmdt = DELTAT;
	a->fixed = false;
	a->color = gray;
	a->draw = true;
	a->draw2 = true;
	a->on = true;
	a->dmult = 1;
	a->dtmult = 1;
	
	if(a == &(atoms[numatoms])) {
		numatoms++;
	}

	return a;
}

void addlink(atom *a, atom *b, float rl, float bp) {
	link *l, **p;

	l = &(links[0]);
	while(l->on) l++;

	l->init();
	l->a = a;
	l->b = b;
	l->rl = rl;
	l->bp = bp;
	l->on = true;
	l->color = gray;

	p = &(a->l[0]);
	while(*p != NULL) p++;
	*p = l;
	a->lc++;

	p = &(b->l[0]);
	while(*p != NULL) p++;
	*p = l;
	b->lc++;

	if(a->draw == false && b->draw == false || 1) 
		l->draw = false;
	else
		l->draw = true;

	if(l == &(links[numlinks])) {
		numlinks++;
	}
}

bool overlap(atom *a, atom *b, atom *c, atom *x, atom *y) {
	if(x == a && y == b) return true;
	if(x == b && y == c) return true;
	if(x == c && y == a) return true;
	if(x == b && y == a) return true;
	if(x == c && y == b) return true;
	if(x == a && y == c) return true;
	return false;
}

poly *addpoly(atom *a, atom *b, atom *c) {
	poly *p;
	link *l;
	int i, j, k;

	p = &(polys[0]);
	while(p->on) p++;

	p->init();

	p->a = a;
	p->b = b;
	p->c = c;
	p->ax = &(a->x);
	p->ay = &(a->y);
	p->bx = &(b->x);
	p->by = &(b->y);
	p->cx = &(c->x);
	p->cy = &(c->y);
	p->on = true;

	k = 0;
	l = &(links[0]);
	for(i = 0; i < numlinks; i++) {
		if(overlap(a, b, c, l->a, l->b)) {
			for(j = 0; j < 4; j++) {
				if(l->p[j] == NULL) {
					l->p[j] = p;
					if(k == 0)
						p->l1 = l;
					else if(k == 1)
						p->l2 = l;
					else if(k == 2)
						p->l3 = l;
					k++;
					j = 5;
				}
			}
		}
		l++;
	}

	if(p == &(polys[numpolys]))	{
		numpolys++;
	}
	return p;
}

void do_repulseforceold(atom *a1, atom *a2) {
	int dx, dy;
	float fx, fy;
	dx = (int)(a1->x - a2->x) + 10;
	dy = (int)(a1->y - a2->y) + 10;
	if(dx >= 20 || dy >= 20 || dx < 0 || dy < 0) return;

	fx = forcetable_repulse_x[dx][dy];
	fy = forcetable_repulse_y[dx][dy];

	a1->ix += fx;
	a1->iy += fy;
	a2->ix -= fx;
	a2->iy -= fy;
}			

void do_repulseforce(atom *a1, atom *a2) {
	link **l;
	int i;
	if(a1->nullstate && a2->nullstate) return;	
	if(a1 == NULL || a2 == NULL) 
		fprintf(debug, "a1 = %i, a2 = %i\n", a1, a2);
	if(a1 == NULL || a2 == NULL)
		return;
	if(a1->on == false || a2->on == false) return;
	if(a1->levels[a2->level] == false) return;
	
	l = &(a1->l[0]);
	for(i = 0; i < 8; i++) {
		if((*l) != NULL && ((*l)->a == a2 || (*l)->b == a2)) return;
		l++;
	}

	float dist, dx, dy;
	float force, fx, fy;
	dx = (int)(a1->x - a2->x);
	dy = (int)(a1->y - a2->y);

	if(dx < 10 && dy < 10 && dx > -10 && dy > -10) {
		dist = (float)(sqrt(dx * dx + dy * dy));
		if(dist == 0) {
			dist = dx = dy = 0.1;
		}
		if(dist < 10) {
			force = (10 - dist) * REPULSESTRENGTH;
			fx = (dx / dist) * force;
			fy = (dy / dist) * force;
			if(a2->r != NULL && (a1->level == 6 || a1->level == 3)) {//(a1->level == 6 || a1->level == 3) && (a2->level == 11 || a2->level == 12)) {
				float mod = 0.1;
				a1->ix += fx;
				a2->ix -= mod*fx;

				a1->iy += fy;
				a2->iy -= mod*fy;

				a1->mx += fx;// / 1;
				a2->mx -= mod*fx;// / 1;
				a1->my += fy;// / 1;
				a2->my -= mod*fy;// / 1;

				if(a1->damage != NULL) {
					if(force > 0.5) {
						*(a1->damage) += 3 * (force - 0.5) * a2->dmult * a1->dtmult;
					}
				}
				if(a2->damage != NULL) {
					if(force > 0.5) {
						*(a2->damage) += 0.5 * (force - 0.5) * a1->dmult * a2->dtmult;
					}
				}
			}
			else if(a1->r != NULL && (a2->level == 6 || a2->level == 3)) {//(a2->level == 6 || a2->level == 3) && (a1->level == 11 || a1->level == 12)) {
				float mod = 0.1;
				a1->ix += mod*fx;
				a2->ix -= fx;

				a1->iy += mod*fy;
				a2->iy -= fy;

				a1->mx += mod*fx;// / 1;
				a2->mx -= fx;// / 1;
				a1->my += mod*fy;// / 1;
				a2->my -= fy;// / 1;

				if(a1->damage != NULL) {
					if(force > 0.5) {
						*(a1->damage) += 0.5 * (force - 0.5) * a2->dmult * a1->dtmult;
					}
				}
				if(a2->damage != NULL) {
					if(force > 0.5) {
						*(a2->damage) += 3 * (force - 0.5) * a1->dmult * a2->dtmult;
					}
				}
			}
			else {
				a1->ix += fx;
				a2->ix -= fx;

				a1->iy += fy;
				a2->iy -= fy;

				a1->mx += fx;// / 1;
				a2->mx -= fx;// / 1;
				a1->my += fy;// / 1;
				a2->my -= fy;// / 1;

				if(a1->damage != NULL) {
					if(force > 0.5) {
						*(a1->damage) += 3 * (force - 0.5) * a2->dmult * a1->dtmult;
					}
				}
				if(a2->damage != NULL) {
					if(force > 0.5) {
						*(a2->damage) += 3 * (force - 0.5) * a1->dmult * a2->dtmult;
					}
				}
			}			
		}
	}
}

void destroyatom(atom *a) {
	box *b;
	int i;

	a->on = false;
	a->draw = false;
	a->draw2 = false;
	a->debris = false;

	if(a->bmp != NULL) {
		destroy_bitmap(a->bmp);
		a->bmp = NULL;
	}

	b = &(boxes[a->bx][a->by]);
	i = 0;
	while(i < b->count && b->list[i] != a) i++;
	if(b->list[i] == a) {
		b->count--;
		b->list[i] = b->list[b->count];
	}
	a->init();
}

int findlow(float a, float b) {
	if(a < b) return (int)a;
	return (int)b;
}

int findhigh(float a, float b) {
	if(a > b) return (int)a;
	return (int)b;
}

int findlow(float a, float b, float c) {
	if(a <= b && a <= c) return (int)a;
	if(b <= a && b <= c) return (int)b;
	if(c <= b && c <= a) return (int)c;
	return 0;
}

int findhigh(float a, float b, float c) {
	if(a >= b && a >= c) return (int)a + 1;
	if(b >= a && b >= c) return (int)b + 1;
	if(c >= b && c >= a) return (int)c + 1;
	return 0;
}

/*
void alphablit(BITMAP *source, BITMAP *dest, int x1, int y1, int x2, int y2, int w, int h) {
	int x, y;

	for(x = 0; x < w; x++) {
		for(y = 0; y < h; y++) {
			if(getpixel(dest, x + x2, y + y2) != magenta) {
				putpixel(dest, x + x2, y + y2, getpixel(source, x + x1, y + y1)
*/

void crazyoverlay(BITMAP *dest, BITMAP *source, int sx, int sy) {
	int x, y, c;
	for(x = sx; x < sx + source->w; x++) {
		for(y = sy; y < sy + source->h; y++) {
			//if(x >= 0 && x < dest->w && y >= 0 && y < dest->h) {
				c = getpixel(source, x - sx, y - sy);
				if(getr32(c) == 255 && getg32(c) == 0 && getb32(c) == 255)//magenta)
					putpixel(dest, x, y, c);
			//}
		}
	}
}

void destroypoly(poly *p) {
	int i, x, y;

	//p->a->draw = true;
	//p->b->draw = true;
	//p->c->draw = true;

	p->on = false;

	if(p->transmap != NULL) {
		x = findlow(p->v1->u, p->v2->u, p->v3->u) + 5 - 20;
		y = findlow(p->v1->v, p->v2->v, p->v3->v) + 5 - 20;
		draw_trans_sprite(*(p->tmap), debrisr[p->type], x, y);
		//draw_trans_sprite(*(p->transmap), debrisrm[p->type], x, y);
		crazyoverlay(*(p->transmap), debrisrm[p->type], x, y);

		BITMAP *tmp;
		tmp = create_bitmap_ex(32, 40, 40);
		blit(*(p->transmap), tmp, x, y, 0, 0, 40, 40);
		draw_trans_sprite(*(p->tmap), tmp, x, y);
		//draw_trans_sprite(buf, *(p->transmap), 100, 100);
	}

	/*
	fprintf(debug, "free!");
	p->l1->draw = true;
	//p->l1->a->draw = true;
	//p->l1->b->draw = true;

	p->l2->draw = true;
	//p->l2->a->draw = true;
	//p->l2->b->draw = true;

	p->l3->draw = true;
	//p->l3->a->draw = true;
	//p->l3->b->draw = true;
	fprintf(debug, "alive!");
	*/

	/*
	if(p->l1->p[0] != NULL) p->l1->p[0]->trans = true;
	if(p->l1->p[1] != NULL) p->l1->p[1]->trans = true;
	if(p->l1->p[2] != NULL) p->l1->p[2]->trans = true;
	if(p->l1->p[3] != NULL) p->l1->p[3]->trans = true;

	if(p->l2->p[0] != NULL) p->l2->p[0]->trans = true;
	if(p->l2->p[1] != NULL) p->l2->p[1]->trans = true;
	if(p->l2->p[2] != NULL) p->l2->p[2]->trans = true;
	if(p->l2->p[3] != NULL) p->l2->p[3]->trans = true;

	if(p->l3->p[0] != NULL) p->l3->p[0]->trans = true;
	if(p->l3->p[1] != NULL) p->l3->p[1]->trans = true;
	if(p->l3->p[2] != NULL) p->l3->p[2]->trans = true;
	if(p->l3->p[3] != NULL) p->l3->p[3]->trans = true;
	*/

	p->type = 0;

	for(i = 0; i < 4; i++) {
		if(p->l1->p[i] == p) {
			p->l1->p[i] = NULL;
		}
	}

	///*
	for(i = 0; i < 4; i++) {
		if(p->l1->p[i] != NULL) {
			i = 10;
			break;
		}
	}
	if(i != 10) {
		p->l1->draw = true;
		//p->l1->a->draw = true;
		//p->l1->b->draw = true;
	}
	//*/

	for(i = 0; i < 4; i++) {
		if(p->l2->p[i] == p) {
			p->l2->p[i] = NULL;
		}
	}

	///*
	for(i = 0; i < 4; i++) {
		if(p->l2->p[i] != NULL) {
			i = 10;
			break;
		}
	}
	if(i != 10) {
		p->l2->draw = true;
		//p->l2->a->draw = true;
		//p->l2->b->draw = true;
	}
	//*/

	for(i = 0; i < 4; i++) {
		if(p->l3->p[i] == p) {
			p->l3->p[i] = NULL;
		}
	}

	///*
	for(i = 0; i < 4; i++) {
		if(p->l3->p[i] != NULL) {
			i = 10;
			break;
		}
	}
	if(i != 10) {
		p->l3->draw = true;
		//p->l3->a->draw = true;
		//p->l3->b->draw = true;
	}
	//*/
}
	
void do_linkforce(link *l) {
	if(l->a->nullstate && l->b->nullstate) return;
	int i;
	float dist, dx, dy;
	float force, fx, fy;
	dx = (l->a->x - l->b->x);
	dy = (l->a->y - l->b->y);
	bool broke = false;
	link **lp;
	bool tmp;
	
	if(dx < l->bp && dy < l->bp && dx > -l->bp && dy > -l->bp) {
		dist = (float)(sqrt(dx * dx + dy * dy));
		if(dist == 0) {
			dist = dx = dy = 0;
			return;
		}
		if(dist < l->bp) {
			force = (l->rl - dist) * LINKSTRENGTH;
			fx = (dx / dist) * force;

			l->a->ix += fx;
			l->b->ix -= fx;

			fy = (dy / dist) * force;
			l->a->iy += fy;
			l->b->iy -= fy;

			l->a->mx += fx * .3;
			l->b->mx -= fx * .3;
			l->a->my += fy * .3;
			l->b->my -= fy * .3;
		}
		else
			broke = true;
	}
	else
		broke = true;

	if(l->a->r != NULL || l->b->r != NULL) broke = false;

	if(broke) {
		dopanvol(l->a->x, 0.2);
		if(expc % 5 == 0) play_sample(explodesmall, vol * 0.7, pan, 1000, 0);
		expc++;
		l->on = false;

		int count;

		count = 0;
		for(i = 0; i < 8; i++) {
			if(l->a->l[i] != NULL) {
				count++;
			}
		}

		for(i = 0; i < 8; i++) {
			if(l->a->l[i] != NULL) {
				if(count <= 3) {
					l->a->l[i]->bp = 0;
				}
				//l->a->l[i]->bp -= 0.1;
				if(l->a->l[i] == l) {
					l->a->l[i] = NULL;
					//break;
				}
			}
		}
		count = 0;
		for(i = 0; i < 8; i++) {
			if(l->b->l[i] != NULL) {
				count++;
			}
		}

		for(i = 0; i < 8; i++) {
			if(l->b->l[i] != NULL) {
				if(count <= 3) {
					l->b->l[i]->bp = 0;
				}
				//l->a->l[i]->bp -= 0.1;
				if(l->b->l[i] == l) {
					l->b->l[i] = NULL;
					//break;
				}
			}
		}

		/*
		for(i = 0; i < 8; i++) {
			if(l->a->l[i] != NULL) {
				l->a->l[i]->bp -= 0.1;
				if(l->a->l[i] == l) {
					l->a->l[i] = NULL;
					//break;
				}
			}
		}

		for(i = 0; i < 8; i++) {
			if(l->b->l[i] != NULL) {
				l->b->l[i]->bp -= 0.1;
				if(l->b->l[i] == l) {
					l->b->l[i] = NULL;
					//break;
				}
			}
		}
		*/

		for(i = 0; i < 4; i++) {
			if(l->p[i] != NULL) {
				destroypoly(l->p[i]);
			}
		}

		/*
		for(i = 0; i < 12; i++) {
			if(l->a->p[i] != NULL) {
				for(j = 0; j < 12; j++) {
					if(l->a->p[i] == l->b->p[j]) {
						destroypoly(l->a->p[i]);
						break;
					}
				}
			}
		}
		*/
		
		if(!l->a->fixed) {
			tmp = true;
			lp = &(l->a->l[0]);
			for(i = 0; i < 8; i++) {
				if((*lp) != NULL) {
					tmp = false;
					break;
				}
				lp++;
			}
			if(tmp)	{
				adddebris(l->a, true);
				if(rand() % 6 == 0 && l->a->draw2)
					addtrailanim(l->a, explosionsmallanim, 24, 10, rand() % 10, 500 + rand() % 1000, -2, 1, false, 1);
			}
		}

		if(!l->b->fixed) {
			tmp = true;
			lp = &(l->b->l[0]);
			for(i = 0; i < 8; i++) {
				if((*lp) != NULL) {
					tmp = false;
					break;
				}
				lp++;
			}
			if(tmp) {
				adddebris(l->b, true);
				if(rand() % 6 == 0 && l->b->draw2)
					addtrailanim(l->b, explosionsmallanim, 24, 10, rand() % 10, 500 + rand() % 1000, -2, 1, false, 1);
			}
		}

		l->a = NULL;
		l->b = NULL;
	}
}

void addscorch(int x, int y) {
	BITMAP *tmp;
	int py, pyr, nx;
	tmp = create_bitmap(60, 60);
	blit(bg, tmp, x - 27, y - 19, 0, 0, 60, 60);
	draw_trans_sprite(tmp, scorch, 0, 0);
	for(int xp = 0; xp < 60; xp++) {
		nx = xp + x - 27;
		if(nx > 0 && nx < buf->w - 1) {
			py = path[xp + x - 27] + 1;
			pyr = py - y + 20 + 1;
			blit(tmp, bg, xp, pyr, xp + x - 27, py, 1, 60 - pyr);
			blit(tmp, buf, xp, pyr, xp + x - 27, py, 1, 60 - pyr);
		}
		//blit(tmp, buf, xp, 0, xp + a->x - 27, a->y - 20, 1, path[(int)xp] - (a->y - 22));
	}
	destroy_bitmap(tmp);
	tmp = NULL;
}
		
void physics_update() {
	atom *a;
	link *l;
	box *b;
	int i, j;
	int nbx, nby;
	int gy, gl, gr;
	int dy, dl, dr;
	bool debris;
	float dmg;
	float dif;

	a = &(atoms[0]);
	for(i = 0; i < numatoms; i++) {
		if(a->life == 0) {
			a->on = false;
			destroyatom(a);
		}
		if(a->life > 0) a->life--;
		if(a->on) {
			a->oix = a->ix;
			a->oiy = a->iy;// + GRAVITY;
			a->ox = a->x;
			a->oy = a->y;
			//fprintf(debug, "1");
			//1 - down left
			b = &(boxes[a->bx - 1][a->by + 1]);
			if(b->count != 0) {
				for(j = 0; j < b->count; j++)  {
					do_repulseforce(a, b->list[j]);
				}
			}
			//fprintf(debug, "2");
			//2 - down
			b = &(boxes[a->bx][a->by + 1]);
			if(b->count != 0) {
				for(j = 0; j < b->count; j++) {
					do_repulseforce(a, b->list[j]);
				}
			}
			//fprintf(debug, "3");
			//3 - down right
			b = &(boxes[a->bx + 1][a->by + 1]);
			if(b->count != 0) {
				for(j = 0; j < b->count; j++) {
					do_repulseforce(a, b->list[j]);
				}
			}
			//fprintf(debug, "4");
			//4 - right
			b = &(boxes[a->bx + 1][a->by]);
			if(b->count != 0) {
				for(j = 0; j < b->count; j++) {
					do_repulseforce(a, b->list[j]);
				}
			}
			//fprintf(debug, "5");
			//5 - center (special case)
			b = &(boxes[a->bx][a->by]);
			if(b->count != 1) {
				for(j = 0; j < b->count; j++) {
					if(b->list[j] < a) {
						do_repulseforce(a, b->list[j]);
					}
				}
			}
		}
		
		a++;
	}

	l = &(links[0]);
	for(i = 0; i < numlinks; i++) {
		if(l->on)
			do_linkforce(l);
		l++;
	}

	a = &(atoms[0]);
	for(i = 0; i < numatoms; i++) {
		if(a->r == NULL && !a->fixed && a->on) {
			//fprintf(debug, "A:%i\n",frame);

			if(fabs(a->ix) < 0.005 && fabs(a->iy) < 0.005) {
				a->ix = 0;
				a->iy = 0;
				a->mx = 0;
				a->my = 0;
			}

			a->x += (a->ix + a->mx) * a->rmdt;
			a->y += (a->iy + a->my) * a->rmdt;

			a->mx = 0;
			a->my = 0;
			
			a->ix *= FLUIDFRICTION;
			a->iy *= FLUIDFRICTION;

			a->mvt += fabs(a->ix) + fabs(a->iy);

			if(a->y < waterlevel) {
				if(a->level != 15) a->iy += GRAVITY * a->mass;

				//NEEDS TO BE RESOLVED
				if(a->level == 1 || a->level == 5) {
					a->iy += 0.2;
				}
			}
			else {
				dif = a->y - waterlevel;
				if(dif < 10)
					a->iy -= dif * 0.17 * GRAVITY * a->mass;
				else
					a->iy -= GRAVITY * a->mass;
				a->iy *= 0.99;
				a->ix *= 0.999;
				if(a->oy < waterlevel - 0.1) {
					if(numsplashes < 1) {
						dopanvol(a->x, 0.5);
						play_sample(splash, vol, pan, 1000, 0);
						numsplashes++;
					}
					//void addanimation(BITMAP **newframes, int newnumframes, int newx, int newy, bool trans, float dy, int delay, int rand) {
					addanimation(splashanim, 6, (int)(a->x) - 4, (int)(a->y) - 2, 0, 0, 1, 1);
					
					/*
  0: Nothing interacts with this. Used for debris
  1: The human player
  2: The upper part of buildings (that the player cannot walk through)
  3: The human's bullets
  4: The lower part of buildings (that the player can walk through)
  5: Enemy soldiers
  6: Enemy bullets
  7: Vehicles
  8: Corpses
  9: Acts like bullets (bomb bullets)
  */

					if(a->level == 0 || a->level == 3 || a->level == 6 || a->level == 9)
						a->life = 500;
				}
			}

			if(!(a->debris == true && a->transdeb) && a->x < buf->w && a->x > 0) {
				if(a->level != 1 && a->level != 5 && a->level != 8) {
					gy = path[(int)(a->x)];
					if(a->x - 5 > 0 && a->x - 5 < buf->w - 1) {
						gl = path[(int)(a->x - 5)];
					}
					else gl = 0;
					if(a->x + 5 > 0 && a->x + 5 < buf->w - 1) {
						gr = path[(int)(a->x + 5)];
					}
					else gl = 0;
				}
				else if(a->level != 8) {
					gy = path[(int)(a->x)] - 5;
					if(a->x - 5 > 0 && a->x - 5 < buf->w - 1) {
						gl = path[(int)(a->x - 5)] - 5;
					}
					else gl = 0;
					if(a->x + 5 > 0 && a->x + 5 < buf->w - 1) {
						gr = path[(int)(a->x + 5)] - 5;
					}
					else gl = 0;
				}
				else {
					gy = path[(int)(a->x)] + 5;
					if(a->x - 5 > 0 && a->x - 5 < buf->w - 1) {
						gl = path[(int)(a->x - 5)] + 5;
					}
					else gl = 0;
					if(a->x + 5 > 0 && a->x + 5 < buf->w - 1) {
						gr = path[(int)(a->x + 5)] + 5;
					}
					else gl = 0;
				}
			}
			else {
				gy = 800;
				gl = 800;
				gr = 800;
			}

			if(a->x < 0) {
				a->x = 1;
				a->ix = -a->ix * 0.5;
				gy = 800;
			}
			if(a->x > buf->w - 1) {
				a->x = buf->w - 1;
				a->ix = -a->ix * 0.5;
			}		
			if(a->y < 0) {
				a->y = 1;
				//a->iy = 0;
				a->ix = a->ix * 0.1;
				a->iy = -a->iy * 0.1;
			}

			debris = false;
			
			if(a->debris == true && a->d->accrue == true) {
				dy = debrislev[(int)a->x];
				if(a->transdeb) dy += 5;
				if(a->debris == true && a->y >= dy) {//((!a->transdeb && a->y >= dy) || (a->transdeb && a->y > dy + 5))) {	
					if(a->y > dy + 2) {
						a->y--;
						a->iy = 0;
					}
					else {
						if(a->x > 1) {
							dl = debrislev[(int)a->x - 1];
						}
						else {
							dl = 0;
						}
						if(a->x < buf->w - 1) {
							dr = debrislev[(int)a->x + 1];
						}
						else {
							dr = 0;
						}

						if(dl > dy) {
							a->x -= rand() % 4 + 1;
							a->mx = 0;
							a->my = 0;
							a->ix = 0;
							a->iy = 0;
						}
						else if(dr > dy) {
							a->x += rand() % 4 + 1;
							a->mx = 0;
							a->my = 0;
							a->ix = 0;
							a->iy = 0;
						}
						else if(a->bmp != NULL) {
							int nx;

							if(!a->transdeb) {
								draw_sprite(bg, a->bmp, a->x - 5, a->y - 5);
								draw_sprite(buf, a->bmp, a->x - 5, a->y - 5);
								for(j = 0; j < 10; j++) {
									nx = j + (int)a->x - 5;
									if(nx >= 0 && nx < buf->w - 1) {
										debrislev[j + (int)a->x - 5] = (int)a->y - (15 - abs(5- j));
									}
								}
								
								if(dy == gy - 7) {
									addscorch((int)a->x, (int)a->y);
								}
							}
							else {
								int py, xp;//, pyr;
								draw_sprite(buf, a->bmp, a->x - 5, a->y - 5);
								for(xp = (int)a->x - 7; xp <= (int)a->x + 7; xp++) {
									py = path[xp] + 1;
									//pyr = py + 21;
									blit(bg, buf, xp, py, xp, py, 1, 25);
								}
								draw_sprite(bg, a->bmp, a->x - 5, a->y - 5);

								for(xp = (int)a->x - 7; xp <= (int)a->x + 7; xp++) {
									py = path[xp] + 1;
									//pyr = py + 21;
									blit(buf, bg, xp, py, xp, py, 1, 25);
								}
							}

							
							a->on = false;
							a->d->kill();
							destroyatom(a);
							debris = true;
						}
					}
				}
			}
			else if(a->debris && a->y > gy) {
				a->on = false;
				a->d->kill();
				destroyatom(a);
				debris = true;
			}

			if (!debris) {

				if(a->y > gy) { //gy) {
					a->y = gy;
					if(a->damage != NULL) {
						dmg = fabs(a->iy) - 13;
						if(fabs(a->ix) > 5) dmg += a->ix - 5;
						if(dmg > 0) {
							*(a->damage) += 1 * dmg;
						}
					}
					a->iy = -a->iy * 0.1;
				}

				if(a->y > gy - 5) {
					if(a->level != 1 && a->level != 5) {
						if(gl < gy && gr > gy) {
							a->ix += (a->y - gy + 10) * .002;
						}
						else if(gl > gy && gr < gy) {
							a->ix -= (a->y - gy + 10) * .002;
						}
						a->ix *= 0.9;
					}
					else {
						if(gl < gy && gr > gy && (a->ix < -0.2 || a->ix > 0.2)) {
							if(a->ix < -0.5 || a->ix > 0.5)
								a->mx = .2;
						}
						else if(gl > gy && gr < gy && (a->ix < -0.2 || a->ix > 0.2)) {
							a->mx = -.2;
						}
						a->ix *= 0.995;
					}
				}

				nbx = ((int)(a->x) / 10) + 2;
				nby = ((int)(a->y) / 10) + 2;

				if(nbx != a->bx || nby != a->by) {

					b = &(boxes[a->bx][a->by]);
					j = 0;
					b->count--;
					while(j < b->count && b->list[j] != a) j++;
					b->list[j] = b->list[b->count];

					b = &(boxes[nbx][nby]);
					if(b->count < 195) {
						b->list[b->count] = a;
						b->count++;
					}
					a->bx = nbx;
					a->by = nby;
				}
			}
		}
		a++;
	}
}





//					**ACTUAL PROGRAM**

void setupforcetable() {
	int x, y;
	float dist, dx, dy;
	float force, fx, fy;
	
	for(x = 0; x < 20; x++) {
		for(y = 0; y < 20; y++) {
			dx = x - 10;
			dy = y - 10;
			dist = (float)(sqrt(dx * dx + dy * dy));
			if(dist <= 10) {
				force = (10 - dist) * REPULSESTRENGTH;
				fx = (dx / dist) * force;
				fy = (dy / dist) * force;
				forcetable_repulse_x[x][y] = fx;
				forcetable_repulse_y[x][y] = fy;
			}
			else {
				forcetable_repulse_x[x][y] = 0;
				forcetable_repulse_y[x][y] = 0;
			}
		}
	}
}

void physics_initvars() {
	debug = fopen("debug.txt", "w");
	setbuf(debug, NULL);

	DIAGRL = sqrt(200);
	DIAGBP = BPMULT * DIAGRL; //- 0;
	STRBP = BPMULT * 10.0 + 0.4;
	numatoms = 0;
	numpolys = 0;
	numobjects = 0;
	expc = 0;

	setupforcetable();
}

void initializeold() {
	int i, nbx, nby;
	for(i = 0; i < MAXATOMS; i = i + 1) {
		atoms[i].x = (float)(rand() % 300);
		atoms[i].y = (float)(rand() % 600);
		nbx = (int)(((int)atoms[i].x / 10) + 2);
		nby = (int)(((int)atoms[i].y / 10) + 2);
		boxes[nbx][nby].list[boxes[nbx][nby].count] = &(atoms[i]);
		boxes[nbx][nby].count++;
		atoms[i].bx = nbx;
		atoms[i].by = nby;
		atoms[i].rmdt = 1;
	}

	atoms[0].x = 100;
	atoms[0].y = 500;
	atoms[1].x = 110;
	atoms[1].y = 500;
	atoms[2].x = 110;
	atoms[2].y = 510;
	atoms[3].x = 100;
	atoms[3].y = 510;
	addlink(&(atoms[0]), &(atoms[1]), 10, STRBP);
	addlink(&(atoms[1]), &(atoms[2]), 10, STRBP);
	addlink(&(atoms[2]), &(atoms[3]), 10, STRBP);
	addlink(&(atoms[3]), &(atoms[0]), 10, STRBP);

	addlink(&(atoms[0]), &(atoms[2]), DIAGRL, DIAGBP);
	addlink(&(atoms[1]), &(atoms[3]), DIAGRL, DIAGBP);
}

int shouldbeatom(BITMAP *obj, int x, int y) {

	bool mag = false;
	bool omag = false;

	for(int xp = x - PIXW; xp < x + PIXW; xp++) {
		for(int yp = y - PIXW; yp < y + PIXW; yp++) {
			if(xp >= 0 && yp >= 0 && xp < obj->w && yp < obj->h) {
				if(getpixel(obj, xp, yp) != magenta) {
					omag = true;
				}
				else {
					mag = true;
				}
			}
		}
	}

	if(omag && mag) return 2;
	else if(omag) return 1;
	else return 0;
	return 0;
}

void dotex(poly *r, BITMAP **obj, BITMAP **transmap, int x1, int y1, int x2, int y2, int x3, int y3) {
	V3D_f *a, *b, *c;
	a = new V3D_f;
	b = new V3D_f;
	c = new V3D_f;

	a->u = x1;
	a->v = y1;
	b->u = x2;
	b->v = y2;
	c->u = x3;
	c->v = y3;

	a->c = b->c = c->c = 2;
	a->z = b->z = c->z = 10;

	r->v1 = a;
	r->v2 = b;
	r->v3 = c;
	r->tmap = obj;
	if(*transmap == NULL) {
		r->transmap = NULL;
	}
	else
		r->transmap = transmap;

	/*
	if(r->trans == true) {
		r->thold = create_bitmap(15, 15);
		clear_to_color(r->thold, 0);
	}
	*/
}

void checktransdeb(atom *a) {
	int x, y;
	bool mag = false;
	for(x = 0; x < a->bmp->w; x++) {
		for(y = 0; y < a->bmp->h; y++) {
			if(getpixel(a->bmp, x, y) == magenta) {
				mag = true;
				break;
			}
		}
	}
	if(!mag)
		a->transdeb = false;
	else
		a->transdeb = true;
}

void addmodobject(char *fn, char *fnt, float startx, float starty, bool fixed, bool levels[MAXLEVELS], int level, float lmod, float aposx[100][100], float aposy[100][100]) {
	int x, y;
	poly *r;
	object *o;
	int v, maxy = 0;
	atom *a;
	
	o = &(objects[numobjects]);
	numobjects++;
	o->obj = load_bitmap(fn, NULL);
	if(fnt != NULL) {
		o->transmap = load_bitmap(fnt, NULL);
	}
	else {		
		o->transmap = NULL;
	}
	o->origobj = o->obj;

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			v = shouldbeatom(o->obj, x * 10, y * 10);
			if(v != 0) {
				structure[x][y] = addatom(aposx[x][y], aposy[x][y], levels, level);//x * 10 + startx, y * 10 + starty, levels, level);
				a = structure[x][y];
				a->draw = false;
				/*
				if(v == 2)
					a->draw2 = false;
				else
					a->draw2 = true;
				*/
				a->bmp = create_bitmap(14, 14);
				clear_to_color(a->bmp, magenta);
				blit(o->obj, a->bmp, aposx[x][y] - 7, aposy[x][y] - 7, 0, 0, 14, 14); //x * 10 - 7, y * 10 - 7, 0, 0, 14, 14);
				checktransdeb(a);
				if(!a->transdeb) {
					draw_trans_sprite(a->bmp, debris1, 0, 0);
				}
				else {
					int x, y, r1, g1, b1, r2, g2, b2, rf, gf, bf;
					r2 = 40;
					g2 = 40;
					b2 = 40;
					int dist, gd;
					float al = .5;
					for(x = 0; x < a->bmp->w; x++) {
						for(y = 0; y < a->bmp->h; y++) {
							if(getpixel(a->bmp, x, y) != magenta) {
								r1 = getr(getpixel(a->bmp, x, y));
								g1 = getg(getpixel(a->bmp, x, y));
								b1 = getb(getpixel(a->bmp, x, y));
								dist = r2 - r1;
								gd = al * dist;
								rf = r1 + gd;
								dist = g2 - g1;
								gd = al * dist;
								gf = g1 + gd;
								dist = b2 - b1;
								gd = al * dist;
								bf = b1 + gd;
								putpixel(a->bmp, x, y, makecol16(rf, gf, bf));
							}
						}
					}
					draw_trans_sprite(a->bmp, debriso1, 0, 0);
				}
			}
			else {
				structure[x][y] = NULL;
			}
		}
	}

	float dx, dy, dist;
	float tbpmult, tbpadd;
	tbpmult = 1.04;
	tbpadd = .1;

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				if(x > 0 && structure[x-1][y] != NULL) {
					dx = aposx[x-1][y] - aposx[x][y];
					dy = aposy[x-1][y] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x-1][y], dist, (dist * tbpmult + tbpadd) * lmod);
				}
				if(y > 0 && structure[x][y-1] != NULL) {
					dx = aposx[x][y-1] - aposx[x][y];
					dy = aposy[x][y-1] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x][y-1], dist, (dist * tbpmult + tbpadd) * lmod);
				}				
				if(x > 0 && y > 0 && structure[x-1][y-1] != NULL) {
					dx = aposx[x-1][y-1] - aposx[x][y];
					dy = aposy[x-1][y-1] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x-1][y-1], dist, (dist * tbpmult + tbpadd) * lmod);
				}
				if(x < 99 && y > 0 && structure[x+1][y-1] != NULL) {
					dx = aposx[x+1][y-1] - aposx[x][y];
					dy = aposy[x+1][y-1] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x+1][y-1], dist, (dist * tbpmult + tbpadd) * lmod);
				}
			}
		}
	}
	
	for(x = 0; x < 99; x++) {
		for(y = 0; y < 99; y++) {
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y] != NULL && structure[x - 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y], structure[x - 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->type = 0;
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				//dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW);
				dotex(r, &(o->obj), &(o->transmap), aposx[x][y], aposy[x][y],aposx[x-1][y], aposy[x-1][y],aposx[x-1][y-1], aposy[x-1][y-1]);
			}
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y - 1] != NULL && structure[x][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y - 1], structure[x][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->type = 1;
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}				
				dotex(r, &(o->obj), &(o->transmap), aposx[x][y], aposy[x][y],aposx[x-1][y-1], aposy[x-1][y-1],aposx[x][y-1], aposy[x][y-1]);
				//dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW,(x) * PIXW, (y - 1) * PIXW);
			}
			/*
			//if(x == 1 && y == 2) {
			if(y - 1 >= 0 && structure[x][y] != NULL && structure[x][y - 1] != NULL && structure[x + 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x][y - 1], structure[x + 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), (x-0) * PIXW, (y-0) * PIXW,(x) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW);
			}
			if(y - 1 >= 0 && structure[x][y] != NULL && structure[x + 1][y - 1] != NULL && structure[x + 1][y] != NULL) {
				r = addpoly(structure[x][y], structure[x + 1][y - 1], structure[x + 1][y]);//getpixel(o->obj, x * PIXW, y * PIXW));
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), (x) * PIXW, (y) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y) * PIXW);
			}
			*/
		}
	}

	for(y = 0; y < 100; y++) {
		for(x = 0; x < 100; x++) {
			if(structure[x][y] != NULL) {
				maxy = y;
				structure[x][y]->x += startx;
				structure[x][y]->y += starty;
			}
		}
	}

	if(strcmp(fn, "building.pcx") == 0 || strcmp(fn, "building2.pcx") == 0 || strcmp(fn, "building3.pcx") == 0 || strcmp(fn, "building4.pcx") == 0) {
		for(x = 0; x < 50; x++) {
			for(y = maxy; y > maxy - 5; y--) {
				if(structure[x][y] != NULL) {
					structure[x][y]->levels[1] = false;
					structure[x][y]->levels[5] = false;
					structure[x][y]->levels[11] = false;
					structure[x][y]->levels[12] = false;
					structure[x][y]->level = 4;
				}
			}
		}
	}

	if(fixed) {
		for(x = 0; x < 50; x++) {
			if(structure[x][maxy] != NULL) {
				structure[x][maxy]->fixed = true;
				structure[x][maxy]->draw = false;
			}
		}
	}
}

rigidbody *addmodrigidobject(char *fn, char *fnt, float startx, float starty, bool fixed, bool levels[MAXLEVELS], int level, float lmod, float rm, float ram, float gmult, float aposx[100][100], float aposy[100][100], float amass[100][100]) {
	int x, y;
	poly *r;
	object *o;
	int v, maxy = 0;
	atom *a;

	rigidbody *rb;
	float *structurex[100][100];
	float *structurey[100][100];

	rb = addrigidbody(rm, ram, gmult);
	
	o = &(objects[numobjects]);
	numobjects++;
	o->obj = load_bitmap(fn, NULL);
	if(fnt != NULL) {
		o->transmap = load_bitmap(fnt, NULL);
	}
	else {		
		o->transmap = NULL;
	}
	o->origobj = o->obj;

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			v = shouldbeatom(o->obj, x * 10, y * 10);
			if(v != 0) {
				structure[x][y] = addatom(aposx[x][y], aposy[x][y], levels, level);//x * 10 + startx, y * 10 + starty, levels, level);
				a = structure[x][y];
				if(amass != NULL)
					a->mass = amass[x][y];
				rb->addatom(a);
				structurex[x][y] = &(rb->polylistx[rb->mynumpolys]);
				structurey[x][y] = &(rb->polylisty[rb->mynumpolys]);
				rb->mynumpolys++;
				a->draw = false;
				/*
				if(v == 2)
					a->draw2 = false;
				else
					a->draw2 = true;
				*/
				a->bmp = create_bitmap(14, 14);
				clear_to_color(a->bmp, magenta);
				blit(o->obj, a->bmp, aposx[x][y] - 7, aposy[x][y] - 7, 0, 0, 14, 14); //x * 10 - 7, y * 10 - 7, 0, 0, 14, 14);
				checktransdeb(a);
				if(!a->transdeb) {
					draw_trans_sprite(a->bmp, debris1, 0, 0);
				}
				else {
					int x, y, r1, g1, b1, r2, g2, b2, rf, gf, bf;
					r2 = 40;
					g2 = 40;
					b2 = 40;
					int dist, gd;
					float al = .5;
					for(x = 0; x < a->bmp->w; x++) {
						for(y = 0; y < a->bmp->h; y++) {
							if(getpixel(a->bmp, x, y) != magenta) {
								r1 = getr(getpixel(a->bmp, x, y));
								g1 = getg(getpixel(a->bmp, x, y));
								b1 = getb(getpixel(a->bmp, x, y));
								dist = r2 - r1;
								gd = al * dist;
								rf = r1 + gd;
								dist = g2 - g1;
								gd = al * dist;
								gf = g1 + gd;
								dist = b2 - b1;
								gd = al * dist;
								bf = b1 + gd;
								putpixel(a->bmp, x, y, makecol16(rf, gf, bf));
							}
						}
					}
					draw_trans_sprite(a->bmp, debriso1, 0, 0);
				}
			}
			else {
				structure[x][y] = NULL;
			}
		}
	}

	float dx, dy, dist;
	float tbpmult, tbpadd;
	tbpmult = 1.04;
	tbpadd = 0.1;

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				if(x > 0 && structure[x-1][y] != NULL) {
					dx = aposx[x-1][y] - aposx[x][y];
					dy = aposy[x-1][y] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x-1][y], dist, (dist * tbpmult + tbpadd) * lmod);
				}
				if(y > 0 && structure[x][y-1] != NULL) {
					dx = aposx[x][y-1] - aposx[x][y];
					dy = aposy[x][y-1] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x][y-1], dist, (dist * tbpmult + tbpadd) * lmod);
				}				
				if(x > 0 && y > 0 && structure[x-1][y-1] != NULL) {
					dx = aposx[x-1][y-1] - aposx[x][y];
					dy = aposy[x-1][y-1] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x-1][y-1], dist, (dist * tbpmult + tbpadd) * lmod);
				}
				if(x < 99 && y > 0 && structure[x+1][y-1] != NULL) {
					dx = aposx[x+1][y-1] - aposx[x][y];
					dy = aposy[x+1][y-1] - aposy[x][y];
					dist = sqrt(dx * dx + dy * dy);
					addlink(structure[x][y], structure[x+1][y-1], dist, (dist * tbpmult + tbpadd) * lmod);
				}
			}
		}
	}
	
	rb->mynumpolys = 0;
	for(x = 0; x < 99; x++) {
		for(y = 0; y < 99; y++) {
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y] != NULL && structure[x - 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y], structure[x - 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->type = 0;
				rb->addpoly(r);
				r->ax = structurex[x][y];
				r->ay = structurey[x][y];
				r->bx = structurex[x-1][y];
				r->by = structurey[x-1][y];
				r->cx = structurex[x-1][y-1];
				r->cy = structurey[x-1][y-1];
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				//dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW);
				dotex(r, &(o->obj), &(o->transmap), aposx[x][y], aposy[x][y],aposx[x-1][y], aposy[x-1][y],aposx[x-1][y-1], aposy[x-1][y-1]);
			}
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y - 1] != NULL && structure[x][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y - 1], structure[x][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->type = 1;
				rb->addpoly(r);
				r->ax = structurex[x][y];
				r->ay = structurey[x][y];
				r->bx = structurex[x-1][y-1];
				r->by = structurey[x-1][y-1];
				r->cx = structurex[x][y-1];
				r->cy = structurey[x][y-1];
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}				
				dotex(r, &(o->obj), &(o->transmap), aposx[x][y], aposy[x][y],aposx[x-1][y-1], aposy[x-1][y-1],aposx[x][y-1], aposy[x][y-1]);
				//dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW,(x) * PIXW, (y - 1) * PIXW);
			}
			/*
			//if(x == 1 && y == 2) {
			if(y - 1 >= 0 && structure[x][y] != NULL && structure[x][y - 1] != NULL && structure[x + 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x][y - 1], structure[x + 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), (x-0) * PIXW, (y-0) * PIXW,(x) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW);
			}
			if(y - 1 >= 0 && structure[x][y] != NULL && structure[x + 1][y - 1] != NULL && structure[x + 1][y] != NULL) {
				r = addpoly(structure[x][y], structure[x + 1][y - 1], structure[x + 1][y]);//getpixel(o->obj, x * PIXW, y * PIXW));
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), (x) * PIXW, (y) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y) * PIXW);
			}
			*/
		}
	}

	for(y = 0; y < 100; y++) {
		for(x = 0; x < 100; x++) {
			if(structure[x][y] != NULL) {
				maxy = y;
				structure[x][y]->x += startx;
				structure[x][y]->y += starty;
			}
		}
	}

	rb->complete();

	if(strcmp(fn, "building.pcx") == 0 || strcmp(fn, "building2.pcx") == 0 || strcmp(fn, "building3.pcx") == 0 || strcmp(fn, "building4.pcx") == 0) {
		for(x = 0; x < 50; x++) {
			for(y = maxy; y > maxy - 5; y--) {
				if(structure[x][y] != NULL) {
					structure[x][y]->levels[1] = false;
					structure[x][y]->levels[5] = false;
					structure[x][y]->levels[11] = false;
					structure[x][y]->levels[12] = false;
					structure[x][y]->level = 4;
				}
			}
		}
	}

	if(fixed) {
		for(x = 0; x < 50; x++) {
			if(structure[x][maxy] != NULL) {
				structure[x][maxy]->fixed = true;
				structure[x][maxy]->draw = false;
			}
		}
	}

	return rb;
}

void addobject(char *fn, char *fnt, float startx, float starty, bool fixed, bool levels[MAXLEVELS], int level, float lmod) {
	int x, y;
	poly *r;
	object *o;
	int v, maxy = 0;
	atom *a;

	o = &(objects[numobjects]);
	numobjects++;
	o->obj = load_bitmap(fn, NULL);
	if(fnt != NULL) {
		o->transmap = load_bitmap(fnt, NULL);
	}
	else {		
		o->transmap = NULL;
	}
	o->origobj = o->obj;

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			v = shouldbeatom(o->obj, x * 10, y * 10);
			if(v != 0) {
				structure[x][y] = addatom(x * 10 + startx, y * 10 + starty, levels, level);
				a = structure[x][y];
				a->draw = false;
				/*
				if(v == 2)
					a->draw2 = false;
				else
					a->draw2 = true;
				*/
				a->bmp = create_bitmap(14, 14);
				clear_to_color(a->bmp, magenta);
				blit(o->obj, a->bmp, x * 10 - 7, y * 10 - 7, 0, 0, 14, 14);
				checktransdeb(a);
				if(!a->transdeb) {
					draw_trans_sprite(a->bmp, debris1, 0, 0);
				}
				else {
					int x, y, r1, g1, b1, r2, g2, b2, rf, gf, bf;
					r2 = 40;
					g2 = 40;
					b2 = 40;
					int dist, gd;
					float al = .5;
					for(x = 0; x < a->bmp->w; x++) {
						for(y = 0; y < a->bmp->h; y++) {
							if(getpixel(a->bmp, x, y) != magenta) {
								r1 = getr(getpixel(a->bmp, x, y));
								g1 = getg(getpixel(a->bmp, x, y));
								b1 = getb(getpixel(a->bmp, x, y));
								dist = r2 - r1;
								gd = al * dist;
								rf = r1 + gd;
								dist = g2 - g1;
								gd = al * dist;
								gf = g1 + gd;
								dist = b2 - b1;
								gd = al * dist;
								bf = b1 + gd;
								putpixel(a->bmp, x, y, makecol16(rf, gf, bf));
							}
						}
					}
					draw_trans_sprite(a->bmp, debriso1, 0, 0);
				}
			}
			else {
				structure[x][y] = NULL;
			}
		}
	}

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				if(x > 0 && structure[x-1][y] != NULL)
					addlink(structure[x][y], structure[x-1][y], 10, STRBP * lmod);
				if(y > 0 && structure[x][y-1] != NULL)
					addlink(structure[x][y], structure[x][y-1], 10, STRBP * lmod);
				
				if(x > 0 && y > 0 && structure[x-1][y-1] != NULL)
					addlink(structure[x][y], structure[x-1][y-1], DIAGRL, DIAGBP * lmod);
				if(x < 99 && y > 0 && structure[x+1][y-1] != NULL)
					addlink(structure[x][y], structure[x+1][y-1], DIAGRL, DIAGBP * lmod);
			}
		}
	}
	
	for(x = 0; x < 99; x++) {
		for(y = 0; y < 99; y++) {
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y] != NULL && structure[x - 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y], structure[x - 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->type = 0;
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW);
			}
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y - 1] != NULL && structure[x][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y - 1], structure[x][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->type = 1;
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW,(x) * PIXW, (y - 1) * PIXW);
			}
			/*
			//if(x == 1 && y == 2) {
			if(y - 1 >= 0 && structure[x][y] != NULL && structure[x][y - 1] != NULL && structure[x + 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x][y - 1], structure[x + 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), (x-0) * PIXW, (y-0) * PIXW,(x) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW);
			}
			if(y - 1 >= 0 && structure[x][y] != NULL && structure[x + 1][y - 1] != NULL && structure[x + 1][y] != NULL) {
				r = addpoly(structure[x][y], structure[x + 1][y - 1], structure[x + 1][y]);//getpixel(o->obj, x * PIXW, y * PIXW));
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), (x) * PIXW, (y) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y) * PIXW);
			}
			*/
		}
	}

	for(y = 0; y < 100; y++) {
		for(x = 0; x < 100; x++) {
			if(structure[x][y] != NULL) {
				maxy = y;
				x = 100;
			}
		}
	}

	if(strcmp(fn, "building.pcx") == 0 || strcmp(fn, "building2.pcx") == 0 || strcmp(fn, "building3.pcx") == 0 || strcmp(fn, "building4.pcx") == 0) {
		for(x = 0; x < 50; x++) {
			for(y = maxy; y > maxy - 5; y--) {
				if(structure[x][y] != NULL) {
					structure[x][y]->levels[1] = false;
					structure[x][y]->levels[5] = false;
					structure[x][y]->levels[11] = false;
					structure[x][y]->levels[12] = false;
					structure[x][y]->level = 4;
				}
			}
		}
	}

	if(fixed) {
		for(x = 0; x < 50; x++) {
			if(structure[x][maxy] != NULL) {
				structure[x][maxy]->fixed = true;
				structure[x][maxy]->draw = false;
			}
		}
	}
}

rigidbody *addrigidobject(char *fn, float startx, float starty, bool fixed, bool levels[MAXLEVELS], int level, float rm, float ram, float gmult, float bpmult) {
	int x, y;
	poly *r;
	object *o;
	int v, maxy = 0;
	atom *a;
	rigidbody *rb;
	float *structurex[100][100];
	float *structurey[100][100];

	o = &(objects[numobjects]);
	numobjects++;
	//fprintf(debug, "o:%i\n", o->obj);
	o->obj = load_bitmap(fn, NULL);
	o->transmap = NULL;
	//fprintf(debug, "o:%i\n", o->obj);
	o->origobj = o->obj;

	rb = addrigidbody(rm, ram, gmult);

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			v = shouldbeatom(o->obj, x * 10, y * 10);
			if(v != 0) {
				structure[x][y] = addatom(x * 10 + startx, y * 10 + starty, levels, level);
				a = structure[x][y];
				rb->addatom(a);
				structurex[x][y] = &(rb->polylistx[rb->mynumpolys]);
				structurey[x][y] = &(rb->polylisty[rb->mynumpolys]);
				rb->mynumpolys++;
				if(v == 2) {
					a->draw = false;
				}
				a->bmp = create_bitmap(14, 14);
				clear_to_color(a->bmp, magenta);
				blit(o->obj, a->bmp, x * 10 - 7, y * 10 - 7, 0, 0, 14, 14);
				checktransdeb(a);
				if(!a->transdeb) {
					BITMAP *tmp;
					tmp = load_bitmap("debris1.tga", NULL);
					draw_trans_sprite(a->bmp, tmp, 0, 0);
				}
				else {
					int x, y, r1, g1, b1, r2, g2, b2, rf, gf, bf;
					r2 = 40;
					g2 = 40;
					b2 = 40;
					int dist, gd;
					float al = .5;
					for(x = 0; x < a->bmp->w; x++) {
						for(y = 0; y < a->bmp->h; y++) {
							if(getpixel(a->bmp, x, y) != magenta) {
								r1 = getr(getpixel(a->bmp, x, y));
								g1 = getg(getpixel(a->bmp, x, y));
								b1 = getb(getpixel(a->bmp, x, y));
								dist = r2 - r1;
								gd = al * dist;
								rf = r1 + gd;
								dist = g2 - g1;
								gd = al * dist;
								gf = g1 + gd;
								dist = b2 - b1;
								gd = al * dist;
								bf = b1 + gd;
								putpixel(a->bmp, x, y, makecol16(rf, gf, bf));
							}
						}
					}
					draw_trans_sprite(a->bmp, debriso1, 0, 0);
				}
			}
			else {
				structure[x][y] = NULL;
			}
		}
	}

	rb->complete();

	for(x = 0; x < 100; x++) {
		for(y = 0; y < 100; y++) {
			if(structure[x][y] != NULL) {
				if(x > 0 && structure[x-1][y] != NULL)
					addlink(structure[x][y], structure[x-1][y], 10, STRBP * bpmult);
				if(y > 0 && structure[x][y-1] != NULL)
					addlink(structure[x][y], structure[x][y-1], 10, STRBP * bpmult);
				if(x > 0 && y > 0 && structure[x-1][y-1] != NULL)
					addlink(structure[x][y], structure[x-1][y-1], DIAGRL, DIAGBP * bpmult);
				if(x < 99 && y > 0 && structure[x+1][y-1] != NULL)
					addlink(structure[x][y], structure[x+1][y-1], DIAGRL, DIAGBP * bpmult);
			}
		}
	}
	
	rb->mynumpolys = 0;
	for(x = 0; x < 99; x++) {
		for(y = 0; y < 99; y++) {
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y] != NULL && structure[x - 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y], structure[x - 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->ax = structurex[x][y];
				r->ay = structurey[x][y];
				r->bx = structurex[x-1][y];
				r->by = structurey[x-1][y];
				r->cx = structurex[x-1][y-1];
				r->cy = structurey[x-1][y-1];
				rb->addpoly(r);
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW);
			}
			if(x - 1 >= 0 && y - 1 >= 0 && structure[x][y] != NULL && structure[x - 1][y - 1] != NULL && structure[x][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x - 1][y - 1], structure[x][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->ax = structurex[x][y];
				r->ay = structurey[x][y];
				r->bx = structurex[x-1][y-1];
				r->by = structurey[x-1][y-1];
				r->cx = structurex[x][y-1];
				r->cy = structurey[x][y-1];
				rb->addpoly(r);
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x - 1) * PIXW, (y - 1) * PIXW,(x) * PIXW, (y - 1) * PIXW);
			}
			//if(x == 1 && y == 2) {
			if(y - 1 >= 0 && structure[x + 1][y] == NULL && structure[x][y] != NULL && structure[x][y - 1] != NULL && structure[x + 1][y - 1] != NULL) {
				r = addpoly(structure[x][y], structure[x][y - 1], structure[x + 1][y - 1]);//getpixel(o->obj, x * PIXW, y * PIXW));				
				r->ax = structurex[x][y];
				r->ay = structurey[x][y];
				r->bx = structurex[x][y-1];
				r->by = structurey[x][y-1];
				r->cx = structurex[x+1][y-1];
				r->cy = structurey[x+1][y-1];
				rb->addpoly(r);
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), &(o->transmap), (x-0) * PIXW, (y-0) * PIXW,(x) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW);
			}
			if(y - 1 >= 0 && structure[x][y - 1] == NULL && structure[x][y] != NULL && structure[x + 1][y - 1] != NULL && structure[x + 1][y] != NULL) {
				r = addpoly(structure[x][y], structure[x + 1][y - 1], structure[x + 1][y]);//getpixel(o->obj, x * PIXW, y * PIXW));
				r->ax = structurex[x][y];
				r->ay = structurey[x][y];
				r->bx = structurex[x+1][y-1];
				r->by = structurey[x+1][y-1];
				r->cx = structurex[x+1][y];
				r->cy = structurey[x+1][y];
				rb->addpoly(r);
				if(r->a->draw == false && r->b->draw == false && r->c->draw == false) {
					r->trans = true;
				}
				dotex(r, &(o->obj), &(o->transmap), (x) * PIXW, (y) * PIXW,(x + 1) * PIXW, (y - 1) * PIXW,(x + 1) * PIXW, (y) * PIXW);
			}
		}
	}

	for(y = 0; y < 100; y++) {
		for(x = 0; x < 100; x++) {
			if(structure[x][y] != NULL) {
				maxy = y;
				x = 100;
			}
		}
	}

	if(strcmp(fn, "building.pcx") == 0) {
		for(x = 0; x < 50; x++) {
			for(y = maxy; y > maxy - 5; y--) {
				if(structure[x][y] != NULL) {
					structure[x][y]->levels[1] = false;
					structure[x][y]->level = 4;
				}
			}
		}
	}

	if(fixed) {
		for(x = 0; x < 50; x++) {
			if(structure[x][maxy] != NULL) {
				structure[x][maxy]->fixed = true;
				structure[x][maxy]->draw = false;
			}
		}
	}

	return rb;
}

void addbox() {
	bool levels[MAXLEVELS];
	for(int i = 0; i < MAXLEVELS; i++) {
		levels[i] = true;
	}
	levels[0] = false;
	//levels[1] = false;
	
	addobject("building.pcx", "buildingt.tga", 200, 200, false, levels, 2, 1);
}

void physics_initialize() {
	//thold = create_bitmap(15, 15);
	thold = create_bitmap(20, 20);
	tmp = create_bitmap_ex(32, 40, 40);
	clear_to_color(thold, 0);
}

void drawatoms() {
	int i;
	atom *a;
		
	a = &(atoms[0]);
	for(i = 0; i < numatoms; i++) {
		if(a->draw && a->on) {
			putpixel(buf, a->x, a->y, a->color);
		}
		a++;
	}
}

void drawlinks() {
	int i;
	link *l;

	l = &(links[0]);
	for(i = 0; i < numlinks; i++) {
		if(l->on && l->draw && ((l->a->x > lx && l->a->x < rx) || (l->b->x > lx && l->b->x < rx))) {
			line(buf, l->a->x, l->a->y, l->b->x, l->b->y, l->color);
			l->drew = true;
		}
		l++;
	}
}

void cleanline(BITMAP *bmp, int x, int y, int d) {
	putpixel(buf, x, y, getpixel(bg, x, y));
}

void eraselinks() {
	link *l;
	int i;
	
	l = &(links[0]);
	for(i = 0; i < numlinks; i++) {
		if(l->drew && l->draw && l->on) {
			do_line(buf, l->a->x, l->a->y, l->b->x, l->b->y, 0, cleanline);
			l->drew = false;
		}
		l++;
	}
}

/*
void eraselinks() {
	int i;
	link *l;

	l = &(links[0]);
	for(i = 0; i < numlinks; i++) {
		if(l->on && l->draw) {
			line(buf, l->a->x, l->a->y, l->b->x, l->b->y, black);
		}
		l++;
	}
}
*/

void drawpolys() {
	poly *p;
	int i;

	p = &(polys[0]);

	for(i = 0; i < numpolys; i++) {
		if(p->on && ((p->a->x > lx && p->a->x < rx) || (p->b->x > lx && p->b->x < rx) || (p->c->x > lx && p->c->x < rx))) {
			if(p->trans == false && 0
				//|| 1
				) {
				
				p->v1->x = *p->ax;
				p->v1->y = *p->ay;
				p->v2->x = *p->bx;
				p->v2->y = *p->by;
				p->v3->x = *p->cx;
				p->v3->y = *p->cy;
				
				//draw_sprite(buf, p->tmap, 50, 50);

				triangle3d_f(buf, POLYTYPE_ATEX, *(p->tmap), p->v1, p->v2, p->v3);
			}
			else {
				clear_to_color(thold, magenta);

				double lowx, lowy;
				
				lowx = findlow(*p->ax, *p->bx, *p->cx);
				lowy = findlow(*p->ay, *p->by, *p->cy);
				
				p->v1->x = *p->ax - lowx;
				p->v1->y = *p->ay - lowy;

				p->v2->x = *p->bx - lowx;
				p->v2->y = *p->by - lowy;

				p->v3->x = *p->cx - lowx;
				p->v3->y = *p->cy - lowy;

				triangle3d_f(thold, POLYTYPE_ATEX, *(p->tmap), p->v1, p->v2, p->v3);
				draw_sprite(buf, thold, lowx, lowy);
			}
			p->drew = true;
		}
		p++;
	}
}

void erasepolys() {
	int lowx, lowy, highx, highy;
	poly *p;
	int i;

	p = &(polys[0]);

	for(i = 0; i < numpolys; i++) {
		if(p->on && p->drew) {
			lowx = findlow(*p->ax, *p->bx, *p->cx);
			lowy = findlow(*p->ay, *p->by, *p->cy);
			/*
			lowx = findlow(p->a->x, p->b->x, p->c->x);
			lowy = findlow(p->a->y, p->b->y, p->c->y);
			highx = findhigh(p->a->x, p->b->x, p->c->x);
			highy = findhigh(p->a->y, p->b->y, p->c->y);
			*/
			highx = findhigh(*p->ax, *p->bx, *p->cx);
			highy = findhigh(*p->ay, *p->by, *p->cy);

			//rectfill(buf, lowx, lowy, highx, highy, black);
			blit(bg, buf, lowx-1, lowy-1, lowx-1, lowy-1, highx - lowx + 2, highy - lowy + 2);
			p->drew = false;
		}
		p++;
	}
}

void loadstate(char *fn) {	
	FILE *input;

	input = fopen(fn, "rb");

	//fread(&numatoms, sizeof(int), 1, input);
	fread(&atoms, sizeof(atom), MAXATOMS, input);

	fread(&boxes, sizeof(box *), MAXBOXX, input);
	for(int i = 0; i < MAXBOXX; i++) {
		fread(&(boxes[i]), sizeof(box), MAXBOXY, input);
	}

	fread(&rigidbodies, sizeof(rigidbody), MAXRIGIDBODIES, input);

	fclose(input);
}

void savestate(char *fn) {
	FILE *output;
	
	output = fopen(fn, "w+b");

	//fwrite(&numatoms, sizeof(int), 1, output);
	fwrite(&atoms, sizeof(atom), MAXATOMS, output);
	
	//box boxes[MAXBOXX][MAXBOXY];
	fwrite(&boxes, sizeof(box *), MAXBOXX, output);
	for(int i = 0; i < MAXBOXX; i++) {
		fwrite(&(boxes[i]), sizeof(box), MAXBOXY, output);
	}
	
	//rigidbody rigidbodies[MAXRIGIDBODIES];
	fwrite(&rigidbodies, sizeof(rigidbody), MAXRIGIDBODIES, output);

	fclose(output);
}

void reset() {
	int x, y, i;
	for(x = 0; x < MAXBOXX; x++) {
		for(y = 0; y < MAXBOXY; y++) {
			boxes[x][y].count = 0;
			for(int z = 0; z < 50; z++) {
				boxes[x][y].list[z] = NULL;
			}
		}
	}
	for(i = 0; i < numatoms; i++) {
		atoms[i].ix = atoms[i].iy = 0;
		atoms[i].lc = 0;
		atoms[i].fixed = false;
		atoms[i].on = false;
		atoms[i].debris = false;
		destroyatom(&(atoms[i]));
		if(atoms[i].bmp != NULL) {
			destroy_bitmap(atoms[i].bmp);
			atoms[i].bmp = NULL;
		}
		atoms[i].init();
	}
	numatoms = 0;
	for(i = 0; i < numpolys; i++) {
		polys[i].on = false;
		polys[i].init();
	}
	numpolys = 0;
	for(i = 0; i < numlinks; i++) {
		links[i].on = false;
		links[i].init();
	}
	numlinks = 0;
	for(i = 0; i < numrigidbodies; i++) {
		rigidbodies[i].on = false;
		rigidbodies[i].init();
	}
	numrigidbodies = 0;
	for(i = 0; i < numobjects; i++) {
		objects[i].reset();
	}
	numobjects = 0;
	physics_initialize();
}

void eraseatoms() {
	int i;
	atom *a;
	
	a = &(atoms[0]);
	for(i = 0; i < numatoms; i++) {
		if(a->draw && a->on)
			putpixel(buf, a->x, a->y, getpixel(bg, a->x, a->y));
		a++;
	}
}




//Homeostasis:


		/*
		if(time(&timenow) - timestart >= 1) {
			textprintf(buf, font, 10, 20, white, "Framerate: %i", frame);
			textprintf(buf, font, 10, 30, white, "Comp rate: %i", compframe);
			textprintf(buf, font, 10, 40, white, "Compframes: %i", COMPFRAMES);
			if(frame < 20) {
				COMPFRAMES -= 20 - frame;
			}
			else if(frame < COMPFRAMES) {
				COMPFRAMES -= 3;
			}
			if(frame > 30) {
				COMPFRAMES += (frame - 30) / 2;
			}
			if(COMPFRAMES < 1) COMPFRAMES = 1;
			frame = 0;
			compframe = 0;
			timestart = time(&timenow);
		}
		if(compframe % COMPFRAMES == 0) {
			drawatoms();
			blit(buf, screen, 0, 0, 0, 0, 800, 600);
			eraseatoms();
			frame++;
		}
		*/