Results 1 to 21 of 21

Thread: How can I make this shorter/neater?

  1. #1
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default How can I make this shorter/neater?

    So I'm rewriting a few functions of grandexchange.simba (quite the educating process) and I came upon what I would call an aesthetic issue. First, I should say what the code does. It basically lets you pick which slot you want to buy from the GE ('any' or 1 to 6). I built in a failsafe that returns a message if the slot isn't free, but in the process I ended up writing a "begin end" with nothing in middle since I didn't want to repeat the same action for the 7 options and make this look even more atrocious. In case that wasn't clear, the action I want it to do if the value is true is the same for the 7 options. Let me show you the code (which works flawlessly as far as I can tell):

    Simba Code:
    function BuyGE(spot : String): Boolean;
    var
      x, y : Integer;
    begin
        if not InGEE then
          Exit;
        if GEESellMenu or GEEBuyMenu then
          GEEMenuExit;
        case spot of
          'any':
             if (FindObject(x,y,BuyButton,MSX1,MSY1,MSX2,MSY2)) then
             begin
             end else
             begin
               Writeln('No slot is free');
               Exit;
             end;
           '1':
             if (FindObject(x,y,BuyButton,35,85,173,190)) then
             begin
             end else
             begin
               Writeln('This slot is not free');
               Exit;
             end;
           '2':
             if (FindObject(x,y,BuyButton,190,85,328,190)) then
             begin
             end else
             begin
               Writeln('This slot is not free');
               Exit;
             end;
           '3':
             if (FindObject(x,y,BuyButton,346,85,485,190)) then
             begin;
             end else
             begin
               Writeln('This slot is not free');
               Exit;
             end;
           '4':
             if (FindObject(x,y,BuyButton,35,200,170,310)) then
             begin
             end else
             begin
               Writeln('This slot is not free');
               Exit;
             end;
            '5':
             if (FindObject(x,y,BuyButton,190,200,330,310)) then
             begin
             end else
             begin
               Writeln('This slot is not free');
               Exit;
             end;
            '6':
             if (FindObject(x,y,BuyButton,345,200,480,300)) then
             begin
             end else
             begin
               Writeln('This slot is not free');
               Exit;
             end;
         end;
           begin;
             ClickMouse2(true);
             WaitOption('Buy O',500);
             WaitFunc(@GEEBuyMenu,10,6000);
           end;
    end;

    I considered coding a separate function which would be the failsafe itself (I really dislike the way I'm repeating many times the same Writeln message), but I was curious about other people's opinions. I'll more than likely be coding that other function which will act as the failsafe by the time someone replies (wondering if I can code this a simple way without using "spot" as a global variable at the moment), but I'd like to know how other people would tackle this issue.

    Any suggestion regarding how I coded this is more than welcome. Also, if you have any question, feel free to ask me.

  2. #2
    Join Date
    Jan 2012
    Posts
    2,568
    Mentioned
    35 Post(s)
    Quoted
    356 Post(s)

    Default

    Since you are not doing any action if condition is false, you can just do:
    if not condition then blabla.

    eg:
    Simba Code:
    if not (FindObject(x,y,BuyButton,MSX1,MSY1,MSX2,MSY2)) then
    begin
      Writeln('No slot is free');
      Exit;
    end;

    Also you dont need the begin and end after ur case statement.

  3. #3
    Join Date
    Jul 2011
    Location
    /home/litoris
    Posts
    2,226
    Mentioned
    0 Post(s)
    Quoted
    159 Post(s)

    Default

    Simba Code:
    function BuyGE(spot : String): Boolean;
    var
      x, y, XS, YS, XE, YE : Integer;
    begin
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        'any':
        begin
          XS := MSX1;
          YS := MSY1;
          XE := MSX2;
          YE := MSY2;
        end;
        '1':
        begin
          XS := 35;
          YS := 85;
          XE := 173;
          YE := 190;
        end;
        //go on like this...
      end;
      if not (FindObject(x,y,BuyButton,345,200,480,300)) then //pointless to do an empty begin-end staetement
      begin                                                   //using not instead
        Writeln('This slot is not free');
        Exit;
      end;
      ClickMouse2(true);
      WaitOption('Buy O',500);
      WaitFunc(@GEEBuyMenu,10,6000);
    end;
    Fixed the standards too.
    Miner & Urn Crafter & 07 Chicken Killer
    SPS BlindWalk Tutorial

    Working on: Nothing

    teacher in every art, brought the fire that hath proved to mortals a means to mighty ends

  4. #4
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default

    Thank you very much. I was actually wondering if the "if not" could be used that way. For some reason, I wasn't able to fully grasp it.

    I really love the way you wrote it down, litoris. I really dread repetition, yet I don't have the knowledge or experience to deal with it appropriately yet. I hadn't considered this way of fixing it and I'm sure it'll be extremely useful in the future even though it's a basic use of variables. I can already think of a few other functions I'll be using it with.

  5. #5
    Join Date
    Jul 2011
    Location
    /home/litoris
    Posts
    2,226
    Mentioned
    0 Post(s)
    Quoted
    159 Post(s)

    Default

    Quote Originally Posted by Wardancer View Post
    Thank you very much. I was actually wondering if the "if not" could be used that way. For some reason, I wasn't able to fully grasp it.

    I really love the way you wrote it down, litoris. I really dread repetition, yet I don't have the knowledge or experience to deal with it appropriately yet. I hadn't considered this way of fixing it and I'm sure it'll be extremely useful in the future even though it's a basic use of variables. I can already think of a few other functions I'll be using it with.
    No problem. The best way to learn handy stuff like this is to read through people's scripts. I learned 90% of the things I know that way, and the rest from tutorials.
    Miner & Urn Crafter & 07 Chicken Killer
    SPS BlindWalk Tutorial

    Working on: Nothing

    teacher in every art, brought the fire that hath proved to mortals a means to mighty ends

  6. #6
    Join Date
    Oct 2006
    Location
    Netherlands
    Posts
    3,285
    Mentioned
    105 Post(s)
    Quoted
    494 Post(s)

    Default

    Simba Code:
    function BuyGE(spot : String): Boolean;
    var
      x, y: Integer;
      searchBox: TBox;
    begin
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        'any':
          searchBox := IntToBox(MMX1, MMY1, MMX2, MMY2);
        '1':
          searchBox := IntToBox(35, 85, 173, 190);
        //go on like this...
      end;
      if not (FindObject(x,y,BuyButton, searchBox.x1, searchBox.y1, searchBox.x2, searchBox.y2)) then //pointless to do an empty begin-end staetement
      begin                                                   //using not instead
        Writeln('This slot is not free');
        Exit;
      end;
      ClickMouse2(true);
      WaitOption('Buy O',500);
      WaitFunc(@GEEBuyMenu,10,6000);
    end;
    Working on: Tithe Farmer

  7. #7
    Join Date
    Jul 2011
    Location
    /home/litoris
    Posts
    2,226
    Mentioned
    0 Post(s)
    Quoted
    159 Post(s)

    Default

    ^I think my version is better when it comes to editing, but yours looks nicer if it's going to be in the include.
    Miner & Urn Crafter & 07 Chicken Killer
    SPS BlindWalk Tutorial

    Working on: Nothing

    teacher in every art, brought the fire that hath proved to mortals a means to mighty ends

  8. #8
    Join Date
    Oct 2006
    Location
    Netherlands
    Posts
    3,285
    Mentioned
    105 Post(s)
    Quoted
    494 Post(s)

    Default

    Simba Code:
    procedure BuyGE(spot : String);
    var
      x, y: Integer;
      searchBox: TBox;
    begin
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        'any':
          searchBox := IntToBox(MMX1, MMY1, MMX2, MMY2);
        '1':
          searchBox := IntToBox(35, 85, 173, 190);
        //go on like this...
      end;
      if (FindObject(x,y,BuyButton, searchBox.x1, searchBox.y1, searchBox.x2, searchBox.y2)) then //pointless to do an empty begin-end staetement
      begin  
        ClickMouse2(true);
        WaitOption('Buy O', 500);
        WaitFunc(@GEEBuyMenu, 10, 6000);
      end else
        Writeln('This slot is not free');
    end;

    This is how I would do it. I think boxes should be used when possible over 4 integers.
    Working on: Tithe Farmer

  9. #9
    Join Date
    Jan 2008
    Location
    C:\
    Posts
    1,483
    Mentioned
    2 Post(s)
    Quoted
    2 Post(s)

    Default

    Building on Bart's version:

    Simba Code:
    function BuyGE(spot: String): Boolean;
    var
      s, x, y: Integer;
      searchBox: TBox;
    begin
      Result := False;
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      if (spot = 'any') then
        searchBox := IntToBox(MMX1, MMY1, MMX2, MMY2)
      else
      begin
        s := StrToInt(spot);
        if not InRange(s, 1, 6) then
        begin
          Writeln('Invalid slot value!');
          Exit;
        end;
        searchBox := IntToBox(35 + ((s - 1) mod 3 * 155), 85 + (Floor(s / 4.0) * 115), 170 + ((s - 1) mod 3 * 155), 190 + (Floor(s / 4.0) * 115));
      end;
      if not (FindObject(x, y, BuyButton, searchBox.x1, searchBox.y1, searchBox.x2, searchBox.y2)) then
      begin
        if (spot = 'any') then
          Writeln('No slots are free!')
        else
          Writeln('Slot '+ spot +' is not free!');
        Exit;
      end;
      ClickMouse2(true);
      if WaitOption('Buy O', 500) then
        Result := WaitFunc(@GEEBuyMenu, 10, 6000);
    end;

    Perfect scenario for some mods & floors
    Last edited by Runaway; 09-07-2012 at 04:46 PM.

  10. #10
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default

    Thank you for this other example, masterBB. Makes me realize there are so many ways to code the same thing.

    What is your (everyone) opinion on records? In this particular case, I think it would be superfluous, but I'm wondering if it's actively used by people. I only know one script (from NKN) that uses it in his custom find object function.

    EDIT: Thank you Runaway for this. I was actually scratching my head wondering how to do -exactly- this yesterday (assuming I'm understanding what you wrote). I don't fully understand "mod" and "floor". Got to look it up... okay the search was a bit of a waste as I didn't find anything regarding mod and floor, but it led me to opening the math include which has a great function that would let me do exactly that (I think) (GridBox). I'll try to come up with my own version to see if it works.
    Last edited by Wardancer; 09-07-2012 at 05:11 PM.

  11. #11
    Join Date
    Oct 2006
    Location
    Netherlands
    Posts
    3,285
    Mentioned
    105 Post(s)
    Quoted
    494 Post(s)

    Default

    I kind off accidentally swapped MM with MS, but there are indeed a lot of options to solve the same problem. Runaway his version is the best, but personally I try to keep the amount of formulas a bit low. It will make your code harder to read.

    Records are cool. There are no pros and cons in the way they work opposed to multiple variables.
    Working on: Tithe Farmer

  12. #12
    Join Date
    Jan 2008
    Location
    C:\
    Posts
    1,483
    Mentioned
    2 Post(s)
    Quoted
    2 Post(s)

    Default

    Quote Originally Posted by Wardancer View Post
    EDIT: Thank you Runaway for this. I was actually scratching my head wondering how to do -exactly- this yesterday (assuming I'm understanding what you wrote). I don't fully understand "mod" and "floor". Got to look it up... okay the search was a bit of a waste as I didn't find anything regarding mod and floor, but it led me to opening the math include which has a great function that would let me do exactly that (I think) (GridBox). I'll try to come up with my own version to see if it works.
    I'll give you a small overview of both of them

    Mod is a special divisor operator that returns the remainder rather than the answer. Example:

    Code:
    0 mod 2 = 0
    1 mod 2 = 1
    2 mod 2 = 0
    3 mod 2 = 1
    etc...
    It's very useful for a continuous pattern. If i is any real number, then:

    Simba Code:
    if (i mod 2 = 0) then
      Writeln('i is an even number.');

    You can effectively check whether i is even or odd. In the BuyGE code I posted above, I used i mod 3 to determine what the x1 value would be since the difference pattern was:

    Code:
    x1: 35, 190, 345, 35, 190, 345
    or
    x1: 35 + (155*0), 35 + (155*1), 35 + (155*2), etc.
    Since the pattern i mod 3 creates follows the same routine (0, 1, 2, 0, 1, 2):

    Code:
    0 mod 3 = 0
    1 mod 3 = 1
    2 mod 3 = 2
    3 mod 3 = 0
    4 mod 3 = 1
    etc...
    I knew that the following equation could be used to determine the value of x1 relative to the value of i:

    Simba Code:
    for i := 1 to 6 do
    begin
      x1 := 35 + ((i - 1) mod 3 * 155);
      Writeln(x1);
    end;

    Hopefully that will cover the basic usage of mod! As for floor, I use it as a version of mod with a 'greater interval'. Since the difference pattern of y1 was:

    Code:
    y1: 85, 85, 85, 200, 200, 200
    or
    x1: 85 + (115*0), 85 + (115*0), 85 + (115*0), 85 + (115*1), 85 + (115*1), 85 + (115*1)
    A simple mod approach would not work. Floor rounds down the value to the nearest whole number, so it can be used to measure patterns that stick to the same number for more than 1 repetition. Since:

    Code:
    Floor(1 / 4.0) = 0
    Floor(2 / 4.0) = 0
    Floor(3 / 4.0) = 0
    Floor(4 / 4.0) = 1
    Floor(5 / 4.0) = 1
    etc...
    I used that method to produce the pattern we observed for y1 above, making the equation to determine the value of y1 relative to the value of i:

    Simba Code:
    for i := 1 to 6 do
    begin
      y1 := 85 + (Floor(i / 4.0) * 115);
      Writeln(y1);
    end;

    So, it all relates back to observing a pattern and finding an equation to replicate the pattern based upon differences. The best way to learn more complex uses of this would be to jump right into it and try to solve complex patterns with these (and other) functions

    Here's the code I used to quickly determine the equations for the code you posted:

    Simba Code:
    program new;
    {$I SRL/SRL.simba}
    var
      Box: TBox;
      i: Integer;
      x1, y1, x2, y2: Integer;
    begin
      // x1: 35, 190, 345, 35, 190, 345 (155)
      // y1: 85, 85, 85, 200, 200, 200 (115)
      // x2: 170, 325, 480, 170, 325, 480 (155)
      // y2: 190, 190, 190, 305, 305, 305 (115)
      for i := 1 to 6 do
      begin
        x1 := 35 + ((i - 1) mod 3 * 155);
        y1 := 85 + (Floor(i / 4.0) * 115);
        x2 := 170 + ((i - 1) mod 3 * 155);
        y2 := 190 + (Floor(i / 4.0) * 115);
        Box := IntToBox(x1, y1, x2, y2);
        Writeln(Box);
      end;
    end.

    Once you pinpoint a pattern, it's actually quite simple to work out the code to replicate it!

  13. #13
    Join Date
    Jul 2011
    Location
    /home/litoris
    Posts
    2,226
    Mentioned
    0 Post(s)
    Quoted
    159 Post(s)

    Default

    Quote Originally Posted by Runaway View Post
    I'll give you a small overview of both of them

    Mod is a special divisor operator that returns the remainder rather than the answer. Example:

    Code:
    0 mod 2 = 0
    1 mod 2 = 1
    2 mod 2 = 0
    3 mod 2 = 1
    etc...
    It's very useful for a continuous pattern. If i is any real number, then:

    Simba Code:
    if (i mod 2 = 0) then
      Writeln('i is an even number.');

    You can effectively check whether i is even or odd. In the BuyGE code I posted above, I used i mod 3 to determine what the x1 value would be since the difference pattern was:

    Code:
    x1: 35, 190, 345, 35, 190, 345
    or
    x1: 35 + (155*0), 35 + (155*1), 35 + (155*2), etc.
    Since the pattern i mod 3 creates follows the same routine (0, 1, 2, 0, 1, 2):

    Code:
    0 mod 3 = 0
    1 mod 3 = 1
    2 mod 3 = 2
    3 mod 3 = 0
    4 mod 3 = 1
    etc...
    -snip-
    Once you pinpoint a pattern, it's actually quite simple to work out the code to replicate it!
    This was a great read, thanks!
    Miner & Urn Crafter & 07 Chicken Killer
    SPS BlindWalk Tutorial

    Working on: Nothing

    teacher in every art, brought the fire that hath proved to mortals a means to mighty ends

  14. #14
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default

    Thank you for the explanation. Here is the code I came up with by myself using GridBox. I'm having an issue with standards though...

    Simba Code:
    function BuyGE(spot : integer): Boolean;
    var
      x, y : Integer;
      a : TBox;
    begin
        if not InGEE then
          Exit;
        if GEESellMenu or GEEBuyMenu then
          GEEMenuExit;
        case spot of
          0:
            if not (FindObject(x,y,BuyButton,MSX1,MSY1,MSX2,MSY2)) then
            begin
              writeln('No spot is free')
              Exit;
            end;
          1..6:
            begin;
            a:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
            if not FindObject(x,y,BuyButton,a.x1,a.y1,a.x2,a.y2) then
            begin
              writeln('This spot is not free')
              Exit;
            end;
            begin;
              ClickMouse2(true);
              WaitOption('Buy O',500);
              WaitFunc(@GEEBuyMenu,10,6000);
            end;
          end;
       end;
    end;

    First, I have to say that I -know- that all those begin and end look atrocious but that was the only way I could get the script to work. Removing a single begin or end (even trying to just place it somewhere else) ends up giving me an error message. As you can read in the code, the part of the clicking only works for 1 to 6 which isn't what I want. Trying to place one of the four ends at the end before the begin of the clicking also doesn't work. I also can't take off the begin before the GridBox function. Basically, I'd like to understand what goes wrong there.

    Thank you for your time.
    Last edited by Wardancer; 09-07-2012 at 09:38 PM.

  15. #15
    Join Date
    Jan 2008
    Location
    C:\
    Posts
    1,483
    Mentioned
    2 Post(s)
    Quoted
    2 Post(s)

    Default

    Try this out:

    Simba Code:
    function BuyGE(spot : integer): Boolean;
    var
      x, y : Integer;
      b : TBox;
    begin
      Result := False; // need a result for a function
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        0:
        begin
          if not (FindObject(x,y,BuyButton,MSX1,MSY1,MSX2,MSY2)) then
          begin
            writeln('No spot is free')
            Exit;
          end;
        end;
        1..6:
        begin
          b:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
          if not FindObject(x,y,BuyButton,b.x1,b.y1,b.x2,b.y2) then
          begin
            writeln('This spot is not free')
            Exit;
          end;
        end;
        else // if spot is none of the above
        begin
          writeln('Invalid spot entered');
          Exit;
        end;
      end;
      ClickMouse2(true);
      if WaitOption('Buy O',500) then // no point checking for the menu if you didn't choose an option
        Result := WaitFunc(@GEEBuyMenu,10,6000);
    end;

  16. #16
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default

    Thank you Runaway. That solved the issue.

    I finally understand the problem I had too. A case statement has to finish with an end. By adding only one end before my clicking action, it was like I tried to use my "begin" as a case statement.

    At first, you mention that the function needs a result. I thought that it automatically gave the result "true" if it could do what it did. Now, I'm starting to think I coded some procedures as functions. Yeah, that part was really a procedure... yet it still does what I intend it to. The temptation to code absolutely everything in functions is very high now. I have to go back to the theory and get to really understand the limitations of both.

    I appreciate the "end else" you added too. I was searching to find what "infinity" would be. Didn't want to paste my code with a case being 7..99999999999999999999999999999, haha.
    Last edited by Wardancer; 09-07-2012 at 10:06 PM.

  17. #17
    Join Date
    Jul 2011
    Location
    /home/litoris
    Posts
    2,226
    Mentioned
    0 Post(s)
    Quoted
    159 Post(s)

    Default

    You should make sure you always Do Result := True/false before the function exits. A good way is to set it to false at the very beginning, and set to true when something is finished.
    Miner & Urn Crafter & 07 Chicken Killer
    SPS BlindWalk Tutorial

    Working on: Nothing

    teacher in every art, brought the fire that hath proved to mortals a means to mighty ends

  18. #18
    Join Date
    Oct 2006
    Location
    Netherlands
    Posts
    3,285
    Mentioned
    105 Post(s)
    Quoted
    494 Post(s)

    Default

    Yeah, functions are cool. They make it much easier to create a reliable script. Remember they can return more then just a Boolean type. With the exception of procedures like init and proggy, most procedures could be rewritten to a function. Using a 'Boolean' function is advised if it can 'fail'.

    Simba Code:
    function BuyGE(spot : integer): Boolean;
    var
      x, y : Integer;
      b : TBox;
    begin
      Result := False; // need a result for a function
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        0:
          if not (FindObject(x,y,BuyButton,MSX1,MSY1,MSX2,MSY2)) then
          begin
            writeln('No spot is free')
            Exit;
          end;
        1..6:
          begin
            b:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
            if not FindObject(x,y,BuyButton,b.x1,b.y1,b.x2,b.y2) then
            begin
              writeln('This spot is not free')
              Exit;
            end;
          end;
        else // if spot is none of the above
        begin
          writeln('Invalid spot entered');
          Exit;
        end;
      end;
      ClickMouse2(true);
      if WaitOption('Buy O',500) then // no point checking for the menu if you didn't choose an option
        Result := WaitFunc(@GEEBuyMenu,10,6000);
    end;

    I personally liked his case statements standards a bit more. Makes the default, else, look more inline with the other cases. Also removed a begin and end at the first case. Also awesome comment explaining mod and floor.

    e:
    Simba Code:
    function BuyGE(spot: integer): Boolean;
    var
      x, y, i: Integer;
      b: TBox;
    begin
      Result := False; // need a result for a function
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        0:
          begin
            for i := 1 to 6 do
            begin
              b:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
              if FindObject(x,y,BuyButton,b.x1,b.y1,b.x2,b.y2) then
              begin
                Writeln('Found in spot: ' + IntToStr(i));
                break;
              end;
            end;
            Writeln('No free slot found');
            Exit;
          end;
        1..6:
          begin
            b:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
            if not FindObject(x,y,BuyButton,b.x1,b.y1,b.x2,b.y2) then
            begin
              writeln('This spot is not free')
              Exit;
            end;
          end;
        else // if spot is none of the above
        begin
          writeln('Invalid spot entered');
          Exit;
        end;
      end;
      ClickMouse2(true);
      if WaitOption('Buy O',500) then // no point checking for the menu if you didn't choose an option
        Result := WaitFunc(@GEEBuyMenu,10,6000);
    end;
    Last edited by masterBB; 09-07-2012 at 10:22 PM.
    Working on: Tithe Farmer

  19. #19
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default

    Well, that was definitely a procedure so I'm not sure I understand the practical aspect of what you're trying to say. For my "real" functions, it is quite obvious that I'm making them to receive a value. Do you mean a function that does something AND tells me if it did it? Some kind of half breed between a procedure and a function. I understand the theory behind it, but I didn't get to a point where that's actually needed or useful.

    EDIT: I really can't see the practical aspect of turning procedures into functions. Do you use it as an extra layer of failsafe? My first reflex would be to reach the same result using a different path (i.e exit, if..then..etc), but I can see how a different scripting style can go around the problem differently.
    Last edited by Wardancer; 09-07-2012 at 10:49 PM.

  20. #20
    Join Date
    Jan 2008
    Location
    C:\
    Posts
    1,483
    Mentioned
    2 Post(s)
    Quoted
    2 Post(s)

    Default

    Quote Originally Posted by Wardancer View Post
    Well, that was definitely a procedure so I'm not sure I understand the practical aspect of what you're trying to say. For my "real" functions, it is quite obvious that I'm making them to receive a value. Do you mean a function that does something AND tells me if it did it? Some kind of half breed between a procedure and a function. I understand the theory behind it, but I didn't get to a point where that's actually needed or useful.

    EDIT: I really can't see the practical aspect of turning procedures into functions. Do you use it as an extra layer of failsafe? My first reflex would be to reach the same result using a different path (i.e exit, if..then..etc), but I can see how a different scripting style can go around the problem differently.
    Yes. It can be used as a failsafe to improve speed, accuracy and efficiency. For example, you originally had this in your code:

    Simba Code:
    ClickMouse2(true);
      WaitOption('Buy O',500);
      WaitFunc(@GEEBuyMenu,10,6000);

    It does what it's supposed to. But if the script cannot find the specified option, it will waste time and resources searching for the buy menu when there's a 100% chance it's not there! Utilizing the functional properties of WaitOption not only allows you to skip the unnecessary menu check, but you can execute code designed specifically to act when WaitOption fails. Like so:

    Simba Code:
    ClickMouse2(true);
      if WaitOption('Buy O',500) then
        WaitFunc(@GEEBuyMenu,10,6000)
      else
      begin
        Writeln('Could not locate option');
        //DoFailsafe;
      end;

    Although, not everything benefits from a result.

  21. #21
    Join Date
    Jul 2012
    Posts
    279
    Mentioned
    5 Post(s)
    Quoted
    46 Post(s)

    Default

    What I meant is that instead of using a function, we can use a if..then and end up with the same result (in the case that we're dealing with a procedure). It might come to preference too. I have a procedure for opening the grand exchange and another to make sure that it really is open. I could've made the procedure as a function and put both together I guess. I might end up hated with my one line functions, haha.

    EDIT: I might as well share all I have so far. Some people might want to play a bit with the functions and procedures I came up with and I have 2-3 questions. I won't be able to stress it enough, but the general frame of the script (like Declareplayers, Antiban and such) was made by NKN and should be entirely credited to him. I also removed the LoadObjects function as it isn't mine and while I have permission to use it, I didn't ask if I could publicly release it. I put a few notes in the script which I'll explain after.

    Simba Code:
    program new;
    {$DEFINE SMART}
    {$i srl/srl.simba}
    {$i srl/srl/misc/SmartGraphics.simba}

    procedure DeclarePlayers;
    begin
      HowManyPlayers := 1; // This is set to the total amount of players (more on multiplayer later ;)), for now, just keep it set as 1
      NumberOfPlayers(HowManyPlayers); // This is a procedure in SRL which sets up player arrays (also, more on that later), this will always be the same
      CurrentPlayer := 0; // This is the player to start with; the first player will always be 0 (you'll find out when you learn all about arrays)

      Players[0].Name := 'Uqam'; // Username
      Players[0].Pass := ''; // Password
      Players[0].Nick := ''; // 3-4 lowercase letters from username; used for random event detection
      Players[0].Active := True; // Set to true if you want to use Player 0
      Players[0].Pin := ''; // Leave blank if the player doesn't have a bank pin
      Players[0].BoxRewards := ['Xp', 'mote', 'ostume', 'oins', 'aphire', 'ssence'];
    end;
       procedure Antiban;
    begin
      FindNormalRandoms;
      case Random(80) of
        0: RandomRClick;
        2: PickUpMouse;
        3: RandomMovement;
        4: BoredHuman;
        5: ExamineInv;
        7: SetAngle(SRL_ANGLE_HIGH);
        8: Wait(5000)
      end;
    end;
    type                                       //Credit goes to NKN for the custom object finding functions. I only put the values in there. The frame is all his.
      MSObject = record
        Col, Tol, TPADist, MinCount: Integer;
        Hue, Sat: Extended;
        Uptext: String;
        MMDot: String;
      end;
    var
      GE, BuyButton, SellButton, ExitGEMenuButton : MSObject;
    procedure LoadObjects;
    var
      i:integer;
    begin
      with GE do
       begin
        Col := 2891040;
        Tol := 20;
        Hue := 0.18;
        Sat := 0.30;
        UpText := 'Exch'
       end;
      with BuyButton do
       begin
        Col := 247218;
        Tol := 4;
        Hue := 0.25;
        Sat := 1.29;
        UpText := 'Buy O'
       end;
      with SellButton do
       begin
        Col := 224454;
        Tol := 4;
        Hue := 0.34;
        Sat := 0.03;
        UpText := 'Sell O'
       end;
      with ExitGEMenuButton do
       begin
        Col := 11975110;
        Tol := 10;
        Hue := 0.80;
        Sat := 0.31;
        UpText := 'ack'
       end;
      for i := 1 to 28 do
        Boxes[i] := InvBox(i)
    end;
    function FindObject(var x,y : Integer; Obj: MSObject; X1,Y1,X2,Y2:integer) : Boolean;
    //Censored =)
    function InGEE: Boolean;
    begin;
      result := findTextTPA(39116, 20, 204, 27, 248, 49, 'Grand', upCharsEx, nothing);
    end;
    function GEESellMenu: Boolean;
    begin;
      result := findTextTPA(39116, 20, 87, 68, 155, 86, 'Sell O', upCharsEx, nothing);
    end;
    function GEEBuyMenu: Boolean;
    begin;
      result := findTextTPA(39116, 20, 87, 68, 155, 86, 'Buy O', upCharsEx, nothing);
    end;
    function GEECanTypeAmount: Boolean;
    begin;
      result := findTextTPA(0, 150, 125, 387, 166, 412, 'nter', upCharsEx, nothing);
    end;
    function GEECanTypePrice: Boolean;
    begin;
      result := findTextTPA(0, 150, 140, 392, 182, 411, 'nter', upCharsEx, nothing);
    end;
    function GEECanTypeItem: Boolean;
    begin;
      result := findTextTPA(23200, 50, 196, 355, 228, 373, 'rand', upCharsEx, nothing);
    end;
    function OpenGE: Boolean;
    var
      x,y:integer;
    begin
      if InGEE or GEESellMenu or GEEBuyMenu then
        Exit;
      if(FindObject(x,y,GE,MSX1,MSY1,MSX2,MSY2)) then
      begin
        Clickmouse2(false);
        WaitOption('Exchange G',500);
        WaitFunc(@InGEE,10,6000);
      end else
        Exit;
    end;
    function GEEMenuExit: Boolean;
    var
      x, y : Integer;
    begin
      if not InGEE then
        Exit;
      if not GEESellMenu and not GEEBuyMenu then
        Exit;
      if(FindObject(x,y,ExitGEMenuButton,MSX1,MSY1,MSX2,MSY2)) then
      begin
        ClickMouse2(true);
        WaitOption('ack',500);
        WaitFunc(@InGEE,10,6000);
      end else
        Exit;
    end;
    function GEEBuyAt(spot: integer): Boolean;
    var
      x, y, i: Integer;
      b: TBox;
    begin
      Result := False;
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        Exit;
      case spot of
        0:
          if not (FindObject(x,y,BuyButton,MSX1,MSY1,MSX2,MSY2)) then
          begin
            writeln('No spot is free')
            Exit;
          end;
        1..6:
          begin
            b:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
            if not FindObject(x,y,BuyButton,b.x1,b.y1,b.x2,b.y2) then
            begin
              writeln('This spot is not free')
              Exit;
            end;
          end;
        else
        begin
          writeln('Invalid spot entered');
          Exit;
        end;
      end;
      ClickMouse2(true);
      WaitOption('Buy O',500);
      Wait(500+Random(250));
      WaitFunc(@GEEBuyMenu,10,6000);
    end;
    function GEESellAt(spot: integer): Boolean;
    var
      x, y, i: Integer;
      b: TBox;
    begin
      Result := False;
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      case spot of
        0:
          if not (FindObject(x,y,SellButton,MSX1,MSY1,MSX2,MSY2)) then
          begin
            writeln('No spot is free')
            Exit;
          end;
        1..6:
          begin
            b:= GridBox(spot, 3, 2, 155, 120, 155, 120, point(100,136));
            if not FindObject(x,y,SellButton,b.x1,b.y1,b.x2,b.y2) then
            begin
              writeln('This spot is not free')
              Exit;
            end;
          end;
        else
        begin
          writeln('Invalid spot entered');
          Exit;
        end;
      end;
      ClickMouse2(true);
      if WaitOption('Sell O',500) then
      WaitFunc(@GEEBuyMenu,10,6000);
      Wait(1250+Random(250));
    end;
    procedure GEESetQuantity(Q : String);
    var
      x, y, numberOfFailures : integer;
      searchBox: TBox;
    begin
      for numberofFailures := 0 to 5 do
      if not InGEE then
        Exit;
      if not GEESellMenu and not GEEBuyMenu then
        Exit;
      case lowercase(Q) of
        '1':
          searchBox := IntToBox(56, 211, 87, 231);
        '10':
          searchBox := IntToBox(97, 211, 129, 231);
        '100':
          searchBox := IntToBox(138, 211, 170, 231);
        'all':
          if not GEESellMenu then
            begin
              writeln('Invalid parameter');
              Exit;
            end else
          searchBox := IntToBox(220, 211, 253, 231);
        else
          begin
            if (FindColorTolerance(x, y, 39116, 222, 211, 252, 231, 100)) then
              begin
                MMouse(x, y, 4, 4);
                ClickMouse2(true);
                WaitFunc(@GEECanTypeAmount, 10, 16000);
                TypeSendEx(Q, true);
                Wait(1500 + Random(250));
              end;
          end;
        end;
      case lowercase(Q) of
        '1', '10', '100', 'all':
          if (FindColorTolerance(x, y, 39116, searchBox.x1, searchBox.y1, searchBox.x2, searchBox.y2, 100)) then
          begin
            MMouse(x, y, 4, 4);
            ClickMouse2(true);
            Wait(1000 + Random(500));
          end;
       end;
      if (ExtractFromStr(GetTextAtExWrap(86, 184, 227, 198, 0, 10, 1, 6400255, 50, UpCharsEx), Numbers)) = Q then
        Exit;
        begin
          writeln('Something went wrong!')
          Inc(numberOfFailures);
          if numberofFailures = 5 then
            begin
              writeln('Failed too many times. Terminating script.');
              TerminateScript;
            end;
        end;
    end;
    procedure GEESetPrice(Value : String; numberOfClicks : Integer);
    var
      x, y, numberOfFailures, numberOfClickz : integer;
      searchBox: TBox;
    begin
      for numberOfFailures := 0 to 5 do
      if not InGEE then
        Exit;
      if not GEESellMenu and not GEEBuyMenu then
        Exit;
      case lowercase(Value) of
        'min':
          searchBox := IntToBox(274, 211, 304, 231);
        'mid':
          Exit;
        'max':
          searchBox := IntToBox(427, 211, 460, 231);
        else
          begin
            if (FindColorTolerance(x, y, 39167, 371, 211, 403, 231, 100)) then
              begin
                MMouse(x, y, 4, 4);
                ClickMouse2(true);
                WaitFunc(@GEECanTypePrice, 10, 6000);
                TypeSendEx(Value, true);
                Wait(1500 + Random(250));
                if (ExtractFromStr(GetTextAtExWrap(296, 184, 438, 198, 0, 10, 1, 6400255, 50, UpCharsEx), Numbers)) = Value then
                  Exit;
                begin
                  writeln('Something went wrong!')
                  Inc(numberOfFailures);
                  if numberOfFailures = 5 then
                    begin
                      writeln('Failed too many times. Terminating script.');
                      TerminateScript;
                    end;
                end;
              end;
          end;
      end;
      case lowercase(Value) of
        'min', 'max':
          if (FindColorTolerance(x, y, 39167, searchBox.x1, searchBox.y1, searchBox.x2, searchBox.y2, 100)) then
          begin
            repeat
              MMouse(x, y, 4, 4);
              ClickMouse2(true);
              Inc(numberOfClickz);
              Wait(200 + Random(50));
            until (numberOfClickz = numberOfClicks);
            Wait(500 + Random(200));
          end;
       end;
    end;
    procedure GEEConfirmOffer;
    begin
      MouseBoxEx(215, 286, 310, 325, 10, 1);
      Wait(1500 + Random(500));
    end;
    procedure GEEBuy(What, Quantity, Value: String; numberOfClicks, spot : Integer);
    var
      x, y : Integer;
    begin
      if not InGEE then
        Exit;
      if GEESellMenu or GEEBuyMenu then
        GEEMenuExit;
      GEEBuyAt(spot);
      WaitFunc(@GEECanTypeItem, 10, 6000);
      TypeSendEx(What, true);
      WaitFindColor(x, y, 23200, 67, 343, 119, 359, 30, 6000);
      MouseBoxEx(200, 350, 228, 368, 5, 1);
      WaitColorGone(39372, 394, 81, 40, 6000);
      //if not findTextTPA(39372, 20, 210, 75, 380, 95, What, StatChars, nothing) = true then   //Look at the note below
        //Writeln('A problem occurred. Trying again.');
        //GEEBuy(What, Quantity, Value, numberOfClicks, spot);
      GEESetQuantity(Quantity);
      GEESetPrice(value, numberOfClicks);
      GEEConfirmOffer;
    end;




    procedure BuyRanarr;
    var
      Price, x, y : Integer;
    begin
      OpenGE;
      //GEEBuyAt(6);
      //GEESetQuantity('12354');
      //GEESetPrice('852', 4)
      //GEEMenuExit;
      GEEBuy('lean ranarr', '2', 'max', 1, 0);

      writeln('See if any malicious loop is going on');
    end;



    procedure Mainloop;
    begin
      //OpenGE;
      BuyRanarr;



    end;

    begin
      {$IFDEF SMART}
        SRL_SIXHOURFIX := TRUE;
        SMART_FIXSPEED := TRUE;
      {$ENDIF}

      ClearDebug;
      SetupSRL;
      DeclarePlayers; // Calls the procedure, you can't forget this!
      LoginPlayer;
      ClickNorth(SRL_ANGLE_HIGH);
      LoadObjects;
      repeat
        Mainloop;
      until(allPlayersInactive);
    end.

    Note: I'm trying to use this as a failsafe to make sure that the item the person is trying to purchase is really the one he wants. However, for some reason beyond me, the text reading doesn't work at this spot. I'll figure out the issue eventually, but I wanted to post what I have done so far for people to comment/insult/make use of.

    Once again, what I'm looking for are methods to make this look neater. Everything works and I'll add more failsafes as I figure out holes, but I'm always looking for ways to optimize things.

    If someone has any question about what a particular function does or would like details, feel free to ask.
    Last edited by Wardancer; 09-09-2012 at 07:42 PM.

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
  •