/*
 * EDITOR2.C:
 *
 *      Object, creature, room and player editor routines (cont'd).
 *
 *      Copyright (C) 1991 Brett J. Vickers
 *
 */

#include "mstruct.h"
#include "editor.h"
#include "mtype.h"
#include <time.h>

#ifdef TC
#include <fcntl.h>
#include <stdlib.h>
#include <sys/stat.h>
#endif

void edit_player()
{
	int 		i, x;
	long 		j;
	char		str[256];
	creature	*ply_ptr;

	clearscreen();
	posit(3,20); printf("Enter player name to edit: ");
	getstr(str, "", 80);
	if(!str[0]) return;

	load_ply_from_file(str, &ply_ptr);
	ply_ptr->type = 0;			/* player */

	while(1) {
		clearscreen();
		posit(2,25);  printf("Player: %s",ply_ptr->name);
		posit(3,30);  printf(" 1. Edit name/password");
		posit(4,30);  printf(" 2. Edit level/class/align/stats/race");
		posit(5,30);  printf(" 3. Edit HP/MP/armor/thaco");
		posit(6,30);  printf(" 4. Edit exp/gold/dmg/room");
		posit(7,30);  printf(" 5. Edit proficiencies");
		posit(8,30);  printf(" 6. Edit spells");
		posit(9,30);  printf(" 7. Edit flags");
		posit(10,30); printf(" 8. Edit daily-use variables");
		posit(11,30); printf(" 9. Edit last-time variables");
		posit(12,30); printf("10. Edit 2nd page of last-time");
		posit(13,30); printf("11. Edit 3rd page of last-time");
		posit(14,30); printf("12. Edit quests fulfilled");
		posit(15,30); printf("13. Edit inventory");
		posit(16,30); printf("14. Clear this player");
		posit(17,30); printf("15. Abort this player");
		posit(18,30); printf("16. Back to main menu");
		posit(20,30); printf("Choice: ");

		getnum(&i, 1, 16);

		switch(i) {
		case 1:			/* name */
			clearscreen();
			posit(2,1); printf("Name:");
			posit(3,1); printf("%s",ply_ptr->name);
			posit(5,1); printf("Password: %s",ply_ptr->password);
			posit(3,1); getstr(str, ply_ptr->name, 80);
			strcpy(ply_ptr->name, str);
			posit(5,11); getstr(str, ply_ptr->password, 15);
			strcpy(ply_ptr->password, str);
			break;
		case 2:			/* level/class/align/stats */
			clearscreen();
			posit(2,1); printf("Level: %-3d", ply_ptr->level);
			posit(2,20); printf("Class: %-3d", ply_ptr->class);
			posit(2,40); printf("Align: %-5d", ply_ptr->alignment);
			posit(3,1); printf("  Str: %-2d", ply_ptr->strength);
			posit(3,20); printf("  Dex: %-2d", ply_ptr->dexterity);
			posit(3,40); printf("  Con: %-2d", ply_ptr->constitution);
			posit(4,1); printf("  Int: %-2d", ply_ptr->intelligence);
			posit(4,20); printf("  Pty: %-2d", ply_ptr->piety);
			posit(5,1); printf(" Race: %-3d", ply_ptr->race);
			posit(2,8); getnums(&j, (long)ply_ptr->level, 0L, 127L);
			ply_ptr->level = j;
			posit(2,27); getnums(&j, (long)ply_ptr->class, -127L, 127L);
			ply_ptr->class = j;
			posit(2,47); getnums(&j, (long)ply_ptr->alignment, -30000L, 30000L);
			ply_ptr->alignment = j;
			posit(3,8); getnums(&j, (long)ply_ptr->strength, 0L, 25L);
			ply_ptr->strength = j;
			posit(3,27); getnums(&j, (long)ply_ptr->dexterity, 0L, 25L);
			ply_ptr->dexterity = j;
			posit(3,47); getnums(&j, (long)ply_ptr->constitution, 0L, 25L);
			ply_ptr->constitution = j;
			posit(4,8); getnums(&j, (long)ply_ptr->intelligence, 0L, 25L);
			ply_ptr->intelligence = j;
			posit(4,27); getnums(&j, (long)ply_ptr->piety, 0L, 25L);
			ply_ptr->piety = j;
			posit(5,8); getnums(&j, (long)ply_ptr->race, 0L, 10L);
			ply_ptr->race = j;
			break;
		case 3:			/* HP/MP/Armor/Thac0 */
			clearscreen();
			posit(2,1); printf("   HP: %-5d/%-5d", ply_ptr->hpcur, ply_ptr->hpmax);
			posit(2,30); printf("   MP: %-5d/%-5d", ply_ptr->mpcur, ply_ptr->mpmax);
			posit(3,1); printf("Armor: %-3d", ply_ptr->armor);
			posit(3,30); printf("Thac0: %-3d", ply_ptr->thaco);
			posit(2,8); getnums(&j, (long)ply_ptr->hpcur, 0L, 32000L);
			ply_ptr->hpcur = j;
			posit(2,14); getnums(&j, (long)ply_ptr->hpmax, 0L, 32000L);
			ply_ptr->hpmax = j;
			posit(2,37); getnums(&j, (long)ply_ptr->mpcur, 0L, 32000L);
			ply_ptr->mpcur = j;
			posit(2,43); getnums(&j, (long)ply_ptr->mpmax, 0L, 32000L);
			ply_ptr->mpmax = j;
			posit(3,8); getnums(&j, (long)ply_ptr->armor, -127L, 127L);
			ply_ptr->armor = j;
			posit(3,37); getnums(&j, (long)ply_ptr->thaco, -127L, 127L);
			ply_ptr->thaco = j;
			break;
		case 4:			/* exp/gold/dmg/room */
			clearscreen();
			posit(2,1); printf("Experience: %ld", ply_ptr->experience);
			posit(2,30); printf("  Gold: %ld", ply_ptr->gold);
			posit(3,1); printf("    # Dice: %-5d", ply_ptr->ndice);
			posit(3,30); printf(" Sides: %-5d", ply_ptr->sdice);
			posit(3,60); printf("  Plus: %-5d", ply_ptr->pdice);
			posit(4,1); printf("      Room: %-5d", ply_ptr->rom_num);
			posit(2,13); getnums(&j, (long)ply_ptr->experience, 0L, 1000000L);
			ply_ptr->experience = j;
			posit(2,38); getnums(&j, (long)ply_ptr->gold, 0L, 20000000L);
			ply_ptr->gold = j;
			posit(3,13); getnums(&j, (long)ply_ptr->ndice, 0L, 32000L);
			ply_ptr->ndice = j;
			posit(3,38); getnums(&j, (long)ply_ptr->sdice, 0L, 32000L);
			ply_ptr->sdice = j;
			posit(3,68); getnums(&j, (long)ply_ptr->pdice, 0L, 32000L);
			ply_ptr->pdice = j;
			posit(4,13); getnums(&j, (long)ply_ptr->rom_num, 0L, 32000L);
			ply_ptr->rom_num = j;
			break;
		case 5:			/* proficiencies */
			clearscreen();
			posit(2,1); printf("Proficiencies:");
			posit(3,1); printf("1:%ld", ply_ptr->proficiency[0]);
			posit(3,27); printf("2:%ld", ply_ptr->proficiency[1]);
			posit(3,54); printf("3:%ld", ply_ptr->proficiency[2]);
			posit(4,1); printf("4:%ld", ply_ptr->proficiency[3]);
			posit(4,27); printf("5:%ld", ply_ptr->proficiency[4]);
			posit(6,1); printf("Realms:");
			posit(7,1); printf("1:%ld", ply_ptr->realm[0]);
			posit(7,27); printf("2:%ld", ply_ptr->realm[1]);
			posit(7,54); printf("3:%ld", ply_ptr->realm[2]);
			posit(8,1); printf("4:%ld", ply_ptr->realm[3]);
			posit(3,3); getnums(&j, (long)ply_ptr->proficiency[0], 0L, 1000000L);
			ply_ptr->proficiency[0] = j;
			posit(3,29); getnums(&j, (long)ply_ptr->proficiency[1], 0L, 1000000L);
			ply_ptr->proficiency[1] = j;
			posit(3,56); getnums(&j, (long)ply_ptr->proficiency[2], 0L, 1000000L);
			ply_ptr->proficiency[2] = j;
			posit(4,3); getnums(&j, (long)ply_ptr->proficiency[3], 0L, 1000000L);
			ply_ptr->proficiency[3] = j;
			posit(4,29); getnums(&j, (long)ply_ptr->proficiency[4], 0L, 1000000L);
			ply_ptr->proficiency[4] = j;
			posit(7,3); getnums(&j, (long)ply_ptr->realm[0], 0L, 1000000L);
			ply_ptr->realm[0] = j;
			posit(7,29); getnums(&j, (long)ply_ptr->realm[1], 0L, 1000000L);
			ply_ptr->realm[1] = j;
			posit(7,56); getnums(&j, (long)ply_ptr->realm[2], 0L, 1000000L);
			ply_ptr->realm[2] = j;
			posit(8,3); getnums(&j, (long)ply_ptr->realm[3], 0L, 1000000L);
			ply_ptr->realm[3] = j;
			break;
		case 6:		   	/* spells */
			clearscreen();
			posit(2,10); printf("1");
			posit(2,20); printf("2");
			posit(2,30); printf("3");
			posit(2,40); printf("4");
			posit(2,50); printf("5");
			posit(2,60); printf("6");
			posit(2,70); printf("7");
			posit(7,10); printf("8");
			posit(7,20); printf("9");
			posit(7,30); printf("0");
			posit(7,40); printf("1");
			posit(7,50); printf("2");
			posit(6,30); printf("1");
			posit(6,40); printf("1");
			posit(6,50); printf("1");
			posit(3,1); printf("1234567890123456789012345678901234567890123456789012345678901234567890");
			posit(8,1); printf("1234567890123456789012345678901234567890123456789012345678");
			posit(11,1); printf("Spell #: ");
			posit(12,1); printf("(0 to exit)");
			while(1) {
				for(j=0;j<128;j++)
					str[j] = (ply_ptr->spells[j/8] & 1<<(j%8)) ? '*':'.';
				str[128] = 0; j = str[70];
				str[70] = 0;
				posit(4,1); printf("%s",str);
				str[70] = j;
				posit(9,1); printf("%s",&str[70]);
				posit(11,10); getnum(&j, 0, 128);
				if(!j) break;
				if(ply_ptr->spells[(j-1)/8] & 1<<((j-1)%8))
					ply_ptr->spells[(j-1)/8] &= ~(1<<((j-1)%8));
				else
					ply_ptr->spells[(j-1)/8] |= 1<<((j-1)%8);
			}
			break;			
		case 7:			/* flags */
			clearscreen();
			posit(2,10); printf("1");
			posit(2,20); printf("2");
			posit(2,30); printf("3");
			posit(2,40); printf("4");
			posit(2,50); printf("5");
			posit(2,60); printf("6");
			posit(3,1); printf("1234567890123456789012345678901234567890123456789012345678901234");
			posit(7,1); printf("Flag #: ");
			posit(8,1); printf("(0 to exit)");
			while(1) {
				for(j=0;j<64;j++)
					str[j] = (ply_ptr->flags[j/8] & 1<<(j%8)) ? '*':'.';
				str[64] = 0;
				posit(4,1); printf("%s",str);
				posit(7,9); getnum(&j, 0, 64);
				if(!j) break;
				if(ply_ptr->flags[(j-1)/8] & 1<<((j-1)%8))
					ply_ptr->flags[(j-1)/8] &= ~(1<<((j-1)%8));
				else
					ply_ptr->flags[(j-1)/8] |= 1<<((j-1)%8);
			}
			break;
		case 8:			/* Daily-use variables */
			clearscreen();
			posit(2,1); printf("Daily-use variables:");
			posit(4,10); printf("Max");
			posit(4,20); printf("Current");
			posit(4,30); printf("Last Time");
			for(x=0; x<10; x++) {
				posit(x+5, 2); printf("%2d:",x+1);
				posit(x+5, 10); printf("%d",ply_ptr->daily[x].max);
				posit(x+5, 20); printf("%d",ply_ptr->daily[x].cur);
				posit(x+5, 30); printf("%lu",ply_ptr->daily[x].ltime);
			}
			posit(17,1); printf("Daily #:");
			while(1) {
				posit(17,10); getnum(&x, 0, 10);
				if(!x) break;
				posit(x+4, 10); getnums(&j, (long)ply_ptr->daily[x-1].max, -127L, 127L);
				ply_ptr->daily[x-1].max = j;
				posit(x+4, 20); getnums(&j, (long)ply_ptr->daily[x-1].cur, -127L, 127L);
				ply_ptr->daily[x-1].cur = j;
				posit(x+4, 30); getnums(&j, (long)ply_ptr->daily[x-1].ltime, 0L, 10000000L);
				ply_ptr->daily[x-1].ltime = j;
			}
			break;
		case 9:			/* Last-time variables */
			clearscreen();
			posit(2,1); printf("Last-time variables:");
			posit(4,10); printf("Interval");
			posit(4,20); printf("Lastreset");
			posit(4,30); printf("Misc");
			for(x=0; x<15; x++) {
				posit(x+5, 2); printf("%2d:",x+1);
				posit(x+5, 10); printf("%lu",ply_ptr->lasttime[x].interval);
				posit(x+5, 20); printf("%lu",ply_ptr->lasttime[x].ltime);
				posit(x+5, 30); printf("%-5d",ply_ptr->lasttime[x].misc);
			}
			posit(22,1); printf("Variable #:");
			while(1) {
				posit(22,13); getnum(&x, 0, 15);
				if(!x) break;
				posit(x+4, 10); getnums(&j, (long)ply_ptr->lasttime[x-1].interval, 0L, 1000000000L);
				ply_ptr->lasttime[x-1].interval = j;
				posit(x+4, 20); getnums(&j, (long)ply_ptr->lasttime[x-1].ltime, 0L, 1000000000L);
				ply_ptr->lasttime[x-1].ltime = j;
				posit(x+4, 30); getnums(&j, (long)ply_ptr->lasttime[x-1].misc, 0L, 32000L);
				ply_ptr->lasttime[x-1].misc = j;
			}
			break;
		case 10: 		/* page 2 of lasttime */
			clearscreen();
			posit(2,1); printf("Last-time variables:");
			posit(4,10); printf("Interval");
			posit(4,20); printf("Lastreset");
			posit(4,30); printf("Misc");
			for(x=15; x<30; x++) {
				posit(x-10, 2); printf("%2d:",x+1);
				posit(x-10, 10); printf("%lu",ply_ptr->lasttime[x].interval);
				posit(x-10, 20); printf("%lu",ply_ptr->lasttime[x].ltime);
				posit(x-10, 30); printf("%-5d",ply_ptr->lasttime[x].misc);
			}
			posit(22,1); printf("Variable #:");
			while(1) {
				posit(22,13); getnum(&x, 0, 30);
				if(x<16) break;
				posit(x-11, 10); getnums(&j, (long)ply_ptr->lasttime[x-1].interval, 0L, 1000000000L);
				ply_ptr->lasttime[x-1].interval = j;
				posit(x-11, 20); getnums(&j, (long)ply_ptr->lasttime[x-1].ltime, 0L, 1000000000L);
				ply_ptr->lasttime[x-1].ltime = j;
				posit(x-11, 30); getnums(&j, (long)ply_ptr->lasttime[x-1].misc, 0L, 32000L);
				ply_ptr->lasttime[x-1].misc = j;
			}
			break;
		case 11: 		/* page 3 of lasttime */
			clearscreen();
			posit(2,1); printf("Last-time variables:");
			posit(4,10); printf("Interval");
			posit(4,20); printf("Lastreset");
			posit(4,30); printf("Misc");
			for(x=30; x<45; x++) {
				posit(x-25, 2); printf("%2d:",x+1);
				posit(x-25, 10); printf("%lu",ply_ptr->lasttime[x].interval);
				posit(x-25, 20); printf("%lu",ply_ptr->lasttime[x].ltime);
				posit(x-25, 30); printf("%-5d",ply_ptr->lasttime[x].misc);
			}
			posit(22,1); printf("Variable #:");
			while(1) {
				posit(22,13); getnum(&x, 0, 45);
				if(x<31) break;
				posit(x-26, 10); getnums(&j, (long)ply_ptr->lasttime[x-1].interval, 0L, 1000000000L);
				ply_ptr->lasttime[x-1].interval = j;
				posit(x-26, 20); getnums(&j, (long)ply_ptr->lasttime[x-1].ltime, 0L, 1000000000L);
				ply_ptr->lasttime[x-1].ltime = j;
				posit(x-26, 30); getnums(&j, (long)ply_ptr->lasttime[x-1].misc, 0L, 32000L);
				ply_ptr->lasttime[x-1].misc = j;
			}
			break;
		case 12:		/* quests */
			clearscreen();
			posit(2,10); printf("1");
			posit(2,20); printf("2");
			posit(2,30); printf("3");
			posit(2,40); printf("4");
			posit(2,50); printf("5");
			posit(2,60); printf("6");
			posit(2,70); printf("7");
			posit(7,10); printf("8");
			posit(7,20); printf("9");
			posit(7,30); printf("0");
			posit(7,40); printf("1");
			posit(7,50); printf("2");
			posit(6,30); printf("1");
			posit(6,40); printf("1");
			posit(6,50); printf("1");
			posit(3,1); printf("1234567890123456789012345678901234567890123456789012345678901234567890");
			posit(8,1); printf("1234567890123456789012345678901234567890123456789012345678");
			posit(11,1); printf("Quest #: ");
			posit(12,1); printf("(0 to exit)");
			while(1) {
				for(j=0;j<128;j++)
					str[j] = (ply_ptr->quests[j/8] & 1<<(j%8)) ? '*':'.';
				str[128] = 0; j = str[70];
				str[70] = 0;
				posit(4,1); printf("%s",str);
				str[70] = j;
				posit(9,1); printf("%s",&str[70]);
				posit(11,10); getnum(&j, 0, 128);
				if(!j) break;
				if(ply_ptr->quests[(j-1)/8] & 1<<((j-1)%8))
					ply_ptr->quests[(j-1)/8] &= ~(1<<((j-1)%8));
				else
					ply_ptr->quests[(j-1)/8] |= 1<<((j-1)%8);
			}
			break;
		case 13:		/* edit items */
			edit_items(ply_ptr);
			break;
		case 14:		/* abort */
			clearscreen();
			posit(1,1);
			printf("Are you sure you want to clear it? ");
			getstr(str, "n", 2);
			if(str[0]=='y' || str[0]=='Y') {
				free_crt(ply_ptr);
				ply_ptr = (creature *)malloc(sizeof(creature));
				zero(ply_ptr, sizeof(creature));
			}
			break;
		case 15:		/* Abort */
			free_crt(ply_ptr);
			return;
		case 16:		/* Return to main menu */
			if(!ply_ptr->name[0]) break;
			save_ply_to_file(ply_ptr->name, ply_ptr);
			free_crt(ply_ptr);
			return;
		}
	}
}

void edit_items(ply_ptr)
creature	*ply_ptr;
{
	int 	i, x, error;
	long 	j;
	object	*obj_ptr;
	otag	*op, *ot, *prev;

	while(1) {
		clearscreen();
		posit(5,25);  printf("Player: %s",ply_ptr->name);
		posit(6,30);  printf("1. Add item");
		posit(7,30);  printf("2. Remove item");
		posit(8,30);  printf("3. List items");
		posit(9,30);  printf("4. Back to player menu");
		posit(11,30); printf("Choice: ");
	
		getnum(&i, 1, 4);
	
		switch(i) {
		case 1: 	/* add */
			clearscreen();
			posit(2,1); printf("Enter item number: ");
			getnum(&j, 0, 32000);
			if(load_obj_from_file((int)j, &obj_ptr) < 0)
				free(obj_ptr);
			else {
				ot = (otag *)malloc(sizeof(otag));
				ot->obj = obj_ptr;
				ot->next_tag = 0;
				op = ply_ptr->first_obj;
				if(!op) {
					ply_ptr->first_obj = ot;
					break;
				}
				if(strcmp(op->obj->name,ot->obj->name) >= 0 ||
				   (strcmp(op->obj->name,ot->obj->name)==0 &&
				   op->obj->adjustment > ot->obj->adjustment) ) {
					ot->next_tag = op;
					ply_ptr->first_obj = ot;
					break;
				}
				while(op) {
					if(strcmp(op->obj->name,ot->obj->name) > 0 || 
					  (strcmp(op->obj->name,ot->obj->name)==0 && 
					  op->obj->adjustment > ot->obj->adjustment) ) break;
					prev = op;
					op = op->next_tag;
				}
				ot->next_tag = prev->next_tag;
				prev->next_tag = ot;
			}
			break;
		case 2:
			clearscreen();
			posit(2,1); printf("Delete item #");
			getnum(&i, 0, 90);
			if(!i) break;
			op = ply_ptr->first_obj; x = 1; error = 0;
			while(x <= i) {
				if(!op) {
					error = 1;
					break;
				}
				if(x == i)
					break;
				x++;
				prev = op;
				op = op->next_tag;
			}
			if(error) break;
			if(op == ply_ptr->first_obj) {
				ply_ptr->first_obj = op->next_tag;
				free_obj(op->obj);
				free(op);
			}
			else {
				prev->next_tag = op->next_tag;
				free_obj(op->obj);
				free(op);
			}
			break;
		case 3:			/* list */
			clearscreen();
			op = ply_ptr->first_obj; x = 1;
			while(op) {
				posit(x%24, (x/24>0)?40:1);
				printf("%2d: %s", x, op->obj->name);
				x++;
				op = op->next_tag;
			}
			posit(24,40); printf("Hit Enter:");
			getnum(&x, 0, 0);
			break;
		case 4:
			return;
		}
	}
}

int load_ply_from_file(str, ply_ptr)
char		*str;
creature	**ply_ptr;
{
	int fd;
	long n;
	char file[80];
#ifdef COMPRESS
	char *a_buf, *b_buf;
	int size;
#endif

	*ply_ptr = (creature *)malloc(sizeof(creature));
	if(!*ply_ptr)
		merror("load_from_file", FATAL);
	zero(*ply_ptr, sizeof(creature));

#ifdef TC
	sprintf(file, "%s\\%s", PLAYERPATH, str);
#else
	sprintf(file, "%s/%s", PLAYERPATH, str);
#endif
	fd = open(file, O_RDONLY | O_BINARY, 0);
	if(fd < 0) 
		return(-1);

#ifdef COMPRESS
	a_buf = (char *)malloc(30000);
	if(!a_buf) merror(FATAL, "Memory allocation");
	size = read(fd, a_buf, 30000);
	if(size >= 30000) merror(FATAL, "Player too large");
	if(size < 1) {
		close(fd);
		return(-1);
	}
	b_buf = (char *)malloc(80000);
	if(!b_buf) merror(FATAL, "Memory allocation");
	n = uncompress(a_buf, b_buf, size);
	if(n > 80000) merror(FATAL, "Player too large");
	n = read_crt_from_mem(b_buf, *ply_ptr, 0);
	free(a_buf);
	free(b_buf);
#else
	n = read_crt(fd, *ply_ptr);
	if(n < 0) {
		close(fd);
		return(-1);
	}
#endif

	close(fd);

	return(0);
}

int save_ply_to_file(str, ply_ptr)
char		*str;
creature	*ply_ptr;
{
	int fd;
	long n;
	char file[80];
#ifdef COMPRESS
	char *a_buf, *b_buf;
	int size;
#endif

#ifdef TC
	sprintf(file, "%s\\%s", PLAYERPATH, str);
#else
	sprintf(file, "%s/%s", PLAYERPATH, str);
#endif
	unlink(file);
#ifdef TC
	fd = open(file, O_RDWR | O_CREAT | O_BINARY, S_IWRITE | S_IREAD);
#else
	fd = open(file, O_RDWR | O_CREAT, ACC);
#endif
	if(fd < 0)
		return(-1);

#ifdef COMPRESS
	a_buf = (char *)malloc(80000);
	if(!a_buf) merror(FATAL, "Memory allocation");
	n = write_crt_to_mem(a_buf, ply_ptr, 0);
	if(n > 80000) merror(FATAL, "Player too large");
	b_buf = (char *)malloc(n);
	if(!b_buf) merror(FATAL, "Memory allocation");
	size = compress(a_buf, b_buf, n);
	n = write(fd, b_buf, size);
	free(a_buf);
	free(b_buf);
#else
	n = write_crt(fd, ply_ptr, 0);
	if(n < 0) {
		close(fd);
		return(-1);
	}
#endif

	close(fd);

	return(0);
}
