#include "mathpi.h"
#include "sheep2.h"



static void try_to_move(STATE *state, unsigned char dir)
{
	int x = state->px + xmove[dir];
	int y = state->py + ymove[dir];
	if (x >= 0 && x < state->l->w && y >= 0 && y < state->l->h) {
		BLOCK *bside = state->block[y][x];
		BLOCK *block = state->block[state->py][state->px];
		/* Can we go downhill? */
		if (block && !BLOCK_CAN_SUPPORT(block->type) && (block->type & BLOCK_SLOPE_MASK) == dir && (!bside || bside->z + 2.0f - BLOCK_RAISED < state->pz)) {
			state->pdisp++;
			state->pmd = dir;
			state->pzmd = -1;
			state->pcount = 1;
		} else
		/* Can we go straight? */
		if (!bside || bside->z + 1.0f - BLOCK_RAISED < state->pz) {
			state->pdisp++;
			state->pmd = dir;
			state->pzmd = 0;
			state->pcount = 1;
		} else
		/* Can we go uphill? */
		if (bside && !BLOCK_CAN_SUPPORT(bside->type) && (bside->type & BLOCK_SLOPE_MASK) == (dir^2)) {
			if (bside->z - BLOCK_RAISED < state->pz) {
				state->pdisp++;
				state->pmd = dir;
				state->pzmd = 1;
				state->pcount = 1;
			}
		}
		/* Sorry mate, you're gonna have to dig your way out! */
	}
}



void update_player(STATE *state)
{
	unsigned char l = key[KEY_LEFT];
	unsigned char r = key[KEY_RIGHT];
	unsigned char f = key[KEY_A];
	unsigned char b = key[KEY_Z];
	unsigned char u = key[KEY_DOWN];
	unsigned char d = key[KEY_UP];
	unsigned char p = key[KEY_SPACE];

	if (state->pturndelay == 0) {
		if (l && !r) {
			state->pfd = (state->pfd - 1) & 3;
			state->pfd_disp += M_PI/2.0f;
			state->pturndelay = PTURNDELAY - 1;
		} else if (r && !l) {
			state->pfd = (state->pfd + 1) & 3;
			state->pfd_disp -= M_PI/2.0f;
			state->pturndelay = PTURNDELAY - 1;
		}
	} else if (l || r)
		state->pturndelay--;
	else
		state->pturndelay = 0;

	state->pfd_disp *= 0.94f;

	if (state->pdisp == 0) {
		BLOCK *block = state->block[state->py][state->px];
		float z = block ? ceil(block->z) + BLOCKS_SEPARATED : BLOCK_RAISED;
		if (state->pz + state->pzdisp >= z) {
			state->pzv -= 0.007f;
			state->pzv *= 0.97f;
			state->pzdisp += state->pzv;
			if (state->pz + state->pzdisp < z - 2*BLOCK_RAISED) {
				state->pz = (int)z;
				state->pzv = 0.0f;
				state->pzdisp = 0.0f;
			}
		} else {
			if (p) {
				int x = state->px + xmove[state->pfd];
				int y = state->py + ymove[state->pfd];
				if (x >= 0 && x < state->l->w && y >= 0 && y < state->l->h) {
					BLOCK **blockp = &state->block[y][x];
					BLOCK *block = *blockp;
					if (block ? (BLOCK_CAN_SUPPORT(block->type) &&
						block->z >= state->pz - 1.0 - BLOCK_RAISED &&
						block->z <= state->pz - 1.0 + BLOCK_RAISED) :
						(state->pz == 0))
					{
						if (state->pcount == 0) {
							state->pcount = PDESTROYCOUNT+1; /* So it won't get destroyed */
							block = malloc(sizeof(*block));
							if (block) {
								block->nextdown = *blockp;
								*blockp = block;
								block->type = state->pipeline[0];
								block->z = state->pz;
								block->zv = 0.0f;
								{
									int i;
									for (i = 0; i < N_PIPELINE_BLOCKS-1; i++)
										state->pipeline[i] = state->pipeline[i+1];
									state->pipeline[i] = new_pipeline_block();
									state->pipeline_disp += 1.0f;
								}
							}
						}
					} else {
						while (block && block->z >= state->pz + BLOCK_RAISED) {
							blockp = &block->nextdown;
							block = *blockp;
						}
						if ((block = *blockp) && block->z >= state->pz - BLOCK_RAISED) {
							if (BLOCK_DESTRUCTIBLE(block->type)) {
								if (state->pcount <= PDESTROYCOUNT) {
									if (state->pcount == PDESTROYCOUNT) {
										*blockp = block->nextdown;
										free(block);
									}
									state->pcount++;
								}
							} else state->pcount = PDESTROYCOUNT+1;// else buzz?
						} // else buzz?
					}
				} // else play a buzzing sound? only once!
			} else
				state->pcount = 0;

			if (f && !b)
				try_to_move(state, state->pfd);
			else if (b && !f)
				try_to_move(state, state->pfd ^ 2);
		}
	} else if (++state->pdisp >= PDISP_MAX) {
		state->pdisp = 0;
		state->px += xmove[state->pmd];
		state->py += ymove[state->pmd];
		state->pz += state->pzmd;
	}

	if (u && !d)
		state->plookup += 0.01f*M_PI;
	else if (d && !u)
		state->plookup -= 0.01f*M_PI;
	state->plookup *= 0.96f;

	state->pzphase = (state->pzphase + 1) & (PZPHASE_MAX - 1);

	state->pipeline_disp *= 0.94f;
}
