function application(S)
% EVADER_APPLICATION  Evader-centric tracking 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;
R=4;
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('parent', -inf, 'hops', 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.hops<R & (memory.val< data.data.val | (memory.val == data.data.val & memory.hops > data.data.hops +1))
        if (memory.parent>0 & memory.parent~=ID)
           DrawLine('Delete', ID,memory.parent)
        end
        memory.parent=data.data.ID;
        memory.hops=data.data.hops+1;
        memory.val=data.data.val;
        Send_Packet(radiostream(struct('val', memory.val, 'ID', ID, 'hops', memory.hops), 1));
        PrintMessage([num2str(memory.val) '/' num2str(memory.hops)]) 
        DrawLine('Arrow', ID,memory.parent, 'color', [0 0 0])
        %if memory.hops<3
        %    LED('red on')
        %elseif memory.hops<6
        %    LED('green on')
        %else
        %    LED('yellow on')
        %end            
     elseif memory.val < data.data.val &  data.data.hops>=R %time to prune this node off the tree
        memory.parent=-inf;
        memory.hops=-inf;
    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.hops=0;
        memory.val=memory.val+1;
	if (memory.parent>0 & memory.parent~=ID)
           DrawLine('Delete', ID,memory.parent)
           memory.parent=ID;
        end
	PrintMessage([num2str(memory.val) '/' num2str(memory.hops)]) 
        Send_Packet(radiostream(struct('val', memory.val, 'ID', ID, 'hops', 0), 1));

        %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');
     elseif(memory.parent>0)
        Move_Pursuer(PURSUER_WAIT, memory.parent);
        LED('red on');
     end
    %end


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 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
