function PirateShip() {
  
  this.x = 0;
  this.y = 0;
  
  this.targetX = 0;
  this.targetY = 0;
  
  this.lastNode = { x : 0, y : 0 };
  this.nextNode = { x : 0, y : 0 };
  
  this.path = [];
  
  this.ownSails = 0;
  this.ownHulls = 0;
  this.ownCannon = 0;
  this.ownCannonballs = 0;
  this.ownSailors = 0;
  
  this.speed = 0.04;
  
  this.direction = 0;
  
  this.wake;
  
  this.hp = 30;
  this.maxHp = 30;
  
  this.destroyed = false;
  
  this.healCountdown = 450;
  
  this.parentPortId = 6;
  
  this.attackMode = false;
  this.backToPortCountdown = 0;
  
  this.shotVelocity = 0.194;
  this.damage = 5;
  
  this.coolDown = 45;
  this.coolDownProgress = 0;
  
  
  this.init = function(x, y, parentPortId) {
    this.x = x;
    this.y = y;
    this.targetX = x;
    this.targetY = y;
    this.lastNode = { x : x, y : y };
    this.nextNode = { x : x, y : y };
    this.direction = rand(0, 7);
    this.parentPortId = parentPortId;
    this.occupySpace();
    
    this.wake = new ParticleSystem();
    this.wake.setType(1);
    this.wake.setV(-0.2, 0.2, -0.1, 0.1);
    this.wake.setLife(25, 25);
    
    this.setUpdates();
    this.hp = this.maxHp;
  };
  
  
  this.setUpdates = function() {
    this.speed = Ship.sails[this.ownSails] * 0.75;
    this.maxHp = Math.round(Ship.hulls[this.ownHulls] * 0.5);
    this.shotVelocity = Ship.cannon[this.ownCannon] * 0.9;
    this.damage = Math.round(Ship.cannonballs[this.ownCannonballs] * 0.8);
    this.coolDown = Math.round(Ship.sailors[this.ownSailors] * 0.75);
  };
  
  
  this.update = function() {
    
    this.freeSpace();
    
    var bigX = (this.x - 1) / 4;
    var bigY = (this.y - 1) / 4;
    var distToShip = distance(bigX, bigY, ship.x, ship.y); 
    var distToHomePort = distance(bigX, bigY, map.homePort.x, map.homePort.y);
    
    if(rand(0, 1500 * map.pirateShipCounter) == 0) {
      this.attackMode = true;
    }
    
    if(rand(0, 9) == 0) {
      
      if(this.attackMode) {
        
        if(this.path.length == 0 && distToHomePort > 2) {
          var tries = 0;
          var foundSpot = false;
          while(tries < 20 && !foundSpot) {
            tries++;
            var spotX = ((map.homePort.x + randFloat(-1, 1)) * 4) + 1;
            spotX = setInRange(Math.round(spotX), 0, map.gridW - 2);
            var spotY = ((map.homePort.y + randFloat(-1, 1)) * 4) + 1;
            spotY = setInRange(Math.round(spotY), 0, map.gridH - 2);
            if(map.isFreeForPirateShip(spotX, spotY)) {
              this.targetX = spotX;
              this.targetY = spotY;
              this.findPath();
              if(this.path.length > 0) {
                foundSpot = true;
              }
            }
          }
          if(foundSpot) {
            if(rand(0, 99) < ship.numOfSpies) {
              panel.openInfoBox(2);
            }
          }
        }
  
      } else {
        
        var parentPort = map.piratePorts[this.parentPortId];
        
        if(distance(parentPort.x, parentPort.y, ship.x, ship.y) < 5 || parentPort.beingAttacked) {
          this.backToPortCountdown = 600;
          if(distToShip > 2) { 
            var tries = 0;
            var foundSpot = false;
            while(tries < 20 && !foundSpot) {
              tries++;
              var spotX = ((ship.x + randFloat(-1, 1)) * 4) + 1;
              spotX = setInRange(Math.round(spotX), 0, map.gridW - 2);
              var spotY = ((ship.y + randFloat(-1, 1)) * 4) + 1;
              spotY = setInRange(Math.round(spotY), 0, map.gridH - 2);
              if(map.isFreeForPirateShip(spotX, spotY)) {
                this.targetX = spotX;
                this.targetY = spotY;
                this.findPath();
                if(this.path.length > 0) {
                  foundSpot = true;
                }
              }
            }
          }
          
        } else {
          if(this.backToPortCountdown > 0) {
            this.backToPortCountdown--;
            if(this.backToPortCountdown == 0) {
              var tries = 0;
              var foundSpot = false;
              while(tries < 20 && !foundSpot) {
                tries++;
                var spotX = ((parentPort.x + rand(-1, 2)) * 4) + 1;
                var spotY = ((parentPort.y + rand(-1, 2)) * 4) + 1;
                if(map.isFreeForPirateShip(spotX, spotY)) {
                  this.targetX = spotX;
                  this.targetY = spotY;
                  this.findPath();
                  if(this.path.length > 0) {
                    foundSpot = true;
                  }
                }
              }
            }
          }
        }
      }
    }
    
    if(this.coolDownProgress > 0 && !map.paused) {
      this.coolDownProgress--;
    }
    if(this.coolDownProgress == 0) {
      if(distToShip < 3) {
        this.coolDownProgress = this.coolDown;
        var cannonVelocity = { x : ship.x - bigX, y : ship.y - bigY };
        cannonVelocity = normalize(cannonVelocity);
        cannonVelocity.x *= this.shotVelocity;
        cannonVelocity.y *= this.shotVelocity;
        map.pushCannonball(false, bigX, bigY, cannonVelocity, this.damage);
        
      } else if(distToHomePort < 3) {
        this.coolDownProgress = this.coolDown;
        var cannonVelocity = { x : map.homePort.x - bigX, y : map.homePort.y - bigY };
        cannonVelocity = normalize(cannonVelocity);
        cannonVelocity.x *= this.shotVelocity;
        cannonVelocity.y *= this.shotVelocity;
        map.pushCannonball(false, bigX, bigY, cannonVelocity, this.damage);
      }
    }
    
    var lastX = this.x;
    var lastY = this.y;
    
    if(this.path.length > 0) {
      
      var diffX = this.nextNode.x - this.x;
      var diffY = this.nextNode.y - this.y;
      
      var moveVector = normalize({ x : diffX, y : diffY });
      
      var moveX = moveVector.x * (this.speed * 4);
      var moveY = moveVector.y * (this.speed * 4);
      
      if(Math.abs(diffX) > Math.abs(moveX) || Math.abs(diffY) > Math.abs(moveY)) {
        this.x += moveX;
        this.y += moveY;
        
      } else {
        this.x = this.nextNode.x;
        this.y = this.nextNode.y;
        
        this.lastNode.x = this.nextNode.x;
        this.lastNode.y = this.nextNode.y;
        
        this.path.splice(0, 1);
        
        if(this.path.length > 0) {
          if(map.isFreeForPirateShip(this.path[0].x, this.path[0].y)) {
            this.nextNode = this.path[0];
          } else {
            this.findPath();
          }
        }
      }
    }
    this.occupySpace(); 
    
    if(lastX != this.x || lastY != this.y) {
      var pos = map.transform((this.x - 1) / 4, (this.y - 1) / 4);
      this.wake.setEmitter(pos.x, pos.y);
      this.wake.on();
    } else {
      this.wake.off();
    }
    
    if(this.x < lastX && this.y < lastY) {
      this.direction = 0;
    } else if(this.x == lastX && this.y < lastY) {
      this.direction = 1;
    } else if(this.x > lastX && this.y < lastY) {
      this.direction = 2;
    } else if(this.x > lastX && this.y == lastY) {
      this.direction = 3;
    } else if(this.x > lastX && this.y > lastY) {
      this.direction = 4;
    } else if(this.x == lastX && this.y > lastY) {
      this.direction = 5;
    } else if(this.x < lastX && this.y > lastY) {
      this.direction = 6;
    } else if(this.x < lastX && this.y == lastY) {
      this.direction = 7;
    }
    
    this.healCountdown--;
    if(this.healCountdown == 0) {
      this.healCountdown = 450;
      if(this.hp < this.maxHp) {
        this.hp++;
      }
    }
  };
  
  
  this.findPath = function() {
    var start = { x : Math.round(this.x), y : Math.round(this.y) };
    var end = { x : Math.round(this.targetX), y : Math.round(this.targetY) };
    var pathFinding = new PathFinding();
    this.path = pathFinding.find(start, end, function(x, y) {
      return map.isFreeForPirateShip(x, y);
    });
    if(this.path.length > 0) {
      this.nextNode = this.path[0];
    }
  };
  
  
  this.freeSpace = function() {
    map.setPirateShipSpace(this.lastNode.x, this.lastNode.y, 0);
    map.setPirateShipSpace(this.nextNode.x, this.nextNode.y, 0);
  };
  
  
  this.occupySpace = function() {
    map.setPirateShipSpace(this.lastNode.x, this.lastNode.y, 1);
    map.setPirateShipSpace(this.nextNode.x, this.nextNode.y, 1);
  };
  
  
  this.dealDamage = function(damage) {
    if(!this.destroyed) {
      this.hp -= damage;
      this.healCountdown = 450;
      if(this.hp <= 0) {
        this.destroyed = true;
        ship.gold += 100;
        this.freeSpace();
      }
    }
  };
  
  
  this.isHit = function(x, y) {
    var hitX = (this.x - 1) / 4;
    var hitY = (this.y - 1) / 4;
    
    return distance(hitX, hitY, x, y) < 0.4;
  };
  
  
  this.draw = function() {
    
    var pos = map.transform((this.x - 1) / 4, (this.y - 1) / 4);
    
    if(pos.x > (viewport.x - 300) && pos.x > (viewport.x + viewport.w + 300) &&
       pos.y > (viewport.y - 300) && pos.y > (viewport.y + viewport.h + 300)) {

      img.drawSprite("ship", pos.x - 60, pos.y - 90, 120, 120, this.direction, 0);
      
      if(!this.destroyed && this.hp < this.maxHp) {
        c.strokeStyle = "rgba(0, 0, 0, 0.4)";
        c.strokeRect(pos.x - 30.5, pos.y - 50.5, 61, 5);
        
        var hpPercentage = 100 * (this.hp / this.maxHp);
        if(hpPercentage <= 10) {
          c.fillStyle = "#f00";
        } else if(hpPercentage <= 40) {
          c.fillStyle = "#fe0";
        } else {
          c.fillStyle = "#0e0";
        }
        c.fillRect(pos.x - 30, pos.y - 50, 0.6 * hpPercentage, 4);
      }
    }
  };
  
  
  this.drawWake = function() {
    this.wake.draw();
  };
  
}