#include "plane.h"
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include <limits.h>

#define MAX_DEPTH 100
static int iterations = 0;

static int state_is_invalid(state_t *s) {
    int plane_tire_y;
    int yyy,xxx;

    if (!s->upsidedown) {
	yyy = 5;
	xxx = 5;
    } else {
	yyy = -5;
	xxx = 5; 
    }
    
    if (s->y < 0) {
	return 1;
    }
    plane_tire_y = (s->y) + (((-xxx*sinit[s->angle>>8]+yyy*cosinit[s->angle>>8]+128)>>8)<<8) + 256;
    if (plane_tire_y >= (AIRFIELD_Y<<8) && !s->on_airfield) {
	return 1;
    }

    if (s->x < 10<<8) {
	return 1;
    }
    if (s->x > 1000<<8) {
	return 1;
    }

    if (s->frame > MAX_DEPTH) {
	return 1;
    }

    return 0;
}

static int state_is_win(state_t *s) {
    if (s->on_airfield && s->speed == 0) {
	return 1;
    }
    return 0;
}

static void state_init(state_t *s) {
    s->frame = 0;
    s->x = 121<<8;
    s->y = 170<<8;
    s->speed = 1700;
    s->angle = 0;
    s->upsidedown = 0;
    s->plane = 0;
    s->bombs = 0;
    s->ammo = 0;
    s->gas = 24*20;
    s->on_airfield = 1;
    s->was_on_airfield = 0;
    s->in.power = 0;
    s->in.up = 0;
    s->in.down = 0;
    s->score = INT_MAX;
}

#if 0
static int test1(void) {
    state_t s;
    input_t in;

    state_init(&s);
    in.up = in.down = in.power = 0;

    for (;;) {
	state_print(&s);
	if (state_is_invalid(&s)) {
	    printf("reached invalid state\n");
	    return 0;
	}
	if (state_is_win(&s)) {
	    printf("reached winning state\n");
	    return 0;
	}
	update_state(&s, &in);
    }
    return 0;
}
#endif

static void state_score(state_t *s) {
    if (s->on_airfield) {
	s->score = s->speed;
    } else {
	s->score = (AIRFIELD_Y<<8) - s->y;
	if (s->x < AIRFIELD_X1) {
	    s->score += AIRFIELD_X1 - s->x;
	} else if (s->x > AIRFIELD_X2) {
	    s->score += s->x - AIRFIELD_X2;
	}	    
    }
    
}

static int state_compare(state_t *s1, state_t *s2) {
    return s1->score - s2->score;
}

static int can_land(state_t *s) {
    int i;
    state_t tmp_s[8];
    input_t in;

    if ((iterations++ & 0xfffff) == 0) {
	printf("(iter %d) ", iterations);
	state_print(s);
    }

    if (state_is_invalid(s)) {
	return 0;
    }
    if (state_is_win(s)) {
	return 1;
    }

    for (i = 0; i < (1<<3); i++) {
	in.up = i & 1;
	in.down = (i>>1) & 1;
	in.power = (i>>2) & 1;
	memcpy(&tmp_s[i], s, sizeof(*s));
	update_state(&tmp_s[i], &in);
	state_score(&tmp_s[i]);
    }

    qsort(&tmp_s[0], 8, sizeof(tmp_s[0]),
	  state_compare);
    
    for (i = 0; i < (1<<3); i++) {
	if (can_land(&tmp_s[i])) {
	    state_print(&tmp_s[i]);
	    return 1;
	}
    }
    return 0;
}

int main(int argc, char *argv[]) {
    state_t s;
    int ret;
    
    state_init(&s);
    ret = can_land(&s);
    printf("can_land returned %d after %d iterations\n", ret, iterations);
    return !ret;
}

