SRL Archive - Senior News and General

TPA or IntArray?


Boreas

2008-11-17 12:11:19

I've been working on an item identification thing, and I'm having trouble deciding on a format for it. First it was TDTM, but then the TDTMtoString and back functions were messy. Since all the branches were integers, I switched to 2D IntArray, but for the black outline, most were 0s, so I made the arrays 2 ints long (a TPA but with flexibility to grow if needed), and that is the script at the bottom (use with the picture saved as C:\Program Files\SCAR 3.15\UIDB\BmpTest2.bmp).

All the tpoints are relative to the top left corner of an item box, and they are all derived from

repeat
hy:=9;
hx:=hx+1;
repeat
hy:=hy+1;
if (((hx mod 2)=0) or ((hy mod 2)=0)) then
So I could go back to what I used a couple years ago. Use the above code to generate a TPA of all points to check for black, and save the indexes of black points to an intarray in the ini file. This would mean the black outline part of the ini would be half the size, and easier to convert to and from a string. However it would mean keeping a 506 point long TPA in memory.

So which do you think is better? List of tpoints in the ini (script below), or a list of ints in the ini that refers to a tpa in memory (more like black lists)?

Edit: please post your reasons too.



http://i38.tinypic.com/24wylw4.jpg
program New;
{.include Srl\SRL.scar}

type
ItemDTM = array of array of integer;
{first array, info on item, including number of blackpts
second through blackpts+1: one array per pt, 2 ints (x,y) in each array
after that, for colors.

}
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 UIDB_MakeDTMPoint(X,Y,Color,Tol:integer): array [0..5] of integer;
begin
result[0]:=X;
result[1]:=Y;
result[2]:=0;
result[3]:=0;
result[4]:=Color;
result[5]:=Tol;
end;
function UIDB_MakeBlackDTMPoint(X,Y:integer): array [0..1] of integer;
begin
result[0]:=X;
result[1]:=Y;
end;

function UIDB_ItemDTMToString(TheItemDTM:ItemDTM):string;
var tmpAL,i,tmptmpAL,i2:integer;
begin
tmpAL:=getarraylength(TheItemDTM);
for i:=0 to tmpAL-1 do
begin
result:=result+'@';
tmptmpAL:=getarraylength(TheItemDTM[i]);
for i2 := 0 to tmptmpAL-1 do
result:=result+inttostr(TheItemDTM[i][i2])+',';
end;
end;
function UIDB_StringToItemDTM(TheString:string):ItemDTM;
var ptp,pt2,pt1,tmpcount,tmptmpcount:integer;
begin
ptp:=0;
repeat
pt1:=posex('@',TheString,ptp+1);
ptp:=pt1;
tmptmpcount:=0;
setarraylength(result,tmpcount+1);
repeat
pt2:=posex(',',TheString,ptp+1);
pt1:=posex('@',TheString,ptp+1);
setarraylength(result[tmpcount],tmptmpcount+1);
result[tmpcount][tmptmpcount]:=strtoint(copy(TheString,ptp+1,pt2-ptp-1));
ptp:=pt2;
tmptmpcount:=tmptmpcount+1;
until ((pt2+1)=pt1) or ((pt2+1)>length(TheString));
tmpcount:=tmpcount+1;
until (pt2+1)>length(TheString);
end;






function CreateTDTM(Area:string; Slot:integer): ItemDTM;
var SlotBox:TBox;
hx,hy,BlackPts:integer;

tmpcount:integer;
begin
case lowercase(Area) of
'inv': SlotBox:= InvBox2(Slot);
'bank': SlotBox:= BankIndexToMSBox(Slot);
end;
SetArrayLength(result,1);
repeat
hy:=9;
hx:=hx+1;
repeat
hy:=hy+1;
if (((hx mod 2)=0) or ((hy mod 2)=0)) then
begin
if getcolor(hx+SlotBox.x1,hy+SlotBox.y1)=65536 then
begin
BlackPts:=BlackPts+1;
SetArrayLength(result,BlackPts+1);
result[BlackPts]:=UIDB_MakeBlackDTMPoint(hx,hy);
end;
end;
until hy=31;
until hx=31;
result[0]:=UIDB_MakeDTMPoint(BlackPts-1,0,0,0);
end;

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


var x,c,t,y,MyBMP:integer;
MyTDTM:ItemDTM;
begin
//repeat

MyBmp:= LoadBitmap(AppPath+'\UIDB\BmpTest2.bmp');
SetTargetBitmap(MyBmp);
for c:=1 to 26 do
begin
MyTDTM:=CreateTDTM('inv',c);

WriteINI('Item'+inttostr(c),'Black', UIDB_ItemDTMToString(MyTDTM),AppPath+'\UIDB\UIDB.ini');

end;
t:=getsystemtime;
if CompareTDTM(UIDB_StringToItemDTM(ReadIni('Item3','Black',AppPath+'\UIDB\UIDB.ini')),
CreateTDTM('inv',8)) then
writeln('yes');
writeln(inttostr(getsystemtime-t));
//until isfkeydown(12);
FreeBitmap(mybmp);
end.

HyperSecret

2008-11-17 12:46:03

So your making a dtm of everything in your inventory then comparing a certain dtm to see if that dtm is present in a certain inventory spot?

Boreas

2008-11-17 13:02:48

Yes, the main loop in that script is just an example to prove it works, showing that 3 and 8 (mind rune and chaos rune) have the same outline.

In actual use, it will be used to create a profile of an item, and compare it to a database of profiles (the ini file). I'm going to generate this database by writing a bank organizer, which will drag items (perfect time to grab uptext) from the first tab, to the tab for their category (which is found from runehqs item database, or from a custom config). And since it's an ini file, new items can be added easily when the scripts comes across them.


Edit: seeing as LoadSRLBitmaps already does more than a 506 pt tpa, memory isn't really an con, and just the pro of smaller ini is left. So I'm leaning towards option 2…

Edit 2: I leaned :p

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

{first array, info on item, including number of blackpts
second through blackpts+1: one array per pt, 2 ints (x,y) in each array
after that, for colors.

}

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.

Script in first post:
[Item1]
Black=@,27,0,0,0,0,255@,1,16,0,0,65536,0@,1,18,0,0,65536,0@,2,20,0,0,65536,0@,2,21,0,0,65536,0@,3,22,0,0,65536,0@,4,24,0,0,65536,0@,4,25,0,0,65536,0@,5,26,0,0,65536,0@,6,27,0,0,65536,0@,8,28,0,0,65536,0@,9,28,0,0,65536,0@,10,29,0,0,65536,0@,12,29,0,0,65536,0@,14,29,0,0,65536,0@,16,29,0,0,65536,0@,18,29,0,0,65536,0@,20,29,0,0,65536,0@,21,28,0,0,65536,0@,22,28,0,0,65536,0@,24,26,0,0,65536,0@,25,26,0,0,65536,0@,26,24,0,0,65536,0@,26,25,0,0,65536,0@,27,22,0,0,65536,0@,28,20,0,0,65536,0@,28,21,0,0,65536,0@,29,16,0,0,65536,0@,29,18,0,0,65536,0

Script in this post:
[Item1]
Black=35 1 2 3 4 11 21 22 39 58 59 74 94 128 141 162 195 228 261 294 327 339 359 390 404 421 422 429 435 441 450 451 463 464 465 466


And it's just as fast, so I'm going with option 2 unless you guys have any reasons for 1…