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 |
You are guest number 148 since November 2019.
This file was last modified: June 2000.