SRL Archive - Research & Development Lounge

Auto Responder!


Naike

2009-02-08 17:04:07

Auto Responder
By N1ke!


About

This is my responder which i made for the #4 SRL competition!
It loads the triggers/responses from an .ini file namned Dictionary which shall
be placed at Includes/SRL.


Dictionary.ini

Dictionary.ini is made and can be edited with Widget's form, if you do edit
it heavily feel free to post/pm me an uptaded version.

If you do edit it then theres some "commands" that you need to know,
they are declared by a $ and followed by the command - Example, $mining
will result in the players mining level. These commands works for all the skills
(only as the hole names, not $wc, $rc) and 2 name commands, $namesplit
which makes a human nickname and $name which results in the players name.

All the commands are

Response commands

$attack
$strength
$defence
$range
$prayer
$magic
$runecrafting
$hitpoints
$agility
$herblore
$thieving
$crafting
$fletching
$slayer
$mining
$smithing
$fishing
$cooking
$firemaking
$woodcutting
$farming
$construction
$hunter
$summoning


Trigger commands

$name
$namesplit

Now instead of switching gametabs to get all the Skill levels everytime
someone asks you, you simply do GetAllLevels; anywhere in your script and
it will load it from there!.


How to use

Now how to use this fine include, you simply replace CAutoResponder.scar in SRL/Core with the one in the .Rar file and you place Dictionary.ini in Include/SRL.
Now the only thing you have to do is to call SetupAutoResponder; after your DeclarePlayers procedure! and it's all loaded!. From here you don't have to do
a single thing since FindNormalRandoms loads Respond which my include replaces.


Problems

I can currently only find one single problem and that is that it misses to
respond to the Woodcutting triggers, if you find out why i be more then happy to rep++ you.


Other info

Feel free to give any feedback, ideas, bugs or such that i can work with!
Thanks for reading and hope you enjoy it!.

NCDS

2009-02-08 17:07:05

Ahh Glad to see you finally released it!

did it not win the Competition?! lol

Looks good tho, Nice Release.

rep+

Naike

2009-02-08 17:10:08

Wizzup? is busy so he havnt marked the scripts yet.. But he sayd it was ok to release it :)

ZaSz

2009-02-08 17:10:44

Very nice, looked through it, will end up using

Naike

2009-02-08 17:15:15


procedure SetupAutoResponder(ChanceOfResponding: Integer; SaveQuestions: Boolean);

Try reading the include before using ^^

ian.

2009-02-08 17:16:39

lol yeah deleted that post :p

what's a good number for chance of responding if I want it to respond to everything?

Naike

2009-02-08 17:20:02

It's in % so SetupAutoResponder(100, False); would respond to everything.

ian.

2009-02-08 17:21:09

thanks ;D I'll test this out and tell you what happens :)

NCDS

2009-02-08 17:21:43

Do you mind if I use this in a couple Scripts I will be releasing in the next couple weeks?

I will Credit good no worries.

mormonman

2009-02-08 17:22:15

You should add the feature to have a chance to remember the question… not to hard I don't think. Very nice, I can't wait to see MK's, and maybe the possibilty of adding them together for srl commit?…

Naike

2009-02-08 17:28:26

Feel free to use this at free will!

And MasterKill is a really good scripter, Kinda sure he will beat me.. But who knows ;)

Harry

2009-02-08 17:37:03

Grats on finally working on it ^_^ I was too lazy to do it, heh. It looks nice.

EvilChicken!

2009-02-09 02:54:16

Awesome, you released it! ^3^

I've seen it before, it looks really nice – makes me wonder what MK will come up with ..

/me looks forward to seeing the result of the competition..

Sandstorm

2009-02-09 08:58:38

Lol wow, nice autoresponder! Looks like I got stomped in the competition :/.

~Sandstorm

Naike

2009-02-12 10:01:18

New release! V 1.0

Added an global TStringArray to save all the questions/responses and a ResponsesMade interger to keep the count up..

Note* This includes main function, Respond is being used in FindNormalRandoms!

TRiLeZ

2009-03-31 20:35:51

I got this error:
[Runtime Error] : Out Of Range in line 301 in script H:\SCAR 3.15\includes\SRL/SRL/Core/CAutoRespond.scar

Nava2

2009-04-02 07:30:52

//-----------------------------------------------------------------//
//-- Scar Standard Resource Library --//
//-- ยป AutoRespond Routines --//
//-----------------------------------------------------------------//
// * Procedure SetResponseChance(Chance: Integer); // * by N1ke!
// * Procedure SetDicArrays; // * by N1ke!
// * Function SplitName(Name: String):String; // * by N1ke!
// * Procedure RenewTrigger(var Text : TStringArray); // * by N1ke!
// * Procedure RenewAllTriggers; // * by N1ke!
// * Procedure DebugDicArrays; // * by N1ke!
// * Procedure DebugDictionary; // * by N1ke!
// * Function ReplaceSign(Text : String): string; // * by N1ke!
// * Function ChatText(Text: TStringArray): Boolean; // * by N1ke!
// * Procedure DeleteIndex(Index : Integer; var Arr : TStringArray); // * by N1ke!
// * procedure SetupSRLAutoResponder(ChanceResponse: Integer); // * by N1ke!
// * Function Responder: Boolean; // * by N1ke!

Type
RowType = Record
Trigger, Response: TStringArray;
UsedResponse: Integer;
end;
PlayerDictionary = Record
Row: Array of RowType;
end;

var
PlayerDic: Array of PlayerDictionary;
SQAA, UseAutoResponder: Boolean;
ResponseArrays: TStringArray;
ChanceResponding, ResponsesMade: Integer;


{*******************************************************************************
Procedure SetResponseChance(Chance: Integer);
By: N1ke!
Description: Sets response chance.
Example SetResponseChance(75); would set the response chance to 75%.
Reason it's a Procedure instead of just the var is the following:
Vars can be hard to remember, and is annoying to find out!
Also, you can simply find it by Clicking CTRL + Space then typing SetRes ect.
*******************************************************************************}
Procedure SetResponseChance(Chance: Integer);
begin
ChanceResponding := Chance;
end;

{*******************************************************************************
Procedure SetDicArrays;
By: N1ke!
Description: Loads the length of the arrays using the Dictionary.ini.
*******************************************************************************}
Procedure SetDicArrays;
var
i, ii : integer;
begin
SetArrayLength(PlayerDic, HowManyPlayers);
// add H vars instead
For i:= 0 to High(PlayerDic) do
begin
SetArrayLength(PlayerDic[i].Row, StrToInt(ReadIni('General', 'Rows', AppPath + 'includes\SRL\Dictionary.ini')) + 1);
For ii:= 1 to High(PlayerDic[i].Row) do
begin
SetArrayLength(PlayerDic[i].Row[ii].Trigger, StrToInt(ReadINI('Row' + IntToStr(ii), 'TriggerCount', AppPath + 'includes\SRL\Dictionary.ini'))+ 1);
SetArrayLength(PlayerDic[i].Row[ii].Response, StrToInt(ReadINI('Row' + IntToStr(ii), 'ResponseCount', AppPath + 'includes\SRL\Dictionary.ini'))+ 1);
end;
end;
end;

{*******************************************************************************
Function SplitName(Name: String):String;
By: N1ke!
Description: Makes a name into a human like nick.
Example, Input = 1 w0nt l0se output = w0nt
If a name got many spaces it will delete them and result in the 3
first letters. Example, Input = N 1 k e e Output = N1k
*******************************************************************************}
Function SplitName(Name: String):String;
var I : integer;
begin
If Length(GetOthers(Name)) < 3 then
If Pos(' ', Name) > 0 then
begin
Result := Copy(Name, Pos(' ', Name), Length(Name));
Delete(Result, Pos(' ', Result), 1);
If Pos(' ', Name) > 0 then
Delete(Result, Pos(' ', Result), Length(Result));
If Not Length(Result) <= 2 then
Exit;
end;
// add H vars instead
For I:=0 to Length(GetOthers(Name))+1do
Delete(Name, Pos(' ', Name), 1);
Result := Left(Name, 3);
end;

{*******************************************************************************
Procedure RenewTrigger(var Text : TStringArray);
By: N1ke!
Description: Renews a trigger to match the currentplayer.
*******************************************************************************}
Procedure RenewTrigger(var Text : TStringArray; Player: Integer);
var
TStrP: TStringArray;
Temp: String;
I, II, L: integer;
begin
// add H vars instead even 0..1 here
L := GetArrayLength(Text);
TStrP:= ['$name', '$namesplit'];
For I:=0 to High(Text) do
For ii:=0 to High(TStrP) do
begin
if Pos( LowerCase(TStrP[II]), LowerCase(Text[I])) > 0 then
begin
Case Lowercase(TStrP[I]) of
'$name' : Temp := Players[Player].Name;
'$namesplit' : Temp := SplitName(Players[Player].Name);
end;
Text[i] := Replace(Text[i], LowerCase(TStrP[I]), Temp);
end else Text[i] := Text[i];
end;
SetArrayLength(Text, L);
end;

{*******************************************************************************
Procedure RenewAllTriggers;
By: N1ke!
Description: Renews all triggers to match the currentplayer.
*******************************************************************************}
Procedure RenewAllTriggers;
var
i, ii: integer;
begin
// add H vars instead
For i:=0 to High(PlayerDic)do
For ii:=1 to High(PlayerDic[i].Row)do
RenewTrigger(PlayerDic[I].Row[ii].Trigger, I);
end;

{*******************************************************************************
Procedure DebugDicArrays;
By: N1ke!
Description: Debugs the length of the triggers and responses.
*******************************************************************************}
Procedure DebugDicArrays;
var
I, II : Integer;
begin
// add H vars instead
If GetArrayLength(PlayerDic) = 0 Then Exit;
For I:=0 To High(PlayerDic)do
For II:=1 to High(PlayerDic[I].Row)do
Writeln('[' + IntToStr(i) + '] Row: ' + IntToStr(II) + ' | Triggers: ' + IntToStr(High(PlayerDic[I].Row[II].Trigger)) + ' | Responses: ' + IntToStr(High(PlayerDic[I].Row[II].Response)));
end;

{*******************************************************************************
Procedure DebugDictionary;
By: N1ke!
Description: Debugs the hole dictionary.
*******************************************************************************}
Procedure DebugDictionary;
var
I, II, III: Integer;
begin
// Add Highs please.
If GetArrayLength(PlayerDic) = 0 Then Exit;
For I:=0 To High(PlayerDic)do
For II:=1 to High(PlayerDic[I].Row)do
begin
Writeln('[' + IntToStr(i) + ']Row: ' + IntToStr(II));
For III:=0 to High(PlayerDic[I].Row[II].Trigger) - 1 do
Writeln('Trigger[' + IntToStr(III) + '] = ' + PlayerDic[I].Row[II].Trigger[III]);
For III:=0 to High(PlayerDic[I].Row[II].Response) - 1 do
Writeln('Response[' + IntToStr(IIII) + '] = ' + PlayerDic[I].Row[II].Response[IIII]);
end;
end;

{*******************************************************************************
Function ReplaceResponseSign(Text : String): string;
By: N1ke!
Description: Checks if players have been switched.
*******************************************************************************}
Function ReplaceResponseSign(Text : String): string;
var
TStrP: TStringArray;
I, H: integer;
begin
TStrP:= ['$attack', '$strength', '$defence', '$range', '$prayer',
'$magic', '$runecrafting', '$hitpoints', '$agility', '$herblore',
'$thieving', '$crafting', '$fletching', '$slayer', '$mining', '$smithing', '$fishing', '$cooking',
'$firemaking', '$woodcutting', '$farming', '$construction', '$hunter', '$summoning'];
H := High(TStrP);
Text := LowerCase(Text);
for I:= 0 to H do
begin
if Pos( LowerCase(TStrP[I]), text) > 0 then //
begin
Result := TStrP[I];
Delete(TStrP[I], Pos('$', TStrP[I]), 1);
If Players[CurrentPlayer].Level[i+1] = 0 then
Players[CurrentPlayer].Level[i+1] := GetSkillInfo(TStrP[I], False);
Result := Replace(Text, LowerCase(Result), IntToStr(Players[CurrentPlayer].Level[i+1]));
Exit;
end;
end;
end;

{*******************************************************************************
Function ChatText(Text: TStringArray): Boolean;
By: N1ke!
Description: Tries to find a match between a trigger array and the last
typed message. If the message is from the current player it will exit.
*******************************************************************************}
Function ChatText(Text: TStringArray; var Sresult: String): Boolean;
var
I, II: integer;
S, Name : string;
begin
LastChatter(Name);
if (not (GetLastChatText(S))) then Exit;
II := High(Text);
S := LowerCase(S);
for I := 0 to II do
begin
if Pos(LowerCase(Text[i]), S) = 1 then // Shouldnt this be <> 0
begin
SResult := Name + ': ' + Text[i];
Result := True;
Exit;
end;
end;
end;

{*******************************************************************************
Procedure DeleteIndex(Index: Integer; var Arr: TStringArray);
By: N1ke!
Description: Deletes a index in a TStringArray.
*******************************************************************************}
Procedure DeleteIndex(Index: Integer; var Arr: TStringArray);
var
i, h: integer;
Begin
H := High(Arr) - 1;
for i:= Index to H do
Swap(Arr[i], Arr[i+1]);
SetArrayLength(Arr, H + 1);
end;

{*******************************************************************************
procedure SetupSRLAutoResponder(ChanceResponse: Integer);
By: N1ke!
Description: Loads dictionary and sets up the responder.
*******************************************************************************}
procedure SetupAutoResponder(ChanceOfResponding: Integer; SaveQuestions: Boolean);
var
I, II, III, H, HH, HHH: Integer;
Begin
SetDicArrays;
SetResponseChance(ChanceOfResponding);
SQAA := SaveQuestions;
H := High(PlayerDic);
For I := 0 to H do
begin
HH := High(PlayerDic[i].Row);
For II := 1 to HH do
begin
HHH := High(PlayerDic[i].Row[II].Trigger);
For III := 0 to HHH do
PlayerDic[i].Row[II].Trigger[III] := ReadINI('Row' + IntToStr(II), 'Trigger' + IntToStr(III), AppPath + 'includes\SRL\Dictionary.ini');
HHH := High(PlayerDic[i].Row[II].Response);
For III := 0 to HHH do
PlayerDic[i].Row[II].Response[III] := ReadINI('Row' + IntToStr(II), 'Response' + IntToStr(III), AppPath + 'includes\SRL\Dictionary.ini');
end;
end;
RenewAllTriggers;
UseAutoResponder := True;
MarkTime(PlayerDic[CurrentPlayer].Row[i].UsedResponse);
end;

{*******************************************************************************
Function Respond: Boolean;
By: N1ke!
Description: Responds to triggers which is set in the Dictionary.ini file.
Also add small mistakes and deletes the response after.
*******************************************************************************}
Function Respond: Boolean;
var
I, N, H: Integer;
Msg, GBCM: String;
Begin
If Not UseAutoResponder Then Exit;
GBCM := GetBlackChatMessage;
If (Pos(Lowercase(Players[CurrentPlayer].Name) , Lowercase(GBCM)) <> 0) then Exit;
If GBCM = 'Welcome to RuneScape.' then Exit;
H := High(PlayerDic[CurrentPlayer].Row);
For I :=0 to H do
begin
If Not ChatText(PlayerDic[CurrentPlayer].Row[i].Trigger, Msg)then Continue;
If TimeFromMark(PlayerDic[CurrentPlayer].Row[i].UsedResponse) < 1000*30+Random(60)then Exit;
If GetArrayLength(PlayerDic[CurrentPlayer].Row[i].Response) = 0 then Exit;
If ChanceResponding < Random(100) then Exit;
N := RandomRange(0, High(PlayerDic[CurrentPlayer].Row[i].Response));
PlayerDic[CurrentPlayer].Row[i].Response[N] := ReplaceResponseSign(PlayerDic[CurrentPlayer].Row[i].Response[N]);
case Random(4) of
0..2: TypeSend(PlayerDic[CurrentPlayer].Row[i].Response[N]);
3: TypeSend(AddMistakes(PlayerDic[CurrentPlayer].Row[i].Response[N], 10+Random(20)));
end;
Writeln(Msg);
Writeln(Players[CurrentPlayer].Name + ': ' + PlayerDic[CurrentPlayer].Row[i].Response[N]);
MarkTime(PlayerDic[CurrentPlayer].Row[i].UsedResponse)
Result := True;
If SQAA then
begin
AddToSRLLog('Trigger: ' + Msg + ' | Response: ' + Players[CurrentPlayer].Name + ': ' + PlayerDic[CurrentPlayer].Row[i].Response[N]);
ResponseArrays[ResponsesMade] := TheTime + ' | Trigger: ' + Msg + ' | Response: ' + Players[CurrentPlayer].Name + ': ' + PlayerDic[CurrentPlayer].Row[i].Response[N];
end;
Inc(ResponsesMade);
DeleteIndex(N, PlayerDic[CurrentPlayer].Row[i].Response);
Exit;
end;
end;

Procedure SetupSRLAutoResponder; // To avoid errors.
begin
end;

Check it!