** LambdaMOO Database, Format Version 4 ** 185 2309 0 4 2 71 36 38 #0 The System Object 24 2 -1 -1 -1 1 -1 7 22 do_login_command 2 173 -1 server_started 2 173 -1 core_objects 2 173 -1 init_for_core 2 173 -1 user_created user_connected 2 173 -1 user_disconnected user_client_disconnected 2 173 -1 bf_chparent 2 173 -1 bf_add_verb 2 173 -1 bf_add_property 2 173 -1 bf_recycle 2 173 -1 user_reconnected 2 173 -1 bf_set_verb_info 2 173 -1 do_out_of_band_command doobc 2 173 -1 do_command 2 173 -1 bf_match match 2 173 -1 bf_rmatch rmatch 2 173 -1 handle_uncaught_error 2 173 -1 bf_force_input 2 173 -1 moveto 2 173 -1 bf_set_property_info set_property_info 2 173 -1 checkpoint_started 2 173 -1 checkpoint_finished 2 173 -1 209 builder login last_huh guest_log last_restart_time biglist big_mail_recipient limbo registration_db new_player_log verb_help core_help prog_help wiz_help shutdown_task wiz_utils site_db math_utils set_utils builtin_function_help new_prog_log generic_help guest seq_utils quota_log you max_seconds max_ticks hacker generic_db shutdown_message shutdown_time no_one player_db class_registry player_class gender_utils trig_utils time_utils editor_help mail_recipient mail_agent mail_editor note_editor verb_editor generic_editor match_utils object_utils lock_utils gripe_recipients letter dump_interval list_utils command_utils player wiz prog code_utils help nothing failed_match ambiguous_match perm_utils building_utils string_utils news note container thing exit room player_start root_class recycler garbage mail_options edit_options display_options generic_options maxint minint error newt_log toad_log site_log housekeeper network generic_biglist_home feature local gopher prog_options build_options mail_name_db generic_utils quota_utils paranoid_db no_connect_message sysobj byte_quota_utils object_quota_utils server_options warehouse builder_help mail_help ftp password_verifier new_password_log frand_class mail_recipient_class pasting_feature core_history matrix_utils ansi_help ansi_pc ansi_utils ansi_options scheduler rpgamer reaper_feature reaper feature_warehouse subthing money_utils rpg_room rpg_objects_help monster homer weapon hand claw teeth collective ammo death_purse puppet clothing veroom terrain terrexit cuffs medkit rp_regulator rp_note social_feature dead_zone default_holder lang_utils lang light realm lobby food1 food2 temple sales_bot display_room replicating_monster breeder_relay breeder frand_help booth chargen default_lang channels puppet_strings edu_stds school special_warehouse default_item_home local_chargen rpg_help cursed_artifact healing_orb scroll_of_healing magic_item_warehouse book_of_healing tome_of_healing scroll_of_knowledge book_of_knowledge tome_of_knowledge scroll_of_enchantment book_of_enchantment tome_of_enchantment scroll_of_sleep book_of_sleep tome_of_sleep scroll_of_death book_of_death tome_of_death quest_social_feature scroll_of_magic_missile book_of_magic_missile tome_of_magic_missile scroll_of_escape book_of_escape tome_of_escape scroll_of_fear book_of_fear tome_of_fear scroll_of_power book_of_power tome_of_power scroll_of_speed book_of_speed tome_of_speed scroll_of_pacifism book_of_pacifism tome_of_pacifism 213 1 4 2 5 1 10 2 1 1 11 2 1 1 12 2 1 0 1541645798 2 5 1 13 2 5 1 14 2 5 1 15 2 5 1 16 2 5 1 17 2 5 1 18 2 5 1 19 2 5 1 22 2 5 1 23 2 5 3 0 2 5 1 24 2 5 1 25 2 5 1 26 2 5 1 27 2 5 1 28 2 5 1 29 2 5 1 30 2 5 1 31 2 1 1 33 2 5 1 34 2 5 1 35 36 1 0 5 2 5 0 30000 2 5 1 36 2 5 1 37 2 5 2 Bel (#2): 1 Name change 2 5 0 1537082538 2 5 1 38 2 1 1 39 2 1 4 2 4 3 2 generics 2 Generic objects intended for use as the parents of new objects 4 40 1 3 1 7 1 5 1 9 1 54 1 8 1 1 1 6 1 58 1 57 1 50 1 45 1 46 1 107 1 108 1 109 1 110 1 113 1 114 1 116 1 117 1 118 1 119 1 121 1 122 1 120 1 123 1 127 1 128 1 129 1 130 1 131 1 132 1 133 1 134 1 135 1 136 1 137 1 138 1 140 4 3 2 utilities 2 Objects holding useful general-purpose verbs 4 22 1 20 1 55 1 24 1 27 1 41 1 26 1 43 1 51 1 52 1 53 1 56 1 42 1 21 1 33 1 13 1 80 1 82 1 59 1 93 1 32 1 103 1 125 2 5 1 91 2 5 1 41 2 1 1 26 2 5 1 43 2 5 1 44 2 5 1 45 2 5 1 46 2 5 1 47 2 5 1 48 2 5 1 49 2 5 1 50 2 5 1 51 2 5 1 52 2 5 1 53 2 5 4 1 1 2 2 5 1 54 2 5 0 3600 2 5 1 55 2 5 1 56 2 5 1 6 2 5 1 57 2 5 1 58 2 5 1 59 2 5 1 60 2 5 1 -1 2 5 1 -3 2 5 1 -2 2 5 1 42 2 5 1 21 2 5 1 20 2 5 1 61 2 5 1 9 2 5 1 8 2 5 1 5 2 5 1 7 2 5 1 3 2 5 1 62 2 5 1 1 2 5 1 63 2 5 1 64 2 5 1 65 2 5 1 66 2 5 1 67 2 5 1 68 2 5 0 2147483647 2 5 0 -2147483648 2 5 1 69 2 5 1 70 2 5 1 70 2 5 1 70 2 5 1 71 2 5 1 72 2 5 1 73 2 1 1 74 2 5 1 -1 2 5 1 75 2 1 1 76 2 5 1 77 2 5 1 78 2 5 1 79 2 5 1 80 2 5 1 81 2 1 0 0 2 5 1 0 2 1 1 80 2 5 1 82 2 5 1 83 2 5 1 84 2 1 1 85 2 1 1 86 2 1 1 87 2 5 1 88 2 1 1 89 2 1 1 90 2 5 1 40 2 5 1 92 2 5 4 4 4 3 2 rpgcore 2 1.1 0 -1090650498 4 3 2 rpgcore 2 1.0 0 -1091292219 4 3 2 nefandous 2 1.8.0p6 0 -1119114251 4 3 2 LambdaMOO 2 1.8.0p5 0 854992537 2 1 1 93 36 1 1 96 2 1 1 95 2 1 1 32 2 1 1 97 2 1 1 99 2 1 1 91 2 1 1 100 2 1 1 2 2 5 1 101 2 1 1 102 2 1 1 103 2 1 1 104 2 1 1 106 2 1 1 107 2 1 1 108 2 1 1 109 2 1 1 182 2 1 1 183 2 1 1 184 2 1 1 113 2 1 1 114 2 1 1 115 2 1 1 116 2 1 1 117 2 1 1 118 2 1 1 119 2 1 1 121 2 1 1 122 2 1 1 120 2 1 1 98 2 1 1 123 2 1 1 124 2 1 1 146 2 5 1 36 2 5 1 125 2 1 1 126 2 1 1 127 2 1 1 128 2 1 1 130 2 1 1 131 2 1 1 132 2 1 1 133 2 1 1 134 2 1 1 135 2 1 1 136 2 1 1 137 2 1 1 138 2 1 1 139 2 1 1 140 2 1 1 141 2 1 1 142 2 1 1 143 2 1 1 144 2 1 1 163 2 1 1 129 2 1 1 179 2 5 1 180 2 5 1 178 2 5 1 105 2 5 1 177 2 5 1 175 2 5 1 110 2 5 1 176 2 5 1 111 2 5 1 112 2 5 1 122 2 5 1 136 2 5 1 145 2 5 1 147 2 5 1 148 2 5 1 149 2 5 1 150 2 5 1 151 2 5 1 152 2 5 1 153 2 5 1 154 2 5 1 155 2 5 1 578 2 5 1 156 2 5 1 157 2 5 1 158 2 5 1 159 2 5 1 160 2 5 1 161 2 5 1 162 2 5 1 164 2 5 1 165 2 5 1 166 2 5 1 167 2 5 1 168 2 5 1 169 2 5 1 170 2 5 1 171 2 5 1 172 2 5 1 173 2 5 1 174 2 5 5 2 4 4 1 2 The System Object 2 5 2 The known universe. 2 5 4 2 0 30704 0 1539462952 36 1 #1 Root Class 152 2 -1 -1 -1 -1 3 -1 38 initialize 2 173 -1 recycle 2 173 -1 set_name 2 173 -1 title 2 173 -1 titlec 2 173 -1 set_aliases 2 173 -1 match 2 173 -1 match_object 2 173 -1 set_description 2 173 -1 description 2 173 -1 look_self 2 173 -1 notify 2 173 -1 tell 2 173 -1 tell_lines 2 173 -1 accept 2 173 -1 moveto 2 173 -1 eject eject_nice eject_basic 2 173 -1 is_unlocked_for 2 173 -1 huh 2 173 -1 set_message 2 173 -1 do_examine 2 173 -1 examine_key 2 173 -1 examine_names 2 173 -1 examine_desc 2 173 -1 examine_contents 2 173 -1 examine_verbs 2 173 -1 get_message 2 173 -1 room_announce*_all_but 2 173 -1 init_for_core 2 173 -1 contents 36 173 -1 examine_verb_ok 2 173 -1 is_listening 2 173 -1 hidden_verbs 2 173 -1 examine_owner 2 173 -1 announce*_all_but 2 173 -1 tell_lines_suspended 2 173 -1 acceptable 2 173 -1 help_msg 2 173 -1 4 key aliases description object_size 4 0 0 2 4 4 0 2 5 2 2 5 4 2 0 22305 0 1539462952 36 1 #2 Wizard 7 2 62 181 -1 57 -1 -1 0 2 mcd_save test 148 4 2 4 164 1 0 1 2 1 4 1 10 1 11 1 12 1 13 1 14 1 15 1 16 1 17 1 18 1 19 1 22 1 23 1 24 1 25 1 26 1 27 1 28 1 29 1 30 1 31 1 33 1 34 1 35 1 36 1 37 1 38 1 39 1 91 1 41 1 43 1 44 1 45 1 46 1 47 1 48 1 49 1 50 1 51 1 52 1 53 1 54 1 55 1 56 1 6 1 57 1 58 1 59 1 60 1 42 1 21 1 20 1 61 1 9 1 8 1 5 1 7 1 3 1 62 1 1 1 63 1 64 1 65 1 66 1 67 1 68 1 69 1 70 1 71 1 72 1 73 1 74 1 75 1 76 1 77 1 78 1 79 1 80 1 81 1 82 1 83 1 84 1 85 1 86 1 87 1 88 1 89 1 90 1 40 1 92 1 93 1 96 1 95 1 32 1 97 1 99 1 100 1 101 1 102 1 103 1 104 1 105 1 106 1 107 1 108 1 109 1 110 1 111 1 112 1 113 1 114 1 115 1 116 1 117 1 118 1 119 1 121 1 122 1 120 1 98 1 123 1 124 1 125 1 126 1 127 1 128 1 130 1 131 1 132 1 133 1 134 1 135 1 136 1 137 1 138 1 139 1 140 1 141 1 142 1 143 1 144 1 145 1 146 1 147 1 148 1 149 1 150 1 151 1 152 1 153 1 154 1 155 1 156 1 157 1 158 1 159 1 160 1 161 1 162 1 167 1 129 1 94 4 170 2 builder 2 login 2 last_huh 2 guest_log 2 biglist 2 big_mail_recipient 2 limbo 2 registration_db 2 new_player_log 2 verb_help 2 core_help 2 prog_help 2 wiz_help 2 wiz_utils 2 site_db 2 math_utils 2 set_utils 2 builtin_function_help 2 new_prog_log 2 generic_help 2 guest 2 seq_utils 2 quota_log 2 you 2 hacker 2 generic_db 2 no_one 2 player_db 2 player_class 2 gender_utils 2 trig_utils 2 time_utils 2 editor_help 2 mail_recipient 2 mail_agent 2 mail_editor 2 note_editor 2 verb_editor 2 generic_editor 2 match_utils 2 object_utils 2 lock_utils 2 letter 2 list_utils 2 command_utils 2 player 2 wiz 2 prog 2 code_utils 2 help 2 perm_utils 2 building_utils 2 string_utils 2 news 2 note 2 container 2 thing 2 exit 2 room 2 player_start 2 root_class 2 recycler 2 garbage 2 mail_options 2 edit_options 2 display_options 2 generic_options 2 error 2 newt_log 2 toad_log 2 site_log 2 housekeeper 2 network 2 generic_biglist_home 2 feature 2 gopher 2 prog_options 2 build_options 2 mail_name_db 2 generic_utils 2 quota_utils 2 paranoid_db 2 sysobj 2 byte_quota_utils 2 object_quota_utils 2 server_options 2 warehouse 2 builder_help 2 mail_help 2 ftp 2 password_verifier 2 new_password_log 2 frand_class 2 mail_recipient_class 2 pasting_feature 2 matrix_utils 2 ansi_help 2 ansi_pc 2 ansi_utils 2 ansi_options 2 scheduler 2 rpgamer 2 reaper_feature 2 reaper 2 feature_warehouse 2 subthing 2 money_utils 2 rpg_room 2 rpg_help 2 rpg_objects_help 2 monster 2 homer 2 weapon 2 hand 2 claw 2 teeth 2 collective 2 ammo 2 death_purse 2 puppet 2 clothing 2 veroom 2 terrain 2 terrexit 2 cuffs 2 medkit 2 rp_regulator 2 rp_note 2 social_feature 2 dead_zone 2 default_holder 2 lang_utils 2 lang 2 light 2 realm 2 lobby 2 food1 2 food2 2 temple 2 sales_bot 2 display_room 2 replicating_monster 2 breeder_relay 2 breeder 2 frand_help 2 booth 2 chargen 2 default_lang 2 channels 2 puppet_strings 2 rmprop_demo_1 2 rmprop_demo_2 2 rmprop_demo_3 2 rmprop_demo_4 2 rmprop_demo_5 2 rmprop_demo_6 2 rmprop_demo_7 2 rmprop_demo_8 2 rmprop_demo_9 2 rmprop_demo_10 2 rmprop_demo_11 2 rmprop_demo_12 2 rmprop_demo_13 2 rmprop_demo_14 2 rmprop_demo_15 2 rmprop_demo_16 2 rmprop_demo_17 2 rmprop_demo_18 2 edu_stds 2 school 2 1 2 gtolxnoqEgK5s 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 4 5 2 5 5 36 1 5 36 1 5 36 1 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 0 0 36 1 5 2 5 5 2 5 5 2 5 5 2 5 0 1 36 1 0 1 36 1 0 1 36 1 1 182 36 1 1 365 36 1 5 36 1 1 -1 36 1 1 -1 36 1 9 0.002550000000000000183 36 1 4 2 4 4 2 Strength 2 Dexterity 2 Intelligence 2 Health 4 4 9 10.00040000000000084 9 10 9 10.00008000000000052 9 10 36 1 4 2 4 4 2 Strength 2 Dexterity 2 Intelligence 2 Health 4 4 9 10.00040000000000084 9 10 9 10.00008000000000052 9 10 36 1 4 2 4 3 2 combat 2 medical 2 language 4 3 9 0 9 0 9 0 36 1 2 Human 36 1 5 36 1 4 1 4 2 2 gold 9 32 36 1 5 2 5 5 2 5 1 -1 36 1 4 2 4 2 1 142 1 198 4 2 9 2.000559016994374772 9 2 36 1 1 142 36 1 4 13 4 2 1 2 2 Wizard 4 2 1 201 2 Savo 4 2 1 202 2 Elder Minko 4 2 1 206 2 Avda 4 2 1 196 2 Beskh 4 2 1 242 2 Mero 4 2 1 432 2 Chokh 4 2 1 552 2 Veza 4 2 1 557 2 Zhan 4 2 1 615 2 Zwat 4 2 1 617 2 Khoda 4 2 1 365 2 Sai'lax 4 2 1 737 2 Garoz 36 1 2 a male elf wizard 36 1 4 0 2 5 0 0 2 5 0 0 2 7 0 0 2 5 0 0 2 5 0 1 2 5 0 0 2 5 0 6 2 5 0 0 2 5 0 0 2 5 2 Blue Mage 2 5 0 0 2 5 0 0 2 5 0 2130143452 2 5 4 0 2 4 5 2 5 5 2 1 5 2 5 4 1 2 netmail 2 5 5 2 5 4 0 2 5 4 8 0 2 0 1536870082 4 3 1 17 0 0 0 0 4 3 1 29 0 1 0 1538781269 4 3 1 34 0 0 0 0 4 3 1 70 0 1 0 1539465872 4 3 1 89 0 1 0 1538619537 4 3 1 61 0 0 0 -1090650498 2 4 4 0 2 4 4 5 2 bold 2 blinking 2 misc 2 extra 2 colors 36 1 4 20 2 bold 2 unbold 2 bright 2 unbright 2 normal 2 red 2 green 2 yellow 2 blue 2 purple 2 cyan 2 gray 2 grey 2 magenta 2 white 2 underline 2 inverse 2 blink 2 unblink 2 beep 36 1 4 6 1 92 1 143 1 99 1 100 1 98 1 144 36 1 4 2 0 1541645812 2 localhost 2 0 2 2 0 0 1541645911 2 1 0 0 2 5 5 2 5 5 36 1 5 36 1 5 36 0 5 36 1 4 98 1 0 1 1 1 2 1 3 1 4 1 5 1 6 1 7 1 8 1 9 1 10 1 11 1 12 1 15 1 20 1 21 1 22 1 24 1 29 1 34 1 42 1 52 1 53 1 54 1 56 1 57 1 58 1 70 1 72 1 75 1 79 1 83 1 87 1 88 1 89 1 94 1 98 1 99 1 100 1 102 1 108 1 113 1 115 1 118 1 119 1 121 1 123 1 124 1 125 1 126 1 135 1 144 1 163 1 146 1 179 1 191 1 197 1 347 1 415 1 371 1 391 1 501 1 325 1 321 1 372 1 378 1 162 1 460 1 442 1 518 1 449 1 539 1 420 1 513 1 435 1 579 1 629 1 583 1 299 1 565 1 525 1 499 1 575 1 439 1 574 1 592 1 394 1 626 1 548 1 493 1 489 1 559 1 554 1 418 1 181 1 182 1 183 1 184 2 1 0 -79 36 1 1 70 2 4 4 16 2 localhost 2 97-127-225-155.dvnp.qwest.net 2 65-103-81-203.dvnp.qwest.net 2 ip-66-87-142-191.omahne.spcsdns.net 2 ip-66-87-143-222.omahne.spcsdns.net 2 ip-66-87-143-46.omahne.spcsdns.net 2 ip-66-87-143-114.omahne.spcsdns.net 2 ip-66-87-142-242.omahne.spcsdns.net 2 ip-66-87-143-72.omahne.spcsdns.net 2 97-127-210-220.dvnp.qwest.net 2 174-22-102-18.dvnp.qwest.net 2 174-22-104-235.dvnp.qwest.net 2 ip-66-87-143-55.omahne.spcsdns.net 2 ip-66-87-143-104.omahne.spcsdns.net 2 ip-66-87-142-169.omahne.spcsdns.net 2 ip-66-87-142-236.omahne.spcsdns.net 2 0 2 port 2222 from localhost, port 51033 2 0 5 2 5 5 2 4 5 2 5 2 his 2 5 2 His 2 5 5 2 5 5 2 5 5 2 5 0 1541645916 2 1 0 -10000 36 0 2 male 2 5 2 Himself 2 5 2 His 2 5 2 Him 2 5 2 He 2 5 2 himself 2 5 2 his 2 5 2 him 2 5 2 he 2 5 1 62 2 5 0 0 2 0 5 2 5 5 2 5 5 2 5 5 2 5 0 1529432722 2 1 4 4 0 2500000 0 979260 0 1539462952 0 155 36 0 0 1539467533 2 0 5 2 0 5 2 1 5 36 1 0 1 2 5 5 2 1 9 0.5 2 1 0 2 36 1 0 1 36 1 4 1 4 2 2 Vrel 2 [bold][green][underline]Vrel[normal] 36 1 5 36 1 5 2 5 0 0 2 4 4 1 2 Wizard 2 1 2 2 5 4 2 0 12697 0 1539462952 36 1 #3 generic room 152 2 -1 -1 -1 1 50 0 45 confunc 2 173 -1 disfunc 2 173 -1 say 2 85 -2 emote 2 93 -2 announce 2 173 -1 match_exit 2 173 -1 add_exit 2 173 -1 tell_contents 2 173 -1 @exits 2 13 -1 look_self 2 173 -1 acceptable 2 173 -1 add_entrance 2 173 -1 bless_for_entry 2 173 -1 @entrances 2 9 -1 go 2 93 -2 l*ook 2 93 -2 announce_all 2 173 -1 announce_all_but 2 173 -1 enterfunc 2 173 -1 exitfunc 2 173 -1 remove_exit 2 173 -1 remove_entrance 2 173 -1 @add-exit 2 25 -1 @add-entrance 2 25 -1 recycle 2 173 -1 e east w west s south n north ne northeast nw northwest se southeast sw southwest u up d down out exit o 2 13 -1 @eject @eject! @eject!! 2 25 -1 ejection_msg oejection_msg victim_ejection_msg 36 173 -1 accept_for_abode 2 173 -1 @resident*s 2 25 -1 match 2 173 -1 @remove-exit 2 25 -1 @remove-entrance 2 25 -1 moveto 2 173 -1 who_location_msg 2 173 -1 exits entrances 2 173 -1 obvious_exits obvious_entrances 2 173 -1 here_huh 2 173 -1 room_announce*_all_but 2 173 -1 examine_commands_ok 2 173 -1 examine_key 2 173 -1 examine_contents 2 173 -1 free_entry 36 173 -1 dark 2 173 -1 -* `* 2 93 -2 13 who_location_msg free_home victim_ejection_msg ejection_msg oejection_msg residents free_entry entrances blessed_object blessed_task exits dark ctype 17 2 %T 2 5 0 0 2 5 2 You have been expelled from %i by %n. 2 5 2 You expel %d from %i. 2 5 2 %N unceremoniously %{!expels} %d from %i. 2 5 4 0 2 5 0 1 2 5 4 0 2 4 1 -1 2 5 0 0 2 5 4 0 2 4 0 0 2 5 0 3 2 5 5 2 4 4 1 2 generic room 2 5 5 2 5 4 2 0 29054 0 1539462952 36 1 #4 generic builder 144 2 -1 -1 -1 90 58 -1 36 @quota 2 25 -1 @create 2 89 -2 @recycle 2 25 -1 @recreate 2 89 13 @dig 2 89 -2 @audit 2 89 -2 @count 2 25 -1 @countDB 2 25 -1 @sort-owned*-objects 2 25 -1 @add-owned 2 25 -1 @verify-owned 2 9 -1 @unlock 2 25 -1 @lock 2 89 0 @newmess*age 2 89 -2 @unmess*age 2 89 -2 _messagify 2 173 -1 @kids 2 29 -1 @contents 2 25 -1 @par*ents 2 25 -1 @location*s 2 25 -1 @cl*asses 2 89 -2 classes_2 2 173 -1 _create 2 173 -1 _recycle 2 173 -1 @chparent 2 89 1 @check-chp*arent 2 89 1 @set*prop 2 89 1 build_option 2 173 -1 set_build_option 2 173 -1 @build-o*ptions @buildo*ptions @builder-o*ptions @buildero*ptions 2 89 -2 @measure 36 89 -2 init_for_core 2 173 -1 @botl*ock 2 93 -2 @retail 2 93 -2 @dark 2 93 -2 @sanc*tuary 2 93 -2 1 build_options 132 4 1 4 2 2 dig_room 1 118 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 5 5 2 5 5 2 5 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 5 36 1 9 1.362499999999990052 36 1 4 2 4 4 2 Strength 2 Dexterity 2 Intelligence 2 Health 4 4 9 20 9 20 9 20 9 20 36 1 4 2 4 4 2 Strength 2 Dexterity 2 Intelligence 2 Health 4 4 9 20 9 20 9 20 9 20 36 1 4 2 4 3 2 combat 2 medical 2 language 4 3 9 5 9 5 9 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 5 5 36 1 4 2 4 1 1 142 4 1 9 2 36 1 5 36 1 4 0 36 1 2 36 1 5 2 5 5 2 5 5 2 7 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 4 5 2 5 5 2 1 5 2 5 4 0 2 5 5 2 5 5 2 5 4 2 0 0 0 -1300000000 2 4 5 2 4 5 36 1 5 36 1 5 36 1 5 2 0 5 2 0 5 2 1 4 2 1 85 1 106 2 5 5 2 5 5 36 1 5 36 1 5 36 0 5 36 1 5 2 1 5 36 1 5 2 4 5 2 0 5 2 0 5 2 5 5 2 4 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 1 0 0 36 0 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 1 62 2 5 5 2 0 5 2 5 5 2 5 5 2 5 5 2 5 5 2 1 5 36 0 5 2 0 5 2 0 5 2 1 5 36 1 5 2 5 5 2 1 5 2 1 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 4 4 1 2 generic builder 2 1 2 You see a player who should type '@describe me as ...'. 2 5 4 2 0 39044 0 1539462952 36 1 #5 generic thing 152 2 -1 -1 -1 102 9 6 6 g*et t*ake 2 45 -1 dr*op th*row 2 45 -1 moveto 2 173 -1 take_failed_msg take_succeeded_msg otake_failed_msg otake_succeeded_msg drop_failed_msg drop_succeeded_msg odrop_failed_msg odrop_succeeded_msg 2 173 -1 gi*ve ha*nd 2 109 1 examine_key 2 173 -1 8 drop_failed_msg drop_succeeded_msg odrop_failed_msg odrop_succeeded_msg otake_succeeded_msg otake_failed_msg take_succeeded_msg take_failed_msg 19 2 You can't seem to drop %t here. 2 5 2 You drop %t. 2 5 2 tries to drop %t but fails! 2 5 2 drops %t. 2 5 2 picks up %t. 2 5 2 2 5 2 You take %t. 2 5 2 You can't pick that up. 2 5 5 2 1 5 2 1 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 4 4 1 2 generic thing 2 5 5 2 5 4 2 0 4899 0 1539462952 36 1 #6 generic player 152 2 -1 -1 -1 102 95 94 100 init_for_core 2 173 -1 confunc 2 173 -1 disfunc 2 173 -1 initialize 2 173 -1 acceptable 2 173 -1 my_huh 2 173 -1 last_huh 2 173 -1 my_match_object 2 173 -1 tell_contents 2 173 -1 titlec 2 173 -1 notify 2 173 -1 notify_lines 2 173 -1 linesplit 2 173 -1 linelen 36 173 -1 @more 2 25 -1 @wrap 36 9 -2 @linelen*gth 36 25 -1 @pagelen*gth 2 25 -1 tell 2 173 -1 gag_p 2 173 -1 set_gaglist 2 173 -1 @gag*! 2 89 -2 @listgag @gaglist @gagged 2 29 -1 @ungag 2 29 -1 whodunnit 2 173 -1 @ch*eck-full 2 89 -2 @paranoid 2 89 -2 @sw*eep 2 9 -1 wh*isper 2 157 1 page 2 93 -2 receive_page 2 173 -1 page_origin_msg page_echo_msg page_absent_msg 36 173 -1 i inv*entory 2 9 -1 look_self 2 173 -1 home 2 13 -1 @sethome 2 9 -1 g*et take 2 45 -1 @move @teleport @m 2 93 1 @eject @eject! @eject!! 2 89 5 where*is @where*is 2 93 -2 @who 2 93 -2 @wizards 2 29 -1 ?* help info*rmation @help 2 93 -2 display_option 2 173 -1 edit_option 2 173 -1 set_mail_option set_edit_option set_display_option 2 173 -1 @mailo*ptions @mail-o*ptions @edito*ptions @edit-o*ptions @displayo*ptions @display-o*ptions 2 89 -2 set_name 2 173 -1 set_aliases 2 173 -1 @rename*# 2 89 1 @addalias*# @add-alias*# 2 89 1 @rmalias*# @rm-alias*# 2 89 5 @desc*ribe 2 89 13 @mess*ages 2 25 -1 @notedit 36 25 -1 @last-c*onnection 2 29 -1 set_gender 2 173 -1 @gender 2 25 -1 set_brief 2 173 -1 @mode 2 89 -2 @exam*ine 2 29 -1 exam*ine 2 25 -1 add_feature 36 173 -1 remove_feature 36 173 -1 @add-feature @addfeature 2 29 -1 @remove-feature @rmfeature 2 29 -1 @features 2 93 11 @memory 36 9 -1 @version 36 9 -1 @uptime 36 9 -1 @quit 2 9 -1 examine_commands_ok 2 173 -1 is_listening 2 173 -1 moveto 2 173 -1 announce*_all_but 2 173 -1 linewrap 36 173 -1 @set-note-string @set-note-text 2 25 -1 verb_sub 2 173 -1 ownership_quota 2 173 -1 tell_lines 2 173 -1 @lastlog 2 29 -1 set_linelength 2 173 -1 set_pagelength 2 173 -1 set_home 2 173 -1 @registerme 2 89 -2 ctime 2 173 -1 @age 36 25 -1 news 2 29 -1 @edit 36 89 -2 erase_paranoid_data 2 173 -1 @move-new 2 89 -2 notify_lines_suspended 2 173 -1 _chparent 2 173 -1 @users 36 13 -1 @password 2 89 -2 recycle 2 173 -1 gc_gaglist 2 173 -1 @ping @idle 2 73 -2 _ping 2 173 -1 @unping @unidle 2 73 -2 47 features previous_connection email_address last_disconnect_time help more_msg linetask linesleft linebuffer pagelen owned_objects linelen current_folder all_connect_places last_connect_place brief lines page_absent_msg pq pqc page_origin_msg page_echo_msg edit_options last_connect_time ownership_quota gender prc ppc poc psc pr pp po ps home password gaglist paranoid display_options verb_subs first_connect_time size_quota last_password_time last_connect_attempt page_count_start_time ping_task infobar 58 4 0 36 1 0 0 2 0 2 2 0 0 0 2 1 0 0 2 5 2 *** More *** %n lines left. Do @more [rest|flush] for more. 2 5 4 2 0 0 0 0 36 1 0 0 36 1 4 0 36 0 0 0 36 1 4 0 2 1 0 -79 36 1 0 1 2 4 4 0 2 0 2 ? 2 0 0 0 2 5 0 0 2 4 2 %N is not currently logged in. 2 5 2 its 2 5 2 Its 2 5 2 You sense that %n is looking for you in %l. 2 5 2 Your message has been sent. 2 5 4 0 2 5 0 0 2 1 0 0 36 0 2 neuter 2 5 2 Itself 2 5 2 Its 2 5 2 It 2 5 2 It 2 5 2 itself 2 5 2 its 2 5 2 it 2 5 2 it 2 5 1 62 2 5 2 impossible password to type 2 0 4 0 2 5 0 0 2 5 4 0 2 5 4 0 2 5 0 2147483647 2 1 4 4 0 25000 0 0 0 0 0 1 36 0 0 0 2 0 0 0 2 0 0 799707307 2 1 4 2 0 0 0 0 36 1 0 1 2 5 5 2 1 5 2 1 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 4 4 1 2 generic player 2 1 2 You see a player who should type '@describe me as ...'. 2 5 4 2 0 99005 0 1539462952 36 1 #7 generic exit 152 2 -1 -1 -1 1 121 46 13 invoke 2 173 -1 move 2 173 -1 recycle 2 173 -1 leave_msg oleave_msg arrive_msg oarrive_msg nogo_msg onogo_msg 2 173 -1 set_name 2 173 -1 set_aliases 2 173 -1 announce_all_but 2 173 -1 defaulting_oleave_msg 2 173 -1 moveto 2 173 -1 examine_key 2 173 -1 announce_msg 2 173 -1 look_self 2 173 -1 g*et t*ake 2 45 -1 9 obvious source dest nogo_msg onogo_msg arrive_msg oarrive_msg oleave_msg leave_msg 13 0 1 2 5 1 -1 2 5 1 -1 2 5 0 0 2 5 0 0 2 5 0 0 2 5 0 0 2 5 0 0 2 5 0 0 2 5 5 2 4 4 1 2 generic exit 2 5 5 2 5 4 2 0 7844 0 1539462952 36 1 #8 generic container 152 2 -1 -1 -1 5 84 132 15 p*ut in*sert dr*op 2 157 3 re*move ta*ke g*et 2 157 5 look_self 2 173 -1 acceptable 2 173 -1 open 2 45 -1 @lock_for_open 2 105 0 is_openable_by 2 173 -1 close 2 45 -1 @unlock_for_open 2 41 -1 tell_contents 2 173 -1 set_opened 2 173 -1 @opacity 2 105 12 set_opaque 2 173 -1 oclose_msg close_msg oopen_msg open_msg oput_fail_msg put_fail_msg oremove_fail_msg oremove_msg remove_fail_msg remove_msg oput_msg put_msg oopen_fail_msg open_fail_msg empty_msg 36 173 -1 dark 2 173 -1 19 oclose_msg close_msg oopen_msg open_msg oput_fail_msg put_fail_msg opaque dark oremove_fail_msg oremove_msg remove_fail_msg remove_msg oput_msg put_msg oopen_fail_msg open_fail_msg empty_msg opened open_key 38 2 closes %d. 2 5 2 You close %d. 2 5 2 opens %d. 2 5 2 You open %d. 2 5 2 2 5 2 You can't put %d in that. 2 5 0 1 2 1 0 1 2 1 2 2 5 2 removes %d from %i. 2 5 2 You can't remove that. 2 5 2 You remove %d from %i. 2 5 2 puts %d in %i. 2 5 2 You put %d in %i. 2 5 2 2 5 2 You can't open that. 2 5 2 It is empty. 2 5 0 0 2 1 0 0 2 4 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 1 5 2 1 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 4 4 1 2 generic container 2 5 5 2 5 4 2 0 9747 0 1539462952 36 1 #9 generic note 152 2 -1 -1 -1 5 54 63 11 r*ead 2 45 -1 er*ase 2 45 -1 wr*ite 2 157 4 del*ete rem*ove 2 153 5 encrypt 2 105 0 decrypt 2 41 -1 text 2 173 -1 is_readable_by 2 173 -1 set_text 2 173 -1 is_writable_by 2 173 -1 mailme @mailme 2 41 -1 3 writers encryption_key text 22 4 0 2 5 0 0 2 4 4 0 2 4 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 5 5 2 1 5 2 1 5 36 1 5 36 1 5 36 1 5 36 1 5 2 5 5 2 4 4 1 2 generic note 2 5 2 There appears to be some writing on the note ... 2 5 4 2 0 6412 0 1539462952 36 1 #10 Login Commands 16 2 -1 -1 -1 1 -1 68 44 ? 2 93 -1 wel*come @wel*come 2 93 -1 w*ho @w*ho 2 93 -1 co*nnect @co*nnect 2 93 -1 cr*eate @cr*eate 2 93 -1 q*uit @q*uit 2 93 -1 up*time @up*time 2 93 -1 v*ersion @v*ersion 2 93 -1 parse_command 2 173 -1 check_for_shutdown 2 173 -1 check_player_db 2 173 -1 _match_player 2 173 -1 notify 2 173 -1 tell 36 173 -1 player_creation_enabled 2 173 -1 newt_registration_string registration_string 2 173 -1 init_for_core 2 173 -1 special_action 2 164 -1 blacklisted graylisted redlisted spooflisted 2 173 -1 blacklist_add*_temp graylist_add*_temp redlist_add*_temp spooflist_add*_temp 2 173 -1 blacklist_remove*_temp graylist_remove*_temp redlist_remove*_temp spooflist_remove*_temp 2 173 -1 listname 2 173 -1 record_connection 2 173 -1 sample_lag 2 173 -1 is_lagging 2 173 -1 max_connections 2 173 -1 request_character 2 173 -1 req*uest @req*uest 2 93 -1 h*elp @h*elp 2 93 -1 maybe_print_lag 2 173 -1 current_lag 2 173 -1 maybe_limit_commands 2 173 -1 server_started 2 173 -1 uptime_since 2 173 -1 count_bg_players 2 173 -1 blacklisted_temp graylisted_temp redlisted_temp spooflisted_temp 2 173 -1 templist_expired 2 173 -1 temp_newt_registration_string 2 173 -1 add_interception 36 173 -1 delete_interception 36 173 -1 interception 36 173 -1 intercepted_password 2 173 -1 do_out_of_band_command doobc 36 173 -1 check_for_checkpoint 2 173 -1 39 welcome_message newt_registration_string registration_string registration_address create_enabled bogus_command blank_command graylist blacklist redlist who_masks_wizards max_player_name spooflist ignored max_connections connection_limit_msg lag_samples request_enabled help_message last_lag_sample lag_sample_interval boot_process lag_cutoff lag_exemptions newted current_connections current_numcommands max_numcommands temporary_newts downtimes print_lag current_lag temporary_blacklist temporary_redlist temporary_spooflist temporary_graylist intercepted_players intercepted_actions checkpoint_in_progress 43 4 6 2 Welcome to the Centrac QuestCore Database. Developed from RPGCore. 2 2 Type 'connect wizard' to login. Remember to set your password. 2 2 You may wish to modify this text, located in $login.welcome_message. 2 2 5 2 Your character is temporarily hosed. 2 5 2 Character creation is disabled. 2 5 2 2 5 0 1 2 5 2 ? 2 1 2 welcome 2 1 4 2 4 0 4 0 2 0 4 2 4 0 4 0 2 0 4 2 4 0 4 0 2 0 0 0 2 0 0 40 2 5 4 2 4 0 4 0 2 0 4 0 2 5 0 99999 36 5 2 *** The MOO is too busy! The current lag is %l; there are %n connected. WAIT FIVE MINUTES BEFORE TRYING AGAIN. 36 1 4 5 0 0 0 0 0 0 0 0 0 0 2 5 0 0 2 5 4 11 2 2 CENTRAC QUEST / LOGIN HELP 2 2 connect - Connect to an existing character. 2 create - Create a new character and set the password. 2 who - Displays a list of users currently connected. 2 uptime - Displays server uptime. 2 version - Displays server version information. 2 help - Displays this help text. 2 quit - Disconnect from the server. 2 2 5 0 0 2 5 0 15 2 5 0 0 2 5 0 5 2 5 4 0 2 5 4 0 2 0 4 1 1 -3 2 5 4 1 0 2 2 5 0 20 2 5 4 0 2 4 4 15 4 2 0 1541645798 0 0 4 2 0 1539532336 0 0 4 2 0 1539483702 0 0 4 2 0 1539462788 0 0 4 2 0 1539461476 0 0 4 2 0 1538781149 0 0 4 2 0 1538329585 0 0 4 2 0 1538262409 0 0 4 2 0 1537082664 0 0 4 2 0 1535158264 0 0 4 2 0 1534700487 0 0 4 2 0 1534383518 0 0 4 2 0 1534281909 0 0 4 2 0 1529536794 0 0 4 2 0 1529432124 0 0 2 5 0 0 2 5 0 6 2 1 4 2 4 0 4 0 2 0 4 2 4 0 4 0 2 0 4 2 4 0 4 0 2 0 4 2 4 0 4 0 2 0 4 0 36 0 4 0 36 0 0 0 2 5 5 2 4 4 1 2 Login Commands 2 5 2 This provides everything needed by #0:do_login_command. See `help $login' on $core_help for details. 2 5 4 2 0 41034 0 1539462952 36 1 #11 Player Last_huh Verbs 16 2 -1 -1 -1 1 -1 10 4 @* 2 173 -1 give hand 2 173 -1 get take 2 173 -1 drop throw 2 173 -1 0 4 5 2 4 4 1 2 Player Last_huh Verbs 2 5 2 A repository of last-resort player verbs to be called by $player:last_huh 2 5 4 2 0 4598 0 1539462952 36 1 #12 Guest Log 0 2 -1 -1 -1 1 -1 11 4 enter 2 173 -1 last 2 173 -1 init_for_core 2 173 -1 find 2 173 -1 2 connections max_entries 6 4 0 2 0 0 199 2 0 5 2 4 4 1 2 Guest Log 2 5 5 2 5 4 2 0 3738 0 1539462952 36 1 #13 Generic BigList Utilities 144 36 -1 -1 -1 79 -1 80 25 length 36 173 -1 find_nth 36 173 -1 find_ord 36 173 -1 set_nth 36 173 -1 kill 36 173 -1 insert_after insert_before 36 173 -1 extract_range 36 173 -1 delete_range 36 173 -1 keep_range 36 173 -1 insert_last 36 173 -1 start 36 173 -1 next 36 173 -1 _find_nth 36 173 -1 _find_ord 36 173 -1 _set_nth 36 173 -1 _skill 36 173 -1 _extract 36 173 -1 _merge 36 173 -1 _smerge 36 173 -1 _split 36 173 -1 _rmerge 36 173 -1 _scrunch 36 173 -1 _listfind_nth 36 173 -1 _insertfirst 36 173 -1 debug 36 173 -1 2 about maxfanout 7 4 15 2 Implementation notes 2 -------------------- 2 Each biglist is actually a tree (a kind of B-tree, actually). 2 The routines above pass around handles of the form 2 2 {root_node, size, leftmost_ord} 2 2 where root_node is the (string) name of a property that holds the root of the tree, size is the number of leaves in the tree, and leftmost_ord is the :_ord value of the leftmost element of the list (i.e., the leftmost leaf). 2 Each node property has a value of the form 2 2 {height,list of subtrees}. 2 2 where the each of the subtrees is itself a 3-element list as above unless 2 the height is 0, in which case the subtrees are actually biglist elements of the arbitrary form determined by the home object. 2 At every level, each node except the rightmost has between this.maxfanout/2 and this.maxfanout subtrees; the rightmost is allowed to have as few as 1 subtree. 36 5 0 7 36 5 4 73 2 Generic BigList Utilities 2 ---------------------------- 2 This is a package for maintaining huge persistent (sorted) lists in a format that is less likely to spam the server (which runs into a certain amount of trouble dealing with long ordinary lists --- btw we use `biglist' to refer to the huge data structure we're about to describe and `list' to refer to ordinary MOO lists {...}). The biglist in question lives on a particular object, to which we will refer in the discussion below as the `home' object, and its various elements appear as leaves of a tree whose nodes are kept in properties of the home object. It should be noted that the home object does not need to be (and in fact should *not* be) a descendant of this one; this object merely provides utilities for manipulating the properties on the home object that are used in a particular biglist manipulation. 2 2 All of the utilities below refer to `caller' to locate the home object. Thus verbs to manipulate a given biglist must be located on or inherited by its home object itself. The home object needs to define the following verbs 2 2 :_make(@args) => new property on home object with value args 2 :_kill(prop) delete a given property that was created by :_make 2 :_get(prop) => home.prop 2 :_put(prop,@args) set home.prop = args 2 :_ord(element) given something that is of the form of a biglist element 2 return the corresponding ordinal (for sorting purposes). 2 If you never intend to use :find_ord, then this can be a 2 routine that always returns 0 or some other random value. 2 2 See #5546 (Generic Biglist Resident) or $big_mail_recipient 2 for examples. 2 2 Those of the following routines that take a biglist argument are expecting 2 either {} (empty biglist) or some biglist returned by one of the other routines 2 2 :length(biglist) => length(biglist) (i.e., number of elements) 2 :find_nth(biglist,n) => biglist[n] 2 :find_ord(biglist,k,comp) => n where n is 2 the largest such that home:(comp)(k,home:_ord(biglist[n])) is false, or 2 the smallest such that home:(comp)(k,home:_ord(biglist[n+1])) is true. 2 Always returns a value between 0 and length(biglist) inclusive. 2 This assumes biglist to be sorted in order of increasing :_ord values 2 with respect to home:(comp)(). 2 Standard situation is :_ord returns a number and comp is a < verb. 2 2 :start(biglist,s,e) => {biglist[s..?],@handle} or {} 2 :next(@handle) => {biglist[?+1..??],@newhandle} or {} 2 These two are used for iterating over a range of elements of a biglist 2 The canonical incantation for doing 2 for elt in (biglist[first..last]) 2 ... 2 endfor 2 is 2 handle = :start(biglist,first,last); 2 while(handle) 2 for elt in (handle[1]) 2 ... 2 endfor 2 handle = :next(@listdelete(handle,1)); 2 endwhile 2 2 The following all destructively modify their biglist argument(s) L (and M). 2 2 :set_nth(L,n,value) => L[n] = value 2 replaces the indicated element 2 2 :insert_before(L,M,n) => {@L[1..n-1],@M,@L[n..length(L)]} 2 :insert_after (L,M,n) => {@L[1..n], @M,@L[n+1..length(L)]} 2 takes two distinct biglists, inserts one into the other at the given point 2 returns the resulting consolidated biglist 2 2 :extract_range(L,m,n) => {{@L[1..m-1],@L[n+1..]}, L[m..n]} 2 breaks the given biglist into two distinct biglists. 2 2 :delete_range(L,m,n[,leafkiller]) => {@L[1..m-1],@L[n+1..]} 2 :keep_range (L,m,n[,leafkiller]) => L[m..n] 2 like extract_range only we destroy what we don't want. 2 2 :insertlast(L,value) => {@L,value} 2 inserts a new element at the end of biglist. 2 If find_ord is to continue to work properly, it is assumed that the 2 home:_ord(elt) is greater (comp-wise) than all of the :_ord values 2 of elements currently in the biglist. 2 2 :kill(L[,leafkiller]) 2 destroys all nodes used by biglist. 2 Calls home:leafkiller on each element. 36 5 5 36 4 4 3 2 Generic BigList Utilities 2 ghblu 2 biglist_utils 36 1 4 1 2 This is the Generic BigList Utilities utility package. See `help $biglist' for more details. 36 5 4 2 0 24282 0 -1090650497 36 1 #14 Generic Large-Capacity Mail Recipient 144 36 -1 -1 -1 45 17 70 43 _genprop 36 173 -1 _make 2 173 -1 _kill 2 173 -1 _get 36 173 -1 _put 36 173 -1 _ord 36 173 -1 _makemsg 36 173 -1 _killmsg 36 173 -1 _message_num 36 173 -1 _message_date 36 173 -1 _message_hdr 36 173 -1 _message_text 36 173 -1 _lt_msgnum 36 173 -1 _lt_msgdate 36 173 -1 receive_batch 36 173 -1 receive_message 36 173 -1 messages_in_seq 36 173 -1 display_seq_headers 36 173 -1 display_seq_full 36 173 -1 list_rmm 36 173 -1 undo_rmm 36 173 -1 expunge_rmm 36 173 -1 rm_message_seq 36 173 -1 renumber 36 173 -1 length_all_msgs 36 173 -1 length_num_le 36 173 -1 length_date_le 36 173 -1 exists_num_eq 36 173 -1 new_message_num 36 173 -1 from_msg_seq 36 173 -1 %from_msg_seq 36 173 -1 to_msg_seq 36 173 -1 %to_msg_seq 36 173 -1 subject_msg_seq 36 173 -1 body_msg_seq 36 173 -1 date_sort 36 173 -1 _fix_last_msg_date 36 173 -1 __fix 36 173 -1 init_for_core 2 173 -1 length_date_gt 36 173 -1 _repair 2 165 -1 repair 2 41 -1 restore_from 2 173 -1 4 summary_uses_body _mgr mowner _genprop 26 0 0 36 5 1 13 36 5 1 36 36 1 2 36 1 5 36 5 0 0 36 1 5 36 5 5 36 5 5 36 5 5 36 5 5 36 5 5 36 1 5 36 1 5 36 1 5 36 1 4 0 36 5 5 36 5 5 36 5 5 36 1 5 36 5 5 36 5 5 36 5 5 36 4 4 1 2 Generic Large-Capacity Mail Recipient 36 1 4 41 2 Generic Large Capacity Mail Recipient 2 ------------------------------------- 2 Since any modifications to large lists entail copying the entire list over, operations on ordinary mail recipients having large numbers of messages, that actually change the content of .messages will take inordinately long. Thus we have this version which makes use of the $biglist package, scattering the messages onto numerous properties so that write operations involving only a few messages will not require recopying of the entire list. 2 2 In nearly all respects it behaves as the ordinary Mail Recipient, except that it is faster for certain kinds of operations. 2 2 Certain unimplemented verbs, like :date_sort(), and :messages() currently return E_VERBNF. 2 2 To convert an existing $mail_recipient-child (call it #MR) into a $big_mail_recipient-child the basic procedure is 2 2 ;;something.foo= #MR:messages(); 2 @rmm 1-$ from #MR 2 @unrmm expunge 2 @chparent #MR to $big_mail_recipient 2 ;#MR:receive_batch(@something.foo); 2 2 Reconstructing Damaged Big Mail Recipients 2 ------------------------------------------ 2 On rare occasions, the tree structure created by $biglist can be corrupted (this can happen on lists sufficiently large that a list-modification operation (e.g., @rmm, @renumber) runs out of ticks/seconds). In the vast majority of such cases, your messages are all still there; it's simply that the tree we use for finding/searching them is messed up. 2 2 To recover messages from a damaged big mail recipient (#DBMR) 2 --- read to the end before you start typing any commands --- 2 2 create a fresh $big_mail_recipient (#NEWBMR) and then do the following: 2 2 ;#NEWBMR:restore_from(#DBMR) 2 2 When this finishes, #NEWBMR will contain all of the mail messages we were able to find. (note that this will include messages that you had deleted from #DBMR but not expunged). #NEWMBR should thenceforth be useable in place of #DBMR, however if #DBMR contains custom verbs and non-clear properties, these will also need to be copied over. 2 2 Alternatively, one may do 2 2 @copyobject #DBMR to #TEMPBMR 2 ;#DBMR:restore_from(#TEMPBMR) 2 2 to rebuild #DBMR in place. This, however, will take about twice as long. 2 2 oooooooooooooooooooooooooooooooo 2 WARNING!!! WARNING!!! WARNING!!! 2 oooooooooooooooooooooooooooooooo 2 2 Calling #OBJ:restore_from(...) COMPLETELY AND IRREVOCABLY REMOVES ALL MESSAGES from the object that it is run on (#OBJ); you MUST be sure to EITHER have made a copy of #OBJ OR be doing the restore to a DIFFERENT object. 36 5 4 2 0 40391 0 -1090650497 36 1 #15 Limbo 16 2 -1 -1 -1 1 -1 73 5 acceptable 2 173 -1 confunc 2 173 -1 who_location_msg 36 173 -1 moveto 36 173 -1 eject 2 173 -1 0 4 5 2 4 4 2 2 Limbo 2 The Body Bag 2 5 5 2 5 4 2 0 2203 0 1539462952 36 1 #16 Registration Database 0 36 -1 -1 -1 37 -1 78 8 find* _only* _every* 36 173 -1 add 36 173 -1 init_for_core 2 173 -1 suspicious_address 2 173 -1 suspicious_userid 2 173 -1 describe_registration 2 173 -1 prune 2 173 -1 report_prune_progress 2 173 -1 6 registrar prune_progress prune_stop total_pruned_people total_pruned_characters prune_task 13 1 2 36 5 2 zzz 36 5 2 zzz 36 5 0 22967 36 5 0 470 36 5 0 1766597976 36 5 2 36 5 5 36 1 4 4 2 2 4 0 4 0 36 0 5 36 4 4 1 2 Registration Database 36 5 5 36 5 4 2 0 8728 0 -1090650497 36 1 #17 Player Creation Log 0 36 46 -1 29 14 -1 -1 5 display_seq_headers 2 173 -1 msg_summary_line 2 173 -1 init_for_core 2 173 -1 is_usable_by 2 173 -1 expire_old_messages 36 13 -1 0 26 0 1 36 5 1 13 36 5 1 36 36 1 2 36 1 5 36 5 0 0 36 1 4 0 36 5 4 1 1 17 36 5 5 36 5 5 36 5 5 36 5 4 1 1 2 36 1 4 0 36 1 5 36 1 5 36 1 4 0 36 5 5 36 5 5 36 5 5 36 1 5 36 5 5 36 5 5 36 5 0 0 36 4 4 2 2 Player Creation Log 2 PCL 36 1 2 Log of player creations. 36 5 4 2 0 3894 0 -1090650497 36 1 #18 Verb Help DB 16 36 -1 -1 -1 1 -1 12 3 find_topics 36 173 -1 get_topic 2 173 -1 dump_topic 2 173 -1 1 help_msg 5 4 23 2 This is not a help database in the same way that children of $generic_help are. This object does the work when someone calls help in this way: 2 2 help : 2 2 It parses out the object and verb reference, pulls out the comments at the beginning of the verb, and returns them to the help system for nice display. 2 2 :find_topics(string) 2 tries to pull out an object:verb reference from string 2 returns {string} if successful 2 returns {} if not 2 2 :get_topic(string) 2 tries to pull out an object:verb reference from string (returns 0 if 2 it fails to do so) 2 tries to match the object 2 checks the object to see if the verb exists 2 pulls out the initial comments from the verb if they exist 2 returns a meaningful list of strings to be displayed to the player 2 2 :dump_topic(string) 2 does the same as :get_topic above, but returns the verb documentation 2 in dump form. 2 ---- 36 5 5 36 4 4 3 2 Verb Help DB 2 verbhelp 2 vh 36 5 2 A `help database' that knows about all of the documented verbs. 36 5 4 2 0 4695 0 -1090650497 36 1 #19 Core Utility Help 16 36 -1 -1 -1 30 -1 85 3 find_topics 36 173 -1 get_topic 36 173 -1 dump_topic 2 173 -1 40 $login $container $mail_agent MR-subscribing MR-naming MR-access $mail_recipient receiving-mail mail-format mail-resolve sending-mail mail-system $player_db core-index object-matching $no_one $exit $room $help $generic_db $generic_editor $generic_help $generic_options MR-sequences MR-reading MR-writing MR-searching $housekeeper $recycler $error $biglist $guest_log mail-resolution $news matching MR-expiration mail-expiration $big_mail_recipient $local local 46 4 77 2 $login 2 ------ 2 This object manages command parsing for unconnected players and governs the initiation of an actual connection. There are verbs pertaining to registration, controlling player creation, and doing site-locks (see `help blacklist' on $wiz_help). 2 2 COMMANDS FOR UNCONNECTED PLAYERS 2 2 Recall that for each line that an unconnected player types, the server parses that line into words (the same way normal commands are parsed into a list of words that is then assigned to `args') and then #0:do_login_command is called. 2 2 :parse_command (@args) => {verb, @args} 2 given the sequence of arguments that were fed to #0:do_login_command 2 this returns the name of a verb on $login to be called together with a 2 list of arguments to be passed to it. 2 2 By default this just returns args iff args[1] names an actual verb on $login that is +x and has args {"any","none","any"}. Otherwise, it returns one of 2 2 .blank_command -- verb to call if command line is empty 2 .bogus_command -- verb to call if command line otherwise unintelligible 2 2 In both cases :parse_command returns a verbname followed by the entire args list passed to it (including the would-be verb at the beginning if any). 2 2 Currently the following verbs are available to non-connected players 2 2 h*elp @h*elp -- print .welcome_message 2 ? -- print a short list of available commands 2 w*ho @w*ho -- print a list of logged in players (excluding wizards) 2 co*nnect @co*nnect -- connect to an existing player 2 cr*eate @cr*eate -- create a new player 2 up*time @up*time -- tell how long the server has been running 2 version @version -- tell which version of the server is running 2 q*uit @q*uit -- logoff 2 2 Adding a new command is fairly straightforward; just create a verb on $login, making sure a previous verb doesn't already match the name you want to give it. Then give it args of "any" "none "any" and make sure it is +x. Such a verb should begin with `if (caller != #0) return E_PERM; ...' so as to prevent anyone other from a not-logged-in player from making use of it. 2 2 CUSTOMIZATIONS 2 2 .welcome_message 2 -- the message for "help" to print. 2 .create_enabled 2 == 0 => @create prints .registration_string if one tries to use it 2 == 1 => anyone from a non-blacklisted site (see `help blacklist') 2 may use @create to make a new player 2 2 .registration_address 2 -- an email address for character creation requests 2 .registration_string 2 -- string to print to players to give them information about how to get 2 a character created for them, .registration_address is substituted 2 for %e, % for %% 2 .newt_registration_string 2 -- string to print to @newted players (see `help @newt'). 2 same substitutions as for .registration_string. 2 2 .max_connections 2 -- integer representing the maximum connected players permitted on this moo. 2 .connection_limit_msg 2 -- string printed out when this is reached. 2 .lag_exemptions 2 -- list of non-wizard players who may login anyway. 2 2 Other verbs 2 :registration_string() => .registration_string with substitutions 2 :newt_registration_string() => .newt_registration_string with substitutions 2 :player_creation_enabled(connection) 2 decides whether someone on connection should be allowed to create 2 a player. If you decide this shouldn't depend strictly on the blacklist 2 and on the value of .create_enabled, here's where the extra code can go. 2 :check_for_shutdown() 2 prints a warning message to append to the login banner in the event 2 that the server will be going down soon. 2 :check_player_db() 2 prints a warning message to append to the login banner in the event 2 that $player_db is being reloaded to warn players that their character 2 names might not be recognized. 2 2 SITE LOCKS 2 see `help blacklist' 2 36 5 4 29 2 The Generic Container (for programmers) 2 2 In addition to the command verbs described under `help containers' 2 and the _msg properties described in `help container-messages', 2 the following verbs and properties are available for use within programs 2 2 .opened == TRUE iff the container is open 2 .dark == TRUE iff the contents of the container may be seen 2 .opaque -- describes the correlation between .open and .dark 2 == 0 container is always !dark 2 == 1 container is dark iff it is closed 2 == 2 container is always dark 2 2 :set_opaque(newvalue) 2 changes the .opaque value for the container 2 => newvalue or E_PERM or E_INVARG 2 2 :set_opened(newvalue) 2 opens/closes the container (updates .open and .dark) according to newvalue 2 => newvalue or E_PERM 2 2 :is_openable_by(player) 2 what the :open command uses to test whether the player should be able to open 2 the container. By default this refers to .open_key (set by 2 @(un)lock_for_open), but the object owner is free to customize this. 2 2 N.B.: There is no way to directly set .dark; .dark can be changed only by 2 changing one of .opaque or .opened. Use :set_opaque(0) and :set_opaque(2) 2 to have .dark change independently of the value of .opened. 36 5 4 68 2 $mail_agent 2 2 This object contains a two distinct sets of routines: 2 2 1. utilities for performing basic mailsystem functions, e.g., 2 matching on recipient names, resolving mail forwarding, 2 formatting messages, sending messages 2 2 Recipient Matching 2 2 match - match on a $mail_recipient 2 match_recipient - match on either a $mail_recipient or a player 2 match_failed - print angry messages to the user for $failed/ambiguous_match 2 2 look_self - provides a list of available $mail_recipients 2 check_names 2 touch 2 accept 2 2 Message Format 2 2 make_message - produces a message in the canonical transmission format 2 name - single recipient => string for address field 2 name_list - list of recipients => string for address field 2 parse_address_field - address field string => object list 2 2 Sending Messages 2 2 send_message - advertised message sending routine. 2 raw_send - raw message sending routine 2 (only called by $mail_editor:send and this:send_message) 2 resolve_addr - converts a given list recipients into a list of actual 2 recipients and objects to be notified. 2 sends_to - Does X forward (transitively) to Y 2 2 Mail Options 2 2 option 2 option_verbose 2 2 2. canonical versions of mail_recipient verbs 2 2 Ideally, the verbs to perform operations on a given mail recipient would be located on the recipient itself, except for the fact that these verbs also need to be located on players, which for various reasons, shouldn't be children of $mail_recipient. Multiple inheritance would solve our problems, but we don't have it yet. Ergo, both $mail_recipient and $player refer to the following verbs here: 2 2 display_seq_full print entire text of messages (@read) 2 display_seq_headers print headers of messages (@mail) 2 rm_message_seq remove messages (@rmm) 2 undo_rmm undo last rm_message_seq (@unrmm) 2 expunge_rmm flush removed messages (@unrmm expunge) 2 list_rmm list removed messages (@unrmm list) 2 renumber renumber messages (@renumber) 2 msg_summary_line msg header => display_seq_headers/list_rmm summary line 2 2 parse_message_seq command line msg sequence spec => message sequence 2 new_message_num => message number of next new message 2 length_all_msgs => number of messages (total) 2 length_num_le => number of messages numbered <= some number 2 length_date_le => number of messages dated <= some date 2 exists_num_eq => true iff there exists a messsage with the given number 2 from_msg_seq => message sequence of msgs from given sender(s) 2 to_msg_seq => message sequence of msgs to given recipient(s) 2 subject_msg_seq => message sequence of msgs with subjects containing text 2 body_msg_seq => message sequence of msgs with bodies containing text 2 messages_in_seq => list of {message number, message} pairs 2 2 messages == :messages_in_seq(1,:length_all_msgs()+1) (obsolete) 2 2 The $mail_agent versions of these verbs are set_task_perms(caller_perms()) and perform their operations on caller, which in turn is assumed to have done any necessary security checks. 36 5 4 38 2 Subscribing to Mail Recipients 2 ------------------------------ 2 There are two notions of being "subscribed" to a mailing list/recipient. 2 2 (1) Hard subscribed == being on the recipient's .mail_forward list so that mail sent to this list is forwarded to one's own .messages as well (see `help mail-forwarding'). 2 2 (2) Soft subscribed == keeping track of a current message for this recipient and (optionally) being on the recipient's .mail_notify list. 2 2 2 Each player has a .current_message property that contains, for each recipient the player cares to keep track of, a current message number and a last read date. 2 2 player:current_message(rcpt) (somewhat obsolete) 2 => player's current message number for rcpt 2 2 player:get_current_message(rcpt) 2 => player's {current message number for rcpt, last-read-date for rcpt} 2 2 player:make_current_message(rcpt) 2 => adds a current_message entry for rcpt (NOOP if rcpt == player) 2 2 player:set_current_message(rcpt,n|E_NONE,[,date]) 2 => sets player's current message number for rcpt to n iff n!=E_NONE 2 updates the last-read-date for rcpt to date iff date > last-read-date 2 2 player:kill_current_message(rcpt) 2 => removes current-message info for rcpt (NOOP if rcpt == player) 2 2 2 On $mail_recipient, .mail_forward and .mail_notify are -c so one needs to use the following verbs to actually modify them. 2 2 :add_forward(@new_recipients) 2 :delete_forward(@recpients) 2 :add_notify(@new_notifiees) 2 :delete_notify(@notifiees) 2 2 A recipient's owner is, of course, allowed to make arbitrary changes to .mail_forward and .mail_notify. However, the default versions of these verbs also allow any player to add him/herself to a recipient's .mail_forward or .mail_notify if the recipient is readable (see `help MR-access') by him/her. 2 2 Likewise any player may use the :delete* verbs to delete him/herself from any .mail_forward/.mail_notify list, regardless of his actual access to the list. 36 5 4 15 2 One may always refer to a list by its object number. In order to refer to it by name, it must be contained in $mail_agent, which holds all mailing lists, i.e., those that you want others to be able to refer to by name. 2 2 The .aliases field holds the names by which one may refer to the list, but only those names not containing spaces actually count for anything. As with certain other types of objects (e.g., players), set_aliases() needs to be called in order to change the .aliases field. 2 2 $mail_agent:match(name) 2 is the canonical way to obtain the objectid of a mailing list 2 given the name ("*" is assumed; an initial "*" will be dropped). 2 2 $mail_agent:match_recipient(name) 2 is the canonical way to obtain the objectid of a list or player 2 matching the given name. An initial "*" indicates that this is 2 supposed to be a list. 2 2 $mail_agent:match_failed(objid,name) 2 is the mail_recipient counterpart to $command_utils:object_match_failed 36 5 4 32 2 Controlling Access to Mail Recipients 2 ------------------------------------- 2 :is_writable_by(one) - one may alter/add/remove saved messages 2 :is_readable_by(one) - one may read messages. 2 :is_usable_by(one) - one may send to this list 2 2 By default, these verbs refer to the following properties: 2 2 writers - list of players other from the owner who can do anything 2 readers - if == 1, indicates a public mailing list. 2 list of additional readers (by default anyone who receives mail 2 sent to the list can read the saved messages). 2 moderated - if false, indicates a normal mail recipient everyone can send to. 2 otherwise this should be a list of approved senders. 2 2 Terminology: 2 A mailing list is "public" if everyone can read it. 2 A mailing list is "moderated" if not everyone can send to it. 2 2 Note that while being able to write to a recipient implies being able to read from it or send to it, neither of read-ability or send-ability implies the other. 2 2 It is highly recommended that if you are creating custom mail recipients with variable reader/sender lists, i.e., you find you need to write your own :is_readable/usable/writabe_by verbs, you are best off if such verbs are of the form 2 2 return pass(@args) || << your_test(args[1]) >> 2 2 and have .writers == .readers == {} and .moderated == 1. This will ensure 2 (1) wizards having write access 2 --- necessary in order for :receive_message to work 2 (2) writers being able to read and send (the converse being a ludicrous 2 situation), 2 (3) persons on the mail_forward list of someone with reader access will also 2 have read access (convenient). 36 5 4 20 2 Generic Mail Recipient 2 ---------------------- 2 A "mail recipient" is, by definition, an object that can be sent mail. 2 Mail recipients must either be players or descendants of $mail_recipient. 2 2 One source of confusion is that the terms "mail recipient", "mail folder", "mailing list", and "mail collection" really all refer to the same kind of object. It so happens that $mail_recipient serve several distinct functions and we tend to use whatever term happens to best match the application under discussion, e.g., it's a "mailing list" if we're playing with its .mail_forward property but it's also a "mail folder" if we're examining the messages that have been saved in it. 2 2 Note that, by default, a freshly created recipient is accessibly only by you. If you wish to make a publically accessible recipient, set .readers=1. Furthermore, if you want to allow a message on your recipient to be removed by its sender without your intervention, set .rmm_own_msgs=1. Finally, in order for other players to be able to refer to your recipient by name, the object must reside in $mail_agent. $mail_agent will not accept the object unless it has an actual description and a name distinct from all other mail recipient names/aliases. 2 2 Topics: 2 2 MR-access -- controlling read, write and send access to a recipient 2 MR-naming -- naming conventions and how to match on recipient names 2 MR-sequences -- message sequence arguments to $mail_recipient verbs 2 MR-reading -- reading messages/headers on recipients 2 MR-searching -- searching message lists for patterns in certain fields 2 MR-writing -- removing and renumbering messages 2 MR-subscribing -- updating .mail_forward, .mail_notify 2 and the story of .current_message 2 MR-expiration -- expiring and netmailing messages from recipients 36 5 4 24 2 Receiving Mail 2 -------------- 2 By definition a recipient "receives" a mail message when its :receive_message verb is called with that message as an argument. 2 2 :new_message_num() 2 => number that will be assigned to the next incoming message. 2 By default this returns the maximum of the message numbers appearing in 2 messages or .messages_going, incremented by 1. If the recipient is a player 2 then the value returned will be 1 higher if it conflicts with the player's 2 current message number for him/herself. 2 2 :receive_message(msg,sender) 2 By default this first calls this:new_message_num to obtain a message number to assign to the incoming message and then appends {num,msg} to this.messages. 2 `sender', the original sender, is supplied in case one wants different 2 action depending on who is sending the message (e.g., mail-gagging). 2 The return value should be an error or string if :receive_message is considered to have failed in some way. Otherwise, a number should be returned --- this number is given to any :notify_mail routines that are called and is expected to either be 0 or the number assigned to the incoming message. 2 2 Note that :receive_message can do arbitrary things, including resending the same message to a new destination. Hacking :receive_message to resend messages is different from using .mail_forward in the following respects 2 (1) the resent message is considered to be a distinct message having this 2 object as its "author" --- i.e., the From: line will necessarily be 2 different. 2 (2) since this "forwarding" is invisible to the mailsystem, 2 there is no protection against loops and multiple copies. 2 36 5 4 34 2 Mail Transmission Format 2 ------------------------ 2 There is a standard message format used for transmitting messages. This is the format that $mail_editor:make_message produces, and that :receive_message verbs on players and $mail_recipients expect to see. The (currently experimental) @refile and @copym commands also use this format to transfer messages. 2 2 This *transmission* format is distinct from the *storage* format, though, for convenience this same format is often used as well for storing messages in player collections and ordinary $mail_recipient children though, in general, there is no requirement that this be the case. 2 2 A transmitted message is a list in the following form 2 2 date (number), 2 the time() value at the time the message was sent. 2 from (string), 2 the sending object (address list form) 2 if this is not a player, an additional header will indicate the 2 current ownership of the object. 2 to (string), 2 recipients (address list form) which can either be players 2 or $mail_recipient descendents. 2 subject (string), 2 subject of the message, or " " if there is no subject, 2 @additional optional headers (list of strings), 2 each header has the form ": text" where : 2 is padded out to a width of 10 columns for the convenience of 2 :display_message. Currently "Reply-to:
" is the only 2 additional header in use, 2 "", 2 @body of message (list of strings) 2 2 Note that the from, to and subject lines do *not* include a header name like "From:", "To:", or "Subject:". The @'s indicate that the lists in question get spliced in (as usual), thus the entire message is a list whose first element is a number and the rest are strings. 2 2 The address lists that appear in the from and to lines is a string in the form a sequence of object ids, each enclosed in parentheses and preceded by optional text, e.g., 2 2 "*Core-DB-Issues (#8175), Rog (#4292), and Haakon (#2)" 2 2 The text is intended to give the current name of each object for the benefit of human readers, but is actually ignored by all header parsing routines. The convention is that the text is either a player name or a * followed by a mailing list name. 36 5 4 52 2 Resolving Mail Forwarding & Notification 2 ---------------------------------------- 2 For each recipient of a given mail message, the following two verbs are called to determine where the message should actually go and who should be notified about it: 2 2 :mail_forward([from]) 2 should return either 2 . a list of objects (either players or $mail_recipients) 2 to which mail for this recipient will be redirected. 2 . a string error message to be printed to the player sending the message. 2 If this recipient is one of the original destinations (i.e., not the 2 result of a previous forwarding), no mail is actually sent. 2 2 If :mail_forward returns a nonempty list, the recipient itself will *not* 2 actually receive the mail message unless it is included in the list. 2 #-1 is allowed to be on the list; it is ignored but does make the list 2 nonempty. Thus, having :mail_forward() return {#-1} is the canonical way 2 to have arriving mail disappear without being kept or forwarded. 2 2 :mail_notify([from]) 2 should return a list of objects that are to be told about any mail sent 2 to this recipient (whether or not the recipient actually receives it). 2 Said objects must have a :notify_mail verb, but other from that, there 2 is no restriction on what these can be. 2 2 object:notify_mail is called with the arguments 2 (sender,recipients,msgnumbers) where 2 recipients == list of recipients including object in .mail_notify 2 msgsnumbers == corresponding list of :receive_message return values 2 (or 0 if :receive_message is not actually called, which 2 will be the case if the recipient forwards without keeping) 2 2 When called as part of a mail send, the `from' argument is the immediate predecessor on the forwarding chain. The default versions of these verbs return the values of .mail_forward and .mail_notify respectively (pronoun_subbing if the value is a string), unless this is a moderated mailing list and `from' is an unapproved sender (see `help MR-access') in which case the following verbs are called instead: 2 2 :moderator_forward(from) 2 what :mail_forward should return for mail coming from unapproved senders 2 This returns .moderator_forward (pronoun_subbed if a string) by default. 2 2 :moderator_notify(from) 2 what :mail_notify should return for mail coming from unapproved senders 2 This returns .moderator_notify (pronoun_subbed if a string) by default. 2 2 Since the :mail_forward verbs only see the previous sender in the forwarding chain, if, e.g, B is moderated but A can send to B (i.e., B:mail_forward(A) returns an actual list), then any mail sent to A goes to B even if the original sender isn't normally allowed to send to B directly. 2 2 These verbs should all allow `from' to be omitted in which case they should return as if `from' were a generic approved sender (e.g., wizard). 2 2 It should rarely be necessary to actually modify any of :*_forward/*_notify verbs, since one has a fair amount of control over their behavior via the following properties 2 2 .mail_forward 2 .mail_notify 2 .moderated (see `help MR-access') 2 .moderator_forward 2 .moderator_notify 36 5 4 24 2 Sending Mail 2 ------------ 2 $mail_agent:send_message(from,recipients,headers,body) 2 from: sender of the message 2 (this must be you or something you own; otherwise => E_PERM) 2 recipients: object or list of objects (must all be players or 2 $mail_recipient descendants) 2 headers: either a string (contents of the Subject: line) 2 or a list {subject,replytos} replytos is a list 2 of objects designated to receive replies. 2 Use {"",replytos} to have a Reply-to: without a Subject: 2 2 This is the canonical way to send a mail message from a program. 2 This calls $mail_agent:make_message to format the arguments into an actual message (see `help mail-format') and then $mail_agent:raw_send to do the actual sending which goes as follows: 2 2 (1) Call :mail_forward on all recipients add any new recipients thus obtained to final recipient list, keep calling mail:forward on the new recipients until we obtain no additional recipients. If one of the initial recipients is invalid, is not a player or $mail_recipient, or has its mail_forward return a string error, then we print the error message and abort at this point with no mail being sent. If one of the later recipients bombs similarly, error messages are printed, but in this case mail still goes out to the other recipients. 2 2 (2) Call :mail_notify on all recipients encountered in stage (1) to get a list of objects to notify. 2 2 (3) All final recipients receive the message (see `help receive-mail') 2 (4) All notifications are delivered (using :notify_mail()) 2 2 We return {0, @failed_recipients} if we bombed out at step 1. 2 Otherwise return {1, @actual_rcpts} indicating what mail was sent. 36 5 4 13 2 Mail System 2 ----------- 2 The following topics describe the guts of the LambdaCore mail system 2 2 sending-mail -- how to send mail from a program; what happens. 2 mail-forwarding -- how to do mail forwarding/notification (the simple version) 2 mail-resolve -- how mail forwarding/notification works, in gory detail 2 receiving-mail -- what :receive_message should do 2 mail-format -- format of transmitted messages 2 mail-command-parsing (TODO) -- routines for parsing mail commands 2 2 $mail_recipient -- generic non-player mail recipient 2 $mail_agent -- mail utility object 36 5 4 34 2 2 Database of Players 2 ------------------- 2 This is an instance of the Generic Database ($generic_db) that 2 holds the {name/alias,#objectid} pairs for every 2 name and alias of every player in the MOO. 2 2 Verbs supplied include 2 2 :find(string) => player or $ambiguous_match or $failed_match 2 :find_exact(string) => player or $failed_match (does not do partial matches) 2 :find_all(string) => list of all matching players 2 2 :insert(string,player) 2 records that string is now a name or alias of player 2 :delete(string) 2 removes string from the db 2 :available(string) 2 returns 1 if string is available as a player name or alias, 2 an object if string is in use, or 0 if string is otherwise unavailable. 2 :load() 2 resets the db, inserting all current player names and aliases. 2 2 The internal representation and all of the above verbs (except :load() and 2 :available()) are as described for $generic_db. 2 2 It should be noted that for any application that involves resolving a player name from a command line, you should be using $string_utils:match_player() rather than $player_db:find(), since the former will deal correctly with other ways of referring to players apart from their names and aliases (e.g., literal object numbers, "me", "$no_one"...). 2 2 :load() needs to be done periodically as it is possible for the player db 2 to get out of synch with reality. In particular, there is currently no way 2 to block someone writing his own player :recycle() verb that neglects to 2 remove his names from the player db. 2 2 While a :load() is in progress the .frozen property is set to 1 to indicate that any results of :find*() are not to be trusted. 36 5 4 2 2 *index* 2 Core Utility Help Topics 36 5 4 64 2 2 Which :match...() Verb Do I Call? 2 --------------------------------- 2 There are many situations where one wishes to obtain an object from a room or a player's .contents whose name/aliases matches a particular string. There are four main verbs available for this and it is important to understand the distinctions between them and how they are supposed to be used. 2 2 (*) LOC:match("X") 2 -- what you get looking for something that is inside LOC and named "X". 2 By default, this looks through LOC.contents to find a unique object 2 having a name or alias that has "X" as a prefix. 2 2 Essentially, you can think of :match as a contents-matching verb, though, e.g., for rooms you also get matches on exits as well. 2 2 (*) LOC:match_object("X", YOU) [YOU defaults to player] 2 (*) YOU:my_match_object("X", LOC) [LOC defaults to player.location] 2 -- what YOU get being located at LOC and looking for something named "X". 2 By default these both return $string_utils:match_object("X",LOC,YOU) 2 2 (*) $string_utils:match_object("X", LOC, YOU) 2 -- what you *would* get *if* YOU were a typical player, YOU were inside LOC, 2 YOU were looking for something named "X", *and* LOC were a typical place. 2 2 In other words, $string_utils:match_object describes the :match_object() algorithm for "typical places" and the :my_match_object for "typical players": 2 2 (1) check for "X" being one of "", "me", "here", "$something", or "#n" 2 (2) try YOU:match("X") i.e., something in your inventory (maybe) 2 (3) try LOC:match("X") i.e., some object in the room (maybe) 2 2 The distinction between these location:match_object and player:my_match_object has to do with whether the player or the location should determine what the matching algorithm is. Which one you should use depends on the command that you are writing. If you are writing a command with a virtual-reality flavor, then you should be respecting the room owner's idea of which objects you can "see" and thus the command should be calling the location's :match_object verb. If you are writing a building/programming command where it is appropriate for the player to determine the matching algorithm --- whether because the current location is irrelevant, not to be trusted, or both --- then the player's :my_match_object verb should be called. 2 2 Examples: 2 2 `look diamond in box' 2 calls box:match("diamond"). This is a match on the contents of box. 2 2 `take ball', 2 calls player.location:match_object("ball") 2 to determine which "ball" to take. Note that if the room is dark, 2 we might not be able to find any "ball". 2 2 `@program widget:foo', 2 calls player:my_match_object("widget") to get the player's own idea 2 of what "widget" should be. Note that if I were carrying something 2 named "widget" and expecting to be programming a :foo() verb on it, 2 it would be potentially disastrous should the room where I am decide 2 for me to be programming something else (not even necessarily 2 called "widget"). 2 2 Object Matching Failures 2 ------------------------ 2 As with other matching routines, one gets back 2 2 $failed_match in the case of no matching object 2 $ambiguous_match in the case of more than one matching object 2 $nothing in the case of a blank string argument 2 2 or an object-id. In these first 3 cases, one usually wants to translate these nonresults to the player; this is what $command_utils:object_match_failed. The standard idiom to mimic what the builtin parser does, say, with the direct object is 2 2 dobj = foo:match_???(dobjstr); 2 if($command_utils:object_match_failed(dobj, dobjstr)) 2 "...give up. nothing to do. error message has already printed..."; 2 else 2 "...dobj is something useful. Continue..."; 2 ... 2 endif 36 5 4 15 2 $no_one 2 ------- 2 ..is a powerless player. He owns no objects, not even himself; nor does he own any verbs. He is, however, a programmer and thus may use eval(). 2 In fact his sole purpose is to evaluate questionable code. 2 `questionable' could be in either or both of the following senses 2 2 (1) Its origin is sufficiently uncertain so that there is no obvious way of deciding whose permissions it should run under. 2 (2) The code itself is potentially malicious, i.e., to the extent that one does not want to be evaluating it using one's own permissions. 2 2 set_task_perms($no_one); is thus the canonical idiom in wizard code for rendering anything that follows mostly harmless. For use by ordinary programmers, we have: 2 2 $no_one:eval(string) 2 2 which attempts to evaluate an arbitrary string using $no_one's permissions. 2 string is either an expression or ";" followed by one or more statements, of which the final semicolon may be omitted. return values are what eval() would return (either {1,value} or {0,@error_messages}). 36 5 4 19 2 Exits 2 ----- 2 An exit can be renamed by either the owner of the exit or the owner of its source. 2 2 The standard verbs that are called in exit movement are: 2 2 :move(object) - moves the object via this exit 2 :invoke() - equivalent to :move(player) 2 2 When an exit is invoked on a particular object (via exit:move(object)), the following occurs. 2 2 (1) The exit may be locked against the object, in which case we print the 2 nogo messages and quit. 2 2 (2) (room=exit.dest):bless_for_entry(object) is called. Assuming that exit is recognized by room as being a legitimate entrance (i.e., is in room.entrances), this will enable room:accept(object) to return true. 2 2 (3) object:moveto(room) is called and the various messages (see `help exit-messages') are :announced/:told. Note that this, in accordance with the way the builtin move() (and hence the default :moveto()) works, we get a call to room:accept(object) which checks for the room itself being locked against the object, and otherwise returns true if the blessing in the previous step worked. The move is performed, here:exitfunc(object) and room:enterfunc(object) are called. In particular, room:enterfunc clears the blessing bestowed in (2) now that it is no longer needed. 2 2 In general, the move may fail, in which case we :announce the (o)nogo_msgs. 36 5 4 81 2 The Generic Room ($room) 2 ---------------- 2 2 (1) Announcements 2 2 :announce (@text) => broadcasts to all except player 2 :announce_all (@text) => broadcasts to all 2 :announce_all_but (objects,@text) => broadcasts to all except those in objects 2 2 say, emote 2 2 2 (2) Command recovery 2 2 :huh (verb,args) - server hook: last chance to make sense of verb 2 :here_huh (verb,args) - room's last attempt to parse something 2 :here_explain_syntax (this,verb,args) - attempts to explain usage of verb 2 2 2 (3) Residency 2 2 free_home - true => @sethome allows anyone to set his .home to be here 2 residents - objects on this list may teleport in and/or set their homes here. 2 2 :accept_for_abode(player) 2 => true iff player should be allowed to set .home to this room. 2 2 @resident*s 2 2 2 (4) Looking 2 2 dark - true => contents are not visible 2 ctype - 0..3 for four different styles of .contents lists 2 2 :match (string) => exit or object in room's .contents 2 :tell_contents (objects,ctype) - format objects according to ctype, tell player 2 2 l*ook 2 2 2 (5) Entrance and exit. 2 2 :accept (object) - Called by move() and :moveto() before an object enters a room, if false is returned, movement is prevented. Protocol permits this verb to make noise (though this is discouraged) as this is the only place the room will learn the object's original location. 2 2 :acceptable (object) - Called by verbs which wish to check whether movement will be possible. Protocol prohibits this verb from making noise and requires it to return the same value as :accept would for the same arguments. 2 2 :is_unlocked_for (object) - interface with the @lock protocol. Returns true or false depending on the state of locks for the object with the room. Other things may prevent entrance even if this returns true. Protocol prohibits this verb from making noise. 2 2 :enterfunc (object) - called after entrance has succeeded. Noise is fine. 2 2 :exitfunc (object) - called after an object has successfully left. Noisemaking is fine. 2 2 (6) Topology and Movement via Exits 2 2 See `help $exit' for an explanation of how the generic $exit works. 2 2 free_entry - true => `teleporting' in is allowed 2 false => only residents may teleport in 2 exits - list of invokable exits leading from this room 2 entrances - list of recognized exits leading to this room 2 blessed_object - object currently entering via an exit 2 blessed_task - task_id for entering object 2 2 :match_exit (string) => exit whose name matches string 2 :bless_for_entry (object) - set up room to accept object arriving from entrance 2 :add_exit (exit) 2 :add_entrance (exit) 2 :remove_exit (exit) 2 :remove_entrance (exit) 2 2 e/east/w/west/s/south/n/north/ne/northeast/nw/northwest/se/southeast/sw/southwest/u/up/d/down, go, @add-exit, @add-entrance, @remove-exit, @remove-entrance, @exits, @entrances 2 2 2 (7) Ejection 2 2 victim_ejection_msg/oejection_msg/ejection_msg 2 :*_msg() messages 2 2 @eject 2 36 5 4 2 2 *forward* 2 $generic_help 36 5 4 79 2 Generic Database 2 ---------------- 2 This holds a collection of {string key, datum} pairs, where datum can be anything. At most one datum may be associated with any given string. Data may be anything (lists, strings, numbers, objectids). If you like, you can think of this as an array indexed by strings. 2 Verbs supplied include 2 2 :find(string) => datum, $ambiguous_match or $failed_match 2 :find_key(string) => full string key, $ambiguous_match or $failed_match 2 :find_exact(string) => datum or $failed_match (no partial matches) 2 :find_all(string) => list of all data corresponding to matching strings 2 :find_all_keys(string) => list of all matching strings 2 2 :insert(string,datum) 2 if the string is already present in the db, 2 changes the associated datum and returns {old_datum}; 2 otherwise enters a new {string,datum} pair and return 0. 2 :delete(string) 2 if there is a datum associated with string, 2 remove this association and return {datum}; otherwise return 0. 2 :delete2(string,datum) 2 if the given datum is associated with string, 2 removes that association and return {datum}, 2 if some other datum is associated with string, just return {other datum} 2 otherwise return 0. 2 :clearall([4|3]) 2 removes all associations from the database. 2 optional argument changes the type of the database 2 (4 is normal, 3 is a kludge for when the data are simply boolean flags 2 i.e., this is a set of strings rather than a string-indexed array; 2 more on this below) 2 2 count [entries|chars] in this 2 provide some vague statistics about how big this thing is. 2 2 N.B. As entries get made, properties belonging to $generic_db.owner will be created on the db object itself. These properties will be created having flags as specified by .node_perms, which by default is "r", but can be changed to "" should you want to ensure that randoms don't have access to the raw information. 2 2 Implementation notes 2 - - - - - - - - - - 2 The representation is as a `trie', a tree in which each internal node corresponds to a prefix shared by two or more strings in the db. 2 Each internal node is kept in a property named " "+, where is a prefix shared by all strings in the subtree under this node. 2 The property value is a 4 element list 2 2 this.(" "+)[1] = 2 maximal continuation shared by all strings beginning with prefix 2 i.e., all these names actually begin with + 2 2 this.(" "+)[2] = 2 string of all characters that can follow + for which 2 there is more than one string in the db beginning with ++ 2 2 this.(" "+)[3] = 2 list of all strings in this subtree for which 2 the character (or lack thereof) following the + substring 2 suffices to determine the string. 2 2 this.(" "+)[4] = 2 list of data corresponding to the strings in [3]. 2 2 Child nodes are this.(" "+++) 2 for all in this.(" "+)[2]. 2 The root node is this.(" "). 2 If, e.g., there are 2 or more strings in the db beginning with a, 2 there will be a node this.(" a"). 2 If all of these strings actually begin with "ani", then this.(" a")[1]=="ni". 2 The db consisting of the 5 correspondences 2 2 {"animal", #1} 2 {"anime", #2} 2 {"anil", #3} 2 {"anile", #4} 2 {"banal", #5} 2 2 would be represented 2 2 this.(" ") =={"", "a", {"banal"}, {#5}} 2 this.(" a") =={"ni","lm", {}, {}} 2 this.(" anim")=={"", "", {"animal","anime"},{#1,#2}} 2 this.(" anil")=={"", "", {"anil","anile"}, {#3,#4}} 2 2 In some cases one may merely wish to hold a collection of strings without trying to associate a particular datum with each string. One may then instead set up a db without the fourth field on each of the properties. In this case the datum is taken to be the found string itself and that is what gets returned by :find*() in the event of a successful search. :find and :find_key are then equivalent as are :find_all and :find_all_keys. To setup the db this way, do a :clearall(3). :clearall(4) reverts to the above described type of db with a separately kept datum. Note that you can't change the type without emptying the db. 3 and 4 are currently the only db types allowed. 36 5 4 201 2 The Generic Editor enables a player to edit a list of strings. While one might contrive to use it directly, it is rather intended as a parent for some actual editor. It supplies the following commands: 2 2 say w*hat 2 emote abort 2 lis*t [] [nonum] q*uit,done,pause 2 ins*ert [] ["] 2 n*ext,p*rev [n] ["] 2 del*ete [] 2 f*ind /[/[c][]] 2 s*ubst //[/[g][c][]] 2 m*ove,c*opy [] to 2 join*l [] 2 fill [] [@] 2 2 $editor_help.(cmdname) descrbes cmdname 2 $editor_help.insert descrbes insertion points () 2 $editor_help.ranges descrbes range specifications () 2 2 You'll notice that nowhere does it say how to load in a given list of strings or how and where one may save said list away when one is done editing. These commands are supplied by the child editor object. The generic editor contains only the code for editing lines, though it defines additional functions for use by the children: 2 2 :loaded(player) 2 returns the index (player in this.active) iff text has been loaded 2 from somewhere, otherwise returns 0. 2 2 Note that, by default, there is a difference between 2 2 having nothing loaded (:text(who)==0) and 2 having loaded something with no text (:text(who)=={}). 2 2 If you don't care about this distinction in a particular case, 2 just do (player in this.active) instead of this:loaded(player). 2 If you don't want your editor to make this distinction at all, do 2 2 @stateprop texts={} for 2 2 which changes the initial value of :text() to {} 2 2 In all functions below, 'who' is the index returned by :loaded(player) 2 2 BTW, be careful about using 'player' in non-user (i.e., +x this-none-this) verbs --- much better to have the user verb get the index with :loaded() and then pass that around. 2 2 Also be careful about suspend() and verbs that call suspend(). In particular, the player's index in the .active list can change during the suspend interval, so you must be sure to obtain the index (e.g., using :loaded()) again after the suspend() returns. 2 2 For your non-user verbs, we have 2 2 :ok(who) 2 returns E_PERM if the caller is not an editor verb and E_RANGE 2 if 'who' does not point to a valid session. 2 2 which should take care of the more egregious security holes (but maybe not the less egregious ones). For getting and loading text, we have 2 2 :text(who) 2 the current text string list or 0 if nothing loaded yet. 2 :load(who,text) 2 loads the given list of strings as the text to be edited. 2 this also resets the 'changed' flag and pushes the insertion 2 point to the end. 2 2 and various flags and properties (all of the set_* routines return E_PERM when not called from an editor verb, E_RANGE if who is out of bounds, E_INVARG if something is wrong with the 2nd arg, or the new value, which may not necessarily be the same as the 2nd arg (e.g., set_insertion(..,37) on a 5 line text buffer returns 6). 2 2 :changed(who) 2 has the text been altered since the last save/load? 2 (the child editor gets to define what "save" means). 2 :set_changed(who,value) 2 Any child editor command that is considered to save the text should do a 2 :set_changed(who,0). 2 Note that if the changed flag is 0, the session will be flushed when 2 the player leaves the editor, so you may also want certain commands to 2 do set_changed(who,1)... 2 2 :origin(who) 2 room where the player came from. 2 :set_origin(who,room) 2 can be used to change the room the player will return to when finished 2 editing. Since origin gets set even in cases where the player teleports 2 into the editor you probably won't usually need to do this. 2 2 :insertion(who) 2 current insertion point. 2 :set_insertion(who,linenumber) 2 linenumber needs to be a positive integer and will get 2 2 :readable(who) 2 whether the current editing session has been made globally readable. 2 :set_readable(who,boolean) 2 change the readability of the current editing session. 2 This is used by the publish/perish verbs. 2 2 We also provide 2 2 :invoke(...) 2 If the player has a previous unsaved (i.e., :changed()!=0) 2 session, we return to it, moving the player to the editor. 2 If the player is already in the editor, this has no effect other 2 than to print a few nasty messages. In any case a :changed() 2 session must be aborted or set_changed(,0) before anything else 2 can be started 2 2 Otherwise, we pass the arguments (which are assumed to be the 2 result of some munging of the command line) to :parse_invoke(), 2 move the player to the editor and load whatever parse_invoke() 2 specified. The only interpretation the generic editor makes on 2 the arguments is that if the boolean value of the first is true, 2 this indicates that the player wanted to load something as 2 opposed to resume a previous session. Usually a command calling 2 :invoke will have a true (i.e., nonzero number, nonempty list or 2 string) first arg iff the command line is nonempty, in which case 2 'args' works fine for this purpose. 2 2 If the command parses sucessfully (:parse_invoke() returns a list), 2 we move the player to the editor if necessary and then call 2 :init_session() to set things up. 2 2 The child editor is assumed to provide 2 2 :parse_invoke(...) 2 given :invoke()'s arguments, determines what the player wants to edit. 2 It either returns 0 and reports syntax errors to player, 2 or it returns some list that :init_session() will understand. 2 2 :init_session(who,@spec) 2 where spec is something that was returned by :parse_invoke(). 2 Loads the text and sets the stateprops (below) to indicate that 2 we are working on whatever it is we're suppose to be working on. 2 2 :working_on(who) 2 returns a string X as in "You are working on X." 2 This is called by the 'w*hat' command, among other things. 2 2 Child editors may have their own properties giving state information for the various editing sessions. The value of each such property will be a list giving a value for each player in the editor. For each such property, you should, once the editor object has been created, initialize the property to {} and do one of 2 2 @stateprop for 2 @stateprop = for 2 (0 is the default ) 2 2 Henceforth, adding and deleting new editing sessions will amend the list held by the given property. The value of the property for a given session can be obtained via this.[player in this.active] and can be changed with a corresponding listset() call. The usual idiom for an editor command is 2 2 if(!(who=this:loaded(player))) 2 player:tell(nothing_loaded_msg()); 2 else 2 ... various references to this.[who] ... 2 endif 2 2 To remove such a property from the list of such state properties: 2 2 @rmstateprop from 2 2 Note that you can only do this with properties defined on the child editor itself. 2 2 Sometimes you may wish to @stateprop a new property on an editor where active editing sessions exist. @stateprop will fail if the property in question does not hold a list of the correct length (== length(editor.active); one value for each editing session). You need to either give the @flush command to clear out all sessions and boot all players currently in the editor or somehow manually initialize the property to a list of appropriate values and pray that nobody enters/exits the editor between the property initialization and the @stateprop command --- this problem can be avoided by doing an eval() that does all of the initializations (beware of suspends()) and calls :set_stateprops directly. 2 2 Incidentally, the @flush command may be used at any time to clean out the editor or to remove all sessions older than a given date. 2 2 There are also numerous _msg properties that may be customized 2 2 @depart announced at the origin when :invoke() is called. 2 @return announced at the origin the player is returned there. 2 @nothing_loaded printed when user attempts editing 2 before anything has been loaded. 2 @no_text response to 'list' when :text()=={} 2 @no_change printed by 'what' when :changed()==0 2 @change printed by 'what' when :changed()==1 2 @no_littering printed upon leaving the editor with :changed()==1. 2 @previous_session printed by :invoke() when player tries to start a 2 new session without aborting or saving the old one 2 2 The general procedure for creating a child editor: 2 2 . @create $generic_editor named 2 2 . define additional verbs/properties 2 At the very least you need 'edit' and 'save' commands. 2 Usually you can get away with just having 'edit' call :invoke(); 2 Presumably, you'll need at least a command to load text from somewhere 2 as well as a command to save it back out. 2 2 . define a verb (somewhere) to invoke the editor 2 This could be just a one-liner that calls :invoke(args,verb). 2 Either that or 2 . you have to set up an exit somewhere whose destination is 2 . you have to advertise the object number so that people can 2 teleport to it. 2 2 . @stateprop x for 2 2 . if you want the 'abort' command to boot the player from the editor do 2 .exit_on_abort = 1; 2 2 . set .commands to be the list of additional commands defined 2 by . 2 Each element of the list is itself a list of the form {name,args}. 2 set .commands2 to be the list of commands that should appear 2 in the `look' listing, and should be a list of strings appearing 2 as names in .commands on either or some editor ancestor. 2 look at $verb_editor or $note_editor for an example. 2 2 . If you want to have help text for new verbs you define, create a child of 2 $generic_help and add properties to this object for each of the topics 2 that you want to provide help text. 2 Finally, set .help = {this object} so that the help system 2 knows to consult this object. 36 5 4 87 2 The Help System 2 --------------- 2 When a player types help, the following list of objects is consulted for .help properties: the player itself, all ancestors of player up to and including $player, and, if the current location is a room, the current location together with all ancestors of the current location back to and including $room. Each help property should have as value either an object or a list of objects (otherwise we just ignore it). These objects are then strung together as a list of `help databases' to be searched in order for the requested topic. 2 2 A help database (in the sense of anything that is usable by $player:help()) is any object having the following three verbs: 2 2 :find_topics([string]) 2 where string is a supposed help topic, returns a list of strings, 2 i.e., actual help topics that this db knows about, or some boolean 2 false value in the event that this db is clueless... 2 If no arguments are given, this should return a list of all topics 2 in the db 2 2 :get_topic(string) 2 given one of the strings returned by :find_topics this either 2 returns a list of strings (text to be spewed to the player) or 2 returns 1 to indicate that it has already taken care of printing 2 information to the player. 2 2 :dump_topic(string) 2 like get_topic, but instead returns the raw text of a help topic 2 as a (download/upload) script 2 2 In short if :find_topic reports that a particular db knows about a given topic 2 it returns the full topic name, so that :get_topic may be called on it later. 2 :dump_topic is used by maintainers (see $wiz:@gethelp) to edit help topics. 2 2 $generic_help and $help 2 ----------------------- 2 The Generic Help Database, $generic_help, is the parent class of a particular kind of help database of which $help is an instance. On help databases of this type, every help topic has a corresponding property, interpreted as follows: 2 2 this.(topic) = string 2 one-line help text. 2 2 this.(topic) = {"**",@args} 2 call this:(args,dblist) to get text where dblist is the list of 2 help objects that would have been consulted had the topic not been found 2 on this object. 2 2 this.(topic) = other list of strings 2 multi-line help text 2 2 For the {"**",...} form, the current verbs available are 2 2 {"*forward*", topic, @rest} 2 - get help text for topic and then append the lines of `rest'. 2 rest may, in turn, begin with a "**"... 2 2 {"*pass*", topic, @rest} 2 - get help text for topic from the first help database after this one 2 that actually has help text for topic, and then append lines of `rest'. 2 As with "*forward*" rest may, in turn, begin with a "**"... 2 2 {"*subst*", @lines} 2 - All occurences of %[exp] in lines are replaced with the value of exp 2 which is assumed to evaluate to a string. 2 All lines beginning with %;exp are replaced with the value of exp 2 which is assumed to evaluate to a list of strings. 2 Evaluation is done using $no_one's permissions so exp in either case 2 can only refer to public information. 2 2 {"*index*", title} 2 - returns a list of all topics in this database, arranged in columns. 2 title is used as a heading for this index. 2 2 In order for your help database to appear in the list presented 2 by 'help index', your db object must be set to +r. 2 2 {"*objectdoc*", object} 2 - gets the documentation for the given object (i.e., object:help_msg()) 2 N.B. as with all other *verb* arguments, object must be a string. 2 2 {"*verbdoc*", object, verbname} 2 - gets the documentation for the named verb on the given object 2 (i.e., any strings at the beginning of said verbcode) 2 2 Individual help dbs are free to define additional verbs that may be used in this context. $help itself defines the following additional such verbs: 2 2 {"*index_list*"} 2 - returns a list of all index topics in all databases in the search list. 2 An index topic is one whose actual text is {"*index*", something}. 2 When creating a help db, you should be sure to make an index topic. 2 2 {"*full_index*"} 2 - prints indices for all help databases in the search list. 2 2 It should be noted (once again) that help databases need not be children of $generic_help, so long as they have :find_topics/:get_topic/:dump_topic working as specified above. 36 5 4 62 2 Generic Option Package 2 ---------------------- 2 It occasionally happens that one has a command or set of commands for which one wishes to provide several options/flags that a player can set to customize the command's behavior for him/herself. Making each option a separate property is a bit expensive, especially when the option in question is merely a boolean flag that gets set to false in most cases. This package provides an alternative, as well as providing a uniform set of commands for setting these flags/options and checking that the values given are of appropriate types. 2 2 Instead of needing several properties, only one is required to store a list containing values for all of the options. An "option package" (pkg, below) is then an object of this class, which provides routines for manipulating such lists. 2 2 The set of option names is divided into a set of "real" options, those whose names will actually appear in a given list, and "extras" which are either synonyms for or represent combinations of real options. 2 2 pkg:add_name(name) adds name to .names (remove it from .extras if there) 2 pkg:add_name(name,1) adds name to .extras (remove it from .names if there) 2 => 1 - ok, 0 - already added, E_INVARG - illegal name, E_PERM 2 2 pkg:remove_name(name) remove name from either .names or .extras 2 => 1 - ok, 0 - not present, E_PERM 2 2 For setting or retrieving values we have 2 2 pkg:get(options,name) 2 => value (or 0 if name isn't a real option) 2 pkg:set(options,name,value) 2 => revised options (or string error message if something goes wrong) 2 2 By default, a given option can only be a boolean flag, having one of the values 0 (absent from the list), or 1 (present in the list). :set translates 0/""/{} to 0 and any other non-object value to 1. 2 2 One may however designate a wider range of possible values for an option "foo" by either installing one of 2 2 pkg.type_foo 2 -- list of allowed types, 2 e.g., {NUM,STR} => must be a number or a string 2 e.g., {OBJ,{OBJ}} => must be an object or a list of objects 2 for anything fancier use: 2 2 pkg:check_foo(value) 2 => string error message or {value munged as desired} 2 2 In general, the only restriction on option values is that 0 is the only false value; setting an option to "" or {} sets it to 0. Every option defaults to 0, and no matter what you install as .type_foo or :check_foo(), 0 will always be a legal value for option "foo". 2 2 When presented with an option that is in .extras, :set will typecheck the value as described, however, then :actual(name, value) will be called to obtain a list of {name-of-real-option, value} pairs indicating which combination of real options should be set. 2 2 Other verbs 2 pkg:parse(args,...) 2 parses the command line arguments of a @whatever_option command 2 => {optionname, value} if the player wants to set an option 2 => {optionname} if the player wants to view an option 2 => string error message otherwise 2 2 one may install pkg:parse_foo to parse arguments for option "foo" 2 !foo => {"foo",0} (:parse_foo not called) 2 foo= => {"foo",0} (:parse_foo not called) 2 -foo => {"foo",0} (:parse_foo not called) 2 +foo => pkg:parse_foo("foo",1) 2 foo=word => pkg:parse_foo("foo","word") 2 foo word1 word2 => pkg:parse_foo("foo",{"word1","word2"}) 2 foo is word1 word2 => pkg:parse_foo("foo",{"word1","word2"}) 2 2 pkg:show(options,name|list of names) 2 => list of strings describing the current value of the named option(s). 2 calls pkg:show_foo(options,list of names) or 2 refers to pkg.show_foo 2 to describe option "foo" 2 2 (see sources for details... at some point I'll finish writing this... --Rog) 36 5 4 24 2 Message Sequences 2 ----------------- 2 A "message sequence" is a handle by which one may refer to a particular subset of a mail recipient's (player or $mail_recipient-descendant) saved messages. Routines like rcpt:display_seq_headers or rcpt:display_seq_full need to be supplied with message-sequence arguments to deterimine which headers or full-messages to display. 2 2 Message sequences can in turn be obtained from routines like rcpt:parse_message_seq, which takes a command-line description of a message sequence on that particular recipient and returns the corresponding message sequence handle. 2 2 The actual form of a message sequence (though you shouldn't actually need to make use of this) is that of a set of integers in the format used by $seq_utils (see `help $seq_utils'). It should however be noted that these integers are *not* themselves message numbers, but rather indices into the list of saved messages. For example, if a particular recipient holds 5 messages numbered 1,3,5,7,9. Then the message sequence handle representing messages 3,5,7 collectively, would be {2,5} which is $seq_utils-ese for the range 2..4, namely the second, third and fourth messages saved on that recipient. 2 2 The following verbs are available for obtaining indices to use in message sequences 2 2 :length_all_msgs() => total number of messages, or equivalently, 2 => index of last message 2 :length_num_le(n) => number of messages numbered <= n, or equivalently, 2 => index of highest numbered message <= n 2 :exists_num_eq(n) => 0 unless there exists a message numbered n in which 2 case we return the index of that message. 2 :length_date_le(date) => number of messages dated <= date, or equivalently, 2 => index of most recent message dated <= date 2 2 :length_date_gt(date) => number of messages dated > date 2 2 Note that r:length_date_gt(date) == r:length_all_msgs()-r:length_date_le(date). 2 The only reason :length_date_gt is provided as a separate routine is in order 2 to do quick checks for the existence of new mail (as @rn needs to do). 36 5 4 24 2 Read verbs 2 ---------- 2 The following verbs may be used to extract headers/messages from readable mail recipients/players; 2 2 :display_seq_headers (message sequence, current message number, last_read_date) 2 Does a @mail listing of the given message sequence. If current message 2 number is given and the sequence includes it, we mark it with a `>'. 2 Likewise if the sequence includes any new messages (i.e., dated after 2 last_read_date), these are also indicated as such. 2 2 display_seq_full (message sequence, preamble) 2 Does a @read listing of the given message sequence. Each message is preceded 2 by preamble. 2 => {new current message number, new last_read_date} 2 2 :messages_in_seq (index) 2 => {n, msg} 2 :messages_in_seq (message sequence) 2 => {{n_1,msg_1},{n_2,msg_2},...} 2 where the n_i are message numbers and the msg_i are messages in transmission 2 format (see `help mail-format') 2 2 :list_rmm () 2 Does an `@unrmm list' listing of messages in .messages_going 36 5 4 17 2 Write verbs 2 ----------- 2 The following verbs can be used to manipulate writable mail recipients/players: 2 2 :rm_message_seq (message sequence) 2 Does an @rmmail. Messages in message sequence are removed from this 2 recipient's saved .messages and written to .messages_going. 2 2 :undo_rmm () 2 Does an @unrmm. Messages in .messages_going are copied back to .messages. 2 2 :expunge_rmm () 2 Does an @unrmm expunge. Blows away .messages_going. 2 2 :renumber () 2 Does a @renumber. 2 36 5 4 25 2 Search verbs 2 ------------ 2 The following verbs can be used on a readable mail-recipient/player to search for messages with fields matching a given pattern. 2 2 from_msg_seq (objectid or list [,mask]) 2 => message sequence: messages from (one of) the given objectid(s) 2 2 %from_msg_seq (string or list [,mask]) 2 => message sequence: messages with (one of) the given string(s) 2 in the From: line 2 2 to_msg_seq (objectid or list [,mask]) 2 => message sequence: messages to (one of) the given objectid(s) 2 2 %to_msg_seq (string or list [,mask]) 2 => message sequence: messages with (one of) the given string(s) 2 in the To: line 2 2 subject_msg_seq (string [,mask]) 2 => message sequence: messages with given string occurring in Subject: 2 2 body_msg_seq (string [,mask]) 2 => message sequence: messages with given string occurring in body of message 2 2 In all cases `mask' is a message sequence which one may supply to limit the range of the search. One way of looking at it is that the message sequence to be returned is first intersected with mask. 36 5 4 44 2 The housekeeper is an object that can help keep other objects where they belong. New MOOs may want to add their own user interface for the housekeeper; here is some information that may be helpful. 2 2 To indicate what objects should be cleaned: 2 2 :add_cleanup(object[, requestor[, where]]) 2 Ask the housekeeper to clean 'object' for 'requestor' to 'where'. 2 Requestor defaults to 'player'. 2 Where defaults to object.location. 2 2 :remove_cleanup(what[, requestor]) 2 Remove 'what' from the cleanup list at 'requestor's request. 2 Will remove it only if 'requestor' made the original request and owns 2 the object or the destination. 2 2 To actually get the housekeeper to clean stuff up: 2 2 :cleanup([insist]) 2 Clean up player's objects. Argument is 'up' or 'up!' for manually 2 requested cleanups. 'up!' means to clean things even if it's against 2 the housekeeper's better judgement. 2 2 :replace(object[, insist]) 2 Clean up the indicated object. 'insist' is as in :cleanup. 2 2 :litterbug() 2 Clean up all the places in housekeeper.public_places by getting rid of 2 all contents not in their .residents lists. This is called by 2 :continuous, so it doesn't need to be called directly. 2 2 @begin $housekeeper at (delay in seconds) 2 This verb relies on the $scheduler for continuous operation. 2 Starts the housekeeper cleaning continuously, killing any previous 2 continuous task. This should be called only when starting up a new MOO, 2 or if something has gone wrong, as normally it will just keep going 2 without any help. 2 2 To find out what's being cleaned to where for whom: 2 2 :cleanup_list([whom]) 2 Show 'player' the personal cleanup list for 'whom', or the housekeeper's 2 complete list if no argument is given. 2 2 :clean_status() 2 Show 'player' a brief summary of eir personal cleanup list. 36 5 4 28 2 $recycler 2 ========= 2 2 Rather than having the server built-in recycle() and create() functions handle the creation and destruction of objects, a recycling center has been created to simulate these actions by changing objects that would have been recycled into children of $garbage (The Generic Garbage Object) and making them owned by Hacker, and then when they're needed again, to avoid a raw create() command, those objects are given to whoever's asking for them. 2 2 Most Useful Verbs 2 ----------------- 2 2 $recycler:_recycle( object ) 2 This will effectively recycle an object. (As a point of fact, it changes ownership of the object to Hacker and makes the object a child of $garbage.) It handles .ownership_quota and .owned_objects properly. Generally, use this instead of a recycle() in your verbs. 2 2 $recycler:_create( parent object [ , new owner object ] ) 2 This effectively creates an object (with the specified parent, if possible, and with the specified owner, if possible; these are the same restrictions as on the server create() builtin). This is what should generally be used instead of create() in your programming. 2 2 $recycler:valid ( object ) 2 This is a variant of the server built-in valid() except that it handles the $garbage objects as well. It returns a 1 if the object specified -is- valid and is -not- a $garbage object. 2 2 Other Notes 2 ----------- 2 2 request from 2 This is not an internal verb (it's !x). It is, however, a command-line verb that can be used to request a specific object from the recycler. It's also useful for the creation of objects like a Magic Number Repository. When the object is removed from the recycler, the .announce_removal_msg is announced to the room if it's set (it's piped through $string_utils for pronoun substitution). 2 2 show-history 2 This is a wizardly verb which allows wizards to check the `history list' of the recycler. The history maintains the latest ($recycler.nhist) entries. 2 2 $recycler.orphans 2 This maintains a list of objects for which the recreation process got mangled. It ought to be checked every once in a while to see what's up. 2 1 4 10 2 $error 2 ====== 2 2 The Error Generator, $error, may be used to automatically generate errors. This is particularly useful if you are working in a !d verb but have occasion to -want- to crash with traceback. To raise a specific error, use $error:raise(error type) -- for example, $error:raise(E_PERM) will produce traceback resulting from a Permission Denied error. 2 2 Random notes about $error: 2 2 + The complete list of errors is stored in $error.names. 2 + The seemingly useless :accept() verb on $error is so that $error:E_RECMOVE and $error:E_NACC will be guaranteed success (success meaning, of course, a termination by traceback). 2 + There is, unfortunately, no way to raise the error E_NONE. 2 1 4 72 2 Generic BigList Utilities 2 ---------------------------- 2 $biglist is a collection of routines for maintaining huge persistent (sorted) lists in a format that is less likely to spam the server (which runs into a certain amount of trouble dealing with long ordinary lists --- btw we use `biglist' to refer to the huge data structure we're about to describe and `list' to refer to ordinary MOO lists {...}). The biglist in question lives on a particular object, to which we will refer in the discussion below as the `home' object, and its various elements appear as leaves of a tree whose nodes are kept in properties of the home object. It should be noted that the home object does not need to be (and in fact should *not* be) a descendant of $biglist one; $biglist merely provides utilities for manipulating the properties on the home object that are used in a particular biglist manipulation. 2 2 All of the utilities below refer to `caller' to locate the home object. Thus verbs to manipulate a given biglist must be located on or inherited by its home object itself. The home object needs to define the following verbs 2 2 :_make(@args) => new property on home object with value args 2 :_kill(prop) delete a given property that was created by :_make 2 :_get(prop) => home.prop 2 :_put(prop,@args) set home.prop = args 2 :_ord(element) given something that is of the form of a biglist element 2 return the corresponding ordinal (for sorting purposes). 2 If you never intend to use :find_ord, then this can be a 2 routine that always returns 0 or some other random value. 2 2 See $generic_biglist_home or $big_mail_recipient for examples. 2 2 Those of the following routines that take a biglist argument are expecting 2 either {} (empty biglist) or some biglist returned by one of the other routines 2 2 :length(biglist) => length(biglist) (i.e., number of elements) 2 :find_nth(biglist,n) => biglist[n] 2 :find_ord(biglist,k,comp) => n where n is 2 the largest such that home:(comp)(k,home:_ord(biglist[n])) is false, or 2 the smallest such that home:(comp)(k,home:_ord(biglist[n+1])) is true. 2 Always returns a value between 0 and length(biglist) inclusive. 2 This assumes biglist to be sorted in order of increasing :_ord values 2 with respect to home:(comp)(). 2 Standard situation is :_ord returns a number and comp is a < verb. 2 2 :start(biglist,s,e) => {biglist[s..?],@handle} or {} 2 :next(@handle) => {biglist[?+1..??],@newhandle} or {} 2 These two are used for iterating over a range of elements of a biglist 2 The canonical incantation for doing 2 for elt in (biglist[first..last]) 2 ... 2 endfor 2 is 2 handle = :start(biglist,first,last); 2 while(handle) 2 for elt in (handle[1]) 2 ... 2 endfor 2 handle = :next(@listdelete(handle,1)); 2 endwhile 2 2 The following all destructively modify their biglist argument(s) L (and M). 2 2 :set_nth(L,n,value) => L[n] = value 2 replaces the indicated element 2 2 :insert_before(L,M,n) => {@L[1..n-1],@M,@L[n..length(L)]} 2 :insert_after (L,M,n) => {@L[1..n], @M,@L[n+1..length(L)]} 2 takes two distinct biglists, inserts one into the other at the given point 2 returns the resulting consolidated biglist 2 2 :extract_range(L,m,n) => {{@L[1..m-1],@L[n+1..]}, L[m..n]} 2 breaks the given biglist into two distinct biglists. 2 2 :delete_range(L,m,n[,leafkiller]) => {@L[1..m-1],@L[n+1..]} 2 :keep_range (L,m,n[,leafkiller]) => L[m..n] 2 like extract_range only we destroy what we don't want. 2 2 :insertlast(L,value) => {@L,value} 2 inserts a new element at the end of biglist. 2 If find_ord is to continue to work properly, it is assumed that the 2 home:_ord(elt) is greater (comp-wise) than all of the :_ord values 2 of elements currently in the biglist. 2 2 :kill(L[,leafkiller]) 2 destroys all nodes used by biglist. 2 Calls home:leafkiller on each element. 36 1 4 17 2 $guest_log 2 2 records guest connect/disconnect events. 2 2 .max_events -- maximum number of connect/disconnect events kept 2 .connections -- actual list of events, the most recent ones first 2 each element is of the form 2 {object, is_connect, time, site} 2 object is the particular guest that (dis)connected 2 is_connect 1 or 0 according as this is a connect or not. 2 2 :find(who,when) 2 => site name of WHO at the particular time 2 (or 0 if WHO was not logged in then) 2 2 :last(n) 2 prints a listing of the last n events 36 5 4 2 2 *forward* 2 mail-resolve 36 5 4 32 2 *subst* 2 $news 2 ----- 2 This object is a mail_recipient like any other (see `help $mail_recipient'). One may send messages to it and use the usual recipient manipulation commands (@mail, @read, @rmm,...). 2 2 Selected messages on this recipient are ordered in reverse date order (i.e., most recent first) and concatenated to produce the "news" that is printed in response to the player `news' command. Each news item is thus a distinct message. The default $player:confunc checks to see if any new messages have been selected for inclusion in the "news" since the player last read the news. 2 2 The property $news.current_news holds the message sequence of messages currently considered as comprising "the news". The following commands are used to change .current_news: 2 2 @addnews to %[$news] 2 @rmnews from %[$news] 2 @setnews %[$news] to 2 2 @addnews includes the specified messages, @rmnews excludes the specified messages, and @setnews changes .current_news to be the given message sequence. Note that these ONLY change whether a given message is marked as being "in the news" and do not actually add or remove messages from the mail recipient $news. 2 2 The procedure for adding a news article is 2 2 Send a mail message to %[$mail_agent:name($news)] 2 @addnews last to %[$news] 2 This marks the message as belonging to the current newspaper. 2 This also announces to any player who have not yet read this message 2 that there is a new version of the newspaper. 2 2 The preferred method for updating a news items is to send a new version of the item, @rmnews the old version and @addnews the new one. 2 2 The following ordinary mail commands behave differently 2 @rmm removes any reference to message from .current_news 2 in addition to removing the message itself from .messages 2 @unrmm completely undoes the effect of the previous @rmm; 2 this includes restoring .current_news. 2 2 By default, the newspaper is moderated, however there is the possibility of unmoderating it (see `help MR-access'), letting arbitrary players send mail to it; administrators could then @addnews those items deemed worthy. 36 5 4 2 2 *forward* 2 object-matching 36 5 4 32 2 The mail messages stored in mail recipients may be removed automatically by a weekly expiration task. New core owners who wish to turn this feature on and cut down on the db space used by mail recipients (Remember, players are mail recipients too) should start this task: 2 2 $wiz_utils:expire_mail_weekly 2 2 When this task runs, it searches through all mail recipients and checks their .expire_period property. This property contains a time, in seconds, that messages should expire after. If this property is set to 0, then no expiration will take place from that recipient. The task, then, will compile a list of messages that are older than the expire period (e.g., if the property is set to 30 days, messages older than 30 days from the current date will expire). The default expiration period for mail recipients is 30 days. 2 2 Normally, when the mail messages are expired from the recipient they are deleted. However, the owner of the recipient may elect to have the messages mailed to an email address prior to their erasure. There are two methods for doing this, one for players and one for children of $mail_recipient. 2 2 Players: 2 2 Players may completely turn off mail expiration by setting the mail option `expire' off. If it is on, then $mail_agent.player_expire_time is the expire period used for mail on players. 2 If a player has a registered email address, he may simply turn the mail option `no_auto_forward' off in order to have the expired messages sent to his email address before they are deleted. (The reversed logic saves on db space). See `help mail-options' and `help @registerme'. 2 2 Mail Recipients: 2 2 The command to set the expiration period of a mail recipient is: 2 2 @set_expire to