Thread

a few 3.1 tips (Sdk)

a few 3.1 tips // Sdk

1  |  

xelag

Feb 11, 2001, 9:51am
Here go a few things I learned using the new 3.1 sdk, I hope this helps
someone.

How the CellIterator works.

The cell iterator is a 32 bit integer (4 bytes), which consists of two
parts. The most significant 16 bits (or hi word) is the x coordinate of the
cell (West is positive, South is negative), in decametres, the low word is
the z coordinate (North is positive, South negative). These are signed 16
bit integers (2 bytes) which in Delphi Pascal is called a Smallint.

When you put it to 0, and call aw_cell_next, a whole process is triggered.
(I assume the callback AW_CELL_RESULT has been installed).

In Pascal:
aw_instance_set(Instance);
aw_int_set(AW_CELL_ITERATOR, CellIterator);
aw_cell_next;
where Instance is the instance number of the bot and CellIterator is what I
mentioned above (normally, you start with a 0 value).

What happens next? These events:

AW_CELL_BEGIN, where you can collect the same information as when you query
a zone,
AW_CELL_OBJECT, (none ore more, depending on how many objects are in the
cell). Here you collect your objects,
AW_CELL_END.

All this is followed by the callback AW_CELL_RESULT. This callback returns
a new CellIterator when you call aw_int(AW_CELL_ITERATOR). Depending on the
value of rc:
rc = 0 : the CellIterator collected here will give you a new cell coordinate
which you can use to get the next cell contents, by repeating the previous
calls: you can omit the call to
aw_int_set(AW_CELL_ITERATOR, CellIterator) in this case;
rc <> 0 : the new CellIterator has no practical value (remains unaltered in
my experience).

By starting off the CellIterator at 0 (equivalent to 0n 0w), you can get
the contents or all the valid cells in the world, and must stop when in the
callback AW_CELL_RESULT the value of rc becomes <> 0.

But there is more to all this: the CellIterator can be set to a specific
cell coordinate, to retrieve the contents of that cell. By setting the upper
word of the CellIterator to the x value of the cell, and the lower word to
the z value, you can issue your aw_cell_next for just that cell. This means
that there is a new way to query... And the beautiful part of this is that
it does not interfere with a live update or a query, if you follow certain
rules.

Both a zone query and a cell iteration use the same event handlers:
AW_CELL_BEGIN, AW_CELL_OBJECT and AW_CELL_END. If a query has finished and
live update has started, you can use the iteration method safely. You must,
of course, handle the situation differently in these three event handlers,
so you may want to set a flag or something before you call aw_query and
aw_cell_next so as to distinguish these cases in the event handlers.

In an ongoing query (before the AW_QUERY_COMPLETE returns true) you can also
issue the iteration order: just make sure you do that after receiving the
callback AW_CALLBACK_QUERY: instead of issing a new aw_query, you issue your
aw_cell_next, wait for the callback AW_CELL_RESULT, and then resume your
query with aw_query.

Supposing you use the iteration method to search for lost property... in a
huge world like AlphaWorld.... this will take days. You may need to
disconnect and reconnect, or you may get disconnected from the world etc...
no panic. Keep the last value of the CellIterator, and resume the iteration
using this value instead of starting from zero.

For Pascal freaks, below are some usefull chunks of code. The zSplit series
splits the 32 bits into two chunks, the zUnite series joins two signed
values into a 32 bit thingmebob :) Note: this code will not work with
Delphi3, because of the use of overload and because Delphi 3 has a 31 bit
Cardinal (or was it Delphi 2?).

Have fun, XelaG.

in the interface declare:

procedure zSplit(a: Integer; var H, L: Integer); overload;
procedure zSplit(a: Cardinal; var H, L: Integer); overload;
procedure zSplit(a: Integer; var H, L: Cardinal); overload;
procedure zSplit(a: Cardinal; var H, L: Cardinal); overload;
procedure zSplit(a: Cardinal; var H, L: Word); overload;
function zUnite(H, L: Integer): Cardinal; overload;
function zUnite(H, L: word): Cardinal; overload;
function CardToInt(a: Cardinal): Integer;
function IntToCard(a: Integer): Cardinal;


in the implementation declare:

procedure zSplit(a: Integer; var H, L: Integer);
type
PCar = ^Cardinal;
PWor = ^Word;
var
p: Pointer;
pc: PCar;
pw: PWor;
c: Cardinal;
HW, LW: Word;
SH, SL: Smallint;
begin
p := at a;
pc := PCar(p);
c := pc^;
zSplit(c, HW, LW); // calls the Word version
p := at HW;
pw := PWor(p);
SH := pw^;
H := SH;
p := at LW;
pw := PWor(p);
SL := pw^;
L := SL;
end;

procedure zSplit(a: Cardinal; var H, L: Integer);
type
PWor = ^Word;
var
p: Pointer;
pw: PWor;
HW, LW: Word;
SH, SL: Smallint;
begin
zSplit(a, HW, LW); // calls the Word version
p := at HW;
pw := PWor(p);
SH := pw^;
H := SH;
p := at LW;
pw := PWor(p);
SL := pw^;
L := SL;
end;

procedure zSplit(a: Integer; var H, L: Cardinal);
type
PCar = ^Cardinal;
PWor = ^Word;
var
p: Pointer;
pc: PCar;
c: Cardinal;
HW, LW: Word;
begin
p := at a;
pc := PCar(p);
c := pc^;
zSplit(c, HW, LW); // calls the Word version
H := HW;
L := LW;
end;

procedure zSplit(a: Cardinal; var H, L: Cardinal);
var
HW, LW: Word;
begin
zSplit(a, HW, LW); // calls the Word version
H := HW;
L := LW;
end;

procedure zSplit(a: Cardinal; var H, L: Word); // this is the Word version
type
Pwor = ^Word;
var
b: Cardinal;
p: Pointer;
pw: Pwor;
begin
p := at a;
pw := PWor(p);
L := pw^;
b := (a shr 16);
p := at b;
pw := PWor(p);
H := pw^;
end;

function zUnite(H, L: Integer): Cardinal;
type
PWor = ^Word;
var
p: Pointer;
pw: PWor;
SH, SL: Smallint;
WH, WL: Word;
begin
try
SH := H;
SL := L;
p := at SH;
pw := PWor(p);
WH := pw^;
p := at SL;
pw := PWor(p);
WL := pw^;
Result := zUnite(WH, WL); // calls the Word version
except
raise;
end;
end;

function zUnite(H, L: Integer): Cardinal;
type
PWor = ^Word;
var
p: Pointer;
pw: PWor;
SH, SL: Smallint;
WH, WL: Word;
begin
try
SH := H;
SL := L;
p := at SH;
pw := PWor(p);
WH := pw^;
p := at SL;
pw := PWor(p);
WL := pw^;
Result := zUnite(WH, WL); // calls the Word version
except
raise;
end;
end;

function zUnite(H, L: word): Cardinal; // this is the Word version
var
CH: Cardinal;
begin
CH := H;
Result := ((CH shl 16) and $FFFF0000) or L;
end;

function CardToInt(a: Cardinal): Integer;
{ changes a Cardinal (32 bit unsigned) to Integer (32 bit signed) }
type
Pint = ^Integer;
var
p: Pointer;
pin: PInt;
begin
p := at a;
pin := PInt(p);
Result := pin^;
end;

function IntToCard(a: Integer): Cardinal;
{ changes an Integer (32 bit signed) to a Cardinal (32 bit unsigned) }
type
PCar = ^Cardinal;
var
p: Pointer;
pc: PCar;
begin
p := at a;
pc := PCar(p);
Result := pc^;
end;

xelag

Feb 12, 2001, 11:13am
A word of caution about using the cell iterator for collecting the contents
of one cell. I just got this email from Roland:



Maybe you could add the cell iterator's secret to the docs: high word
(signed) = x, low word (signed) = z (x and z in decametres). Took me a while
to figure it out...

I'd actually prefer to keep this undocumented for the moment...I mean,
I expected people would probably notice that, but by keeping it
undocumented I have the right to change the significance of the
cell iterator value in the future. :) aw_cell_next() isn't
intended as a mechanism for querying the value of specific cells.

But oh no! I hear Alex cry...that will break my bots! Never fear...
I am planning (was planning for 3.1 in fact but ran out of time) to
add a new SDK method, something like aw_cell_get (int x, int z) which
simply queries the entire contents of any cell. This makes it nice
and clean and formalized with no (x << 16) + z or other funny
business like that. :)

-Roland

1  |  
Awportals.com is a privately held community resource website dedicated to Active Worlds.
Copyright (c) Mark Randall 2006 - 2024. All Rights Reserved.
Awportals.com   ·   ProLibraries Live   ·   Twitter   ·   LinkedIn