/**
  * @param Cell $cell
  *
  * @return Cell
  * @throws AIException
  */
 private static function attackCell(Cell $cell) : Cell
 {
     if ($cell->hasFlag(CellModel::FLAG_DEAD)) {
         throw new AIException("cell: {$cell->getId()} already flagged as *DEAD*");
     }
     return CellModel::switchPhase($cell);
 }
 /**
  * @param Cell  $cell
  * @param int[] $paths
  *
  * @return Cell[]
  */
 protected function processPaths(Cell $cell, array $paths) : array
 {
     $cells = [];
     foreach ($paths as $path) {
         try {
             $cells[] = $this->processPath($cell->getBattlefield(), $path, $cell->getCoordinate());
         } catch (CellException $e) {
             continue;
         }
     }
     return $cells;
 }
 public static function isShipDead(Cell $cell) : bool
 {
     if (!$cell->hasFlag(static::FLAG_DEAD_SHIP)) {
         return false;
     }
     foreach ((new PathProcessor($cell->getCoordinate()))->getAdjacentCells($cell->getBattlefield(), 4, static::FLAG_SHIP) as $cell) {
         if (!$cell->hasFlag(static::FLAG_DEAD_SHIP)) {
             return false;
         }
     }
     return true;
 }
 /**
  * @since 3.5
  *
  * @param Cell $cell
  *
  * @return int
  */
 private function chooseStrategy(Cell $cell) : int
 {
     $processor = new PathProcessor($cell->getCoordinate());
     $battlefield = $cell->getBattlefield();
     foreach (static::$strategyMap as $path => $strategy) {
         $processor->setPath($path);
         /** @var Cell $cell */
         if (null !== ($cell = $battlefield->getCellByCoordinate($processor->calculateNextCoordinate()))) {
             if ($cell->hasFlag(CellModel::FLAG_DEAD_SHIP)) {
                 return $strategy;
             }
         }
     }
     return AIStrategyProcessor::STRATEGY_BOTH;
 }
 /**
  * @param Cell $cell
  *
  * @return Game
  * @throws GameProcessorException
  */
 public function processTurn(Cell $cell) : Game
 {
     $game = $cell->getBattlefield()->getGame();
     if (null !== $game->getResult()) {
         throw new GameProcessorException("game: {$game->getId()} already has result");
     }
     foreach ($game->getBattlefields() as $battlefield) {
         $attacker = $battlefield->getPlayer();
         if ($this->processPlayerTurnOnBattlefields($game, $attacker, $cell)) {
             $result = (new GameResult())->setPlayer($attacker);
             $game->setResult($result);
             break;
         }
     }
     return $game;
 }
 public static function flagWaterAroundShip(Cell $cell)
 {
     $processor = new PathProcessor($cell->getCoordinate());
     $battlefield = $cell->getBattlefield();
     $cells = $processor->getAdjacentCells($cell->getBattlefield(), 4, CellModel::FLAG_SHIP);
     $cells[$cell->getCoordinate()] = $cell;
     foreach ($cells as $cell) {
         foreach ($processor->reset($cell->getCoordinate())->getAdjacentCells($battlefield, 1, 0, CellModel::FLAG_SHIP) as $waterCell) {
             CellModel::switchPhase($waterCell, CellModel::FLAG_SKIP);
         }
     }
 }