#include <stdio.h>
#include <fcntl.h>
#include <sys/stat.h>

typedef enum {OPENING=0, MIDDLE, ENDING, MATING} GameStage;
#define __COEFFS_PER_STAGE__ (__TOTAL_COEFFS__/(MATING+1))

typedef int etype;
#include "../eval.h"
#include "../names.h"

#define READ_COEFFS 0
#define ZERO 1


char *stage_name[] = {"OPENING", "MIDDLE", "ENDING", "MATING"};
etype *coefficients;
etype total_coefficients[__TOTAL_COEFFS__];


static void p_coeff_vector(struct coefficient_name *cn, FILE *large, FILE *small)
{
	int x;
	fprintf(large,"/* %s */\n", cn->name);
	if (small)
		fprintf(small,"/* %s */\n", cn->name);
	for (x=0; x<(cn+1)->index - cn->index; x++) {
		fprintf(large,"%7d,", coefficients[cn->index + x]);
		if (small)
			fprintf(small,"%7d,", coefficients[cn->index + x]/100);
	}
	fprintf(large,"\n");
	if (small)
		fprintf(small,"\n");
}

static void p_coeff_array(struct coefficient_name *cn, FILE *large, FILE *small)
{
	int x;
	fprintf(large,"/* %s */\n", cn->name);
	if (small)
		fprintf(small,"/* %s */\n", cn->name);
	for (x=0; x<(cn+1)->index - cn->index; x++) {
		fprintf(large,"%7d,", coefficients[cn->index + x]);
		if (small)
			fprintf(small,"%7d,", coefficients[cn->index + x]/100);
		if ((x+1)%10 == 0) {
			fprintf(large, "\n");
			if (small)
				fprintf(small, "\n");
		}
	}
	fprintf(large,"\n");
	if (small)
		fprintf(small,"\n");
}


static void p_coeff_board(struct coefficient_name *cn, FILE *large, FILE *small)
{
	int x, y;
	fprintf(large,"/* %s */\n", cn->name);
	if (small)
		fprintf(small,"/* %s */\n", cn->name);
	for (y=0; y<8; y++) {
		for (x=0; x<8; x++) {
			fprintf(large,"%7d,", coefficients[cn->index + x + y*8]);
			if (small) 
				fprintf(small,"%7d,", coefficients[cn->index + x + y*8]/100);
		}
		fprintf(large,"\n");
		if (small)
			fprintf(small,"\n");
	}
}

static void p_coeff_half_board(struct coefficient_name *cn, FILE *large, FILE *small)
{
	int x, y;
	fprintf(large,"/* %s */\n", cn->name);
	if (small)
		fprintf(small,"/* %s */\n", cn->name);
	for (y=0; y<8; y++) {
		for (x=0; x<4; x++) {
			fprintf(large,"%7d,", coefficients[cn->index + x + y*4]);
			if (small)
				fprintf(small,"%7d,", coefficients[cn->index + x + y*4]/100);
		}
		fprintf(large,"\n");
		if (small)
			fprintf(small,"\n");
	}
}

main()
{
        struct stat st;
        struct coefficient_name *cn;
        FILE *large, *small;
	int i, fd;
	char *coeffs_file = "coeffs.dat";

	large = (FILE *)fopen("large_coeffs.h", "w");
	small = (FILE *)fopen("small_coeffs.h", "w");

	if (large == NULL) {
		exit(1);
        }

	if (READ_COEFFS) {
		fd = open("coeffs.dat", O_RDONLY);
		if (fd == -1) {
			printf("Failed to open %s\n", coeffs_file);
			exit(1);
		}
	
		if (fstat(fd, &st) != 0 &&                   
		    st.st_size != __TOTAL_COEFFS__*sizeof(total_coefficients[0])) {
			printf("%s is corrupt\n", coeffs_file);
			exit(1);
		}

		if (read(fd, (char *)total_coefficients,st.st_size) != st.st_size) {
			printf("failed to read coefficients\n");
			close(fd);
			exit(1);
		}

		printf("Loaded coefficients from %s\n", coeffs_file);
		close(fd);
	}

	if (ZERO)
		memset(total_coefficients, 0, 
		       __TOTAL_COEFFS__*sizeof(total_coefficients[0]));

        fprintf(large, "etype orig_coefficients[] = {\n");
	if (small)
		fprintf(small, "etype orig_coefficients[] = {\n");
	for (i=OPENING; i<=MATING; i++) {
		fprintf(large, "\n/* %%%s%% */\n", stage_name[i]);
		if (small)
			fprintf(small, "\n/* %%%s%% */\n", stage_name[i]);
		cn = &coefficient_names[0];
		coefficients = 	total_coefficients + i*__COEFFS_PER_STAGE__;
		while (cn->name) {
			int n = cn[1].index - cn[0].index;
			if (n == 1) {
				fprintf(large, "/* %s */ %d,\n", cn[0].name, 
					coefficients[cn[0].index]);
				if (small) 
					fprintf(small, "/* %s */ %d,\n", cn[0].name, 
						coefficients[cn[0].index]/100);
			} else if (n == 64) {
				p_coeff_board(cn,large,small);
			} else if (n == 32) {
				p_coeff_half_board(cn,large,small);
			} else if (n % 10 == 0) {
				p_coeff_array(cn,large,small);
			} else {
				p_coeff_vector(cn,large,small);
			}
			cn++;
		}
	}

        fprintf(large, "};\n");
	if (small)
		fprintf(small, "};\n");
        fclose(large);
	if (small)
		fclose(small);

        return;
}
  
