SRL Archive - Discussions and Debates

Idea for an Item Recongnizer(Inventory)


Cazax

2008-11-19 17:37:26

I have been thinking this idea some time ago, but now i want your opinion. Here is the idea: A black pixel's counter. Here is the explanation:

For example, an uncut sapphire:

You may have seen other threads about Items recognizers, but this is a special one. Why? Look:
The uncut sapphire(like every item) has black pixels covering the sapphire, but the count of those pixels is unique. Every item in Runescape has a different count of the black pixels EXCEPT similar objects. For example: Rune axe with Bronze axe, Uncut Sapphire with Uncut Ruby, etc…

The thing its that we can collect the count of those pixels in the most important F2P items, and use it in a recognizer. Example:
Function RecognizeItem(Slot : Integer): String;
Var
Box : TBox;
TPA : TPointArray;
Begin
Box := InvBox(Slot);
FindColorsTolerance(TPA, 65536, Box.X1, Box.Y1, Box.X2, Box.Y2, 0);
Case Length(TPA) Of
51: Result := 'clay';
66: Result := 'uncut gem'; //Attention to this
etc...
End;
End;
Just an example, we can make a better one.
Suggestions or comments please.

Method

2008-11-19 18:52:03

I don't think you're using the word "length" correctly here. I believe you mean "count" or something similar instead. Using the Length function gives you the length of the array of black pixels, not the length of the pixels themselves.

Anyways, as long as you can build a database of items from this and there aren't many (if any) duplicate counts, this idea might be plausible.

Boreas

2008-11-19 18:55:42

I'm working on something similar at the moment, except that the database builds itself.


program New;
{.include Srl\SRL.scar}
var
UIDB_Net: TPointArray;

procedure UIDB_LoadNet;
var tmpcount,hx,hy:integer;
begin
SetArrayLength(UIDB_Net,506);
repeat
hy:=9;
hx:=hx+1;
repeat
hy:=hy+1;
if (((hx mod 2)=0) or ((hy mod 2)=0)) then
begin
UIDB_Net[tmpcount]:=Point(hx,hy);
Inc(tmpcount);
end;
until hy=31;
until hx=31;
end;



Function InvBox2(i :Integer): TBox;
begin
if (i < 1) or (i > 28) then
begin
srl_Warn('InvBox', 'Incorrect index: ' + IntToStr(i), warn_AllVersions);
exit;
end;
{1 x1 563 y1 213 x2 594 y2 244}
{5 x1 605 y1 249}
Result.x1 :=563+((((i+3)mod 4))*(605-563));
Result.y1 :=213+((((i-1)/4))*(249-213));
Result.x2 := Result.x1+31;
Result.y2 := Result.y1+31;
end;

{*******************************************************************************
function strToIntArrayEx(intArray, Separater : String) : Array of Integer;
By: moparisthebest and modified by Ron
Description: Loads a String into an array of integer. (Example String: '567 389 3234 98342 7998767')
*******************************************************************************}

function strToIntArrayEx(intArray, Separater : String) : Array of Integer;
var
i, spacePos: Integer;
begin
repeat
SetArrayLength(Result, i + 1);
spacePos := Pos(Separater, intArray);
if (not (spacePos = 0)) then
Result[i] := StrToInt(Copy(intArray, 1, spacePos - 1))
else
begin
Result[i] := StrToInt(Copy(intArray, 1, Length(intArray)));
break;
end;
Delete(intArray, 1, spacePos);
i := i + 1;
until (False)
end;

{*******************************************************************************
function strToIntArray(intArray : String) : Array of Integer;
By: moparisthebest and modified by Ron
Description: Refer to strToIntArrayEx.
*******************************************************************************}

function strToIntArray(intArray : String) : Array of Integer;
begin
Result := strToIntArrayEx(intArray, ' ');
end;

{*******************************************************************************
function intArrayToStrEx(intArray : Array of Integer; Separater : String) : String;
By: moparisthebest and modified by Ron
Description: Loads an array of integer into a String. (Example String: '567 389 3234 98342 7998767')
*******************************************************************************}

function intArrayToStrEx(intArray : Array of Integer; Separater : String) : String;
var
i, arrayLength: Integer;
begin
arrayLength := GetArrayLength(intArray);
repeat
Result := Result + IntToStr(intArray[i]);
if (not(i = (arrayLength - 1))) then
Result := Result + Separater;
i := i + 1;
until (i = arrayLength)
end;

{*******************************************************************************
function intArrayToStr(intArray : Array of Integer) : String;
By: moparisthebest and modified by Ron
Description: Refer to intArrayToStrEx.
*******************************************************************************}

function intArrayToStr(intArray : Array of Integer) : String;
begin
Result := intArrayToStrEx(intArray, ' ');
end;







function CreateBL(Area:string; Slot:integer): TIntegerArray;
var SlotBox:TBox;
i,tmpAL:integer;
begin
case lowercase(Area) of
'inv': SlotBox:= InvBox2(Slot);
'bank': SlotBox:= BankIndexToMSBox(Slot);
end;
tmpAL:=1;
SetArrayLength(result,tmpAL+1);
for i:=0 to 505 do
begin
if getcolor(UIDB_Net[i].x+SlotBox.x1,UIDB_Net[i].y+SlotBox.y1)=65536 then
begin
result[tmpAL]:=i;
Inc(tmpAL);
SetArrayLength(result,tmpAL+1);
end;
end;
SetArrayLength(result,tmpAL);
result[0]:=tmpAL-1;
end;

function CompareBL(First,Second:TIntegerArray):boolean;
var i:integer;
begin
if First[0]<> Second[0] then exit;
for i:=1 to First[0] do
begin
if First[i] <> Second[i] then exit;
end;
result:=true;
end;


var c,t,MyBMP:integer;
MyBL:TIntegerArray;
begin
UIDB_LoadNet;

MyBmp:= LoadBitmap(AppPath+'\UIDB\BmpTest2.bmp');
SetTargetBitmap(MyBmp);
for c:=1 to 26 do
begin
MyBL:=CreateBL('inv',c);
WriteINI('Item'+inttostr(c),'Black', intArrayToStr(MyBL),AppPath+'\UIDB\UIDB.ini');
end;
FreeBitmap(mybmp);

t:=getsystemtime;
if CompareBL( strToIntArray(ReadIni('Item3','Black',AppPath+'\UIDB\UIDB.ini')),
CreateBL('inv',8)) then
writeln('yes');
writeln(inttostr(getsystemtime-t));
end.

Edit: The above use a bmp saved in the scar folder generated with this while I had the first 26 spaces in the inventory with stuff
program New;
var MyBmp,w,h:integer;
begin
GetClientDimensions(w,h);
MyBmp:=BitmapFromString(w,h,'');
CopyClientToBitmap(MyBmp, 0,0,w,h);
SaveBitmap(MyBmp,AppPath+'\UIDB\Bmp'+'Test2'+'.bmp');
end.

Cazax

2008-11-19 18:58:10

From: Method
I don't think you're using the word "length" correctly here. I believe you mean "count" or something similar instead. Using the Length function gives you the length of the array of black pixels, not the length of the pixels themselves.

Anyways, as long as you can build a database of items from this and there aren't many (if any) duplicate counts, this idea might be plausible.


Thanks for pointing that out. I know that duplicates counts may be a problem, but i have get the count of the black pixels many times, with different items(F2P btw) and i haven't encountered with any duplicate. There could be a duplicate with P2P items, because there are a lot of P2P items.

EDIT: oo nice boreas

Boreas

2008-11-19 20:57:42

Yea there's definitely duplicates with p2p. Item slots are 31x31 pixels, which means a maximum of 961 different possible amounts for the counts. The high and low ones aren't probable, so let's guess 500. There are about 5000 total items, which means duplicates are pretty much guaranteed, even without counting water/air rune etc.

Since p2p autoing is becoming more and more popular, I'm going with a net of points. Of course if the count is different, then there is no point in checking the positions:
if First[0]<> Second[0] then exit;

A G E N T

2008-11-19 21:01:28

I had an idea like this a while ago (for logs):

function CheckLogs : TIntegerArray;
var
i, n : integer;
Box : TBox;
ResArr : Array of integer;
begin
GameTab(4);
n := 0;
for i:=1 to 28 do
begin
Box := InvBox(i);
if(CountColor(65536, Box.x1, Box.y1, Box.x2, Box.y2) = 85)then
begin
SetArrayLength(ResArr, (n+1));
ResArr[n] := i;
Inc(n);
end;
end;
Result := ResArr;
end;