/* 
 * amazing1
 *
 * Displays a randomly-generated ASCII text maze to console output.
 * Apply command-line arguments to specify options including:
 * number of rows, given as an integer >= MIN_SIZE and <= MAX_SIZE
 * number of columns, given as an integer >= MIN_SIZE and <= MAX_SIZE
 * character symbol to denote a wall such as @ or W.  Note that # is not a valid option.
 * background color code given as an integer 0-8, inclusive.
 *   0 - black
 *   1 - dark gray
 *   2 - red
 *   3 - green
 *   4 - yellow
 *   5 - blue
 *   6 - purple
 *   7 - light blue
 *   8 - light gray
 *
 * In this first version of amazing, we will expect command-line arguments
 * in a hard-coded fixed order.  The first argument will be interpreted to
 * be the number of rows. The second argument the number of columns.
 * The third argument the background color.  The fourth argument the wall symbol.
 *
 * Example command line usage with four arguments:
 * ./amazing1 8 6 1 #
 *           8 -> number of rows
 *             6 -> number of columns
 *               1 -> background color
 *                 # -> wall symbol
 *
 * The user may supply fewer than four arguments.  Assign default values for
 * any of the four arguments whose values were not specified:
 *   default number of rows 8
 *   default number of columns 8
 *   default color 0
 *   default wall symbol @
 *
 * Example command line usage with only two arguments:
 * ./amazing1 8 6
 *           8 -> number of rows
 *             6 -> number of columns
 *               color will default to 0 and wall symbol defaults to #
 *
 * Adapted by William Bares for use in Dr. Henry Walker's Imperative Programming class at Grinnell College.
 * The original C maze program is copyright (C) 2008 Henry Kroll www.thenerdshow.com.
 * To read more about the maze algorithm visit https://thenerdshow.com/maze.html
 */

#include <stdio.h>
#include <stdlib.h>
#include <sys/time.h>
#include <string.h>

// Define minimum and maximum number of rows and columns.
#define MIN_SIZE 2
#define MAX_SIZE 69 

/*
 * usage
 * Print a message explaining what arguments are expected.
 */
void usage(char **a){
  // Extra work - add fprintf statements to explain what arguments are expected.
	// An ideal solution will use the MIN_SIZE and MAX_SIZE values.
	printf("Example usage: ./amazing1 8 6 1 #\n");
	exit(1);
}

/*
 * parseArgs
 * Process command line arguments and assign values for maze parameters
 * numRows, numCols, color, and wall character.
 * Assign default values for omitted arguments as described in comments above.
 * Call the usage() function to print instructions on argument usage if 
 * number of rows or columns is not within the allowable range MIN_SIZE to MAX_SIZE, inclusive. 
 * post-condition: parameters numRows, numCols, color, and wall will be assigned
 * values specified by command-line arguments or defaults for those omitted. 
 */
void parseArgs(int argc, char *argv[], int *numRows, int *numCols, int *color, char *wall){

	// Assign default values for all arguments in case any argument is omitted.

	
	
	
	
}

/*
 * initRandomGenerator
 * Initialize random number generator with time of day seed.
 */
void initRandomGenerator(){
	struct timeval tv; /* seed srand() */
	gettimeofday(&tv,0); /* with something... */
	srand((unsigned int)tv.tv_usec);
}

/*
 * mazeInit
 * Create 2D array of characters all set to designated wall character.
 * Maze construction begins will solid walls that will be randomly carved away.
 * @param numRows - number of rows as an integer >= MIN_SIZE and <= MAX_SIZE
 * @param numCols - number of cols as an integer >= MIN_SIZE and <= MAX_SIZE
 * @param wallCharacter - wall symbol as a type char value
 * @return two-d array of char values with all elements set to wallCharacter
 */
char **mazeInit(int numRows,int numCols, char wallCharacter){

  // Allocate a two-d array by first allocating a list of pointers for each row.
	char **mazeBoard=malloc((2*numRows+1)*sizeof(char*)); /* 3x3 with overlap of 1 */
	int i,j;
	
	for(i=0;i<2*numRows+1;i++){
		// For each row, dynamically allocate characters for the columns.
		if(!(mazeBoard[i]=malloc(2*numCols+1))){
			fprintf(stderr,"Out of memory.\n");
			exit(1);
		}
		// Initialize each maze element to be wallCharacter.
		for(j=0;j<2*numCols+1;j++)
			mazeBoard[i][j] = wallCharacter;
	}
	return mazeBoard;
}

/*
 * mazeStep
 * recursive function that begins at a specified row, column position,
 * convert the wall character to the space character, then randomly
 * select one of four possible next directions.  Recursively call
 * mazeStep passing the row, column indices of the current location.
 *
 * post-condition: Changes elements of mazeArray to remove part of the
 * wall to gradually open up a random walk path through the maze.
 */
void mazeStep(char **mazeArray, int *rows, int *cols, int r, int c){
	int i,vector[3][2];
	
	#define ROW vector[i][0]
	#define COL vector[i][1]
	
	while(1){
		i=0; /* look around */
		if(r > 1 && mazeArray[r-2][c] != ' ') {
		  ROW=r-2;
			COL=c;
			i++; 
		}
		if(r<*rows*2-1	&&mazeArray[r+2][c] !=' ') {
		  ROW=r+2;
			COL=c;
			i++;
		}
		if(c>1 && mazeArray[r][c-2] !=' '){
		  ROW=r;
			COL=c-2;
			i++;
		}
		if(c<*cols*2-1 &&mazeArray[r][c+2] !=' ') {
		  ROW=r;
			COL=c+2;
			i++;
		}
		if(!i)
		  break; /* check for dead end */
		i=(int)(i*(rand()/(RAND_MAX+1.0))); /* choose mazeArray path */
		mazeArray[(ROW+r)/2][(COL+c)/2]=' ';	/* knock out mazeArray wall */
		mazeArray[ROW][COL]=' ';			/* clear to it */
		mazeStep(mazeArray, rows, cols, ROW, COL);		/* recursive call */
	}
}

/*
 * mazeWalkBegin
 * Begin the random walk to carve an open passage.
 * @param mazeArray Given 2D array of char element representing the maze
 * @param numRows Number of rows as an integer >= MIN_SIZE and <= MAX_SIZE.
 * @param numCols Number of columns as an integer >= MIN_SIZE and <= MAX_SIZE.
 */
void mazeWalkBegin(char **mazeArray, int numRows, int numCols){
	/* this starts at one side but you can start anywhere */
	/* there is a way out no matter where your exits are */
	int i, r, c;
	c = numCols | 1;
	mazeArray[0][c]=' ';
	mazeArray[2*numRows][c] = ' ';
	i = (int)(2*(rand()/(RAND_MAX+1.0)));
	c=(i)?1:2*numCols-1;
	r=numRows|1;
	mazeArray[r][c]=' ';

	mazeStep(mazeArray, &numRows, &numCols, r, c);
}

/*
 * mazePrint
 * Print the maze to the console terminal.
 * @param mazeArray Given 2D array of char element representing the maze
 * @param numRows Number of rows as an integer >= MIN_SIZE and <= MAX_SIZE.
 * @param numCols Number of columns as an integer >= MIN_SIZE and <= MAX_SIZE.
 * @param color ASCII color code given as an integer 0-8, inclusive.
 */
void mazePrint(char **mazeArray, int numRows, int numCols, int color){
	int i,j;
	for(i=0;i<2*numRows+1;i++){
		for(j=0;j<2*numCols+1;j++){
			if(color && mazeArray[i][j] != ' ')
				if(j==0 || mazeArray[i][j-1] == ' ') /* reduce control codes */
					printf("%c[4%dm",27,color-1);
			if(color && mazeArray[i][j] == ' ' && mazeArray[i][j-1] != ' ') 
			  printf("%c[0m",27);
			printf("%c",mazeArray[i][j]);
		}// end for j loop.		
		if(color)
		  printf("%c[0m",27);
		printf("\n");
	}// end for i loop.
}

/*
 * mazeFreeMemory
 * Deallocate dynamically allocated maze memory.
 * @param mazeArray Two-d array of characters given as an array of char* pointers, one per row.
 * @param numRows Number of rows as a positive integer >= MIN_SIZE and <= MAX_SIZE.
 */
void mazeFreeMemory(char **mazeArray, int numRows){
	int i;
	for(i=0;i<2*numRows+1;i++)
		free(mazeArray[i]);
	free(mazeArray);
}

/*
 * main function
 * Process command line arguments, generate, and print the random ASCII maze.
 */
int main(int argc, char *argv[]){

  // Variables to be assigned values from command line arguments,
  // or defaults if corresponding argument is not provided.
	int rows, cols, color;
	char wall;
	
	// Two-dimensional array of char elements that represents the ASCII maze.
	char ** mazeArray;
	
	// Inspects command line arguments defined by argc and argv.
	// Assign values to rows, cols, color, and wall based on command line arguments 
	// or default values for any omitted arguments.
	parseArgs(argc, argv, &rows, &cols, &color, &wall);
	
	// Testing print message to display argument values found.
	printf("rows %d cols %d color %d wall %c\n", rows, cols, color, wall);
	
	// Initialize random number generator seed using current clock time.
	initRandomGenerator();
	
	// Dynamically allocated two-dimensional array with all elements
	// initially set to the wall character symbol.
  mazeArray =	mazeInit(rows,cols,wall);
	
	// Begin process of randomly walking through the maze carving open a passage.
	mazeWalkBegin(mazeArray,rows,cols);
	
	// Print the resulting random maze to the text console.
	mazePrint(mazeArray,rows,cols,color);
	
	// Free memory that was dynamically allocated for the maze.
	mazeFreeMemory(mazeArray,rows);
	
	return 0;
}