Page 1 of 2 12 LastLast
Results 1 to 25 of 26

Thread: Colorizing library

  1. #1
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default Colorizing library

    Hi folks,

    I wrote this code for my fighter update so we would stop having so many problems with color updates.

    It's a bunch of functions to grab colors from the screen, keep track of them, and determine which ones successfully lead to our desired goal.

    I thought I would publish them for peer review / comments / improvement.

    The test script finds an attackable NPC by motion. Each time you run the test script it finds 5 new colors which are likely to lead to the NPC.

    Best,
    Bonsai

    Alpha testing of the new fighter that uses a version of this (use hd):



    Functions:

    Simba Code:
    procedure Tcolorizer.init(nm: string; ut: string; utt: integer; t: integer;
       d: integer; minp: integer; maxp: integer);

    function Tcolorizer.load(): boolean;
    procedure Tcolorizer.save();
    procedure Tcolorizer.setName(nm: string);
    procedure Tcolorizer.delete(col: integer);
    procedure Tcolorizer.cleanupColors();

    procedure Tcolorizer.updateCount(col: integer; cnt: integer);
    procedure Tcolorizer.updateTrials(col: integer; success: boolean);
    procedure Tcolorizer.updatePointCount(col: integer; points: integer;
       objs: integer; msec: integer);

    function Tcolorizer.gather(var atpa: T2DPointArray; c: integer): boolean;
    function Tcolorizer.testCol(c: integer; trials: integer = 1): boolean;
    procedure Tcolorizer.sample(n: integer = 3);
    procedure Tcolorizer.deepSample(x: integer; y: integer; n: integer = 3);

    function Tcolorizer.untriedColors() : TIntegerArray;
    function Tcolorizer.activeColors() : TIntegerArray;
    function Tcolorizer.successfulColors() : TIntegerArray;


    function Tcolorizer.colorize(maxTime: integer = 120000; enough: integer = 5): boolean;

    function Tcolorizer.detectObj(var x: integer; var y: integer; var menuText: string;
       b: TBox; mouseButton: integer = MOUSE_MOVE): boolean;

    function Tcolorizer.examineGrid(grid: TBoxArray): string;

    function Tcolorizer.motionDetect(): string;

    Script (log in first, be somewhere with things moving around):

    Simba Code:
    program new;
    {$DEFINE SMART}
    {$DEFINE DEBUG_ON}
    {$DEFINE SMART}
    {$i srl-6/srl.simba}

    // -----------------------------------------------------------------------------
    // --    libcolorizer.simba
    // --    Written by: bonsai
    // -----------------------------------------------------------------------------

    {$f-}

    const  
       BLACKLIST_THRESHOLD = 400;    // msec.  if a findcolor takes longer than this we dont want it
       PIXELSHIFT_WAIT     = 350;    // msec
       SUCCESS_THRESHOLD   = 0.75;   // what is good enough (percent) to call a color successful
       FAILURE_THRESHOLD   = 0.30;   // what is bad enough (percent) to call a failure
       ATTEMPT_THRESHOLD   = 25;     // by this many attempts, demand success or blacklist
       GRIDSIZE            = 50;     // box size to break up the screen for motion detection
       CLEANUP_LOW_WATER   = 40;     // how many colors to keep if we are cleaning up

    type  
       TcolRec = record
          color      : integer;
          count      : integer;      // how many times have we seen this color
          attempts   : integer;      // how many times have we tried this color
          matches    : integer;      // how many attempts made a match
          maxPoints  : integer;      // max points returned when finding this color
          maxObj     : integer;      // max objects found when finding this color
          queryTime  : integer;      // how long did it take to find this color
       end;
       
       TcolSet = array of TcolRec;
         
       Tcolorizer = record
          name          : string;    // a name for this object, used as file name in load/save
          discovered    : TcolSet;   // colors we have discovered that may be relevant
          active        : TcolSet;   // colors we are testing to see if they are worthy
          successful    : TcolSet;   // colors that worked
          blacklist     : TcolSet;   // colors that suck for one reason or another
          runty         : TcolSet;   // colors that return too few points, maybe good matches?
          uptext        : string;    // uptext of the object we are colorizing
          uptextTimeout : integer;   // how long to wait for an uptext to display before moving on
          tol           : integer;   // tolerance on color search (cts 0)
          dist          : integer;   // distance for object making (tpa split)
          minPixels     : integer;   // min pixels to keep an object
          maxPixels     : integer;   // objects bigger than this get tossed
       end;

    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // Some functions that had issues or were missing from SRL
    // -----------------------------------------------------------------------------      
    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    function getPixelShiftAverage(b: TBoxArray; waitPerLoop, maxTime: integer): TIntegerArray; override;

    var
      len, i, j: integer;
      samples: array of TIntegerArray;
      tmp: TIntegerArray;
      timer: TTimeMarker;
     
    begin
       i := 0;
       timer.start();
       while (timer.getTime() < maxTime) do
       begin  
          setLength(samples, i + 1);
          samples[i] := getPixelShift(b, waitPerLoop);
          inc(i);
       end;
       
       setLength(tmp, i); // i got incremented one extra time so is good for length
       len := length(b);
       setLength(result, len);  

       for i := 0 to (len - 1) do
       begin
          for j := 0 to high(samples) do
             tmp[j] := samples[j][i];

          result[i] := tmp.average();
       end;
    end;

    function getPixelShift(b: TBoxArray; time: integer): TIntegerArray; override;

    var
      hi, i: integer;
      before, after: integer;
     
    begin
       hi := high(b);
       setLength(result, hi+1);

       before := bitmapFromClient(mainscreen.getBounds());
       sleep(time);
       after  := bitmapFromClient(mainscreen.getBounds());

       for i := 0 to hi do
          result[i] := calculatePixelShift(before, after, b[i]);

       freeBitmap(before);
       freeBitmap(after);
    end;

    function TIntegerArray.max(): integer;
    var
       i, tmpmax: integer;
    begin
       tmpmax := -(MAXINT);
       for i := 0 to length(self) do
          if self[i] > tmpmax then tmpmax := self[i];
       exit(tmpmax);
    end;
     
    function TBoxArray.pixelShift(time: integer = 200): TIntegerArray;
    begin
       result := getPixelShift(self, time);
    end;
     
    function TBoxArray.returnInArray(const b : TBox) : integer;
    var
      i: integer;
    begin
      for i := 0 to high(self) do
        if (self[i].equals(b)) then exit(i);
      exit(-1);
    end;

    function TBoxArray.isInArray(const b : TBox) : Boolean;
    begin
      if (self.returnInArray(b) <> -1) then
        result := true
      else
        result := false;
    end;

    procedure TBoxArray.addIndex(const b : TBox; const index : Integer);
    var
      I : Integer;
    begin
      if not inRange(index, low(self), length(self)) then
      begin
        WriteLn('ERROR: addIndex: index larger than array length.');
        Exit;
      end;

      setLength(self, length(self)+1);
      for I := high(self)-1 downto index do
        self[I+1] := self[I];
      self[index] := b;
    end;

    procedure TBoxArray.append(const b : TBox);
    begin
      self.addIndex(b, length(self));
    end;

    procedure TBoxArray.combine(const arr : TBoxArray);
    var
      i : integer;
    begin
      for i := 0 to high(arr) do
        self.append(arr[i]);
    end;

    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------
    // -----------------------------------------------------------------------------

    // -----------------------------------------------------------------------------
    // sortByCount()
    //
    // sorts the array by count desc
    // -----------------------------------------------------------------------------
    procedure TcolSet.sortByCount();

    var
       i, j, m: integer;
       tmp: TcolSet;
       
    begin
       setLength(tmp, 1);
       for i := 0 to high(self) - 1 do
       begin    
          m := i;    
          for j := i + 1 to high(self) do
          begin
             if self[j].count > self[m].count then
                m := j;  
          end;
          tmp[0]  := self[m];    
          self[m] := self[i];    
          self[i] := tmp[0];
       end;
    end;

    // -----------------------------------------------------------------------------
    // sortBySuccess()
    //
    // sorts the array by success rate desc
    // -----------------------------------------------------------------------------
    procedure TcolSet.sortBySuccess();

    var
       i, j, m: integer;
       tmp: TcolSet;
       
    begin
       setLength(tmp, 1);
       for i := 0 to high(self) - 1 do
       begin    
          m := i;    
          for j := i + 1 to high(self) do
          begin
             if (self[j].matches / self[j].attempts) > (self[m].matches / self[m].attempts) then
                m := j;  
          end;
          tmp[0]  := self[m];    
          self[m] := self[i];    
          self[i] := tmp[0];
       end;
    end;

    // -----------------------------------------------------------------------------
    // returnInArray()
    //
    // Returns the index of color c in the array (-1 if not found)
    // -----------------------------------------------------------------------------
    function TcolSet.returnInArray(const c: integer): integer;

    var
       i: integer;  

    begin
       for i := 0 to high(self) do
          if (self[i].color = c) then exit(i);
       exit(-1);
    end;

    // -----------------------------------------------------------------------------
    // isInArray()
    //
    // Returns true if color c in the array
    // -----------------------------------------------------------------------------
    function TcolSet.isInArray(const c: integer): boolean;

    var
       i: integer;  

    begin
       i := self.returnInArray(c);
       if (i = -1) then
          result := false
       else
          result := true;
    end;

    // -----------------------------------------------------------------------------
    // append()
    //
    // Adds a color to the array
    // -----------------------------------------------------------------------------
    procedure TcolSet.append(const t: TcolRec);

    var
       i: integer;
       
    begin
       setLength(self, (length(self) + 1));
       self[high(self)] := t;
    end;

    // -----------------------------------------------------------------------------
    // deleteIndex()
    //
    // Deletes the color at the given index
    // -----------------------------------------------------------------------------
    procedure TcolSet.deleteIndex(const index: integer);

    var
       i : integer;

    begin
       if not inRange(index, low(self), high(self)) then
       begin
          writeln('TcolSet.deleteIndex: ERROR - index (', index, ' is out of range');
          exit;
       end;

       for i := index to (high(self) - 1) do
          self[i] := self[i + 1];
       setLength(self, (length(self) - 1));
    end;

    // -----------------------------------------------------------------------------
    // delete()
    //
    // Deletes the color
    // -----------------------------------------------------------------------------
    procedure TcolSet.delete(const c: integer);

    var
       i : integer;
       
    begin
       i := self.returnInArray(c);
       if (i >= 0) then
          self.deleteIndex(i);
    end;

    // -----------------------------------------------------------------------------
    // cleanupColors()
    //
    // Weeds down the color list
    // -----------------------------------------------------------------------------
    procedure TcolSet.cleanupColors();

    var
       i, t, cnt: integer;
       tmp: TcolSet;
       
    begin
       cnt := 1;
       while (cnt < 15) do
       begin
          if (length(self) < CLEANUP_LOW_WATER) then exit;
         
          t := 0;
          setLength(tmp, length(self));
         
          for i := 0 to high(self) do
          begin
             if ((self[i].matches > 0) or (self[i].count > cnt)) then
             begin
                tmp[t] := self[i];
                inc(t);
             end;
          end;
         
          setLength(tmp, t);
          self := tmp;
          inc(cnt);
       end;
    end;

    // -----------------------------------------------------------------------------
    // _fpath()
    //
    // Loads previous work from a file
    // -----------------------------------------------------------------------------
    function Tcolorizer._fpath(): string;

    var
       s: string;
       
    begin
       if (self.name = '') then
       begin
          result := '';
          exit;
       end;
       s := lowercase(self.name);
       s := replace(s, ' ', '-', [rfReplaceAll]);
       s := replace(s, '/', '-', [rfReplaceAll]);
       s := replace(s, ':', '-', [rfReplaceAll]);
       
       result := includePath + 'bonsai\colors\';  
       if (not DirectoryExists(result)) then
       begin
          if (CreateDirectory(result)) then
             writeln('***** Tcolorizer._fpath: created include folder ' + result)
          else
             writeln('***** Tcolorizer._fpath: ERROR - Could not create directory ' + result);
       end;

       result := result + s + '.xml';
    end;

    // -----------------------------------------------------------------------------
    // load()
    //
    // Loads previous work from a file
    // -----------------------------------------------------------------------------
    function Tcolorizer.load(): boolean;

    var
      fileId, i, j, k: integer;
      filePath, fileData: string;
      allData, colArr, colorSets, cRec: TStringArray;
      tmp: TcolRec;
     
    begin
       result := false;
       filePath := self._fpath();
        if (not FileExists(filePath)) then
        begin
        {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.load: Requested file does not exist [', filePath, ']'); {$ENDIF}
            exit;
        end;

        fileId := OpenFile(filePath, false);
        if (fileId = -1) then
       begin
        {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.load: OpenFile failed [', filePath, ']'); {$ENDIF}
          exit;
       end;
       
        if (not ReadFileString(fileId, fileData, FileSize(fileId))) then   
       begin
        {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.load: ReadFileString failed [', filePath, ']'); {$ENDIF}
            exit;
        end;  
        CloseFile(fileId);

        // now we have the contents in fileData, parse it
        allData := MultiBetween(fileData, '<colorizer>', '</colorizer>');
        if (length(allData) <> 1) then
        begin
           writeln('***** Tcolorizer.load: Corrupt file [', filePath,
            '], does not have proper <colorizer></colorizer> tags');
            exit;
        end;
       
       self.name     :=             between('<name>',          '</name>',          allData[0]);
       self.uptext   :=             between('<uptext>',        '</uptext>',        allData[0]);
       uptextTimeout := StrToIntDef(between('<uptextTimeout>', '</uptextTimeout>', allData[0]), 0);
       tol           := StrToIntDef(between('<tol>',           '</tol>',           allData[0]), 0);
       dist          := StrToIntDef(between('<dist>',          '</dist>',          allData[0]), 0);
       minPixels     := StrToIntDef(between('<minPixels>',     '</minPixels>',     allData[0]), 0);
       maxPixels     := StrToIntDef(between('<maxPixels>',     '</maxPixels>',     allData[0]), 0);

       colorSets := ['discovered', 'active', 'successful', 'blacklist', 'runty'];
       for i := 0 to high(colorSets) do
       begin
          colArr := multiBetween(allData[0], '<' + colorSets[i] + '>', '</' + colorSets[i] + '>');
          for j := 0 to high(colArr) do
          begin
             cRec := multiBetween(colArr[j], '<colorRecord>', '</colorRecord>');
             for k := 0 to high(cRec) do
             begin
                tmp.color     := StrToIntDef(between('<color>',     '</color>',     cRec[k]), 0);
                tmp.count     := StrToIntDef(between('<count>',     '</count>',     cRec[k]), 0);
                tmp.attempts  := StrToIntDef(between('<attempts>',  '</attempts>',  cRec[k]), 0);
                tmp.matches   := StrToIntDef(between('<matches>',   '</matches>',   cRec[k]), 0);
                tmp.maxPoints := StrToIntDef(between('<maxPoints>', '</maxPoints>', cRec[k]), 0);
                tmp.maxObj    := StrToIntDef(between('<maxObj>',    '</maxObj>',    cRec[k]), 0);
                tmp.queryTime := StrToIntDef(between('<queryTime>', '</queryTime>', cRec[k]), 0);
               
                case colorSets[i] of
                   'discovered' : begin; self.discovered.append(tmp); end;
                   'active'     : begin; self.active.append(tmp);     end;
                   'successful' : begin; self.successful.append(tmp); end;
                   'blacklist'  : begin; self.blacklist.append(tmp);  end;
                   'runty'      : begin; self.runty.append(tmp);      end;
                end;
             end;
          end;
       end;
    end;

    // -----------------------------------------------------------------------------
    // save()
    //
    // Saves the accumulated data
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.save();

    var
       s, filePath: string;
       i, j, fileId: integer;
       colorSets: TstringArray;

       function colRec(r: TcolRec): string;
       begin
          result := result + '    <colorRecord>';
          result := result + '<color>'     + intToStr(r.color)     + '</color>';
          result := result + '<count>'     + intToStr(r.count)     + '</count>';
          result := result + '<attempts>'  + intToStr(r.attempts)  + '</attempts>';
          result := result + '<matches>'   + intToStr(r.matches)   + '</matches>';
          result := result + '<maxPoints>' + intToStr(r.maxPoints) + '</maxPoints>';
          result := result + '<maxObj>'    + intToStr(r.maxObj)    + '</maxObj>';
          result := result + '<queryTime>' + intToStr(r.queryTime) + '</queryTime>';
          result := result + '</colorRecord>' + #13#10;
       end;
       
    begin
       s := s + '<colorizer>' + #13#10;
       s := s + '  <name>'          + self.name                    + '</name>' + #13#10;
       s := s + '  <uptext>'        + self.uptext                  + '</uptext>' + #13#10;
       s := s + '  <uptextTimeout>' + intToStr(self.uptextTimeout) + '</uptextTimeout>' + #13#10;
       s := s + '  <tol>'           + intToStr(self.tol)           + '</tol>' + #13#10;
       s := s + '  <dist>'          + intToStr(self.dist)          + '</dist>' + #13#10;
       s := s + '  <minPixels>'     + intToStr(self.minPixels)     + '</minPixels>' + #13#10;
       s := s + '  <maxPixels>'     + intToStr(self.maxPixels)     + '</maxPixels>' + #13#10;

       colorSets := ['discovered', 'active', 'successful', 'blacklist', 'runty'];
       for i := 0 to high(colorSets) do
          case colorSets[i] of
             'discovered':
                begin
                   s := s + '  <discovered>' + #13#10;
                   for j := 0 to high(self.discovered) do
                      s := s + colRec(self.discovered[j]);
                   s := s + '  </discovered>' + #13#10;
                end;
             'active':
                begin
                   s := s + '  <active>' + #13#10;
                   for j := 0 to high(self.active) do
                      s := s + colRec(self.active[j]);              
                   s := s + '  </active>' + #13#10;
                end;
             'successful':
                begin
                   s := s + '  <successful>' + #13#10;
                   for j := 0 to high(self.successful) do
                      s := s + colRec(self.successful[j]);              
                   s := s + '  </successful>' + #13#10;
                end;
             'blacklist':
                begin
                   s := s + '  <blacklist>' + #13#10;
                   for j := 0 to high(self.blacklist) do
                      s := s + colRec(self.blacklist[j]);              
                   s := s + '  </blacklist>' + #13#10;
                end;
             'runty':
                begin
                   s := s + '  <runty>' + #13#10;
                   for j := 0 to high(self.runty) do
                      s := s + colRec(self.runty[j]);
                   s := s + '  </runty>' + #13#10;
                end;
          end;
         
       s := s + '</colorizer>' + #13#10;
         
       filePath := self._fpath();

        fileId := RewriteFile(filePath, false);
        if (fileId = -1) then
       begin
        {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.save: RewriteFile failed [', filePath, ']'); {$ENDIF}
          exit;
       end;
       
        if (not WriteFileString(fileId, s)) then   
       begin
        {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.save: WriteFileString failed [', filePath, ']'); {$ENDIF}
            exit;
        end;  
        CloseFile(fileId);
    end;

    // -----------------------------------------------------------------------------
    // init()
    //
    // Initialize the object
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.init(nm: string; ut: string; utt: integer; t: integer;
       d: integer; minp: integer; maxp: integer);

    begin
       self.name          := nm;
       self.uptext        := ut;
       self.uptextTimeout := utt;
       self.tol           := t;
       self.dist          := d;
       self.minPixels     := minp;
       self.maxPixels     := maxp;
       setLength(self.discovered, 0);
       setLength(self.active,     0);
       setLength(self.successful, 0);
       setLength(self.blacklist,  0);
       setLength(self.runty,      0);
    end;

    // -----------------------------------------------------------------------------
    // setName()
    //
    // Initialize the object
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.setName(nm: string);
    begin
       self.name := nm;
    end;

    // -----------------------------------------------------------------------------
    // updateCount()
    //
    // Updates count info for a color.  Adds it if new.
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.updateCount(col: integer; cnt: integer);

    var
       d, a, s, b, r: integer;
       
    begin  
       d := self.discovered.returnInArray(col);
       a := self.active.returnInArray(col);
       s := self.successful.returnInArray(col);
       b := self.blacklist.returnInArray(col);
       r := self.runty.returnInArray(col);
       
       if (d+a+s+b+r = -5) then  // this is a new color
       begin
          setLength(self.discovered, length(self.discovered) + 1);
          with self.discovered[high(self.discovered)] do
          begin
             color     := col;
             count     := cnt;
             attempts  := 0;
             matches   := 0;
             maxPoints := 0;
             maxObj    := 0;
             queryTime := 0;
          end;
       end
       else
       begin
          if (d >= 0) then
             self.discovered[d].count := self.discovered[d].count + cnt;
          if (a >= 0) then
             self.active[a].count := self.active[a].count + cnt;
          if (s >= 0) then
             self.successful[s].count := self.successful[s].count + cnt;
          if (b >= 0) then
             self.blacklist[b].count := self.blacklist[b].count + cnt;
          if (r >= 0) then
             self.runty[r].count := self.runty[r].count + cnt;
       end;  
    end;


    // -----------------------------------------------------------------------------
    // updateTrials()
    //
    // Records success/failure of an attempt to use a color.  Will move the
    // color from place to place depending on the situation.
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.updateTrials(col: integer; success: boolean);

    var
       d, a, s, b, r: integer;
       pct: extended;
       
    begin  
       d := self.discovered.returnInArray(col);
       a := self.active.returnInArray(col);
       s := self.successful.returnInArray(col);
       b := self.blacklist.returnInArray(col);
       r := self.runty.returnInArray(col);
       
       if (d+a+s+b+r = -5) then
       begin
          writeln('Tcolorizer.updateTrials: ERROR - Asked to update color, ', col, ' - does not exist');
          exit;
       end

       if (d >= 0) then
          with self.discovered[d] do
          begin
             inc(attempts);
             if (success) then inc(matches);
             // move it to active since it is being used.
             {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.updateTrials: moving (', self.discovered[d].color, ') discovered -> active'); {$ENDIF}
             self.active.append(self.discovered[d]);
             self.discovered.deleteIndex(d);
          end;
         
       if (a >= 0) then
          with self.active[a] do
          begin
             inc(attempts);
             if (success) then inc(matches);
             pct := matches / attempts;
           
             // see if this active color has met criteria for blacklist or success
             
             if ((attempts >= ATTEMPT_THRESHOLD) and (pct < SUCCESS_THRESHOLD)) or
                ((attempts >= 5) and (pct < FAILURE_THRESHOLD)) then
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updateTrials: moving (', self.active[a].color,
                      ') active -> blacklist');
                {$ENDIF}
                self.blacklist.append(self.active[a]);   // time to give up on this one
                self.active.deleteIndex(a);
             end
             else if ((matches >= 5) and (pct >= SUCCESS_THRESHOLD)) then
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updateTrials: moving (', self.active[a].color,
                      ') active -> successful');
                {$ENDIF}
                self.successful.append(self.active[a]);
                self.active.deleteIndex(a);
             end;
          end;
         
       if (s >= 0) then
          with self.successful[s] do
          begin
             inc(attempts);
             if (success) then inc(matches);

             if ((matches / attempts) < (SUCCESS_THRESHOLD - 0.1)) then
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updateTrials: moving (', self.successful[s].color,
                      ') successful -> active');
                {$ENDIF}
                self.active.append(self.successful[s]);
                self.successful.deleteIndex(s);
             end;
          end;
         
       if (b >= 0) then
          with self.blacklist[b] do
          begin
             inc(attempts);
             if (success) then inc(matches);
          end;
         
       if (r >= 0) then
          with self.runty[r] do
          begin
             inc(attempts);
             if (success) then inc(matches);
          end;
    end;

    // -----------------------------------------------------------------------------
    // updatePointCount()
    //
    // Updates stats on a color
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.updatePointCount(col: integer; points: integer;
       objs: integer; msec: integer);

    var
       d, a, s, b, r: integer;
       
    begin  
       d := self.discovered.returnInArray(col);
       a := self.active.returnInArray(col);
       s := self.successful.returnInArray(col);
       b := self.blacklist.returnInArray(col);
       r := self.runty.returnInArray(col);
       
       if (d+a+s+b+r = -5) then
       begin
          writeln('Tcolorizer.updatePointCount: ERROR - Asked to update color, ',
             col, ' - does not exist');
          exit;
       end

       if (d >= 0) then
          with self.discovered[d] do
          begin
             if (points > maxPoints) then maxPoints := points;
             if (objs > maxObj)      then maxObj    := objs;
             if (msec > queryTime)   then queryTime := msec;
             if (msec > BLACKLIST_THRESHOLD) then // move it to the blacklist
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.discovered[d].color,
                      ') discovered -> blacklist');
                {$ENDIF}
                self.blacklist.append(self.discovered[d]);
                self.discovered.deleteIndex(d);
             end
             else if (objs < 1) then // move it to the runty list
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.discovered[d].color,
                      ') discovered -> runty');
                {$ENDIF}
                self.runty.append(self.discovered[d]);
                self.discovered.deleteIndex(d);            
             end
             else // since it is being used, move it to active
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.discovered[d].color,
                      ') discovered -> active');
                {$ENDIF}
                self.active.append(self.discovered[d]);
                self.discovered.deleteIndex(d);
             end;
          end;

       if (a >= 0) then
          with self.active[a] do
          begin
             if (points > maxPoints) then maxPoints := points;
             if (objs > maxObj)      then maxObj    := objs;
             if (msec > queryTime)   then queryTime := msec;
             if (msec > BLACKLIST_THRESHOLD) then // move it to the blacklist
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.active[a].color,
                      ') active -> blacklist');
                {$ENDIF}
                self.blacklist.append(self.active[a]);
                self.active.deleteIndex(a);
             end
             else if (objs < 1) then // move it to the runty list
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.active[a].color,
                      ') active -> runty');
                {$ENDIF}
                self.runty.append(self.active[a]);
                self.active.deleteIndex(a);            
             end;
       end;
         
       if (s >= 0) then
          with self.successful[s] do
          begin
             if (points > maxPoints) then maxPoints := points;
             if (objs > maxObj)      then maxObj    := objs;
             if (msec > queryTime)   then queryTime := msec;
             if (msec > BLACKLIST_THRESHOLD) then // move it to the blacklist
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.successful[s].color,
                      ') successful -> blacklist');
                {$ENDIF}
                self.blacklist.append(self.successful[s]);
                self.successful.deleteIndex(s);
             end
             else if (objs < 1) then // move it to the runty list
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.successful[s].color,
                      ') successful -> runty');
                {$ENDIF}
                self.runty.append(self.successful[s]);
                self.successful.deleteIndex(s);            
             end;        
          end;
         
       if (b >= 0) then
          with self.blacklist[b] do
          begin
             writeln('Tcolorizer.updatePointCount: Warning - Updating blacklisted color (', col, ')');
             if (points > maxPoints) then maxPoints := points;
             if (objs > maxObj)      then maxObj    := objs;
             if (msec > queryTime)   then queryTime := msec;
          end;
         
       if (r >= 0) then
          with self.runty[r] do
          begin
             writeln('Tcolorizer.updatePointCount: Warning - Updating runty color (', col, ')');
             if (points > maxPoints) then maxPoints := points;
             if (objs > maxObj)      then maxObj    := objs;
             if (msec > queryTime)   then queryTime := msec;
             if (msec > BLACKLIST_THRESHOLD) then // move it to the blacklist
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.runty[r].color,
                      ') runty -> blacklist');
                {$ENDIF}
                self.blacklist.append(self.runty[r]);
                self.runty.deleteIndex(r);
             end
             else if (objs > 1) then // it started providing matches, move out of runty
             begin
                {$IFDEF DEBUG_ON}
                   writeln('***** Tcolorizer.updatePointCount: moving (', self.runty[r].color,
                      ') runty -> active');
                {$ENDIF}
                self.active.append(self.runty[r]);
                self.runty.deleteIndex(r);            
             end;
          end;  
    end;

    // -----------------------------------------------------------------------------
    // delete()
    //
    // Delete info for a color
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.delete(col: integer);

    var
       d, a, s, b, r: integer;
       
    begin
       d := self.discovered.returnInArray(col);
       a := self.active.returnInArray(col);
       s := self.successful.returnInArray(col);
       b := self.blacklist.returnInArray(col);
       r := self.runty.returnInArray(col);

       if (d+a+s+b+r = -5) then
       begin
          writeln('Tcolorizer.delete: ERROR - Asked to delete color, ',
             col, ' - does not exist');
          exit;
       end

       {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.delete: deleting (', col, ')'); {$ENDIF}
               
       if (d >= 0) then self.discovered.delete(col);
       if (a >= 0) then self.active.delete(col);
       if (s >= 0) then self.successful.delete(col);
       if (b >= 0) then self.blacklist.delete(col);
       if (r >= 0) then self.runty.delete(col);
    end;

    // -----------------------------------------------------------------------------
    // cleanupColors()
    //
    // Weeds down the color list.  Does not clean sucessful, blacklisted,
    // or runty lists since these keep us from using bad colors or are the result
    // of hard searching.
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.cleanupColors();

    var
       i, t, cnt: integer;
       found: boolean;
       tmp: Tcolorizer;
       
    begin
       self.discovered.cleanupColors();
       self.active.cleanupColors();
    end;
     
    // -----------------------------------------------------------------------------
    // _gatherQ()
    //
    // Gathers a color by screen quadrants so we dont get so bogged
    // down on background colors that take forever to collect.  Hopefully
    // don't have to break this into eights or make it recursive.
    // -----------------------------------------------------------------------------
    function Tcolorizer._gatherQ(var tpa: TPointArray; col: integer): boolean;

    var
       b: TBox;
       c: TPoint;
       quadrant: array[0..3] of TBox;
       i: integer;
       timer: TTimeMarker;
       qtpa: TPointArray;
       
    begin
       b := mainscreen.getBounds();
       c := mainscreen.getCenterPoint();
       // NE, SE, SW, NW
       quadrant[0] := IntToBox(c.x,  b.y1, b.x2, c.y);
       quadrant[1] := IntToBox(c.x,  c.y,  b.x2, b.y2);
       quadrant[2] := IntToBox(b.x1, c.y,  c.x,  b.y2);
       quadrant[3] := IntToBox(b.x1, b.y1, c.x,  c.y);

       setLength(tpa, 0);
       timer.start();
       {$IFDEF DEBUG_ON} writeln('***** Tcolorizer._gatherQ: gathering colors for (', col, ')'); {$ENDIF}
       for i := 0 to 3 do
       begin
          setLength(qtpa, 0);
          if (findColorsTolerance(qtpa, col, quadrant[i], self.tol)) then
          begin
             if (timer.getTime() > (BLACKLIST_THRESHOLD div 4)) then
             begin
                // dump this color for something more productive
                self.updatePointCount(col, length(qtpa)*4, 0, BLACKLIST_THRESHOLD+1);
                result := false;
                exit;
             end
             else
                tpa.combine(qtpa);
          end;
       end;
       if (length(tpa) > 0) then
          result := true
       else
          result := false;
    end;

    // -----------------------------------------------------------------------------
    // gather()
    //
    // Gathers a color into an atpa.
    // -----------------------------------------------------------------------------
    function Tcolorizer.gather(var atpa: T2DPointArray; c: integer): boolean;

    var
       tpa: TPointArray;
       timer: TTimeMarker;
       
    begin
       setLength(tpa, 0);
       result := true;
       timer.start();
       if (not self._gatherQ(tpa, c)) then
       begin
          result := false;
          // no point in updating if it already got blacklisted
          if (not self.blacklist.isInArray(c)) then
             self.updatePointCount(c, 0, 0, timer.getTime());
          exit;
       end;

       atpa := tpa.split(self.dist);
       atpa.filterBetween(0, self.minPixels);
       atpa.filterBetween(self.maxPixels, maxint);
       atpa.sortBySize();

       if (length(atpa) = 0) then
          result := false;
       
       self.updatePointCount(c, length(tpa), length(atpa), timer.getTime());
    end;
     
    // -----------------------------------------------------------------------------
    // sample()
    //
    // Grabs a sampling of colors around the mouse area
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.sample(n: integer = 3);

    var
       i, x, y: integer;
       b: TBox;
       colList: TIntegerArray;
       
    begin
       getMousePos(x,y);
       b := [x, y, x, y];
       b.expand(n);
       if (b.x1 < 0) then b.x1 := 0;
       if (b.x2 < 0) then b.x2 := 0;
       if (b.y1 < 0) then b.y1 := 0;
       if (b.y2 < 0) then b.y2 := 0;
       
       colList := getColors(b.createTPA());
       
       for i := 0 to high(colList) do
          self.updateCount(colList[i], 1);
    end;
     
    // -----------------------------------------------------------------------------
    // deepSample()
    //
    // Jiggles the mouse around a good spot to see if we can collect more colors
    // -----------------------------------------------------------------------------
    procedure Tcolorizer.deepSample(x: integer; y: integer; n: integer = 3);

    var
       p: TPoint;
       i, t: integer;
       matched: boolean;
       s: string;
       
    begin
       p.create(x,y);
       i := 5;
       matched := true;
       while (matched) do
       begin
          matched := false;        
          mouse(p.rand(i));
          inc(i);

          t := getSystemTime() + randomRange(uptextTimeout, uptextTimeout+80);
          repeat
             wait(20);
             s := getMouseOverText();
             if (pos(self.uptext, s) > 0) then
             begin
                matched := true;
                self.sample(n);
             end
             else
                if (s <> '') then  // we got an uptext, but it isnt what we want
                   break;
          until (matched or (getSystemTime() > t));        
       end;
    end;      
         
         
    // -----------------------------------------------------------------------------
    // untriedColors()
    //
    // Returns an array of colors we havent tried yet
    // -----------------------------------------------------------------------------
    function Tcolorizer.untriedColors() : TIntegerArray;

    var
       i, j: integer;
       closeToBG, bgList: TIntegerArray;
       
    begin
       if (length(self.discovered) > CLEANUP_LOW_WATER) then
          self.cleanupColors(); // might as well try to cut it down

       self.discovered.sortByCount();

       // put colors close to successful ones first in the list
       for i := 0 to high(self.successful) do
          for j := 0 to high(self.discovered) do
          begin
             if SimilarColors(self.successful[i].color, self.discovered[j].color, 10) then
             begin
                result.append(self.discovered[j].color);
                break;
             end;
          end;

       // find background colors (blacklisted with high queryTime).  Put
       // things close to the blacklist at the end.
       setLength(bgList, 0);
       for i := 0 to high(self.blacklist) do
       begin
          if self.blacklist[i].queryTime > BLACKLIST_THRESHOLD then
             bgList.append(self.blacklist[i].color);
       end;
       setLength(closeToBG, 0);
       for i := 0 to high(bgList) do
          for j := 0 to high(self.discovered) do
          begin
             if (not result.isInArray(self.discovered[j].color)) and
                SimilarColors(bgList[i], self.discovered[j].color, 10) then
             begin
                closeToBG.append(self.discovered[j].color);
                break;
             end;
          end;  
       
       for i := 0 to high(self.discovered) do
          if (not result.isInArray(self.discovered[i].color)) and
             (not closeToBG.isInArray(self.discovered[i].color)) then
          begin
             result.append(self.discovered[i].color);
          end;
         
       result.combine(closeToBG);
    end;
       
    // -----------------------------------------------------------------------------
    // activeColors()
    //
    // Returns an array of colors we need to test more
    // -----------------------------------------------------------------------------
    function Tcolorizer.activeColors() : TIntegerArray;

    var
       i: integer;
       
    begin
       if (length(self.active) > CLEANUP_LOW_WATER) then
          self.cleanupColors(); // might as well try to cut it down
         
       setLength(result, 0);
       self.active.sortBySuccess();
       for i := 0 to high(self.active) do
          result.append(self.active[i].color);
    end;

    // -----------------------------------------------------------------------------
    // successfulColors()
    //
    // Returns an array of colors we have confidence in
    // -----------------------------------------------------------------------------
    function Tcolorizer.successfulColors() : TIntegerArray;

    var
       i: integer;
       
    begin
       self.successful.sortBySuccess();
       for i := 0 to high(self.successful) do
          result.append(self.successful[i].color);
    end;

    // -----------------------------------------------------------------------------
    // testCol()
    //
    // Sees if a color will get us to the desired mousetext
    // -----------------------------------------------------------------------------
    function Tcolorizer.testCol(c: integer; trials: integer = 1): boolean;

    var
       i, t, x, y: integer;
       s: string;
       atpa: T2DPointArray;
       matched: boolean;
         
    begin    
       result := false;
       if (not self.gather(atpa, c)) then
       begin
          self.updateTrials(c, false);
          exit;
       end;
         
       for i := 0 to high(atpa) do
       begin
          if (trials = 0) then
             break
          else
             trials := trials - 1;;

          atpa[i].getBounds().mouse();
         
          matched := false;
          t := getSystemTime() + randomRange(uptextTimeout, uptextTimeout+80);
          repeat
             wait(20);
             s := getMouseOverText();
             if (pos(self.uptext, s) > 0) then
                matched := true
             else
                if (s <> '') then  // we got an uptext, but it isnt what we want
                   break;
          until (matched or (getSystemTime() > t));
         
          if (matched) then
          begin
             getMousePos(x,y);
             case random(10) of
                3,4: self.deepSample(x,y);
             end;
             self.updateTrials(c, true);
             result := true;
          end
          else
             self.updateTrials(c, false);
       end;  
    end;

    // -----------------------------------------------------------------------------
    // colorize()
    //
    // Tests new and in progress colors to try to find new ones that are successful.
    // -----------------------------------------------------------------------------
    function Tcolorizer.colorize(maxTime: integer = 120000; enough: integer = 5): boolean;

    var
       i, timeout: integer;
       tia: TIntegerArray;
       
    begin
       if (length(self.successful) >= enough) then exit;
         
       timeout := getSystemTime() + maxTime;

       result := false;

       while (getSystemTime() < timeout) do
       begin  
          while ((length(self.active) < 8) and (length(self.discovered) > 0)) do
          begin
             tia := self.untriedColors();
             if (length(tia) < 1) then exit;
             self.testCol(tia[0], 1);
          end;
         
          tia := self.activeColors();
          if (length(tia) < 1) then exit;
          for i := 0 to min(high(tia), 4) do
          begin
             self.testCol(tia[i], 2);      
          end;
         
          if (length(self.successful) >= enough) then
          begin
             {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.colorize: REACHED SUCCESS!!!'); {$ENDIF}
             result := true;
             exit;
          end;
       end;
    end;

    // -----------------------------------------------------------------------------
    // detectObj()
    //
    // Detect an object in a box.
    // -----------------------------------------------------------------------------
    function Tcolorizer.detectObj(var x: integer; var y: integer; var menuText: string;
       b: TBox; mouseButton: integer = MOUSE_MOVE): boolean;

    var
       i, j: integer;
       s: string;
       opts: TOptionArray;
       t: integer;
       p: TPoint;
       matched: boolean;
       
    begin
       x := 0;
       y := 0;
       menuText := '';
       result := false;
       matched := false;
       
       if (mouseButton = MOUSE_NONE) or (mouseButton = MOUSE_MIDDLE) then exit;
       
       t := getSystemTime() + randomRange(uptextTimeout, uptextTimeout+80);
       
       repeat
          b.mouse();
          wait(20);
          s := getMouseOverText();
          if (pos(self.uptext, s) > 0) then
          begin
             menuText := s;
             matched := true;
             result := true;
          end
          else    
             if (s <> '') then break;    // we got an uptext, but it isnt what we want
             
       until (matched or (getSystemTime() > t));

       if (matched) then
       begin
          self.sample();
          getMousePos(x,y);          // save this for a sec
          case (mouseButton) of
             MOUSE_LEFT:
                begin
                   fastClick(MOUSE_LEFT);
                   exit;
                end;
             MOUSE_RIGHT, MOUSE_MOVE:
                begin
                   fastClick(MOUSE_RIGHT);
                   if (mouseButton = MOUSE_RIGHT) then
                   begin
                      result := chooseoption.select([self.uptext], 100);
                      exit;
                   end              
                   opts := chooseOption.getOptions();
                   chooseOption.close();
                   for j := 0 to high(opts) do
                   begin
                      if (pos(self.uptext, opts[j].str) > 0) then
                      begin
                         menuText := opts[j].str;
                         break;
                      end;
                   end;
                   mouse(point(x,y), MOUSE_MOVE);
                end;
          end;
       end;
    end;

    // -----------------------------------------------------------------------------
    // examineGrid()
    //
    // Try to detect an object in one of the boxes in grid.
    // -----------------------------------------------------------------------------
    function Tcolorizer.examineGrid(grid: TBoxArray): string;

    var
       i, j, x, y, t: integer;
       s: string;
       opts: TOptionArray;
       p: TPoint;
       matched: boolean;
       
    begin
       result := '';
       while (length(grid) > 0) do
       begin
          i := randomRange(0, length(grid));    
          if self.detectObj(x, y, s, grid[i]) then
          begin
             result := s;
             break;
          end;
          grid.deleteIndex(i);
       end;
       if (result <> '') then
          case random(10) of
             3,4: self.deepSample(x,y);  
          end;
    end;

    // -----------------------------------------------------------------------------
    // motionDetect()
    //
    // Finds objects based on screen movement (pixel shift).
    // -----------------------------------------------------------------------------
    function Tcolorizer.motionDetect(): string;

    var
       i, j, t: integer;
       grid, targetGrid, tried: TBoxArray;
       pixels: TIntegerArray;
       max, pct: integer;
     
    begin
       result := '';
       setLength(tried, 0);
       grid := mainscreen.getBounds().split(GRIDSIZE, GRIDSIZE);
       
       for t := 15 to 95 with 20 do
       begin
          if (t > 70) then              // we're not doing very good, lets try some
             setLength(tried, 0);       // of the boxes we tried earlier
             
          pixels := grid.pixelShift(PIXELSHIFT_WAIT);
          max := pixels.max();
         
          setLength(targetGrid, 0);
          for i := 0 to high(grid) do
          begin
             if (tried.isInArray(grid[i])) then     // dont keep moving the mouse to the
                continue;                           // same place... try new ones
             
             pct := trunc( ((pixels[i]/max) * 100.0 ));
             if ((pct + t) > 100) then
             begin    
                setLength(targetGrid, length(targetGrid)+1);
                targetGrid[high(targetGrid)] := grid[i];
             end;
          end;
         
          result := self.examineGrid(targetGrid);      
          if (result = '') then
          begin
             {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.motionDetect: FAILED TO IDENTIFY ANYTHING.  tol=', t); {$ENDIF}
          end
          else
          begin
             {$IFDEF DEBUG_ON} writeln('***** Tcolorizer.motionDetect: Identified - ', result); {$ENDIF}
             exit;
          end;
         
          tried.combine(targetGrid);
       end;
    end;    

    ///////////////////////////////////////////////////////////////////////////
    ///////////   TEST PROGRAM
    ///////////
    ///////////////////////////////////////////////////////////////////////////
    var
       colorTest: Tcolorizer;
       i, t: integer;
       name: string;

    begin
       smartPlugins := ['d3d9.dll'];
       smartEnableDrawing := true;
       ClearDebug();
       SetupSRL();

       colorTest.init('Unknown', 'Attack', 150 {uptext timeout}, 3 {tol},
          5 {dist}, 5 {min}, 1000 {max});
         
       t := getSystemTime();
       name := colorTest.motionDetect();
       if (name <> '') and (name <> 'Attack') then
       begin
          writeln('took ', getSystemTime() - t, ' to detect ', name);
         
          colorTest.name := name;
          colorTest.load();
          writeln(colorTest);
         
          for i := 1 to ( length(colorTest.successful) + 5 ) do
          begin
             t := getSystemTime();
             colorTest.colorize(60000, i);
             writeln('took ', getSystemTime() - t, ' to identify good color # ', i);
          end;

          writeln(colorTest);
          colorTest.save();
       end;
    end.

  2. #2
    Join Date
    Sep 2007
    Location
    Australia, NSW
    Posts
    934
    Mentioned
    6 Post(s)
    Quoted
    145 Post(s)

    Default

    Wow. Impressive. I may test these functions out at some point

    INACTIVE
    How-to: Make S.M.A.R.T. less laggy

    Sell me your Maple Shieldbows (u)! Up to 95gp ea!

    My Scripts:
    Ivy Chopper Ultra [RS3] | Fantastic Fletcher [RS3]
    99 x78 | 99 x10 | 99 x2 | 99 x12


    Use the REPORT tags when posting progress reports to make life easier (:
    [REPORT]Put progress report in here![/REPORT]

    Super Savvy Smither V1.06Cool Classy Cooker V1.02 [EoC]

  3. #3
    Join Date
    May 2013
    Posts
    205
    Mentioned
    1 Post(s)
    Quoted
    85 Post(s)

    Default

    so it detects npc's (any) automatically? without us having to assign any color?

  4. #4
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by toxjq View Post
    so it detects npc's (any) automatically? without us having to assign any color?
    Right.

    It uses pixel shift to find moving things that match the uptext, then grabs the colors around the mouse.

    It tests those to see if they work. Whenever an NPC is found we take a sample of more colors around the successful point. Whenever a color is tried it keeps track of it so it can accept/reject them based on success rate.

    The idea could be used more broadly than just NPCs but that's what I wrote it for.

  5. #5
    Join Date
    Feb 2012
    Location
    Portugal
    Posts
    91
    Mentioned
    3 Post(s)
    Quoted
    41 Post(s)

    Default

    Just amazing! Outstanding really! I need to try it, I wanna see this working :3
    It is implemented on your fighter already? Or you are still developing it?

  6. #6
    Join Date
    May 2013
    Posts
    205
    Mentioned
    1 Post(s)
    Quoted
    85 Post(s)

    Default

    Quote Originally Posted by bonsai View Post
    Right.

    It uses pixel shift to find moving things that match the uptext, then grabs the colors around the mouse.

    It tests those to see if they work. Whenever an NPC is found we take a sample of more colors around the successful point. Whenever a color is tried it keeps track of it so it can accept/reject them based on success rate.

    The idea could be used more broadly than just NPCs but that's what I wrote it for.
    wow thats really cool, how are you counting for other players? they are moving pixels also right

  7. #7
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by PatriqDesigns View Post
    Just amazing! Outstanding really! I need to try it, I wanna see this working :3
    It is implemented on your fighter already? Or you are still developing it?
    Thanks. I'm still working on updating the fighter script to use it.

    The script in the first post is fully functional though if you want to see it in action. It doesn't have any fighting logic but it does the motion detection and color refinement.

  8. #8
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by toxjq View Post
    wow thats really cool, how are you counting for other players? they are moving pixels also right
    It uses the mouseovertext. If that matches the requested string (Attack in this case) then it's considered a success.

  9. #9
    Join Date
    Aug 2007
    Location
    Colorado
    Posts
    7,421
    Mentioned
    268 Post(s)
    Quoted
    1442 Post(s)

    Default

    That's some unique ingenuity, I love it! I'd sure like to see a video of this in action. When you have it up and running how you want it would you mind providing an example video or something? This sounds interesting.

    Current projects:
    [ AeroGuardians (GotR minigame), Motherlode Miner, Blast furnace ]

    "I won't fall in your gravity. Open your eyes,
    you're the Earth and I'm the sky..."


  10. #10
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by Flight View Post
    That's some unique ingenuity, I love it! I'd sure like to see a video of this in action. When you have it up and running how you want it would you mind providing an example video or something? This sounds interesting.
    Video added to OP.

    It's all still rough but coming together. I had to cut out 30sec around :30 because it searched on one of those background brown colors.

  11. #11
    Join Date
    Jan 2012
    Location
    East Coast
    Posts
    733
    Mentioned
    81 Post(s)
    Quoted
    364 Post(s)

    Default

    Can this be used for any npc as long as the requested string is changed?

  12. #12
    Join Date
    Jun 2007
    Location
    The land of the long white cloud.
    Posts
    3,702
    Mentioned
    261 Post(s)
    Quoted
    2006 Post(s)

    Default

    Quote Originally Posted by bonsai View Post
    Video added to OP.

    It's all still rough but coming together. I had to cut out 30sec around :30 because it searched on one of those background brown colors.
    WOW that is COOL! Have you ever experienced it grabbing incorrect colours I.e. say the NPC moves too fast but the mouseOverText is still up (Your mouse can be offset from the NPC but mouseOverText box still shows) and you grab a floor colour or something?

  13. #13
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by The Mayor View Post
    WOW that is COOL! Have you ever experienced it grabbing incorrect colours I.e. say the NPC moves too fast but the mouseOverText is still up (Your mouse can be offset from the NPC but mouseOverText box still shows) and you grab a floor colour or something?
    Oh, hell yeah! I've been fighting with all that.

    I grab a 7x7 where the mouse is and that's usually enough to pick up some good color with the bad. It boots itself so as long as it hits some success it tends to breed more.

    It grabs a sample every time it makes a hit so it gets lots of color choices. It also does a deep scan sometimes and wiggles the mouse around an NPC to grab lots of color.

    The biggest problem is that there's no findcolor/countcolor with a timeout. So you get a rotten color like 0 and it take 45 seconds for simba to hand back the array you don't want. I broke the search into quadrants but it's still painful sometimes.

    It's not something that is awesome 100% of the time. Sometime the NPCs don't move much or there is a waterfall making noise. Sometimes it grabs too much background like you mention and it fails to color. But it's working out ok.

    It even managed to color the bandits in AlK where they match the tents. That surprised me.

    I published a working fighter in my thread if you want to see it in action.

  14. #14
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by therossity View Post
    Can this be used for any npc as long as the requested string is changed?
    It just uses the word attack on the uptext, so yes, any npc.

    I'm grabbing the full name from the right click menu but it's hit or miss on the OCR.

    Of course, just because it will self color doesn't mean you can run it anywhere. All the age old problems are still relevant.

    If the NPC matches a lot of other things it may not work well. If you aren't in an enclosed space you may wander away ...

  15. #15
    Join Date
    Jan 2012
    Location
    East Coast
    Posts
    733
    Mentioned
    81 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by bonsai View Post
    It just uses the word attack on the uptext, so yes, any npc.

    I'm grabbing the full name from the right click menu but it's hit or miss on the OCR.

    Of course, just because it will self color doesn't mean you can run it anywhere. All the age old problems are still relevant.

    If the NPC matches a lot of other things it may not work well. If you aren't in an enclosed space you may wander away ...

    Ahh yeah I figured. I'm still having a lot of trouble nailing down Ellis in Al Kharid. He has like 1 or 2 colors that don't match literally the entire screen.

  16. #16
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by therossity View Post
    Ahh yeah I figured. I'm still having a lot of trouble nailing down Ellis in Al Kharid. He has like 1 or 2 colors that don't match literally the entire screen.
    It colored him OK.

    Here's the colors it thought were good (CTS0 tol 3)

    Code:
    3094075
    3094332
    2896183
    3160125
    3159868
    3028282
    3225918
    2962232
    2962489
    5731980
    3028025
    3292482
    6991083
    3358018
    5797260

    Code:
      <successful>
        <colorRecord><color>3094075</color><count>84</count><attempts>5</attempts><matches>5</matches><lastPoints>19</lastPoints><lastObj>1</lastObj><maxPoints>21</maxPoints><maxObj>1</maxObj><queryTime>15</queryTime></colorRecord>
        <colorRecord><color>3094332</color><count>61</count><attempts>5</attempts><matches>5</matches><lastPoints>18</lastPoints><lastObj>1</lastObj><maxPoints>18</maxPoints><maxObj>1</maxObj><queryTime>15</queryTime></colorRecord>
        <colorRecord><color>2896183</color><count>51</count><attempts>6</attempts><matches>5</matches><lastPoints>12</lastPoints><lastObj>1</lastObj><maxPoints>12</maxPoints><maxObj>1</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>3160125</color><count>66</count><attempts>6</attempts><matches>5</matches><lastPoints>18</lastPoints><lastObj>1</lastObj><maxPoints>20</maxPoints><maxObj>1</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>3159868</color><count>46</count><attempts>5</attempts><matches>5</matches><lastPoints>14</lastPoints><lastObj>1</lastObj><maxPoints>15</maxPoints><maxObj>1</maxObj><queryTime>0</queryTime></colorRecord>
        <colorRecord><color>3028282</color><count>50</count><attempts>6</attempts><matches>5</matches><lastPoints>21</lastPoints><lastObj>1</lastObj><maxPoints>21</maxPoints><maxObj>1</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>3225918</color><count>35</count><attempts>5</attempts><matches>5</matches><lastPoints>21</lastPoints><lastObj>1</lastObj><maxPoints>21</maxPoints><maxObj>1</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>2962232</color><count>48</count><attempts>6</attempts><matches>5</matches><lastPoints>11</lastPoints><lastObj>1</lastObj><maxPoints>13</maxPoints><maxObj>1</maxObj><queryTime>0</queryTime></colorRecord>
        <colorRecord><color>2962489</color><count>14</count><attempts>5</attempts><matches>5</matches><lastPoints>14</lastPoints><lastObj>1</lastObj><maxPoints>14</maxPoints><maxObj>1</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>5731980</color><count>176</count><attempts>7</attempts><matches>5</matches><lastPoints>487</lastPoints><lastObj>2</lastObj><maxPoints>487</maxPoints><maxObj>2</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>3028025</color><count>25</count><attempts>5</attempts><matches>5</matches><lastPoints>19</lastPoints><lastObj>1</lastObj><maxPoints>21</maxPoints><maxObj>1</maxObj><queryTime>0</queryTime></colorRecord>
        <colorRecord><color>3292482</color><count>60</count><attempts>5</attempts><matches>5</matches><lastPoints>16</lastPoints><lastObj>1</lastObj><maxPoints>19</maxPoints><maxObj>1</maxObj><queryTime>16</queryTime></colorRecord>
        <colorRecord><color>6991083</color><count>62</count><attempts>5</attempts><matches>5</matches><lastPoints>24</lastPoints><lastObj>1</lastObj><maxPoints>24</maxPoints><maxObj>1</maxObj><queryTime>15</queryTime></colorRecord>
        <colorRecord><color>3358018</color><count>22</count><attempts>6</attempts><matches>5</matches><lastPoints>16</lastPoints><lastObj>1</lastObj><maxPoints>18</maxPoints><maxObj>1</maxObj><queryTime>0</queryTime></colorRecord>
        <colorRecord><color>5797260</color><count>13</count><attempts>5</attempts><matches>5</matches><lastPoints>553</lastPoints><lastObj>2</lastObj><maxPoints>553</maxPoints><maxObj>2</maxObj><queryTime>16</queryTime></colorRecord>
      </successful>

  17. #17
    Join Date
    Jan 2012
    Location
    East Coast
    Posts
    733
    Mentioned
    81 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by bonsai View Post
    It colored him OK.

    Here's the colors it thought were good (CTS0 tol 3)

    Code:
    3094075
    3094332
    2896183
    3160125
    3159868
    3028282
    3225918
    2962232
    2962489
    5731980
    3028025
    3292482
    6991083
    3358018
    5797260

    You're a saint!


    Edit: Is there a way I can plug these into ACA? Sorry, I'm new to this.
    Last edited by Ross; 08-10-2014 at 02:22 AM.

  18. #18
    Join Date
    Dec 2011
    Location
    East Coast, USA
    Posts
    4,231
    Mentioned
    112 Post(s)
    Quoted
    1869 Post(s)

    Default

    Quote Originally Posted by therossity View Post
    You're a saint!


    Edit: Is there a way I can plug these into ACA? Sorry, I'm new to this.
    Create an empty .txt file, paste the values into it (like bonsai gave them to you, with linebreaks and all), and save it as whatever.aca

    open up with ACA, poof done
    GitLab projects | Simba 1.4 | Find me on IRC or Discord | ScapeRune scripts | Come play bot ScapeRune!

    <BenLand100> we're just in the transitional phase where society reclassifies guns as Badâ„¢ before everyone gets laser pistols

  19. #19
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by therossity View Post
    You're a saint!


    Edit: Is there a way I can plug these into ACA? Sorry, I'm new to this.
    I don't know about entering them but the files it saves are just a list of colors, so save that list as ellis.aca and open it.

  20. #20
    Join Date
    Jan 2012
    Location
    East Coast
    Posts
    733
    Mentioned
    81 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by KeepBotting View Post
    Create an empty .txt file, paste the values into it (like bonsai gave them to you, with linebreaks and all), and save it as whatever.aca

    open up with ACA, poof done
    Found out that the "add color" button worked as well, but your way is a lot easier! Thanks!

  21. #21
    Join Date
    Jan 2007
    Posts
    8,876
    Mentioned
    123 Post(s)
    Quoted
    327 Post(s)

    Default

    My Jimmies have been thoroughly rustled.

  22. #22
    Join Date
    Aug 2014
    Location
    Michigan, USA
    Posts
    138
    Mentioned
    1 Post(s)
    Quoted
    68 Post(s)

    Default

    Does this work in Runespan?

  23. #23
    Join Date
    Oct 2013
    Location
    East Coast USA
    Posts
    770
    Mentioned
    61 Post(s)
    Quoted
    364 Post(s)

    Default

    Quote Originally Posted by xsorrels View Post
    Does this work in Runespan?
    It can be used to find colors for things that move (twinkle) and have an uptext. I've also used it on non-moving things but I have to do a lot of prep work.

    It finds lists of cts0 colors so it's not a substitute for ACA if you need a single color for something.

    I haven't looked at any of the runespan scripts but I'm guessing they have a single CTS2 color for each item? That would be a job for ACA.

    ACA (v2) (v3) (Yohojo video).

  24. #24
    Join Date
    Dec 2006
    Posts
    908
    Mentioned
    1 Post(s)
    Quoted
    17 Post(s)

    Default

    Wow thank you for having a thread dedicated to this. It really is interesting, and when my finals are over, I MUST study this. It's just too good.

  25. #25
    Join Date
    Dec 2006
    Posts
    908
    Mentioned
    1 Post(s)
    Quoted
    17 Post(s)

    Default

    Wow thank you for having a thread dedicated to this. It really is interesting, and when my finals are over, I MUST study this. It's just too good.

    Just brainstorming possible applications of this function.

Page 1 of 2 12 LastLast

Thread Information

Users Browsing this Thread

There are currently 1 users browsing this thread. (0 members and 1 guests)

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •