/******************************************
* Needle - a bitboard based chess engine. *
* (C) 2004 Mikko Nummelin                 *
******************************************/

#define _CONSOLE_C

#include "needle.h"

char *n_strtok_r (char *s, const char *delim, char **save_ptr);

Movelist all_moves_list1,legal_moves_list1;

void print_board(Board *brd){
	int i;
	for(i=077;i>=0;i--){
		if((i&7)==7)
			printf("\n   +---+---+---+---+---+---+---+---+\n %1d |",
				((i&070)>>3)+1);
		if(((((i&070)>>3)+(i&7))&1)==0){
			printf(" %c ",testsquare(brd,square_for_bit(i)));
		} else {
			if(testsquare(brd,square_for_bit(i))==' '){
				printf("...");
			} else {
				printf(".%c.",testsquare(brd,square_for_bit(i)));
			}
		}
		printf("|");
	}
	printf("\n   +---+---+---+---+---+---+---+---+\n");
	printf("     a   b   c   d   e   f   g   h\n\n");
	fflush(stdout);
}

void console(void){
	Board brd;
	int i,value;
	char commandstring[0x100],*filename,
		FEN_string[0x100],*ptrptr,best_move[6];
	PVlist principal_variation;
	FILE *fp;
	Piececalc pc;

	all_moves_list1.size=0;
	legal_moves_list1.size=0;
	reset_engine_variables();

	/* Forces clock type to be STMOVE in console */
	evars.flags &= ~CONVENTIONAL;
	evars.flags &= ~INCREMENTAL;
	evars.flags |= STMOVE;

	alloc_hashtable(15,3);
	clear_hashtable();
	init_opening_book();
	reset_board(&brd);
	write_position(&brd,&(evars.ntb));

	if(is_check(&brd)){
		generate_check_evasions(&brd,&all_moves_list1);
	} else {
		generate_moves(&brd,&all_moves_list1);
	}

	construct_legal_movelist(&brd,&all_moves_list1,&legal_moves_list1);
	print_board(&brd);
	printf("> ");fflush(stdout);
	fgets(commandstring,0xf0,stdin);
	replace_newline(commandstring);
	while((commandstring[0]!='q')&&(commandstring[0]!='Q')){
		if(commandstring[0]=='p'){
			print_board(&brd);
		}
		if(commandstring[0]=='l'){
			print_movelist_moves(&legal_moves_list1);
		}
		if((commandstring[0]>='a')&&(commandstring[0]<='h')&&
			(commandstring[1]>='1')&&(commandstring[1]<='8')){
			i=make_move_from_list(&brd,&legal_moves_list1,commandstring);
			if(i!=0){
				printf("Illegal move.\n");fflush(stdout);
			} else {
				write_move(&(evars.ntb),commandstring);
				write_position(&brd,&(evars.ntb));
				if(is_check(&brd)){
						generate_check_evasions(&brd,&all_moves_list1);
					} else {
						generate_moves(&brd,&all_moves_list1);
				}
				construct_legal_movelist(&brd,
					&all_moves_list1,&legal_moves_list1);
				if(legal_moves_list1.size==0){
					if(is_check(&brd)){
						printf("Checkmate.\n");
					} else {
						printf("Stalemate.\n");
					}
				}
				if(is_threefold_repetition(&(evars.ntb),
					NULL,brd.half_moves)){
					printf("Threefold repetition.\n");
				}
			}
		}
		if(!strncmp(commandstring,"st",2)){
			evars.st=atoi(&(commandstring[3]));
			printf("Search time is now %d seconds.\n",evars.st);
		}
		if(!strncmp(commandstring,"sd",2)){
			evars.sd=atoi(&(commandstring[3]));
			printf("Maximum search depth is now %d plies.\n",evars.sd);
		}
		if(!strncmp(commandstring,"hint",4)){
			best_move[0]=0;
			value=iterativedeep(&brd,32,best_move,&principal_variation);
			printf("Value: %d\n",value);
			printf("Hint : %s\n",best_move);
			printf("Positions seen: %d\n",evars.positions_seen);
			printf("Principal variation: ");
			print_PVlist(&principal_variation);
			fflush(stdout);
			if(value>=29995) {
				clear_hashtable();
			}
		}
		if(!strncmp(commandstring,"cons",4)){
			printf("%c\n",are_bitboards_consistent(&brd));fflush(stdout);
		}
		if(!strncmp(commandstring,"eval",4)){
			printf("Static evaluation\n=================\n");
			value=evaluate_and_pick_material(&brd,&pc);
			printf("Material:                 %d\n",value);
			value=evaluate_dm(&brd,&pc);
			printf("Development and mobility: %d\n",value);
			value=evaluate_king_safety(&brd,&pc);
			printf("King safety:              %d\n",value);
			value=evaluate_eg_king_safety(&brd,&pc);
			printf("Endgame king safety:      %d\n",value);
			value=evaluate_pawn_structure(&brd,&pc);
			printf("Pawn structure:           %d\n",value);
			value=evaluate_eg_pawn_structure(&brd,&pc);
			printf("Endgame pawn structure:   %d\n",value);
			value=evaluate_for_midgame(&brd,&pc);
			printf("Midgame value:            %d\n",value);
			value=evaluate_for_endgame(&brd,&pc);
			printf("Endgame value:            %d\n",value);
			value=evaluate(&brd);
			printf("Actually computed score:  %d\n",value);
			fflush(stdout);
		}
		if(!strncmp(commandstring,"clearht",7)){
			clear_hashtable();
			printf("Hashtable cleared for request.\n");
		}
		if(!strncmp(commandstring,"export",6)){
			filename=n_strtok_r(commandstring," ",&ptrptr);
			filename=n_strtok_r(NULL," ",&ptrptr);
			fp=fopen(filename,"wb");
			export_fen(&brd,FEN_string);
			fprintf(fp,"%s\n",FEN_string);
			fclose(fp);
			printf("Position exported to: %s\n",filename);fflush(stdout);
		}
		if(!strncmp(commandstring,"import",6)){
			filename=n_strtok_r(commandstring," ",&ptrptr);
			filename=n_strtok_r(NULL," ",&ptrptr);
			fp=fopen(filename,"rb");
			if(fp){
				fgets(FEN_string,0xff,fp);
				fclose(fp);
				import_fen(&brd,FEN_string);
				init_notebook(&(evars.ntb));
				write_position(&brd,&(evars.ntb));
				if(is_check(&brd)){
					generate_check_evasions(&brd,&all_moves_list1);
				} else {
					generate_moves(&brd,&all_moves_list1);
				}
				construct_legal_movelist(&brd,
					&all_moves_list1,&legal_moves_list1);
				printf("Position imported from: %s\n",filename);fflush(stdout);
			} else {
				printf("Error: File '%s' does not exist\n",filename);fflush(stdout);
			}
		}
		if(!strncmp(commandstring,"reverse",7)){
			reverse(&brd,&(evars.ntb),atoi(&(commandstring[8])));
			if(is_check(&brd)){
				generate_check_evasions(&brd,&all_moves_list1);
			} else {
				generate_moves(&brd,&all_moves_list1);
			}
			construct_legal_movelist(&brd,
			&all_moves_list1,&legal_moves_list1);
		}
		if(!strncmp(commandstring,"forward",7)){
			forward(&brd,&(evars.ntb),atoi(&(commandstring[8])));
			if(is_check(&brd)){
				generate_check_evasions(&brd,&all_moves_list1);
			} else {
				generate_moves(&brd,&all_moves_list1);
			}
			construct_legal_movelist(&brd,
			&all_moves_list1,&legal_moves_list1);
		}
		if(!strncmp(commandstring,"notebook",8)){
			print_notebook_contents(&(evars.ntb));
		}
		printf("> ");fflush(stdout);
		fgets(commandstring,0xf0,stdin);
		replace_newline(commandstring);
	}
	free_hashtable();
	free_opening_book();
}
