#include <iostream>
#include <stdlib.h>
#include <math.h>

using std::cout;
using std::endl;

enum { size1 = 45, size2 = 145, randmax1 = size1 - 2, randmax2 = size2 - 2 };	//dimensions of total available area and island available area
int island[size1][size2];
enum {water, mountain, beach, tree};

/*int neighborcount(int x, int y, int n) //return number of 8-neighbors that do NOT match n
{
  int count=0;
  cout<<n<<endl;
  for(int i=-1;i<=1;i++)
  {
    for(int j=-1;j<=1;j++)
    {
      count += (island[x+i][y+j]!=n);
      cout<<island[x+i][y+j];
    }
    cout<<endl;
  }
  count -= (island[x][y]!=n);
  cout<<count<<endl<<endl;
  return count;
}*/

int neighborcount (int x, int y, int n) //return number of 8-neighbors that do NOT match n
{
  int count=0;
  count+=(island[x-1][y-1]!=n)?1:0;
  count+=(island[x-1][y]!=n)?1:0;
  count+=(island[x-1][y+1]!=n)?1:0;
  count+=(island[x][y-1]!=n)?1:0;
  count+=(island[x][y+1]!=n)?1:0;
  count+=(island[x+1][y-1]!=n)?1:0;
  count+=(island[x+1][y]!=n)?1:0;
  count+=(island[x+1][y+1]!=n)?1:0;
  return count;
} //(int)true may not always be 1

int main (void)
{
  char charmap[4] = { ' ', '^', '.', '#' };	//water, mountains, beach, trees
  for (int i = 0; i < size1; i++)
    {
      for (int j = 0; j < size2; j++)
	{
	  island[i][j] = water;	//start with all water
	}
    }
  srand (time (NULL));
  int count = 0;

  island[size1 / 2][size2 / 2] = mountain;	//seed a mountain square in the middle of the water
  int land = size1 * size2 / 4;	//define landmass as a fraction of total area available

  while (count < land - 1)	//generate bare mountains until we've met landmass
    {
      int x = rand () % randmax1 + 1;	//for each random coordinate pair...
      int y = rand () % randmax2 + 1;

      if (count < 10)		//(if there are few island squares)
	{
	  if (island[x][y] == water && neighborcount (x, y, water) > 0)	//...add it to the island if it's touching existing island squares
	    {
	      island[x][y] = mountain;	//set to mountain type
	      count++;
	    }
	}
      else			//(if there are many island squares)
	{
	  if (island[x][y] == water && neighborcount (x, y, water) > /*n= */ 2)	//...add it to the island if it's touching more than n existing island squares
	////////////////lower values of n give more complex coastlines; -1 generates a swamp, 3 generates nearly perfect concentric circles, 2 seems ideal///////
	    {
	      island[x][y] = mountain;	//set to mountain type
	      count++;
	    }
	}
    }
  count = 0;
  while (count < land / 3)	//a fraction of the land should be beach
    {
      int x = rand () % randmax1 + 1;	//for each random coordinate pair...
      int y = rand () % randmax2 + 1;

      if (island[x][y] == mountain && neighborcount (x, y, mountain) > /*n= */ 3)	//...set it to beach if it was mountain and is
										        //adjacent to over n water or beach squares
	{
	  island[x][y] = beach;	//set to beach type
	  count++;
	}
    }
  count = 0;
  while (count < land / 3)	//a fraction of the land should be treeeeees
    {
      int x = rand () % randmax1 + 1;	//for each random coordinate pair...
      int y = rand () % randmax2 + 1;

      if (island[x][y] == mountain && neighborcount (x, y, mountain) > /*n= */ 3)	//...set it to trees if it was mountain and
	//is adjacent to over n water, beach, or tree squares
	{
	  island[x][y] = tree;	//set to treeee type
	  count++;
	}
    }
  int counts[4] = { 0, 0, 0, 0 };
  for (int i = 0; i < size1; i++)	//print the island, using charmap to translate ints
    {
      for (int j = 0; j < size2; j++)
	{
	  cout << charmap[island[i][j]];
	  counts[island[i][j]]++;	//keep track of the numbers of each type of land
	}
      cout << endl;
    }
  for (int i = 0; i < 4; i++)	//print the land type statistics
    cout << charmap[i] << ":  " << counts[i] << endl;
  return 0;
}

