Article View: rec.games.programmer
Article #721Re: Computer-Controlled Players (New, More Appropriate Thread)
From: Chris Gray
Date: Fri, 14 Aug 1992 06:20
Date: Fri, 14 Aug 1992 06:20
273 lines
8512 bytes
8512 bytes
In article <1992Aug13.144305.11297@news.uit.no> roarf@stud.cs.uit.no
(Roar Foshaug) writes:
[pseudo-code in a pseudo-language for running a 'robot' omitted]
Here is some real code in a real language for the Caretaker machine (robot)
in my standard AmigaMUD scenario. Similar, but different ( :-) ) code runs
the Packrat and Postman machines. As you can see it is very similar to the
type of thing that Roar Foshaug was suggesting, but is probably much more
detail than you wanted! I to use fixed intervals between steps, rather than
random ones for these robots. I'm not sure why, since the "monster" machines
use random intervals.
define tp_machines Caretaker CreateThing(nil).
/* caretakerGreet - let the caretaker greet everyone in a room he enters. */
define tp_machines proc caretakerGreet(thing who)void:
string name;
name := who@p_pName;
if name ~= "Caretaker" then
DoSay("Good day " + FormatName(name) + "!");
fi;
corp;
/* caretakerStep - the central action routine for the caretaker */
define tp_machines proc caretakerStep()void:
thing here, me, object, home;
list thing lt;
int dir, firstNum, count, n;
bool found, lost;
if not ClientsActive() then
/* no clients (humans) are playing - do little */
After(60, caretakerStep);
else
me := Me();
if me@p_mArrived then
/* this phase - greet everyone */
me@p_mArrived := false;
ForEachAgent(Here(), caretakerGreet);
After(20, caretakerStep);
else
/* this phase - move */
me@p_mArrived := true;
firstNum := me@p_mLastDir;
if Random(3) ~= 0 then
dir := firstNum;
else
firstNum := DirBack(firstNum);
while
dir := Random(12);
dir = firstNum
do
od;
firstNum := dir;
fi;
found := false;
lost := false;
while not found do
if TryToMove(dir) then
found := true;
else
dir := (dir + 1) % 12;
if dir = firstNum then
lost := true;
found := true;
fi;
fi;
od;
if lost then
Log("Caretaker stuck, " + Here()@p_rName + "\n");
Say("I'm stuck! Heeeeelp!!");
After(600, caretakerStep);
else
me@p_mLastDir := dir;
MachineMove(dir);
here := Here();
/* Go through the objects in the room we just entered. Pick
each normal object up. If the object is not where it
"belongs", then keep it, otherwise drop it right away. */
lt := here@p_rContents;
count := Count(lt);
n := 0;
while n < count do
object := lt[n];
if not object@p_oInvisible then
/* DoGet removes an object from the list */
count := count - 1;
if not DoGet(here, me, object) then
/* something happened - abort out */
n := count;
else
home := object@p_oHome;
if home = here or home = nil then
/* object belongs here - drop it right away */
if not DoDrop(here, me, object) then
/* something happened - abort out */
n := count;
fi;
/* otherwise, object is put on the end of the
contents list, and we do not need to look at
it again. */
fi;
/* otherwise, he just keeps it for now */
fi;
else
n := n + 1;
fi;
od;
/* Go through the list of stuff he is carrying. If anything
in that list "belongs" here, then drop it. */
lt := me@p_pCarrying;
count := Count(lt);
n := 0;
while n < count do
object := lt[n];
if object@p_oHome = here then
count := count - 1;
if not DoDrop(here, me, object) then
n := count;
fi;
else
n := n + 1;
fi;
od;
After(20, caretakerStep);
fi;
fi;
fi;
corp;
/* have the caretaker do the command we want him to do */
define tp_machines proc caretakerCommand()void:
thing me;
string command;
me := Me();
command := me@p_mCommand;
me -- p_mCommand;
ignore Parse(G, command);
corp;
/* the caretaker's "understanding" of things told to him */
define tp_machines proc caretakerTold()void:
thing me;
string w, np;
me := Me();
w := GetTail();
/* skip a , or : in the message, e.g. "say caretaker: get rock" */
if SubString(w, 0, 1) = "," or SubString(w, 0, 1) = ":" then
w := SubString(w, 1, Length(w) - 1);
fi;
SetTail(w);
w := GetWord();
if w == "drop" or w == "put" or w == "p" then
/* someone is telling the caretaker to drop something */
w := GetTail();
np := GetNounPhrase(G, w, 0);
if np = "" or FindName(me@p_pCarrying, p_oName, np) ~= succeed then
/* he is not carrying anything matching what they want him to
drop */
if MatchName("flashlight.light;flash", np) >= 0 then
/* there really isn't any such thing */
DoSay("No way! It's mine!");
else
OPrint("Caretaker shakes his head in confusion.\n");
fi;
else
/* He is carrying something that matches. Say 'Certainly' and
try to drop it after 1 second. */
me@p_mCommand := "drop " + w;
DoSay("Certainly.");
After(1, caretakerCommand);
fi;
else
/* Dropping things is the only thing he will do */
DoSay("Sorry, I've got my work to see to.");
fi;
corp;
define tp_machines proc caretakerHear(string what)void:
string word;
word := SetSay(what);
if word ~= "" and word ~= "Packrat" and word ~= "Caretaker" then
/* ignore things said by the packrat or by himself */
word := GetWord();
if word == "Caretaker" then
/* only act if the speech started with his name */
caretakerTold();
elif word == "hello" or word == "hi" then
/* minimal conversationalist! */
OPrint("Caretaker grunts an acknowledgement.\n");
fi;
fi;
corp;
/* called by the system when someone whispers to him */
define tp_machines proc caretakerWhispered(string what)void:
if SetWhisperMe(what) ~= "" then
caretakerTold();
fi;
corp;
/* called as the first step of someone giving something to him */
define tp_machines proc caretakerPre()status:
SPrint(TrueMe(), "Caretaker accepts the gift.\n");
continue
corp;
/* used for several other possible actions */
define tp_machines proc caretakerNoNo()status:
DoSay("Watch it!");
fail
corp;
/* actually create the caretaker */
define tp_machines proc caretakerCreate()void:
Caretaker@p_pStandard := true;
Caretaker@p_mLastDir := D_SOUTH;
Caretaker@p_mArrived := true;
SetupMachine(Caretaker);
Caretaker@p_pDesc :=
"The caretaker is a simple soul. He wears faded overalls, a green check "
"shirt, heavy work boots and a grimy cap, on backwards. His goal in life is "
"to put things back where they belong. One of his most prized possessions is "
"a small handheld flashlight, which he keeps securely hidden in an inside "
"pocket until he needs it.";
Caretaker@p_oLight := true; /* he makes light in dark places */
CreateMachine("Caretaker", Caretaker, r_crossSW, caretakerStep);
ignore SetMachineActive(Caretaker, caretakerStep);
ignore SetMachineSay(Caretaker, caretakerHear);
ignore SetMachineWhisperMe(Caretaker, caretakerWhispered);
GNewIcon(Caretaker, makeCaretakerIcon());
Caretaker@p_pGivePre := caretakerPre;
Caretaker@p_oTouchAction := caretakerNoNo;
Caretaker@p_oSmellAction := caretakerNoNo;
Caretaker@p_oPushAction := caretakerNoNo;
Caretaker@p_oPullAction := caretakerNoNo;
Caretaker@p_oTurnAction := caretakerNoNo;
Caretaker@p_oLiftAction := caretakerNoNo;
Caretaker@p_oLowerAction := caretakerNoNo;
Caretaker@p_oEatAction := caretakerNoNo;
corp;
caretakerCreate().
Sorry about the long post - I just thought some folks might like to see the
details of a robot done in something other than lpc! And no, AmigaMUD still
isn't done. And yes, I'm still working on it.
--
Chris Gray ualberta!ami-cg!cg or cg%ami-cg@kakwa.UCS.UAlberta.CA
Technical Details
Message-ID:
<cg.0cjd@ami-cg.UUCP>Path:
arc1-ca.pugleaf.net!sparky!uunet!elroy.jpl.nasa.gov!usc!sol.ctr.columbia.edu!destroyer!ubc-cs!alberta!kakwa.ucs.ualberta.ca!ami-cg!cgReferences:
<BsvzMw.LFy@news.cso.uiuc.edu> <1992Aug13.144305.11297@news.uit.no>Show Full Headers
Complete Article Headers
Path: arc1-ca.pugleaf.net!sparky!uunet!elroy.jpl.nasa.gov!usc!sol.ctr.columbia.edu!destroyer!ubc-cs!alberta!kakwa.ucs.ualberta.ca!ami-cg!cg From: cg@ami-cg.UUCP (Chris Gray) Newsgroups: rec.games.programmer Subject: Re: Computer-Controlled Players (New, More Appropriate Thread) Distribution: world Message-ID: <cg.0cjd@ami-cg.UUCP> References: <BsvzMw.LFy@news.cso.uiuc.edu> <1992Aug13.144305.11297@news.uit.no> Date: 13 Aug 92 23:20:25 MST Organization: Not an Organization Lines: 273