#include <stdlib.h>
#include "sheep2.h"



STATE *init_state(LEVEL *level)
{
	STATE *state;
	int x, y;

	if (!level) return NULL;

	state = malloc(sizeof(*state));
	if (!state) return NULL;

	state->block = NULL;
	state->blowerarray = NULL;
	state->sheep = NULL;

	state->l = level;

	state->block = malloc(level->h*sizeof(*state->block));
	if (!state->block) goto error;
	for (y = 0; y < level->h; y++) state->block[y] = NULL;
	for (y = 0; y < level->h; y++) {
		state->block[y] = malloc(level->w*sizeof(*state->block[y]));
		if (!state->block[y]) goto error;
		for (x = 0; x < level->w; x++) state->block[y][x] = NULL;
		for (x = 0; x < level->w; x++) {
			BLOCK **blockp = &state->block[y][x];
			int z = level->n_indestructible[y][x] + level->n_full[y][x];
			if (level->topping[y][x]) {
				BLOCK *block = *blockp = malloc(sizeof(*block));
				if (!block) goto error;
				block->type = level->topping[y][x];
				block->z = z;
				block->zv = 0.0f;
				blockp = &block->nextdown;
			}
			while (z > level->n_indestructible[y][x]) {
				BLOCK *block = *blockp = malloc(sizeof(*block));
				if (!block) goto error;
				block->type = BLOCK_FULL;
				block->z = --z;
				blockp = &block->nextdown;
			}
			while (z > 0) {
				BLOCK *block = *blockp = malloc(sizeof(*block));
				if (!block) goto error;
				block->type = BLOCK_INDESTRUCTIBLE;
				block->z = --z;
				blockp = &block->nextdown;
			}
			*blockp = NULL;
		}
	}

	create_blower_array(state);

	state->sheep_left = state->l->n_sheep;
	state->sheep_lost = state->sheep_saved = 0;

	state->blower_next = 0;
	state->blower_time = level->initial_sheep_delay;

	state->px = level->px;
	state->py = level->py;
	state->pz = state->block[level->py][level->px] ?
	            state->block[level->py][level->px]->z + 1 : 0;

	state->pzphase = 0;
	state->pfd = level->pd;
	state->pdisp = 0;
	state->pmd = 0;
	state->pzmd = 0;
	state->pzdisp = 0.0f;
	state->pzv = 0.0f;
	state->pfd_disp = 0.0f;
	state->plookup = 0.0f;

	for (y = 0; y < N_PIPELINE_BLOCKS; y++)
		state->pipeline[y] = new_pipeline_block();

	state->pipeline_disp = 0.0f;

	state->pcount = 0;
	state->watershift = 0;
	state->fade = 128;

	return state;

	error:
	shut_down_state(state);
	return NULL;
}



void shut_down_state(STATE *state)
{
	if (state) {
		if (state->block) {
			int y;
			for (y = 0; y < state->l->h; y++) {
				BLOCK **blockrow = state->block[y];
				if (blockrow) {
					int x;
					for (x = 0; x < state->l->w; x++) {
						BLOCK *block = blockrow[x];
						while (block) {
							BLOCK *next = block->nextdown;
							free(block);
							block = next;
						}
					}
					free(blockrow);
				}
			}
			free(state->block);
		}
		destroy_blower_array(state);
		{
			SHEEP *sheep = state->sheep;
			while (sheep) {
				SHEEP *next = sheep->next;
				free(sheep);
				sheep = next;
			}
		}
		free(state);
	}
}



int update_logic(STATE *state)
{
	state->watershift++;
	update_player(state);
	update_blocks(state);
	return update_sheep(state);
}
