/* Greg's random artifact generator (randart) */
#define VERSION "0.6.0"

#include <stdio.h>
#include <string.h>
#include <stdlib.h>
#include <time.h>
#include "angband.h"

extern cptr k_info_flags1[];
extern cptr k_info_flags2[];
extern cptr k_info_flags3[];
extern int randart_verbose;

#define A_INFO_TXT "a_info.txt"
#define A_INFO_RND "a_info.rnd"
#define BUFLEN 1024
#define MAX_NAMES 512
#define MAX_TRIES 200

void usage (void);
int do_randart (u32b seed);
int write_a_info (u32b seed);
void copy_a_to_o (int a_idx, object_type *);
void dump_flags (FILE *, const artifact_type *);

#define abs(x)	((x) > 0 ? (x) : (-(x)))

int main (int argc, char *argv[])
{
	int rc;
	char path[1024];
	u32b randart_seed;
	bool have_seed = FALSE;

	if (argc > 1)
	{
		while (--argc)
		{
			char *arg = *++argv;
			if (arg[0] != '-') usage();
			switch (arg[1])
			{
				case 'v': randart_verbose = 1;
					  break;
				case 's': randart_seed = (u32b) atol (arg + 2);
					  have_seed = TRUE;
					  break;
				default:  usage();
			}
		}
	}

	/* Prepare to use the Angband ?_info parsing routines. */
	strcpy (path, DEFAULT_PATH);
	init_file_paths (path);

	if ((rc = init_a_info()) != 0) return rc;
	if ((rc = init_k_info()) != 0) return rc;

	if (!have_seed) randart_seed = time (NULL);
	if ((rc = do_randart (randart_seed)) != 0) return rc;

	printf ("Writing to 'a_info.rnd'.\n");
	if ((rc = write_a_info (randart_seed)) != 0) return rc;

	return 0;
}

void usage (void)
{
	fprintf (stderr, "usage: randart [-v] [-sSEED]\n");
	exit (1);
}

int write_a_info (u32b randart_seed)
{
	FILE *f;
	int i;
	time_t tt;
	char *timestr;

	if ((f = fopen (A_INFO_RND, "w")) == NULL)
	{
		fprintf (stderr, "Cannot create '" A_INFO_RND "'.\n");
		return 1;
	}

	/* Write header information. */
	fprintf (f, "# Random a_info file generated by randart version "
		    VERSION "\n");
	time(&tt);
	timestr = ctime (&tt);
	if (timestr) fprintf (f, "# Generation time: %s", timestr);
	fprintf (f, "# Random seed: %lu\n", (unsigned long) randart_seed);
	fprintf (f, "V:%d.%d.%d\n\n",
		a_head->v_major, a_head->v_minor, a_head->v_patch);

	/* Write each artifact's "paragraph". */
	for (i = 1; i < MAX_A_IDX; i++)
	{
		artifact_type *a_ptr = &a_info[i];
		object_type ot;
		char buf[80];

		/* Skip unused artifacts. */
		if (a_ptr->tval == 0) continue;

		/* Give some human-readable description. */
		copy_a_to_o (i, &ot);
		object_desc (buf, &ot, 0, 2);
		fprintf (f, "# %s\n", buf);

		fprintf (f, "N:%d:%s\n", i, a_name + a_info[i].name);
		fprintf (f, "I:%d:%d:%d\n",
			a_ptr->tval, a_ptr->sval, a_ptr->pval);
		fprintf (f, "W:%d:%d:%d:%ld\n",
			a_ptr->level, a_ptr->rarity,
			a_ptr->weight, a_ptr->cost);
		fprintf (f, "P:%d:%dd%d:%d:%d:%d\n",
			a_ptr->ac, a_ptr->dd, a_ptr->ds,
			a_ptr->to_h, a_ptr->to_d, a_ptr->to_a);
		dump_flags (f, a_ptr);
	}

	fclose (f);
	return 0;
}

void copy_a_to_o (int a_idx, object_type *o_ptr)
{
	artifact_type *a_ptr = &a_info[a_idx];

	o_ptr->tval = a_ptr->tval;
	o_ptr->sval = a_ptr->sval;
	o_ptr->pval = a_ptr->pval;
	o_ptr->to_h = a_ptr->to_h;
	o_ptr->to_d = a_ptr->to_d;
	o_ptr->to_a = a_ptr->to_a;
	o_ptr->ac = a_ptr->ac;
	o_ptr->dd = a_ptr->dd;
	o_ptr->ds = a_ptr->ds;
	o_ptr->weight = a_ptr->weight;
	o_ptr->k_idx = lookup_kind (o_ptr->tval, o_ptr->sval);
	o_ptr->ident = IDENT_KNOWN;
	o_ptr->name1 = a_idx;
	o_ptr->name2 = 0;
	o_ptr->discount = 0;
	o_ptr->number = 1;
	o_ptr->timeout = 0;
}

/* Write the artifact's flags to our already-opened file.  Each flag will be
   put on a separate line, just because it's easier that way.  All but the
   last flag will have " |" at the end of the line. */
void dump_flags (FILE *f, const artifact_type *a_ptr)
{
	int i;
	u32b f3;
	int already_wrote = 0;

	/* Do a_ptr->flags1, a_ptr->flags2 and a_ptr->flags3 separately */
	for (i = 0; i < 32; i++)
	{
		if (a_ptr->flags1 & ((u32b)1<<i))
		{
			if (already_wrote) fprintf (f, " |\n");
			fprintf (f, "F:%s", k_info_flags1[i]);
			already_wrote = 1;
		}
	}

	for (i = 0; i < 32; i++)
	{
		if (a_ptr->flags2 & ((u32b)1<<i))
		{
			if (already_wrote) fprintf (f, " |\n");
			fprintf (f, "F:%s", k_info_flags2[i]);
			already_wrote = 1;
		}
	}

	/* Special case: don't print out the IGNORE_* flags. */
	f3 = a_ptr->flags3 &
		~(TR3_IGNORE_ACID | TR3_IGNORE_ELEC |
		  TR3_IGNORE_FIRE | TR3_IGNORE_COLD);
	for (i = 0; i < 32; i++)
	{
		if (f3 & ((u32b)1<<i))
		{
			if (already_wrote) fprintf (f, " |\n");
			fprintf (f, "F:%s", k_info_flags3[i]);
			already_wrote = 1;
		}
	}

	fprintf (f, "\n\n");
}
