198 lines
6.0 KiB
Plaintext
198 lines
6.0 KiB
Plaintext
{ $HDR$}
|
|
{**********************************************************************}
|
|
{ Unit archived using Team Coherence }
|
|
{ Team Coherence is Copyright 2002 by Quality Software Components }
|
|
{ }
|
|
{ For further information / comments, visit our WEB site at }
|
|
{ http://www.TeamCoherence.com }
|
|
{**********************************************************************}
|
|
{}
|
|
{ $Log: 21828: EZEngine.pas
|
|
|
|
Rev 1.0 2003.07.13 12:12:02 AM czhower
|
|
Initial checkin
|
|
|
|
|
|
Rev 1.0 2003.05.19 2:54:00 PM czhower
|
|
}
|
|
unit EZEngine;
|
|
|
|
interface
|
|
{$ifdef fpc}
|
|
{$mode objfpc}{$H+}
|
|
{$endif}
|
|
{
|
|
ELIZA -- an interactive parroting
|
|
|
|
Original Source: CREATIVE COMPUTING - MORRISTOWN, NEW JERSEY, late 1970's
|
|
|
|
Converted from Basic and some language called Inform to Delphi by
|
|
Chad Z. Hower aka Kudzu in 2002 - email: chad at hower dot org
|
|
Converted to objects, and implementation rewritten from scratch. Logic matched as best possible
|
|
but BASIC code also had bugs in logic. Inform version also differed slightly, but probaly more
|
|
accurate, but I am no Inform expert.
|
|
|
|
Since that time I have made several custom modifications an improvements including the addition
|
|
of personalities.
|
|
|
|
Note:
|
|
Because of the conversion from older languages, this is not my best code.
|
|
Slowly over time I am cleaning it up to make it more proper OO code. I am also
|
|
expanding its capabilities beyond its original design.
|
|
}
|
|
|
|
uses
|
|
Classes,
|
|
ezPersonality;
|
|
|
|
type
|
|
TEZEngine = class(TComponent)
|
|
protected
|
|
FConjugations: TStrings;
|
|
FDone: Boolean;
|
|
FLastMsg: string;
|
|
FPersonality: TEZPersonality;
|
|
//
|
|
procedure InitConjugations;
|
|
public
|
|
constructor Create(AOwner: TComponent); override;
|
|
destructor Destroy; override;
|
|
procedure SetPersonality(const AName: string);
|
|
function TalkTo(AMsg: string): string; overload;
|
|
function TalkTo(AMsg: string; var VSound: string): string; overload;
|
|
//
|
|
property Done: Boolean read FDone;
|
|
property Personality: TEZPersonality read FPersonality;
|
|
end;
|
|
|
|
implementation
|
|
|
|
uses
|
|
SysUtils, StrUtils;
|
|
|
|
{ TEZEngine }
|
|
|
|
constructor TEZEngine.Create(AOwner: TComponent);
|
|
begin
|
|
inherited;
|
|
FConjugations := TStringList.Create;
|
|
InitConjugations;
|
|
end;
|
|
|
|
destructor TEZEngine.Destroy;
|
|
begin
|
|
FreeAndNil(FPersonality);
|
|
FreeAndNil(FConjugations);
|
|
inherited;
|
|
end;
|
|
|
|
procedure TEZEngine.InitConjugations;
|
|
begin
|
|
with FConjugations do begin
|
|
Add('Are=am');
|
|
Add('Were=was');
|
|
Add('You=I');
|
|
Add('Your=my');
|
|
Add('I''ve=you''ve');
|
|
Add('I''m=you''re');
|
|
Add('Me=you');
|
|
end;
|
|
end;
|
|
|
|
procedure TEZEngine.SetPersonality(const AName: string);
|
|
begin
|
|
FreeAndNil(FPersonality);
|
|
FPersonality := TEZPersonality.ConstructPersonality(AName);
|
|
end;
|
|
|
|
function TEZEngine.TalkTo(AMsg: string; var VSound: string): string;
|
|
var
|
|
i, j: Integer;
|
|
s: string;
|
|
LConj: string;
|
|
LFoundKeyword: string;
|
|
LFoundKeywordIdx: Integer;
|
|
LFoundKeywordPos: Integer;
|
|
LKeyword: string;
|
|
LWordIn: string;
|
|
LWordOut: string;
|
|
begin
|
|
VSound := '';
|
|
if FPersonality = nil then begin
|
|
raise Exception.Create('No personality has been specified.');
|
|
end;
|
|
Result := '';
|
|
LConj := '';
|
|
LFoundKeyword := '';
|
|
LFoundKeywordIdx := FPersonality.Keywords.IndexOf('--NOKEYFOUND--');
|
|
LFoundKeywordPos := 0;
|
|
//
|
|
AMsg := ' ' + Trim(AMsg) + ' ';
|
|
AMsg := StringReplace(AMsg, '''', '', [rfReplaceAll]);
|
|
// TODO: Respond to ones with ?
|
|
// Replace with spaces so ' bug ' will match ' bug. ' etc.
|
|
AMsg := StringReplace(AMsg, '?', ' ', [rfReplaceAll]);
|
|
AMsg := StringReplace(AMsg, '!', ' ', [rfReplaceAll]);
|
|
AMsg := StringReplace(AMsg, '.', ' ', [rfReplaceAll]);
|
|
if AnsiSameText(AMsg, FLastMsg) then begin
|
|
Result := 'Please don''t repeat yourself.';
|
|
end else if AnsiContainsText(AMsg, 'SHUT ') then begin
|
|
Result := 'How would you like it if I told you to shut up? I am sorry but we cannot continue'
|
|
+ ' like this. Good bye.';
|
|
FDone := True;
|
|
end else if Trim(AMsg) = '' then begin
|
|
Result := 'I cannot help you if you do not talk to me.';
|
|
end else begin
|
|
FLastMsg := AMsg;
|
|
// Find Keyword
|
|
for i := 0 to FPersonality.Keywords.Count - 1 do begin
|
|
LKeyword := FPersonality.Keywords[i];
|
|
for j := 1 to Length(AMsg) - Length(LKeyword) + 1 do begin
|
|
if AnsiSameText(Copy(AMsg, j, Length(LKeyword)), LKeyword) then begin
|
|
LFoundKeywordIdx := i;
|
|
LFoundKeyword := LKeyword;
|
|
LFoundKeywordPos := j;
|
|
Break;
|
|
end;
|
|
// Break out of second loop
|
|
if LFoundKeyword <> '' then begin
|
|
Break;
|
|
end;
|
|
end;
|
|
end;
|
|
// Take part of string and conjugate it using the list of strings to be swapped
|
|
LConj := ' ' + RightStr(AMsg, Length(AMsg) - Length(LFoundKeyword) - LFoundKeywordPos + 1)
|
|
+ ' ';
|
|
for i := 0 to FConjugations.Count - 1 do begin
|
|
LWordIn := FConjugations.Names[i];
|
|
LWordOut := FConjugations.Values[LWordIn] + ' ';
|
|
LWordIn := LWordIn + ' ';
|
|
LConj := StringReplace(LConj, LWordIn, LWordOut, [rfReplaceAll, rfIgnoreCase]);
|
|
end;
|
|
// Only one space
|
|
if Copy(LConj, 1, 1) = ' ' then begin
|
|
Delete(LConj, 1, 1);
|
|
end;
|
|
LConj := StringReplace(LConj, '!', '', [rfReplaceAll]);
|
|
// Get reply
|
|
s := TEZReply(FPersonality.Keywords.Objects[LFoundKeywordIdx]).NextText;
|
|
VSound := TEZReply(FPersonality.Keywords.Objects[LFoundKeywordIdx]).Sound;
|
|
if AnsiPos('*', s) = 0 then begin
|
|
Result := s;
|
|
end else if Trim(LConj) = '' then begin
|
|
Result := 'You will have to elaborate more for me to help you.';
|
|
end else begin
|
|
Result := StringReplace(s, '*', LConj, [rfReplaceAll, rfIgnoreCase]);
|
|
end;
|
|
end;
|
|
end;
|
|
|
|
function TEZEngine.TalkTo(AMsg: string): string;
|
|
var
|
|
LSound: string;
|
|
begin
|
|
Result := TalkTo(AMsg, LSound);
|
|
end;
|
|
|
|
end.
|