/
bin/95/
docs/DM/
docs/creatures/
docs/objects/
docs/rooms/
docs/utils/
help/
log/
objmon/ddesc/
player/
post/
rooms/
util/
util/fing/
util/italk/
util/lev-reset/
util/lib/
util/list/
util/msg/
util/tdel/
util/vote/
util/wtfix/
/**************************************************************************
*  Find and fix bad perms in databases.  
*  Version 1.0:  (C) 1996, 1997 Brooke Paul
*  Dedicated to Styx (roy@tesla.tech.cerritos.edu)
*/

#include "mstruct.h"
#include "mextern.h"
#include <stdio.h>
#include <unistd.h>

#ifndef WIN32
	#include <signal.h>
#endif


#define PRINTF(a) write(fd, a, strlen(a))
#define ISSET(p,f)    ((p)->flags[(f)/8] & 1<<((f)%8))

extern int find_crt_slot(), find_obj_slot();
extern void end();

int fd=1, Rlow=1, Rhi=10000, n=0, index, dbm, dbo, ff, changed=0, rnum;

/* OPTIONS:  Set and unset these before compilation to configure */

int verbose=0;  /* indicates verbose output -- WARNING: can be VERY verbose */ 
int cleanup=1;  /* will flush clean _all_ rooms after check */
int writeok=1;  /* permission to alter database, 0=readonly */ 
int spinner=1;  /* little spinner and message window toggle */

main(argc, argv)
int     argc;
char    *argv[];
{
	int  found, y, l, slot=0, dots=0;
	char str[80];
	room    *rom;
	ctag	*cp, *ctemp;
	otag	*op, *otemp;

#ifndef WIN32
	signal(SIGSEGV, end);
#endif 
	clearscreen();
	if(argc>1){
                        if(!isdigit(argv[1][0])){
                                sprintf(str, "Syntax: %s room# or %s\n", argv[0], argv[0]);
                                write(fd, str, strlen(str));
                                exit(0);
                        }
                        Rlow = atoi(argv[1]);
                        if(argv[2])
                                Rhi = atoi(argv[2]);
                        else
                                Rhi = Rlow +1;
        }
	sprintf(str, "", 0);
	posit(0,0); printf("Mordor Database Utility v1.0 (c) 1996\n\n");
	if(cleanup)
		strcat(str, "All rooms will be cleaned.\n");
	if(writeok)
		strcat(str, "All changes will be saved.\n");
	else
		strcat(str, "Readonly mode. Changes not saved.\n");
	write(fd, str, strlen(str));
		posit(8,0); printf("Working ");	
	for(rnum=Rlow; rnum<Rhi; rnum++) {
		n=load_rom_from_file(rnum, &rom);
		if(n<0) 
			continue;
		if(!rom)
			continue;
		if(spinner) {
		dots++;
		if(dots > 4 )
			dots=1;
		spin(dots);
		}
		cp=rom->first_mon;
		while(cp) {
			if(ISSET(cp->crt, MPERMT)) {
				if(verbose) {
				 	sprintf(str, "Room %d has a perm %s.", rnum,cp->crt);
					if(!spinner)
					        write(fd, str, strlen(str)); 
					else
						message(str);
				}
				F_CLR(cp->crt, MPERMT);
                		
			}
			found=0;
			n=find_crt_num(cp->crt);	
			for(y=0; y<=9; y++) {
			if(rom->perm_mon[y].misc==n && n){
					found=1;
					break;
				}	
			}		
			if(!found) {
				if(verbose) {
					sprintf(str, "Room %d has a bad perm creature: %s.", rnum, cp->crt);
					if(!spinner)
						write(fd, str, strlen(str));
					else
						message(str);
				}
				/* add monster to DB */
				if(!n && writeok) {
					slot=0;
					dbm=find_crt_slot();
					op=cp->crt->first_obj;
        				while(op) {
                				l=find_obj_num(op->obj);
                				if(!l) {
                        				sprintf(str, "### Unique object in inventory not saved.");
                        				if(!spinner)
								write(fd,  str, strlen(str));
							else
								message(str);
							op=op->next_tag;   
                        				continue;
                				}	
                				cp->crt->carry[slot]=(long)l;
                				slot++;
                				if(slot>9){
                       		 			sprintf(str, "### Only first 10 objects in inventory saved.");
							if(!spinner)
								write(fd, str, strlen(str));
							else
								message(str);
                        				break;

                				}
       				 	op=op->next_tag;
        				}
					
        				op=cp->crt->first_obj;
        				cp->crt->first_obj=0;
        				while(op) {
                				otemp=op->next_tag;
                				free_obj(op->obj); 
                				free(op);
                				op=otemp;
        				}

					sprintf(str, "%s/m%02d", MONPATH, dbm/MFILESIZE);
       					ff = open(str, O_WRONLY | O_CREAT, ACC);
       					if(ff == -1) {
                				close(ff);
						merror("File open error", FATAL);
                				return(0);
        				}
        				l = lseek(ff, (long)((dbm%MFILESIZE)*sizeof(creature)), 0);
				        l = write(ff, cp->crt, sizeof(creature));
        				if(l < sizeof(creature))
                			merror("write_crt", FATAL);
				        close(ff);
					sprintf(str, "### Creature %d updated for room %d.", dbm, rnum);
					if(!spinner)
						write(fd, str, strlen(str)); 
					else
						message(str);

				} /* writeok */
		/* properly perm monster */
				l=0;
				while(rom->perm_mon[l].misc) {
					l++;        
				}
				if(l>9) {
					sprintf(str, "### Room %d is already full of perm creatures.", rom->rom_num);
					if(!spinner)
						write(fd, str, strlen(str));  
					else
						message(str);
					break;
				}
				changed=1;
				if(!n)
					rom->perm_mon[l].misc=dbm;
				else				
					rom->perm_mon[l].misc=n;

				rom->perm_mon[l].interval=7200;
                	} /* !found */
		cp=cp->next_tag;
			
		}
		l=0;
		while(rom->perm_mon[l].misc && l<10) {
			if(rom->perm_mon[l].interval < 5) {
				sprintf(str, "### Interval fixed on monster %d in room %d.", rom->perm_mon[l].misc, rnum);
				if(!spinner)
					write(fd, str, strlen(str));	
				else
					message(str);
			}
		rom->perm_mon[l].interval=3600;
			l++;
		}								
		op=rom->first_obj;
		while(op) {
			if(ISSET(op->obj, OPERMT)) {
				if(verbose){
                                        sprintf(str, "Room %d has a perm %s.", rnum,op->obj);
                                        if(!spinner)
						write(fd, str, strlen(str)); 
					else
						message(str);
				}
				F_CLR(op->obj,OPERMT);
                        }
                        found=0; 
                	n=find_obj_num(op->obj);
                        for(y=0; y<=9; y++) {
                        	if(rom->perm_obj[y].misc==n && n){
                                        found=1;
                                        break;
                                }
                        }
                        if(!found) {
				if(verbose){
                                	sprintf(str, "Room %d has a bad perm object: %s.", rnum, op->obj);
        				if(!spinner)
                        			write(fd, str, strlen(str)); 
					else
						message(str);
				}
				if(!n && writeok) {
					dbo=find_obj_slot();
					sprintf(str, "%s/o%02d", OBJPATH, dbo/OFILESIZE);
       					ff = open(str, O_WRONLY | O_CREAT, ACC);
       					if(ff == -1) {
                				close(ff);
						merror("File open error", FATAL);
                				return(0);
        				}
        				l = lseek(ff, (long)((dbo%OFILESIZE)*sizeof(object)), 0);
					op->obj->parent_rom = 0;
	       				op->obj->parent_obj = 0;
       					op->obj->first_obj = 0;
       					op->obj->parent_crt = 0;

		        		l = write(ff, op->obj, sizeof(object));
        				if(l < sizeof(object))
		                		merror("write_obj", FATAL);

        				close(ff);
					sprintf(str, "### Object %d updated for room %d.", dbo, rnum);
					if(!spinner)
						write(fd, str, strlen(str)); 
					else
						message(str);
				}
		/* properly perm object */
				l=0;
				while(rom->perm_obj[l].misc) {
					l++;        
					}
					if(l>9) {
						sprintf(str, "### Room %d is already full of perm objects.", rom->rom_num);
						if(!spinner)
							write(fd, str, strlen(str)); 
						else
							message(str);
						break;
					}
					changed=1;
					if(!n) 
						rom->perm_obj[l].misc=dbo;
					else
						rom->perm_obj[l].misc=n;

					rom->perm_obj[l].interval=(long)7200;
                        	}
                	op=op->next_tag;

			} /* !found */
		l=0;
		while(rom->perm_obj[l].misc && l<10) {
			if(rom->perm_obj[l].interval < 5) {
				sprintf(str, "### Interval fixed on object %d in room %d.", rom->perm_obj[l].misc, rnum);
                                if(!spinner)
                                        write(fd, str, strlen(str));
                                else
                                        message(str);
                        }

				rom->perm_obj[l].interval=3600;
			l++;
		}
		if(changed || cleanup) {
			/* flush the room */
			cp=rom->first_mon;
			rom->first_mon=0;
			while(cp) {
				ctemp = cp->next_tag;
				free_crt(cp->crt);
                        	free(cp);

                		cp = ctemp;
        		}
			op = rom->first_obj;
		        rom->first_obj = 0;
        		while(op) {
                		otemp = op->next_tag;
	                        free_obj(op->obj);
        	                free(op);
                                        
	                	op = otemp;
        		}
			if(writeok) {
				if(verbose) {
					sprintf(str, "Saving Room %d.", rnum); 
					if(!spinner)
						write(fd, str, strlen(str)); 
					else
						message(str);
				}
				save_rom_to_file(rnum, rom);
			}		
		}
		if(rom)
		   free_rom(rom);  
		changed=0;
	}
	posit(0,20);
	sprintf(str, "Processed %d rooms.\nDone.", Rhi-Rlow);
	write(fd, str, strlen(str));
	exit(0);
}

int find_obj_num(obj_ptr)   
object  *obj_ptr;
{
        int i;
        object  *obj_src;
                
        for (i=0;i<OMAX;i++) {
                if(load_obj_from_file(i, &obj_src) < 0)
                        continue;
		if(!strcmp(obj_ptr->name, obj_src->name)) {
        			if(obj_src)
		                    free(obj_src);
                            break; 
                }                  
		if(obj_src)
	                free(obj_src);
        }

                                
        if(i<OMAX)
                return(i);
        else            
                return(0);

}
        

int find_crt_num(crt_ptr)
creature  *crt_ptr;
{               
        int i;
        creature  *crt_src;
            
        for (i=0;i<CMAX;i++) {
                if(load_crt_from_file(i, &crt_src) < 0) 
                        continue;
		
		if(!strcmp(crt_ptr->name, crt_src->name)) {
			if(crt_src)
	                        free(crt_src);
                        break;  
		}
		if(crt_src)
	                free(crt_src);
        }
                
        if(i<CMAX)
                return(i);  
        else
                return(0);
        
}

int find_obj_slot()
{
	int i, fd=1;
	char  str[80];
	object obj;

	for(i=2; i<=OMAX; i++) {
		if(load_obj_from_file(i, &obj) < 0)
			break;
	}
	if(verbose) {
		sprintf(str, "Object slot open at %d.", i);
		message(str);
	}
	return(i);
}

int find_crt_slot()
{
	int i;
	char  str[80];
	creature  crt;

	for(i=2; i<=CMAX; i++) {
                if(load_crt_from_file(i, &crt) < 0)
                        break;
	}
	if(verbose) {
		sprintf(str, "Creature slot open at %d.", i);
		message(str);
        }
	return(i);
}
#ifndef WIN32
void end()
{
char str[80];

	sprintf(str, "\n\nCheck DB has encountered an error.\nPlease restart at room %d.\n", rnum);
	write(fd, str, strlen(str));
}
#endif