
<?php

abstract class Animal
{
    protected $symbol; //символ на карте
    protected $x;      //координата
    protected $y;      //координата
    protected $name;   //имя животного
    protected $field;  //карта класса Field
    protected $vision; //дальность обзора

    abstract protected function tryToMove();
    abstract protected function setSymbol($symbol);
    abstract protected function setVision($vision);

    //Методы получения к защищенным свойствам для других классов
    public function getX()
    {
        return $this->x;
    }

    public function getY()
    {
        return $this->y;
    }

    //Методы установки защищенных свойств
    public function setX($x)
    {
        $this->x = $x;
    }

    public function setY($y)
    {
        $this->y = $y;
    }

    public function setField(Field $field)
    {
        $this->field = $field;
    }

    public function unsetField()
    {
        $this->field = NULL;
    }

    //Называем животное
    public function __construct($name)
    {
        $this->name = $name;
    }

    //Метод возвращения символа для вывода на карте
    public function getSymbol()
    {
        return $this->symbol;
    }

    //Метод передвижения в определенную координату
    protected function moveTo($x, $y)
    {
        if ($this->x == $x && $this->y == $y) {
            echo "Я, {$this->name}, стою на месте.\n";
        } else {
            echo "Я, {$this->name}, хожу x:{$x}, y:{$y}.\n";
        }
        $this->x = $x;
        $this->y = $y;
    }

    //Метод случайного хода без обдумывания побега или охоты
    protected function freeMove(array $possibleMoves)
    {
        //Выбираем случайный ход из возможных и ходим
        $randTurn = array_rand($possibleMoves);
        $this->moveTo($possibleMoves[$randTurn]->x, $possibleMoves[$randTurn]->y);
    }

    //Метод поиска лучшего хода
    protected function searchBestMove(array $foundAnimals, array $possibleMoves, callable $countPoints)
    {
        //Очки за лучшиий за ход мыши. -INF из-за случаев когда лучший ход приносит 0 баллов
        $pointsMax = -INF;
        $bestMove  = NULL;
        foreach ($possibleMoves as $move)
        {
            $points = $countPoints($foundAnimals, $move);
            //Если ход выдал максимальное количество очков - он становится потенциально лучшим ходом
            if ($points > $pointsMax) {
                $pointsMax = $points;
                $bestMove = $move;
            }
        }
        //Возвращаем лучший ход
        return $bestMove;
    }
}

class Mouse extends Animal
{
    private static $counterOfSymbols = 1; //идентификационный символ-номер на карте

    public function __construct($name)
    {
        parent::__construct($name);
        if ($this->symbol == NULL) {
            $this->setSymbol(self::$counterOfSymbols++);
        }
        $this->setVision(4);
    }

    //Метод инициадизации символа
    public function setSymbol($symbol)
    {
        $this->symbol = $symbol;
    }

    //Метод инициализации дальности обзора
    public function setVision($vision)
    {
        $this->vision = $vision;
    }

    //Метод хода
    public function tryToMove()
    {
        $foundAnimals  = $this->field->searchForAnimals($this->x, $this->y, $this->vision);
        $possibleMoves = $this->searchPossibleMoves();
        if ($foundAnimals["Cat"] != NULL) {
            echo "У мышки {$this->name} рядом кошка. ";
            $bestMove = $this->searchBestMove($foundAnimals, $possibleMoves, array($this, "countPoints"));
            $this->moveTo($bestMove->x, $bestMove->y);
        } else {
            echo "Кошек рядом нет. ";
            $this->freeMove($possibleMoves);
        }
    }

    //Метод поиска возможных ходов
    private function searchPossibleMoves()
    {
        //Возможые ходы для мышки (4 стороны)
        $moves = [
            new Move($this->x,     $this->y - 1),
            new Move($this->x + 1, $this->y),
            new Move($this->x,     $this->y + 1),
            new Move($this->x - 1, $this->y),
        ];
        //Ищем возможные ходы с помощью метода canIMoveTo
        //$possibleMoves = array_filter($moves, array($this->field, "canIMoveTo"));
        $possibleMoves = array_filter($moves, function($move) {
            //Если ход за пределы карты или клетка занята - нет
            if ($move->x < 1                         ||
                $move->y < 1                         ||
                $move->x > $this->field->getWidth()  ||
                $move->y > $this->field->getHeight() ||
                $this->field->getAnimal($move->x, $move->y)) {
                return FALSE;
            } else {
                return TRUE;
            }
        });
        //Добавляем ход ожидания на месте
        $possibleMoves[] = new Move($this->x, $this->y);
        //Ключи должны идти с нуля
        $possibleMoves = array_values($possibleMoves);
        //Возвращаем результат
        return $possibleMoves;
    }

    //Метод подсчета очков за ход
    protected function countPoints (array $foundAnimals, Move $move)
    {
        /**
         * Оценка каждого хода.
         * Приоритет 1: Количество клеток до врага. Их должно быть как можно больше. Коэффициент 100
         * Приоритет 2: Количество клеток до ближайших углов в сумме. Как можно больше, чтобы не забиться в угол. Коэфициент 10
         * Приоритет 3: Количество клеток до одной линии с кошкой, удобная позиция для зажатия в угол.
         * Приоритет 4: Количество клеток до собаки. Может стать приоритетом 2 в ситуации когда только собака может спасти от съедения кошкой
         */
        if (!count($foundAnimals["Cat"])) {
            throw new Exception("Ошибка. Должна быть как минимум одна кошка.");
        }
        //Ищем ближайшего врага и считаем шаги до него
        $nearbyEnemy    = $this->field->searchNearbyAnimal($move->x, $move->y, $foundAnimals["Cat"]);
        $stepsToEnemy   = Field::countSteps($move->x, $move->y, $nearbyEnemy->x, $nearbyEnemy->y);
        //Не даем очки, если один шаг чтобы этот ход был максимально плохим вариантом
        if ($stepsToEnemy == 1) {
            $pointsForEnemy = 0;
        } else {
            $pointsForEnemy = $stepsToEnemy * 100;
        }
        //Если оказались на одной линии с кошкой, то плохо, так нас легко будет поймать
        if ($move->x == $nearbyEnemy->x || $move->y == $nearbyEnemy->y) {
            $pointsForOneLine = -30;
        } else {
            $pointsForOneLine = 10 - min(abs($move->x - $nearbyEnemy->x), abs($move->y - $nearbyEnemy->y));
        }
        //Если есть рядом собаки - используем их в плане побега
        if (isset($foundAnimals["Dog"]) && $foundAnimals["Dog"]) {
            $nearbyDog  = $this->field->searchNearbyAnimal($move->x, $move->y, $foundAnimals["Cat"]);
            $stepsToDog = Field::countSteps($move->x, $move->y, $nearbyDog->x, $nearbyDog->y);
            //Тот случай когда собака может спамти мышке жизнь
            if ($stepsToDog == 1 && $stepsToEnemy == 1) {
                $pointsForDog = 90;
                //В остальных случаях это наименьший по очкам приоритет
            } else{
                $pointsForDog = -$stepsToDog;
            }
            //Если собак нету - даем отрицательные очки
        } else {
            $pointsForDog = -$this->field->getWidth();
        }
        //Считаем очки за степень приближения к ближайшему краю, стараемся быть дальше от него
        $pointsForCorner = $this->field->countStepsToCorners($move->x, $move->y) * 10;
        //Считаем общее число очков за ход
        $points = $pointsForEnemy  + $pointsForOneLine + $pointsForDog + $pointsForCorner;
        //Если этот ход обогнал лучший результат - он становится лучшим ходом
        return $points;
    }
}

class Cat extends Animal
{
    private $movesInARow      = 0;     //кол-во ходов подряд
    private $turnWhenCatSleep = 8;     //правило "на каком ходу подряд кошка засыпает"
    private $sleepMode        = FALSE; //переключатель спящего режима

    public function __construct($name)
    {
        parent::__construct($name);
        $this->setSymbol("K");
        $this->setVision(INF);
    }

    //Метод инициадизации символа
    public function setSymbol($symbol)
    {
        $this->symbol = $symbol;
    }

    //Метод инициализации дальности обзора
    public function setVision($vision)
    {
        $this->vision = $vision;
    }

    //Метод хода
    public function tryToMove()
    {
        //Если спим - то...
        if($this->isSleeping()) {
            //...переключатель сна перейдет в отрицательное положение
            $this->sleepMode = FALSE;
            //...на поле, показываем результат прошлого хода, мы будем со спящим сиволом
            $this->symbol = "@";
            //...счетчик ходов подряд обнулится
            $this->movesInARow = 0;
            echo "Кошка спит :3\n";
            return;
        } else {
            $this->symbol = "K";
        }
        //Ищем животное в дальности обзора
        $foundAnimals  = $this->field->searchForAnimals($this->x, $this->y, $this->vision);
        //Присваиваем полям найденные результаты
        $possibleMoves = $this->searchPossibleMoves($foundAnimals);
        //Если нельзя сдвинуться - стоим
        if (!count($possibleMoves)) {
            echo "Стою на месте.\n";
        } else {
            $bestMove = $this->searchBestMove($foundAnimals, $possibleMoves, array($this, "countPoints"));
            //Если можно съесть мышь по данным координатам - едим
            if ($this->canIEatIt($bestMove->x, $bestMove->y, $foundAnimals)) {
                $this->eatIt($bestMove->x, $bestMove->y);
                //Если нет - передвигаемся в эту клетку
            } else {
                $this->moveTo($bestMove->x, $bestMove->y);
            }
            //Прибавляем счетчик ходов подряд
            $this->movesInARow++;
        }
    }

    //Метод проверки состояния сна
    private function isSleeping()
    {   //Если ходили заданное по правилам количество ходов или спим после трапезы
        if ($this->movesInARow == $this->turnWhenCatSleep || $this->sleepMode == TRUE) {
            return TRUE;
        } else {
            return FALSE;
        }
    }

    //Метод поиска возможных ходов
    private function searchPossibleMoves(array $foundAnimals)
    {
        $moves = NULL;
        $possibleMoves = NULL;
        //Возможые ходы для кошки (8 сторон);
        for ($x = $this->x - 1; $x <= $this->x + 1; $x++) {
            for ($y = $this->y - 1; $y <= $this->y + 1; $y++) {
                //Стоять на месте по правилам без причины нельзя
                if ($x == $this->x && $y == $this->y) {
                    continue;
                }
                $moves[] = new Move($x, $y);
            }
        }
        /**
        $moves["up"]         = array('x' => $this->x,     'y' => $this->y - 1);
        $moves["up-right"]   = array('x' => $this->x + 1, 'y' => $this->y - 1);
        $moves["right"]      = array('x' => $this->x + 1, 'y' => $this->y);
        $moves["right-down"] = array('x' => $this->x + 1, 'y' => $this->y + 1);
        $moves["down"]       = array('x' => $this->x,     'y' => $this->y + 1);
        $moves["down-left"]  = array('x' => $this->x - 1, 'y' => $this->y + 1);
        $moves["left"]       = array('x' => $this->x - 1, 'y' => $this->y);
        $moves["left-up"]    = array('x' => $this->x - 1, 'y' => $this->y - 1);
         */
        foreach ($moves as $move) {
            //Если на этой клетке собака - сразу отбрасываем этот ход
            if ($this->field->howManyAnimalsNearTheCage($move->x, $move->y, "Dog") == 0) {
                //Если там можно съесть мышь или походить - это возможных ход
                if ($this->canIEatIt($move->x, $move->y, $foundAnimals)) {
                    $possibleMoves[] = $move;
                } elseif ($this->field->canIMoveTo($move->x, $move->y)) {
                    $possibleMoves[] = $move;
                }
            }
        }
        //Добавляем ход "ожидания на месте"
        $possibleMoves[] = new Move($this->x, $this->y);
        //Возвращаем результат
        return $possibleMoves;
    }

    //Метод подсчета очков за ход
    protected function countPoints(array $foundAnimals, Move $move)
    {
        /**
         * Приоритет 1: Мышку можно съесть. 9999 очков
         * Приоритет 2: Количество клеток до врага. Их должно быть как можно меньше. Коэффициент 100.
         * Приоритет 3: Количество клеток до одной линии с мышью, удобная позиция для зажатия в угол.
         */
        //Ищем ближайшего врага и считаем шаги до него
        $nearbyEnemy = $this->field->searchNearbyAnimal($move->x, $move->y, $foundAnimals["Mouse"]);
        $stepsToEnemy = Field::countSteps($move->x, $move->y, $nearbyEnemy->x, $nearbyEnemy->y);
        //Если можно съесть мышь по указанным координатам - это однозначно лучший ход
        if ($this->canIEatIt($move->x, $move->y, $foundAnimals)) {
            $pointsForEnemy = 9999;
        } else {
            $pointsForEnemy = -$stepsToEnemy * 100;
        }
        //Если кошка на одной линии с мышкой
        if ($move->x == $nearbyEnemy->x || $move->y == $nearbyEnemy->y) {
            $pointsForOneLine = 99;
        } else {
            $pointsForOneLine = min(abs($move->x - $nearbyEnemy->x), abs($move->y - $nearbyEnemy->y));
        }
        //Считаем общее очков за ход
        $points = $pointsForEnemy + $pointsForOneLine;
        //Если этот ход обогнал лучший результат - он становится лучшим ходом
        return $points;
    }

    //Метод возможности съедения мышки по данным координатам
    private function canIEatIt($x, $y, array $foundAnimals)
    {
        //Если по данным координатам нет мышки - нет
        if (!$this->field->getAnimal($x, $y) instanceof Mouse) {
            return FALSE;
            //Если там мышка - очевидно возомжно, но еще не можно
        } else {
            //Обнажили зубки
            echo "Пытаюсь съесть {$this->field->getAnimal($x, $y)->name}. ";
            //В переменной oneLine считаем количество мышей, которые рядом с друг другом
            foreach ($foundAnimals["Mouse"] as $mouse) {
                if ($this->field->howManyAnimalsNearTheCage($mouse->x, $mouse->y, "Mouse") > 1) {
                    echo "Мыши защищают друг друга. ";
                    return FALSE;
                }
            }
            return TRUE;
        }
    }

    //Метод поедения несчастного объекта
    private function eatIt($x, $y)
    {
        //Удаление элемента массива по значению
        $this->field->removeAnimal($x, $y);
        //Ход на освободившуюся клетку
        $this->moveTo($x, $y);
        //Переход в спящий режим
        $this->sleepMode = TRUE;
    }

}

class Dog extends Animal {

    public function __construct($name)
    {
        parent::__construct($name);
        $this->setSymbol("D");
    }

    public function setSymbol($symbol)
    {
        $this->symbol = $symbol;
    }

    //Метод инициализации дальности обзора
    public function setVision($vision)
    {
        $this->vision = $vision;
    }

    //Метод хода
    public function tryToMove()
    {
        $possibleMoves = $this->searchPossibleMoves();
        $this->freeMove($possibleMoves);
    }

    //Метод поиска возможных ходов
    private function searchPossibleMoves()
    {
        $moves = NULL;
        //Возможые ходы для собаки (8 сторон)
        for ($x = $this->x - 2; $x <= $this->x + 2; $x += 2) {
            for ($y = $this->y - 2; $y <= $this->y + 2; $y += 2) {
                if ($x == $this->x && $y == $this->y) {
                    continue;
                }
                $moves[] = new Move($x, $y);
            }
        }
        /**
        $moves["up"]         = array('x' => $this->x,   'y' => $this->y-2);
        $moves["up-right"]   = array('x' => $this->x+2, 'y' => $this->y-2);
        $moves["right"]      = array('x' => $this->x+2, 'y' => $this->y);
        $moves["right-down"] = array('x' => $this->x+2, 'y' => $this->y+2);
        $moves["down"]       = array('x' => $this->x,   'y' => $this->y+2);
        $moves["down-left"]  = array('x' => $this->x-2, 'y' => $this->y+2);
        $moves["left"]       = array('x' => $this->x-2, 'y' => $this->y);
        $moves["left-up"]    = array('x' => $this->x-2, 'y' => $this->y-2);
         */
        //$possibleMoves   = array_filter($moves, array($this->field, "canIMoveTo"));
        $possibleMoves = array_filter($moves, function($move) {
            //Если ход за пределы карты или клетка занята - нет
            if ($move->x < 1                         ||
                $move->y < 1                         ||
                $move->x > $this->field->getWidth()  ||
                $move->y > $this->field->getHeight() ||
                $this->field->getAnimal($move->x, $move->y)) {
                return FALSE;
            } else {
                return TRUE;
            }
        });
        if (!count($possibleMoves)) {
            //Добавляем ход "ожидания на месте"
            $possibleMoves[] = new Move($this->x, $this->y);
        }
        $possibleMoves   = array_values($possibleMoves);
        //Возвращаем результат
        return $possibleMoves;
    }


}

class Field {
    private $width;              //ширина
    private $height;             //высота
    private $numberOfTurns = 30; //количество ходов
    private $animals = array();  //массив животных

    //Задаем ширину, высоту
    public function __construct($width, $height)
    {
        $this->width = $width;
        $this->height = $height;
    }

    //Метод получения защищенных свойств для других классов
    public function getWidth()
    {
        return $this->width;
    }

    public function getHeight()
    {
        return $this->height;
    }

    //Метод размещения животного на карте
    public function addAnimal(Animal $animal)
    {
        //Добавляем животное в список
        $this->animals[] = $animal;
        //Передаем карту в поле животного для удобства
        $animal->setField($this);
        //Координаты могут быть заняты, если мы вручную их забиваем тестируя возможные ситуации
        if ($animal->getX() == NULL && $animal->getY() == NULL) {
            //Получаем свободные координаты
            $this->getRandomCoords($animal);
        }
    }

    //Метод получения свободных координат
    private function getRandomCoords(Animal $animal)
    {
        //Рандомим пока не найдем пустую клетку
        $i = 0;
        do {
            $x = mt_rand(1, $this->width);
            $y = mt_rand(1, $this->height);
        } while ($this->getAnimal($x, $y) && ++$i < 100);
        if ($i == 100) {
            throw new Exception("Превышено количество попыток в методе getRandomCoords!");
        }

        //Инициализурем удачные координаты
        $animal->setX($x);
        $animal->setY($y);
    }

    //Метод определения возможности животного походить по указанным координатам
    public function canIMoveTo($x, $y)
    {
        //Если ход за пределы карты или клетка занята - нет
        if ($x < 1             ||
            $y < 1             ||
            $x > $this->width  ||
            $y > $this->height ||
            $this->getAnimal($x, $y)) {
            return FALSE;
        } else {
            return TRUE;
        }
    }

    //Метод подсчета шагов до ближайших углов
    public function countStepsToCorners($x, $y)
    {
        //Находимся ли мы слева от центра или справа, вверху или внизу
        $stepsToCornerX = ($x < $this->width/2)  ? $x - 1 : $this->width - $x;
        $stepsToCornerY = ($y < $this->height/2) ? $y - 1 : $this->height - $y;
        return $stepsToCornerX + $stepsToCornerY;
    }


    //Метод получения объекта по координатам из массива животных
    public function getAnimal ($x, $y)
    {
        foreach ($this->animals as $animal)
        {
            if ($x == $animal->getX() && $y == $animal->getY()) {
                return $animal;
            }
        }
    }

    //Метод удаления животного из списка
    public function removeAnimal($x, $y)
    {
        if(($key = array_search($this->getAnimal($x, $y), $this->animals)) !== FALSE){
            $this->animals[$key]->unsetField();
            unset($this->animals[$key]);
        }
    }

    //Метож вывода карты
    private function showField($turn)
    {
        for ($y = 0; $y <= $this->height; $y++) {
            for ($x = 0; $x <= $this->width; $x++) {
                //Если первая строка
                if ($y == 0) {
                    //Три пробела, если первый символ оси
                    if ($x == 0) {
                        $array[$y][$x] = str_pad("", 3);
                    //Номер оси X, если не первый
                    } else {
                        $array[$y][$x] = str_pad($x, 3);
                    }
                //Если первый символ оси X, печатаем номер строки ($y)
                } elseif ($x == 0) {
                    $array[$y][$x] = str_pad($y, 3);
                //Игровая информация
                } else {
                    $array[$y][$x] = str_pad(".", 3);
                }
                if     ($y == 1 && $x == $this->width) {$array[$y][$x + 1] = "  Ход: {$turn}";}
                elseif ($y == 2 && $x == $this->width) {$array[$y][$x + 1] = "  Мышек: {$this->countAnimals('Mouse')}";}
                elseif ($y == 3 && $x == $this->width) {$array[$y][$x + 1] = "  Кошек: {$this->countAnimals('Cat')}";}
                elseif ($y == 4 && $x == $this->width) {$array[$y][$x + 1] = "  Собак: {$this->countAnimals('Dog')}";}
            }
        }
        foreach ($this->animals as $animal) {
            $array[$animal->getY()][$animal->getX()] = str_pad($animal->getSymbol(), 3);
        }
        //Выводи массив как строку
        foreach ($array as $string) {
            echo implode($string);
            echo "\n";
        }
    }

    //Метод игры
    public function startGame()
    {
        //Делаем заданное заранее количество ходов
        for ($turn = 0; $turn <= ($this->numberOfTurns); $turn++) {
            //Выводим поле
            $this->showfield($turn);
            //Каждое животное делает ход
            //Так как в цикле foreach копия массива надо проверять данные с изменениями через ссылку
            for ($i = 0; $i < count($this->animals); $i++) {
                //Животное делает ход
                $this->animals[$i]->tryToMove();
                //Если всех мышей съели - конец игры
                if ($this->countAnimals("Mouse") == 0) {
                    echo "Конец игры.";
                    return;
                }
                $this->animals = array_values($this->animals);
            }

            echo "\n";
        }
    }

    //Метод поиска животных в определенном обзоре
    public function searchForAnimals($x, $y, $vision)
    {
        $foundAnimals = array();
        foreach ($this->animals as $animal) {
            $animalType = get_class($animal);
            //Если обнаружили новый тип животных - добавляем его как ключ
            if (!array_key_exists($animalType, $foundAnimals)) {
                $foundAnimals[$animalType] = NULL;
            }
            //Если нашли самого себя - не добавляем оьъект в массив найденных животных
            if ($animal->getX() == $x && $animal->getY() == $y) {
                continue;
            } elseif (($animal->getX() >= $x - $vision && $animal->getX() <= $x + $vision) || $vision == INF) {
                if (($animal->getY() >= $y - $vision && $animal->getY() <= $y + $vision) || $vision == INF) {
                    $foundAnimals[$animalType][] = $animal;
                }
            }
        }
        //Возвращаем результат
        return $foundAnimals;
    }

    //Метод подсчета животных. Считает определенных животных
    private function countAnimals($nameOfTheAnimal)
    {
        $counter = 0;
        //Если нужное животное есть в массиве - прибавляем счетчик
        foreach ($this->animals as $animal) {
            if ($animal instanceof $nameOfTheAnimal) {
                $counter++;
            }
        }
        return $counter;
    }

    //Метод определяющий наличие опреденного вида животных с данными координатами
    public function howManyAnimalsNearTheCage($x, $y, $typeOfAnimal)
    {
        $count = 0;
        foreach ($this->animals as $animal)
        {
            //Наши координаты не влияют на ответ на поставленный вопрос
            if ($animal->getX() == $x && $animal->getY() == $y) {
                continue;
            }
            if ($animal instanceof $typeOfAnimal) {
                if (self::countSteps($x, $y, $animal->getX(), $animal->getY()) == 1) {
                    $count++;
                }
            }
        }
        //В остальных случаях ответ - нет
        return $count;
    }

    //Метод подсчета шагов между двумя точками
    public static function countSteps($point1X, $point1Y, $point2X, $point2Y)
    {
        //Подсчет шагов по оси X
        $countStepsX = abs($point1X - $point2X);
        //ПОдсчет шагов по оси Y
        $countStepsY = abs($point1Y - $point2Y);
        //Возвращаем наибольшее
        return max($countStepsX, $countStepsY);
    }

    //Метод нахождения ближайшего животного из определенного массива
    public function searchNearbyAnimal($x, $y, array $animals)
    {
        //Лучший результат по умолчанию
        $stepsNearestAnimal = INF;
        foreach ($animals as $animal) {
            //Считаем  шаги между животным и координатами
            $countSteps = self::countSteps($x, $y, $animal->getX(), $animal->getY());
            //Если меньше лучшего результата - это лучший результат
            if ($countSteps < $stepsNearestAnimal) {
                $nearbyAnimal = $animal;
                $stepsNearestAnimal = $countSteps;
                //Если на одном расстоянии с результатом - продалжаем поиск
            }
        }
        //Возвращаем ближайшее животное
        return $nearbyAnimal;
    }
}

//Класс с координатами хода
class Move {
    public $x;
    public $y;

    public function __construct ($x, $y)
    {
        $this->x = $x;
        $this->y = $y;
    }
}


//Создаем карту
$field  = new Field(10, 10);
//Создаем и именум зверье
$mouse1 = new Mouse("mouse1");
$field->addAnimal($mouse1);
$mouse2 = new Mouse("mouse2");
$field->addAnimal($mouse2);
$mouse3 = new Mouse("mouse3");
$field->addAnimal($mouse3);
$cat1   = new Cat("cat1");
$field->addAnimal($cat1);
$cat2   = new Cat("cat2");
$field->addAnimal($cat2);
$dog1   = new Dog("dog1");
$field->addAnimal($dog1);
$dog2   = new Dog("dog2");
$field->addAnimal($dog2);
//Начинаем игру
$field->startGame();


//Тест на... стояние на месте
/**
$field  = new Field(5, 6);
$mouse1 = new Mouse("mouse1");
$mouse1->setX(1);
$mouse1->setY(1);
$mouse1->setSymbol("1");
$field->addAnimal($mouse1);
$cat1   = new Cat("cat1");
$cat1->setX(3);
$cat1->setY(1);
$field->addAnimal($cat1);
$cat2   = new Cat("cat2");
$cat2->setX(1);
$cat2->setY(3);
$field->addAnimal($cat2);
$field->startGame();
 */

//Тест на два огня
/**
$field  = new Field(5, 6);
$mouse1 = new Mouse("mouse1");
$mouse1->x = 3;
$mouse1->y = 3;
$mouse1->symbol = 1;
$field->addAnimal($mouse1);
$cat1   = new Cat("cat1");
$cat1->x = 1;
$cat1->y = 3;
$field->addAnimal($cat1);
$cat2   = new Cat("cat2");
$cat2->x = 5;
$cat2->y = 3;
$field->addAnimal($cat2);
$dog1 = new Dog("dog1");
$dog1->x = 5;
$dog1->y = 6;
$field->addAnimal($dog1);
$field->startGame();
 */

/**
//Тест на мышинную оборону
$field  = new Field(10, 10);
$cat1   = new Cat("cat1");
$cat1->setX(2);
$cat1->setY(1);
$field->addAnimal($cat1);
$mouse1 = new Mouse("mouse1");
$mouse1->setX(1);
$mouse1->setY(1);
$mouse1->setSymbol("1");
$field->addAnimal($mouse1);
$mouse2 = new Mouse("mouse2");
$mouse2->setX(2);
$mouse2->setY(2);
$mouse2->setSymbol("2");
$field->addAnimal($mouse2);
$mouse3 = new Mouse("mouse3");
$mouse3->setX(3);
$mouse3->setY(3);
$mouse3->setSymbol("3");
$field->addAnimal($mouse3);
$field->startGame();
 */

//Тест на пирамиду котов
/**
$field  = new Field(7, 7);
$mouse1 = new Mouse("mouse1");
$mouse1->setX(3);
$mouse1->setY(4);
$mouse1->setSymbol("1");
$field->addAnimal($mouse1);
$cat1    = new Cat("cat1");
$cat1->setX(1);
$cat1->setY(3);
$field->addAnimal($cat1);
$cat2    = new Cat("cat2");
$cat2->setX(2);
$cat2->setY(2);
$field->addAnimal($cat2);
$cat3    = new Cat("cat3");
$cat3->setX(3);
$cat3->setY(1);
$field->addAnimal($cat3);
$cat4    = new Cat("cat4");
$cat4->setX(4);
$cat4->setY(2);
$field->addAnimal($cat4);
$cat5    = new Cat("cat5");
$cat5->setX(5);
$cat5->setY(3);
$field->addAnimal($cat5);
$field->startGame();
 */

//Тест на два огня #2
/**
$field  = new Field(8, 8);
$mouse1 = new Mouse("mouse1");
$mouse1->setX(3);
$mouse1->setY(4);
$mouse1->setSymbol("1");
$field->addAnimal($mouse1);
$cat1 = new Cat("cat1");
$cat1->setX(1);
$cat1->setY(3);
$field->addAnimal($cat1);
$cat2 = new Cat("cat2");
$cat2->setX(5);
$cat2->setY(5);
$field->addAnimal($cat2);
$field->startGame();
 */