📄 globallists.pas
字号:
end;//if
End;(* Proc TRandList.SetWeight()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
Safely casts weight into Objects[] array.
*-----------------------------------------------------------------------------*)
Function TRandList.AddObject(
const
Item : Cardinal;
Weight : Cardinal
) : Integer;
Begin
Result := Add(Item);
PutObject(Result, TObject(Weight));
Inc(fTotalWeight,Weight);
End;(* Func TRandList.AddObject()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
*-----------------------------------------------------------------------------*)
Procedure TRandList.Clear;
Var
Index : Integer;
Begin
if Count <> 0 then
begin
//CRW Unset Objects -- remember we're just storing Cardinals in there, not
//"real" objects, otherwise you would be calling
//Objects[Index].Free; before setting to NIL for safety
for Index := 0 to Count-1 do
Objects[Index] := NIL;
//now call std Clear from ancestor, that resets the Integers[] etc.
inherited Clear;
end;
End;(* Proc TRandList.Clear
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
*-----------------------------------------------------------------------------*)
Procedure TRandList.Delete(
Index : Integer
);
Begin
//Don't forget to maintain the TotalWeight..
Dec(fTotalWeight,Weights[Index]);
//CRW - remove the object, which for these lists, set to NIL because
// we aren't really storing objects in there, or else we'd Free before this.
Objects[Index] := NIL;
inherited Delete(Index);
End;(* Proc TRandList.Delete()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
Added here to direct to this class' LoadFromStream
*-----------------------------------------------------------------------------*)
Procedure TRandList.LoadFromFile(
const
Filename : String
);
Var
Stream: TStream;
Begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
End;(* Proc TRandList.LoadFromFile()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
TRandList.LoadFromStream()
-- Assumes you're loading data in the format...
<ItemID>','<Weight>
Any String data that doesn't conform, will be ignored
(i.e., a descriptive header for the data :) )
Based heavily on routines in TStrings, ancestor of TStringList, which
TIntList32 is based on.
*-----------------------------------------------------------------------------*)
Procedure TRandList.LoadFromStream(
Stream : TStream
);
Var
Size : Integer;
P : PChar;
Start : PChar;
S : String;
Line : String;
ItemID : Cardinal;
Weight : Cardinal;
Begin
{BeginUpdate; }
try
Size := Stream.Size - Stream.Position;
SetString(S, NIL, Size);
P := Pointer(S);
Stream.Read(P^, Size);
if P <> NIL then
begin
while P^ <> #0 do
begin
Start := P;
//Find <ItemID> Step through until you find EOL or a Comma
while NOT (P^ IN [#0, #10, #13, #44]) do
Inc(P);
SetString(Line, Start, P - Start);
ItemID := StrToIntDef( Line, 0 );
Inc(P);
//String Found, so find <Weight>
Start := P;
//search for integer until EOF found (not comma this time)
while NOT (P^ IN [#0, #10, #13]) do
Inc(P);
SetString(Line, Start, P - Start);
Weight := StrToIntDef( Line, 0 );
// If EITHER converted integer is Zero, one or both are invalid,
// so, do not add them if so...
if (ItemID > 0) AND (Weight > 0) then
AddObject( ItemID, Weight );
if P^ = #13 then Inc(P);
if P^ = #10 then Inc(P);
end;//while P<>#0
end;//if P<>NIL
finally
{EndUpdate;}
end;
End;(* Proc TRandList.LoadFromSTream()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
"Key" Routine behind this whole class -- generates a random choice in the
list based on the Weighting
*-----------------------------------------------------------------------------*)
Function TRandList.RandomChoice : Cardinal;
Var
Index : Integer;
Tally : Cardinal;
Number : Cardinal;
Begin
case Distribution of
distWeighted :
begin
//Choice based on TotalWeight.
Number := Random(fTotalWeight);
Tally := 0;
Index := -1;
//iterate until you get in that 'bucket' where
repeat
Inc(Index);
Inc(Tally,Weights[ Index ]);
until (Tally > Number);
Result := Integers[ Index ];
end;
distUniform :
begin
Result := Integers[ Random(Count) ];
end;
else
Assert(
Distribution IN [distWeighted, distUniform],
'TRandList.RandomChoice -- no choice for set Distribution'
);
Result := 0;
end;
End;(* Proc TRandList.RandomChoice
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
Reads a different format file than the ancestor
*-----------------------------------------------------------------------------*)
Constructor TSummonMobList.Create(
FileName : String;
DistType : TDistType
);
Begin
inherited Create;
// Always call ancestor's routines first in Create
//Weil, in this case call our granddaddy's constructor...
Clear;
Distribution := DistType;
LoadFromFile( FileName );
End;(* TSummonMobList.Create()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
*-----------------------------------------------------------------------------*)
Destructor TSummonMobList.Destroy;
Begin
// Always call ancestor's routines after you clean up
// objects you created as part of this class
//Ancestor clears out objects and integers cleanly, defer to it.
inherited;
End;(* T.Destroy
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
*-----------------------------------------------------------------------------*)
Procedure TSummonMobList.LoadFromFile(
const
Filename : String
);
Var
Stream: TStream;
Begin
Stream := TFileStream.Create(FileName, fmOpenRead or fmShareDenyWrite);
try
LoadFromStream(Stream);
finally
Stream.Free;
end;
End;(* Proc TSummonMobList.LoadFromFile()
*-----------------------------------------------------------------------------*)
(*-----------------------------------------------------------------------------*
CRW 2004/04/09
We're reading an expanded format of summon_mob.txt
Mob.JNAME,DBWeight,MVPWeight,Mob.ID
This LoadFromStream handles this format, but only reads fields 2 and 4,
DBweight, and Mob.ID
Commas must be present for a line to be read, and the proper format
a number and a number, or the line is ignored.
Blank lines are also ignored, thus making the datafile read a LOT safer from
corrupting what is loaded into the list.
*-----------------------------------------------------------------------------*)
Procedure TSummonMobList.LoadFromStream(
Stream : TStream
);
Var
Size : Integer;
P : PChar;
Start : PChar;
S : String;
Line : String;
MobID : Cardinal;
Weight : Cardinal;
//CRW internal call for clarity/brevity
procedure GetNextToken;
begin
Start := P;
while NOT (P^ IN [#0, #10, #13, #44]) do
Inc(P);
end;
//
Begin
{BeginUpdate; }
try
Size := Stream.Size - Stream.Position;
SetString(S, NIL, Size);
P := Pointer(S);
Stream.Read(P^, Size);
if P <> NIL then
begin
while P^ <> #0 do
begin
//Read past MobID field (not stored)
GetNextToken;
Inc(P);
//Find <DBweight> Step through until you find EOL or a Comma
GetNextToken;
SetString(Line, Start, P - Start);
Weight := StrToIntDef( Line, 0 );
Inc(P);
//Read past MVPweight field (not stored)
GetNextToken;
Inc(P);
//Find <MobID>
GetNextToken;
SetString(Line, Start, P - Start);
MobID := StrToIntDef( Line, 0 );
// If EITHER DBweight or MobID are Zero, one or both are invalid,
// Do not add them if so...
if (MobID > 0) AND (Weight > 0) then
AddObject( MobID, Weight );
// Clear off remaining chars, until new line/eof, then re-read
// tokens in next time around the loop.
// This cleans up stray commas, other junk text, whitespace.
while NOT (P^ IN [#0, #10, #13]) do
Inc(P);
if (P^ = #13) then Inc(P);
if (P^ = #10) then Inc(P);
end;//while P<>#0
end;//if P<>NIL
finally
{EndUpdate;}
end;
End;(* Proc TSummonMobList.LoadFromSTream()
*-----------------------------------------------------------------------------*)
end.
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -