////  M I D T E R M    ////
String title=  "M I D T E R M";
String author=  "Your name";
String instructions="q to quit; r to reset; ? for help";
String news="";

boolean day=true;
float surface;
float left,right,top,bottom;

float sunX,sunY,sunDX=2;
float boatX,boatY,boatDX=2,boatDY=0,boatW=100,boatH=20;
float netX=0,netY=0,netDX=0,netDY=0;
int caught=0;

float octoX,octoY,octoDX,octoDY,octoW=40,octoH=50;
float octoUp= -1, octoDown=9;
float octoR=150, octoG=0, octoB=150;
int octoCount=0;

float fishX=100,fishY,fishDX=3,fishDY,fishW=60,fishH=20;
float fishR,fishG,fishB;
int nfish;
int score=0, total=0;

//// Setup:  size, reset, etc. 
void setup() {
  size( 600,400 );
  surface=  height/4;
  top=  surface;
  bottom=  height-10;
  left=  20;
  right=  width-20;
  //
  reset();
}
//// reset:  initialize all values; randomize some. 
void reset() {
  news=  "RESET";
  sunY=  random(30, surface);
  boatY=  surface;
  octoX=  random(left,right);
  octoY=  surface+100;
  octoDY=  3;
  nfish=  int(random(1,10));
  fishX=  width/2;
  fishY=  random( surface+50, height-50 );
  fishDX=  random(2,7);
  fishColor();
}
void fishColor() {
    fishR=  random(100,200);
    fishG=  random(100,200);
    fishB=  random(100,200);
}  

////Next frame:  scene, boat, oct, school
void draw() {
  scene();
  if (key == '?') {
    help();
    return;
  }
  boat();
  octo();
  school();
  messages();
}

//// scene:  sky, sun, ocean
void scene() {
  sunX += sunDX;
  if (sunX>width) {
    sunX=0;
    day=  ! day;
  }
  if (day) {
    background(200,220,250);    // Light blue sky
    fill(255,255,0);            // Yellow sun.
  } else {
    background(50,100,200);    // Dark blue sky
    fill(200,200,200);          // Pale moon.
  }
  noStroke();
  ellipse(sunX,sunY+20-60*sin(PI*sunX/width), 40,40 );
  // Sea
  fill( 0,150,100 );
  rectMode(CORNER);
  rect( 0,surface, width,height-surface );
}
/**  messages:  title at top, author at lower left, news, score, etc.
*/
void messages() {
  text( title, width/3, 20 );
  if (score>0) text( "SCORE:  "+score, width*3/4, 50 );
  text( news, width/4, 40 );
  text( author, 10, height-15 );
}
void help() {
  int line=0;
  float x=100, y=width/3;
  text( "q to quit; r to reset; ? for help", x, y+12*line++ );
  text( "Click octopus to stop it.", x, y+12*line++ );
  text( "Click boat to catch fish", x, y+12*line++ );
}

/** boat:  moves back and forth, across the surface.
  * Red hull points to direction of travel.
  * Boat stops while fishing.
*/
void boat() {
  if (boatDY == 0) {
    if (netDY == 0) {
        // Normal boat motionm
        boatX += boatDX;
        if (boatX>width-boatW || boatX<0) boatDX = -boatDX;
    } else {
        //// (Boat does not move, while net is in action;
        net();
    }
  } else {
    //// Boat is sinking!
    boatY += boatDY;
    if (boatY > bottom) {
      //// Boat hit bottom -- reset boat. ////
      boatX=left;
      boatY=surface;
      boatDX=2;
      boatDY=0;
      news="";
    }
  }
  // Display the boat //
  fill(255,0,0);
  rectMode(CENTER);
  rect( boatX,boatY-boatH/2, boatW,boatH );
  rect( boatX,boatY-boatH-boatH/3, boatW/3,boatH*2/3 );    // cabin.
  if (boatDX>0) triangle( boatX+boatW/2,boatY, boatX+boatW/2,boatY-boatH, boatX+boatW*3/4,boatY-boatH );
  //--triangle( boatX+boatW,boatY, boatX+boatW,boatY-boatH, boatX+boatW+boatW/4,boatY-boatH ); 
  else triangle( boatX-boatW/2,boatY, boatX-boatW/2,boatY-boatH, boatX-boatW*3/4,boatY-boatH ); 
  fill(0);
  rect( boatX,boatY-boatH-boatH, 6,-15 );
  
  if (total>0) text( total, boatX, boatY );
}
////  Net descends to bottom, catching fish, then ascends quickly.
void net() {
  String nl="\n";
  
  netY += netDY;
  if (netY<surface) {
    //// Net is done.
    netDY=0;
    boatDX=  -2;        // Return home (left);
    total += caught;
  } else if (netY > bottom) {
    score++;
    netDY=  -7;                // Ascend quickly.
  }
    if ( dist( netX,netY, fishX,fishY ) < 100 ) {
      //// Catch fish
      caught += nfish;
      score += nfish;
      news=  "Caught "+ nfish +" fish in net.";
    }
  //// Display the net;
  strokeWeight(1);
  stroke(0,0,150);
  float netW=  100;
  if (netDY<0) netW=30;
  for (float netEnd=netX-netW/2; netEnd<netX+netW/2; netEnd += netW/10 ) {
    line( netX,netY, netEnd,netY+50 );
  }
  strokeWeight(0);
}
/**  octopus
*/
void octo() {
  octoY += octoDY;
  if (octoY<surface) {
    octoDY=  octoDown;
    //// Surfaced.  Catch a boat?  Start downward.
    if ( octoY<surface+octoH  && abs(boatX-octoX) < boatW ) {
      //// Octopus hit ship!
      news=  "Octopus hit the ship!";
      boatDX=  0;
      boatDY=  octoDown;
      netDY=0;              // Remove net (if any).
      score -=100;
      caught=0;
      total /= 2;
      octoW *= 2;
    }
  } else if (octoY>bottom) {
    // new octopus.
    octoReset();
  }
  //// Display octopus.
  fill( octoR,octoG,octoB );
  rectMode(CENTER);
  rect( octoX,octoY, octoW,octoH );
  ellipse( octoX,octoY-octoH/2, octoW,octoW );
  // 8 legs
  float x=  octoX-octoW/2, y=  octoY+octoH/2;         // Lower left corner.
  float dx=  octoW/8;
  stroke( octoR,octoG,octoB );
  strokeWeight(2);
  x=  x + dx/2;
  text( octoDY, 10,10 );
  float swim=  0;
  if (octoDY<0) {
    swim=  frameCount/15 % 2 ==0 ? 5 : -5;
  }
  for (int j=0; j<8; j++) {
    line( x, y, x+swim, y+25 );
    x += dx;
  }
  strokeWeight(0);
  fill(255);
  text( octoCount, octoX-10, octoY );
  // Eye
  y=  octoY - octoH/2 - octoW/2 + 12;
  fill(255);
  ellipse( octoX, y, 12,12 );
  fill(0,0,255);
  ellipse( octoX+swim/4, y, 4,4 );
}
void octoReset() {
    octoX=  random( left, right );
    octoY=  bottom;
    octoDY=  octoUp;
    octoCount++;
    // Random color and size for octopus //
    octoR=  random( 100,200 );
    octoG=  random( 0,100 );
    octoB=  random( 100,200 );
    octoW=  random( 20,50 );
    octoH=  random( 40,80 );
} 

/**  school of fish:  smaller 7 smaller, behind & below.
*/
void school() {
  fishX += fishDX;
  if (fishX>right) {
    //// Reset fish for next school.
    nfish=  int(random(1,10));
    fishX=  left+20;
    text( fishX+"\n"+fishDX, 10,70 );
    fishDX=  random(1,8);
    fishColor();
  }
  // Create a school of fish.
  float x=fishX, y=fishY, w=fishW,h=fishH;
  fill( fishR,fishG,fishB);
  for (int j=0; j<nfish; j++ ) {
    fill( fishR+random(20),fishG+random(20),fishB+random(20));
    oneFish( x,y, w,h );
    x=  x - w - 10;                // Next fish is behind and below.
    y=  y + h/2;
    w=  w * 0.8;
    h=  h * 0.8;              // Each is 80% of previous.
  }
  fill(0);
}
//// onefish:  Display one fish at (x,y)
void oneFish( float x, float y, float w, float h ) {
  ellipse( x,y, w,h );
  float back= x - w/2 +w/10 ;
  triangle( back,y, back-w/4,y-h/2, back-w/4,y+h/2 );
}


//// Check for hits.
boolean hit( float x, float y, float xx, float yy, float ww, float hh ) {
  String comma=", ";
  String and="  ,  ";
  news=  "You missed!  ";
  news +=  "\n hit( "+ x+comma+y +and+ xx+comma+yy +and+ ww+comma+hh +"  )";
  // Return true if (x,y) is within rect( xx,yy, ww, hh )
  if (x < xx-ww/2) return false;
  if (x > xx+ww/2) return false;
  if (y < yy-hh/2) return false;
  if (y > yy+hh/2) return false;
  news=  "H I T !!!!";
  return true;
}


//// EVENT HANDLERS ////
void mousePressed() {
  //// Click on octopus to reset
  if ( hit( mouseX,mouseY, octoX, octoY, octoW, octoH ) ) octoReset();  
  //// Reverse boat direction:
  if ( hit( mouseX,mouseY, boatX, boatY, boatW, 3*boatH ) ) {
    if (netDY == 0) { 
      //// Net begins dropping.;
      news=  "Dropping the net.";
      netX=  boatX;
      netY=  surface+10;
      netDY=  4;
    } else {
      netDY=0;
      news="";
    }
  }
}

void keyPressed() {
  if (key == 'q') exit();
  if (key == 'r') reset();
}