<?php
error_reporting(-1);

class field{
	public $size = 8;
	public $cat = 2;
	public $mouse = 15;
	
	public $animals = array();
	public static $field = array();
	public $xy = array();
	public $record = array();
	
	function create_field(){
		for($i=0;$i<$this->size;++$i){
			$arr = array();
			for($b=0;$b<$this->size;++$b){
				$arr[] = ".";
			}
			$this->field[] = $arr;
		}
	}
	
	function add_animals(){
		for($i=1;$i<=$this->cat+$this->mouse;++$i){
			$animal_name = $i>$this->cat?"mouse":"cat";
			$animal = new $animal_name;
			
			do{
				$xy = array(rand(0, $this->size), rand(0, $this->size));
			}while(
				$this->field[$xy[1]][$xy[0]] !== "."
			);
			$animal->xy = $xy;
			$this->field[$xy[1]][$xy[0]] = $i>$this->cat?"M":"C";	
			
			$this->animals[] = $animal;
		}
		$this->record[] = $this->field;
	}
	
	function move($num){
		for($q=0;$q<$num;++$q){
		foreach($this->animals as $obj){
			if(get_class($obj) == "mouse"){
				$moves = $this->possible_moves($obj, "mouse");
					
				$mouse_sight_zones = array(array(-3,-3,7,3,array(0,-1)), array(1,-3,3,7,array(1,0)), array(-3,1,7,3,array(0,1)), array(-3,-3,3,7,array(-1,0)));
				$danger_zones = array();
					
				foreach($mouse_sight_zones as $arr){
					for($y=0;$y<$arr[3];++$y){	
						for($x=0;$x<$arr[2];++$x){
							if($this->field[($obj->xy[1]+$y+$arr[1])][($obj->xy[0]+$x+$arr[0])] == "C"){
								$direction = $arr[4];
								if(!array_search($arr, $danger_zones)){
									$danger_zones[] = $direction;
								}									
							}
						}
					}
				}		
					
				$moves = $this->my_array_diff($moves, $danger_zones);
					
				$move = $moves[array_rand($moves)];
				$this->field[$obj->xy[1]][$obj->xy[0]] = ".";
				$obj->xy[0]+=$move[0];
				$obj->xy[1]+=$move[1];
				$this->field[$obj->xy[1]][$obj->xy[0]] = "M";
			}	
		}
		foreach($this->animals as $obj){
			if(get_class($obj) == "cat"){
				if($obj->sleep == TRUE){
					$obj->sleep = FALSE;
					continue;
				}

				$moves = $this->possible_moves($obj, "cat");
				
				$cat_sight_zones = array(array(-$this->size,-$this->size,(($this->size)*2)+1,$this->size,array(0,-1)), array(1,-$this->size,$this->size,(($this->size)*2)+1,array(1,0)), array(-$this->size,1,(($this->size)*2)+1,$this->size,array(0,1)), array(-$this->size,-$this->size,$this->size,(($this->size)*2)+1,array(-1,0)));
				$wanted_zones = array();
				
				foreach($cat_sight_zones as $arr){
					for($y=0;$y<$arr[3];++$y){	
						for($x=0;$x<$arr[2];++$x){
							if($this->field[($obj->xy[1]+$y+$arr[1])][($obj->xy[0]+$x+$arr[0])] == "M"){
								$direction = $arr[4];
								if(!array_search($arr, $wanted_zones)){
									$wanted_zones[] = $direction;
								}									
							}
						}
					}
					$wanted_zones[] = ((in_array(array(1,0), $wanted_zones)) and (in_array(array(0,1), $wanted_zones)))?array(1,1):"";
					$wanted_zones[] = ((in_array(array(-1,0), $wanted_zones)) and (in_array(array(0,1), $wanted_zones)))?array(-1,1):"";
					$wanted_zones[] = ((in_array(array(-1,0), $wanted_zones)) and (in_array(array(0,-1), $wanted_zones)))?array(-1,-1):"";
					$wanted_zones[] = ((in_array(array(1,0), $wanted_zones)) and (in_array(array(0,-1), $wanted_zones)))?array(1,-1):"";
					$wanted_zones = array_filter($wanted_zones,function($el){ return !empty($el);});
				}
				
				$moves = $this->my_array_match($moves, $wanted_zones);
				$move = $moves[array_rand($moves)];
			
				$this->field[$obj->xy[1]][$obj->xy[0]] = ".";
				$obj->xy[0]+=$move[0];
				$obj->xy[1]+=$move[1];
				$xxx = $obj->xy[0];
				$yyy = $obj->xy[1];
				$this->field[$obj->xy[1]][$obj->xy[0]] = "C";
				
				$sleep = FALSE;
				$unset_counter = 0;
				
				foreach($this->animals as $obj2){
					if(get_class($obj2) == "mouse"){
						if($obj2->xy==array($xxx, $yyy)){
							unset($this->animals[$unset_counter]);
							sort($this->animals);
							$this->field[$obj2->xy[1]][$obj2->xy[0]] = "@";
							$obj->sleep = TRUE;
						}
					}
					$unset_counter++;
				}
			}
		}
		$this->record[] = $this->field;
		}
	}


	function possible_moves($obj, $animal){
		switch($animal){
			case "mouse":
				$possible_moves = array(array(1,0), array(0,1), array(-1,0), array(0,-1));
				$moves = array();
				foreach($possible_moves as $arr){
					if(isset($this->field[$obj->xy[1]+$arr[1]][$obj->xy[0]+$arr[0]]) and $this->field[$obj->xy[1]+$arr[1]][$obj->xy[0]+$arr[0]] == "."){
						$moves[] = $arr;
					}
				}
				break;
			case "cat":
				$possible_moves = array(array(1,0), array(0,1), array(-1,0), array(0,-1), array(1,1), array(1,-1), array(-1,1), array(-1,-1));
				$moves = array();
				foreach($possible_moves as $arr){
					if(isset($this->field[$obj->xy[1]+$arr[1]][$obj->xy[0]+$arr[0]]) and ($this->field[$obj->xy[1]+$arr[1]][$obj->xy[0]+$arr[0]] == "." or $this->field[$obj->xy[1]+$arr[1]][$obj->xy[0]+$arr[0]] == "M")){
						$moves[] = $arr;
					}
				}
				break;
		}
		return $moves;
	}
	
	function my_array_diff($moves, $danger_zones){
		for($x=0;$x<=count($moves);++$x){
			foreach($danger_zones as $arr){
				if($moves[$x] == $arr){
					unset($moves[$x]);
				}
			}
		}
		return $moves;
	}
	
	function my_array_match($moves, $wanted_zones){
		$moves_temp = array();
		for($x=0;$x<=count($moves);++$x){
			foreach($wanted_zones as $arr){
				if($moves[$x] == $arr){
					$moves_temp[] = $moves[$x];
				}
			}
		}
		return $moves_temp;
	}
	
	function show(){
		echo "\r\n";
		foreach($this->record as $arr=>$arr_2){
			foreach($arr_2 as $var=>$var_3){
				echo "|";
				foreach($var_3 as $var_4){
					echo "$var_4|";
				}
				echo "\r\n";
			}
			echo "\r\n\r\n";
		}
	}
}
	
class cat extends field{
	public $power = 8;
	public $sleep = 2;
}
class mouse extends field{}

$f = new field;
$f->create_field();
$f->add_animals();
$f->move(23);
$f->show();
?>