% 
%   Random Walk mit Entscheidung, 
%     ob der neue Weg genommen werden soll: 
%     
%
%   >> [X,Y] = meshgrid( [0:1:99] );  % Definition des Geländes Z
%   >> Z = - (X-40).*(X-30) - (Y-30).*(Y-40) + 2000;
%   >> obj = RandomWalkEval( Z );
% 
%   bzw. Gelände-Werte mit setRandomWalk<n> belegt: 
%   >> obj = RandomWalkEval( setRandomWalk() );
%   >> obj.walk( 1 );
%   >> obj.walk( 1 );
%   >> ... 
%   oder: 
%   >> obj.walk( 10 );
% 
classdef RandomWalkEval < handle
  
  properties
    Z = [];      % Höhe des Gebirges
    nZ = 0;      % Zahl der Zeilen 
    nS = 0;      % Zahl der Spalten
    mult = 20;
    start = [0,0];  % Startpunkt
  end
  
  methods
    % Konstruktor mit Übergabe des Geländes Z, siehe oben   
    function obj = RandomWalkEval( Z )
      obj.Z = Z;
      sz = size( Z );
      obj.nZ = sz(1);  
      obj.nS = sz(2);
      obj.start = [obj.nS/2,obj.nZ/2];
      % Gelände Zeichnen 
      figure;
      contour3( obj.Z );
      view( 0,90 )
    end
    
    % steps Schritte laufen
    function walk( obj, steps )
      
      % Bewertung: 
      y = int32(obj.start(1));
      x = int32(obj.start(2));
      val0 = obj.Z(x,y);   % Höhe des Geländes am Startpunkt
      
      hold on
      
      akt = obj.start;  % nächster Punkt
      pre = obj.start;  % Startpunkt
      last = akt;
      for( n = 1:steps )  % steps Schritte laufen 
        d = rand( 1, 2 ) - 0.5;   % 2-dim. Zufalls-Richtung
        akt = pre + obj.mult*d;   % nächster Punkt
        plot( [pre(1),akt(1)], [pre(2),akt(2)], 'b-+' ); 
        last = pre;
        pre = akt;
      end
      
      % Check außerhalb des Bereichs      
      if( akt(1) < 1 || akt(1) > obj.nS  || ... 
          akt(2) < 1 || akt(2) > obj.nZ     )
        fprintf( 'außerhalb, zurück auf letzte Position \n' );
        return;
      end
      
      % neue Bewertung
      y1 = int32(akt(1));
      x1 = int32(akt(2));
      val1 = obj.Z(x1,y1); % Höhe des Geländes am vorläufigen Endpunkt 
      % neue Höhe liegt tiefer als Starthöhe 
      if( val1 < val0 )        
        fprintf( 'zurück auf letzte Position \n' );
        return;
      end
      
      % neue Position wird übernommen, da sie höher liegt
      obj.start = akt;  % Endpunkt
      plot( [last(1),pre(1)], [last(2),pre(2)], 'm-+' );
      hold off
      
    end
    
    % Weg wieder auf Anfang setzen  
    function init( obj )
      obj.start = [obj.nS/2,obj.nZ/2];
      clf;
      contour3( obj.Z );
      view( 0,90 )     
    end
    
  end
  
end
