function application(S)
% PURSUER_APPLICATION  
% Murat Demirbas, 3/17/04


% DO NOT edit simulator code (lines that begin with S;)


S; %%%%%%%%%%%%%%%%%%%   housekeeping  %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
S;      persistent app_data 
S;      global ID t
S;      [t, event, ID, data]=get_event(S);
S;      [topology, mote_IDs]=prowler('GetTopologyInfo');
S;      ix=find(mote_IDs==ID);
S;      if ~strcmp(event, 'Init_Application') 
S;         try memory=app_data{ix}; catch memory=[]; end, 
S;      end
S; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%


%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%//%%%%%%%%%%%%%%%%                                          %%%%%%%%%%%%%%
%//%%%%%%%%%%%%%%%%         APPLICATION STARTS               %%%%%%%%%%%%%%
%//%%%%%%%%%%%%%%%%               HERE                       %%%%%%%%%%%%%%
%//%%%%%%%%%%%%%%%%                                          %%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%vvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvvv%

global TTL; %Time To Live for evader, evader gets old at every step
global EVADER_ID;
 
global PURSUER_ID;
global CATCHED; 
Nx=10; Ny=10;
EVADER_WAIT =80000;
PURSUER_WAIT=40000;
switch event
case 'Init_Application'
    signal_strength=1;
    TTL=0;
    EVADER_ID=45;
    PURSUER_ID=1;
    CATCHED=0;
        
    %%%%%%%%%%%%%%   Memory should be initialized here  %%%%%%%%%%%%%%%%%
    memory=struct('next', -inf, 'val', 0);
    %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
    
    if ID==EVADER_ID % first node starts flood
        Move_Evader(1000,ID);
    end
    if ID==PURSUER_ID % first node starts flood
        Move_Pursuer(20000,ID);
    end

    PrintMessage('') 
case 'Packet_Sent'

case 'Packet_Received'
    if data.data.ID==-1
       if memory.val> data.data.val
         Send_Packet(radiostream(struct('val', memory.val, 'ID', ID), 1));
       end
    elseif data.data.val > memory.val
          memory.val=data.data.val;
          memory.next=data.data.ID;
    end



case 'Collided_Packet_Received'
    % this is for debug purposes only
    
case 'Evader_Detected'
    if CATCHED==0
        EVADER_ID=ID;
        TTL=TTL+1; % evader has lived 1 more round
        if mod(TTL,2)==0
           fprintf('\n TTL == %d',TTL);
        end
	
	%action
        memory.val=TTL;
        PrintMessage([num2str(memory.val)]) 
        %move evader
        nxtx=floor((ID-1)/Ny);nxty=mod(ID-1, Ny); %Mv evader to random nbr
        r=rand;
        if r <= 0.2 & nxtx+2<Nx
           nxtx=nxtx+2;
        elseif r <= 0.4 & nxty+2<Ny
           nxty=nxty+2;
        elseif r <= 0.6 & nxtx-2>=0
            nxtx=nxtx-2;
        elseif r <= 0.8 & nxty-2>=0
            nxty=nxty-2;                        
        %else skip a move
        end
 
	Move_Evader(EVADER_WAIT,nxtx*Ny+ nxty +1);%Schedule an evader move
    end

case 'Pursuer_Detected'
     PURSUER_ID=ID
     if PURSUER_ID==EVADER_ID
        CATCHED=1
        LED('red on');
        LED('green on');
        LED('yellow on');
     else
        Send_Packet(radiostream(struct('val', memory.val, 'ID', -1), 1));
        LED('red on');
        Set_Clock(t+5000);
     end     

case 'Clock_Tick'
      if(memory.next<1)
        %random move
        nxtx=floor((ID-1)/Ny);nxty=mod(ID-1, Ny); %Mv evader to random nbr
        r=rand;
        if r <= 0.25 & nxtx+2<Nx
           nxtx=nxtx+2;
        elseif r <= 0.5 & nxty+2<Ny
           nxty=nxty+2;
        elseif r <= 0.75 & nxtx-2>=0
            nxtx=nxtx-2;
        elseif r <= 1 & nxty-2>=0
            nxty=nxty-2;                        
        end
 
	memory.next=nxtx*Ny+ nxty +1;
      end
      Move_Pursuer(PURSUER_WAIT,memory.next);
      memory.val=0;
      memory.next=-inf;



case 'GuiInfoRequest'
    if ~isempty(memory)
        disp(sprintf('Memory Dump of mote ID# %d:\n',ID)); disp(memory)
    else
        disp(sprintf('No memory dump available for node %d.\n',ID)); 
    end
    
otherwise
    error(['Bad event name for application: ' event])
end

%^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^^%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
 
S; %%%%%%%%%%%%%%%%%%%%%% housekeeping %%%%%%%%%%%%%%%%%%%%%%%%%%%
S;        app_data{ix}=memory;
S; %%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%                           %%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%        COMMANDS           %%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%                           %%%%%%%%%%%%%%%%%%%
%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%%

function b=Send_Packet(data);
global ID t
radio=prowler('GetRadioName');
b=feval(radio, 'Send_Packet', ID, data, t);

function b=Move_Evader(EVADER_WAIT,dest_ID);
global t 
prowler('InsertEvents2Q', make_event(t+EVADER_WAIT,'Evader_Detected', dest_ID));


function b=Move_Pursuer(PURSUER_WAIT,dest_ID);
global t 
prowler('InsertEvents2Q', make_event(t+PURSUER_WAIT,'Pursuer_Detected', dest_ID));

function b=Set_Clock(alarm_time);
global ID
prowler('InsertEvents2Q', make_event(alarm_time, 'Clock_Tick', ID));

function PrintMessage(msg)
global ID
prowler('TextMessage', ID, msg)

function LED(msg)
global ID
prowler('LED', ID, msg)

function DrawLine(command, varargin)
switch lower(command)
case 'line'
    prowler('DrawLine', varargin{:})
case 'arrow'
    prowler('DrawArrow', varargin{:})
case 'delete'
    prowler('DrawDelete', varargin{:})
otherwise
    error('Bad command for DrawLine.')
end
