INFO
	smartmonster - About the OLD smartmonster object.

DESCRIPTION
	The smartmonster was written back in 1990, and has been worked on by
	about every arch wizard since then. By now it is a quagmire of strange
	patches, and uses up much memory and CPU. The new monsters in /std/
	should be used instead.

	Obsolete text:
	About the smartmonster - for version 0.4 (August 3, 1992)
	-------------------------------------------------------
	
	Written by Padrone, latest change of this file August 3, 1992.
	
	This is a description of a monster object, "obj/smartmonster".
	
	This smartmonster is (almost) backwards compatible
	with the old /obj/monster, so you can replace most usages of
	/obj/monster with /obj/smartmonster.
	
	These functions, that were used to configure the old "obj/monster"
	object, have been replaced, but can still be used in the compatible
	version of the smartmonster:
	    set_chance(int c)
	    set_spell_mess1(string m)
	    set_spell_mess2(string m)
	    set_spell_dam(in d)
	    load_chat(int chance, string *strs)
	    load_a_chat(int chance, string *strs)
	    set_match(object ob, mixed *func, mixed *type, mixed *match)
	    set_aggressive(status a)
	    set_alias(string a)
	    set_alt_name(string a)
	    set_whimpy()
	(Later we might do something about move_at_reset, set_dead_ob,
	and set_random_pick.)
	This file contains a description on how to do corresponding things,
	and more, in "obj/smartmonster".
	
	
	Contents of this file
	---------------------
	
	    1. Some small changes
	    2. A kinder, gentler aggressivity
	    3. A more advanced (and correctly spelled) wimpy mode
	    4. Simple chats, similar to "load_chat" in the old "/obj/monster"
	    5. Responses to actions from players and monsters
	    7. Special attacks and other things to do in a fight
	    8. A function to call in each heart-beat
	    9. The smartmonsters can be friends!
	    10. Aliases
	    11. The functions to call to configure the object
	    12. Expanded stat format
	    13. An example: Harry
	    14. Incompatibilities with the old /obj/monster
	
	
	1. Some small changes
	---------------------
	
	There are more (and better used) possible directions in the random
	move, which is used both if the monster is trying to run away and if
	"move_at_reset" has ben set.
	
	To give the monster a soul, just call the function "set_soul".
	
	
	2. A kinder, gentler aggressivity
	---------------------------------
	
	"set_aggressive" has ben replaced by "set_aggressivity",
	which takes an argument between 0 (never attacks anything - corresponds
	to the old set_aggressive(0)) and 100 (attacks everything it sees -
	corresponds to the old set_aggressive(1)).
	The attack decision is now dependent of the alignments and levels of
	both the monster and the intended victim, and has an element of
	randomness.
	
	By default monsters are totally peaceful.
	
	
	3. A more advanced (and correctly spelled) wimpy mode
	-----------------------------------------------------
	
	The old "set_whimpy", which made the monster run away when its
	hitpoints became low, has been replaced by "set_wimpyness", which takes
	an argument between 0 (never run away) and 100 (run as soon as you are
	hurt). The monster will run when it has less per cent hitpoints left
	then the given argument.
	
	To get the same effect as the old "set_whimpy()", use
	"set_wimpyness(20)".
	
	By default monsters are totally un-wimpy, and will never run away.
	
	
	4. Simple chats, similar to "load_chat" in the old "/obj/monster"
	-----------------------------------------------------------------
	
	Usage:
	    set_chat_chance  CHAT-CHANCE
	    set_chat_in_fight  FLAG
	    add_chat  CHAT-MESSAGE
	    set_chats  CHAT-MESSAGES-ARRAY
	
	Examples:
	    harry->set_chat_chance(2);
	    harry->set_chat_in_fight(1);
	    harry->add_chat("Harry says: What are you waiting for?\n");
	    harry->add_chat("Harry says: Nice weather, isn't it?\n");
	    smurf->set_chats(({ "The smurf smurfs.\n",
				"The smurf smurfs a smurf.\n" }));
	
	After the above calls to harry, there is now a 2 percent chance at each
	heartbeat (every two or three seconds), that one of the add_chat'ed
	strings will be printed by Harry.
	The reason for not having individual percentages for every string,
	i. e. with the usage
	    add_chat  CHAT-MESSAGE  [ CHANCE ]
	is just because of efficiency. Maybe it can be changed later.
	
	
	5. Responses to actions from players and monsters
	-------------------------------------------------
	
	Usage:
	  add_response ACTION  RESPONSE  [ PERSONAL-REPLY-MESSAGE ]  [ CHANCE ]
	  set_responses  RESPONSE-ARRAY
	  set_response_object  OBJECT
	
	Or, in another way of putting it:
	  add_response  ACTION  "REPLY-MESSAGE"  [ "PERSONAL-REPLY-MESSAGE" ]  [ CHANCE ]
	    add_response  ACTION  "*FUNCTION-NAME"  [ CHANCE ]
	    add_response  ACTION  "!COMMAND"  [ CHANCE ]
	    add_response  ACTION  ARRAY-OF-RESPONSES  [ CHANCE ]
	
	Examples of simple responses:
	    harry->add_response("smiles happily", "Harry smiles happily.\n");
	    harry->add_response("smiles happily", "Harry smiles happily.\n", 100);
	    harry->add_response("smiles happily", "Harry smiles happily.\n", 0, 100);
	    harry->add_response("smiles happily", "Harry smiles happily.\n",
				"Harry smiles at you.\n", 100);
	    harry->add_response("says:", "Harry looks at the one who was talking.\n",
				"Harry looks at you.\n");
	    harry->add_response("drops", "Harry says: Why did you drop that?\n");
	    harry->add_response("drops", "Harry says: Why did you drop that?\n", 75);
	
	If there is a second string, it is sent to the "opponent" instead of
	the first message. If no CHANCE is given, or if it is 0, it will be set to 100.
	
	Warning! Each matching response is tested against its chance in the order it
	         was add_response'd, so if you set three responses, all with 50%
		 chance, their probabilities, if they match a certain action,
		 will be 50%, 25% and 12.5%!
		 This also applies to responses and attacks.
	
	If the REPLY-MESSAGE starts with one of the characters '*' or a '!',
	it is used as a function to call, or a command for the monster to execute.
	
	Examples of advanced responses (function calls and commands):
	    harry->set_response_object(this_object());
	    harry->add_response("sings", "*handle_sing")
	    harry->add_response("pukes", "*handle_puke", 0)
	    harry->add_response("smiles happily", "*handle_happy_smile", 35)
	    harry->add_response("smiles", "*handle_smile", 100)
	    harry->add_response("kicks you", "!scream")
	
	The function FUNCTION-NAME in the object OBJECT will be called with
	three arguments: who, what and how.
	If Harry now gets the message "Padrone smiles like a surgeon.\n",
	the call will be:
	    handle_smile("Padrone", "smiles", "like a surgeon.")
	
	The RESPONSE can also be an array of responses:
	    harry->add_response("bounce", ({ "!flip", "!smile", "!grin" }), 100);
	
	The response is performed in the next heart beat (1-2 seconds later).
	The value of this_player() will be the monster, so if you call a
	function (with the "*FUNCTION-NAME" syntax), messages from say() will
	go to everyone in the room except the monster, and write() will go to
	the monster itself.
	
	Warning! Messages printed by write() in a response function or a
	command will be seen by the monster (in the next heartbeat), and if
	they are matched by a response there might be an infinite loop.
	
	Often you want to use the name of the monster or player whose action we
	are responding to. You can use the string "$OTHER", which will be
	substituted with the other monster's or player's name. Example:
	    harry->add_response("kicks you", "Harry glares at $OTHER.\n",
			        "Harry glares at you.\n");
	The string "$LOWOTHER" will be substituted with the lower-case form of
	the name.
	"$OTHER" and "$LOWOTHER" also works in commands and function calls:
	    harry->add_response("kicks you", "!kick $LOWOTHER");
	    harry->add_response("kicks you", "*handle_kick_by_$LOWOTHER");
	
	
	6. Responses to certain frequently used actions
	-----------------------------------------------
	
	Usage:
	    set_say_handler  [ OBJECT  [ FUNCTION-NAME ] ]
	    set_tell_handler  [ OBJECT  [ FUNCTION-NAME ] ]
	    set_give_handler  [ OBJECT  [ FUNCTION-NAME ] ]
	    set_give_money_handler  [ OBJECT  [ FUNCTION-NAME ] ]
	    set_arrive_handler  [ OBJECT  [ FUNCTION-NAME ] ]
	    set_leave_handler  [ OBJECT  [ FUNCTION-NAME ] ]
	
	Examples:
	    harry->set_say_handler();
	    harry->set_tell_handler(this_object(), "handle_say_and_tell");
	    harry->set_give_handler("players/ugh/centcomp", "got_something");
	
	Whenever one of the actions happen (someone saying something, etc.),
	the function FUNCTION-NAME in the object OBJECT will be called with
	some useful arguments. Default function names: "handle_say",
	"handle_tell", "handle_give", "handle_give_money", "handle_arrive",
	"handle_leave".
	
	The arguments that are sent are:
	    1.  the object that did something (if it wasn't possible to find
	        this object, the function is not called - except in the case of
	        leaving),
	    2.  the name of the player or monster that did it, and finally
	    3a. the phrase that was said, or
	    3b. the object (and it's name) that was given, or
	    3c. the way someone arrived or left.
	
	If we assume that the default function names are used, this might give
	an idea of how the calls are made:
	    handle_say(who_obj, who_string, phrase_string);
	    handler_tell(who_obj, who_string, phrase_string);
	    handle_give(who_obj, who_string, what_obj, what_string);
	    handle_give_money(who_obj, who_string, number_of_coins);
	    handle_arrive(who_obj, who_string, how_string);
	    handle_leave(who_obj, who_string, how_string);
	
	Don't forget that "handle_give" takes four arguments,
	that the third argument to handle_give_money is an integer,
	and that the first argument to handle_leave will be 0.
	Also remember the difference from response functions (see above),
	which are called with three strings as arguments: who, what and how.
	
	
	7. Special attacks and other things to do in a fight
	----------------------------------------------------
	
	This is a replacement for both "load_a_chat" (attack chats)
	and the "set_spell_mess1" functions:
	
	Usage:
	   add_attack  ATTACK-MESSAGE  [ PERSONAL-ATTACK-MESSAGE ]  MAX-DAMAGE  [ CHANCE ]
	
	Examples:
	   harry->add_attack("Harry says: Help, someone!\n", 0, 0, 10);
	   harry->add_attack("Harry punched his opponents nose.\n",
			     "Harry punched your nose.\n", 2, 50);
	   glumglot->add_attack("Glumglot casts a fireball.\n",
				"You are hit by a fireball.\n", 50, 10);
	   glumglot->add_attack("Glumglot casts a fireball.\n", 50, 10);
	
	"$OTHER" can be used in the attack messages:
	   harry->add_attack("Harry punched $OTHER's nose.\n",
			     "Harry punched your nose.\n", 2, 50);
	
	
	8. A function to call in each heart-beat
	----------------------------------------
	
	The smartmonster can be set up to call a function at every heartbeat
	while it's in a fight, and another function at every heartbeat while
	it's not in a fight.
	
	Usage:
	    set_fight_beat  [ OBJECT  [ FUNCTION-NAME ] ]
	    set_peace_beat  [ OBJECT  [ FUNCTION-NAME ] ]
	
	Examples:
	    wizard->set_fight_beat(this_object(), "teleport_away");
	    cow->set_peace_beat("players/grendel/room/meadow", "munch_hay");
	    orc->set_fight_beat();
	
	The function FUNCTION-NAME in the object OBJECT will be called
	each heart-beat, in the case of fight_beat with the current enemy
	as argument.
	
	Default function names: "fight_beat" and "peace_beat".
	
	
	9. The smartmonsters can be friends!
	------------------------------------
	
	Usage:
	   add_friend  OBJECT-OR-NAME
	   set_friends  ARRAY-OF-OBJECTS-OR-NAMES
	
	Examples:
	   wizard->add_friend("sheriff");
	   orc1->add_friend(orc2);
	   orc1->set_friends( ({ orc2, orc3, orc4 }) );
	
	Friends will help each other in a fight, i. e. they will attack
	the monster or player that their friends are fighting.
	
	
	10. Aliases
	-----------
	
	A smartmonster can have any number of aliases.
	
	Usage:
	   add_alias  STRING
	   set_friends  ARRAY-OF-STRINGS
	Examples:
	   arnold->set_aliases( ({ "hero", "big-guy", "muscle" }) );
	   arnold->add_alias("terminator");
	
	
	11. The functions to call to configure the object
	-------------------------------------------------
	
	These are the functions you should call to configure the monster.
	
	First, call these three functions:
	
	    set_name(string n)
	    set_short(string sh)
	    set_level(int l)
	
	IT IS IMPORTANT that you call these functions FIRST,
	and that you call set_name BEFORE you call set_short,
	since they will set default values for some values.
	
	Then, call any of these functions that you want.
	It is strongly suggested that you always use at least set_long, set_al
	and the gender function.
	
	    set_aliases(string *all_aliases)
	    add_alias(string str)
	    set_race(string r)
	    set_long(string lo)
	
	    set_wc(int wc)
	    set_ac(int ac)
	    set_hp(int hp)
	    set_ep(int ep)
	
	    set_str(int i)
	    set_int(int i)
	    set_con(int i)
	    set_dex(int i)
	
	    set_al(int al)
	    set_aggressivity(int a)
	    set_wimpyness(int w)
	    set_gender(int g)	
	    set_attacks(mixed *all_attacks)
	    add_attack(string msg, mixed arg2, mixed arg3, mixed arg4)
	
	    set_chats(string *all_chats)
	    add_chat(string the_chat)
	    set_chat_chance(int percentage)
	    set_chat_in_fight(status f)
	
	    set_responses(mixed *all_responses)
	    add_response(string act, mixed response, mixed arg3, mixed arg4)
	    set_response_object(mixed obj)
	
	    set_say_handler(mixed obj, string fun)
	    set_tell_handler(mixed obj, string fun)
	    set_give_handler(mixed obj, string fun)
	    set_give_money_handler(mixed obj, string fun)
	    set_arrive_handler(mixed obj, string fun)
	    set_leave_handler(mixed obj, string fun)
	
	    set_fight_beat(object obj, string fun)
	    set_peace_beat(object obj, string fun)
	
	    set_friends(mixed *all_friends)
	    add_friend(mixed the_name)
	
	    set_soul()
	
	    set_move_at_reset()
	    set_random_pick(status r)
	    set_init_ob(mixed ob)
	
	
	12. Expanded stat format
	------------------------
	
	If you call show_stats() in a smartmonster, for example with the wizard
	command "stat", you will see some additional smartmonster-specific
	data, for example as in this output from "stat harry":
	
	    Harry the affectionate
	    level:  3
	    coins:  0
	    hp:     66 (max: 66)
	    spell   66 (max: 0)
	    ep:     1522
	    ac:     0
	    wc:     5
	    carry:  0
	    align:  50
	    gender: male
	    str: 3, int: 3, con: 3, dex: 3
	    age:    2 seconds.
	    Additional smartmonster data:
	      chat_data: 10 chats, chat_chance: 2, chat_in_fight: 0
	      say_handler: 'answer_say' in OBJ(room/vill_road2)
	      tell_handler: 'answer_say' in OBJ(room/vill_road2)
	      give_handler: 'handle_give' in OBJ(room/vill_road2)
	      give_money_handler: 'handle_give_money' in OBJ(room/vill_road2)
	      arrive_handler: 'say_hello' in OBJ(room/vill_road2)
	      leave_handler: 'follow' in OBJ(room/vill_road2)
	      handle_caught_texts = 1
	      Waiting texts from catch_tell(): 0
	      aggressivity: 0
	      attack_data: 9 attacks
	      friends: 0
	      response_data: 12 responses, response_object = OBJ(room/vill_road2)
	    Smartmonster responses:
	      'sells': '*why_did' - 100%
	      'attacks': '*why_did' - 100%
	      'left the game': '*why_did' - 100%
	      'takes': '*why_did' - 100%
	      'drops': '*why_did' - 100%
	      'is now level': '*how_does_it_feel' - 100%
	      'falls down laughing': 'Harry looks at the one who laughed.\n'
	        ('Harry looks at you.\n') - 100%
	      'bounces': ['!flip', '!smile'] - 100%
	      'sings': 'Harry says: You really have a nice voice!\n' - 50%
	      'sings': 'Harry tries to sing too.\n' - 50%
	      'sings': '!applaud' - 50%
	      'smiles happily': 'Harry smiles happily.\n' - 100%
	
	
	13. An example: Harry
	---------------------
	
	I have re-written /room/vill_road2.c (the room which defines Harry)
	to use the smartmonster.
	
	
	14. Incompatibilities with the old /obj/monster
	-----------------------------------------------
	
	In the old monster, when it called a function set up by "set_match",
	the value of this_player() usually was the monster object, but
	sometimes (rather randomly) it could be the object that sent the
	string the monster reacted to. In the smartmonster, the value of
	this_player() will always be the monster object.
	
	If you have a randomly moving monster (move_at_reset or wimpy),
	and rely on it going only in some directions, your code could fail.
	
	The percentages for attack-chats will not be quite right.
	
	If the monster object is inherited, and the functions in it
	are called in non-standard ways, I don't know what will happen.

Help topics available:
armour drinks food key monster
smartmonster weapon

[START|BACK ]




[ NannyMuds main page | FAQ | Contact us ]

You are guest number 148 since November 2019.
This file was last modified: June 2000.