// Final Project IAT 800
// FALL 06  
// by
// Veronica Zammitto
// Game:  Danger in the Dungeon
// Our Hero goes around the world slaying monsters.
// You have a specific goal, killing just one monster per dungeon.
// Monster are quite alike... so, you have to make your best decision.
// Good Luck and farewell !
//
// Player decisions are storage in disk.


//Global variables====================================================================================


int mySize = 500;
int instSize = 100;
int tileSize = 20;
int initialX = 0;

boolean playerAgree;

float monsterRgb ;
float monsterrGb ;
float monsterrgB ;

float m = millis();

Hero myHero = new Hero (1, 1, 20);
Monster myMonster = new Monster (23,23,20);
ColorMonster myColorMonster = new ColorMonster (21,23,20);

String [ ] instruction = {"you have to kill only the", "monster. \n \nUse arrow keys to move, press 'spacebar' to use your sword"};
String [ ] myColor = new String [ 13 ];

String [ ] myAdjectiveList;
int myNumberOfAdjectives;
int [ ] myRGB = new int [3];
String myCurrentAdjective;
int myCurrentColor;

ArrayList playerColor = new ArrayList();
int nHero = 1;
PImage testmap;
PImage wall;
PImage hero1;
PImage hero2;
PImage hero3;
PImage ground;
PImage splash;
PImage hooray;
PFont myfont;

Maze maze;

int nextMap = 0;
String currentMap;    

// Setup Method =======================================================================================
void setup (){
  size (mySize, mySize+instSize);
  smooth();
  wall = loadImage ("wall.png");
  hero1 = loadImage ("hero1.png");
  hero2 = loadImage ("hero2.png");
  hero3 = loadImage ("hero3.png");
  ground = loadImage ("ground.png");
  splash = loadImage ("splash.png");
  hooray = loadImage ("hooray.png");
  myfont = loadFont ("CopperplateGothic-Bold.vlw");
  maze = new Maze();
  nextLevel();
}

void keyPressed()
{
  // advance one turn
  maze.update();
  myHero.update();
  myMonster.update();
  myColorMonster.update();
  slay();
}


// draw Method ===========================================================================================
void draw ()
{
 
  if (millis() < 5000) {image (splash, 0,0);}
  else{ 
  background (0);
  maze.drawMe();
  myHero.drawMe();
  myMonster.drawMe();
  myColorMonster.drawMe();
  goal();
  }
}

// Maze class - which path our hero would follow??? ===================================================
class Maze 
{
  public int [][] map;
  public int mazeWidth;
  public int mazeHeight;
  void load()
  {
    testmap = loadImage (currentMap);
    mazeWidth = testmap.width;
    mazeHeight = testmap.height;
    map = new int[mazeWidth][mazeHeight];
    
    for(int y = 0; y < mazeHeight; y ++)
    {
      for (int x = 0; x < mazeWidth; x ++)
      {

        int colour = testmap.get(x,y);
        if(colour != -1) // if not almost black
          map[x][y] = 1; // wall
        else
          map[x][y] = 0; // ground
      }
    }
  }

  void update()
  {
  }

  void drawMe()
  {
    pushMatrix ();
    translate (initialX, instSize);
    for(int y = 0; y < mazeHeight; y ++)
    {
      for (int x = 0; x < mazeWidth; x ++)
      {
        if(map[x][y] == 1) // wall
        {   
          image (wall, x*tileSize, y*tileSize);
        }
        else
        {
          image (ground, x*tileSize, y*tileSize);
        }
      }
    }
    popMatrix ();
  }

}

// Entity class - todo bicho que camina va a parar al asador =============================================
class Entity
{
  int x;
  int y;
  int entitySize;

  Entity (int x, int y, int entitySize)
  {
    this.x = x;
    this.y = y;
    this.entitySize = entitySize;
  }

  void update()
  {
  }

  void drawMe()
  {      
  }

  void move(int offsetX, int offsetY)
  {
    int targetX = x + offsetX;
    int targetY = y + offsetY;
    if(canMove(targetX, targetY))
    {  
      x = targetX;
      y = targetY;
    }
  }

  boolean canMove(int newX, int newY)
  {  
    if(newX < 0 || newX >= maze.mazeWidth || newY < 0 || newY >= maze.mazeHeight)
      return false;
    return maze.map[newX][newY] != 1;
  }

}

//Hero class - Our rash hero, mosters slaughter -hooray! =============================================
class Hero extends Entity
{
  Hero (int x, int y, int entitySize)
  {
    super(x, y, entitySize);
  }

  void update()
  {
    move();
  }

  void drawMe()
  {      
    pushMatrix ();
    translate (initialX, instSize);
    
    switch (nHero)  //walking images
    {
    case 1:
    image (hero1, x*tileSize, y*tileSize);
      break;
    case 2:
    image (hero2, x*tileSize, y*tileSize);
      break;
    case 3:
    image (hero3, x*tileSize, y*tileSize);
      break;
    }
    popMatrix ();
  }

  void move()
  {
    if (keyPressed)
    {
      if (key == CODED) 
      {
        if (keyCode == UP) move(0,-1);
        if (keyCode == DOWN ) move(0,1);
        if (keyCode == LEFT ) move(-1,0);
        if (keyCode == RIGHT) move(1,0);
      }
      nHero++;  //for drawing him walking (alternate images)
      if(nHero>3) nHero=1;   
    }

  }

  void nextLevel ()
  {
    myHero.x = 1;
    myHero.y = 1;
  }
}

// Monster class - Those who don't deserve to live ========================================================
class Monster extends Entity
{
  int directionX = 0;
  int directionY = -1; // starts by going up

  Monster (int x, int y, int entitySize)
  {
    super(x, y, entitySize);
  }

  void drawMe ()
  {
    pushMatrix ();
    translate (initialX, instSize);
    smooth ();
    fill (monsterRgb, monsterrGb, monsterrgB);
    pushMatrix();
    translate (x*tileSize, y*tileSize);
    triangle (10,4, 19,17,2,17); //body
    ellipse (10,4, 15,8);  //head
    pushMatrix();
    translate (15,4);
    line (0,7,6,3);   //arm
    line (4,4, 6,0);  //finger
    line (4,4, 6, 7); //finger
    popMatrix();

    pushMatrix();
    translate (5,4);
    rotate (radians (90));
    line (0,7,6,3);    //the other arm
    line (4,4, 6,0);
    line (4,4, 6, 7);
    popMatrix();

    pushMatrix();
    translate (13,17);   //feet
    line (0,0, 0, 3);
    line (0,0, 3,3);
    line (0,0, -3, 3);
    popMatrix();

    pushMatrix();
    translate (7,17);
    line (0,0, 0, 3);
    line (0,0, 3,3);
    line (0,0, -3, 3);
    popMatrix();

    popMatrix();

    popMatrix();
  }

  void update()
  {
    move();
  }

  void move()
  {
    // check if my current direction is free of walls
    println("moving x:"+directionX+" y:"+directionY + " map:"+maze.map[x+directionX][y+directionY]);
    if(canMove(directionX+x, directionY+y))
    {
      println("entered");
      move(directionX, directionY);
    }
    else
    {
      // change dir
      if(directionX == 0 && directionY == -1) // was going up
      {
        directionX = -1; // then go left
        directionY = 0;
      }
      else
        if(directionX == -1 && directionY == 0) // was going left
        {
          directionX = 0; // then go down
          directionY = 1;
        }
        else
          if(directionX == 0 && directionY == 1) // was going down
          {
            directionX = 1; // then go right
            directionY = 0;
          }
          else
          {
            directionX = 0; // then go up
            directionY = -1;        
          }

    }
  }

  void nextLevel ()
  {
    myMonster.x = 23;
    myMonster.y = 23; 
  }
}


// subclass of monster that matchs with the meaning ===================================================
class ColorMonster extends Monster
{
  ColorMonster (int x, int y, int  entitySize)
  {
    super(x, y, entitySize);
  }

  void drawMe()
  {
    pushMatrix ();
    translate (initialX, instSize);
    fill (myRGB[0],myRGB[1],myRGB[2]);
    pushMatrix();
    translate (x*tileSize, y*tileSize);
    triangle (10,4, 19,17,2,17);
    ellipse (10,4, 15,8);

    pushMatrix();
    translate (15,4);
    line (0,7,6,3);
    line (4,4, 6,0);
    line (4,4, 6, 7);
    popMatrix();

    pushMatrix();
    translate (5,4);
    rotate (radians (90));
    line (0,7,6,3);
    line (4,4, 6,0);
    line (4,4, 6, 7);
    popMatrix();

    pushMatrix();
    translate (13,17);
    line (0,0, 0, 3);
    line (0,0, 3,3);
    line (0,0, -3, 3);
    popMatrix();

    pushMatrix();
    translate (7,17);
    line (0,0, 0, 3);
    line (0,0, 3,3);
    line (0,0, -3, 3);
    popMatrix();
    popMatrix();
    popMatrix();
  }

  void nextLevel ()
  {
    myColorMonster.x = 21;
    myColorMonster.y = 23;
  }
}


//====================================================================================================
void instructions () 
{
  float mySemiAdjective = (random (myNumberOfAdjectives));
  //println ("mySemiAdjective:"+mySemiAdjective);
  int mySelectAdjective = int (mySemiAdjective);
  myCurrentAdjective =  myAdjectiveList [mySelectAdjective];
  //println ("myCurrentAdjective:"+myCurrentAdjective); 
}


//==================================================================================================
void goal()
{

  String goal = instruction[0] + " " + myCurrentAdjective + " " + instruction [1] ;
  fill (255);
  textFont (myfont, 18);
  text (goal, tileSize, tileSize, mySize-tileSize, instSize-tileSize );
}

//==================================================================================================
void meaningfulColor ()
{

  myColor [0] = "black";
  myColor [1] = "blue";
  myColor [2] = "brown";
  myColor [3] = "gold";
  myColor [4] = "green";
  myColor [5] = "grey";
  myColor [6] = "orange";
  myColor [7] = "red";
  myColor [8] = "violet";
  myColor [9] = "white";
  myColor [10] = "yellow";
  myColor [11] = "yellow (dingy)";
  myColor [12] = "yellow (brightest)";

  float mySemiCurrentColor = (random (myColor.length-1));
  println (mySemiCurrentColor);
  myCurrentColor = int (mySemiCurrentColor);
  println (myCurrentColor);



  switch (myCurrentColor)
  {
  case 0:
    myRGB[0] = 0;
    myRGB[1] = 0;
    myRGB[2] = 0;
    myNumberOfAdjectives = 10;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "deadly";
    myAdjectiveList[1] = "evil";
    myAdjectiveList[2] = "unbearable";
    myAdjectiveList[3] = "criminal";
    myAdjectiveList[4] = "sinister";
    myAdjectiveList[5] = "depressive";
    myAdjectiveList[6] = "hopeless";
    myAdjectiveList[7] = "authoritarian";
    myAdjectiveList[8] = "stylish";
    myAdjectiveList[9] = "mourning";
    break;
  case 1:
    myRGB[0] = 15;
    myRGB[1] = 18;
    myRGB[2] = 177;
    myNumberOfAdjectives = 10;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "cold";
    myAdjectiveList[1] = "peaceful";
    myAdjectiveList[2] = "depressive";
    myAdjectiveList[3] = "sad";
    myAdjectiveList[4] = "calm";
    myAdjectiveList[5] = "wise";
    myAdjectiveList[6] = "lonely";
    myAdjectiveList[7] = "solitary";
    myAdjectiveList[8] = "contemplative";
    myAdjectiveList[9] = "not hungry";
    break;
  case 2:
    myRGB[0] = 128;
    myRGB[1] = 59;
    myRGB[2] = 8;
    myNumberOfAdjectives = 3;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = " wooden";
    myAdjectiveList[1] = "comfortable";
    myAdjectiveList[2] = "earthy";
    break;
  case 3:
    myRGB[0] = 233;
    myRGB[1] = 198;
    myRGB[2] = 4;
    myNumberOfAdjectives = 3;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "valuable";
    myAdjectiveList[1] = "honorable";
    myAdjectiveList[2] = "loyal";
    break;
  case 4:
    myRGB[0] = 20;
    myRGB[1] = 146;
    myRGB[2] = 17;
    myNumberOfAdjectives = 3;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "natural";
    myAdjectiveList[1] = "young";
    myAdjectiveList[2] = "fertile";
    break;
  case 5:
    myRGB[0] = 130;
    myRGB[1] = 130;
    myRGB[2] = 130;
    myNumberOfAdjectives = 1;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "neutral";
    break;

  case 6:
    myRGB[0] = 253;
    myRGB[1] = 176;
    myRGB[2] = 27;
    myNumberOfAdjectives = 3;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "vital";
    myAdjectiveList[1] = "strong";
    myAdjectiveList[2] = "endurable";
    break;
  case 7:
    myRGB[0] = 255;
    myRGB[1] = 0;
    myRGB[2] = 0;
    myNumberOfAdjectives = 7;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "passionate";
    myAdjectiveList[1] = "excited";
    myAdjectiveList[2] = "hungry";
    myAdjectiveList[3] = "hot";
    myAdjectiveList[4] = "dangerous";
    myAdjectiveList[5] = "aggressive";
    myAdjectiveList[6] = "powerful";
    break;
  case 8:
    myRGB[0] = 192;
    myRGB[1] = 29;
    myRGB[2] = 163;
    myNumberOfAdjectives = 4;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "mystic";
    myAdjectiveList[1] = "royal";
    myAdjectiveList[2] = "high";
    myAdjectiveList[3] = "ranged";
    break;
  case 9:
    myRGB[0] = 255;
    myRGB[1] = 255;
    myRGB[2] = 255;
    myNumberOfAdjectives = 5;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "light";
    myAdjectiveList[1] = "pure";
    myAdjectiveList[2] = "innocent";
    myAdjectiveList[3] = "clean";
    myAdjectiveList[4] = "chaste";
    break;
  case 10:
    myRGB[0] = 246;
    myRGB[1] = 244;
    myRGB[2] = 35;
    myNumberOfAdjectives = 5;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "intellingt";
    myAdjectiveList[1] = "innovative";
    myAdjectiveList[2] = "spiritual";
    myAdjectiveList[3] = "delicate";
    myAdjectiveList[4] = "sunny";
    break;
  case 11:
    myRGB[0] = 208;
    myRGB[1] = 232;
    myRGB[2] = 44;
    myNumberOfAdjectives = 4;
    myAdjectiveList = new String [myNumberOfAdjectives];    
    myAdjectiveList[0] = "coward";
    myAdjectiveList[1] = "mean";
    myAdjectiveList[2] = "stingy";
    myAdjectiveList[3] = "decadent";
    break;
  case 12:
    myRGB[0] = 252;
    myRGB[1] = 252;
    myRGB[2] = 100;
    myNumberOfAdjectives = 2;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "angry";
    myAdjectiveList[1] = "raged";
    break;
  default:
    myRGB[0] = 255;
    myRGB[1] = 170;
    myRGB[2] = 170;
    myNumberOfAdjectives = 2;
    myAdjectiveList = new String [myNumberOfAdjectives];
    myAdjectiveList[0] = "mariposon";
    myAdjectiveList[1] = "marico";
    break;
  }

}



//==================================================================================================
void slay()
{
  boolean collision , collisionBoth;
  collision = dist(myHero.x, myHero.y, myMonster.x, myMonster.y) <=1; 
  playerAgree = dist(myHero.x, myHero.y, myColorMonster.x, myColorMonster.y) <=1 ;
  collisionBoth = collision || playerAgree;
  if (keyPressed)
  {
    if (key == ' ') 
    {
      if (collisionBoth) 
      {
        println ("collision");
        storage();
        nextLevel();
      }
    }
  }
}


//===================================================================================================
void storage ()
{
  String [ ] tmp = new String [ 1 ];
  tmp[0]= "Player thinks that "  + myColor [myCurrentColor] + " means " + myCurrentAdjective + "? " + str(playerAgree); 
  saveStrings("Result "+ nf(nextMap, 1)+ ".txt", tmp);

}

//====================================================================================================
void nextLevel()
{
  nextMap ++;
  if (nextMap > 6) nextMap = 1;
  currentMap = "map" + nf(nextMap, 1) + ".png";
  testmap = loadImage (currentMap) ;
  println ("CurrentMap:"+currentMap);

  monsterRgb = random (255);
  monsterrGb = random (255);
  monsterrgB = random (255);
  
  image (hooray, 0,0);
  delay (1500);
  maze.load();
  meaningfulColor();
  instructions();
  myColorMonster.nextLevel();
  myMonster.nextLevel();
  myHero.nextLevel();
}
