rom24-quickmud-python 2.1.2__py3-none-any.whl → 2.2.1__py3-none-any.whl

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.
mud/models/character.py CHANGED
@@ -249,21 +249,32 @@ class SpellEffect:
249
249
  class Character:
250
250
  """Python representation of CHAR_DATA"""
251
251
 
252
+ # Core identity (ROM parity fields)
252
253
  name: str | None = None
254
+ id: int = 0 # Unique character ID (ROM: long id)
255
+ version: int = 0 # Character version (ROM: sh_int version)
256
+ valid: bool = True # Validity flag (ROM: bool valid)
253
257
  account_name: str = ""
254
258
  short_descr: str | None = None
255
259
  long_descr: str | None = None
256
260
  description: str | None = None
257
261
  prompt: str | None = None
258
262
  prefix: str | None = None
263
+
264
+ # Class/Race/Clan
259
265
  sex: int = 0
260
266
  ch_class: int = 0
261
267
  race: int = 0
262
268
  clan: int = 0
269
+ group: int = 0 # Group number for area repop (ROM: sh_int group)
270
+
271
+ # Levels and trust
263
272
  level: int = 0
264
273
  trust: int = 0
265
274
  invis_level: int = 0
266
275
  incog_level: int = 0
276
+
277
+ # Stats
267
278
  hit: int = 0
268
279
  max_hit: int = 0
269
280
  mana: int = 0
@@ -273,90 +284,125 @@ class Character:
273
284
  gold: int = 0
274
285
  silver: int = 0
275
286
  exp: int = 0
287
+
288
+ # Flags
276
289
  act: int = 0
277
290
  affected_by: int = 0
291
+
292
+ # Location
278
293
  position: int = Position.STANDING
279
- room: Room | None = None
294
+ room: Room | None = None # ROM: in_room
295
+ was_in_room: Room | None = None # ROM: was_in_room
296
+ zone: object | None = None # ROM: AREA_DATA *zone
297
+
298
+ # Relationships
280
299
  master: Character | None = None
281
300
  leader: Character | None = None
282
301
  pet: "Character | None" = None
302
+ reply: Character | None = None # ROM: reply target for tells
303
+ mprog_target: "Character | None" = None # ROM: mob program target
304
+
305
+ # Skills and training
283
306
  practice: int = 0
284
307
  train: int = 0
285
308
  skills: dict[str, int] = field(default_factory=dict)
309
+
310
+ # Encumbrance
286
311
  carry_weight: int = 0
287
312
  carry_number: int = 0
313
+
314
+ # Combat stats
288
315
  saving_throw: int = 0
289
316
  alignment: int = 0
290
317
  hitroll: int = 0
291
318
  damroll: int = 0
292
319
  wimpy: int = 0
320
+
321
+ # Display/UI
293
322
  lines: int = DEFAULT_PAGE_LINES
294
323
  newbie_help_seen: bool = False
324
+
325
+ # Time tracking
295
326
  played: int = 0
296
327
  logon: int = 0
328
+ timer: int = 0 # ROM: idle timer
329
+
330
+ # Stats (permanent and temporary modifiers)
297
331
  perm_stat: list[int] = field(default_factory=list)
298
332
  mod_stat: list[int] = field(default_factory=list)
333
+
334
+ # Body form and parts
299
335
  form: int = 0
300
336
  parts: int = 0
301
337
  size: int = 0
302
338
  material: str | None = None
303
339
  off_flags: int = 0
340
+
304
341
  # ROM parity: immunity/resistance/vulnerability bitvectors (merc.h)
305
342
  imm_flags: int = 0
306
343
  res_flags: int = 0
307
344
  vuln_flags: int = 0
345
+
346
+ # Damage and attack type
308
347
  damage: list[int] = field(default_factory=lambda: [0, 0, 0])
309
348
  dam_type: int = 0
310
349
  start_pos: int = 0
311
350
  default_pos: int = 0
351
+
352
+ # Mob programs
312
353
  mprog_delay: int = 0
354
+ mob_programs: list[MobProgram] = field(default_factory=list)
355
+ spec_fun: str | None = None # ROM: special function name
356
+
357
+ # Custom fields (Python-specific)
313
358
  hometown_vnum: int = 0
314
359
  pcdata: PCData | None = None
315
- inventory: list[Object] = field(default_factory=list)
316
- equipment: dict[str, Object] = field(default_factory=dict)
360
+ gen_data: object | None = None # ROM: GEN_DATA for character generation
361
+ inventory: list[Object] = field(default_factory=list) # ROM: carrying
362
+ equipment: dict[str, Object] = field(default_factory=dict) # ROM: on (worn items)
317
363
  messages: list[str] = field(default_factory=list)
318
364
  cooldowns: dict[str, int] = field(default_factory=dict)
319
365
  connection: object | None = None
320
- desc: object | None = None
321
- reply: Character | None = None
366
+ desc: object | None = None # ROM: DESCRIPTOR_DATA
322
367
  is_admin: bool = False
323
- # IMC permission level (Notset/None/Mort/Imm/Admin/Imp)
324
- imc_permission: str = "Mort"
368
+
369
+ # Communication and channels
370
+ imc_permission: str = "Mort" # IMC permission level (Notset/None/Mort/Imm/Admin/Imp)
325
371
  muted_channels: set[str] = field(default_factory=set)
326
372
  imc_listen: set[str] = field(default_factory=set)
327
373
  banned_channels: set[str] = field(default_factory=set)
328
- wiznet: int = 0
329
- comm: int = 0
330
- # Per-character admin logging flag mirroring ROM PLR_LOG
331
- log_commands: bool = False
332
- # Wait-state (pulses) applied by actions like movement (ROM WAIT_STATE)
333
- wait: int = 0
334
- # Daze (pulses) — separate action delay used by ROM combat
335
- daze: int = 0
374
+ wiznet: int = 0 # ROM: wiznet flags
375
+ comm: int = 0 # ROM: comm flags
376
+ log_commands: bool = False # Per-character admin logging flag mirroring ROM PLR_LOG
377
+
378
+ # Wait state and delays
379
+ wait: int = 0 # Wait-state (pulses) applied by actions like movement (ROM WAIT_STATE)
380
+ daze: int = 0 # Daze (pulses) — separate action delay used by ROM combat
381
+
336
382
  # Armor class per index [AC_PIERCE, AC_BASH, AC_SLASH, AC_EXOTIC]
337
383
  armor: list[int] = field(default_factory=lambda: [100, 100, 100, 100])
384
+
338
385
  # Per-character command aliases: name -> expansion (pre-dispatch)
339
386
  aliases: dict[str, str] = field(default_factory=dict)
387
+
340
388
  # Optional defense chances (percent) for parity-friendly tests
341
389
  shield_block_chance: int = 0
342
390
  parry_chance: int = 0
343
391
  dodge_chance: int = 0
392
+
344
393
  # Combat skill levels (0-100) for multi-attack mechanics
345
394
  second_attack_skill: int = 0
346
395
  third_attack_skill: int = 0
396
+ enhanced_damage_skill: int = 0 # Enhanced damage skill level (0-100)
397
+
347
398
  # Combat state - currently fighting target
348
399
  fighting: Character | None = None
349
- timer: int = 0
350
- was_in_room: Room | None = None
351
- # Enhanced damage skill level (0-100)
352
- enhanced_damage_skill: int = 0
400
+
353
401
  # Character type flag
354
402
  is_npc: bool = True # Default to NPC, set to False for PCs
355
- # Mob program runtime state mirroring ROM's CHAR_DATA fields
356
- mob_programs: list[MobProgram] = field(default_factory=list)
357
- mprog_target: Character | None = None
358
- # Active spell effects keyed by skill name for parity restores
359
- spell_effects: dict[str, SpellEffect] = field(default_factory=dict)
403
+
404
+ # Spell effects and character generation
405
+ spell_effects: dict[str, SpellEffect] = field(default_factory=dict) # Active spell effects keyed by skill name
360
406
  default_weapon_vnum: int = 0
361
407
  creation_points: int = 0
362
408
  creation_groups: tuple[str, ...] = field(default_factory=tuple)
mud/models/obj.py CHANGED
@@ -59,9 +59,14 @@ obj_index_registry: dict[int, ObjIndex] = {}
59
59
 
60
60
  @dataclass
61
61
  class ObjectData:
62
- """Python representation of OBJ_DATA"""
62
+ """Python representation of OBJ_DATA (ROM src/merc.h struct obj_data)"""
63
63
 
64
+ # Core properties
64
65
  item_type: int
66
+ valid: bool = True # ROM: bool valid (object validity flag)
67
+ enchanted: bool = False # ROM: bool enchanted (magical enhancement flag)
68
+
69
+ # Flags and attributes
65
70
  extra_flags: int = 0
66
71
  wear_flags: int = 0
67
72
  wear_loc: int = 0
@@ -71,21 +76,29 @@ class ObjectData:
71
76
  condition: int = 0
72
77
  timer: int = 0
73
78
  value: list[int] = field(default_factory=lambda: [0] * 5)
79
+
80
+ # Descriptive fields
74
81
  owner: str | None = None
75
82
  name: str | None = None
76
83
  short_descr: str | None = None
77
84
  description: str | None = None
78
85
  material: str | None = None
79
- carried_by: Character | None = None
80
- in_obj: ObjectData | None = None
81
- contains: list[ObjectData] = field(default_factory=list)
82
- extra_descr: list[ExtraDescr] = field(default_factory=list)
83
- affected: list[Affect] = field(default_factory=list)
84
- pIndexData: ObjIndex | None = None
85
- in_room: Room | None = None
86
- enchanted: bool = False
87
- next_content: ObjectData | None = None
88
- next: ObjectData | None = None
86
+
87
+ # Relationships and containment
88
+ carried_by: Character | None = None # ROM: CHAR_DATA *carried_by
89
+ in_obj: ObjectData | None = None # ROM: OBJ_DATA *in_obj (container)
90
+ on: Character | None = None # ROM: OBJ_DATA *on (worn on character - we use wear_loc + carried_by)
91
+ contains: list[ObjectData] = field(default_factory=list) # ROM: OBJ_DATA *contains
92
+ extra_descr: list[ExtraDescr] = field(default_factory=list) # ROM: EXTRA_DESCR_DATA *extra_descr
93
+ affected: list[Affect] = field(default_factory=list) # ROM: AFFECT_DATA *affected
94
+
95
+ # Index and location
96
+ pIndexData: ObjIndex | None = None # ROM: OBJ_INDEX_DATA *pIndexData
97
+ in_room: Room | None = None # ROM: ROOM_INDEX_DATA *in_room
98
+
99
+ # Linked list pointers (Python uses lists but we keep for compatibility)
100
+ next_content: ObjectData | None = None # ROM: OBJ_DATA *next_content
101
+ next: ObjectData | None = None # ROM: OBJ_DATA *next
89
102
 
90
103
  def __repr__(self) -> str:
91
104
  return f"<ObjectData type={self.item_type} name={self.short_descr!r}>"
mud/models/room.py CHANGED
@@ -38,25 +38,40 @@ class Exit:
38
38
 
39
39
  @dataclass
40
40
  class Room:
41
- """Runtime room container built from area files."""
41
+ """Runtime room container built from area files (ROM ROOM_INDEX_DATA)."""
42
42
 
43
+ # Core properties
43
44
  vnum: int
44
45
  name: str | None = None
45
46
  description: str | None = None
46
- owner: str | None = None
47
- area: Area | None = None
48
- room_flags: int = 0
49
- light: int = 0
50
- sector_type: int = 0
51
- heal_rate: int = 100
52
- mana_rate: int = 100
53
- clan: int = 0
54
- exits: list[Exit | None] = field(default_factory=lambda: [None] * len(Direction))
55
- extra_descr: list[ExtraDescr] = field(default_factory=list)
56
- resets: list[ResetJson] = field(default_factory=list)
57
- people: list[Character | MobInstance] = field(default_factory=list)
58
- contents: list[Object] = field(default_factory=list)
59
- next: Room | None = None
47
+ owner: str | None = None # ROM: char *owner
48
+
49
+ # Area and location
50
+ area: Area | None = None # ROM: AREA_DATA *area
51
+
52
+ # Room attributes
53
+ room_flags: int = 0 # ROM: int room_flags
54
+ light: int = 0 # ROM: sh_int light
55
+ sector_type: int = 0 # ROM: sh_int sector_type
56
+ heal_rate: int = 100 # ROM: sh_int heal_rate
57
+ mana_rate: int = 100 # ROM: sh_int mana_rate
58
+ clan: int = 0 # ROM: sh_int clan
59
+
60
+ # Exits and descriptions
61
+ exits: list[Exit | None] = field(default_factory=lambda: [None] * len(Direction)) # ROM: EXIT_DATA *exit[6]
62
+ extra_descr: list[ExtraDescr] = field(default_factory=list) # ROM: EXTRA_DESCR_DATA *extra_descr
63
+
64
+ # Resets (Python uses list; ROM uses linked list)
65
+ resets: list[ResetJson] = field(default_factory=list) # Python: list of resets
66
+ reset_first: object | None = None # ROM: RESET_DATA *reset_first (OLC)
67
+ reset_last: object | None = None # ROM: RESET_DATA *reset_last (OLC)
68
+
69
+ # Contents
70
+ people: list[Character | MobInstance] = field(default_factory=list) # ROM: CHAR_DATA *people
71
+ contents: list[Object] = field(default_factory=list) # ROM: OBJ_DATA *contents
72
+
73
+ # Linked list pointer
74
+ next: Room | None = None # ROM: ROOM_INDEX_DATA *next
60
75
 
61
76
  def __repr__(self) -> str:
62
77
  return f"<Room vnum={self.vnum} name={self.name!r}>"
mud/net/connection.py CHANGED
@@ -1509,11 +1509,15 @@ async def handle_connection_with_stream(
1509
1509
  if selection is None:
1510
1510
  return
1511
1511
 
1512
- char, is_creation = selection
1512
+ char, forced_reconnect = selection
1513
+ reconnecting = bool(was_reconnect or forced_reconnect)
1514
+ is_new_player = not bool(char.level)
1515
+
1513
1516
  if char is None:
1514
1517
  return
1515
1518
 
1516
- if is_creation and not was_reconnect:
1519
+ # Only save if this is truly a new character creation
1520
+ if is_new_player and not reconnecting:
1517
1521
  if account.id:
1518
1522
  char.account_id = account.id
1519
1523
  char.account_name = username
@@ -1537,28 +1541,36 @@ async def handle_connection_with_stream(
1537
1541
  ansi_enabled=conn.ansi_enabled,
1538
1542
  )
1539
1543
  SESSIONS[char.name] = session
1544
+
1545
+ # Give starting outfit if new player
1546
+ outfit_message: str | None = None
1547
+ if is_new_player and give_school_outfit(char):
1548
+ outfit_message = "You have been equipped by Mota."
1540
1549
 
1541
1550
  print(f"[{connection_type}] {char.name} entered the game")
1542
1551
 
1543
1552
  # Send welcome messages
1544
1553
  try:
1545
- if is_creation:
1546
- # New character - send MOTD and newbie help
1547
- await send_to_char(char, "Character created successfully!")
1554
+ if outfit_message:
1555
+ await send_to_char(char, outfit_message)
1556
+ if not reconnecting:
1557
+ await _send_login_motd(char)
1548
1558
  if _should_send_newbie_help(char):
1549
1559
  await _send_newbie_help(char)
1550
- elif was_reconnect:
1560
+ except Exception as exc:
1561
+ print(f"[ERROR] Failed to send MOTD for {session.name}: {exc}")
1562
+
1563
+ try:
1564
+ if reconnecting:
1551
1565
  await send_to_char(char, RECONNECT_MESSAGE)
1552
-
1553
- # Announce login
1554
- note_reminder = _announce_login_or_reconnect(char, host_for_ban, was_reconnect)
1555
- if was_reconnect and note_reminder:
1566
+ note_reminder = _announce_login_or_reconnect(char, host_for_ban, reconnecting)
1567
+ if reconnecting and note_reminder:
1556
1568
  await send_to_char(
1557
1569
  char,
1558
1570
  "You have a note in progress. Type NWRITE to continue it.",
1559
1571
  )
1560
1572
  except Exception as exc:
1561
- print(f"[ERROR] Failed to send welcome messages for {session.name}: {exc}")
1573
+ print(f"[ERROR] Failed to announce wiznet login for {session.name}: {exc}")
1562
1574
 
1563
1575
  # Send initial room look
1564
1576
  try:
@@ -1574,35 +1586,28 @@ async def handle_connection_with_stream(
1574
1586
  # Main game loop
1575
1587
  while True:
1576
1588
  try:
1577
- await asyncio.sleep(0.1)
1578
- if not char or not char.room:
1589
+ await conn.send_prompt("> ", go_ahead=session.go_ahead_enabled)
1590
+ command = await _read_player_command(conn, session)
1591
+ if command is None:
1579
1592
  break
1593
+ _stop_idling(char)
1594
+ if not command.strip():
1595
+ continue
1580
1596
 
1581
- if session.command_queue:
1582
- try:
1583
- cmd = session.command_queue.pop(0)
1584
- result = await interpret_command(char, cmd)
1585
- if result and len(result) < 6000:
1586
- await send_to_char(char, result)
1587
- elif result:
1588
- await send_to_char(
1589
- char,
1590
- "Sorry, there was an error processing that command.",
1591
- )
1592
- except Exception as exc:
1593
- print(f"[ERROR] Command execution error: {exc}")
1594
- await send_to_char(
1595
- char,
1596
- "Sorry, there was an error processing that command.",
1597
- )
1598
-
1599
- while char and char.messages:
1600
- try:
1601
- msg = char.messages.pop(0)
1602
- await send_to_char(char, msg)
1603
- except Exception as exc:
1604
- print(f"[ERROR] Failed to send message: {exc}")
1597
+ try:
1598
+ response = process_command(char, command)
1599
+ await send_to_char(char, response)
1600
+
1601
+ # Check if player requested quit
1602
+ if getattr(char, "_quit_requested", False):
1605
1603
  break
1604
+
1605
+ except Exception as exc:
1606
+ print(f"[ERROR] Command processing failed for '{command}': {exc}")
1607
+ await send_to_char(
1608
+ char,
1609
+ "Sorry, there was an error processing that command.",
1610
+ )
1606
1611
 
1607
1612
  except asyncio.CancelledError:
1608
1613
  break
mud/spawning/templates.py CHANGED
@@ -285,6 +285,7 @@ class MobInstance:
285
285
  is_admin: bool = False
286
286
  is_npc: bool = True
287
287
  messages: list[str] = field(default_factory=list)
288
+ fighting: "Character | MobInstance | None" = None # Combat target
288
289
 
289
290
  @classmethod
290
291
  def from_prototype(cls, proto: MobIndex) -> MobInstance:
mud/world/look.py CHANGED
@@ -72,7 +72,8 @@ def look(char: Character, args: str = "") -> str:
72
72
 
73
73
  # Check extra descriptions in room
74
74
  for ed in getattr(room, "extra_descr", []):
75
- if ed.keyword and args.lower() in ed.keyword.lower().split():
75
+ keyword = getattr(ed, "keyword", None)
76
+ if keyword and args.lower() in keyword.lower().split():
76
77
  return ed.description or "You see nothing special."
77
78
 
78
79
  return "You do not see that here."
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: rom24-quickmud-python
3
- Version: 2.1.2
3
+ Version: 2.2.1
4
4
  Summary: A modern Python port of the ROM 2.4b6 MUD engine with full telnet server and JSON world loading
5
5
  Author-email: Mark Jedrzejczyk <mark.jedrzejczyk@gmail.com>
6
6
  Maintainer-email: Mark Jedrzejczyk <mark.jedrzejczyk@gmail.com>
@@ -158,7 +158,7 @@ python -m mud # Start development server
158
158
 
159
159
  ## 🎯 Project Status
160
160
 
161
- - **Version**: 2.1.2 (Production Ready)
161
+ - **Version**: 2.2.1 (Production Ready)
162
162
  - **ROM 2.4b Parity**: 100% (227/227 behavioral tests passing)
163
163
  - **ROM C Function Coverage**: 96.1% (716/745 functions mapped)
164
164
  - **Test Coverage**: 1435/1436 tests passing (99.93% success rate)
@@ -131,7 +131,7 @@ mud/models/area.py,sha256=RDn6e2N9AhoMW4d68-o8i1p1tNhuszaWjbOIkGTlW9I,835
131
131
  mud/models/area_json.py,sha256=GUCWUgFf2s6DUWzcLLYhoxTP38P5cu1vrSD1W3i7D2c,731
132
132
  mud/models/board.py,sha256=iO25xwmUjUCJLYY5nAJdrIweW0oryuSGffm58zy9wJ8,5169
133
133
  mud/models/board_json.py,sha256=XG8t7lLW7b_V3IjzbGF-o6Ym36CTgKiOiBVZb-M0BpA,472
134
- mud/models/character.py,sha256=x6zfV-Q42e8-ddW2LFJaaklptdrL5Dr4iE76q60TuaI,35602
134
+ mud/models/character.py,sha256=oHHoULEANetPc4P65eEVl_Mo6LyqIIetuP5K6IovhiE,36799
135
135
  mud/models/character_json.py,sha256=7rdI92S-JT38xb2iUyXTAJpLmFOIRy2pb6v1Yen8VQY,1046
136
136
  mud/models/clans.py,sha256=0rAzhRdB_1k-GJpQXhANE-Vn1fEnY6oIuqDkq8kvD4c,2066
137
137
  mud/models/classes.py,sha256=Fv0KjS339EBWqz5OBZu5TYSIDSRYpoalLTBJOf-6ThI,2602
@@ -143,12 +143,12 @@ mud/models/json_io.py,sha256=q_gWOXgmSCS0B-w8xbbfs2DFh0uqpQgywzIJzLPpo_o,2146
143
143
  mud/models/mob.py,sha256=_3Ao7vzpY41OA3S8KGNjYWob-wmDHqfsqw7oSHi8o1Y,3124
144
144
  mud/models/note.py,sha256=stKuDsBJ5UQHngPVRbgDH4me_6RtUgjRczC2X3jbhgI,653
145
145
  mud/models/note_json.py,sha256=BuYWIGyZFevoObHGknfMOxjpL0laP7G070wNPZLccXU,320
146
- mud/models/obj.py,sha256=Iug3JeEOf8Iu0YGYzbDiTTyb7xMGVlk3TdB3Pfbe2vs,2511
146
+ mud/models/obj.py,sha256=Omj2-xvY4T3-KeaZP_cUw1ZD8P0eGmIHzXyG2BMyPm0,3284
147
147
  mud/models/object.py,sha256=qm9k3__b1H6lFa5t7zYUVPfTNBuzKK5OYSzyYZfglmQ,1869
148
148
  mud/models/object_json.py,sha256=v1_FnQnvkGBM1lnXPWQARfDQrs20C5mZDhCaLYgNiZs,960
149
149
  mud/models/player_json.py,sha256=YQerAs3vxyAo7wr3orCXCC-pM_QWiwbz3aQ9RMzWW-Q,1249
150
150
  mud/models/races.py,sha256=lZB3xb4b_j4eSU7p-swaKWU-YKf8XqfYhncYBIxWNc8,16568
151
- mud/models/room.py,sha256=LEqns9FWBM_wkoS5ypTvyWHA-zWjdOaXBIbkjxRSovQ,3240
151
+ mud/models/room.py,sha256=Zq3H6U33NhrmMhQxAVVoHbM9SL8A7tR9Z7JL4JqxRQQ,3993
152
152
  mud/models/room_json.py,sha256=IC5795rGTBUpphhJMeDFxUQknis3ALz-C2dAWlEgbPM,1138
153
153
  mud/models/shop.py,sha256=XkRbxLMgbThm0q0tcWjpQrSyX8ZHnoPYh3OTyZi27tQ,455
154
154
  mud/models/shop_json.py,sha256=HkjWn3NHXJ1B8bI7XPobFh0NA7tQZqJOD0UnV9lZXg0,391
@@ -159,7 +159,7 @@ mud/models/social_json.py,sha256=_dir6JDEMN3m4qERdbX4xveoga-YdRic7tLhpiHCfK4,447
159
159
  mud/music/__init__.py,sha256=QKXSuF6XcqoR22e9qAKjK8cYL2H0MveikdlF1cwA0_A,4435
160
160
  mud/net/__init__.py,sha256=LHCpGaVl9a5SqH396-1yngVEyNZSxWmaT62d-Ry5sms,178
161
161
  mud/net/ansi.py,sha256=ron4xslwKoAM2Y1tkfYHTL8tXiXkHyVv5cDEfyyrFaw,1128
162
- mud/net/connection.py,sha256=NOjOxTeNZ48L9o-6wmnRRF4FEfj3wEnKJePRdG7uMHI,66203
162
+ mud/net/connection.py,sha256=mqI_BwQPHV9ot91gTtxw2MoX3r6JOGXO4zmLozlDAWU,66330
163
163
  mud/net/protocol.py,sha256=ImgMHwTcxYD2xgQ5SNOsGhiu7FwtB-pfms1KE4hCeXY,2760
164
164
  mud/net/session.py,sha256=U09R5agaguFqJNn6IoUbVNYvW2BhumHA1Q5xhgTaIr0,4779
165
165
  mud/net/ssh_server.py,sha256=sg5G3npy5lG96SgyHzE6Yl1I-Xgya05-LDAKmut0lmo,10629
@@ -188,21 +188,21 @@ mud/spawning/__init__.py,sha256=AbpHGcgLb-kRsJGnwFEktk7uzpZOCcBY74-YBdrKVGs,1
188
188
  mud/spawning/mob_spawner.py,sha256=CZSvWn1aV3AQbxcS2QFqG0OzL2qXrLUNUKvoQnDQR9o,292
189
189
  mud/spawning/obj_spawner.py,sha256=etEqWOvZsteajNO3HCzmJO7GulhxO4k_4ID9PUhZTsM,2708
190
190
  mud/spawning/reset_handler.py,sha256=pi3A7WMghn1uYTIC75Ygm7nu_JM2IaPdlX16fdRJ4rw,32493
191
- mud/spawning/templates.py,sha256=w2uDim3ElzlUx1lWhaeUQXyaE5Bb0zvGnCzxq4FSjyI,15039
191
+ mud/spawning/templates.py,sha256=oyFsjjGW-cuEhMs9H1amoSqsWjlsnT7QpbOvlx1PDWs,15110
192
192
  mud/utils/act.py,sha256=3GJVlnztkt4d2sMkxgL9uKGLerok8chTf_hM_N8mcaI,4224
193
193
  mud/utils/rng_mm.py,sha256=7kCeV9Q6mqvTDaiIwrcEaSarlmFtNjJTYuLYUWYBs5U,3591
194
194
  mud/utils/text.py,sha256=kq3wP8am5jG-F0CPpNJukVPDEWJ_e5BOMofE-nBLmos,3191
195
195
  mud/world/__init__.py,sha256=HDEHtULHu1OWjOa3xglmhquW8L6NkJTWzLEURJ4BQjk,263
196
196
  mud/world/char_find.py,sha256=9k4q1ucT1O_YvN1WUMKh-ePfA1eSEwR2JP0fAyg1P4Q,3523
197
197
  mud/world/linking.py,sha256=mxEvgqA9Y6sDGXxN46aauU-jBhx4dOUcbgq64fIVz8g,1169
198
- mud/world/look.py,sha256=vWGSs7Xz5PuOzB431msXtlOqQGc4aOYe9z6rT5YFFjI,9590
198
+ mud/world/look.py,sha256=n9ecKP3y9lEZuzKn2GHsXyd-azfD_vbfeHHCGdEKZls,9631
199
199
  mud/world/movement.py,sha256=Y7it7pXrPORgKyy2tRB8br_kb4-s9UK-gj0N-E2U9oM,18695
200
200
  mud/world/obj_find.py,sha256=7QjVAhA-XEqAEm0CoanNtBuYj6rKijNSu8Vu1JcueMY,4304
201
201
  mud/world/vision.py,sha256=q8VjzSzm0cbNrHX6-o0j1UG-jlcM3Z9bzUxK6T-Bsi8,9862
202
202
  mud/world/world_state.py,sha256=W9ABMADlY5H-ZmywACsryFKZp34OufjzMRD6WT331qg,7917
203
- rom24_quickmud_python-2.1.2.dist-info/licenses/LICENSE,sha256=anQ2j9As6sIC8tZgQCXbo0-09JDH9vPiqhA9djnOvkY,1078
204
- rom24_quickmud_python-2.1.2.dist-info/METADATA,sha256=x77JLRHe2XTnZUMQ8KYtTXCzWYR_ckeUFswZ3QBKDHw,11714
205
- rom24_quickmud_python-2.1.2.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
206
- rom24_quickmud_python-2.1.2.dist-info/entry_points.txt,sha256=VFru08UQTXZA_CkK-NBjJmWHyEX5a3864fQHjhaojbw,41
207
- rom24_quickmud_python-2.1.2.dist-info/top_level.txt,sha256=Fk1WPmabIIjp7_iZXLYpbAVqiq7lG7TeAHt30AsOKtQ,4
208
- rom24_quickmud_python-2.1.2.dist-info/RECORD,,
203
+ rom24_quickmud_python-2.2.1.dist-info/licenses/LICENSE,sha256=anQ2j9As6sIC8tZgQCXbo0-09JDH9vPiqhA9djnOvkY,1078
204
+ rom24_quickmud_python-2.2.1.dist-info/METADATA,sha256=LWqWeukreJ_6nfCInB2DwK9h-I7h-OMOSF2H5jxii3U,11714
205
+ rom24_quickmud_python-2.2.1.dist-info/WHEEL,sha256=_zCd3N1l69ArxyTb8rzEoP9TpbYXkqRFSNOD5OuxnTs,91
206
+ rom24_quickmud_python-2.2.1.dist-info/entry_points.txt,sha256=VFru08UQTXZA_CkK-NBjJmWHyEX5a3864fQHjhaojbw,41
207
+ rom24_quickmud_python-2.2.1.dist-info/top_level.txt,sha256=Fk1WPmabIIjp7_iZXLYpbAVqiq7lG7TeAHt30AsOKtQ,4
208
+ rom24_quickmud_python-2.2.1.dist-info/RECORD,,