rom24-quickmud-python 2.5.4__tar.gz → 2.7.0__tar.gz

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (1000) hide show
  1. rom24_quickmud_python-2.7.0/CHANGELOG.md +1315 -0
  2. rom24_quickmud_python-2.7.0/PKG-INFO +417 -0
  3. rom24_quickmud_python-2.7.0/README.md +364 -0
  4. rom24_quickmud_python-2.7.0/data/areas/air.json +1420 -0
  5. rom24_quickmud_python-2.7.0/data/areas/arachnos.json +2286 -0
  6. rom24_quickmud_python-2.7.0/data/areas/astral.json +6075 -0
  7. rom24_quickmud_python-2.7.0/data/areas/canyon.json +4744 -0
  8. rom24_quickmud_python-2.7.0/data/areas/catacomb.json +3500 -0
  9. rom24_quickmud_python-2.7.0/data/areas/chapel.json +3598 -0
  10. rom24_quickmud_python-2.7.0/data/areas/daycare.json +1402 -0
  11. rom24_quickmud_python-2.7.0/data/areas/draconia.json +3583 -0
  12. rom24_quickmud_python-2.7.0/data/areas/dream.json +1671 -0
  13. rom24_quickmud_python-2.7.0/data/areas/drow.json +2349 -0
  14. rom24_quickmud_python-2.7.0/data/areas/dwarven.json +3009 -0
  15. rom24_quickmud_python-2.7.0/data/areas/dylan.json +2768 -0
  16. rom24_quickmud_python-2.7.0/data/areas/eastern.json +2895 -0
  17. rom24_quickmud_python-2.7.0/data/areas/galaxy.json +4132 -0
  18. rom24_quickmud_python-2.7.0/data/areas/gnome.json +4421 -0
  19. rom24_quickmud_python-2.7.0/data/areas/grave.json +1808 -0
  20. rom24_quickmud_python-2.7.0/data/areas/grove.json +1806 -0
  21. rom24_quickmud_python-2.7.0/data/areas/haon.json +3761 -0
  22. rom24_quickmud_python-2.7.0/data/areas/hitower.json +11474 -0
  23. rom24_quickmud_python-2.7.0/data/areas/hood.json +4145 -0
  24. rom24_quickmud_python-2.7.0/data/areas/immort.json +769 -0
  25. rom24_quickmud_python-2.7.0/data/areas/limbo.json +480 -0
  26. rom24_quickmud_python-2.7.0/data/areas/mahntor.json +7795 -0
  27. rom24_quickmud_python-2.7.0/data/areas/marsh.json +1696 -0
  28. rom24_quickmud_python-2.7.0/data/areas/mega1.json +2079 -0
  29. rom24_quickmud_python-2.7.0/data/areas/midennir.json +2027 -0
  30. rom24_quickmud_python-2.7.0/data/areas/midgaard.json +12771 -0
  31. rom24_quickmud_python-2.7.0/data/areas/mirror.json +6112 -0
  32. rom24_quickmud_python-2.7.0/data/areas/mobfact.json +1045 -0
  33. rom24_quickmud_python-2.7.0/data/areas/moria.json +5565 -0
  34. rom24_quickmud_python-2.7.0/data/areas/newthalos.json +14363 -0
  35. rom24_quickmud_python-2.7.0/data/areas/nirvana.json +2236 -0
  36. rom24_quickmud_python-2.7.0/data/areas/ofcol.json +284 -0
  37. rom24_quickmud_python-2.7.0/data/areas/ofcol2.json +7288 -0
  38. rom24_quickmud_python-2.7.0/data/areas/olympus.json +3575 -0
  39. rom24_quickmud_python-2.7.0/data/areas/plains.json +2000 -0
  40. rom24_quickmud_python-2.7.0/data/areas/pyramid.json +4093 -0
  41. rom24_quickmud_python-2.7.0/data/areas/redferne.json +804 -0
  42. rom24_quickmud_python-2.7.0/data/areas/school.json +3380 -0
  43. rom24_quickmud_python-2.7.0/data/areas/sewer.json +7500 -0
  44. rom24_quickmud_python-2.7.0/data/areas/shire.json +3994 -0
  45. rom24_quickmud_python-2.7.0/data/areas/smurf.json +1697 -0
  46. rom24_quickmud_python-2.7.0/data/areas/thalos.json +3828 -0
  47. rom24_quickmud_python-2.7.0/data/areas/tohell.json +8843 -0
  48. rom24_quickmud_python-2.7.0/data/areas/trollden.json +794 -0
  49. rom24_quickmud_python-2.7.0/data/areas/valley.json +4291 -0
  50. rom24_quickmud_python-2.7.0/data/areas/wyvern.json +3366 -0
  51. rom24_quickmud_python-2.7.0/mud/__init__.py +1 -0
  52. rom24_quickmud_python-2.7.0/mud/account/__init__.py +74 -0
  53. rom24_quickmud_python-2.7.0/mud/account/account_manager.py +108 -0
  54. rom24_quickmud_python-2.7.0/mud/account/account_service.py +1100 -0
  55. rom24_quickmud_python-2.7.0/mud/admin_logging/__init__.py +1 -0
  56. rom24_quickmud_python-2.7.0/mud/advancement.py +229 -0
  57. rom24_quickmud_python-2.7.0/mud/agent/__init__.py +1 -0
  58. rom24_quickmud_python-2.7.0/mud/ai/__init__.py +381 -0
  59. rom24_quickmud_python-2.7.0/mud/combat/assist.py +211 -0
  60. rom24_quickmud_python-2.7.0/mud/combat/engine.py +1534 -0
  61. rom24_quickmud_python-2.7.0/mud/commands/admin_commands.py +491 -0
  62. rom24_quickmud_python-2.7.0/mud/commands/advancement.py +395 -0
  63. rom24_quickmud_python-2.7.0/mud/commands/affects.py +182 -0
  64. rom24_quickmud_python-2.7.0/mud/commands/alias_cmds.py +140 -0
  65. rom24_quickmud_python-2.7.0/mud/commands/auto_settings.py +446 -0
  66. rom24_quickmud_python-2.7.0/mud/commands/build.py +3267 -0
  67. rom24_quickmud_python-2.7.0/mud/commands/character.py +219 -0
  68. rom24_quickmud_python-2.7.0/mud/commands/combat.py +947 -0
  69. rom24_quickmud_python-2.7.0/mud/commands/communication.py +642 -0
  70. rom24_quickmud_python-2.7.0/mud/commands/consumption.py +353 -0
  71. rom24_quickmud_python-2.7.0/mud/commands/dispatcher.py +1051 -0
  72. rom24_quickmud_python-2.7.0/mud/commands/doors.py +605 -0
  73. rom24_quickmud_python-2.7.0/mud/commands/equipment.py +599 -0
  74. rom24_quickmud_python-2.7.0/mud/commands/give.py +249 -0
  75. rom24_quickmud_python-2.7.0/mud/commands/group_commands.py +498 -0
  76. rom24_quickmud_python-2.7.0/mud/commands/healer.py +247 -0
  77. rom24_quickmud_python-2.7.0/mud/commands/imm_admin.py +320 -0
  78. rom24_quickmud_python-2.7.0/mud/commands/imm_commands.py +489 -0
  79. rom24_quickmud_python-2.7.0/mud/commands/imm_display.py +328 -0
  80. rom24_quickmud_python-2.7.0/mud/commands/imm_emote.py +221 -0
  81. rom24_quickmud_python-2.7.0/mud/commands/imm_load.py +402 -0
  82. rom24_quickmud_python-2.7.0/mud/commands/imm_olc.py +561 -0
  83. rom24_quickmud_python-2.7.0/mud/commands/imm_punish.py +262 -0
  84. rom24_quickmud_python-2.7.0/mud/commands/imm_search.py +1137 -0
  85. rom24_quickmud_python-2.7.0/mud/commands/imm_server.py +255 -0
  86. rom24_quickmud_python-2.7.0/mud/commands/imm_set.py +593 -0
  87. rom24_quickmud_python-2.7.0/mud/commands/info.py +593 -0
  88. rom24_quickmud_python-2.7.0/mud/commands/info_extended.py +300 -0
  89. rom24_quickmud_python-2.7.0/mud/commands/inspection.py +287 -0
  90. rom24_quickmud_python-2.7.0/mud/commands/inventory.py +885 -0
  91. rom24_quickmud_python-2.7.0/mud/commands/liquids.py +321 -0
  92. rom24_quickmud_python-2.7.0/mud/commands/magic_items.py +362 -0
  93. rom24_quickmud_python-2.7.0/mud/commands/misc_player.py +274 -0
  94. rom24_quickmud_python-2.7.0/mud/commands/movement.py +98 -0
  95. rom24_quickmud_python-2.7.0/mud/commands/notes.py +480 -0
  96. rom24_quickmud_python-2.7.0/mud/commands/obj_manipulation.py +713 -0
  97. rom24_quickmud_python-2.7.0/mud/commands/player_info.py +223 -0
  98. rom24_quickmud_python-2.7.0/mud/commands/position.py +466 -0
  99. rom24_quickmud_python-2.7.0/mud/commands/remaining_rom.py +564 -0
  100. rom24_quickmud_python-2.7.0/mud/commands/session.py +414 -0
  101. rom24_quickmud_python-2.7.0/mud/commands/shop.py +1058 -0
  102. rom24_quickmud_python-2.7.0/mud/commands/socials.py +85 -0
  103. rom24_quickmud_python-2.7.0/mud/commands/thief_skills.py +441 -0
  104. rom24_quickmud_python-2.7.0/mud/commands/typo_guards.py +62 -0
  105. rom24_quickmud_python-2.7.0/mud/db/__init__.py +1 -0
  106. rom24_quickmud_python-2.7.0/mud/db/migrations.py +63 -0
  107. rom24_quickmud_python-2.7.0/mud/db/models.py +132 -0
  108. rom24_quickmud_python-2.7.0/mud/db/seed.py +27 -0
  109. rom24_quickmud_python-2.7.0/mud/devtools/__init__.py +1 -0
  110. rom24_quickmud_python-2.7.0/mud/game_loop.py +1224 -0
  111. rom24_quickmud_python-2.7.0/mud/handler.py +1685 -0
  112. rom24_quickmud_python-2.7.0/mud/loaders/json_loader.py +818 -0
  113. rom24_quickmud_python-2.7.0/mud/loaders/mob_loader.py +255 -0
  114. rom24_quickmud_python-2.7.0/mud/magic/effects.py +782 -0
  115. rom24_quickmud_python-2.7.0/mud/math/stat_apps.py +294 -0
  116. rom24_quickmud_python-2.7.0/mud/mob_cmds.py +1391 -0
  117. rom24_quickmud_python-2.7.0/mud/mobprog.py +1766 -0
  118. rom24_quickmud_python-2.7.0/mud/models/board.py +179 -0
  119. rom24_quickmud_python-2.7.0/mud/models/character.py +1230 -0
  120. rom24_quickmud_python-2.7.0/mud/models/clans.py +85 -0
  121. rom24_quickmud_python-2.7.0/mud/models/constants.py +1059 -0
  122. rom24_quickmud_python-2.7.0/mud/models/object.py +87 -0
  123. rom24_quickmud_python-2.7.0/mud/models/races.py +551 -0
  124. rom24_quickmud_python-2.7.0/mud/models/room.py +204 -0
  125. rom24_quickmud_python-2.7.0/mud/models/social.py +120 -0
  126. rom24_quickmud_python-2.7.0/mud/music/__init__.py +264 -0
  127. rom24_quickmud_python-2.7.0/mud/net/ansi.py +88 -0
  128. rom24_quickmud_python-2.7.0/mud/net/connection.py +2055 -0
  129. rom24_quickmud_python-2.7.0/mud/net/session.py +173 -0
  130. rom24_quickmud_python-2.7.0/mud/network/__init__.py +1 -0
  131. rom24_quickmud_python-2.7.0/mud/network/websocket_server.py +73 -0
  132. rom24_quickmud_python-2.7.0/mud/network/websocket_stream.py +162 -0
  133. rom24_quickmud_python-2.7.0/mud/notes.py +348 -0
  134. rom24_quickmud_python-2.7.0/mud/olc/editor_state.py +79 -0
  135. rom24_quickmud_python-2.7.0/mud/olc/save.py +534 -0
  136. rom24_quickmud_python-2.7.0/mud/persistence.py +1239 -0
  137. rom24_quickmud_python-2.7.0/mud/rom_api.py +677 -0
  138. rom24_quickmud_python-2.7.0/mud/scripts/convert_are_to_json.py +235 -0
  139. rom24_quickmud_python-2.7.0/mud/scripts/load_test_data.py +9 -0
  140. rom24_quickmud_python-2.7.0/mud/security/__init__.py +1 -0
  141. rom24_quickmud_python-2.7.0/mud/security/bans.py +311 -0
  142. rom24_quickmud_python-2.7.0/mud/skills/handlers.py +7924 -0
  143. rom24_quickmud_python-2.7.0/mud/skills/registry.py +396 -0
  144. rom24_quickmud_python-2.7.0/mud/spawning/mob_spawner.py +20 -0
  145. rom24_quickmud_python-2.7.0/mud/spawning/reset_handler.py +841 -0
  146. rom24_quickmud_python-2.7.0/mud/spawning/templates.py +553 -0
  147. rom24_quickmud_python-2.7.0/mud/spec_funs.py +1529 -0
  148. rom24_quickmud_python-2.7.0/mud/utils/bit.py +122 -0
  149. rom24_quickmud_python-2.7.0/mud/utils/fix_sex.py +24 -0
  150. rom24_quickmud_python-2.7.0/mud/utils/olc_tables.py +127 -0
  151. rom24_quickmud_python-2.7.0/mud/utils/poses.py +187 -0
  152. rom24_quickmud_python-2.7.0/mud/utils/prefix_lookup.py +217 -0
  153. rom24_quickmud_python-2.7.0/mud/utils/prompt.py +169 -0
  154. rom24_quickmud_python-2.7.0/mud/utils/string_editor.py +581 -0
  155. rom24_quickmud_python-2.7.0/mud/wiznet.py +324 -0
  156. rom24_quickmud_python-2.7.0/mud/world/char_find.py +132 -0
  157. rom24_quickmud_python-2.7.0/mud/world/look.py +402 -0
  158. rom24_quickmud_python-2.7.0/mud/world/movement.py +659 -0
  159. rom24_quickmud_python-2.7.0/mud/world/obj_find.py +201 -0
  160. rom24_quickmud_python-2.7.0/mud/world/world_state.py +257 -0
  161. rom24_quickmud_python-2.7.0/pyproject.toml +144 -0
  162. rom24_quickmud_python-2.7.0/rom24_quickmud_python.egg-info/PKG-INFO +417 -0
  163. rom24_quickmud_python-2.7.0/rom24_quickmud_python.egg-info/SOURCES.txt +781 -0
  164. rom24_quickmud_python-2.7.0/tests/integration/conftest.py +105 -0
  165. rom24_quickmud_python-2.7.0/tests/integration/test_act_comm_gaps.py +285 -0
  166. rom24_quickmud_python-2.7.0/tests/integration/test_act_enter_gaps.py +684 -0
  167. rom24_quickmud_python-2.7.0/tests/integration/test_act_wiz_command_parity.py +1587 -0
  168. rom24_quickmud_python-2.7.0/tests/integration/test_advancement_con_app.py +180 -0
  169. rom24_quickmud_python-2.7.0/tests/integration/test_advancement_wis_app.py +136 -0
  170. rom24_quickmud_python-2.7.0/tests/integration/test_alias_command_parity.py +56 -0
  171. rom24_quickmud_python-2.7.0/tests/integration/test_architectural_parity.py +167 -0
  172. rom24_quickmud_python-2.7.0/tests/integration/test_auto_flags.py +521 -0
  173. rom24_quickmud_python-2.7.0/tests/integration/test_ban_command_parity.py +78 -0
  174. rom24_quickmud_python-2.7.0/tests/integration/test_bit_flag_string.py +69 -0
  175. rom24_quickmud_python-2.7.0/tests/integration/test_bit_flag_value.py +81 -0
  176. rom24_quickmud_python-2.7.0/tests/integration/test_bit_is_stat.py +63 -0
  177. rom24_quickmud_python-2.7.0/tests/integration/test_boards_rom_parity.py +430 -0
  178. rom24_quickmud_python-2.7.0/tests/integration/test_character_advancement.py +521 -0
  179. rom24_quickmud_python-2.7.0/tests/integration/test_character_commands.py +275 -0
  180. rom24_quickmud_python-2.7.0/tests/integration/test_character_creation_runtime.py +258 -0
  181. rom24_quickmud_python-2.7.0/tests/integration/test_combat_dex_app.py +113 -0
  182. rom24_quickmud_python-2.7.0/tests/integration/test_combat_str_app.py +210 -0
  183. rom24_quickmud_python-2.7.0/tests/integration/test_communication_enhancement.py +251 -0
  184. rom24_quickmud_python-2.7.0/tests/integration/test_config_commands.py +317 -0
  185. rom24_quickmud_python-2.7.0/tests/integration/test_consumables.py +864 -0
  186. rom24_quickmud_python-2.7.0/tests/integration/test_container_retrieval.py +652 -0
  187. rom24_quickmud_python-2.7.0/tests/integration/test_db2_loader_parity.py +195 -0
  188. rom24_quickmud_python-2.7.0/tests/integration/test_door_portal_commands.py +293 -0
  189. rom24_quickmud_python-2.7.0/tests/integration/test_drop_command.py +311 -0
  190. rom24_quickmud_python-2.7.0/tests/integration/test_equipment_system.py +1202 -0
  191. rom24_quickmud_python-2.7.0/tests/integration/test_flag_command_parity.py +231 -0
  192. rom24_quickmud_python-2.7.0/tests/integration/test_furniture_occupancy.py +255 -0
  193. rom24_quickmud_python-2.7.0/tests/integration/test_get_room_messages.py +303 -0
  194. rom24_quickmud_python-2.7.0/tests/integration/test_give_command.py +324 -0
  195. rom24_quickmud_python-2.7.0/tests/integration/test_group_combat.py +678 -0
  196. rom24_quickmud_python-2.7.0/tests/integration/test_healer_command_parity.py +113 -0
  197. rom24_quickmud_python-2.7.0/tests/integration/test_info_display.py +339 -0
  198. rom24_quickmud_python-2.7.0/tests/integration/test_interp_dispatcher.py +287 -0
  199. rom24_quickmud_python-2.7.0/tests/integration/test_interp_prefix_order.py +128 -0
  200. rom24_quickmud_python-2.7.0/tests/integration/test_interp_trust.py +83 -0
  201. rom24_quickmud_python-2.7.0/tests/integration/test_json_loader_parity.py +723 -0
  202. rom24_quickmud_python-2.7.0/tests/integration/test_lookup_parity.py +132 -0
  203. rom24_quickmud_python-2.7.0/tests/integration/test_mob_ai.py +550 -0
  204. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_assist.py +117 -0
  205. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_call.py +129 -0
  206. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_cast.py +113 -0
  207. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_damage.py +121 -0
  208. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_flee.py +160 -0
  209. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_junk.py +56 -0
  210. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_kill.py +105 -0
  211. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_oload.py +127 -0
  212. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_purge.py +86 -0
  213. rom24_quickmud_python-2.7.0/tests/integration/test_mob_cmds_transfer.py +101 -0
  214. rom24_quickmud_python-2.7.0/tests/integration/test_mobprog_edge_cases.py +317 -0
  215. rom24_quickmud_python-2.7.0/tests/integration/test_mobprog_greet_trigger.py +100 -0
  216. rom24_quickmud_python-2.7.0/tests/integration/test_mobprog_predicates.py +251 -0
  217. rom24_quickmud_python-2.7.0/tests/integration/test_mobprog_program_flow.py +122 -0
  218. rom24_quickmud_python-2.7.0/tests/integration/test_mobprog_scenarios.py +445 -0
  219. rom24_quickmud_python-2.7.0/tests/integration/test_money_objects.py +675 -0
  220. rom24_quickmud_python-2.7.0/tests/integration/test_music_load_songs.py +85 -0
  221. rom24_quickmud_python-2.7.0/tests/integration/test_music_play.py +202 -0
  222. rom24_quickmud_python-2.7.0/tests/integration/test_nanny_login_parity.py +615 -0
  223. rom24_quickmud_python-2.7.0/tests/integration/test_new_player_workflow.py +183 -0
  224. rom24_quickmud_python-2.7.0/tests/integration/test_numbered_get_syntax.py +270 -0
  225. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_001_aedit_create.py +128 -0
  226. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_002_redit_create.py +143 -0
  227. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_003_redit_reset.py +127 -0
  228. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_004_redit_vnum_teleport.py +150 -0
  229. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_005_oedit_create.py +168 -0
  230. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_006_medit_create.py +176 -0
  231. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_007_aedit_show_flags.py +93 -0
  232. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_008_redit_show_parity.py +76 -0
  233. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_009_oedit_show_parity.py +136 -0
  234. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_010_medit_show_parity.py +168 -0
  235. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_011_name_messages.py +70 -0
  236. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_012_aedit_reset.py +33 -0
  237. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_013_get_area_for_vnum_order.py +75 -0
  238. rom24_quickmud_python-2.7.0/tests/integration/test_olc_act_014_area_changed_protocol.py +104 -0
  239. rom24_quickmud_python-2.7.0/tests/integration/test_olc_alist.py +96 -0
  240. rom24_quickmud_python-2.7.0/tests/integration/test_olc_builders.py +383 -0
  241. rom24_quickmud_python-2.7.0/tests/integration/test_olc_descriptor_state.py +76 -0
  242. rom24_quickmud_python-2.7.0/tests/integration/test_olc_display_resets.py +344 -0
  243. rom24_quickmud_python-2.7.0/tests/integration/test_olc_do_resets_subcommands.py +492 -0
  244. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_001_mob_defensive_flags.py +123 -0
  245. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_002_mob_form_parts_size_material.py +125 -0
  246. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_003_mob_mprogs.py +118 -0
  247. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_004_mob_shops.py +130 -0
  248. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_005_mob_spec_fun.py +95 -0
  249. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_006_object_level.py +91 -0
  250. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_007_object_affects.py +147 -0
  251. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_008_object_extra_descr.py +130 -0
  252. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_009_area_helps_round_trip.py +128 -0
  253. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_010_asave_area_dispatch.py +146 -0
  254. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_011_autosave_entry.py +95 -0
  255. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_012_npc_security_gate.py +67 -0
  256. rom24_quickmud_python-2.7.0/tests/integration/test_olc_save_013_area_list_social_prepend.py +77 -0
  257. rom24_quickmud_python-2.7.0/tests/integration/test_pit_timer_handling.py +295 -0
  258. rom24_quickmud_python-2.7.0/tests/integration/test_player_npc_interaction.py +233 -0
  259. rom24_quickmud_python-2.7.0/tests/integration/test_position_commands.py +432 -0
  260. rom24_quickmud_python-2.7.0/tests/integration/test_prompt_rom_parity.py +136 -0
  261. rom24_quickmud_python-2.7.0/tests/integration/test_put_pit_timer.py +499 -0
  262. rom24_quickmud_python-2.7.0/tests/integration/test_put_room_messages.py +496 -0
  263. rom24_quickmud_python-2.7.0/tests/integration/test_put_weight_mult.py +385 -0
  264. rom24_quickmud_python-2.7.0/tests/integration/test_recall_train_commands.py +296 -0
  265. rom24_quickmud_python-2.7.0/tests/integration/test_remove_command.py +226 -0
  266. rom24_quickmud_python-2.7.0/tests/integration/test_room_retrieval.py +377 -0
  267. rom24_quickmud_python-2.7.0/tests/integration/test_runtime_bugs_2026_04_30.py +151 -0
  268. rom24_quickmud_python-2.7.0/tests/integration/test_sacrifice_command.py +214 -0
  269. rom24_quickmud_python-2.7.0/tests/integration/test_scan_broadcasts.py +108 -0
  270. rom24_quickmud_python-2.7.0/tests/integration/test_skills_integration.py +494 -0
  271. rom24_quickmud_python-2.7.0/tests/integration/test_socials.py +558 -0
  272. rom24_quickmud_python-2.7.0/tests/integration/test_spell_affects_persistence.py +719 -0
  273. rom24_quickmud_python-2.7.0/tests/integration/test_steal_command.py +351 -0
  274. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_append.py +110 -0
  275. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_edit.py +70 -0
  276. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_first_arg.py +74 -0
  277. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_format_string.py +147 -0
  278. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_lineadd.py +83 -0
  279. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_linedel.py +68 -0
  280. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_merc_getline.py +53 -0
  281. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_numlines.py +61 -0
  282. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_proper.py +46 -0
  283. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_replace.py +83 -0
  284. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_string_add.py +323 -0
  285. rom24_quickmud_python-2.7.0/tests/integration/test_string_editor_unpad.py +38 -0
  286. rom24_quickmud_python-2.7.0/tests/integration/test_tables_001_affect_migration.py +139 -0
  287. rom24_quickmud_python-2.7.0/tests/integration/test_tables_parity.py +218 -0
  288. rom24_quickmud_python-2.7.0/tests/test_account_auth.py +2535 -0
  289. rom24_quickmud_python-2.7.0/tests/test_advancement.py +428 -0
  290. rom24_quickmud_python-2.7.0/tests/test_affects.py +451 -0
  291. rom24_quickmud_python-2.7.0/tests/test_alias_parity.py +225 -0
  292. rom24_quickmud_python-2.7.0/tests/test_ansi.py +28 -0
  293. rom24_quickmud_python-2.7.0/tests/test_area_exits.py +20 -0
  294. rom24_quickmud_python-2.7.0/tests/test_area_loader.py +1140 -0
  295. rom24_quickmud_python-2.7.0/tests/test_bans.py +63 -0
  296. rom24_quickmud_python-2.7.0/tests/test_boards.py +835 -0
  297. rom24_quickmud_python-2.7.0/tests/test_combat.py +767 -0
  298. rom24_quickmud_python-2.7.0/tests/test_combat_death.py +875 -0
  299. rom24_quickmud_python-2.7.0/tests/test_commands.py +421 -0
  300. rom24_quickmud_python-2.7.0/tests/test_communication.py +494 -0
  301. rom24_quickmud_python-2.7.0/tests/test_db_resets_rom_parity.py +1123 -0
  302. rom24_quickmud_python-2.7.0/tests/test_db_seed.py +25 -0
  303. rom24_quickmud_python-2.7.0/tests/test_encumbrance.py +407 -0
  304. rom24_quickmud_python-2.7.0/tests/test_enter_portal.py +21 -0
  305. rom24_quickmud_python-2.7.0/tests/test_fix_sex.py +44 -0
  306. rom24_quickmud_python-2.7.0/tests/test_game_loop.py +627 -0
  307. rom24_quickmud_python-2.7.0/tests/test_game_loop_order.py +61 -0
  308. rom24_quickmud_python-2.7.0/tests/test_game_loop_wait_daze.py +63 -0
  309. rom24_quickmud_python-2.7.0/tests/test_healer.py +53 -0
  310. rom24_quickmud_python-2.7.0/tests/test_healer_parity.py +199 -0
  311. rom24_quickmud_python-2.7.0/tests/test_healer_rom_parity.py +98 -0
  312. rom24_quickmud_python-2.7.0/tests/test_help_system.py +355 -0
  313. rom24_quickmud_python-2.7.0/tests/test_inventory_persistence.py +27 -0
  314. rom24_quickmud_python-2.7.0/tests/test_mobprog_commands.py +679 -0
  315. rom24_quickmud_python-2.7.0/tests/test_movement_followers.py +150 -0
  316. rom24_quickmud_python-2.7.0/tests/test_movement_portals.py +140 -0
  317. rom24_quickmud_python-2.7.0/tests/test_networking_telnet.py +373 -0
  318. rom24_quickmud_python-2.7.0/tests/test_olc_aedit.py +286 -0
  319. rom24_quickmud_python-2.7.0/tests/test_olc_medit.py +489 -0
  320. rom24_quickmud_python-2.7.0/tests/test_olc_oedit.py +402 -0
  321. rom24_quickmud_python-2.7.0/tests/test_player_auto_settings.py +568 -0
  322. rom24_quickmud_python-2.7.0/tests/test_player_equipment.py +680 -0
  323. rom24_quickmud_python-2.7.0/tests/test_player_info_commands.py +207 -0
  324. rom24_quickmud_python-2.7.0/tests/test_player_prompt.py +83 -0
  325. rom24_quickmud_python-2.7.0/tests/test_player_title_description.py +254 -0
  326. rom24_quickmud_python-2.7.0/tests/test_rom_api.py +203 -0
  327. rom24_quickmud_python-2.7.0/tests/test_scan_parity.py +193 -0
  328. rom24_quickmud_python-2.7.0/tests/test_shops.py +1657 -0
  329. rom24_quickmud_python-2.7.0/tests/test_skill_envenom_rom_parity.py +350 -0
  330. rom24_quickmud_python-2.7.0/tests/test_skills.py +960 -0
  331. rom24_quickmud_python-2.7.0/tests/test_spec_funs.py +1501 -0
  332. rom24_quickmud_python-2.7.0/tests/test_spell_creation_rom_parity.py +482 -0
  333. rom24_quickmud_python-2.7.0/tests/test_telnet_server.py +676 -0
  334. rom24_quickmud_python-2.7.0/tests/test_thief_skills_dispatcher_parity.py +89 -0
  335. rom24_quickmud_python-2.7.0/tests/test_websocket_server.py +58 -0
  336. rom24_quickmud_python-2.7.0/tests/test_world.py +47 -0
  337. rom24_quickmud_python-2.5.4/CHANGELOG.md +0 -359
  338. rom24_quickmud_python-2.5.4/PKG-INFO +0 -339
  339. rom24_quickmud_python-2.5.4/README.md +0 -286
  340. rom24_quickmud_python-2.5.4/data/areas/air.json +0 -1418
  341. rom24_quickmud_python-2.5.4/data/areas/arachnos.json +0 -2278
  342. rom24_quickmud_python-2.5.4/data/areas/astral.json +0 -6023
  343. rom24_quickmud_python-2.5.4/data/areas/canyon.json +0 -4682
  344. rom24_quickmud_python-2.5.4/data/areas/catacomb.json +0 -3468
  345. rom24_quickmud_python-2.5.4/data/areas/chapel.json +0 -3550
  346. rom24_quickmud_python-2.5.4/data/areas/daycare.json +0 -1386
  347. rom24_quickmud_python-2.5.4/data/areas/draconia.json +0 -3501
  348. rom24_quickmud_python-2.5.4/data/areas/dream.json +0 -1663
  349. rom24_quickmud_python-2.5.4/data/areas/drow.json +0 -2319
  350. rom24_quickmud_python-2.5.4/data/areas/dwarven.json +0 -2975
  351. rom24_quickmud_python-2.5.4/data/areas/eastern.json +0 -2831
  352. rom24_quickmud_python-2.5.4/data/areas/galaxy.json +0 -4078
  353. rom24_quickmud_python-2.5.4/data/areas/gnome.json +0 -4373
  354. rom24_quickmud_python-2.5.4/data/areas/grove.json +0 -1778
  355. rom24_quickmud_python-2.5.4/data/areas/haon.json +0 -3719
  356. rom24_quickmud_python-2.5.4/data/areas/hitower.json +0 -11284
  357. rom24_quickmud_python-2.5.4/data/areas/hood.json +0 -4107
  358. rom24_quickmud_python-2.5.4/data/areas/immort.json +0 -769
  359. rom24_quickmud_python-2.5.4/data/areas/limbo.json +0 -442
  360. rom24_quickmud_python-2.5.4/data/areas/mahntor.json +0 -7607
  361. rom24_quickmud_python-2.5.4/data/areas/marsh.json +0 -1684
  362. rom24_quickmud_python-2.5.4/data/areas/mega1.json +0 -2045
  363. rom24_quickmud_python-2.5.4/data/areas/midennir.json +0 -2015
  364. rom24_quickmud_python-2.5.4/data/areas/midgaard.json +0 -12451
  365. rom24_quickmud_python-2.5.4/data/areas/mirror.json +0 -6048
  366. rom24_quickmud_python-2.5.4/data/areas/mobfact.json +0 -1045
  367. rom24_quickmud_python-2.5.4/data/areas/moria.json +0 -5507
  368. rom24_quickmud_python-2.5.4/data/areas/newthalos.json +0 -14163
  369. rom24_quickmud_python-2.5.4/data/areas/nirvana.json +0 -2232
  370. rom24_quickmud_python-2.5.4/data/areas/ofcol2.json +0 -7148
  371. rom24_quickmud_python-2.5.4/data/areas/olympus.json +0 -3519
  372. rom24_quickmud_python-2.5.4/data/areas/plains.json +0 -1978
  373. rom24_quickmud_python-2.5.4/data/areas/pyramid.json +0 -4037
  374. rom24_quickmud_python-2.5.4/data/areas/redferne.json +0 -798
  375. rom24_quickmud_python-2.5.4/data/areas/school.json +0 -3334
  376. rom24_quickmud_python-2.5.4/data/areas/sewer.json +0 -7434
  377. rom24_quickmud_python-2.5.4/data/areas/shire.json +0 -3958
  378. rom24_quickmud_python-2.5.4/data/areas/smurf.json +0 -1677
  379. rom24_quickmud_python-2.5.4/data/areas/thalos.json +0 -3750
  380. rom24_quickmud_python-2.5.4/data/areas/tohell.json +0 -8743
  381. rom24_quickmud_python-2.5.4/data/areas/trollden.json +0 -782
  382. rom24_quickmud_python-2.5.4/data/areas/valley.json +0 -4239
  383. rom24_quickmud_python-2.5.4/data/areas/wyvern.json +0 -3324
  384. rom24_quickmud_python-2.5.4/data/areas_backup/ofcol.json +0 -205
  385. rom24_quickmud_python-2.5.4/mud/__init__.py +0 -0
  386. rom24_quickmud_python-2.5.4/mud/account/__init__.py +0 -60
  387. rom24_quickmud_python-2.5.4/mud/account/account_manager.py +0 -135
  388. rom24_quickmud_python-2.5.4/mud/account/account_service.py +0 -978
  389. rom24_quickmud_python-2.5.4/mud/admin_logging/__init__.py +0 -0
  390. rom24_quickmud_python-2.5.4/mud/advancement.py +0 -203
  391. rom24_quickmud_python-2.5.4/mud/agent/__init__.py +0 -0
  392. rom24_quickmud_python-2.5.4/mud/ai/__init__.py +0 -380
  393. rom24_quickmud_python-2.5.4/mud/combat/assist.py +0 -205
  394. rom24_quickmud_python-2.5.4/mud/combat/engine.py +0 -1520
  395. rom24_quickmud_python-2.5.4/mud/commands/admin_commands.py +0 -499
  396. rom24_quickmud_python-2.5.4/mud/commands/advancement.py +0 -224
  397. rom24_quickmud_python-2.5.4/mud/commands/affects.py +0 -149
  398. rom24_quickmud_python-2.5.4/mud/commands/alias_cmds.py +0 -64
  399. rom24_quickmud_python-2.5.4/mud/commands/auto_settings.py +0 -321
  400. rom24_quickmud_python-2.5.4/mud/commands/build.py +0 -2493
  401. rom24_quickmud_python-2.5.4/mud/commands/character.py +0 -207
  402. rom24_quickmud_python-2.5.4/mud/commands/combat.py +0 -947
  403. rom24_quickmud_python-2.5.4/mud/commands/communication.py +0 -604
  404. rom24_quickmud_python-2.5.4/mud/commands/consumption.py +0 -257
  405. rom24_quickmud_python-2.5.4/mud/commands/dispatcher.py +0 -854
  406. rom24_quickmud_python-2.5.4/mud/commands/doors.py +0 -508
  407. rom24_quickmud_python-2.5.4/mud/commands/equipment.py +0 -483
  408. rom24_quickmud_python-2.5.4/mud/commands/give.py +0 -200
  409. rom24_quickmud_python-2.5.4/mud/commands/group_commands.py +0 -393
  410. rom24_quickmud_python-2.5.4/mud/commands/healer.py +0 -78
  411. rom24_quickmud_python-2.5.4/mud/commands/imm_admin.py +0 -280
  412. rom24_quickmud_python-2.5.4/mud/commands/imm_commands.py +0 -463
  413. rom24_quickmud_python-2.5.4/mud/commands/imm_display.py +0 -281
  414. rom24_quickmud_python-2.5.4/mud/commands/imm_emote.py +0 -156
  415. rom24_quickmud_python-2.5.4/mud/commands/imm_load.py +0 -382
  416. rom24_quickmud_python-2.5.4/mud/commands/imm_olc.py +0 -254
  417. rom24_quickmud_python-2.5.4/mud/commands/imm_punish.py +0 -259
  418. rom24_quickmud_python-2.5.4/mud/commands/imm_search.py +0 -593
  419. rom24_quickmud_python-2.5.4/mud/commands/imm_server.py +0 -239
  420. rom24_quickmud_python-2.5.4/mud/commands/imm_set.py +0 -500
  421. rom24_quickmud_python-2.5.4/mud/commands/info.py +0 -591
  422. rom24_quickmud_python-2.5.4/mud/commands/info_extended.py +0 -375
  423. rom24_quickmud_python-2.5.4/mud/commands/inspection.py +0 -279
  424. rom24_quickmud_python-2.5.4/mud/commands/inventory.py +0 -358
  425. rom24_quickmud_python-2.5.4/mud/commands/liquids.py +0 -246
  426. rom24_quickmud_python-2.5.4/mud/commands/magic_items.py +0 -450
  427. rom24_quickmud_python-2.5.4/mud/commands/misc_player.py +0 -274
  428. rom24_quickmud_python-2.5.4/mud/commands/movement.py +0 -87
  429. rom24_quickmud_python-2.5.4/mud/commands/notes.py +0 -469
  430. rom24_quickmud_python-2.5.4/mud/commands/obj_manipulation.py +0 -555
  431. rom24_quickmud_python-2.5.4/mud/commands/player_info.py +0 -183
  432. rom24_quickmud_python-2.5.4/mud/commands/position.py +0 -85
  433. rom24_quickmud_python-2.5.4/mud/commands/remaining_rom.py +0 -571
  434. rom24_quickmud_python-2.5.4/mud/commands/session.py +0 -413
  435. rom24_quickmud_python-2.5.4/mud/commands/shop.py +0 -959
  436. rom24_quickmud_python-2.5.4/mud/commands/socials.py +0 -34
  437. rom24_quickmud_python-2.5.4/mud/commands/thief_skills.py +0 -351
  438. rom24_quickmud_python-2.5.4/mud/commands/typo_guards.py +0 -86
  439. rom24_quickmud_python-2.5.4/mud/db/__init__.py +0 -0
  440. rom24_quickmud_python-2.5.4/mud/db/migrations.py +0 -51
  441. rom24_quickmud_python-2.5.4/mud/db/models.py +0 -142
  442. rom24_quickmud_python-2.5.4/mud/db/seed.py +0 -28
  443. rom24_quickmud_python-2.5.4/mud/devtools/__init__.py +0 -0
  444. rom24_quickmud_python-2.5.4/mud/game_loop.py +0 -1215
  445. rom24_quickmud_python-2.5.4/mud/handler.py +0 -1424
  446. rom24_quickmud_python-2.5.4/mud/loaders/json_loader.py +0 -540
  447. rom24_quickmud_python-2.5.4/mud/loaders/mob_loader.py +0 -187
  448. rom24_quickmud_python-2.5.4/mud/magic/effects.py +0 -775
  449. rom24_quickmud_python-2.5.4/mud/mob_cmds.py +0 -1145
  450. rom24_quickmud_python-2.5.4/mud/mobprog.py +0 -1685
  451. rom24_quickmud_python-2.5.4/mud/models/board.py +0 -156
  452. rom24_quickmud_python-2.5.4/mud/models/character.py +0 -1226
  453. rom24_quickmud_python-2.5.4/mud/models/clans.py +0 -83
  454. rom24_quickmud_python-2.5.4/mud/models/constants.py +0 -1005
  455. rom24_quickmud_python-2.5.4/mud/models/object.py +0 -59
  456. rom24_quickmud_python-2.5.4/mud/models/races.py +0 -534
  457. rom24_quickmud_python-2.5.4/mud/models/room.py +0 -191
  458. rom24_quickmud_python-2.5.4/mud/models/social.py +0 -99
  459. rom24_quickmud_python-2.5.4/mud/music/__init__.py +0 -161
  460. rom24_quickmud_python-2.5.4/mud/net/ansi.py +0 -42
  461. rom24_quickmud_python-2.5.4/mud/net/connection.py +0 -1873
  462. rom24_quickmud_python-2.5.4/mud/net/session.py +0 -165
  463. rom24_quickmud_python-2.5.4/mud/network/__init__.py +0 -0
  464. rom24_quickmud_python-2.5.4/mud/network/websocket_server.py +0 -111
  465. rom24_quickmud_python-2.5.4/mud/notes.py +0 -97
  466. rom24_quickmud_python-2.5.4/mud/olc/save.py +0 -293
  467. rom24_quickmud_python-2.5.4/mud/persistence.py +0 -1147
  468. rom24_quickmud_python-2.5.4/mud/rom_api.py +0 -677
  469. rom24_quickmud_python-2.5.4/mud/scripts/convert_are_to_json.py +0 -218
  470. rom24_quickmud_python-2.5.4/mud/scripts/load_test_data.py +0 -16
  471. rom24_quickmud_python-2.5.4/mud/security/__init__.py +0 -0
  472. rom24_quickmud_python-2.5.4/mud/security/bans.py +0 -309
  473. rom24_quickmud_python-2.5.4/mud/skills/handlers.py +0 -7884
  474. rom24_quickmud_python-2.5.4/mud/skills/registry.py +0 -381
  475. rom24_quickmud_python-2.5.4/mud/spawning/mob_spawner.py +0 -13
  476. rom24_quickmud_python-2.5.4/mud/spawning/reset_handler.py +0 -842
  477. rom24_quickmud_python-2.5.4/mud/spawning/templates.py +0 -532
  478. rom24_quickmud_python-2.5.4/mud/spec_funs.py +0 -1451
  479. rom24_quickmud_python-2.5.4/mud/wiznet.py +0 -268
  480. rom24_quickmud_python-2.5.4/mud/world/char_find.py +0 -132
  481. rom24_quickmud_python-2.5.4/mud/world/look.py +0 -388
  482. rom24_quickmud_python-2.5.4/mud/world/movement.py +0 -571
  483. rom24_quickmud_python-2.5.4/mud/world/obj_find.py +0 -201
  484. rom24_quickmud_python-2.5.4/mud/world/world_state.py +0 -249
  485. rom24_quickmud_python-2.5.4/pyproject.toml +0 -144
  486. rom24_quickmud_python-2.5.4/rom24_quickmud_python.egg-info/PKG-INFO +0 -339
  487. rom24_quickmud_python-2.5.4/rom24_quickmud_python.egg-info/SOURCES.txt +0 -662
  488. rom24_quickmud_python-2.5.4/tests/integration/conftest.py +0 -84
  489. rom24_quickmud_python-2.5.4/tests/integration/test_architectural_parity.py +0 -162
  490. rom24_quickmud_python-2.5.4/tests/integration/test_auto_flags.py +0 -487
  491. rom24_quickmud_python-2.5.4/tests/integration/test_character_advancement.py +0 -475
  492. rom24_quickmud_python-2.5.4/tests/integration/test_character_commands.py +0 -276
  493. rom24_quickmud_python-2.5.4/tests/integration/test_character_creation_runtime.py +0 -258
  494. rom24_quickmud_python-2.5.4/tests/integration/test_communication_enhancement.py +0 -243
  495. rom24_quickmud_python-2.5.4/tests/integration/test_config_commands.py +0 -315
  496. rom24_quickmud_python-2.5.4/tests/integration/test_equipment_system.py +0 -657
  497. rom24_quickmud_python-2.5.4/tests/integration/test_group_combat.py +0 -676
  498. rom24_quickmud_python-2.5.4/tests/integration/test_info_display.py +0 -328
  499. rom24_quickmud_python-2.5.4/tests/integration/test_mob_ai.py +0 -545
  500. rom24_quickmud_python-2.5.4/tests/integration/test_mobprog_scenarios.py +0 -445
  501. rom24_quickmud_python-2.5.4/tests/integration/test_money_objects.py +0 -415
  502. rom24_quickmud_python-2.5.4/tests/integration/test_new_player_workflow.py +0 -183
  503. rom24_quickmud_python-2.5.4/tests/integration/test_olc_builders.py +0 -366
  504. rom24_quickmud_python-2.5.4/tests/integration/test_player_npc_interaction.py +0 -234
  505. rom24_quickmud_python-2.5.4/tests/integration/test_skills_integration.py +0 -449
  506. rom24_quickmud_python-2.5.4/tests/integration/test_socials.py +0 -262
  507. rom24_quickmud_python-2.5.4/tests/integration/test_spell_affects_persistence.py +0 -717
  508. rom24_quickmud_python-2.5.4/tests/test_account_auth.py +0 -2605
  509. rom24_quickmud_python-2.5.4/tests/test_advancement.py +0 -397
  510. rom24_quickmud_python-2.5.4/tests/test_affects.py +0 -448
  511. rom24_quickmud_python-2.5.4/tests/test_alias_parity.py +0 -227
  512. rom24_quickmud_python-2.5.4/tests/test_ansi.py +0 -5
  513. rom24_quickmud_python-2.5.4/tests/test_area_exits.py +0 -22
  514. rom24_quickmud_python-2.5.4/tests/test_area_loader.py +0 -1140
  515. rom24_quickmud_python-2.5.4/tests/test_bans.py +0 -62
  516. rom24_quickmud_python-2.5.4/tests/test_boards.py +0 -813
  517. rom24_quickmud_python-2.5.4/tests/test_combat.py +0 -762
  518. rom24_quickmud_python-2.5.4/tests/test_combat_death.py +0 -874
  519. rom24_quickmud_python-2.5.4/tests/test_commands.py +0 -412
  520. rom24_quickmud_python-2.5.4/tests/test_communication.py +0 -489
  521. rom24_quickmud_python-2.5.4/tests/test_db_resets_rom_parity.py +0 -1118
  522. rom24_quickmud_python-2.5.4/tests/test_db_seed.py +0 -26
  523. rom24_quickmud_python-2.5.4/tests/test_encumbrance.py +0 -406
  524. rom24_quickmud_python-2.5.4/tests/test_enter_portal.py +0 -20
  525. rom24_quickmud_python-2.5.4/tests/test_game_loop.py +0 -596
  526. rom24_quickmud_python-2.5.4/tests/test_game_loop_order.py +0 -31
  527. rom24_quickmud_python-2.5.4/tests/test_game_loop_wait_daze.py +0 -33
  528. rom24_quickmud_python-2.5.4/tests/test_healer.py +0 -53
  529. rom24_quickmud_python-2.5.4/tests/test_healer_parity.py +0 -197
  530. rom24_quickmud_python-2.5.4/tests/test_healer_rom_parity.py +0 -100
  531. rom24_quickmud_python-2.5.4/tests/test_help_system.py +0 -353
  532. rom24_quickmud_python-2.5.4/tests/test_inventory_persistence.py +0 -33
  533. rom24_quickmud_python-2.5.4/tests/test_mobprog_commands.py +0 -677
  534. rom24_quickmud_python-2.5.4/tests/test_movement_followers.py +0 -132
  535. rom24_quickmud_python-2.5.4/tests/test_movement_portals.py +0 -139
  536. rom24_quickmud_python-2.5.4/tests/test_networking_telnet.py +0 -280
  537. rom24_quickmud_python-2.5.4/tests/test_olc_aedit.py +0 -286
  538. rom24_quickmud_python-2.5.4/tests/test_olc_medit.py +0 -490
  539. rom24_quickmud_python-2.5.4/tests/test_olc_oedit.py +0 -402
  540. rom24_quickmud_python-2.5.4/tests/test_player_auto_settings.py +0 -566
  541. rom24_quickmud_python-2.5.4/tests/test_player_equipment.py +0 -680
  542. rom24_quickmud_python-2.5.4/tests/test_player_info_commands.py +0 -204
  543. rom24_quickmud_python-2.5.4/tests/test_player_prompt.py +0 -83
  544. rom24_quickmud_python-2.5.4/tests/test_player_title_description.py +0 -155
  545. rom24_quickmud_python-2.5.4/tests/test_rom_api.py +0 -198
  546. rom24_quickmud_python-2.5.4/tests/test_scan_parity.py +0 -187
  547. rom24_quickmud_python-2.5.4/tests/test_shops.py +0 -1377
  548. rom24_quickmud_python-2.5.4/tests/test_skill_envenom_rom_parity.py +0 -257
  549. rom24_quickmud_python-2.5.4/tests/test_skills.py +0 -941
  550. rom24_quickmud_python-2.5.4/tests/test_spec_funs.py +0 -1494
  551. rom24_quickmud_python-2.5.4/tests/test_spell_creation_rom_parity.py +0 -481
  552. rom24_quickmud_python-2.5.4/tests/test_telnet_server.py +0 -668
  553. rom24_quickmud_python-2.5.4/tests/test_world.py +0 -45
  554. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/LICENSE +0 -0
  555. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/MANIFEST.in +0 -0
  556. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/air.are +0 -0
  557. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/arachnos.are +0 -0
  558. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/area.lst +0 -0
  559. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/astral.are +0 -0
  560. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/canyon.are +0 -0
  561. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/catacomb.are +0 -0
  562. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/chapel.are +0 -0
  563. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/daycare.are +0 -0
  564. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/draconia.are +0 -0
  565. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/dream.are +0 -0
  566. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/drow.are +0 -0
  567. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/dwarven.are +0 -0
  568. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/dylan.are +0 -0
  569. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/eastern.are +0 -0
  570. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/galaxy.are +0 -0
  571. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/gnome.are +0 -0
  572. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/grave.are +0 -0
  573. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/group.are +0 -0
  574. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/grove.are +0 -0
  575. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/haon.are +0 -0
  576. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/help.are +0 -0
  577. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/hitower.are +0 -0
  578. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/hood.are +0 -0
  579. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/immort.are +0 -0
  580. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/limbo.are +0 -0
  581. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/mahntor.are +0 -0
  582. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/marsh.are +0 -0
  583. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/mega1.are +0 -0
  584. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/midennir.are +0 -0
  585. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/midgaard.are +0 -0
  586. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/mirror.are +0 -0
  587. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/mobfact.are +0 -0
  588. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/moria.are +0 -0
  589. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/newthalos.are +0 -0
  590. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/nirvana.are +0 -0
  591. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/ofcol.are +0 -0
  592. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/ofcol2.are +0 -0
  593. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/olympus.are +0 -0
  594. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/plains.are +0 -0
  595. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/proto.are +0 -0
  596. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/pyramid.are +0 -0
  597. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/quifael.are +0 -0
  598. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/redferne.are +0 -0
  599. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/rom.are +0 -0
  600. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/school.are +0 -0
  601. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/sewer.are +0 -0
  602. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/shire.are +0 -0
  603. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/smurf.are +0 -0
  604. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/social.are +0 -0
  605. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/thalos.are +0 -0
  606. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/tohell.are +0 -0
  607. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/trollden.are +0 -0
  608. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/valley.are +0 -0
  609. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/area/wyvern.are +0 -0
  610. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/area.json +0 -0
  611. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/area_0.json +0 -0
  612. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/group.json +0 -0
  613. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/help.json +0 -0
  614. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/quifael.json +0 -0
  615. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/rom.json +0 -0
  616. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas/social.json +0 -0
  617. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/arachnos.json +0 -0
  618. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/area.json +0 -0
  619. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/area_0.json +0 -0
  620. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/astral_plane.json +0 -0
  621. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/catacombs.json +0 -0
  622. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/chapel.json +0 -0
  623. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/day_care.json +0 -0
  624. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/dragon_tower.json +0 -0
  625. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/drow_city.json +0 -0
  626. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/dwarven_kingdom.json +0 -0
  627. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/dylan's_area.json +0 -0
  628. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/elemental_canyon.json +0 -0
  629. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/galaxy.json +0 -0
  630. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/gangland.json +0 -0
  631. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/gnome_village.json +0 -0
  632. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/graveyard.json +0 -0
  633. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/group.json +0 -0
  634. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/haon_dor.json +0 -0
  635. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/help.json +0 -0
  636. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/high_tower.json +0 -0
  637. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/holy_grove.json +0 -0
  638. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/in_the_air.json +0 -0
  639. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/limbo.json +0 -0
  640. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/machine_dreams.json +0 -0
  641. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/mahn-tor.json +0 -0
  642. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/marsh.json +0 -0
  643. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/mega_city_one.json +0 -0
  644. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/miden'nir.json +0 -0
  645. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/midgaard.json +0 -0
  646. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/mob_factory.json +0 -0
  647. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/moria.json +0 -0
  648. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/mud_school.json +0 -0
  649. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/new_ofcol.json +0 -0
  650. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/new_thalos.json +0 -0
  651. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/nirvana.json +0 -0
  652. {rom24_quickmud_python-2.5.4/data/areas → rom24_quickmud_python-2.7.0/data/areas_backup}/ofcol.json +0 -0
  653. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/old_thalos.json +0 -0
  654. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/olympus.json +0 -0
  655. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/plains.json +0 -0
  656. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/pyramid.json +0 -0
  657. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/quifael's.json +0 -0
  658. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/redferne's.json +0 -0
  659. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/rom.json +0 -0
  660. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/sands_of_sorrow.json +0 -0
  661. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/sewers.json +0 -0
  662. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/shire.json +0 -0
  663. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/smurfville.json +0 -0
  664. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/social.json +0 -0
  665. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/thalos.json +0 -0
  666. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/tohell.json +0 -0
  667. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/troll_den.json +0 -0
  668. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/valhalla.json +0 -0
  669. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/valley_of_the_elves.json +0 -0
  670. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/areas_backup/wyvern's_tower.json +0 -0
  671. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/help.json +0 -0
  672. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/players/.json +0 -0
  673. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/players/attacker.json +0 -0
  674. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/players/eddol.json +0 -0
  675. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/players/hero.json +0 -0
  676. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/players/sleeper.json +0 -0
  677. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/players/trouble.json +0 -0
  678. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/shops.json +0 -0
  679. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/skills.json +0 -0
  680. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/socials.json +0 -0
  681. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/data/time.json +0 -0
  682. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/MPDocs/examples.doc +0 -0
  683. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/MPDocs/hacker.doc +0 -0
  684. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/MPDocs/mobprog.doc +0 -0
  685. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/MPDocs/new_readme.txt +0 -0
  686. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/QuickMUD.txt +0 -0
  687. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/Rom2.4.doc +0 -0
  688. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/act.txt +0 -0
  689. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/area.txt +0 -0
  690. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/c_module_inventory.md +0 -0
  691. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/c_python_cross_reference.md +0 -0
  692. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/c_to_python_file_coverage.md +0 -0
  693. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/class.txt +0 -0
  694. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/command.txt +0 -0
  695. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/contrib.txt +0 -0
  696. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/drool.txt +0 -0
  697. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/hacker.txt +0 -0
  698. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/license.doc +0 -0
  699. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/license.txt +0 -0
  700. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/memory.txt +0 -0
  701. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/new.txt +0 -0
  702. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/pfile.txt +0 -0
  703. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/port.txt +0 -0
  704. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/pr_queue.md +0 -0
  705. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/python_architecture.md +0 -0
  706. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/python_module_inventory.md +0 -0
  707. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/security.txt +0 -0
  708. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/sites.txt +0 -0
  709. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/skill.txt +0 -0
  710. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/sky.txt +0 -0
  711. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/trad.txt +0 -0
  712. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/vnum.txt +0 -0
  713. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/doc/~$Rom2.4.doc +0 -0
  714. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/__main__.py +0 -0
  715. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/admin_logging/admin.py +0 -0
  716. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/admin_logging/agent_trace.py +0 -0
  717. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/affects/engine.py +0 -0
  718. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/affects/saves.py +0 -0
  719. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/agent/agent_protocol.py +0 -0
  720. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/agent/character_agent.py +0 -0
  721. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/ai/aggressive.py +0 -0
  722. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/characters/__init__.py +0 -0
  723. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/characters/conditions.py +0 -0
  724. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/characters/follow.py +0 -0
  725. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/combat/__init__.py +0 -0
  726. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/combat/death.py +0 -0
  727. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/combat/kill_table.py +0 -0
  728. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/combat/messages.py +0 -0
  729. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/combat/safety.py +0 -0
  730. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/__init__.py +0 -0
  731. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/channels.py +0 -0
  732. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/compare.py +0 -0
  733. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/consider.py +0 -0
  734. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/decorators.py +0 -0
  735. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/feedback.py +0 -0
  736. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/help.py +0 -0
  737. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/imc.py +0 -0
  738. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/misc_info.py +0 -0
  739. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/mobprog_tools.py +0 -0
  740. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/murder.py +0 -0
  741. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/commands/player_config.py +0 -0
  742. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/config.py +0 -0
  743. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/db/init.py +0 -0
  744. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/db/migrate_from_files.py +0 -0
  745. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/db/session.py +0 -0
  746. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/devtools/agent_demo.py +0 -0
  747. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/entrypoint.py +0 -0
  748. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/game_tick_scheduler.py +0 -0
  749. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/groups/__init__.py +0 -0
  750. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/groups/xp.py +0 -0
  751. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/imc/__init__.py +0 -0
  752. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/imc/commands.py +0 -0
  753. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/imc/network.py +0 -0
  754. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/imc/protocol.py +0 -0
  755. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/__init__.py +0 -0
  756. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/area_loader.py +0 -0
  757. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/base_loader.py +0 -0
  758. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/help_loader.py +0 -0
  759. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/json_area_loader.py +0 -0
  760. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/mobprog_loader.py +0 -0
  761. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/obj_loader.py +0 -0
  762. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/reset_loader.py +0 -0
  763. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/room_loader.py +0 -0
  764. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/shop_loader.py +0 -0
  765. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/social_loader.py +0 -0
  766. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/loaders/specials_loader.py +0 -0
  767. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/logging.py +0 -0
  768. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/magic/__init__.py +0 -0
  769. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/math/c_compat.py +0 -0
  770. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/__init__.py +0 -0
  771. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/area.py +0 -0
  772. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/area_json.py +0 -0
  773. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/board_json.py +0 -0
  774. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/character_json.py +0 -0
  775. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/classes.py +0 -0
  776. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/conversion.py +0 -0
  777. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/help.py +0 -0
  778. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/help_json.py +0 -0
  779. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/json_io.py +0 -0
  780. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/mob.py +0 -0
  781. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/note.py +0 -0
  782. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/note_json.py +0 -0
  783. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/obj.py +0 -0
  784. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/object_json.py +0 -0
  785. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/player_json.py +0 -0
  786. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/room_json.py +0 -0
  787. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/shop.py +0 -0
  788. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/shop_json.py +0 -0
  789. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/skill.py +0 -0
  790. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/skill_json.py +0 -0
  791. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/models/social_json.py +0 -0
  792. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/net/__init__.py +0 -0
  793. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/net/protocol.py +0 -0
  794. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/net/ssh_server.py +0 -0
  795. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/net/telnet_server.py +0 -0
  796. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/network/websocket_session.py +0 -0
  797. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/olc/__init__.py +0 -0
  798. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/registry.py +0 -0
  799. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/scripts/convert_help_are_to_json.py +0 -0
  800. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/scripts/convert_player_to_json.py +0 -0
  801. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/scripts/convert_shops_to_json.py +0 -0
  802. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/scripts/convert_skills_to_json.py +0 -0
  803. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/scripts/convert_social_are_to_json.py +0 -0
  804. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/security/hash_utils.py +0 -0
  805. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/server.py +0 -0
  806. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/skills/__init__.py +0 -0
  807. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/skills/groups.py +0 -0
  808. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/skills/metadata.py +0 -0
  809. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/skills/say_spell.py +0 -0
  810. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/spawning/__init__.py +0 -0
  811. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/spawning/obj_spawner.py +0 -0
  812. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/time.py +0 -0
  813. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/utils/act.py +0 -0
  814. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/utils/rng_mm.py +0 -0
  815. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/utils/text.py +0 -0
  816. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/world/__init__.py +0 -0
  817. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/world/linking.py +0 -0
  818. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/mud/world/vision.py +0 -0
  819. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/rom24_quickmud_python.egg-info/dependency_links.txt +0 -0
  820. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/rom24_quickmud_python.egg-info/entry_points.txt +0 -0
  821. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/rom24_quickmud_python.egg-info/requires.txt +0 -0
  822. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/rom24_quickmud_python.egg-info/top_level.txt +0 -0
  823. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/setup.cfg +0 -0
  824. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/setup.py +0 -0
  825. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/conftest.py +0 -0
  826. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/helpers.py +0 -0
  827. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/helpers_player.py +0 -0
  828. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_admin_commands.py +0 -0
  829. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_auto_sequences.py +0 -0
  830. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_channels.py +0 -0
  831. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_compare_critical_gaps.py +0 -0
  832. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_death_and_corpses.py +0 -0
  833. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_affects.py +0 -0
  834. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_consider_command.py +0 -0
  835. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_equipment.py +0 -0
  836. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_examine_command.py +0 -0
  837. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_exits_command.py +0 -0
  838. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_help_command.py +0 -0
  839. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_inventory.py +0 -0
  840. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_password_command.py +0 -0
  841. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_practice_command.py +0 -0
  842. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_time_command.py +0 -0
  843. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_weather_command.py +0 -0
  844. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_where_command.py +0 -0
  845. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_who_command.py +0 -0
  846. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_do_worth.py +0 -0
  847. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_environmental_effects.py +0 -0
  848. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_equipment_ac_calculations.py +0 -0
  849. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_invisibility_combat.py +0 -0
  850. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_pet_persistence.py +0 -0
  851. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_pilot_integration.py +0 -0
  852. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_player_config.py +0 -0
  853. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_room_light_tracking.py +0 -0
  854. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_room_safety_features.py +0 -0
  855. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_save_load_parity.py +0 -0
  856. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_skills_integration_combat_specials.py +0 -0
  857. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_spell_casting.py +0 -0
  858. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/integration/test_weather_time.py +0 -0
  859. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_act_comm_rom_parity.py +0 -0
  860. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_act_enter_rom_parity.py +0 -0
  861. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_act_info_rom_parity.py +0 -0
  862. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_act_obj_rom_parity.py +0 -0
  863. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_act_wiz_rom_parity.py +0 -0
  864. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_agent_interface.py +0 -0
  865. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_are_conversion.py +0 -0
  866. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_area_counts.py +0 -0
  867. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_area_specials.py +0 -0
  868. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_builder_hedit.py +0 -0
  869. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_builder_stat_commands.py +0 -0
  870. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_building.py +0 -0
  871. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_char_update_rom_parity.py +0 -0
  872. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_assist.py +0 -0
  873. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_damage_types.py +0 -0
  874. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_defenses_prob.py +0 -0
  875. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_messages.py +0 -0
  876. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_position_damage.py +0 -0
  877. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_rom_parity.py +0 -0
  878. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_skills.py +0 -0
  879. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_state.py +0 -0
  880. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_surrender.py +0 -0
  881. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_thac0.py +0 -0
  882. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_combat_thac0_engine.py +0 -0
  883. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_command_abbrev.py +0 -0
  884. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_command_parity.py +0 -0
  885. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_connection_motd.py +0 -0
  886. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_convert_are_to_json_cli.py +0 -0
  887. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_critical_function_parity.py +0 -0
  888. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_damage_reduction.py +0 -0
  889. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_damage_reduction_integration.py +0 -0
  890. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_defense_flags.py +0 -0
  891. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_fighting_state.py +0 -0
  892. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_golden_reference.py +0 -0
  893. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_handler_affects_rom_parity.py +0 -0
  894. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_hash_utils.py +0 -0
  895. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_help_conversion.py +0 -0
  896. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_imc.py +0 -0
  897. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_json_io.py +0 -0
  898. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_json_model_instantiation.py +0 -0
  899. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_json_room_fields.py +0 -0
  900. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_load_midgaard.py +0 -0
  901. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_logging_admin.py +0 -0
  902. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_logging_rotation.py +0 -0
  903. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_mob_act_flags.py +0 -0
  904. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_mob_damage_modifiers.py +0 -0
  905. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_mobprog.py +0 -0
  906. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_mobprog_helpers.py +0 -0
  907. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_mobprog_triggers.py +0 -0
  908. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement.py +0 -0
  909. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_charm.py +0 -0
  910. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_costs.py +0 -0
  911. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_doors.py +0 -0
  912. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_mobprog.py +0 -0
  913. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_npc.py +0 -0
  914. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_privacy.py +0 -0
  915. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_movement_visibility.py +0 -0
  916. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_music.py +0 -0
  917. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_nanny_rom_parity.py +0 -0
  918. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_obj_update_rom_parity.py +0 -0
  919. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_olc_save.py +0 -0
  920. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_passive_skills_rom_parity.py +0 -0
  921. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_persistence.py +0 -0
  922. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_affect_flags.py +0 -0
  923. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_combat_attributes.py +0 -0
  924. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_conditions.py +0 -0
  925. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_creation.py +0 -0
  926. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_flags.py +0 -0
  927. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_mechanics.py +0 -0
  928. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_resistance_flags.py +0 -0
  929. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_save_format.py +0 -0
  930. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_skills_spells.py +0 -0
  931. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_stats.py +0 -0
  932. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_player_wimpy.py +0 -0
  933. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_practice.py +0 -0
  934. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_reset_levels.py +0 -0
  935. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_resets.py +0 -0
  936. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_rng_and_ccompat.py +0 -0
  937. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_rng_dice.py +0 -0
  938. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_runtime_models.py +0 -0
  939. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_saves_rom_parity.py +0 -0
  940. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_say_spell.py +0 -0
  941. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_schema_validation.py +0 -0
  942. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_scripted_session.py +0 -0
  943. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_shop_conversion.py +0 -0
  944. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_combat_rom_parity.py +0 -0
  945. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_conversion.py +0 -0
  946. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_haggle_rom_parity.py +0 -0
  947. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_hide_rom_parity.py +0 -0
  948. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_peek_rom_parity.py +0 -0
  949. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_pick_lock_rom_parity.py +0 -0
  950. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_recall_rom_parity.py +0 -0
  951. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_registry.py +0 -0
  952. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skill_steal_rom_parity.py +0 -0
  953. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_buffs.py +0 -0
  954. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_combat.py +0 -0
  955. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_conjuration.py +0 -0
  956. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_damage.py +0 -0
  957. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_debuffs.py +0 -0
  958. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_detection.py +0 -0
  959. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_healing.py +0 -0
  960. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_identify.py +0 -0
  961. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_learned.py +0 -0
  962. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_mass.py +0 -0
  963. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_misc.py +0 -0
  964. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_skills_transport.py +0 -0
  965. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_social_conversion.py +0 -0
  966. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_social_placeholders.py +0 -0
  967. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spawning.py +0 -0
  968. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spec_fun_behaviors.py +0 -0
  969. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spec_funs_extra.py +0 -0
  970. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_specials_loader_ext.py +0 -0
  971. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_area_effects_rom_parity.py +0 -0
  972. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_breath_weapons_rom_parity.py +0 -0
  973. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_buff_debuff_additional_rom_parity.py +0 -0
  974. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_buff_debuff_rom_parity.py +0 -0
  975. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_cancellation_rom_parity.py +0 -0
  976. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_charm_control_rom_parity.py +0 -0
  977. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_critical_gameplay_rom_parity.py +0 -0
  978. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_damage_additional_rom_parity.py +0 -0
  979. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_detection_rom_parity.py +0 -0
  980. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_enchantment_rom_parity.py +0 -0
  981. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_farsight_rom_parity.py +0 -0
  982. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_final_nine_rom_parity.py +0 -0
  983. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_harm_rom_parity.py +0 -0
  984. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_healing_rom_parity.py +0 -0
  985. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_heat_metal_rom_parity.py +0 -0
  986. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_high_priority_missing_rom_parity.py +0 -0
  987. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_information_rom_parity.py +0 -0
  988. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_mass_healing_rom_parity.py +0 -0
  989. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_priority_high_rom_parity.py +0 -0
  990. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_shocking_grasp_rom_parity.py +0 -0
  991. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spell_travel_portal_rom_parity.py +0 -0
  992. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spells_basic.py +0 -0
  993. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_spells_damage.py +0 -0
  994. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_state_transitions.py +0 -0
  995. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_time_daynight.py +0 -0
  996. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_time_persistence.py +0 -0
  997. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_utility_spells_parity.py +0 -0
  998. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_weapon_damage.py +0 -0
  999. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_weapon_special_attacks.py +0 -0
  1000. {rom24_quickmud_python-2.5.4 → rom24_quickmud_python-2.7.0}/tests/test_wiznet.py +0 -0
@@ -0,0 +1,1315 @@
1
+ # Changelog
2
+
3
+ All notable changes to this project will be documented in this file.
4
+
5
+ The format is based on [Keep a Changelog](https://keepachangelog.com/en/1.0.0/),
6
+ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0.html).
7
+
8
+ ## [Unreleased]
9
+
10
+ ## [2.7.0] — ROM Character-First Login
11
+
12
+ ### Changed
13
+
14
+ - **Login model replaced with ROM-faithful character-first auth** — the
15
+ `PlayerAccount` ORM table and account-layer have been removed entirely.
16
+ Characters now authenticate directly (mirroring ROM `nanny.c`/`save.c`):
17
+ the server prompts `Name:`, branches to `Password:` for returning chars or
18
+ `Did I get that right, <Name> (Y/N)?` → `New password:` → `Confirm
19
+ password:` for new ones. The `PlayerAccount` class is gone; `password_hash`
20
+ now lives on the `Character` row.
21
+ - **`_select_character` simplified** — no character-selection menu; the login
22
+ name *is* the character name, matching ROM's single-character-per-login model.
23
+ - **`login_with_host` / `login_character`** updated to query `Character` directly;
24
+ `create_account` / `list_characters` / `release_account` kept as thin shims
25
+ for call-site compatibility.
26
+ - **Reconnect flow** — duplicate-session detection and reconnect prompt now
27
+ occur at the `Name:` stage (before password), matching ROM nanny behaviour.
28
+
29
+ ### Fixed
30
+
31
+ - **`negotiate_ansi_prompt` test helper** — was waiting for `b"Account: "` after
32
+ the ANSI negotiation; updated to `b"Name: "` to match the new login prompt.
33
+ - **`test_select_character_allows_permit_from_permit_host`** — monkeypatched
34
+ `load_character` now uses single-arg signature; `account` arg updated to be
35
+ the character row directly (ROM model).
36
+ - **`test_websocket_boots_loaded_world_and_uses_account_login_flow`** — rewritten
37
+ for ROM flow (`Name:` → confirm → `New password:` → `Confirm password:`).
38
+ - **`test_telnet_server_handles_multiple_connections`** and
39
+ **`test_telnet_break_connect_prompts_and_reconnects`** — updated to ROM login
40
+ flow (no `Character:` prompt step).
41
+
42
+ ### Fixed
43
+
44
+ - **Combat message delivery** — combat messages (damage, parry, dodge, position
45
+ changes, weapon specials) now reach connected players immediately via
46
+ fire-and-forget asyncio tasks, matching ROM C's `write_to_buffer()` real-time
47
+ delivery. Previously messages were queued in `char.messages` and only drained
48
+ when the player typed a command, causing combat to appear frozen.
49
+ See `docs/divergences/MESSAGE_DELIVERY.md` for the design rationale.
50
+
51
+ ### Changed (v2.6.108)
52
+
53
+ - **JSON_LOADER_C_AUDIT.md** — all 18 gaps now closed (remaining 6 in this batch).
54
+ - JSON loader applies per-type value coercion (`_parse_item_values`) at load time, mirroring ROM `src/db2.c:429-478` and the `.are` loader path.
55
+ - `attack_lookup` now handles numeric-string inputs (in-range passes through, out-of-range falls to name prefix-match), consistent with `_skill_lookup`/`_liq_lookup`/`_weapon_type_lookup`.
56
+
57
+ ### Fixed (json_loader.py parity closures — JSONLD-001,003,015,016,017,018)
58
+
59
+ - **JSONLD-001** — Object keyword list populated from JSON `keywords` key (with `name` fallback) so `is_name()` matching works on JSON-loaded objects. Converter (`convert_are_to_json.py`) now emits `keywords` separately from display `name`. All 44 area JSONs regenerated.
60
+ - **JSONLD-003** — Object `level` field emitted by converter (`convert_are_to_json.py:object_to_dict`) and read by JSON loader. All area JSONs regenerated with `level` for every object.
61
+ - **JSONLD-015** — JSON loader now calls `_parse_item_values` (from `obj_loader`) to apply per-type value coercion at load time. `attack_lookup` updated to handle pre-resolved integer values from JSON.
62
+ - **JSONLD-016** — Object `short_descr` lowercased-first and `description` uppercased-first at load time, mirroring ROM `src/db2.c:869-870`.
63
+ - **JSONLD-017** — Room `light` verified at dataclass default 0 (ROM `src/db.c:1164`). Explicit init deemed redundant — closed-by-design.
64
+ - **JSONLD-018** — JSON-only `ROOM_NO_MOB` auto-add on no-exit rooms removed. ROM does not do this; rooms now behave identically to the `.are` path.
65
+
66
+ ### Changed (v2.6.107)
67
+
68
+ - Includes previously uncommitted JSONLD-012, OLC, and build changes from earlier session.
69
+
70
+ ### Fixed (act_wiz.c stat family parity closures — WIZ-039..044)
71
+
72
+ - **WIZ-039** — `do_mstat` practices now uses caller's NPC status (`char.is_npc`) instead of victim's, matching ROM `IS_NPC(ch) ? 0 : victim->practice`.
73
+ - **WIZ-040** — `do_mstat` Hit/Dam now use `get_hitroll(victim)` / `get_damroll(victim)` (including STR-app bonuses) per ROM `GET_HITROLL` / `GET_DAMROLL`.
74
+ - **WIZ-041** — `do_mstat` Age/Played/Last_Level now computed via `get_age(victim)`, `(played + current_time - logon) / 3600`, and `pcdata.last_level` per ROM instead of hardcoded 17/0/0.
75
+ - **WIZ-042** — `do_mstat` Carry weight now uses `get_carry_weight(victim) // 10` (includes coin burden) per ROM.
76
+ - **WIZ-043** — `do_ostat` Number/Weight line now uses `_object_carry_number(obj)` and `_get_obj_weight(obj)` per ROM `get_obj_number` / `get_obj_weight` / `get_true_weight`.
77
+ - **WIZ-044** — `do_rstat` Objects list now has 3 spaces after colon per ROM `".\n\rObjects: "`.
78
+
79
+ ### Fixed (JSON loader parity closures — v2.6.105)
80
+
81
+ - **JSONLD-012** — JSON-loaded mob `race` values now resolve through ROM `race_lookup` into integer `race_table` indexes at load time, matching ROM `src/db2.c:234`. Race flag merging, OLC JSON save, and `medit show` display now handle integer-backed mob races without losing the human-readable race name.
82
+
83
+ ### Fixed (JSON loader parity closures — v2.6.104)
84
+
85
+ - **JSONLD-009** — JSON-loaded areas now default `security` to 9 for both supported JSON formats, preserving explicit JSON values when present. This mirrors ROM `src/db.c:452` / `src/db.c:531` and restores the expected OLC builder-security default.
86
+ - **JSONLD-010** — Format 1 JSON areas now hydrate `credits` from the JSON payload when present, mirroring ROM `src/db.c:457`.
87
+ - **JSONLD-013** — JSON room `clan` values now resolve through `lookup_clan_id`, including ROM-style prefix matching, instead of preserving raw strings. Mirrors ROM `src/db.c:1192`.
88
+ - **JSONLD-014** — JSON `D` resets now apply boot-time door state and are discarded rather than retained in `area.resets` / `room.resets`, mirroring ROM `src/db.c:1058-1104`.
89
+
90
+ ### Fixed (JSON loader parity closures — v2.6.103)
91
+
92
+ - **JSONLD-002** — Object `extra_descr` now stores `ExtraDescr` instances instead of raw dicts, matching the `.are` loader and ROM (`src/db2.c:571-580`). Consumer sites no longer need dict-aware fallback.
93
+ - **JSONLD-004** — Mob `hit`/`mana`/`damage` int tuples now parsed from `hit_dice`/`mana_dice`/`damage_dice` strings at load time via `_parse_dice_tuple`, matching ROM (`src/db2.c:251-269`). The `templates.py:_parse_dice` fallback still works as defense.
94
+ - **JSONLD-005** — Object `wear_flags` now converted from ROM letter string to int bitmask via `convert_flags_from_letters(WearFlag)`, matching the `.are` loader (`obj_loader.py:389`).
95
+ - **JSONLD-006** — Object `affected` list now populated with typed `Affect` instances from `affects` dicts, matching ROM (`src/db2.c:519-568`). `obj.affected` is no longer empty on JSON-loaded objects.
96
+ - **JSONLD-007** — Mob `hitroll` now populated from JSON `hitroll` key (falling back to `thac0`), matching ROM (`src/db2.c:248`). Previously `hitroll` was always 0 for JSON-loaded mobs.
97
+ - **JSONLD-008** — Mob `off_flags`/`imm_flags`/`res_flags`/`vuln_flags` int fields now populated after `merge_race_flags` via `_to_int_flags`, matching ROM (`src/db2.c:279-286`). Previously these stayed 0 on JSON-loaded mobs.
98
+ - **JSONLD-011** — Mob `form`/`parts` now converted from letter strings to int bitmasks after `merge_race_flags`, matching ROM (`src/db2.c:295-297`). Previously `IS_SET(mob.form, FORM_EDIBLE)` would fail with `ValueError`.
99
+
100
+ ### Fixed (in-game runtime bugs surfaced 2026-04-30)
101
+
102
+ - `BUG-MOBHP` — Every JSON-loaded mob spawned with `max_hit=0` / `current_hp=1`, so look reported "awful condition" universally and a level 1 PC could one-shot Hassan (level 45). `mud/spawning/templates.py:_parse_dice` short-circuited on the default `(0,0,0)` primary tuple before consulting the `hit_dice` / `mana_dice` / `damage_dice` string fallback the JSON loader populated. Now treats all-zero primary as "unset" and falls through. ROM ref: `src/db.c:fread_mobile`. (commit `715469d`)
103
+ - `BUG-CORPSEINT` — `get coins corpse` raised `ValueError: invalid literal for int() with base 10: 'npc_corpse'`. `mud/loaders/json_loader.py:_load_objects_from_json` now routes prototype `item_type` through `_resolve_item_type_code` (mirroring the legacy `.are` loader), and `mud/commands/inventory.py:do_get` defensively coerces. ROM ref: `src/db.c:load_objects` `flag_value`. (commit `0f0d871`)
104
+ - `BUG-EDDICT` — `look fountain`, `read letter` raised `'dict' object has no attribute 'description'` because the JSON loader stores `extra_descr` as raw dicts and `mud/world/look.py` accessed `.description` attribute-style. Added `_ed_fields(ed)` helper accepting both shapes. ROM ref: `src/act_info.c:do_look`, `EXTRA_DESCR_DATA`. (commit `cb4eed7`)
105
+ - `BUG-NLOWER` — `look corpse`, `open south`, `open door` raised `'NoneType' object has no attribute 'lower'` because JSON-loaded prototypes carry `name=None` (the JSON schema collapsed ROM's separate keyword field) and ~15 helper sites used `getattr(x, "name", "").lower()`. Swept all match sites to the safe `(getattr(x, "name", None) or "").lower()` form across `mud/world/{obj_find,char_find}.py` and `mud/commands/{obj_manipulation,combat,misc_player,info_extended,imm_commands,imm_search,socials,remaining_rom}.py`. (commit `658d319`)
106
+
107
+ ### Changed
108
+
109
+ - `docs/parity/ROM_C_SUBSYSTEM_AUDIT_TRACKER.md` and `docs/parity/DB_C_AUDIT.md` — added "Re-audit Triggers from In-Game Debug Pass (2026-04-30)" sections flagging `mud/loaders/json_loader.py` as a partial port of `src/db.c:load_objects` / `load_mobiles` / `fread_obj` / `fread_mobile`. The four fixed bugs all trace to the JSON-path skipping ROM normalization that the `.are` loader performs. Recommendation to downgrade the db.c "100% certified" badge or split scope deferred to next session. The data-side gap (JSON dropped ROM's separate `name`/keyword field on objects) is still unfixed.
110
+
111
+ ### Added
112
+
113
+ - `mud/loaders/json_loader.py` parity audit (`docs/parity/JSON_LOADER_C_AUDIT.md`) — Phase 1–3 complete. Function inventory mapped against `src/db.c:load_objects` / `load_mobiles` / `load_rooms` / `load_resets` / `load_shops` / `fread_obj` / `fread_mobile` / `convert_mob` / `convert_obj`. **18 stable gap IDs filed (JSONLD-001..018)**: 7 CRITICAL (object keyword list missing from schema; `extra_descr` raw dicts; object `level` missing; mob hit/mana/damage tuples not populated at load; `wear_flags` raw string; `obj.affected` typed list never populated; mob `hitroll` populated from wrong JSON key — `thac0`); 8 IMPORTANT (off/imm/res/vuln int fields zero on JSON-loaded mobs; area `security`/`credits` defaults; `form`/`parts` raw strings; `race` as string not index; room `clan` not lookup-validated; D-reset semantics divergence; no per-type `value[]` coercion at load time); 3 MINOR (`short_descr`/`description` first-letter normalization; room `light` default reliance; `_link_exits_for_area` JSON-only `ROOM_NO_MOB` auto-set). The four runtime bugs fixed earlier today appear as JSONLD-001/002/003/004 — three are mitigated at consumer sites and remain ⚠️ OPEN at the loader, JSONLD-003 (`item_type`) is ✅ FIXED loader-side. `convert_mob` / `convert_obj` documented as intentionally absent (JSON files carry pre-resolved new-format values). Closures pending via `rom-gap-closer` per-gap; suggested ordering (single-commit fixes first): JSONLD-002, 004, 005, 006, 007, 008, 011 → then schema/converter changes for JSONLD-001, 003.
114
+
115
+ ### Added
116
+
117
+ - `olc_save.c` parity audit (`docs/parity/OLC_SAVE_C_AUDIT.md`) — Phase 1–3 complete. 17 ROM functions inventoried. **JSON-authoritative framing locked**: Python writes JSON via `mud/olc/save.py` (`save_area_to_json`); `.are` remains read-only legacy input via `mud/loaders/area_loader.py`. Format-level divergences (ROM `fwrite_flag` A–Za–z encoding, `fix_string` tilde strip, `.are` column widths) are documented as N/A under this framing. 20 stable gap IDs filed (OLC_SAVE-001..020): **8 CRITICAL** round-trip data-loss bugs (mob `off`/`imm`/`res`/`vuln` flags, `form`/`parts`/`size`/`material`, mprog list, shop binding, spec_fun binding; object `level`, structured affect chain, structured extra-descr); **5 IMPORTANT** (no help-save path, `cmd_asave area` only handles `redit`, no autosave entry, NPC security gate gap, `save_area_list` missing `social.are` + HELP_AREA prepend); **7 MINOR** (4 string-drift cases, condition-letter ladder, exit lock-flag normalization, door-reset synthesis). Closures pending via `rom-gap-closer` per-gap. Tracker: `olc_save.c` row flipped ❌ Not Audited → ⚠️ Partial.
118
+
119
+ ### Fixed
120
+
121
+ - `OLC_SAVE-009` — Area-grouped help-save / help-load round trip. New `_serialize_help` helper in `mud/olc/save.py` emits the canonical `{level, keywords, text}` shape; `save_area_to_json` now includes a per-area `helps` list (symmetric with mobs / objects / rooms / mob_programs / shops / specials). Paired loader-side change: new `_load_helps_from_json` in `mud/loaders/json_loader.py` walks the section, appends each entry to `area.helps`, and registers it in `help_registry` so `do help <keyword>` keeps resolving across save→reload cycles. Mirrors ROM `src/olc_save.c:826-843` (save_helps). Closes the IMPORTANT-block hole that forced the OLC_SAVE-010 hedit dispatcher to no-op behind a "Grabando area :" placeholder. ROM `save_other_helps` standalone-help-file fan-out (`src/olc_save.c:845-872`) remains N/A under JSON-authoritative framing — Python has no global `had_list`; helps live on their owning area. Tests: `tests/integration/test_olc_save_009_area_helps_round_trip.py` (3 cases).
122
+ - `OLC_SAVE-013` — `save_area_list` (`mud/olc/save.py`) now prepends `social.are\n` as the first line of the area.lst file, mirroring ROM `src/olc_save.c:94` (ROM OLC convention). Python omitted the prepend, causing the first area filename to appear in the position ROM reserves for the `social.are` marker. HAD/HELP_AREA standalone-help-area filename rows remain N/A pending OLC_SAVE-009 (help-save port). Tests: `tests/integration/test_olc_save_013_area_list_social_prepend.py` (2 cases: prepend with areas present, prepend with empty registry).
123
+ - `OLC_SAVE-012` — `_is_builder` (`mud/commands/build.py`) now gates on `char.is_npc` before consulting `pcdata.security` or `area.builders`, mirroring the ROM `IS_BUILDER` macro's leading `!IS_NPC(ch)` clause (`src/merc.h`) and the `IS_NPC(ch) → sec = 0` clamp in `cmd_asave` (`src/olc_save.c:933`). Without this gate, an NPC whose name happened to appear in an area's `builders` list (or one carrying a stub `pcdata.security`) would have passed the builder check, letting mob_special-style flows bypass area security. Existing OLC test fixtures updated to set `is_npc=False` on PCs (they were relying on the missing gate). Tests: `tests/integration/test_olc_save_012_npc_security_gate.py` (3 cases: NPC name match, NPC stub-pcdata bypass, PC regression).
124
+ - `OLC_SAVE-011` — `cmd_asave` now accepts `char=None` for the autosave-timer entry path. Mirrors ROM `src/olc_save.c:931-936` (`if (!ch) sec = 9` lets `do_asave(NULL, "world")` persist every area). The "world" branch now skips the `_is_builder` gate when ch is None and returns silently (ROM `if (ch) send_to_char`); other args short-circuit before char-attribute access. Unblocks future autosave wiring (`olc_save.c` autosave timer port). Tests: `tests/integration/test_olc_save_011_autosave_entry.py` (3 cases: null-ch saves every area, null-ch with empty registry no-crash, player-path message regression).
125
+ - `OLC_SAVE-010` — `@asave area` now dispatches across all five ROM editor types (aedit / redit / oedit / medit / hedit) instead of only `redit`. `cmd_asave` (`mud/commands/build.py`) now resolves the target area from `session.editor_state["area"]` for aedit, `room.area` for redit, `obj_proto.area` for oedit, and `mob_proto.area` for medit; hedit returns the ROM-faithful "Grabando area :" prefix pending OLC_SAVE-009 (help-save port). Mirrors ROM `src/olc_save.c:1080-1128`. Without this, aedit/oedit/medit users got "You are not editing an area, therefore an area vnum is required." and their changes were silently unsaveable. Tests: `tests/integration/test_olc_save_010_asave_area_dispatch.py` (6 cases: aedit/redit/oedit/medit dispatch, hedit help-save marker, ED_NONE error).
126
+ - `OLC_SAVE-008` — Object extra-description list now routed through `_serialize_extra_descr` (`mud/olc/save.py`), which is dict-aware so a prototype carrying either a plain `{"keyword", "description"}` dict (from `mud/loaders/obj_loader.py`) or an `ExtraDescr` dataclass instance produces an identical flat payload. Mirrors ROM `src/olc_save.c:431-435`. Replaces the prior raw `list(...extra_descr, [])` pass-through that crashed `json.dump` on dataclass values and let stray dict keys leak through. Tests: `tests/integration/test_olc_save_008_object_extra_descr.py` (3 cases: dict round-trip, `ExtraDescr` dataclass json-safe, canonical-key shape).
127
+ - `OLC_SAVE-007` — Object affect chain now serialized through a dedicated `_serialize_affect` helper (`mud/olc/save.py`) that normalizes a prototype affect — accepting either a plain dict (A-line `{location, modifier}` or F-line `{where, location, modifier, bitvector}` per `mud/loaders/obj_loader.py`) or an `Affect` dataclass instance — into a json-safe dict. Mirrors ROM `src/olc_save.c:399-429` (TO_OBJECT applies + TO_AFFECTS/IMMUNE/RESIST/VULN). Replaces the prior opaque `list(...affects, [])` pass-through that silently dropped fields and crashed `json.dump` on dataclass values. Tests: `tests/integration/test_olc_save_007_object_affects.py` (5 cases: A-line dict normalization, F-line preservation, `Affect` dataclass shape, mixed-shape round-trip, `json.dump` regression).
128
+ - `OLC_SAVE-006` — Object `level` now persisted on JSON save. `_serialize_object` (`mud/olc/save.py`) emits the field; paired loader-side change in `_load_objects_from_json` (`mud/loaders/json_loader.py`) reads it back. Mirrors ROM `src/olc_save.c:378` (save_object level emission). Without this, a save→reboot→reload cycle silently reset every object level to 0, breaking level-gated drops, identify output, and equipment loadout heuristics. Tests: `tests/integration/test_olc_save_006_object_level.py` (3 cases: serializer field emit, full round-trip, default level=0 round-trip).
129
+ - `OLC_SAVE-005` — Mob `spec_fun` bindings now persisted on JSON save via a new top-level `specials` section emitted by `save_area_to_json` (`mud/olc/save.py`). Mirrors ROM `src/olc_save.c:578-606` (save_specials writes `M <vnum> <spec_fun>` rows in the per-area `#SPECIALS` section). Loader-side `apply_specials_from_json` (`mud/loaders/specials_loader.py`) was already in place; this closure adds the missing serialize half. Without this, a save→reboot→reload cycle silently erased every spec_fun binding (e.g. `spec_breath_fire` on dragons reverted to no special). Tests: `tests/integration/test_olc_save_005_mob_spec_fun.py` (3 cases: section emit, full round-trip, mob-without-spec_fun emits no entry).
130
+ - `OLC_SAVE-004` — Mob shop bindings (`MobIndex.pShop` → keeper / buy_types[5] / profit_buy / profit_sell / open_hour / close_hour) now persisted on JSON save via a new top-level `shops` section emitted by `save_area_to_json` (`mud/olc/save.py`). Mirrors ROM `src/olc_save.c:786-824` (save_shops). Paired loader-side change: new `_load_shops_from_json` (`mud/loaders/json_loader.py`) rehydrates `mud.registry.shop_registry` keyed by keeper vnum and re-attaches `MobIndex.pShop` after mob load. Without this, a save→reboot→reload cycle silently erased every shop binding — keepers reverted to non-merchant NPCs. Tests: `tests/integration/test_olc_save_004_mob_shops.py` (3 cases: section emit, full round-trip restoring `shop_registry`, mob-without-shop emits no entry). Loader and serializer changes ship in one commit per the audit's locked closure rule.
131
+ - `OLC_SAVE-003` — Mob `mprogs` (mob program assignments) now persisted on JSON save via a new `mob_programs` section emitted by `save_area_to_json` (`mud/olc/save.py`). Mirrors ROM `src/olc_save.c:151-169` (save_mobprogs writes the per-area `#MOBPROGS` section) plus `src/olc_save.c:245-250` (per-mob MPROG_LIST inside save_mobile). Without this, a save→reboot→reload cycle silently erased every mob program binding. Python's JSON layout factors program code area-wide and links via assignments (matching `mud/loaders/json_loader.py:_load_mob_programs_from_json`); the new `_collect_mob_programs` helper reverses that projection by walking each mob's `mprogs` list and grouping by program vnum. Triggers serialize via `mud.mobprog.format_trigger_flag` (int → ROM keyword). Tests: `tests/integration/test_olc_save_003_mob_mprogs.py` (3 cases: single assignment, multiple mobs sharing one program, mob without mprogs).
132
+ - `OLC_SAVE-002` — Mob `form`/`parts`/`size`/`material` now persisted by `_serialize_mobile` on JSON save (`mud/olc/save.py:136`). Mirrors ROM `src/olc_save.c:213-219` (save_mobile fwrite/fwrite_flag for Form/Parts/Size/Material). Without this, a save→reload cycle silently dropped physical descriptors that drive corpse parts, magic targeting, and combat sizing. `Size` enum values are coerced to lowercase names (e.g. `Size.MEDIUM` → `"medium"`) to match the `_load_mobs_from_json` string contract. JSON-write content locked by `tests/integration/test_olc_save_002_mob_form_parts_size_material.py` (3 cases). Note: a full Python-object equality round-trip is not asserted because the loader's `merge_race_flags` unions race-default bits into `form`/`parts` on read; the JSON file itself is the canonical write surface and is asserted directly.
133
+ - `OLC_SAVE-001` — Mob defensive/offensive flag sets (`offensive`/`immune`/`resist`/`vuln` letter-strings) now persisted by `_serialize_mobile` on JSON save (`mud/olc/save.py:136`). Mirrors ROM `src/olc_save.c:205-208` (save_mobile fwrite_flag for Off/Imm/Res/Vuln). Without this, a save→reboot→reload cycle silently dropped all mob defensive flag sets. Round-trip locked by `tests/integration/test_olc_save_001_mob_defensive_flags.py` (3 cases: serializer field emission, full save→load round-trip, empty/zero flag-string safety).
134
+ - `OLC_ACT-014` — Locked the `area.changed = True` protocol divergence between Python and ROM. ROM `src/olc.c:452-463`/`:510-521` dispatchers `SET_BIT(pArea->area_flags, AREA_CHANGED)` whenever a subcommand handler returns `TRUE`; Python uses an imperative pattern where each `_interpret_*edit` branch sets `area.changed = True` directly after a successful mutation. Structural divergence with equivalent behavior. Added a ROM-cite comment to `_mark_area_changed` (`mud/commands/build.py:220`) and a regression test that exercises one representative `name` mutation per editor (aedit/redit/oedit/medit), one secondary subcommand (aedit `security`), and one failed-mutation no-op case mirroring ROM's "handler returned FALSE → no SET_BIT" path. Test: `tests/integration/test_olc_act_014_area_changed_protocol.py` (6 cases).
135
+ - `OLC_ACT-013` — Locked the equivalence between Python `_get_area_for_vnum` (`mud/commands/build.py:1352`) and ROM `get_vnum_area` (`src/olc_act.c:588-599`). ROM walks the `area_first` linked list; Python iterates `area_registry.values()`. CPython dicts preserve insertion order (3.7+), so load-order traversal is equivalent to ROM's linked-list walk. Added a ROM-cite comment to the function and a regression test that locks the dict insertion-order guarantee plus first-match-on-overlap behavior. Test: `tests/integration/test_olc_act_013_get_area_for_vnum_order.py` (3 cases).
136
+
137
+ ### Added
138
+
139
+ - `OLC-016` / `OLC-017` / `OLC-018` / `OLC-019` — sibling-audit dispatcher gaps closed transitively by OLC_ACT-001/002/003/004/005/006. The OLC-NNN gaps were filed in `OLC_C_AUDIT.md` as "missing dispatcher subcommand" entries; the OLC_ACT-NNN gaps are the corresponding builder-logic closures in `src/olc_act.c`. In Python, the dispatcher and builder live in the same `cmd_*edit` function in `mud/commands/build.py`, so closing the OLC_ACT side automatically closes the OLC side. All four CRITICAL `do_*edit create` paths are now wired with full ROM validation chains and authoritative `new_*_index` defaults from `src/mem.c`.
140
+ - `OLC_ACT-002` + `OLC_ACT-003` + `OLC_ACT-004` — `redit create <vnum>` / `redit reset` / `redit <vnum>` silent teleport (`mud/commands/build.py:cmd_redit`). All three are branches of ROM's single `do_redit` function (`src/olc.c:745-821`) so they ship in one combined commit. **OLC_ACT-002**: explicit `redit create <vnum>` keyword wired with full ROM validation chain (vnum required, area assignment, IS_BUILDER, already-exists). `new_room_index` defaults from `src/mem.c:181-218` (heal_rate=100, mana_rate=100). After create, builder is moved into the new room via silent `_char_from_room`/`_char_to_room`. **OLC_ACT-003**: `redit reset` dispatcher wired — security gate, exact ROM message "Room reset.\\n\\r", area `changed=True`, calls `apply_resets(area)` via `_apply_resets_for_redit` wrapper. ROM uses `reset_room(pRoom)` (src/olc.c:765); Python's broader-scope `apply_resets(area)` is a documented minor divergence pending a per-room reset port. **OLC_ACT-004**: `redit <vnum>` silent-teleport reuses existing `_char_from_room`/`_char_to_room` primitives from `mud.commands.imm_commands` per the locked human-decision flag — no new movement infra. Validates target room exists, IS_BUILDER on TARGET area, relocates, sets descriptor edit pointer. Unblocks OLC-017 (all three halves: create/reset/vnum). Tests: `tests/integration/test_olc_act_002_redit_create.py` (8), `tests/integration/test_olc_act_003_redit_reset.py` (4), `tests/integration/test_olc_act_004_redit_vnum_teleport.py` (5).
141
+ - `OLC_ACT-006` — `medit create <vnum>` subcommand (`mud/commands/build.py:_medit_create`). Mirrors ROM `src/olc_act.c:3704-3753` plus `new_mob_index` defaults from `src/mem.c:365-424` (player_name="no name", short_descr="(no short description)", long_descr="(no long description)\\n\\r", description="", level=0, sex=Sex.NONE, size=Size.MEDIUM, start_pos="standing", default_pos="standing", material="unknown", new_format=True). **CRITICAL**: `ActFlag.IS_NPC` is set on both `act_flags` (modern) and legacy `act` per ROM `src/olc_act.c:3745` `pMob->act = ACT_IS_NPC;` — without this, every NPC-classification check downstream would misclassify newly-built mobs as players. Full ROM validation chain (vnum required, area assignment, builder security, already-exists). Removed pre-existing auto-create-on-unknown-vnum bug. Unblocks OLC-019. Test: `tests/integration/test_olc_act_006_medit_create.py` (12 cases). Drive-by: `tests/integration/test_olc_builders.py:test_mob_proto` fixture also patched to write to the canonical `mud.models.mob.mob_registry` (matching the OLC_ACT-005 obj-fixture fix).
142
+ - `OLC_ACT-005` — `oedit create <vnum>` subcommand (`mud/commands/build.py:_oedit_create`). Mirrors ROM `src/olc_act.c:3178-3225` plus `new_obj_index` defaults from `src/mem.c:297-335` (name="no name", short_descr="(no short description)", description="(no description)", item_type="trash", material="unknown", extra_flags=0, wear_flags=0, weight=0, cost=0, value=[0]*5, new_format=True). Full ROM validation chain: vnum required (empty/zero rejected with "Syntax: oedit create [vnum]"), area assignment ("OEdit: That vnum is not assigned an area."), builder security ("OEdit: Vnum in an area you cannot build in."), already-exists ("OEdit: Object vnum already exists."). Returns "Object Created.\n\r" on success. **Removed** the pre-existing auto-create-on-unknown-vnum bug — unknown vnums without the explicit `create` keyword now return an error instead of silently allocating a new proto. Unblocks OLC-018. Test: `tests/integration/test_olc_act_005_oedit_create.py` (11 cases). Drive-by: fixed `tests/integration/test_olc_builders.py:test_obj_proto` fixture which registered protos in the wrong registry (`mud.registry.obj_registry` vs the canonical `mud.models.obj.obj_index_registry`).
143
+ - `OLC_ACT-001` — `aedit create` subcommand (`mud/commands/build.py:cmd_aedit` + `_aedit_create`). Mirrors ROM `src/olc_act.c:667-679` plus authoritative defaults from `src/mem.c:91-122` (`new_area`): `name="New area"`, `builders="None"`, `security=1`, `min/max_vnum=0`, `empty=True`, `area_flags=AreaFlag.ADDED`, `file_name="area<vnum>.are"`. Vnum allocation uses `max(area_registry) + 1` (Python adaptation; ROM uses global `top_area` counter). Reachable from both `@aedit create` (no active session) and `create` typed inside an active aedit session. Unblocks OLC-016 in the sibling audit. Test: `tests/integration/test_olc_act_001_aedit_create.py` (9 cases).
144
+ - `olc_act.c` parity audit (`docs/parity/OLC_ACT_C_AUDIT.md`) — Phase 1–3 complete. 108 ROM functions inventoried across four editors (aedit/redit/oedit/medit); mpedit/hedit out of scope (sibling audits). 14 stable gap IDs filed (OLC_ACT-001..014): 6 CRITICAL (aedit_create wholly missing; redit_create missing; redit reset/vnum dispatcher gaps; oedit_create missing security gate; medit_create missing ACT_IS_NPC flag on new mobs), 6 IMPORTANT (show-command completeness for all four editors; success message string drift; aedit_reset missing), 2 MINOR (structural). Tier breakdown: TIER A 9 functions (line-by-line), TIER B 8 functions (moderate), TIER C ~78 functions (inventory). Closures pending via `rom-gap-closer` per-gap. Tracker: olc_act.c row flipped ❌ Not Audited → ⚠️ Partial.
145
+
146
+ ### Fixed
147
+
148
+ - `OLC_ACT-007` — `aedit show` now includes the area flags row (mirroring ROM `src/olc_act.c:644-646`). The Flags line uses `flag_string(AreaFlag, area.area_flags)` to format the ADDED/CHANGED/LOADING flags. Test: `tests/integration/test_olc_act_007_aedit_show_flags.py` (5 cases).
149
+ - `OLC_ACT-008` — `redit show` brought to ROM byte-parity with `src/olc_act.c:1068-1236`. Sector display labels in `_SECTOR_NAMES` (`mud/commands/build.py`) now use `swim`/`noswim` per ROM `src/tables.c:391-392` (previously `water_swim`/`water_noswim`); the exit line in `_room_summary` now emits the two-space gap between `Key: [%5d]` and `Exit flags:` per ROM lines 1184/1196 (single sprintf trailing space + strcat leading space). The remaining ROM fields (description, name, area, vnum, room flags, heal/mana/clan/owner/extra-descs, characters, objects, per-exit keyword/description, uppercase-non-reset flag rule) were already implemented in `_room_summary`; the new parity tests lock them in going forward. Test: `tests/integration/test_olc_act_008_redit_show_parity.py` (4 cases).
150
+ - `OLC_ACT-010` — `medit show` rewritten to ROM byte layout (`src/olc_act.c:3519-3699`). Now emits all ROM rows in order: Name/Area, Act flags, Vnum/Sex/Race, Level/Align/Hitroll/DamType, conditional Group, Hit/Damage/Mana dice, Affected by, Armor (4 columns), Form, Parts, Imm, Res, Vuln, Off, Size, Material, Start/Default pos, Wealth, Short/Long/Description. New helpers `_format_intflag`/`_format_position`/`_format_size`/`_format_sex` in `mud/commands/build.py`. Three sub-gaps explicitly deferred and recorded in `docs/parity/OLC_ACT_C_AUDIT.md`: **OLC_ACT-010b** dice/AC byte format (Python data model stores strings; ROM stores 3 ints per dice); **OLC_ACT-010c** shop/mprogs/spec_fun rendering (needs MobShop/MProg model alignment + `spec_name` lookup); **OLC_ACT-010d** ROM-faithful flag-table name strings (display tables analogous to OLC_ACT-009's `_WEAR_FLAG_DISPLAY`/`_EXTRA_FLAG_DISPLAY` needed for 10 mob flag tables). Existing `tests/test_olc_medit.py::test_medit_show_command` assertions updated to ROM format. New: `tests/integration/test_olc_act_010_medit_show_parity.py` (8 cases).
151
+ - `OLC_ACT-012` — `aedit reset` subcommand wired in `_interpret_aedit` (`mud/commands/build.py`). Mirrors ROM `src/olc_act.c:653-663` `aedit_reset`: calls `apply_resets(area)` via the existing `_apply_resets_for_redit` wrapper, sets `area.changed=True`, returns ROM-exact `"Area reset."` (previously `"Unknown area editor command: reset"`). Test: `tests/integration/test_olc_act_012_aedit_reset.py` (1 case).
152
+ - `OLC_ACT-011` — All four `*_name` OLC builders (`aedit_name`, `redit_name`, `oedit_name`, `medit_name`) now return ROM's exact `"Name set."` success message (was Python-verbose "Area name set to: X" / "Room name set to X" / "Object name (keywords) set to: X" / "Player name set to: X"). ROM source: `src/olc_act.c:683-700`/`1770-1787`/`2990-3010`/`3913-3931`. Existing assertions in `tests/test_olc_aedit.py` / `test_olc_medit.py` / `test_olc_oedit.py` updated. New: `tests/integration/test_olc_act_011_name_messages.py` (4 cases).
153
+ - `OLC_ACT-009` — `oedit show` rewritten to ROM byte layout (`src/olc_act.c:2733-2812`) + `_show_obj_values` ported from ROM `show_obj_values` (`src/olc_act.c:2210-2374`). New display tables `_WEAR_FLAG_DISPLAY` / `_EXTRA_FLAG_DISPLAY` mirror `src/tables.c:434-483` byte-for-byte (ROM-faithful labels: "finger"/"nosac"/"wearfloat"/"antigood"/"rotdeath" — not Python enum-name forms). New `_APPLY_NAMES` dict mirrors `src/merc.h:1205-1231` + `src/tables.c:489-516` for the affects table (with the ROM `APPLY_SAVES`/`APPLY_SAVING_PARA` 20-collision resolved to "saves"). `_show_obj_values` covers 13 ITEM_* cases (LIGHT, WAND/STAFF, PORTAL, FURNITURE, SCROLL/POTION/PILL, ARMOR, WEAPON, CONTAINER, DRINK_CON, FOUNTAIN, FOOD, MONEY); WAND/STAFF/SCROLL/POTION/PILL spell-name lookup emits raw value-index until a skill-by-index registry lands. Existing `tests/test_olc_oedit.py::test_oedit_show_command` assertions updated from Python-only verbose labels to ROM format. New: `tests/integration/test_olc_act_009_oedit_show_parity.py` (8 cases).
154
+ - `OLC-022` — `do_resets` (`mud/commands/imm_olc.py`) rewritten with full ROM subcommand set (src/olc.c:1232-1469): P-reset via `inside <containerVnum> [limit] [count]` (validates ITEM_CONTAINER or ITEM_CORPSE_NPC), O-reset via `room`, G/E-reset via wear-loc prefix lookup (`lfin` → FINGER_L), R-reset via `random 1..6`, M-reset extended with optional `[max#area] [max#room]` args. 6-line syntax block on unrecognized numeric-arg subcommand. `_add_reset` helper extracted. Test: `tests/integration/test_olc_do_resets_subcommands.py` (27 cases).
155
+ - `OLC-020` — `display_resets` (`mud/commands/imm_olc.py`) now faithfully formats each reset type (M/O/P/G/E/D/R) with exact ROM `sprintf` column widths, pet-shop `final[5]='P'` overlay (src/olc.c:1037-1044), wear-loc decoding via `wear_loc_strings` table, and door-reset state decoding. Bad-mob/obj `continue` paths correctly suppress output per ROM. New `mud/utils/olc_tables.py` provides `WEAR_LOC_STRINGS`, `WEAR_LOC_FLAGS`, `DOOR_RESETS`, `DIR_NAMES` tables ported from `src/tables.c:355-572`. Test: `tests/integration/test_olc_display_resets.py` (16 cases).
156
+ - `OLC-023` — `do_alist` (`mud/commands/imm_olc.py:121-146`) iterated the nonexistent `registry.areas` attribute and returned a header-only listing on a live system. Now iterates `area_registry.values()`, prints `area.vnum` (was a 1-indexed enumerate counter — drifted from ROM `src/olc.c:1494`'s `pArea->vnum`), and reads `area.file_name` (was the nonexistent `area.filename`). Test: `tests/integration/test_olc_alist.py` (4 cases).
157
+
158
+ ### Added
159
+
160
+ - `STRING-004` — `string_add` OLC editor input dispatcher (.c/.s/.r/.f/.h/.ld/.li/.lr dot-commands, ~/@ termination with on_commit callback, MAX_STRING_LENGTH-4 length cap) (src/string.c:121). 24 integration tests in `tests/integration/test_string_editor_string_add.py`. Completes `string.c` at 100%.
161
+ - `STRING-005` — `format_string` word-wrap, sentence capitalization (src/string.c:299).
162
+ - `STRING-002` — `mud/utils/string_editor.py:string_append(string_edit_obj, current) -> str`. Mirrors ROM `src/string.c:66-86`: enter APPEND mode, preserve the buffer, and return the editor banner (4 lines) plus the `numlines()` line-numbered listing. Takes a `StringEdit` object and a *current* string (the existing text to append to), unlike `string_edit` which clears. The banner matches ROM verbatim: `-=======- Entering APPEND Mode -========-`, help, termination, and separator. The listing shows each line with its 1-indexed line number in `%2d` format. Used by every OLC description builder (`aedit_builder`, `redit`, `medit`, `oedit`, etc.). Test: `tests/integration/test_string_editor_append.py` (9 cases).
163
+ - `STRING-001` — `mud/utils/string_editor.py:string_edit(string_edit_obj) -> str`. Mirrors ROM `src/string.c:38-57`: enter EDIT mode, clear the buffer, return the editor banner (4 lines). Takes a `StringEdit` object (mirrors ROM `ch->desc->pString` field) and initializes it with an empty buffer. The returned banner matches ROM verbatim: `-========- Entering EDIT Mode -=========-`, help prompt, termination instructions, and separator. Used by `olc_act.c::aedit_builder` ("desc edit"), `redit` (edit-description), `medit` (edit-description). Test: `tests/integration/test_string_editor_edit.py` (6 cases).
164
+ - `STRING-003` — `mud/utils/string_editor.py:string_replace(orig, old, new) -> str`. Mirrors ROM `src/string.c:95-112`: replace the first occurrence of *old* substring within *orig* with *new*. If *old* is not found, returns *orig* unchanged. Empty *old* returns *orig* unchanged (ROM behavior). Used by `string_add::.r` dot-command (STRING-004) and `aedit_builder::replace`. Test: `tests/integration/test_string_editor_replace.py` (9 cases).
165
+ - `STRING-010` — `mud/utils/string_editor.py:string_lineadd(string, newstr, line) -> str`. Mirrors ROM `src/string.c:607-645`: insert *newstr* as the 1-indexed line N. The inserted line gets a `\n\r` suffix. If line is past the end, insertion doesn't happen (never reached). Used by `.li` and `.lr` dot-commands. Test: `tests/integration/test_string_editor_lineadd.py` (10 cases).
166
+ - `STRING-009` — `mud/utils/string_editor.py:string_linedel(string, line) -> str`. Mirrors ROM `src/string.c:574-605`: remove the 1-indexed line N from the string, preserving `\n\r` line endings. Out-of-range line numbers are a no-op. Used by `.ld` dot-command. Test: `tests/integration/test_string_editor_linedel.py` (8 cases).
167
+ - `STRING-012` — `mud/utils/string_editor.py:numlines(string) -> str`. Mirrors ROM `src/string.c:676-692`: format string as line-numbered listing (`%2d. <line>\n\r`), 1-indexed. Used by `.s` dot-command and `string_append` greeting. Test: `tests/integration/test_string_editor_numlines.py` (7 cases).
168
+ - `STRING-011` — `mud/utils/string_editor.py:merc_getline(string) -> tuple[str, str]`. Mirrors ROM `src/string.c:647-674`: read one `\n`-terminated line; consume trailing `\r` when present (ROM `\n\r` canonical line ending). Returns `(rest, line)`. Test: `tests/integration/test_string_editor_merc_getline.py` (6 cases).
169
+ - `STRING-006` — `mud/utils/string_editor.py:first_arg(argument, lower=False) -> tuple[str, str]`. Mirrors ROM `src/string.c:468-508`: quote/paren-aware single-arg parser. Recognizes `'`/`"`/`%` (self-pair quotes) and `(`/`)` (balanced pair). Unterminated quotes consume the entire remainder. The `lower` flag (ROM `fCase`) lowercases the parsed word. Test: `tests/integration/test_string_editor_first_arg.py` (10 cases).
170
+ - `STRING-008` — `mud/utils/string_editor.py:string_proper(argument) -> str`. Mirrors ROM `src/string.c:551-572`: uppercases first char of each space-delimited word, leaves rest of each word as-is. Differs from Python `str.title()` which also lowercases the rest. Test: `tests/integration/test_string_editor_proper.py` (8 cases).
171
+ - `STRING-007` — `mud/utils/string_editor.py:string_unpad(argument) -> str`. Mirrors ROM `src/string.c:516-543`: trims leading/trailing spaces (only spaces, not all whitespace) — `aedit_builder` callers expect tab/newline preservation. Test: `tests/integration/test_string_editor_unpad.py` (7 cases).
172
+ - `BIT-003` — `mud/utils/bit.py:is_stat(table) -> bool`. Mirrors ROM `src/bit.c:93-104` (and replaces ROM's static `flag_stat_table[]` registry at `src/bit.c:50-83`): returns True for IntEnum (stat) tables, False for IntFlag (flag) tables. The Python port encodes the stat-vs-flag distinction in the type system, so no runtime registry is needed. With BIT-001/002/003 closed, `bit.c` flips ✅ Audited 90% → ✅ Audited 100%. Test: `tests/integration/test_bit_is_stat.py` (5 cases).
173
+ - `BIT-002` — `mud/utils/bit.py:flag_string(table, bits) -> str`. Mirrors ROM `src/bit.c:151-177`: returns a space-joined string of every flag name set in *bits* for IntFlag (flag) tables, the single matched name for IntEnum (stat) tables, or the literal `"none"` when nothing matched. The ROM rotating two-buffer trick (`buf[2][512]`) is unnecessary in Python (immutable strings). Composite alias IntFlag members are skipped to avoid double-printing. Test: `tests/integration/test_bit_flag_string.py` (8 cases).
174
+ - `BIT-001` — `mud/utils/bit.py:flag_value(table, argument) -> int | None`. Mirrors ROM `src/bit.c:111-142`: tokenizes the argument, prefix-looks up each token, OR-accumulates hits for IntFlag (flag) tables, returns a single matched value for IntEnum (stat) tables, returns `None` (the `NO_FLAG` sentinel) on no match. Unknown tokens are silently skipped, mirroring ROM `flag_value` semantics (which differ from ROM `do_flag` on purpose). Test: `tests/integration/test_bit_flag_value.py` (9 cases).
175
+ - `OLC-INFRA-001` — descriptor-level OLC editor state plumbing. New `mud/olc/editor_state.py` provides `EditorMode` IntEnum (mirrors ROM `src/olc.h:53-59` — `NONE`/`AREA`/`ROOM`/`OBJECT`/`MOBILE`/`MPCODE`/`HELP`), `StringEdit` dataclass (mirrors ROM `desc->pString` — buffer + on-commit hook + `MAX_STRING_EDIT_LENGTH=4604`), and `route_descriptor_input(session)` (mirrors ROM `src/comm.c:833-847` — `string_edit` precedes `editor_mode` precedes normal interpret). `Session.editor_mode` and `Session.string_edit` fields wired in `mud/net/session.py`. Destinations (`string_add` for STRING-004, `run_olc_editor` for OLC-001) remain stubbed under their own gap IDs; this commit lands only the routing decision and data shapes that unblock the STRING-001..012 cluster. Test: `tests/integration/test_olc_descriptor_state.py` (6 cases).
176
+
177
+ ### Changed
178
+
179
+ - `string.c` parity audit (`docs/parity/STRING_C_AUDIT.md`) — `string.c` flipped ⚠️ Partial 85% (stale, wrong file path) → ✅ Audited 5% (accurate). Phase 1 inventory catalogues all 12 public functions (`string_edit`, `string_append`, `string_replace`, `string_add`, `format_string`, `first_arg`, `string_unpad`, `string_proper`, `string_linedel`, `string_lineadd`, `merc_getline`, `numlines`); every one is OLC-editor backend operating on `ch->desc->pString`/`ch->desc->editor` with no current Python consumer (`mud/olc/` skeleton only). 12 stable gap IDs filed (`STRING-001..STRING-012`), all DEFERRED to the OLC audit cluster (`olc.c`/`olc_act.c`/`olc_save.c`/`olc_mpcode.c`/`hedit.c`) where their first concrete consumers will appear. Previous tracker note "85% — `mud/utils.py`" was stale: that file does not exist; only `mud/utils/text.py:smash_tilde` (a `merc.h` helper, not a `string.c` helper) is ported. No code changes.
180
+ - `const.c` parity audit (`docs/parity/CONST_C_AUDIT.md`) — Phase 1–3 complete. 16 ROM data tables inventoried; 13 ✅ AUDITED (item, wiznet, attack, race, pc_race, class, int_app, liq, skill, group, plus `str_app.carry` + `str_app.wield` columns); 7 stable gap IDs filed (`CONST-001`..`CONST-007`). **Four CRITICAL combat-math gaps surfaced**: `CONST-002` `GET_HITROLL` macro missing `str_app[STR].tohit` (`mud/combat/engine.py:411,420`), `CONST-003` `GET_DAMROLL` missing `str_app[STR].todam` (`mud/combat/engine.py:1184`), `CONST-004` `GET_AC` missing `dex_app[DEX].defensive` (`mud/combat/engine.py:391`), `CONST-005` `advance_level` missing `con_app[CON].hitp` + `number_range(hp_min,hp_max)` per-level HP roll (`mud/advancement.py:91`). One IMPORTANT advancement gap (`CONST-006` `wis_app[WIS].practice` in `advance_level`). One IMPORTANT data gap (`CONST-001` `title_table` 480 entries — defer to NANNY-009 dedicated session). One MINOR (`CONST-007` `weapon_table` — defer to OLC audit, BIT-style). `ROM_C_SUBSYSTEM_AUDIT_TRACKER.md` row updated; tracker held at ⚠️ Partial 80% pending closures via `/rom-gap-closer`. No code changes.
181
+ - `bit.c` parity audit (`docs/parity/BIT_C_AUDIT.md`) — `bit.c` flipped ⚠️ Partial 90% → ✅ Audited 90%. Confirmed the only current Python consumer of bit.c-shaped logic (`do_flag` in `mud/commands/remaining_rom.py`) faithfully mirrors ROM `do_flag` semantics (not ROM `flag_value` — they differ on unknown-name handling on purpose). Three MINOR helpers (`flag_value`, `flag_string`, `flag_stat_table`+`is_stat`) recorded as `BIT-001`/`BIT-002`/`BIT-003` and deferred to the OLC audit, where their first concrete consumers (`olc.c`, `olc_act.c`, `olc_save.c`, `act_olc.c`) will appear. No code changes.
182
+ - `docs/parity/ROM_C_SUBSYSTEM_AUDIT_TRACKER.md` — reconciled the stale `P1-3: db.c + db2.c (PARTIAL - 55%)` section with the actual audit state. Both files have been ✅ Audited 100% on the summary table since the Jan 5 (db.c) and Apr 28 (db2.c) sessions; the P1-3 narrative section has been rewritten to reflect that and to point at the per-file audit docs (`DB_C_AUDIT.md` covers db.c's 44/44 functional functions; `DB2_C_AUDIT.md` covers DB2-001/002/003/006 closures and DB2-004/005 deferred MINORs). No code changes.
183
+
184
+ ### Added
185
+
186
+ - `comm.c` parity audit (`docs/parity/COMM_C_AUDIT.md`) — non-networking surface of `src/comm.c` (`bust_a_prompt`, `act_new`, `colour`, `check_parse_name`, `stop_idling`, `fix_sex`, `show_string`) mapped to Python equivalents. Networking layer (`main`, `init_socket`, `game_loop_*`, descriptor I/O) confirmed deferred-by-design per the asyncio rewrite. Phase 3 produces 9 stable gap IDs (`COMM-001..COMM-009`).
187
+ - `mud/utils/prompt.py:bust_a_prompt(char) -> str` — port of ROM `src/comm.c:1420-1595`. Expands `%h %H %m %M %v %V %x %X %g %s %a %r %R %z %% %e %c %o %O` against character state, falls back to `<%dhp %dm %dmv> %s` when `ch->prompt` is unset, short-circuits to `<AFK>` when `COMM_AFK` is on. Wired into both telnet game-loop call sites in `mud/net/connection.py`. Test: `tests/integration/test_prompt_rom_parity.py` (8 cases).
188
+ - `board.c` parity audit (`docs/parity/BOARD_C_AUDIT.md`) — full Phase 1 inventory of every public ROM function in `src/board.c` (Erwin Andreasen 1995–96 note-board subsystem) mapped to `mud/notes.py`, `mud/models/board.py`, and `mud/commands/notes.py`. Phase 3 produces 14 stable gap IDs (BOARD-001..BOARD-014); `tracker.md` flips `board.c` from ❌ Not Audited 35% → ⚠️ Partial 85%. New regression suite `tests/integration/test_boards_rom_parity.py` (6 ROM-parity tests, all green).
189
+
190
+ ### Added
191
+
192
+ - `MUSIC-002` — `mud/music/__init__.py:load_songs(path=area/music.txt)` ports ROM `src/music.c:160-218`. Reads the ROM-format music data file (`group~` / `name~` / lyric lines / `~` / `#`), populates `mud.music.song_table` (up to `MAX_SONGS=20`), resets `channel_songs[0..MAX_GLOBAL]` to `-1`, drops lyrics past `MAX_LINES=100` with a warning, and gracefully no-ops on a missing file. Wired into `mud/world/world_state.py:initialize_world` so the song table is populated at boot — the global "MUSIC:" channel and `play list` previously had nothing to broadcast or display. Tests: `tests/integration/test_music_load_songs.py` (3 cases).
193
+
194
+ ### Fixed
195
+
196
+ - `CONST-006` — `advance_level` per-level practice gain now applies `wis_app[get_curr_stat(ch, STAT_WIS)].practice`, mirroring ROM `src/update.c:87`. Previously the gain was a hardcoded `PRACTICES_PER_LEVEL = 2` constant — WIS-3 dunce was getting 2 free practices/level instead of 0; WIS-13 default got 2 instead of 1; WIS-25 sage got 2 instead of 5. New `mud/math/stat_apps.py::WIS_APP` table (verbatim port of `src/const.c:790-817`) and `wis_practice_bonus(ch)` accessor. The level-up message now reflects the actual roll with correct singular/plural pluralisation. Per AGENTS.md "test asserting behavior that contradicts ROM is a bug in the test", five existing tests in `tests/test_advancement.py` and `tests/integration/test_character_advancement.py` that asserted the old constant gain were updated to assert ROM's wis_app formula. Test: `tests/integration/test_advancement_wis_app.py` (26 cases).
197
+ - `CONST-005` — `advance_level` per-level HP gain now follows ROM `src/update.c:74-79` exactly: `UMAX(2, (con_app[get_curr_stat(ch, STAT_CON)].hitp + number_range(class_table[ch->class].hp_min, class_table[ch->class].hp_max)) * 9 / 10)`. Previously used a static `LEVEL_BONUS[ch_class]` dict (`mud/advancement.py:91`) — both the RNG roll and the CON modifier were absent, so a CON-25 character was missing +8 hitp/level and a CON-3 character was missing −2 hitp/level on top of the missing variability. New `mud/math/stat_apps.py::CON_APP` table (verbatim port of `src/const.c:850-878`) and `con_hitp_bonus(ch)` accessor. Mana/move continue to use the legacy `LEVEL_BONUS` path until their respective gaps close. Per AGENTS.md "test asserting behavior that contradicts ROM is a bug in the test", six existing tests in `tests/test_advancement.py` and `tests/integration/test_character_advancement.py` that asserted the old static HP values were updated to seed `rng_mm.number_range` and assert the ROM formula. Test: `tests/integration/test_advancement_con_app.py` (14 cases).
198
+ - `CONST-004` — Armor class now augments `armor[type]` with `dex_app[get_curr_stat(ch, STAT_DEX)].defensive` when the character `IS_AWAKE` (`position > POS_SLEEPING`), mirroring ROM `src/merc.h:2104-2106`. New `mud/math/stat_apps.py::DEX_APP` table (verbatim from `src/const.c:821-848`) and `get_ac(ch, ac_type)` accessor; combat at `mud/combat/engine.py:391`, `do_score` at `mud/commands/session.py`, and the wiz `stat char` AC line at `mud/commands/imm_search.py` all read through it. Sleeping/stunned/incap/dead victims still show raw armor (the IS_AWAKE gate). Before this fix, a DEX-3 character was missing +40 AC penalty and a DEX-25 character was missing −120 AC bonus on every combat hit-roll and every AC display. Test: `tests/integration/test_combat_dex_app.py` (11 cases).
199
+ - `CONST-003` — Combat `GET_DAMROLL` now augments `ch->damroll` with `str_app[get_curr_stat(ch, STAT_STR)].todam`, mirroring ROM `src/merc.h:2109-2110` (consumed at `src/fight.c:588` for weapon damage). New `mud/math/stat_apps.py::get_damroll(ch)` accessor; `calculate_weapon_damage` at `mud/combat/engine.py:1189` now reads it. Before this fix, a STR-3 attacker missed −1 damage and a STR-25 attacker missed +9 damage. Test: `tests/integration/test_combat_str_app.py::test_get_damroll_*` (7 cases).
200
+ - `CONST-002` — Combat `GET_HITROLL` now augments `ch->hitroll` with `str_app[get_curr_stat(ch, STAT_STR)].tohit`, mirroring ROM `src/merc.h:2107-2108` (consumed at `src/fight.c:471` for THAC0). New module `mud/math/stat_apps.py` ports `STR_APP[26]` verbatim from `src/const.c:728-755` and exposes `get_hitroll(ch)`; both attack paths in `mud/combat/engine.py` (THAC0 at L411, percent fallback at L420) now read the augmented value. Before this fix, a STR-3 attacker missed −3 to-hit and a STR-25 attacker missed +6. Test: `tests/integration/test_combat_str_app.py` (8 cases).
201
+ - `MUSIC-004` — `mud/commands/player_info.py:do_play` jukebox scan now applies `mud.world.vision.can_see_object(ch, obj)` so invisible / VIS_DEATH / dark-room jukeboxes drop out of selection, mirroring ROM `src/music.c:229-232`'s `can_see_obj(ch, juke)` filter. Test: `tests/integration/test_music_play.py::test_do_play_skips_invisible_jukebox`.
202
+
203
+ - `MUSIC-003` — `play list` in `mud/commands/player_info.py:do_play` now reads `mud.music.song_table` (previously `mud.registry.song_table`, which doesn't exist, so it always fell through to a 3-song hardcoded stub). Reproduces ROM `src/music.c:246-292`: capitalized `"<short_descr> has the following songs available:"` header, `play list <prefix>` filters song names by case-insensitive prefix in two `%-35s` columns, `play list artist [<prefix>]` filters by group name in single-line `%-39s %-39s` group/name pairs, and a trailing odd column is flushed on its own line. Tests: `tests/integration/test_music_play.py` (4 new list-formatting cases).
204
+
205
+ - `MUSIC-001` — `mud/commands/player_info.py:do_play` now ports the queueing half of ROM `src/music.c:220-354`. Previously a stub: it found a jukebox, returned `"Coming right up."`, and queued nothing — so `song_update()` had nothing to broadcast and `play loud` was silently ignored. The port now resolves the `loud` keyword for global plays, enforces the `value[4] > -1` / `channel_songs[MAX_GLOBAL] > -1` queue-full check (`"The jukebox is full up right now."`), case-insensitive name-prefix matches against `mud.music.song_table`, surfaces `"That song isn't available."` on no match, and writes the song id into the first free `juke.value[1..4]` (local) or `channel_songs[1..MAX_GLOBAL]` (global) slot — also resetting the slot-0 line cursor to `-1` when slot 1 is filled, matching ROM `src/music.c:337-352`. Tests: `tests/integration/test_music_play.py` (7 cases).
206
+
207
+ - `NANNY-008` — `broadcast_entry_to_room` (`mud/net/connection.py`) now moves `char.pet` into the owner's room via `char_to_room` and emits a TO_ROOM "$n has entered the game." for the pet on login, mirroring ROM `src/nanny.c:810-815`. Previously a returning player's pet stayed un-roomed and onlookers never saw the pet's arrival. Test: `tests/integration/test_nanny_login_parity.py::test_login_pet_follows_owner_into_room`.
208
+ - `COMM-009` — Standalone `mud/utils/fix_sex.py:fix_sex(ch)` helper added, mirroring ROM `src/comm.c:2178-2182`: clamps `ch.sex` to `[0,2]`, falling back to `pcdata.true_sex` for PCs and `0` for NPCs. Inline clamp at the affect-strip site in `mud/handler.py:1110-1112` now delegates to the helper. Test: `tests/test_fix_sex.py` (5 cases).
209
+ - `COMM-008` — ANSI translator now covers ROM `colour()` specials at `src/comm.c:2714-2728`: `{D` → `\x1b[1;30m`, `{*` → `\x07` (bell), `{/` → `\n\r`, `{-` → `~`, `{{` → `{`. `mud/net/ansi.py` rewritten as a single-pass `re.sub` so `{{` cannot be re-matched as `{h` once partially consumed; `strip_ansi` mirrors ROM `send_to_char` non-colour branch (`src/comm.c:1995-2007`) by eating both characters of any `{X` pair. Tests: `tests/test_ansi.py::test_translate_ansi_handles_rom_specials` and `::test_strip_ansi_eats_rom_token_pairs`.
210
+ - `COMM-007` — `_stop_idling` now broadcasts the ROM "$n has returned from the void." message through `mud/utils/act.py:act_format`, mirroring ROM `act(...)` at `src/comm.c:1922`. The previous literal `f"{name} has returned from the void."` fallback rendered "Someone has returned…" for entities without a `name`; with the new act_format pipeline, `$n` expands via `_pers` (name → short_descr fallback). Test: `tests/test_networking_telnet.py::test_stop_idling_broadcast_uses_rom_act_format`.
211
+ - `COMM-002` — `show_string` pager input semantics now match ROM. While paging, `_read_player_command` (`mud/net/connection.py`) used to treat `"c"` as continue and dispatch arbitrary non-empty input to `interpret()`. ROM `src/comm.c:632-633` instead routes input to `show_string` instead of `interpret`, and `show_string` at `src/comm.c:2131-2141` aborts on any non-empty input and consumes it as no-op. Fix: empty input continues paging; any non-empty input clears the pager and returns `" "` (no-op). The bulk paging machinery (`Session.start_paging` / `send_next_page`) was already wired through `mud/net/protocol.py:send_to_char`; this closure pinned the missing ROM-faithful abort semantics. Tests: `tests/test_networking_telnet.py::test_show_string_pager_aborts_on_any_non_empty_input_per_rom` (new) and `test_show_string_paginates_output` (updated to assert `" "` no-op consumption).
212
+ - `COMM-006` — `is_valid_character_name` now rejects names matching any clan in `CLAN_TABLE` (case-insensitive), mirroring ROM `src/comm.c:1713-1718`. `rom`/`ROM` and `loner` are both rejected at character creation.
213
+ - `COMM-004` — Character-creation name validator now rejects names that collide with any mob prototype's `player_name` keyword list, mirroring ROM `src/comm.c:1782-1796`. Implemented as a new `mud.account.is_valid_character_name` helper layered on top of `is_valid_account_name`; the old syntactic-only validator stays intact for account-name validation (a Python addition with no ROM analogue). `create_character` and the connection-layer character-creation flow both use the new validator. Pre-existing tests in `tests/test_account_auth.py` that used stock RPG names colliding with real mobs (`Zeus`, `Nomad`, `Queen`, `Guardian`) were renamed to invented tokens — per AGENTS.md "test contradicting ROM C is a bug in the test."
214
+ - `COMM-003` — `check_parse_name` length floor now matches ROM. `is_valid_account_name` rejected names shorter than 3 characters; ROM `src/comm.c:1729` rejects only names shorter than 2. Two-letter ROM-legal names (e.g. `Bo`) are now accepted. The previous NANNY-012 test (`test_name_validator_matches_rom_check_parse_name`) had locked in the buggy `< 3` threshold with a docstring misreading ROM — the test now asserts the correct ROM `< 2` bound (`Bo` accepted, `a` rejected).
215
+ - `COMM-001` — Player prompts now render character state. The telnet game loop previously emitted a literal `"> "` regardless of `do_prompt` settings; HP / mana / move / room / alignment never reached the client. Fix: replaced the hard-coded `send_prompt("> ")` with `send_prompt(bust_a_prompt(char))` at `mud/net/connection.py:1698,1923` and made `do_prompt` write to `Character.prompt` (mirrors ROM `ch->prompt`, `src/act_info.c:951-952`) instead of `PCData.prompt` (which in ROM is the colour triplet, not the format string). `send_prompt` now applies ANSI rendering so `{p…{x` colour wrappers don't leak as raw text. Five existing tests in `test_player_prompt.py` / `test_player_auto_settings.py` / `test_config_commands.py` updated to assert the correct field (per AGENTS.md "test contradicting ROM C is a bug in the test").
216
+ - `BOARD-001` — Five hardcoded ROM boards (General/Ideas/Announce/Bugs/Personal) are now seeded on `load_boards()` with the exact ROM levels, force-types, default recipients, and purge-days from `src/board.c:67-76`. Persisted JSON content is overlaid on top so notes survive a reload but the static metadata cannot drift below ROM defaults.
217
+ - `BOARD-002` / `BOARD-003` — `note write` and `note send` now emit ROM TO_ROOM `act()` broadcasts ("$n starts writing a note." / "$n finishes $s note.") via `char.room.broadcast(..., exclude=char)`, mirroring `src/board.c:503` and `src/board.c:1181`. Adds `_possessive(char)` helper for ROM `$s` (his/her/its from `Character.sex`).
218
+ - `BOARD-004` — `Board.post` now routes through a new `mud.notes.next_note_stamp(base)` helper backed by a module-level `_last_note_stamp` counter, mirroring ROM `finish_note` (`src/board.c:154-160`). Two notes posted in the same wall-clock second now get distinct, monotonically increasing timestamps so the `> last_read` unread cursor cannot collide. Test fixtures reset the counter per test (parallel to ROM rebooting `boot_db` globals).
219
+ - `BOARD-005` (and `BOARD-006`) — `Board.unread_count_for(char, last_read)` mirrors ROM `unread_notes` (`src/board.c:444-460`) by filtering through `mud.notes.is_note_to(char, note)` (the canonical recipient predicate, factored out of `mud/commands/notes.py`). `do_board` listing now uses the recipient-aware count, so Personal/per-name notes no longer leak into non-recipients' unread totals. `BOARD-006` is subsumed by this fix (ROM's listing filter `unread_notes != BOARD_NOACCESS` is now consistent with what each row displays).
220
+ - `BOARD-008` — `load_boards` now sweeps every loaded board for notes whose `expire < now` and appends them to `<board>.old.json` before re-saving the active board, mirroring ROM `load_board`'s archive at `src/board.c:365-383`. Boards no longer grow without bound across reloads.
221
+ - `BOARD-012` — `do_note` now mirrors ROM `src/board.c:736-737`: an unknown subcommand (anything other than `read`/`list`/`write`/`remove`/`purge`/`archive`/`catchup` and the Python-only draft verbs) dispatches to `do_help(ch, "note")` instead of returning the generic `"Huh?"`. Test: `tests/integration/test_boards_rom_parity.py::test_note_unknown_subcommand_shows_help`.
222
+ - `BOARD-011` — `note write` now mirrors ROM `do_nwrite` at `src/board.c:482-488`: when the player has an in-progress draft whose `text` is empty (e.g. lost link before typing the body), the stale draft is discarded and the actor sees the ROM cancellation notice ("Note in progress cancelled because you did not manage to write any text before losing link.") before a fresh draft is started. Test: `tests/integration/test_boards_rom_parity.py::test_note_write_discards_textless_in_progress_draft`.
223
+ - `BOARD-013` — Added `mud.notes.make_note(board_name, sender, to, subject, expire_days, text)` and `mud.notes.personal_message(...)` mirroring ROM `make_note` / `personal_message` at `src/board.c:843-886`. Unknown boards and text exceeding `MAX_NOTE_TEXT` (= `4 * MAX_STRING_LENGTH - 1000` = 17432, per `src/board.h:19`) return `None` (mirroring ROM's silent `bug` + return); on success the note is appended via `Board.post` (so it picks up the unique `last_note_stamp` cursor), persisted with `save_board`, and `expire = current_time + expire_days * 86400`. Unblocks programmatic Personal-board injection for death notifications and system mail.
224
+
225
+ - `TABLES-001` — `AffectFlag` bit positions (`mud/models/constants.py`) renumbered to match ROM `src/merc.h:953-982` exactly (letters A..dd → bits 0..29). Closes a 20-of-29-bit divergence where `convert_flags_from_letters` was decoding ROM area-file letters with the canonical mapping (e.g. `G` → bit 6) but Python `AffectFlag.SANCTUARY` sat on bit 6, so any letter-form area data was silently mis-aligned with the enum. Pfile schema gains `pfile_version: int` (default `0`); legacy saves are translated on load by `mud/persistence.py:translate_legacy_affect_bits` (covers character `affected_by`, every nested `Affect.bitvector` on persisted items, pet `affected_by`, and pet affect bitvectors), then re-saved at `pfile_version=1`. Reproducer `tests/integration/test_tables_parity.py::test_affect_flag_letters_match_rom_merc_h` flipped from `xfail(strict)` → green; `test_merc_h_letter_macros_match_python_intflag_values` now also covers `AFF_*`. New migration tests in `tests/integration/test_tables_001_affect_migration.py`. Tables.c flips ⚠️ Partial 75% → ✅ AUDITED 100%.
226
+ - `TABLES-003` — Programmatic verification of every `src/merc.h` letter-mapped `#define` macro against the matching Python `IntFlag` member's bit value. New test `tests/integration/test_tables_parity.py::test_merc_h_letter_macros_match_python_intflag_values` parses merc.h, resolves A..Z / aa..dd letter tokens, and cross-checks ~210 macros across the `ACT_/PLR_/OFF_/IMM_/RES_/VULN_/FORM_/PART_/COMM_/ROOM_/GATE_/FURN_/WEAPON_` prefixes. Confirms only `AFF_*` (TABLES-001) diverges; all other letter-mapped tables in `src/tables.c` have correct Python bit positions. Acts as a durable regression guard.
227
+ - `TABLES-002` — `mud/utils/prefix_lookup.py:prefix_lookup_intflag` now consults a ROM `src/tables.c` table-name alias map (`rom_flag_aliases`) before falling back to Python IntFlag member names. ROM-style abbreviations like `+npc`/`+healer`/`+changer`/`+can_loot`/`+dirt_kick`/`+noclangossip` now resolve to the matching Python flag member (`IS_NPC`/`IS_HEALER`/`IS_CHANGER`/`CANLOOT`/`KICK_DIRT`/`NOAUCTION`), restoring ROM `flag_lookup` parity for `do_flag` and OLC.
228
+
229
+ ### Added
230
+
231
+ - `tables.c` parity audit (`docs/parity/TABLES_C_AUDIT.md`): Phase 1 inventory of all 38 ROM data tables in `src/tables.c` mapped to Python `IntFlag`/`IntEnum` equivalents in `mud/models/constants.py`; Phase 2 spot-checks confirm `ActFlag` / `PlayerFlag` / `OffFlag` / `CommFlag` bit positions match ROM letters A..dd. Three gaps documented: **TABLES-001 (CRITICAL)** — `AffectFlag` bit positions diverge from ROM `merc.h:953-982` (e.g. `AFF_DETECT_GOOD=G=1<<6` in ROM, but `AffectFlag.SANCTUARY=1<<6` in Python); `convert_flags_from_letters` decodes ROM letters with the ROM-correct mapping, so any area-file `AFF G` is silently mis-decoded as `SANCTUARY`. Closure deferred — requires `AffectFlag` renumber + persistence migration plan. TABLES-002 (ROM-name aliases for prefix-match) and TABLES-003 (per-table value verification for the remaining 30+ tables) also open. New `tests/integration/test_tables_parity.py` (4 passing spot-checks + 1 xfail reproducer for TABLES-001).
232
+
233
+ ### Fixed
234
+
235
+ - `LOOKUP-008` — Added public `liq_lookup(name)` to `mud/utils/prefix_lookup.py` mirroring ROM `src/lookup.c:138-150` (case-insensitive prefix-match against `LIQUID_TABLE`, returns `-1` on miss). The loader-internal `mud/loaders/obj_loader.py:_liq_lookup` is retained because it intentionally returns `0` (water) on miss for object-load defaults. With this `lookup.c` is ✅ AUDITED at 100% (LOOKUP-001..008 all closed).
236
+ - `LOOKUP-007` — Added `item_lookup(name)` to `mud/utils/prefix_lookup.py` mirroring ROM `src/lookup.c:124-136` (case-insensitive prefix-match against `ItemType` IntEnum, returns the ITEM_X type value, `-1` on miss). Python's `ItemType` IntEnum values match ROM ITEM_X constants 1:1.
237
+ - `LOOKUP-006` — Added `size_lookup(name)` to `mud/utils/prefix_lookup.py` mirroring ROM `src/lookup.c:95-107` (case-insensitive prefix-match against `Size` IntEnum, returns `-1` on miss).
238
+ - `LOOKUP-005` — Added `sex_lookup(name)` to `mud/utils/prefix_lookup.py` mirroring ROM `src/lookup.c:81-93` (case-insensitive prefix-match against `Sex` IntEnum, returns `-1` on miss). ROM `sex_table {none, male, female, either}` maps 1:1 to Python's enum.
239
+ - `LOOKUP-004` — Added `position_lookup(name)` to `mud/utils/prefix_lookup.py` mirroring ROM `src/lookup.c:67-79` (case-insensitive prefix-match against `Position` IntEnum, returns `-1` on miss).
240
+ - `LOOKUP-003` — `lookup_clan_id` (`mud/models/clans.py`) now uses ROM-faithful prefix-match instead of exact-match. `lookup_clan_id("lo")` returns clan `loner`, `lookup_clan_id("ro")` returns clan `rom`, mirroring ROM `src/lookup.c:53-65` (`clan_lookup` calls `str_prefix`).
241
+ - `LOOKUP-002` — `_lookup_flag_bit` (`mud/commands/remaining_rom.py`) now uses ROM-faithful prefix-match instead of exact-match. `flag char Bob plr +holy` matches `HOLYLIGHT` per ROM `src/lookup.c:39-51` (`flag_lookup` calls `str_prefix`). Introduces `mud/utils/prefix_lookup.py` with shared `prefix_lookup_index` and `prefix_lookup_intflag` helpers for the remaining LOOKUP-003..008 closures.
242
+ - `LOOKUP-001` — Added `race_lookup(name: str | None) -> int` to `mud/models/races.py` mirroring ROM `src/lookup.c:110-122` (case-insensitive prefix-match against `RACE_TABLE`, fall-through `return 0`). Fixes a latent `ImportError` in `mud/persistence.py:614`'s pet-restore path: every pet load with a non-None race snapshot was crashing with `ImportError: cannot import name 'race_lookup'` because the function had not been ported. Caught during the `lookup.c` parity audit.
243
+ - `FLAG-001` — `do_flag` (`mud/commands/remaining_rom.py`) is now a fully-wired immortal command instead of a syntax-validator stub. Mirrors ROM `src/flags.c:44-251`: parses the `=`/`+`/`-`/toggle operator, dispatches `act`/`plr`/`aff`/`immunity`/`resist`/`vuln`/`form`/`parts`/`comm` to the matching Character attribute and IntFlag enum (`ActFlag`, `PlayerFlag`, `AffectFlag`, `ImmFlag`, `FormFlag`, `PartFlag`, `CommFlag`), enforces NPC-only / PC-only field guards (`Use 'plr' for PCs.`, `Use 'act' for NPCs.`, `Form/Parts can't be set on PCs.`, `Comm can't be set on NPCs.`), looks up flag names case-insensitively, rejects unknown flags with `That flag doesn't exist!`, and mutates the matching bit on the victim. Previously the command returned a confirmation string but performed no mutation. New 9-test integration suite in `tests/integration/test_flag_command_parity.py`. FLAG-002 (preserve ROM `flag_type.settable=FALSE` bits across the `=` operator) deferred as MINOR — requires per-bit settable metadata on the IntFlag enums.
244
+
245
+ ### Changed
246
+
247
+ - `sha256.c` audit completed (`docs/parity/SHA256_C_AUDIT.md`). SHA-256 primitive is delegated to Python's stdlib `hashlib` (byte-for-byte equivalent to ROM `src/sha256.c:131-318`). The `sha256_crypt` password hash (ROM `src/sha256.c:320-336`, plain unsalted single-round SHA-256) is replaced by PBKDF2-HMAC-SHA256 with a 16-byte random salt and 100 000 rounds in `mud/security/hash_utils.py` — a deliberate security upgrade with no observable gameplay parity surface (no pfile compatibility goal). Tracker row flipped from ⚠️ Partial → ✅ AUDITED.
248
+
249
+ ### Fixed
250
+
251
+ - `NANNY-012` — Name validator (`is_valid_account_name` in `mud/account/account_service.py`) now matches ROM `check_parse_name` (`src/comm.c`, called from `nanny.c:188`): minimum length raised from 2 to 3 chars, and `god` / `imp` added to the reserved-name set. Existing reserved tokens (`all auto immortal self someone something the you loner none`) are unchanged.
252
+ - `NANNY-013` — Audit correction: ROM `hit=max_hit; mana=max_mana; move=max_move` (src/nanny.c:772-775) is already covered by `from_orm` initialising `max_*` from `perm_*` plus `hit` from saved `hp` (a fresh character is persisted with `hp=perm_hit=100`). NANNY-014 reset_char further guarantees max_* are restored on every login. Added regression test.
253
+ - `NANNY-006` — Login fallback room now distinguishes immortals from mortals when no saved room can be loaded. Added `ROOM_VNUM_CHAT = 1200` constant (ROM `src/merc.h:1250`) and `default_login_room_vnum(char)` helper in `mud/net/connection.py`; an `is_admin` character with `char.room is None` lands in ROOM_VNUM_CHAT (the immortal chat room), mortals in ROOM_VNUM_TEMPLE. Mirrors ROM `src/nanny.c:791-802` `IS_IMMORTAL ? ROOM_VNUM_CHAT : ROOM_VNUM_TEMPLE`.
254
+ - `NANNY-001` — Account login now disconnects on the first wrong password (returns `None` from `_run_account_login`) instead of looping back to the Account prompt, mirroring ROM `src/nanny.c:269-274` (`close_socket(d)` on bad password). The same path applies to reconnect attempts (matching ROM's "one chance" rule for both fresh logins and CON_BREAK_CONNECT).
255
+ - `NANNY-005` — Audit correction: ROM `perm_stat[class.attr_prime] += 3` (src/nanny.c:769) was already implemented in `mud/account/account_service.py:finalize_creation_stats` and locked in by `tests/test_nanny_rom_parity.py::test_prime_attribute_bonus_formula`. ROM applies the bonus during the `level == 0 → 1` promotion inside `CON_READ_MOTD`; Python applies it equivalently during `create_character` since Python characters are persisted at level 1.
256
+ - `NANNY-004` — Audit correction: ROM `learned[weapon_gsn] = 40` (src/nanny.c:653) was already implemented in `mud/models/character.py:from_orm` (lines 1047-1051), which uses `_STARTING_WEAPON_SKILL_BY_VNUM` to seed the picked weapon's skill to ≥40 on every load. Audit had cited the prompt-time path. Added regression test.
257
+ - `NANNY-003` — Audit correction: ROM `learned[gsn_recall] = 50` (src/nanny.c:581) was already implemented in `mud/models/character.py:from_orm` (lines 1052-1053), which clamps `learned["recall"]` to ≥50 on every character load. Audit had cited the wrong source location. Added regression test to lock in the behavior.
258
+ - `NANNY-002` — Login flow now honors the `PlayerFlag.DENY` bit per ROM `src/nanny.c:197-205`: a denied character logs `Denying access to <name>@<host>.`, receives `You are denied access.`, and is rejected before reaching the game loop. New `is_character_denied_access` helper in `mud/net/connection.py`, wired into both load branches of `_select_character`.
259
+ - `NANNY-007` — Login flow now broadcasts `<Name> has entered the game.` to other room occupants on every fresh (non-reconnect) login, mirroring ROM `act("$n has entered the game.", ch, NULL, NULL, TO_ROOM)` at `src/nanny.c:804`. New `broadcast_entry_to_room` helper in `mud/net/connection.py` excludes the actor and uses `act_format` for `$n` substitution.
260
+ - `BAN-004` — `BanEntry.matches` (`mud/security/bans.py`) no longer falls through to exact-string match when neither PREFIX nor SUFFIX bit is set; ROM `src/ban.c:104-132` `check_ban` silently skips such entries. Pre-existing tests in `tests/test_bans.py` and `tests/test_account_auth.py` were updated to use `*host*` patterns so a host-specific ban actually matches under ROM semantics.
261
+ - `BAN-003` — `_apply_ban` (`mud/commands/admin_commands.py`) now accepts ROM-style prefix abbreviations of the type token (`a`, `n`, `p`, `al`, `ne`, …), matching `src/ban.c:180-191` `!str_prefix(arg2, "all"/"newbies"/"permit")`. Previously required full-prefix `startswith` so single-letter abbreviations were rejected.
262
+ - `BAN-002` — `_render_ban_listing` now mirrors ROM's chained ternary at `src/ban.c:166-168`: prints `"newbies"` / `"permit"` / `"all"` based on the corresponding flag bits and falls through to `""` when none is set. Previously defaulted to `"all"` in the no-flag case.
263
+ - `BAN-001` — `_render_ban_listing` (`mud/commands/admin_commands.py`) now left-aligns the level column (`:<3d`) to match ROM `src/ban.c:164` `%-3d` instead of right-aligning. Visible in `banlist` / `ban` (no-arg) output.
264
+ - `NANNY-011` — `_prompt_new_password` (`mud/net/connection.py`) now rejects passwords containing `~` with ROM message "New password not acceptable, try again." mirroring ROM `src/nanny.c:396-405` file-format poisoner check. Python uses a DB backend so the practical risk is gone, but parity with ROM input validation is preserved.
265
+ - `NANNY-014` — Login flow now invokes `reset_char(ch)` on every successful login (ROM `src/nanny.c:760`), restoring `max_hit`/`max_mana`/`max_move` from `pcdata.perm_*`, zeroing transient `mod_stat[]`/`hitroll`/`damroll`/`saving_throw`, and re-applying equipment affects so returning characters land with clean state. Wired into both branches of `mud/net/connection.py:handle_connection` via new `apply_login_state_refresh` helper. Also corrected a latent bug in `mud/handler.py:reset_char` where `range(int(WearLocation.MAX))` raised `AttributeError` (the enum has no `MAX` member); replaced with literal `19` matching ROM `MAX_WEAR` (`src/merc.h:1356`).
266
+ - `SPEC-001` — `spec_executioner` yell now broadcasts area-wide (ROM `src/special.c:890-893`) instead of room-only. Added `_yell_area` helper mirroring ROM `do_yell`.
267
+ - `SPEC-002` — `spec_guard` now checks ALL room occupants for evil-alignment combatants (ROM `src/special.c:948-972`), not just PCs. The fallback path targeting `alignment < max_evil` fighters now works for NPCs too.
268
+ - `SPEC-003` — `spec_mayor` gate open/close now emits proper TO_CHAR (`You open the gate.`) and TO_ROOM (`Mayor opens gate.`) messages, plus reverse-exit toggle. Mirrors ROM `do_function(ch, &do_open, "gate")` / `do_function(ch, &do_close, "gate")`.
269
+ - `SPEC-004` — `spec_thief` gold/silver division now uses `c_div` (C integer division) instead of Python `//`, matching ROM `src/special.c:1174-1186`.
270
+ - `SPEC-005` — `spec_nasty` ambush now calls `do_murder` (which sets PLR_KILLER flag) instead of `do_kill`, matching ROM `src/special.c:368-371`. Updated `_issue_command` to search multiple command modules.
271
+ - `SPEC-006` — `spec_troll_member` and `spec_ogre_member` now check `is_safe()` before attacking, matching ROM `src/special.c:145,213`. Prevents attacks in safe rooms.
272
+ - `SPEC-008` — `spec_mayor` movement now uses `move_character()` (with fallback for test SimpleNamespace objects), matching ROM `move_char(ch, dir, FALSE)`.
273
+ - `SPEC-012` — `spec_nasty` gold steal now uses `c_div(gold_before, 10)` instead of `gold_before // 10`, matching ROM `src/special.c:394-396`.
274
+
275
+ - `WIZ-001` — `goto`, `at`, and `transfer` now mirror ROM `src/act_wiz.c:821-839,897-905,957-966` owner/private-room gating by honoring owner-locked rooms, the canonical `ROOM_SOLITARY` flag value, and `is_room_owner()` bypass semantics.
276
+ - `WIZ-002` — `violate` now mirrors ROM `src/act_wiz.c:1000-1057`: it targets rooms through `find_location()`, rejects public rooms with the `use goto` hint, and no longer parses directions/exits.
277
+ - `WIZ-003` — `protect` now mirrors ROM `src/act_wiz.c:2086-2118` lookup/messages and toggles the real `CommFlag.SNOOP_PROOF` bit instead of the old `COMM_NOTELL` value.
278
+ - `WIZ-004` — `snoop` now honors the canonical `CommFlag.SNOOP_PROOF` bit from ROM `src/act_wiz.c:2167-2174`, preventing snooping of correctly protected targets.
279
+ - `WIZ-006` — `log` command now mirrors ROM `src/act_wiz.c:2927-2984`: uses `get_char_world()` for lookup, toggles `PlayerFlag.LOG` on `victim.act` instead of a `log_commands` bool, rejects NPCs with ROM message, and uses canonical `\n\r` line endings.
280
+ - `WIZ-007` — `force` command now mirrors ROM `src/act_wiz.c:4183-4322`: adds `gods` branch for hero+ players, adds private-room check before forcing individuals, applies trust check to all victims (not just non-NPCs), iterates `descriptor_list` for `force all` and `char_list` for `force players`/`force gods`, and uses canonical `\n\r` line endings.
281
+ - `WIZ-005` — `stat` family now mirrors ROM `src/act_wiz.c:1059-1742`: `do_stat` dispatcher uses `get_char_world`/`get_obj_world`/`find_location` per ROM; `do_rstat` outputs Name/Area/Vnum/Sector/Light/Healing/Mana/Room flags/Description/Extra descs/Characters/Objects/Door details; `do_ostat` outputs Name(s)/Vnum/Format/Type/Resets/Short+Long descr/Wear bits/Extra bits/Number+Weight/Level+Cost+Condition+Timer/In room+In obj+Carried by+Wear_loc/Values/Item-type blocks (scroll, potion, pill, wand, staff, drink_con, weapon, armor, container)/Extra descs/Affects; `do_mstat` outputs Name/Vnum/Format/Race/Group/Sex/Room/Count+Killed/Stats/Hp+Mana+Move+Practices/Level+Class+Align+Gold+Silver+Exp/AC per type/Hit+Dam+Saves+Size+Position+Wimpy/Damage+Fighting/Thirst+Hunger+Full+Drunk for PCs/Carry number+Weight/Age+Played/Act/Comm/Offense/Immune/Resist/Vulnerable/Form+Parts/Affected by/Master+Leader+Pet/Security/Short+Long desc/Spec fun/Affected. Added 8 ROM-faithful bit-name helpers (`wear_bit_name`, `extra_bit_name`, `imm_bit_name`, `off_bit_name`, `form_bit_name`, `part_bit_name`, `weapon_bit_name`, `cont_bit_name`) and 5 display helpers (`size_name`, `position_name`, `sex_name`, `class_name`, `race_name`) to `mud/handler.py`.
282
+ - `WIZ-008` — Punish commands (`nochannels`, `noemote`, `noshout`, `notell`, `freeze`, `pardon`) now use canonical `CommFlag`/`PlayerFlag` enum values instead of hardcoded wrong bit positions that were corrupting unrelated flags. Added `wiznet()` broadcasts with `WIZ_PENALTIES` + `WIZ_SECURE` flags. Added `\n\r` line endings.
283
+ - `WIZ-009` — `peace` now calls `stop_fighting(person, True)` instead of setting `fighting = None` (properly clearing all combat references). Uses `ActFlag.AGGRESSIVE` enum instead of hardcoded `0x20`. Added `\n\r` line endings.
284
+ - `WIZ-010` — `invis` and `incognito` now broadcast room-wide `act()` messages per ROM `src/act_wiz.c:4329-4420`. `incognito` clears `reply` when setting a specific level. Added `\n\r` line endings.
285
+ - `WIZ-011` — Echo family (`echo`, `recho`, `zecho`, `pecho`) now iterates `descriptor_list` with `CON_PLAYING` filter per ROM `src/act_wiz.c:674-777` instead of `registry.players` dict. `pecho` uses ROM trust check and exact messages. Added `\n\r` line endings.
286
+ - `WIZ-012` — `bamfin`/`bamfout` now use `smash_tilde()` and ROM `strstr` case-sensitive name check per `src/act_wiz.c:455-512`. Added `\n\r` line endings.
287
+ - `WIZ-013` — `wizlock`/`newlock` now use `\n\r` line endings per ROM `src/act_wiz.c:3150-3188`.
288
+ - `WIZ-014` — `holylight` now returns empty string for NPCs (ROM parity) and uses `\n\r` line endings per `src/act_wiz.c:4422-4439`.
289
+ - `WIZ-015` — `slookup` now supports `all` arg, shows `Slot` column, uses prefix-match lookup per ROM `src/act_wiz.c:3191-3229`. Added `\n\r` line endings.
290
+ - `WIZ-016` — `sockets` now uses `\n\r` line endings per ROM `src/act_wiz.c:4140-4176`.
291
+ - `WIZ-017` — `deny` rewritten to ROM parity per `src/act_wiz.c:517-557`: SET-only (not toggle), uses `get_char_world()` not `character_registry`, adds `PlayerFlag.DENY` flag, wiznet broadcast, `stop_fighting(victim, True)`, forced quit, `\n\r` line endings.
292
+ - `WIZ-018` — `switch` now has private-room check (`is_room_owner`/`room_is_private`) and wiznet broadcast per ROM `src/act_wiz.c:2202-2269`. Added `\n\r` line endings.
293
+ - `WIZ-019` — `return` now has full ROM message, prompt cleanup, and wiznet broadcast per `src/act_wiz.c:2273-2303`. Added `\n\r` line endings.
294
+ - `WIZ-020` — `smote` now uses ROM `_smote_substitute` letter-by-letter algorithm, case-sensitive `strstr` name check, skips no-descriptor viewers per `src/act_wiz.c:362-453`. Added `\n\r` line endings.
295
+ - `WIZ-021` — `pecho` now uses ROM trust check (`get_trust(char) != MAX_LEVEL`) and exact messages per `src/act_wiz.c:750-777`. Added `\n\r` line endings.
296
+ - `WIZ-022` — `disconnect` now follows ROM descriptor-list victim lookup per `src/act_wiz.c:561-614`. Added `\n\r` line endings.
297
+ - `WIZ-023` — `guild` now uses `lookup_clan_id`/`CLAN_TABLE` per ROM `src/act_wiz.c:196-249`; distinguishes independent-clan (`"a <name>"`) vs member-clan (`"member of clan <Name>"`) messaging; uses `str_prefix`-style match for "none"; all messages have `\n\r`.
298
+ - `WIZ-024` — `outfit` now always returns `"You have been equipped by Mota.\n\r"` per ROM `src/act_wiz.c:251-310` (removed "You already have your equipment" branch).
299
+ - `WIZ-025` — `copyover` now iterates `descriptor_list` with `CON_PLAYING` filter per ROM `src/act_wiz.c:4498-4588`; all messages have `\n\r`.
300
+ - `WIZ-026` — `qmconfig` verified as already ROM-faithful per `src/act_wiz.c:4685-4787`; added test coverage for `"I have no clue..."` fallback.
301
+ - `wiznet()` broadcast now iterates `descriptor_list` with `CON_PLAYING` filter per ROM `src/act_wiz.c:171-194`; falls back to `character_registry` in test environments without descriptor setup.
302
+ - `WIZ-027` — `load` syntax messages now have `\n\r` line endings per ROM; re-invokes `do_load("")` on invalid type.
303
+ - `WIZ-028` — `mload` now returns `"Ok.\n\r"` instead of `"You have created {name}!"` per ROM `src/act_wiz.c:2489-2517`; added `wiznet()` broadcast; safe `getattr` for registry.
304
+ - `WIZ-029` — `oload` now returns `"Ok.\n\r"` instead of `"You have created {name}!"` per ROM `src/act_wiz.c:2521-2570`; added `wiznet()` broadcast; ROM typo preserved in level message; fixed `char.inventory` slot name.
305
+ - `WIZ-030` — `purge` trust check now uses ROM `<=` comparison per `src/act_wiz.c:2625`; added `"X tried to purge you!\n\r"` notification to victim; all messages have `\n\r`.
306
+ - `WIZ-031` — `restore` iterates `descriptor_list` for `restore all` per ROM `src/act_wiz.c:2820-2845`; added wiznet broadcasts; all messages have `\n\r`.
307
+ - `WIZ-032` — `clone` now has wiznet broadcasts per ROM `src/act_wiz.c:2338-2455`; added trust check for mob cloning; uses `obj.carried_by` to determine placement; all messages have `\n\r`.
308
+ - `WIZ-033` — `set` command now uses `\n\r` line endings and re-invokes `do_set("")` on invalid type per ROM `src/act_wiz.c:3233-3275`.
309
+ - `WIZ-034` — `sset` now uses `getattr(registry, "skill_table", [])` iteration; added `(use the name of the skill, not the number)` hint; all messages have `\n\r` per ROM `src/act_wiz.c:3278-3352`.
310
+ - `WIZ-035` — `mset` now fully ROM-parity per `src/act_wiz.c:3355-3790`: uses `smash_tilde()`; uses `get_max_train()` for stat ranges; `level` rejects PCs; `sex` sets `pcdata.true_sex`; `hp`/`mana`/`move` set PC `perm_*` values; uses ROM field name prefixes (`startswith()`); adds fields: `class`, `race`, `group`, `hours`, `thirst`, `drunk`, `full`, `hunger`; `security` uses `ch->pcdata->security` range; clears `victim.zone`; re-invokes `do_mset("")` on unknown field; all messages have `\n\r`.
311
+ - `WIZ-036` — `oset` now fully ROM-parity per `src/act_wiz.c:3958-4067`: uses `smash_tilde()`; adds `v0`-`v4` aliases; caps `value0` at `min(50, value)` per ROM:3998; adds `timer` field; uses ROM field prefixes; re-invokes `do_oset("")` on unknown field; all messages have `\n\r`.
312
+ - `WIZ-037` — `rset` now fully ROM-parity per `src/act_wiz.c:4071-4136`: uses `smash_tilde()`; uses `find_location()` for room lookup; adds private-room check (`is_room_owner`/`room_is_private`); adds "Value must be numeric.\n\r" check; uses ROM field prefixes; re-invokes `do_rset("")` on unknown field; all messages have `\n\r`.
313
+ - `WIZ-038` — `string` now fully ROM-parity per `src/act_wiz.c:3793-3954`: uses `smash_tilde()`; adds `spec` field via `get_spec_fun()`; `long` appends `\n\r`; uses `set_title()` for title; uses ROM field prefixes; adds ROM `extra_descr` insertion; re-invokes `do_string("")` on bad type; all messages have `\n\r`.
314
+ - `ALIAS-001` — `alia` now returns the ROM `src/alias.c:97-100` typo-guard text instead of a generic helper string.
315
+ - `ALIAS-002` — `alias` now mirrors ROM `src/alias.c:112-220`: exact list/query/set/realias messages, reserved-word checks, quote/name validation, `delete`/`prefix` expansion guards, and the five-alias limit.
316
+ - `ALIAS-003` — alias substitution now mirrors ROM `src/alias.c:69-99`: one expansion pass only, truncation warning handling, and `mud.rom_api.substitute_alias()` now returns the expanded string instead of an internal tuple.
317
+ - `ALIAS-004` — `unalias` now mirrors ROM `src/alias.c:236-274` prompt/removal/failure messages.
318
+ - `ALIAS-005` — prefix preprocessing before alias expansion now mirrors ROM `src/alias.c:49-61,88-95`, including the overlong-line warning and full-`prefix` bypass semantics.
319
+ - `HEALER-001` — `heal` now finds NPC healers via `ACT_IS_HEALER` and shows the ROM `src/healer.c:49-79` service table instead of a compressed summary string.
320
+ - `HEALER-002` — `heal mana` now mirrors ROM `src/healer.c:147-190`: silver-aware affordability, `deduct_cost`, healer payout, TO_ROOM utterance, and `dice(2, 8) + level/3` mana restoration.
321
+ - `HEALER-003` — `heal refresh` now dispatches to the underlying ROM spell path from `src/healer.c:156-160,196` instead of a placeholder full-restore shortcut.
322
+ - `HEALER-004` — `heal heal` now dispatches to the underlying ROM `spell_heal` path from `src/healer.c:107-112,196` instead of always filling hit points to max.
323
+
324
+ ## [2.6.15] - 2026-04-28
325
+
326
+ Closes the `scan.c` audit (P2): all 3 gaps fixed, ROM-faithful TO_ROOM/TO_CHAR
327
+ broadcasts on the `scan` command, divergent header and fallback lines removed.
328
+
329
+ ### Added
330
+
331
+ - `SCAN-001` — `do_scan` with no argument now emits the TO_ROOM broadcast
332
+ `"$n looks all around."` so onlookers see the scan, mirroring ROM
333
+ `src/scan.c:60` (`act("$n looks all around.", ch, NULL, NULL, TO_ROOM);`).
334
+ - `SCAN-002` — directional `do_scan` now emits the TO_CHAR/TO_ROOM act() pair
335
+ `"You peer intently <dir>."` / `"$n peers intently <dir>."`, mirroring ROM
336
+ `src/scan.c:89-90`.
337
+
338
+ ### Fixed
339
+
340
+ - `SCAN-002` — directional `do_scan` no longer prints a spurious
341
+ `"Looking <dir> you see:"` header. ROM builds that string into `buf` at
342
+ `src/scan.c:91` but never calls `send_to_char(buf, ch)`; the only visible
343
+ scanner-facing message is the `"You peer intently <dir>."` act().
344
+ - `SCAN-003` — `do_scan` no longer emits non-ROM fallback lines
345
+ (`"No one is nearby."`, `"Nothing of note."`) when no visible characters
346
+ are found. ROM emits only the act() messages and header in that case
347
+ (`src/scan.c:48-104`).
348
+
349
+ ## [2.6.14] - 2026-04-28
350
+
351
+ Closes the `db2.c` audit (P1): all CRITICAL/IMPORTANT mob-loader gaps fixed.
352
+ Both `.are` and JSON loaders now match ROM `src/db2.c:load_mobiles` for AC
353
+ scaling, `ACT_IS_NPC` enforcement, race-table flag merge, and first-char
354
+ uppercase of long_descr/description. Two MINOR gaps (`DB2-004` kill_table,
355
+ `DB2-005` single-line fread_string) remain deferred — both documented as
356
+ not user-reachable in the current port.
357
+
358
+ ### Fixed
359
+
360
+ - `DB2-003` — both mob loaders now uppercase the first character of
361
+ `long_descr` and `description` at load time, mirroring ROM
362
+ `src/db2.c:236-237` (`pMobIndex->long_descr[0] = UPPER(...)`).
363
+ Previously mob protos with a lowercase first letter rendered that way in
364
+ room/look output. `.are` loader normalizes after `read_string_tilde`;
365
+ JSON loader normalizes inline at MobIndex construction.
366
+ - `DB2-006` — mob armor-class fields (`ac_pierce`/`ac_bash`/`ac_slash`/`ac_exotic`)
367
+ are now multiplied by 10 at load time in both the `.are` loader
368
+ (`mud/loaders/mob_loader.py`) and the JSON loader (`mud/loaders/json_loader.py`),
369
+ mirroring ROM `src/db2.c:273-276`. Previously every loaded NPC had an AC value
370
+ 10× off in ROM's negative-AC convention, making them noticeably easier to hit.
371
+ `mud/scripts/convert_are_to_json.py` now divides back when re-emitting JSON so
372
+ the JSON files stay a faithful mirror of the raw `.are` upstream.
373
+ - `DB2-002` — both mob loaders now merge ROM `race_table[race].{act, aff,
374
+ off, imm, res, vuln, form, parts}` flag bits into each loaded mob's
375
+ letter-based flag fields, mirroring ROM `src/db2.c:239-242,279-286,295-297`.
376
+ Previously race-derived intrinsics (dragon flying, troll regeneration,
377
+ modron immunities, undead form/parts) were silently dropped at load time.
378
+ Implemented in `mud/loaders/mob_loader.py:merge_race_flags`; the JSON
379
+ loader (`mud/loaders/json_loader.py`) invokes it after MobIndex construction.
380
+ - `DB2-001` — both mob loaders now unconditionally OR `ACT_IS_NPC` (letter `A`)
381
+ into every prototype's `act_flags` letter string, mirroring ROM
382
+ `src/db2.c:239`. Previously a mob whose area-file flags omitted the `A`
383
+ letter would spawn with `IS_NPC()` returning false, breaking every
384
+ downstream `is_npc` check (combat, save, look, mobprog dispatch).
385
+
386
+ ## [2.6.13] - 2026-04-28
387
+
388
+ Closes the cross-file dependency that blocked `interp.c` completion:
389
+ `WEAR-010` (do_wear dispatches weapons to wield) and `WEAR-011`
390
+ (do_hold auto-replaces) cleared the way for `INTERP-013` to collapse
391
+ `do_wield`/`do_hold` into aliases on `do_wear`, mirroring ROM
392
+ `cmd_table[]`. `interp.c` now closes at **24/24 fixed + 1
393
+ closed-deferred**.
394
+
395
+ ### Fixed
396
+
397
+ - `act_obj.c:WEAR-010` — `do_wear` now dispatches `ITEM_WEAPON` items
398
+ to the WIELD branch (`_dispatch_wield`) instead of rejecting with
399
+ "You need to wield weapons, not wear them." Mirrors ROM
400
+ `src/act_obj.c:1401-1697` `wear_obj` single-dispatcher design where
401
+ `do_wear`/`do_wield`/`do_hold` are all the same function. Tests:
402
+ `tests/integration/test_equipment_system.py::test_wear_010_do_wear_dispatches_weapon_to_wield`.
403
+ - `act_obj.c:WEAR-011` — `do_hold` now auto-unequips an existing held
404
+ item via `_unequip_to_inventory()` instead of rejecting with
405
+ "You're already holding {name}." Mirrors ROM
406
+ `src/act_obj.c:1670-1677` `remove_obj(WEAR_HOLD, fReplace=TRUE)`
407
+ semantics. Tests:
408
+ `tests/integration/test_equipment_system.py::test_wear_011_do_hold_auto_replaces_existing_held`.
409
+ - `interp.c:INTERP-013` — `wield` and `hold` now dispatch to `do_wear`
410
+ via the dispatcher's `aliases=("wield", "hold")` on the `wear`
411
+ Command, mirroring ROM `cmd_table[]` (src/interp.c:103, 215, 232).
412
+ `do_wield`/`do_hold` collapsed to thin wrappers around `do_wear`
413
+ for direct-import callers. Closes `interp.c` to **24/24 fixed +
414
+ 1 closed-deferred** (100% of closeable gaps). Tests:
415
+ `tests/integration/test_interp_dispatcher.py::test_interp_013_wear_wield_hold_share_do_wear`.
416
+
417
+ ### Changed
418
+
419
+ - `wield <non-weapon>` and `hold <non-holdable>` no longer reject with
420
+ command-specific errors ("You can't wield that." / "You can't hold
421
+ that."). They now run the full `do_wear` dispatcher, so
422
+ e.g. `wield ring` wears the ring on a finger — ROM-faithful since
423
+ ROM has no separate `do_wield`/`do_hold` functions.
424
+ - `wield` and `hold` with no argument now emit
425
+ `"Wear, wield, or hold what?"` instead of `"Wield what?"` /
426
+ `"Hold what?"`, mirroring ROM's single-prompt design.
427
+
428
+ ## [2.6.12] - 2026-04-28
429
+
430
+ Closes the remaining `interp.c` parser/extension gaps:
431
+ `INTERP-015` (port ROM `one_argument` to replace `shlex.split`) and
432
+ `INTERP-016` (verify `tail_chain` is a no-op in stock ROM and close-defer).
433
+ `interp.c` is now 22/24 gaps fixed + 1 closed-deferred + 1 deferred-pending
434
+ (`INTERP-013`, blocked on `ACT_OBJ_C` `do_wear` port).
435
+
436
+ ### Fixed
437
+
438
+ - `interp.c:INTERP-015` — `_split_command_and_args` no longer routes
439
+ through `shlex.split`; the new `_one_argument()` mirrors ROM
440
+ `src/interp.c:766-798` byte-for-byte (lowercases head, single-char
441
+ `'` and `"` quote sentinels with no nesting, backslash treated
442
+ literally, surrounding whitespace stripped). `shlex` import dropped.
443
+ Tests:
444
+ `tests/integration/test_interp_dispatcher.py::test_interp_015_one_argument_matches_rom`
445
+ (8 cases).
446
+
447
+ ### Changed
448
+
449
+ - `interp.c:INTERP-016` — closed-deferred. Confirmed `tail_chain()`
450
+ is `return;` only in stock ROM 2.4b6 (`src/db.c:3929`); empty
451
+ hook used by some ROM derivatives for stack-tail-call extension.
452
+ Stock-ROM behavior is "do nothing", which Python already matches
453
+ by omission.
454
+ - `tests/test_alias_parity.py::test_alias_case_sensitivity` renamed
455
+ to `test_alias_case_insensitive_lookup_matches_rom` and flipped to
456
+ assert ROM-correct behavior — ROM `do_alias` stores keys via
457
+ `one_argument` which lowercases (`src/alias.c:127, 217`), so an
458
+ uppercase input head expands a lowercased alias key. The previous
459
+ Python assertion mirrored pre-port `shlex` behavior, not ROM.
460
+
461
+ ## [2.6.11] - 2026-04-28
462
+
463
+ Closes the three small position/trust gates left in `interp.c`
464
+ (`INTERP-004`/`-005`/`-006`). `interp.c` is now 20/24 gaps closed
465
+ (83%); only `INTERP-013` (deferred until `do_wear` ports the missing
466
+ wield/hold logic), `INTERP-015` (shlex/one_argument port), and
467
+ `INTERP-016` (`tail_chain` documentation, no-op) remain.
468
+
469
+ ### Fixed
470
+
471
+ - `interp.c:INTERP-004` — `shout` now requires trust 3 to match ROM
472
+ (`src/interp.c:200`). Previously had no `min_trust` (defaulted to 0).
473
+ Test: `tests/integration/test_interp_dispatcher.py::test_interp_004_shout_requires_trust_3`.
474
+ - `interp.c:INTERP-005` — `murder` now requires trust 5 to match ROM
475
+ (`src/interp.c:247`). Test:
476
+ `test_interp_005_murder_requires_trust_5`.
477
+ - `interp.c:INTERP-006` — `music` `min_position` lowered from
478
+ `RESTING` to `SLEEPING` to match ROM (`src/interp.c:93`). Test:
479
+ `test_interp_006_music_min_position_sleeping`.
480
+
481
+ ## [2.6.10] - 2026-04-27
482
+
483
+ Closes five more `interp.c` gaps: command-mapping cleanup
484
+ (`INTERP-009/010/011/012/014` — `hit`/`take`/`junk`/`tap`/`go`/`:`
485
+ now route to canonical handlers), `do_commands` column-padding fix
486
+ (`INTERP-024`), and the prefix-order sweep (`INTERP-017`) — Python's
487
+ prefix scan now mirrors ROM `cmd_table[]` declaration order via a
488
+ 250-entry table, so 1- and 2-letter abbreviations resolve identically
489
+ to ROM. `INTERP-013` (collapse `do_wield`/`do_hold` into `do_wear`)
490
+ deferred — Python `do_wear` is missing strength/skill/two-hand checks
491
+ and HOLD auto-unequip that the separate functions currently provide;
492
+ collapsing now would regress behavior. `interp.c` is now 17/24 gaps
493
+ closed (71%).
494
+
495
+ ### Fixed
496
+
497
+ - `interp.c:INTERP-009` — `"hit"` now dispatches to `do_kill` as a
498
+ ROM-style alias on the kill `Command`; deleted redundant `do_hit`
499
+ stub from `player_info.py` (`src/interp.c:88`). Test:
500
+ `tests/integration/test_interp_dispatcher.py::test_interp_009_hit_routes_to_do_kill`.
501
+ - `interp.c:INTERP-010` — `"take"` now dispatches to `do_get` as an
502
+ alias on the get `Command`; deleted `do_take` stub
503
+ (`src/interp.c:226`). Test:
504
+ `tests/integration/test_interp_dispatcher.py::test_interp_010_take_routes_to_do_get`.
505
+ - `interp.c:INTERP-011` — `"junk"` and `"tap"` now dispatch to
506
+ `do_sacrifice` as aliases; deleted both stubs from `remaining_rom.py`
507
+ (`src/interp.c:228-229`). Test:
508
+ `test_interp_011_junk_tap_route_to_do_sacrifice`.
509
+ - `interp.c:INTERP-012` — `"go"` now dispatches to `do_enter` as an
510
+ alias; deleted `do_go` stub (`src/interp.c:263`). Test:
511
+ `test_interp_012_go_routes_to_do_enter`.
512
+ - `interp.c:INTERP-014` — `":"` now dispatches to `do_immtalk` as an
513
+ alias; deleted `do_colon` stub from `typo_guards.py` whose
514
+ `"Say what on the immortal channel?"` placeholder was masking ROM's
515
+ NOWIZ toggle behavior (`src/interp.c:356`). Test:
516
+ `test_interp_014_colon_routes_to_do_immtalk`.
517
+ - `interp.c:INTERP-024` — `do_commands`/`do_wizhelp` no longer strip
518
+ trailing whitespace from rows; ROM emits each name as `%-12s` with
519
+ full column padding preserved (`src/interp.c:815-823`). Test:
520
+ `test_interp_024_do_commands_preserves_12char_column_padding`.
521
+ - `interp.c:INTERP-017` — `resolve_command` now walks a 250-entry
522
+ ROM-faithful `_PREFIX_TABLE` in `src/interp.c` declaration order
523
+ instead of Python's feature-grouped `COMMANDS` list; removed the
524
+ exact-match shortcut so prefix resolution mirrors ROM
525
+ `interpret()` exactly (e.g. `"go"` now resolves to `goto` not
526
+ `enter`, matching ROM's hand-ordered prefix block). Sweep test:
527
+ `tests/integration/test_interp_prefix_order.py::test_interp_017_prefix_winner_matches_rom`
528
+ parses `src/interp.c` at collection time and asserts every
529
+ single-letter prefix plus 20 curated 2-letter prefixes resolve
530
+ identically to ROM (45 cases).
531
+
532
+ ## [2.6.9] - 2026-04-27
533
+
534
+ Closes four `interp.c` dispatcher-level gaps in one session: empty-input
535
+ behavior (`INTERP-007`), ROM punctuation aliases (`INTERP-008`), snoop
536
+ forwarding (`INTERP-002`), and verified the wiznet `WIZ_SECURE` mirror
537
+ that was already in place (`INTERP-003`). `interp.c` is now 11/24 gaps
538
+ closed (46%).
539
+
540
+ ### Fixed
541
+
542
+ - `interp.c:INTERP-007` — empty input now returns silently to match
543
+ ROM `interpret()` (`src/interp.c:401-404`). Previously emitted the
544
+ literal `"What?"`. Test:
545
+ `tests/integration/test_interp_dispatcher.py::test_interp_007_empty_input_returns_silently`.
546
+ - `interp.c:INTERP-008` — added ROM punctuation aliases `.` → `gossip`,
547
+ `,` → `emote`, `/` → `recall` to `COMMAND_INDEX`
548
+ (`src/interp.c:184,186,272`). Test:
549
+ `tests/integration/test_interp_dispatcher.py::test_interp_008_punctuation_aliases_route_to_rom_handlers`.
550
+ - `interp.c:INTERP-002` — `process_command` now forwards the input
551
+ logline to `desc.snoop_by.character.messages` prefixed with `"% "`
552
+ (`src/interp.c:491-496`). Test:
553
+ `tests/integration/test_interp_dispatcher.py::test_interp_002_snoop_forwards_logline_to_snooper`.
554
+ - `interp.c:INTERP-003` — verified `log_admin_command` already mirrors
555
+ logged commands to wiznet `WIZ_SECURE` with ROM-style `$`/`{`
556
+ doubling (`mud/admin_logging/admin.py:107-114`,
557
+ `src/interp.c:468-489`). Audit row description was stale. Test:
558
+ `tests/integration/test_interp_dispatcher.py::test_interp_003_logged_command_mirrors_to_wiznet_secure`.
559
+
560
+ ## [2.6.8] - 2026-04-27
561
+
562
+ Closes the immortal command trust drift (`INTERP-001`). All 43 commands
563
+ that were gated too low now match ROM `cmd_table[]` tier-for-tier. This
564
+ is a security-relevant fix — previously a `LEVEL_IMMORTAL` (52) character
565
+ could invoke commands ROM gates at L1..ML (53..60).
566
+
567
+ ### Fixed
568
+
569
+ - `interp.c:INTERP-001` — raised `min_trust` on 43 immortal commands
570
+ in `mud/commands/dispatcher.py` to match ROM `cmd_table[]` trust
571
+ tiers (`src/interp.c:63-381`, `src/interp.h:34-44`). Affected
572
+ tiers: ML, L1, L2, L3, L4, L5, L6, L7. Security-relevant — closes
573
+ privilege drift where `LEVEL_IMMORTAL` (52) characters could
574
+ invoke commands ROM gates at L1..ML (53..60). Test:
575
+ `tests/integration/test_interp_trust.py::test_interp_001_command_trust_matches_rom` (50 parameters).
576
+
577
+ ## [2.6.7] - 2026-04-27
578
+
579
+ `interp.c` social-cluster audit complete (6/6 social gaps closed). Both
580
+ remaining gaps (prefix lookup + literal "not found" message) shipped
581
+ with integration coverage; socials suite now 31/31. `interp.c` overall
582
+ audit progress: 6/24 gaps closed (25%) — non-social gaps (trust drift,
583
+ dispatcher hooks, command-mapping cleanup) remain open.
584
+
585
+ ### Fixed
586
+
587
+ - `interp.c:INTERP-021` — social command lookup now mirrors ROM
588
+ `str_prefix` semantics so partial names (e.g. `gigg` → `giggle`)
589
+ resolve in load order. Added `mud.models.social.find_social()` and
590
+ routed both the dispatcher fallback (`mud/commands/dispatcher.py`)
591
+ and `perform_social` (`mud/commands/socials.py`) through it. Mirrors
592
+ ROM `src/interp.c:584-592`.
593
+ - `interp.c:INTERP-022` — `perform_social` now emits the literal
594
+ `"They aren't here."` when the targeted victim is absent, matching
595
+ ROM `src/interp.c:637-640`. The fabricated `social.not_found` field
596
+ (which has no counterpart in ROM's social table) is no longer used.
597
+
598
+ ## [2.6.6] - 2026-04-27
599
+
600
+ `interp.c` ROM parity audit started — full audit doc with 24 stable gap
601
+ IDs (`INTERP-001`..`INTERP-024`) created. Closed the entire CRITICAL+
602
+ IMPORTANT social-cluster subset of `check_social` (`src/interp.c:597-685`):
603
+ position gates, NOEMOTE, sleeping snore exception, and the NPC slap/echo
604
+ auto-react via `mud.utils.rng_mm.number_bits(4)`. Socials integration
605
+ suite grew from 13 to 27 tests, all green.
606
+
607
+ ### Fixed
608
+
609
+ - `interp.c:INTERP-018` — `perform_social` now refuses socials from
610
+ characters in `Position.DEAD`, `MORTAL`, `INCAP`, or `STUNNED` and
611
+ emits ROM's exact response messages
612
+ (`"Lie still; you are DEAD."`, `"You are hurt far too bad for that."`,
613
+ `"You are too stunned to do that."`). Mirrors
614
+ `src/interp.c:603-616` (`check_social` position gate).
615
+ - `interp.c:INTERP-019` — sleeping characters now receive
616
+ `"In your dreams, or what?"` for every social except `snore`
617
+ (the canonical Furey exception). Mirrors `src/interp.c:618-626`.
618
+ - `interp.c:INTERP-020` — players punished with the `COMM_NOEMOTE`
619
+ flag now receive `"You are anti-social!"` when attempting any
620
+ social. NPCs are unaffected per ROM's `IS_NPC` short-circuit.
621
+ Mirrors `src/interp.c:597-601`.
622
+
623
+ ### Added
624
+
625
+ - `interp.c:INTERP-023` — NPC auto-reaction to player socials. When
626
+ a non-NPC socials at an awake, non-charmed, non-switched NPC,
627
+ `mud.utils.rng_mm.number_bits(4)` (0..15) decides the response:
628
+ values 0..8 echo the social back at the player with the actor and
629
+ victim swapped; values 9..12 produce a slap
630
+ (`"$n slaps $N." / "You slap $N." / "$n slaps you."`); values 13..15
631
+ fall through silently. Mirrors `src/interp.c:652-685`.
632
+
633
+ ## [2.6.5] - 2026-04-27
634
+
635
+ `mob_prog.c` ROM parity audit complete — all 7 gaps closed (2 CRITICAL,
636
+ 4 IMPORTANT, 1 MINOR). MOBprog predicate evaluation, greet/grall trigger
637
+ exclusivity, $-code expansion, and program-flow state-machine now match
638
+ ROM 2.4b6 behaviour.
639
+
640
+ ### Fixed
641
+
642
+ - MOBPROG-007: `_program_flow` now logs a warning and aborts the program when
643
+ an `if`/`or`/`and` keyword is not in ROM's `fn_keyword[]` table, mirroring
644
+ the `bug()` + `return` paths at `src/mob_prog.c:1049-1056`, `1076-1083`,
645
+ `1103-1109`. Typo'd predicates fail loudly instead of silently evaluating
646
+ to False. Integration coverage at
647
+ `tests/integration/test_mobprog_program_flow.py`. Also corrected the
648
+ `test_simple_quest_accept_workflow` fixture program to use the real ROM
649
+ keyword `carries` (not the previously-silent invalid `has_item`).
650
+ - MOBPROG-006: `_expand_arg` `$R` substitution now replicates the ROM
651
+ long-standing bug at `src/mob_prog.c:798-799` — the visibility gate uses
652
+ `rch` (random victim) but the substituted string is `ch->short_descr`
653
+ (NPC actor) or `ch->name` (PC actor). Per AGENTS.md ROM Parity Rules,
654
+ QuickMUD reproduces the bug. Integration coverage at
655
+ `tests/integration/test_mobprog_predicates.py`.
656
+ - MOBPROG-005: `_program_flow` `else` branch now resets
657
+ `state[level] = IN_BLOCK` mirroring ROM `src/mob_prog.c:1138`. Structural
658
+ state-machine parity only — no observable divergence on valid programs;
659
+ regression coverage added at
660
+ `tests/integration/test_mobprog_program_flow.py`.
661
+ - MOBPROG-004: `_cmd_eval` `clan` / `race` / `class` checks now resolve their
662
+ name keyword via a ROM-style prefix lookup over `CLAN_TABLE`, `RACE_TABLE`,
663
+ and `CLASS_TABLE` (mirroring ROM `clan_lookup` / `race_lookup` /
664
+ `class_lookup`, `src/mob_prog.c:601-609`) instead of comparing the int
665
+ attribute to the literal name string. `if class $n mage`,
666
+ `if race $n dragon`, `if clan $n thieves` now match ROM. Integration
667
+ coverage at `tests/integration/test_mobprog_predicates.py`.
668
+ - MOBPROG-003: `_cmd_eval` `vnum` check now compares against `lval=0` when the
669
+ target is a PC instead of returning False. Mirrors ROM `src/mob_prog.c:631-642`
670
+ — `lval` initialises to 0 and is only overwritten for NPCs, so
671
+ `if vnum $n == 0` is True against PCs and `if vnum $n != 0` is False.
672
+ Integration coverage at `tests/integration/test_mobprog_predicates.py`.
673
+ - MOBPROG-002: `mp_greet_trigger` no longer falls through to GRALL after a
674
+ failed GREET percent roll. Mirrors ROM `src/mob_prog.c:1340-1345` where the
675
+ GREET / GRALL branches are exclusive — a mob that is awake, can see the
676
+ entrant, and has a GREET trigger only attempts GREET; GRALL is reserved for
677
+ the busy/blind path. Integration coverage at
678
+ `tests/integration/test_mobprog_greet_trigger.py`.
679
+ - MOBPROG-001: `_cmd_eval` `objexists` now walks `mud.models.obj.object_registry`
680
+ (mirroring ROM `get_obj_world`, `src/mob_prog.c:399`) instead of only the
681
+ current room and same-room carriers. Mob programs that gate on
682
+ `if objexists <vnum|name>` against globally-placed items now match ROM
683
+ semantics. Integration coverage at
684
+ `tests/integration/test_mobprog_predicates.py`.
685
+
686
+ ## [2.6.4] - 2026-04-27
687
+
688
+ `mob_cmds.c` ROM parity audit complete — all 18 gaps closed (6 CRITICAL,
689
+ 9 IMPORTANT, 3 MINOR). MOBprog script commands (`mob kill`, `assist`,
690
+ `oload`, `flee`, `cast`, `call`, `damage`, `junk`, `purge`, `transfer`)
691
+ now match ROM 2.4b6 behaviour for charm/master defence, position gates,
692
+ target-type dispatch, level bounds, NO_MOB respect, recursion, and
693
+ bug-log emission on script authoring errors.
694
+
695
+ ### Fixed
696
+
697
+ - MOBCMD-017: `do_mptransfer` now mirrors ROM's recursive structure — a
698
+ literal `mob transfer all <loc>` recursively dispatches
699
+ `do_mptransfer(ch, "<pcname> <loc>")` once per PC in the room
700
+ (`src/mob_cmds.c:791-806`) so each victim re-runs the full validation
701
+ pipeline (private-room check, location resolution). Previously the
702
+ Python implementation inlined the iteration with a direct
703
+ `_transfer_character` call. NPCs are skipped exactly as in ROM line
704
+ 799. Integration coverage at `tests/integration/test_mob_cmds_transfer.py`.
705
+ - MOBCMD-018: verified `do_mpflee` already checks `ch.fighting` as the
706
+ first guard, mirroring ROM `src/mob_cmds.c:1266-1267`. The audit row
707
+ was stale and is now closed without a code change.
708
+ - MOBCMD-007: `do_mppurge` no longer accepts the literal `"all"` token
709
+ as a synonym for the no-arg purge-everything form. ROM
710
+ `src/mob_cmds.c:631-665` treats an empty argument as purge-all and has
711
+ no `"all"` keyword — the token falls through to the name-resolution
712
+ branch like any other word. Also added the missing
713
+ `Mppurge - Bad argument` (ROM line 663) and `Mppurge - Purging a PC`
714
+ (ROM line 671) bug logs via the new `_bug()` helper. The previously
715
+ divergent unit test (`test_mppurge_all_cleans_room`) now uses the
716
+ no-arg form. Integration coverage at
717
+ `tests/integration/test_mob_cmds_purge.py`.
718
+ - MOBCMD-013: `do_mpdamage` now emits a ROM-style `bug()` warning via
719
+ Python's `logging` module when the min or max argument is non-numeric,
720
+ mirroring ROM `src/mob_cmds.c:1105-1107` + `1113-1115`. Previously the
721
+ function silently returned, swallowing what is a script-authoring
722
+ error. A new module-local `_bug()` helper in `mud/mob_cmds.py` mirrors
723
+ ROM's `bug("Mp... - <reason> from vnum %d.", vnum)` pattern; expect
724
+ this helper to be reused as further `mob_cmds` gaps are closed.
725
+ Integration coverage at
726
+ `tests/integration/test_mob_cmds_damage.py::TestMpDamageNonNumericArgsBugLog`.
727
+ - MOBCMD-009: `do_mpflee` now respects `ROOM_NO_MOB` on a candidate
728
+ destination when the fleeing character is an NPC, mirroring ROM
729
+ `src/mob_cmds.c:1277-1280`. Previously script-driven NPC flees would
730
+ pour mobs into rooms flagged NO_MOB. Integration coverage at
731
+ `tests/integration/test_mob_cmds_flee.py::TestMpFleeNoMobRoomFlag`.
732
+ - MOBCMD-006: `do_mpoload` now validates the optional level argument
733
+ against ROM's `level < 0 || level > get_trust(ch)` check
734
+ (`src/mob_cmds.c:575-580`) and refuses to spawn the object when out of
735
+ range. Previously the level was accepted unconditionally so a script
736
+ could load objects above the mob's trust ceiling. Integration coverage
737
+ at `tests/integration/test_mob_cmds_oload.py`.
738
+ - MOBCMD-004: `do_mpjunk` (MOBprog `junk` script command) now matches
739
+ ROM's empty-needle behaviour: `mob junk all.` (trailing dot, no
740
+ suffix) discards nothing because ROM `src/mob_cmds.c:436` defers to
741
+ `is_name(&arg[4], ...)` which returns FALSE for an empty string.
742
+ Python had been short-circuiting on `not suffix` and discarding every
743
+ carried object. Bare `mob junk all` still clears inventory as before.
744
+ Integration coverage at `tests/integration/test_mob_cmds_junk.py`.
745
+ - MOBCMD-002: `do_mpassist` now enforces ROM `src/mob_cmds.c:393`'s full
746
+ guard set — `victim == ch`, `ch->fighting != NULL`, and
747
+ `victim->fighting == NULL`. Previously only the third clause was
748
+ checked, so a script mob already in a fight could be redirected onto a
749
+ new target via `mob assist`, and a script mob could nonsensically
750
+ assist itself. Integration coverage at
751
+ `tests/integration/test_mob_cmds_assist.py`.
752
+ - MOBCMD-001: `do_mpkill` now refuses when the script mob is charmed
753
+ (`AffectFlag.CHARM`) and the chosen victim is its master, mirroring ROM
754
+ `src/mob_cmds.c:364-369`. Previously a charmed mob scripted to
755
+ `mob kill <master>` would attack its own charmer. Integration coverage
756
+ at `tests/integration/test_mob_cmds_kill.py::TestMpKillCharmedMasterGuard`.
757
+ - MOBCMD-015 + MOBCMD-016: `do_mpcall` (MOBprog `call` script command) now
758
+ parses the optional obj1/obj2 tokens from `mob call <vnum> <victim>
759
+ <obj1> <obj2>` and resolves them via `_find_obj_here` (the `get_obj_here`
760
+ analog), forwarding both to `mobprog.call_prog`. ROM
761
+ `src/mob_cmds.c:1217-1252` initialises obj1/obj2 to NULL and only sets
762
+ them when the corresponding token resolves through `get_obj_here`; the
763
+ Python implementation had been dropping both args entirely so called
764
+ sub-programs could never receive object context. Integration coverage at
765
+ `tests/integration/test_mob_cmds_call.py`.
766
+ - MOBCMD-011 + MOBCMD-012: `do_mpcast` (MOBprog `cast` script command) now
767
+ resolves the JSON `target` string into a canonical `_TargetType` IntEnum
768
+ mirroring ROM `TAR_*` (`src/magic.h`) and dispatches on the enum, matching
769
+ ROM's switch in `src/mob_cmds.c:1043-1066`. The previously string-keyed
770
+ branches were drift-prone; in particular the `TAR_OBJ_CHAR_DEF/OFF/INV`
771
+ cases now require an object (no character fallback) and `TAR_CHAR_DEFENSIVE`
772
+ defaults to `ch` when the lookup fails, matching ROM lines 1055 + 1060-1065.
773
+ Integration coverage at `tests/integration/test_mob_cmds_cast.py`.
774
+ - MOBCMD-003: `do_mpkill` now gates on `ch.position == Position.FIGHTING`
775
+ (matching ROM `src/mob_cmds.c:361`) instead of the looser
776
+ `ch.fighting is not None` check, and short-circuits self-attacks via the
777
+ missing `victim is ch` guard from the same ROM line. Integration coverage
778
+ at `tests/integration/test_mob_cmds_kill.py`.
779
+ - MOBCMD-008: `do_mpflee` now performs 6 `rng_mm.number_door()` random-door
780
+ attempts before giving up, mirroring ROM `src/mob_cmds.c:1272-1286`.
781
+ Previously the function iterated the exits list in order, so the first
782
+ valid exit always won — wrong distribution for ROM-faithful flee
783
+ behavior. Integration coverage at
784
+ `tests/integration/test_mob_cmds_flee.py::TestMpFleeRandomDoor`.
785
+ - MOBCMD-010: `do_mpflee` (MOBprog `flee` script command) now routes through
786
+ `mud.world.movement.move_character` instead of the silent `_move_to_room`
787
+ helper, mirroring ROM `src/mob_cmds.c:1283`
788
+ (`move_char(ch, door, FALSE)`). Leave/arrive broadcasts, mp_exit/entry
789
+ triggers, and the rest of the canonical movement pipeline now fire on
790
+ script-driven flees. Integration coverage at
791
+ `tests/integration/test_mob_cmds_flee.py`.
792
+ - MOBCMD-005: `do_mpoload` (MOBprog `oload` script command) now accepts the
793
+ optional `level` argument from `mob oload <vnum> [level] [R|W]`, mirroring
794
+ ROM `src/mob_cmds.c:538-614`. When omitted, level defaults to
795
+ `get_trust(ch)`; the spawned object's `level` is set post-spawn to mirror
796
+ ROM `create_object(pObjIndex, level)`. Previously the level token was parsed
797
+ but discarded, so script-loaded objects always took the prototype's raw
798
+ level. Integration coverage at `tests/integration/test_mob_cmds_oload.py`.
799
+ - MOBCMD-014: `do_mpdamage` (MOBprog `damage` script command) now routes
800
+ through `mud.combat.engine.apply_damage` instead of raw-decrementing
801
+ `victim.hit`. Mirrors ROM `src/mob_cmds.c:1132-1145`
802
+ (`damage(victim, victim, amount, TYPE_UNDEFINED, DAM_NONE, FALSE)`) so
803
+ the death pipeline, position updates, fight triggers, and corpse
804
+ handling fire on script-driven damage. Integration coverage at
805
+ `tests/integration/test_mob_cmds_damage.py`.
806
+
807
+ ### Changed
808
+
809
+ - `docs/parity/ACT_OBJ_C_AUDIT.md` and `docs/parity/ROM_C_SUBSYSTEM_AUDIT_TRACKER.md`
810
+ refreshed to reflect that ROM `src/act_obj.c` is at 100% parity. Apr 27, 2026
811
+ formal sweep verified all 12 audited functions
812
+ (`do_get`/`do_put`/`do_drop`/`do_give`/`do_remove`/`do_sacrifice`/`do_quaff`/
813
+ `do_drink`/`do_eat`/`do_fill`/`do_pour`/`do_recite`/`do_brandish`/`do_zap`
814
+ plus `do_wear`/`do_wield`/`do_hold` and `do_steal`) against current Python;
815
+ the recent batch commits (`97c901e` do_drop parity batch, `517542b` close
816
+ get/put/drop/give/wear/sacrifice/recite/brandish/zap/steal gaps) closed all
817
+ outstanding gaps. 193 act_obj-area integration tests green. P1 audited count
818
+ rises from 5/11 (81%) to 6/11 (86%). No code changes — documentation
819
+ reconciliation only.
820
+
821
+ ## [2.6.3] - 2026-04-27
822
+
823
+ ### Added
824
+
825
+ - Three project-local skills under `.claude/skills/` encoding the ROM 2.4b6 →
826
+ Python parity loop: `rom-parity-audit` (file-level 5-phase audit),
827
+ `rom-gap-closer` (single-gap TDD close flow), `rom-session-handoff`
828
+ (end-of-session SESSION_SUMMARY + SESSION_STATUS + CHANGELOG generation).
829
+ - `CLAUDE.md` "Porting workflow" section: decision-tree mapping of when to
830
+ invoke each skill plus dependencies between them.
831
+
832
+ ### Changed
833
+
834
+ - `README.md` Project Status / badges refreshed to current state: version
835
+ `2.6.2`, tests `3508/3521 passing` (99.6%) with 11 skipped and 2 known
836
+ pre-existing failures, integration suite `1000+`, ROM 2.4b parity badge
837
+ scoped to "gameplay 100%" (truer given the long tail of P2/P3 files), and
838
+ active focus called out as `act_obj.c` (~60%).
839
+ - `AGENTS.md` Repo Hygiene §2 now requires that any change to README's
840
+ Project Status / badges / metrics be accompanied in the same commit by a
841
+ refresh of AGENTS.md tracker pointers and `docs/sessions/SESSION_STATUS.md`,
842
+ preventing drift between the three surfaces. Underlying numbers stay
843
+ sourced from `docs/parity/*` trackers.
844
+
845
+ ## [2.6.2] - 2026-04-27
846
+
847
+ ### Fixed
848
+
849
+ - **act_enter portal regressions** uncovered by the act_enter.c audit
850
+ (PR #123):
851
+ - `_stand_charmed_follower` now forwards `do_stand`'s returned string
852
+ into the follower's message stream, so charmed sleepers receive the
853
+ "You wake and stand up." text exactly as ROM `act_move.c:1044`
854
+ sends inside `do_stand`.
855
+ - `_portal_fade_out` now explicitly removes the portal from
856
+ `room.contents` and clears `portal.location`. `game_loop._extract_obj`
857
+ keys off `obj.in_room` but `Object` uses `obj.location`, so portal
858
+ detachment after charge expiry was a silent no-op. Behavior now
859
+ matches ROM `extract_obj(portal)` at `act_enter.c:212`.
860
+ - `test_enter_closed_portal_denied`: corrected expected message to
861
+ `"You can't seem to find a way in."` per ROM `act_enter.c:94`. The
862
+ prior `"The portal is closed."` was the door-blocked message from
863
+ `act_move.c`, not the portal path.
864
+ - `test_move_through_portal_blocked_while_fighting`: corrected to
865
+ assert silent return per ROM `act_enter.c:70-71`
866
+ (`if (ch->fighting != NULL) return;`); removed the non-ROM
867
+ `"No way! You are still fighting!"` string.
868
+ - **`test_giant_strength_refuses_to_stack`** (was
869
+ `test_stat_modifiers_stack_from_same_spell`): test asserted +4 STR after
870
+ recasting giant strength, but ROM `src/magic.c:3022-3030`
871
+ `spell_giant_strength` early-returns with "You are already as strong as
872
+ you can get!" when the target is already affected. The Python
873
+ implementation correctly mirrors ROM; the test was wrong. Rewrote the
874
+ test to assert ROM anti-stack behavior.
875
+ - **`test_scavenger_prefers_valuable_items`**: flaky because the
876
+ Mitchell-Moore RNG state leaks across tests, and the scavenger only acts
877
+ on a 1/64 roll per `mobile_update` tick. Seed `rng_mm.seed_mm` to a
878
+ known value at start of test and bump the iteration cap from 2000 to
879
+ 5000 for deterministic passes.
880
+
881
+ ## [2.6.1] - 2026-04-27
882
+
883
+ ### Added
884
+
885
+ - **act_enter.c parity (100% ROM parity for portal/enter mechanics):**
886
+ Close all 15 ENTER-001..016 gaps documented in
887
+ `docs/parity/ACT_ENTER_C_AUDIT.md`. 25 new integration tests in
888
+ `tests/integration/test_act_enter_gaps.py`.
889
+
890
+ ### Fixed
891
+
892
+ - **ENTER-009 (CRITICAL):** `do_enter` TO_CHAR message ("You enter $p." /
893
+ "...somewhere else...") was being returned as a Python string and
894
+ silently dropped — now delivered to the player.
895
+ - **ENTER-005:** Portal lookup uses `get_obj_list` (visibility,
896
+ numbered syntax `2.portal`, keyword-list semantics) instead of fuzzy
897
+ substring matching.
898
+ - **ENTER-004:** Non-portal objects and closed portals both produce
899
+ `"You can't seem to find a way in."` (was diverging).
900
+ - **ENTER-008/010:** Departure/arrival TO_ROOM messages go through
901
+ `act_format` + `broadcast_room` for correct `$n` invisibility
902
+ resolution.
903
+ - **ENTER-011:** Portal fade-out only broadcasts in the old room when
904
+ caller is in the old room; calls `extract_obj` on charge expiry.
905
+ - **ENTER-013:** `_get_random_room` capped at 100k iterations
906
+ (was potentially returning None; ROM loops indefinitely).
907
+ - **ENTER-006/007/012:** Follower cascade — charmed followers stand
908
+ before following, follower-name interpolation via `act_format`.
909
+ - **ENTER-002/003/014/015/016:** Cosmetic message wording matched to
910
+ ROM and fighting-character silent-skip path.
911
+
912
+ ## [2.6.0] - 2026-04-27
913
+
914
+ ### Added
915
+
916
+ - **act_obj.c parity batch (100% ROM parity for object-manipulation
917
+ commands):** do_get/do_put/do_drop/do_give/do_wear/do_remove/do_sacrifice/
918
+ do_quaff/do_eat/do_drink/do_fill/do_pour/do_envenom/do_recite/do_brandish/
919
+ do_zap/do_steal and shop commands (do_buy/do_sell/do_list/do_value).
920
+ Adds full ROM TO_ROOM/TO_VICT/TO_NOTVICT broadcasts via act_format +
921
+ broadcast_room. ~80 new integration tests under tests/integration/.
922
+ - **act_move.c parity batch:** do_stand/do_rest/do_sit/do_sleep/do_wake
923
+ rewritten with full ROM furniture support (STAND/SIT/REST/SLEEP_AT/ON/IN
924
+ with capacity checks and ch.on tracking). MOVE-001 arrival broadcast,
925
+ MOVE-002 follower-name interpolation, SNEAK-001/HIDE-001 dispatcher
926
+ delegation to canonical handlers. 40 new integration tests in
927
+ tests/integration/test_position_commands.py.
928
+ - **act_comm.c P2 batch:** do_emote NOEMOTE check, do_pmote (~312 lines),
929
+ do_colour, do_split gold+silver simultaneous-split fix, do_pose pose_table
930
+ by class+level. New mud/utils/poses.py.
931
+ - **act_info.c P2 batch:** do_title/do_description/auto-settings family
932
+ (autolist, autoassist, autoexit, autogold, autoloot, autopeek, autosac,
933
+ autosplit, autotitle).
934
+ - LIQUID_TABLE in mud/models/constants.py extended with proof/full/thirst/
935
+ food/ssize fields sourced from ROM src/const.c:886-931.
936
+ - WebSocket stream support (mud/network/websocket_stream.py) for the
937
+ browser frontend; tests in tests/test_websocket_server.py.
938
+
939
+ ### Changed
940
+
941
+ - **AGENTS.md rewritten:** ~700 lines → 275. Removed running session
942
+ narrative, duplicated status reporting, stale "next steps". Added Session
943
+ Notes (docs/sessions/) and Repo Hygiene (CHANGELOG / README / semver in
944
+ pyproject.toml) sections modeled on quickmud-web-client/AGENTS.md.
945
+ - 79 SESSION_SUMMARY_*.md and HANDOFF_*.md files moved from repo root to
946
+ `docs/sessions/`.
947
+
948
+ ### Fixed
949
+
950
+ - `_obj_from_char()` now operates on `char.inventory` (was reading the
951
+ wrong field, so transferred objects were not removed from giver).
952
+ - `count_users()` in mud/handler.py now reads `room.people` (room.characters
953
+ does not exist).
954
+ - String-keyed equipment lookups replaced with `WearLocation` IntEnum keys
955
+ across BRANDISH/ZAP/POUR families.
956
+ - Hardcoded hex flag values replaced with enum members
957
+ (`PlayerFlag.AUTOSPLIT`, `WearFlag.NO_SAC`, `ItemType.STAFF/WAND`, etc).
958
+ - `do_steal` MAX_LEVEL set to 60 (was 51); STEAL-001..014 covering
959
+ one_argument semantics, is_safe, is_clan, sleeping-victim wake, PC→PC
960
+ PlayerFlag.THIEF, multi_hit signature, NODROP/INVENTORY checks,
961
+ can_see_object visibility filter.
962
+ - `do_recite/do_brandish/do_zap` success paths were unrunnable due to
963
+ undefined SkillTarget, bad ItemType references, string-keyed HOLD
964
+ lookup; all 17 RECITE/BRANDISH/ZAP gaps closed.
965
+
966
+ ## [2.5.2] - 2025-12-30
967
+
968
+ ### Added
969
+
970
+ - **Command Integration ROM Parity Tests** (70 new tests):
971
+ - `tests/test_act_comm_rom_parity.py` - 23 tests for communication commands (ROM `act_comm.c`)
972
+ - Channel status display (`do_channels`)
973
+ - Communication flag toggles (`do_deaf`, `do_quiet`, `do_afk`)
974
+ - Channel blocking logic (QUIET, NOCHANNELS flags)
975
+ - Delete command NPC blocking
976
+ - Replay command behaviors
977
+ - `tests/test_act_enter_rom_parity.py` - 22 tests for portal mechanics (ROM `act_enter.c`)
978
+ - Random room selection with flag exclusions (`get_random_room`)
979
+ - Portal entry mechanics (closed, curse, trust checks)
980
+ - Portal charge system and flag handling (RANDOM, BUGGY, GOWITH)
981
+ - Follower cascading through portals
982
+ - `tests/test_act_wiz_rom_parity.py` - 25 tests for wiznet/admin commands (ROM `act_wiz.c`)
983
+ - Wiznet channel toggle and flag management
984
+ - Wiznet broadcast filtering (WIZ_ON, flag filters, min_level)
985
+ - Admin commands (freeze, transfer, goto, trust)
986
+ - Trust level enforcement
987
+
988
+ - **Documentation**:
989
+ - `COMMAND_INTEGRATION_PARITY_REPORT.md` - Comprehensive command integration test completion report
990
+ - Detailed ROM C to Python mapping for all 70 tests
991
+ - Test philosophy and design decisions
992
+ - ROM C source analysis summary
993
+ - Quality metrics and coverage matrix
994
+
995
+ ### Changed
996
+
997
+ - **ROM 2.4b6 Parity Certification Updates**:
998
+ - Updated total ROM parity test count: 735 → 805 tests (+70)
999
+ - Updated total test count: 2507 → 2577 tests (+70)
1000
+ - Added Command Integration Tests section to certification document
1001
+ - Updated ROM C source verification to include `act_comm.c`, `act_enter.c`, `act_wiz.c`
1002
+
1003
+ - **Test Coverage**:
1004
+ - Increased command integration test coverage (communication, portal, wiznet modules)
1005
+ - Total ROM parity tests: 805 (127 P0/P1/P2 + 608 combat/spells/skills + 70 command integration)
1006
+
1007
+ ## [2.5.1] - 2025-12-30
1008
+
1009
+ ### Added
1010
+
1011
+ - **Session Summary Documentation**:
1012
+ - `P0_P1_P2_EXTENDED_TESTING_SESSION_SUMMARY.md` - Verification session summary documenting that all P0/P1/P2 ROM C parity tests were already complete from previous sessions (December 29-30, 2025)
1013
+
1014
+ ### Changed
1015
+
1016
+ - Updated README badges and project status to reflect complete ROM C parity test coverage (735 total ROM parity tests including 127 P0/P1/P2 formula verification tests)
1017
+
1018
+ ## [2.5.0] - 2025-12-29
1019
+
1020
+ ### Added
1021
+
1022
+ - **🎉 ROM 2.4b6 Parity Certification**: Official 100% ROM 2.4b6 behavioral parity certification
1023
+ - Created `ROM_2.4B6_PARITY_CERTIFICATION.md` - Comprehensive official certification document
1024
+ - 10 detailed subsystem parity matrices with ROM C source verification
1025
+ - Complete audit trail with 7 comprehensive audit documents (2000+ lines)
1026
+ - Integration test verification (43/43 passing = 100%)
1027
+ - Unit test coverage breakdown (700+ tests)
1028
+ - Differential testing methodology documented
1029
+ - Production readiness assessment
1030
+ - All 7 certification criteria verified and passing
1031
+
1032
+ - **Combat System Parity Verification** (100% Complete):
1033
+ - `COMBAT_PARITY_AUDIT_2025-12-28.md` - Comprehensive combat system audit
1034
+ - Added combat assist system (`mud/combat/assist.py`) with all ROM mechanics
1035
+ - Added 30+ combat tests (damage types, position multipliers, surrender command)
1036
+ - Verified all 32 ROM C combat functions implemented
1037
+ - Verified all 15 ROM combat commands functional
1038
+ - Position-based damage multipliers (sleeping 2x, resting/sitting 1.5x)
1039
+ - Damage resistance/vulnerability system complete
1040
+ - Special weapon effects (sharpness, vorpal, flaming, frost, vampiric, poison)
1041
+
1042
+ - **World Reset System Parity Verification** (100% Complete):
1043
+ - `WORLD_RESET_PARITY_AUDIT.md` - Comprehensive reset system audit
1044
+ - Verified all 7 ROM reset commands (M, O, P, G, E, D, R)
1045
+ - 49/49 reset tests passing with complete behavioral verification
1046
+ - Door state synchronization (bidirectional + one-way doors)
1047
+ - Exit randomization (Fisher-Yates shuffle)
1048
+ - ROM scheduling formula verified exact
1049
+ - Special cases documented (shop inventory, pet shops, infrared)
1050
+
1051
+ - **OLC Builders System Parity Verification** (100% Complete):
1052
+ - `OLC_PARITY_AUDIT.md` - Comprehensive OLC system audit
1053
+ - Verified all 5 ROM editors (@redit, @aedit, @oedit, @medit, @hedit)
1054
+ - 189/189 OLC tests passing with complete workflow verification
1055
+ - All 5 @asave variants functional
1056
+ - All 5 builder stat commands operational
1057
+ - Builder security system complete (trust levels, vnum ranges)
1058
+
1059
+ - **Security System Parity Verification** (100% Complete):
1060
+ - `SECURITY_PARITY_AUDIT.md` - Comprehensive security system audit
1061
+ - `SECURITY_PARITY_COMPLETION_SUMMARY.md` - Security session summary
1062
+ - Verified all 6 ROM ban flags (BAN_SUFFIX, PREFIX, NEWBIES, ALL, PERMIT, PERMANENT)
1063
+ - All 4 pattern matching modes (exact, prefix*, *suffix, *substring*)
1064
+ - 25/25 ban tests passing
1065
+ - Trust level enforcement verified
1066
+ - ROM file format compatibility verified
1067
+
1068
+ - **Object System Parity Verification** (100% Complete):
1069
+ - `OBJECT_PARITY_COMPLETION_REPORT.md` - Object system completion report
1070
+ - `docs/parity/OBJECT_PARITY_TRACKER.md` - Detailed 11-subsystem breakdown
1071
+ - Verified all 17 ROM object commands functional
1072
+ - 152/152 object tests passing + 277+ total object-related tests
1073
+ - Complete equipment system (11/11 wear mechanics)
1074
+ - Full container system (9/9 mechanics)
1075
+ - Exact encumbrance system (7/7 ROM C functions)
1076
+ - Complete shop economy (11/11 features)
1077
+
1078
+ - **Session Documentation**:
1079
+ - `SESSION_SUMMARY_2025-12-28.md` - Complete session documentation
1080
+ - `SESSION_SUMMARY_2025-12-27.md` - Previous session documentation
1081
+
1082
+ - **Additional Audit Documents**:
1083
+ - `SPELL_AFFECT_PARITY_AUDIT_2025-12-28.md` - Spell affect system verification
1084
+ - `COMBAT_GAP_VERIFICATION_FINAL.md` - Combat gap analysis and closure
1085
+ - `COMBAT_DAMAGE_RESISTANCE_COMPLETION.md` - Damage type system completion
1086
+ - `REMAINING_PARITY_GAPS_2025-12-28.md` - Final gap analysis (none remaining)
1087
+ - `COMMAND_AUDIT_2025-12-27_FINAL.md` - Command parity final verification
1088
+
1089
+ ### Changed
1090
+
1091
+ - **README.md Updates**:
1092
+ - Updated version badge to 2.5.0
1093
+ - Updated ROM parity badge to link to official certification
1094
+ - Added "CERTIFIED" designation to ROM parity claim
1095
+ - Updated test counts to reflect integration test results (43/43 passing)
1096
+ - Added integration tests badge
1097
+ - Reorganized documentation section with certification first
1098
+ - Updated project status section with certification details
1099
+
1100
+ - **Documentation Organization**:
1101
+ - Added official certification as primary documentation
1102
+ - Reorganized docs to highlight certification achievement
1103
+ - Updated all parity references to point to certification
1104
+
1105
+ - **Test Organization**:
1106
+ - Added `tests/test_combat_assist.py` - Combat assist mechanics (14 tests)
1107
+ - Added `tests/test_combat_damage_types.py` - Damage resistance/vulnerability (15 tests)
1108
+ - Added `tests/test_combat_position_damage.py` - Position damage multipliers (10 tests)
1109
+ - Added `tests/test_combat_surrender.py` - Surrender command (5 tests)
1110
+
1111
+ ### Fixed
1112
+
1113
+ - Combat damage vulnerability check now runs after immunity check (ROM parity fix)
1114
+ - Corrected misleading "decapitation" comment on vorpal flag (ROM 2.4b6 has no decapitation)
1115
+ - Updated outdated parity assessments in ROM_PARITY_FEATURE_TRACKER.md
1116
+
1117
+ ### Verified
1118
+
1119
+ - ✅ **100% ROM 2.4b6 command coverage** (255/255 commands implemented)
1120
+ - ✅ **100% integration test pass rate** (43/43 tests passing)
1121
+ - ✅ **96.1% ROM C function coverage** (716/745 functions mapped)
1122
+ - ✅ **All 10 major subsystems** verified with comprehensive audits
1123
+ - ✅ **Production readiness** confirmed for players, builders, admins, developers
1124
+
1125
+ ### Documentation
1126
+
1127
+ - 7 comprehensive audit documents totaling 2000+ lines
1128
+ - Official ROM 2.4b6 parity certification document
1129
+ - Complete ROM C source verification methodology
1130
+ - Differential testing documentation
1131
+ - Production deployment guidelines
1132
+
1133
+ ## [2.4.0] - 2025-12-27
1134
+
1135
+ ### Added
1136
+
1137
+ - **GitHub Release Creator Skill**: Comprehensive Claude Desktop skill for automated release management
1138
+ - Added `.claude/skills/github-release-creator/` with complete release automation tooling
1139
+ - Python script for automated release creation (`create_release.py`)
1140
+ - Shell scripts for release validation and creation
1141
+ - Changelog extraction utilities
1142
+ - Complete documentation with usage examples and workflows
1143
+ - GitHub CLI integration for professional release management
1144
+ - Support for semantic versioning, draft releases, and pre-releases
1145
+
1146
+ ## [2.3.1] - 2025-12-27
1147
+
1148
+ ### Added
1149
+
1150
+ - **Comprehensive Test Planning Documentation**:
1151
+ - Created `docs/validation/MOB_PARITY_TEST_PLAN.md` - Complete testing strategy for ROM 2.4b mob behaviors
1152
+ - 22 spec_fun behaviors (guards, dragons, casters, thieves)
1153
+ - 30+ ACT flag behaviors (aggressive, wimpy, scavenger, sentinel)
1154
+ - Damage modifiers (immunities, resistances, vulnerabilities)
1155
+ - Mob memory and tracking systems
1156
+ - Group assist mechanics
1157
+ - Wandering/movement AI
1158
+ - Created `docs/validation/PLAYER_PARITY_TEST_PLAN.md` - Complete testing strategy for player-specific behaviors
1159
+ - Information display commands (score, worth, whois)
1160
+ - Auto-settings (autoassist, autoloot, autogold, autosac, autosplit)
1161
+ - Conditions system (hunger, thirst, drunk, full)
1162
+ - Player flags and reputation (KILLER, THIEF)
1163
+ - Prompt customization
1164
+ - Title/description management
1165
+ - Trust/security levels
1166
+ - Player visibility states (AFK, wizinvis, incognito)
1167
+ - **Claude Desktop Skill Support**:
1168
+ - Added `SKILL.md` - Comprehensive skill documentation for AI assistants
1169
+ - Added `.claude/skills/skill-creator/` - Anthropic's skill-creator tool
1170
+ - Skill validation scripts
1171
+ - Skill packaging utilities
1172
+ - Best practices documentation
1173
+
1174
+ ### Changed
1175
+
1176
+ - **Test Organization**: Created clear roadmap for implementing 180+ behavioral tests
1177
+ - 6 major mob test areas (P0-P3 priority matrix)
1178
+ - 8 major player test areas (P0-P3 priority matrix)
1179
+ - 4-phase implementation roadmap for each
1180
+ - Complete test templates with ROM C references
1181
+
1182
+ ### Documentation
1183
+
1184
+ - Documented 100+ specific test cases with ROM C source references
1185
+ - Added implementation effort estimates and player impact assessments
1186
+ - Created comprehensive testing guides for future development
1187
+
1188
+ ## [2.3.0] - 2025-12-26
1189
+
1190
+ ### Added
1191
+
1192
+ - **MobProg 100% ROM C Parity Achievement**: All 4 critical trigger hookups complete
1193
+ - `mp_give_trigger` integrated in do_give command
1194
+ - `mp_hprct_trigger` integrated in combat damage system
1195
+ - `mp_death_trigger` integrated in character death handling
1196
+ - `mp_speech_trigger` already integrated (verified)
1197
+ - MobProg movement command validation in area file validator
1198
+ - Comprehensive MobProg testing documentation (5 guides)
1199
+ - Enhanced `validate_mobprogs.py` with movement command validation
1200
+ - Organized validation and parity documentation structure
1201
+
1202
+ ### Changed
1203
+
1204
+ - **Documentation Reorganization**: Created proper folder structure
1205
+ - Moved 10 documentation files to `docs/validation/` and `docs/parity/`
1206
+ - Moved 10 scripts to `scripts/validation/` and `scripts/parity/`
1207
+ - Moved 5 report files to appropriate `reports/` subfolders
1208
+ - Created 6 README files documenting folder contents
1209
+ - Updated all cross-references in documentation to use new paths
1210
+ - Enhanced validation scripts with movement command checks
1211
+
1212
+ ### Fixed
1213
+
1214
+ - Integration test issues with Object creation and trigger signatures
1215
+ - Syntax error in validate_mobprogs.py output formatting
1216
+
1217
+ ## [2.2.1] - Previous Release
1218
+
1219
+ ### Added
1220
+
1221
+ - Complete weapon special attacks system with ROM 2.4 parity (WEAPON_VAMPIRIC, WEAPON_POISON, WEAPON_FLAMING, WEAPON_FROST, WEAPON_SHOCKING)
1222
+
1223
+ ### Changed
1224
+
1225
+ ### Deprecated
1226
+
1227
+ ### Removed
1228
+
1229
+ ### Fixed
1230
+
1231
+ ### Security
1232
+
1233
+ ## [1.3.0] - 2025-09-15
1234
+
1235
+ ### Added
1236
+
1237
+ - Complete fighting state management with ROM 2.4 parity
1238
+ - Character immortality protection following IS_IMMORTAL macro
1239
+ - Level constants (MAX_LEVEL, LEVEL_IMMORTAL) matching ROM source
1240
+
1241
+ ### Changed
1242
+
1243
+ ### Deprecated
1244
+
1245
+ ### Removed
1246
+
1247
+ ### Fixed
1248
+
1249
+ - Character position initialization defaults to STANDING instead of DEAD
1250
+ - Fighting state damage application and position updates
1251
+ - Immortal character survival logic in combat system
1252
+ - Combat defense order to match ROM 2.4 C source (shield_block → parry → dodge)
1253
+
1254
+ ### Security
1255
+
1256
+ ## [1.2.0] - 2025-09-15
1257
+
1258
+ ### Added
1259
+
1260
+ - Complete telnet server with multi-user support
1261
+ - Working shop system with buy/sell/list commands
1262
+ - 132 skill system with handler stubs
1263
+ - JSON-based world loading with 352 resets in Midgaard
1264
+ - Admin commands (teleport, spawn, ban management)
1265
+ - Communication system (say, tell, shout, socials)
1266
+ - OLC building system for room editing
1267
+ - pytest-timeout plugin for proper test timeouts
1268
+
1269
+ ### Changed
1270
+
1271
+ - Achieved 100% test success rate (200/200 tests)
1272
+ - Full test suite completes in ~16 seconds
1273
+ - Modern async/await telnet server architecture
1274
+ - SQLAlchemy ORM with migrations
1275
+ - Comprehensive test coverage across all subsystems
1276
+ - Memory efficient JSON area loading
1277
+ - Optimized command processing pipeline
1278
+ - Robust error handling throughout
1279
+
1280
+ ### Fixed
1281
+
1282
+ - Character position initialization (STANDING vs DEAD)
1283
+ - Hanging telnet tests resolved
1284
+ - Enhanced error handling and null room safety
1285
+ - Character creation now allows immediate command execution
1286
+
1287
+ ## [0.1.1] - 2025-09-14
1288
+
1289
+ ### Added
1290
+
1291
+ - Initial ROM 2.4 Python port foundation
1292
+ - Basic world loading and character system
1293
+ - Core command framework
1294
+ - Database integration with SQLAlchemy
1295
+
1296
+ ### Changed
1297
+
1298
+ - Migrated from legacy C codebase to pure Python
1299
+ - JSON world data format for easier editing
1300
+ - Modern Python packaging structure
1301
+
1302
+ ## [0.1.0] - 2025-09-13
1303
+
1304
+ ### Added
1305
+
1306
+ - Initial project structure
1307
+ - Basic MUD framework
1308
+ - ROM compatibility layer
1309
+ - Core game loop implementation
1310
+
1311
+ [Unreleased]: https://github.com/Nostoi/rom24-quickmud-python/compare/v1.3.0...HEAD
1312
+ [1.3.0]: https://github.com/Nostoi/rom24-quickmud-python/compare/v1.2.0...v1.3.0
1313
+ [1.2.0]: https://github.com/Nostoi/rom24-quickmud-python/compare/v0.1.1...v1.2.0
1314
+ [0.1.1]: https://github.com/Nostoi/rom24-quickmud-python/compare/v0.1.0...v0.1.1
1315
+ [0.1.0]: https://github.com/Nostoi/rom24-quickmud-python/releases/tag/v0.1.0