Results 1 to 3 of 3

Thread: Unique, Simple, and effective color finding with TPA's

  1. #1
    Join Date
    Feb 2007
    Posts
    3,616
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default Unique, Simple, and effective color finding with TPA's

    Hey everyone. If you already know what a TPoint is and what a TPA is, then you can skip to the second part of this tutorial.

    I do not know how to effectively use any of the functions in the WizzyPlugin.
    I do not know how to create custom TPointArrays.
    I do not know how to effectively use any function that looks like:
    SplitT2dTPAExAndSortATPAFromMiddleTPACombinedWithS ortATPABySize
    Yet I can still find objects effectively.

    I am not saying that it is bad to learn all that stuff like custom TPA's, because I am sure that in many instances (probably most instances) they are more effective than my methods (In fact, it is probably about time that I take the time to learn about it myself). But for the most part, you can get by in just about any script just fine without that stuff in my opinion.


    TPoint Date Type

    TPoint is just another type of variable. Lets start by declaring a TPoint variable like we would with any other type of variable:

    SCAR Code:
    var
      T: TPoint;

    TPoints are a data type that is basically 2 integer variables combined, called x and y. It was designed to hold the coordinates of a point, which we know by now are x and y. How can we access each individual integer? With a period ".":

    SCAR Code:
    T.x := 5;
      T.y := 20;
      MoveMouse(T.x,T.y);

    Pretty self explanatory, right? Lets move onto TPointArrays


    TPoint Arrays

    This tutorial is in the advanced section, so I expect you to know what an array is. If you know what an array is, and you know what a TPoint is, than the concept of the TPA data type is very simple. Lets declare one:

    SCAR Code:
    var
      TPA: TPointArray;

    Now to use it a bit:

    SCAR Code:
    var
      TPA: TPointArray;
      mx,my: Integer;

    TPA[0].x := 12;
    TPA[0].y := 75;

    TPA[1].x := 186;
    TPA[1].y := 375;

    if(FindColor(x,y,2973685,TPA[0].x,TPA[0].y,TPA[1].x,TPA[1].y))then
      MoveMouse(x,y);

    Make sense? Just like TPoints except you can have multiple of them with one name. We used both the points (TPA[0] and TPA[1]) as a coordinate box to look for a color in. You can use each member like that just like any other integer. Moving on...


    My methods of use for TPA's


    So right now you should know what a TPoint is, what a TPointArray is, and how to declare them and use them on their own. Not much use for them without some functions. These are the only functions that we are going to need to use for all of our color finding:

    Code:
    FindColorsSpiralTolerance(x, y: Integer; var Points: TPointArray; color, xs, ys, xe, ye: Integer; Tolerance: Integer): Boolean;
    GetArrayLength(var Arr): Integer;
    High(x): int64;
    You may be wondering how we can possibly do all of our color finding efficiently using only 3 functions, or you may have faith in me that we can do it. Either way, I'll explain all 3 of the functions here:

    Code:
    FindColorsSpiralTolerance
    
    Notice that it is Colors, not Color.  This makes it a completely different
    function.  This function is used to count all of the colors with tolerance in a
    coordinates box (that you specify), and store them all in a TPointArray.
    When using FindColorsSpiralTolerance, you send it 9 different parameters:
    
    an x and y variable: You don't need to worry about what this is for because
    we will not really be using it, but I believe that this is just the first point that
    the function finds.
    
    A TPointArray to store all of the found colors in.
    
    The color that we want to search for.
    
    The next 4 are the coordinates box to search for/count the colors in.
    
    The last parameter is the tolerance for the color we are looking for.
    Code:
    GetArrayLength
    
    This function you simply send an array to (we will be sending it a TPA), and
    it returns the amount of members it uses.  For example, if we stored values
    in the first 5 members of a TPA (TPA[0].x and TPA[0].y   through   TPA[4].x
    and TPA[4].y), GetArrayLength(TPA) would return 5.
    Code:
    High
    
    This function returns the highest member in an array.  Using the example
    from GetArrayLength, High would return 4, because that is the last member
    that has data stored in it.

    Ok, now we can get to the fun part: Using all of this in your scripts. I am going to be using a few pieces from my clay softener as examples.


    My FillBuckets function. We have to find the well on the main screen and click it to fill the buckets. There are many similar colors around this well though, so a simple FindObj will not work in this case. Here's the concept I used in my script (obviously not the whole thing):

    SCAR Code:
    function FillBuckets: Boolean;
    var
      TPA, TPA2: TPointArray;
      i, Timer: Integer;
    begin
      FindColorsSpiralTolerance(x,y,TPA,3955306,MSX1,MSY1,338,MSY2,6);
      repeat
        FindColorsSpiralTolerance(x,y,TPA2,3955306,TPA[i].x-25,TPA[i].y-35,TPA[i].x+25,TPA[i].y+35,6);
        if(GetArrayLength(TPA2) >= 188)then
        begin
          MMouse(TPA[i].x,TPA[i].y,4,4);
          if(IsUpText('Well'))then
          begin
            Writeln('We found the well!');
            GetMousePos(x,y);
            Mouse(x,y,0,0,true);
            Result := true;
            Exit;
          end;
        end;
        i := i + 10;
      until(i >= High(TPA) - 11);
    end;
    Note: x and y are global variables.


    First, I counted all of the colors (3955306) on the main screen with a tolerance (6) and stored them in TPA. Then I loop through each point of the array (skipping by 10's because I increment I by 10 each time). For each point, I do a second color count using TPA2, but only searching by a 50x50 box around it. If in that 50x50 box, there were 188 or more colors found, then it's probably the well (the biggest object there with these colors). So we move to the suspected well and check it out. If it is, we click and exit out of the function. If not we skip through TPA and do another search until we find it.

    The reason I skip by 10's in this case and do not use a for loop to check every element is because if the mouse goes to the wrong spot, I don't want it to keep moving to elements around there. I know that there are going to be over 190 colors found in the well, so that gives me minimum 19 tries at finding the actual well anyways.

    Hope that I explained that well enough. Lets look at how this can be used for map walking too. The bank I use in edgeville is very close to the well (one map click away). There is a dark red rug inside of the edgeville bank that looks like this:



    and we are supposed to walk to that water symbol near the top left. What I did was counted all of the rug colors, and picked out the point on the rug that was furthest north. I then click specified coordinates to the left and a little up from that point, with a good amount of randomness, to get to the well. Once at the well, I will also use this same method to get to the bank.

    I'm just going to show you a few more parts of the script with comments explaining the logic behind everything.

    SCAR Code:
    function GetTopRug: TPoint; //shortened
    var
      mx,my, i, Tol: Integer;
      TPA, TPA2: TPointArray;
    begin
      MakeCompass('N');
      for i := 3 to 22 do //for tolerance
      begin
        FindColorsSpiralTolerance(x,y,TPA,RugCol,MMX1+12,MMY1,MMX2,MMY2,i); //Count the red rug colors
        if(GetArrayLength(TPA) > 90)then //If there are more than 90 colors, then we know that we used enough
        begin                                         //tolerance and we found the rug
          Tol := i; //Save the required tolerance for later
          break;
        end;
      end;
      if(GetArrayLength(TPA) = 0)then //Never found the rug
      begin
        Writeln('Not finding rug color.  Try setting it in the constants');
        Exit;
      end;
      my := 1000;
      for i := 0 to High(TPA) do //Step through the whole TPA
      begin
        if(TPA[i].y < my)then //if TPA[i].y is the new lowest number (closest to top of screen/top of rug)
        begin
          FindColorsSpiralTolerance(x,y,TPA2,RugCol,TPA[i].x-5,TPA[i].y,TPA[i].x+11,TPA[i].y+20,Tol);
          if(GetArrayLength(TPA2) > 60)then //make sure that it is really the rug by counting around it ^
            if(rs_OnMiniMap(TPA[i].x-32,TPA[i].y-4))then //Make sure that where the well is in reference to this point is on the MM
          begin
            mx := TPA[i].x; //This is the new top most point of the rug
            my := TPA[i].y;
          end;
        end;
      end;
      result.x := mx; //we stepped through all the elements and this must be the top point
      result.y := my;
    end;

    SCAR Code:
    function WalkToWater: Boolean; //Shortened
    var
      T: TPoint;
    begin
      T := GetTopRug; //Get the point where the top of the rug is
      if(not(rs_OnMiniMap(T.x-32,T.y-4))) then //Invalid point or didn't find rug
      begin     //fail safe.  Main walking below
        if(FindSymbolIn(T.x,T.y,'water',MMX1,MMY1,MMCX,MMCY-7))then
        begin //Use the water symbol instead as a fail safe
          Writeln('Did not use rug TPA.  Trying water symbol');
          Result := rs_OnMiniMap(T.x,T.y);
          if(Result)then
          begin
            Mouse(T.x,T.y,5,5,true);
            FFlag(2);
          end else
          begin
            Writeln('Problem walking to water.  Switching players...');
            Logout;
          end;
        end;
        Exit;
      end;
      Mouse(T.x-33,T.y-4,5,5,true); //If GetTopRug returned a valid point, then we move there
      FFlag(2);
      Result := true;
    end;

    SCAR Code:
    //My custom bank opener for edgeville.  Clicks on the banker, not the bank booth (shortened a lot)
    function JADOpenBank: Boolean;
    var
      i, Timer, mx,my: Integer;
      TPA, TPA2: TPointArray;
    begin
      if(not(LoggedIn)) or (BankScreen)then
        Exit;
      FindColorsSpiralTolerance(x,y,TPA,BankerCol,142,39,449,323,12); //BankerCol is a constant I have
      result := false; //above.  I have it there so the user can change if it doesn't work
      for i := 0 to high(TPA) do //Step through all of the colors we just looked for (blue jacket on banker)
      begin
        FindColorsSpiralTolerance(x,y,TPA2,BankerCol,TPA[i].x-15,TPA[i].y-21,TPA[i].x+15,TPA[i].y+21,12);
        if(GetArrayLength(TPA2) > 20) and (GetArrayLength(TPA2) < 100)then
        begin       //Same stuff as usual.  Check the amount of colors around each point and if its
          mx := TPA[i].X; //between 20 and 100, it is probably the banker
          my := TPA[i].y;
          result := true;
          break;
        end;
      end;
      if(not(Result))then
      begin
        Writeln('Could not find banker');
        Exit;
      end;
      MMouse(mx,my,3,3);
    end;


    So there it is. I hope that you learned a few things after reading this and now have some more useful tools to help solve color finding problems. If you have any questions on anything that wasn't explained well enough here, please post and I will do my best to help you.

    Cheers,
    ~JAD

  2. #2
    Join Date
    Apr 2007
    Location
    The Netherlands
    Posts
    5,553
    Mentioned
    0 Post(s)
    Quoted
    0 Post(s)

    Default

    One advice:
    "It's smart to use MM colors which are not accessible for players"
    I use the bankers.
    Last edited by Sir R. M8gic1an; 08-16-2009 at 07:07 PM. Reason: removed tut quote
    ~Hermen

  3. #3
    Join Date
    Dec 2006
    Location
    Sydney, New South Wales, Australia
    Posts
    4,603
    Mentioned
    15 Post(s)
    Quoted
    42 Post(s)

    Default

    Good tutorial JAD Glad you're continuing to write them
    Quote Originally Posted by Hermen View Post
    One advice:
    "It's smart to use MM colors which are not accessible for players"
    I use the bankers.
    Please don't quote the entire tutorial..
    You may contact me with any concerns you have.
    Are you a victim of harassment? Please notify me or any other staff member.

    | SRL Community Rules | SRL Live Help & Chat | Setting up Simba | F.A.Q's |

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
  •