[Home] [Downloads] [Search] [Help/forum]

Gammon Software Solutions forum

See www.mushclient.com/spam for dealing with forum spam. Please read the MUSHclient FAQ!

[Folder]  Entire forum
-> [Folder]  SMAUG
. -> [Folder]  Lua
. . -> [Subject]  How to script area resets using Lua
Home  |  Users  |  Search  |  FAQ
Username:
Register forum user name
Password:
Forgotten password?

How to script area resets using Lua

[Reply to this subject]  Reply to this subject   [New subject]  Start a new subject   [Refresh] Refresh page


Pages: 1 2  

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Sun 15 Jul 2007 04:14 AM (UTC)  quote  ]

Amended on Sun 15 Jul 2007 06:45 AM (UTC) by Nick Gammon

Message
After playing with a Lua interface to SMAUG, I have developed a "scripted" reset system.

This is intended to gradually change the way resets are handled, from "reset" entries in the area file, to doing scripted resets.

The current system is rather inflexible, every x minutes certain rooms will get certain mobs, with certain equipment. There is no provision for randomness. Thus it is all rather predictable.

The scripted resets are implemented by:


  • Having a single Lua script state for the entire MUD (this is new, compared to my earlier posts, where there was one script state per player).

  • Modifying reset_area to first see if the Lua script will handle resetting a particular area, and if so, let it do it, and ignore the resets in the area file. This minor change looks like this:

    
    void reset_area( AREA_DATA * area )
    {
       ROOM_INDEX_DATA *room;
    
       if( !area->first_room )
          return;
    
       
       /* see if Lua script will handle it */
       if (call_mud_lua ("reset_area", area->filename))
         return;
       
          
       for( room = area->first_room; room; room = room->next_aroom )
          reset_room( room );
    }
    


    As each area is handled on a case-by-case basis, you can gradually add in scripted resets, an area at a time.





Advantages of scripted resets

Scripting resets adds heaps of flexibility. Here are some ideas:


  • Randomize the rooms mobs appear in

    Rather than always having a mob appear in the same room, you could make the reset choose a room from a list (eg. neighbouring rooms). This way players can't predict exactly where everything will be after a reset.

  • Randomize mob types

    You could choose to repop a mob from a list (eg. a warrior one time, a mage the next), so that the areas look more natural.

  • Randomize mob numbers

    Instead of always repopping (say) 2 mobs in a room, you might vary from 1 to 3, so that the exact contents of a room are less predictable.

  • Make loot tables

    There are times when you need to generate lots of mobs with similar loot (for example, the cage mobs in the Darkhaven Academy). Rather than tediously listing the same thing for every mob, they can share a common loot table.

  • Randomize loot

    Instead of always having exactly the same loot on each mob, you could choose loot from lists of things of roughly similar value (eg. one time the mob has a sword, the next time, a mace).

  • Randomly have better items

    You might make it so that 10% of the time, a mob has an extra item worth more, or more useful (eg. some extra food, or drink, or a potion).

  • Randomly have much better items

    You might make it so that 1% of the time, a mob has an extra item worth much more, such as a nice sword. This element of surprise would make killing mobs more fun.

  • Randomly have rare items

    You might make it so that 0.1% of the time, a mob has an extra item worth a great deal. The chance of getting this might be low, but the lucky player that finds it can sell it or use it to his advantage.

  • Randomly make objects, like chests

    You might arrange that every 10 resets or so, a chest is spawned that has a nice item in it.

  • Randomly spawn rare mobs

    Every few hours you might spawn an unusual (rare) mob. This might benefit the player in some way, eg.


    • Have better loot if you kill it
    • Offer an unusual quest (task)
    • Be a shopkeeper selling rare things


    The reset code could then despawn it 15 minutes later.

  • Clean up rubbish

    As well as adding stuff, the resets might notice that a room has 20 junk swords in it, and remove most or all of them, preferably if no player is in the room to notice their sudden disappearance.

  • Generate messages

    The reset code could occassionally broadcast a message to a room or the area. This message might just be local flavour, or notify players that a rare item or mob has been spawned.



As an example of the sort of thing you can do with scripted resets, I have converted the Darkhaven Academy resets into a script. The entire reset script looks like this:



function reset_new_academy ()

  -- put the fountains in
  multiple_objects (10401,  -- fountain
    { 10300, 10305, 10319, 10325, 10326, 10327, 10328, 
      10329, 10330, 10364, 10366, 10374, 10382, 10386, 
      10401, 
     } )
     
  -- close various exits
  
  mud.set_exit_state (10300, "s", "c")  -- close door -- Darkhaven Academy
  mud.set_exit_state (10309, "n", "c")  -- close door -- Wandering Darkhaven Academy
  mud.set_exit_state (10310, "s", "c")  -- close door -- An Enclosed Room
  mud.set_exit_state (10312, "w", "c")  -- close door -- Lost in Darkhaven Academy 
  mud.set_exit_state (10313, "e", "c")  -- close door -- A Secret Alcove 
  mud.set_exit_state (10361, "u", "c")  -- close door -- A Final Test 
  mud.set_exit_state (10362, "d", "c")  -- close door -- In the middle of the eastern wall
  mud.set_exit_state (10382, "n", "c")  -- close door -- North-West Corner
  mud.set_exit_state (10386, "d", "c")  -- close door -- South-West Corner
  mud.set_exit_state (10392, "u", "c")  -- close door -- In a Humid Cavern


  -- main helper mobs

  minv (10399, 10300)  -- Tsythia Mistress Headmistress 
  minv (10340, 10303)  -- Domick Dom teacher 
  minv (10333, 10305)  -- healer spectre cage 
  minv (10394, 10306)  -- Abbigayle language teacher
  minv (10342, 10319)  -- Toric lord healer
  minv (10346, 10355)  -- Silvina receptionist woman
  minv (10343, 10357, 1, 1, -- Zurg sage storekeeper 
          {},   -- nothing equipped
          -- shop inventory
          { 10316, -- torch
            10317, -- dried rabbit meat
            10314, -- dragonskin skin water 
          } 
          ) 

  -- initial mob we are sent to kill
  minv (10345, 10308, 1, 1, { neck1 = 10345 } )  -- chadoyn cage, equip: Chadoyn bindings 
          
  -- assorted statues for each class
  
  minv (10352, 10318)  -- statue warrior cage
  minv (10354, 10320)  -- statue druid cage
  minv (10353, 10321)  -- statue vampire cage
  minv (10351, 10322)  -- statue thief cage 
  minv (10349, 10323)  -- statue mage cage 
  minv (10350, 10324)  -- statue cleric cage
  minv (10355, 10391)  -- statue ranger cage 
  minv (10400, 10400)  -- statue Augurer cage  
  
  -- healers for each class
  
  minv (10334, 10325)  -- healer spectre cage --> Chamber of Trials for Warriors Room
  minv (10335, 10326)  -- healer spectre cage --> Chamber of Trials for Druids Room
  minv (10336, 10327)  -- healer spectre cage --> Chamber of Trials for Vampires Room
  minv (10337, 10328)  -- healer spectre cage --> Chamber of Trials for Thieves Room
  minv (10338, 10329)  -- healer spectre cage --> Chamber of Trials for Mages Room
  minv (10339, 10330)  -- healer spectre cage --> Chamber of Trials for Clerics Room
  minv (10333, 10305)  -- healer spectre cage --> Chamber of Trials for Rangers
  minv (10401, 10401)  -- healer spectre cage --> Chamber of Trials for Augurers Room
  
  -- standard cage mob equipment
  
  local west_equip  = { neck1 = 10306,  -- collar metal academy
                        hands = 10319 } -- gloves kid academy
                        
  local north_equip = { waist = 10302,  -- belt leather academy
                        legs = 10303 }  -- leggings mail academy 
                        
  local south_equip = { head = 10304,   --  helmet iron academy 
                        about = 10305 } -- cape brocade academy
                        
  local east_equip  = { wrist1 = 10300, -- bracelet charm academy 
                        feet = 10301 }  -- combat boots academy
  
  -- Clerics cage mobs (2 per room)
  minv (10326, 10331, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10305, 10332, 2, 2, north_equip)  -- naga cage     (north)
  minv (10312, 10333, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10319, 10334, 2, 2, east_equip)   -- kobold cage   (east)
  
  -- Mages cage mobs (2 per room)
  minv (10327, 10337, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10306, 10335, 2, 2, north_equip)  -- naga cage     (north)
  minv (10313, 10336, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10320, 10338, 2, 2, east_equip)   -- kobold cage   (east)

  -- Warriors cage mobs (2 per room)
  minv (10328, 10341, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10307, 10339, 2, 2, north_equip)  -- naga cage     (north)
  minv (10314, 10340, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10321, 10342, 2, 2, east_equip)   -- kobold cage   (east)

  -- Druids cage mobs (2 per room)
  minv (10329, 10345, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10308, 10343, 2, 2, north_equip)  -- naga cage     (north)
  minv (10315, 10344, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10322, 10346, 2, 2, east_equip)   -- kobold cage   (east)

  -- Vampires cage mobs (2 per room)
  minv (10330, 10349, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10309, 10347, 2, 2, north_equip)  -- naga cage     (north)
  minv (10316, 10348, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10323, 10350, 2, 2, east_equip)   -- kobold cage   (east)

  -- Thieves cage mobs (2 per room)
  minv (10331, 10353, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10310, 10351, 2, 2, north_equip)  -- naga cage     (north)
  minv (10317, 10352, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10324, 10354, 2, 2, east_equip)   -- kobold cage   (east)

 -- Rangers cage mobs (2 per room)
  minv (10332, 10390, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10311, 10389, 2, 2, north_equip)  -- naga cage     (north)
  minv (10318, 10387, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10325, 10388, 2, 2, east_equip)   -- kobold cage   (east)

  -- Augurers cage mobs (2 per room)
  minv (10405, 10405, 2, 2, west_equip)   -- minotaur cage (west)
  minv (10402, 10402, 2, 2, north_equip)  -- naga cage     (north)
  minv (10404, 10404, 2, 2, south_equip)  -- gnoll cage    (south)
  minv (10403, 10403, 2, 2, east_equip)   -- kobold cage   (east)

  
  -- Arena mobs - we invoke 1 or 2 at a time, up to a maximum of 4 alive
  
  multiple_mobs (10301, { 10365, 10367, 10368, 10375 }, 1, 4)  -- slug arena 
  multiple_mobs (10303, { 10363, 10370, 10377, 10381 }, 1, 4)  -- crawler arena 
  multiple_mobs (10300, { 10365, 10373, 10374, 10379 }, 1, 4)  -- wolf arena
  multiple_mobs (10302, { 10370, 10372 }, 2, 4)  -- naga arena
  multiple_mobs (10396, { 10395, 10396 }, 2, 4)  -- naga spirit arena
  minv (10397, 10397, 1, 1, { wield = 10318 } )  -- queen naga asp --> wielding 'snakebite'

  -- Lower tunnels
  
  minv (10415, 10407)  -- rat grey arena   --> A dark tunnel below the Battlegrounds
  minv (10409, 10408)  -- ant fire arena 
  minv (10418, 10409)  -- mole arena 
  minv (10417, 10411)  -- rat grey arena 
  minv (10411, 10412)  -- centipede arena 
  minv (10406, 10413)  -- fire ant arena   --> A hollow cavern deep underground
  minv (10416, 10414)  -- rat grey arena 
  minv (10412, 10415)  -- centipede arena 
  minv (10407, 10418)  -- ant fire arena 
  minv (10413, 10421)  -- centipede arena 
  minv (10420, 10422)  -- mole arena 
  minv (10410, 10423)  -- centipede arena
  minv (10408, 10424)  -- ant fire arena 
  minv (10414, 10425)  -- rat grey arena 
  minv (10419, 10426)  -- mole arena 
  minv (10421, 10427)  -- mole arena 
  
  -- New player advancers
  
  minv (10497, 10499)  -- hvak1 advancer   --> Chamber of the Watch Room
  minv (10498, 10499)  -- hvak2 advancer 
  
end -- reset_new_academy


The first thing I noticed was that resets were adding fountains all over the place, so a small helper function let me spawn multiple fountains in a single function call.

Then we close various doors.

After that the friendly mobs are spawned. The shopkeeper has clearly labelled inventory.

Another helper function "minv" was written which puts a mob in a room, spawning x at a time, up to a maximum of y mobs in the area. (eg. add 2 naga at once, to a total of 4).

If the mob has equipped items, or inventory, these can be specified as part of the minv function. You can also do bags with things in them, including other bags.

The "cage mob" equipment was repeatedly being specified in the original resets, so I made a table of equipment, and used it for each different class of cage mob. This lets you modify the cage equipment much more easily, if you want to.

Moving down to the arena, I noticed that the same mob was being spawned in multiple places, so I made a "multiple_mobs" function, that loops around, placing the mobs in the desired places.

You can see from the code above that the resets are much more readable than before. So far I haven't addressed the other ideas (like random mobs, or random equipment) but that would be easily added in.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Sun 15 Jul 2007 04:18 AM (UTC)  quote  ]

Amended on Sun 15 Jul 2007 04:22 AM (UTC) by Nick Gammon

Message
Debugging displays (which you would remove eventually) show all this happening:


Doing Lua reset of area newacad.are
Invoked object 10401 (a fountain) in room 10300 (Darkhaven Academy)
Invoked object 10401 (a fountain) in room 10305 (Chamber of Trials for Rangers)
Invoked object 10401 (a fountain) in room 10319 (The Academy Healer)
Invoked object 10401 (a fountain) in room 10325 (Chamber of Trials for Warriors)
Invoked object 10401 (a fountain) in room 10326 (Chamber of Trials for Druids)
Invoked object 10401 (a fountain) in room 10327 (Chamber of Trials for Vampires)
Invoked object 10401 (a fountain) in room 10328 (Chamber of Trials for Thieves)
Invoked object 10401 (a fountain) in room 10329 (Chamber of Trials for Mages)
Invoked object 10401 (a fountain) in room 10330 (Chamber of Trials for Clerics)
Invoked object 10401 (a fountain) in room 10364 (North-East Corner)
Invoked object 10401 (a fountain) in room 10366 (South-East Corner)
Invoked object 10401 (a fountain) in room 10374 (The Center of the Battlegrounds)
Invoked object 10401 (a fountain) in room 10382 (North-West Corner)
Invoked object 10401 (a fountain) in room 10386 (South-West Corner)
Invoked object 10401 (a fountain) in room 10401 (Chamber of Trials for Augurers)
Invoked mob 10399 (Mistress Tsythia) in room 10300 (Darkhaven Academy)
Invoked mob 10340 (Domick) in room 10303 (The Laboratory of Skills and Spells)
Invoked mob 10333 (the spectre) in room 10305 (Chamber of Trials for Rangers)
Invoked mob 10394 (abbigayle) in room 10306 (Abbigayle's Language Lessons)
Invoked mob 10342 (Lord Toric) in room 10319 (The Academy Healer)
Invoked mob 10346 (Silvina) in room 10355 (The Room of Portals)
Invoked mob 10343 (Zurg) in room 10357 (Darkhaven Academy Supply Store)
Invoked mob 10345 (the chadoyn) in room 10308 (A Dank Pit)
Invoked mob 10352 (the statue) in room 10318 (Hall of the Warrior)
Invoked mob 10354 (the statue) in room 10320 (Hall of the Druid)
Invoked mob 10353 (the statue) in room 10321 (Hall of the Vampire)
Invoked mob 10351 (the statue) in room 10322 (Hall of the Thief)
Invoked mob 10349 (the statue) in room 10323 (Hall of the Mage)
Invoked mob 10350 (the statue) in room 10324 (Hall of the Cleric)
Invoked mob 10355 (the statue) in room 10391 (Hall of the Ranger)
Invoked mob 10400 (The statue) in room 10400 (Hall of the Augurer)
Invoked mob 10334 (the spectre) in room 10325 (Chamber of Trials for Warriors)
Invoked mob 10335 (the spectre) in room 10326 (Chamber of Trials for Druids)
Invoked mob 10336 (the spectre) in room 10327 (Chamber of Trials for Vampires)
Invoked mob 10337 (the spectre) in room 10328 (Chamber of Trials for Thieves)
Invoked mob 10338 (the spectre) in room 10329 (Chamber of Trials for Mages)
Invoked mob 10339 (the spectre) in room 10330 (Chamber of Trials for Clerics)
Invoked mob 10401 (The spectre) in room 10401 (Chamber of Trials for Augurers)
Invoked mob 10326 (the minotaur) in room 10331 (Clerics West Cage)
Invoked mob 10326 (the minotaur) in room 10331 (Clerics West Cage)
Invoked mob 10305 (the naga) in room 10332 (Clerics North Cage)
Invoked mob 10305 (the naga) in room 10332 (Clerics North Cage)
Invoked mob 10312 (the gnoll) in room 10333 (Clerics South Cage)
Invoked mob 10312 (the gnoll) in room 10333 (Clerics South Cage)
Invoked mob 10319 (the kobold) in room 10334 (Clerics East Cage)
Invoked mob 10319 (the kobold) in room 10334 (Clerics East Cage)
Invoked mob 10327 (the minotaur) in room 10337 (Mages West Room)
Invoked mob 10327 (the minotaur) in room 10337 (Mages West Room)
Invoked mob 10306 (the naga) in room 10335 (Mages North Cage)
Invoked mob 10306 (the naga) in room 10335 (Mages North Cage)
Invoked mob 10313 (the gnoll) in room 10336 (Mages South Cage)
Invoked mob 10313 (the gnoll) in room 10336 (Mages South Cage)
Invoked mob 10320 (the kobold) in room 10338 (Mages East Room)
Invoked mob 10320 (the kobold) in room 10338 (Mages East Room)
Invoked mob 10328 (the minotaur) in room 10341 (Warriors West Cage)
Invoked mob 10328 (the minotaur) in room 10341 (Warriors West Cage)
Invoked mob 10307 (the naga) in room 10339 (Warriors North Cage)
Invoked mob 10307 (the naga) in room 10339 (Warriors North Cage)
Invoked mob 10314 (the gnoll) in room 10340 (Warriors South Cage)
Invoked mob 10314 (the gnoll) in room 10340 (Warriors South Cage)
Invoked mob 10321 (the kobold) in room 10342 (Warriors East Cage)
Invoked mob 10321 (the kobold) in room 10342 (Warriors East Cage)
Invoked mob 10329 (the minotaur) in room 10345 (Druids West Cage)
Invoked mob 10329 (the minotaur) in room 10345 (Druids West Cage)
Invoked mob 10308 (the naga) in room 10343 (Druids North Cage)
Invoked mob 10308 (the naga) in room 10343 (Druids North Cage)
Invoked mob 10315 (the gnoll) in room 10344 (Druids South Cage)
Invoked mob 10315 (the gnoll) in room 10344 (Druids South Cage)
Invoked mob 10322 (the kobold) in room 10346 (Druids East Cage)
Invoked mob 10322 (the kobold) in room 10346 (Druids East Cage)
Invoked mob 10330 (the minotaur) in room 10349 (Vampires West Cage)
Invoked mob 10330 (the minotaur) in room 10349 (Vampires West Cage)
Invoked mob 10309 (the naga) in room 10347 (Vampires North Cage)
Invoked mob 10309 (the naga) in room 10347 (Vampires North Cage)
Invoked mob 10316 (the gnoll) in room 10348 (Vampires South Cage)
Invoked mob 10316 (the gnoll) in room 10348 (Vampires South Cage)
Invoked mob 10323 (the kobold) in room 10350 (Vampires East Cage)
Invoked mob 10323 (the kobold) in room 10350 (Vampires East Cage)
Invoked mob 10331 (the minotaur) in room 10353 (Thieves West Cage)
Invoked mob 10331 (the minotaur) in room 10353 (Thieves West Cage)
Invoked mob 10310 (the naga) in room 10351 (Thieves North Cage)
Invoked mob 10310 (the naga) in room 10351 (Thieves North Cage)
Invoked mob 10317 (the gnoll) in room 10352 (Thieves South Cage)
Invoked mob 10317 (the gnoll) in room 10352 (Thieves South Cage)
Invoked mob 10324 (the kobold) in room 10354 (Thieves East Cage)
Invoked mob 10324 (the kobold) in room 10354 (Thieves East Cage)
Invoked mob 10332 (the minotaur) in room 10390 (Rangers West Cage)
Invoked mob 10332 (the minotaur) in room 10390 (Rangers West Cage)
Invoked mob 10311 (the naga) in room 10389 (Rangers North Cage)
Invoked mob 10311 (the naga) in room 10389 (Rangers North Cage)
Invoked mob 10318 (the gnoll) in room 10387 (Rangers South Cage)
Invoked mob 10318 (the gnoll) in room 10387 (Rangers South Cage)
Invoked mob 10325 (the kobold) in room 10388 (Rangers East Cage)
Invoked mob 10325 (the kobold) in room 10388 (Rangers East Cage)
Invoked mob 10405 (the kobold) in room 10405 (Augurers West Cage)
Invoked mob 10405 (the kobold) in room 10405 (Augurers West Cage)
Invoked mob 10402 (the naga) in room 10402 (Augurers North Cage)
Invoked mob 10402 (the naga) in room 10402 (Augurers North Cage)
Invoked mob 10404 (the gnoll) in room 10404 (Augurers South Cage)
Invoked mob 10404 (the gnoll) in room 10404 (Augurers South Cage)
Invoked mob 10403 (the minotaur) in room 10403 (Augurers East Cage)
Invoked mob 10403 (the minotaur) in room 10403 (Augurers East Cage)
Invoked mob 10301 (a slimy slug) in room 10365 (Along the eastern wall)
Invoked mob 10301 (a slimy slug) in room 10367 (Along the southern wall)
Invoked mob 10301 (a slimy slug) in room 10368 (Battle Grounds)
Invoked mob 10301 (a slimy slug) in room 10375 (Central Battlegrounds)
Invoked mob 10303 (a carrion crawler) in room 10363 (Along the eastern wall)
Invoked mob 10303 (a carrion crawler) in room 10370 (Battle Grounds)
Invoked mob 10303 (a carrion crawler) in room 10377 (Along the southern wall)
Invoked mob 10303 (a carrion crawler) in room 10381 (Along the northern wall)
Invoked mob 10300 (the dread wolf) in room 10365 (Along the eastern wall)
Invoked mob 10300 (the dread wolf) in room 10373 (Central Battlegrounds)
Invoked mob 10300 (the dread wolf) in room 10374 (The Center of the Battlegrounds)
Invoked mob 10300 (the dread wolf) in room 10379 (Mid-way in the Battlegrounds)
Invoked mob 10302 (the bone naga) in room 10370 (Battle Grounds)
Invoked mob 10302 (the bone naga) in room 10370 (Battle Grounds)
Invoked mob 10302 (the bone naga) in room 10372 (In the middle of the northern wall)
Invoked mob 10302 (the bone naga) in room 10372 (In the middle of the northern wall)
Invoked mob 10396 (the spirit naga) in room 10395 (Deeper in the Cavern)
Invoked mob 10396 (the spirit naga) in room 10395 (Deeper in the Cavern)
Invoked mob 10396 (the spirit naga) in room 10396 (In the Cavern)
Invoked mob 10396 (the spirit naga) in room 10396 (In the Cavern)
Invoked mob 10397 (Asp) in room 10397 (Cove of the Queen)
Invoked mob 10415 (a large grey rat) in room 10407 (A dark tunnel below the Battlegrounds)
Invoked mob 10409 (a Fire Ant) in room 10408 (A dark tunnel below the Battlegrounds)
Invoked mob 10418 (a mole) in room 10409 (A dark tunnel below the Battlegrounds)
Invoked mob 10417 (a large grey rat) in room 10411 (A dark tunnel below the Battlegrounds)
Invoked mob 10411 (a centipede) in room 10412 (A dark tunnel below the Battlegrounds)
Invoked mob 10406 (a Fire Ant) in room 10413 (A hollow cavern deep underground)
Invoked mob 10416 (a large grey rat) in room 10414 (A hollow cavern deep underground)
Invoked mob 10412 (a centipede) in room 10415 (A hollow cavern deep underground)
Invoked mob 10407 (a Fire Ant) in room 10418 (A hollow cavern deep underground)
Invoked mob 10413 (a centipede) in room 10421 (A hollow cavern deep underground)
Invoked mob 10420 (a mole) in room 10422 (A hollow cavern deep underground)
Invoked mob 10410 (a centipede) in room 10423 (A dark tunnel below the Battlegrounds)
Invoked mob 10408 (a Fire Ant) in room 10424 (A dark tunnel below the Battlegrounds)
Invoked mob 10414 (a large grey rat) in room 10425 (A dark tunnel below the Battlegrounds)
Invoked mob 10419 (a mole) in room 10426 (A dark tunnel below the Battlegrounds)
Invoked mob 10421 (a mole) in room 10427 (A dark tunnel below the Battlegrounds)
Invoked mob 10497 (Hungrily, a hollow voice) in room 10499 (Chamber of the Watch)
Invoked mob 10498 (A rasping voice) in room 10499 (Chamber of the Watch)


In other words, everything was repopped initially. Now I go and kill a kobold and a minotaur, and wait for the next reset:


Admin just killed 10323
Admin just killed 10330
Doing Lua reset of area newacad.are
Invoked mob 10330 (the minotaur) in room 10349 (Vampires West Cage)
Invoked mob 10323 (the kobold) in room 10350 (Vampires East Cage)


Now the two mobs I killed are replaced, but nothing else is done.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Gohan_TheDragonball   USA  (183 posts)  [Biography] bio
Date Reply #2 on Wed 18 Jul 2007 02:24 AM (UTC)  quote  ]
Message
a couple months ago i installed the reset serial snippet so that resets when first called are given a serial number, the mob/object that is invoked is assigned that serial number. when the area is reset next, it checks if that mob/object still exists, if not, then it respawns in the designated room. i call notice this because i have many mobs that wander, and i wanted to make sure more and more of these wandering mobs would not keep being made, eventually overpopulating. does your system do this or is it just like smaugs reset system, where it just checks the room specified, and if not found in that room, it respawns?
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #3 on Wed 18 Jul 2007 05:56 AM (UTC)  quote  ]
Message
The short answer is, as it is a scripted system you can do whatever you want. The longer answer is, that if you look at the function minv:


-- invoke up to 'count' mobs, so we have no more than 'max' mobs in the area
function minv (mob, room, count, max, ...)
  local current = mud.mobinarea (mob, room) or 0  -- present count 
  local most = (max or 1) - current           -- how many we can have
  
  -- invoke the lot of them
  for i = 1, math.min ((count or 1), most) do
    debug_show_mob_invoked (mob, room)
    mud.minvoke (mob, room, ...)
  end -- invoking each one
  
end -- minv


What this does if find how many mobs of that vnum are in the area, and spawn a maximum of the requested number, limited by the maximum number you want in the area. So, it will never spawn more than the maximum you request. For example:


minv (10332, 10390, 2, 2, west_equip)   -- minotaur cage (west)


That spawns up to 2 at once, to a maximum of 2.

If you knew the mobs weren't going to move, you could make a different function that checked the room count, rather than the area count.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio   Moderator
Date Reply #4 on Wed 18 Jul 2007 06:29 AM (UTC)  quote  ]
Message
Actually you can't do quite whatever you want unless you attach extra information to your mobiles, tying them to which reset they came from specifically. What you have is close but it's not quite what Gohan was talking about.

Example:

Two guards reset in room A and two guards reset in room B. The total count is therefore four. Assume the guards might move around so you can't do room counts.

I show up and kill both in room A.

A reset happens. It calls minv, with two guards in room A. But minv gets the area count, and sees that there are already two guards. So it doesn't respawn the two guards.

(Thinking about it, maybe you couldn't spawn the 2nd pair in the first place, since it would already see that there are two guards in the area.)

If you look at the resets you have, there are several "nagas" invoked, but they are in fact different vnums, which is why I think you didn't run into this problem.


This is a considerable problem because it means you wouldn't be able to use minv to load the same mob in several rooms; the area count would get in your way. It's not reasonable to need to always make different copies of the same mob if you want them in different rooms.


The serial number system addresses this by associating each loaded mob with the reset it comes from. So when you process a given reset, it sees if the mobs that came from it are indeed gone.

Thing is, that wouldn't be easily done with a list of minv commands, because you need an actual reset pointer/number to associate to the mob.



Why can this not be solved by just counting? Well, counting loses the origin of a mob. If you want 4 moving mobs (there's redundancy if I've seen it: "moving mobiles") in 4 locations, and you find that only three mobs are left, you could process one of the resets. But which one? You could get into something like picking the room that is the furthest from the current mobs, but isn't that a lot of trouble to go to in the reset?

And what the same mob is spawned in the four rooms, but with different equipment every time? If I want to respawn the mob that died with the same equipment, do I have to go in and check the mobs to see what the ones that are still alive are wearing?

What if the mobs can lose their equipment somehow? That would also throw off the reset system.

The serial number solves this, but it requires attaching extra data to your mobs.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Wed 18 Jul 2007 07:05 AM (UTC)  quote  ]
Message
Quote:

Two guards reset in room A and two guards reset in room B. The total count is therefore four. Assume the guards might move around so you can't do room counts.

I show up and kill both in room A.

A reset happens. It calls minv, with two guards in room A. But minv gets the area count, and sees that there are already two guards. So it doesn't respawn the two guards.


For this to even partly work you would need to spawn 2 to a maximum of 4, which is what this line does:


multiple_mobs (10301, { 10365, 10367, 10368, 10375 }, 1, 4)  -- slug arena 


That spawns 1 in each room, but never more than 4 in an area. So if you killed 2, 2 get replaced. But, the problem is it might add them back into the first and second rooms (10365, 10367) which might already have one or even more in them. Maybe that isn't a problem.

You could make the spawning smarter by having something like:


  • Max to spawn this time around
  • Max allowable in a particular room (so they don't all end up in the same room)
  • Max allowable in the area (in case they walk around)


I'm not sure it is a big problem. Even as written, the number of mobs in the area is regenerated correctly. Maybe you get 2 or 3 in a room at once. That can happen anyway as they walk around.

Quote:

And what the same mob is spawned in the four rooms, but with different equipment every time? If I want to respawn the mob that died with the same equipment, do I have to go in and check the mobs to see what the ones that are still alive are wearing?


Well, I am not sure I would want to, as that goes against the idea of random loot a bit. But you could conceivably check each mob's equipment.

Actually what I was thinking about was making the resets less "chunky". It always seemed a bit strange to me that you gradually deplete all the mobs in a zone, and then suddenly they all come back. What could be nice would be to run the reset code more frequently, but have a way of knowing when a mob died, and not replace it for 5 or 10 minutes.

There is already a "killed_mob" hook, so you could add them to a table with a timestamp for that purpose. I agree however it would be nice to stamp mobs with serial numbers, so you replace the correct one. That wouldn't be a big deal to do.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio   Moderator
Date Reply #6 on Wed 18 Jul 2007 07:18 AM (UTC)  quote  ]
Message
Quote:
I'm not sure it is a big problem. Even as written, the number of mobs in the area is regenerated correctly. Maybe you get 2 or 3 in a room at once. That can happen anyway as they walk around.

I agree, in the very large majority of cases it would work fine.

I'm starting to think though that this SMAUGish approach just isn't the right one. More on that later along the lines of the events you suggested and we discussed a few years back.

Quote:
Well, I am not sure I would want to, as that goes against the idea of random loot a bit.

There are several use cases for such an idea; for instance, you might want certain quest items to deterministically respawn on certain mobs. Or maybe you want the guards assigned to the south gate to all have a specific badge, but the guards are otherwise identical to the north gate guards.

Quote:
Actually what I was thinking about was making the resets less "chunky". It always seemed a bit strange to me that you gradually deplete all the mobs in a zone, and then suddenly they all come back. What could be nice would be to run the reset code more frequently, but have a way of knowing when a mob died, and not replace it for 5 or 10 minutes.

There is already a "killed_mob" hook, so you could add them to a table with a timestamp for that purpose.


I agree -- as I alluded to above, I'm starting to think the monolithic reset approach might just be inherently flawed. It might be better to create spawn points, that are re-queued on the event handler when the mob dies (using the killed-mob hook, for instance). Or spawn points that generate a mob every 2 minutes (up to a certain limit, for instance).

I'm just not sure anymore that it makes a lot of sense for the entire area to reset all at once.

Quote:
I agree however it would be nice to stamp mobs with serial numbers, so you replace the correct one. That wouldn't be a big deal to do.

Indeed, it's not too bad. Well, it's annoying to do in the C reset system, because it's so convoluted... But it wouldn't be bad in Lua. :-)

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

http://david.the-haleys.org
[Go to top] top

Posted by Gohan_TheDragonball   USA  (183 posts)  [Biography] bio
Date Reply #7 on Wed 18 Jul 2007 09:57 AM (UTC)  quote  ]
Message
where i encountered this problem was a builder of mine created a large ocean, and it was populated by a lot of mobs in number, but diversity wise it was very few. across the ocean there were about 22 sharks. although with smaugs reset it would never go beyond 22 sharks, they would all eventually be in the same room, because the reset system invoked the very first reset in the list. this kept happening with all 5 types of mobs, it was quite funny but annoying, thats when i put the serial system in and it works great now.

i don't see why you wouldn't be able to incorporate this kind of system in lua as it is pretty basic. but looking at how exactly the scripts are setup, i can see how it would be a challenge.
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Wed 18 Jul 2007 08:40 PM (UTC)  quote  ]
Message
The script I showed was geared up to replicating what SMAUG currently does. It doesn't incorporate the other ideas I mentioned like random loot, random positions, random mob types, etc.

I think if I wanted resets to give a nice "spread" of mobs each time, without overpopulating or clumping, I would do something like this:


  • Find where each mob in the area is - put that into a table
  • For each mob type, if the numbers were down (ie. they had been killed), I would work out a list of rooms which are allowed to have that mob in, but presently doesn't.
  • I would then randomly choose from the list of empty rooms, putting the mobs back, until the population was back up.


This is easy enough to do, and the point is that scripted resets have that flexibility. However I didn't want to make the demonstration script too complex.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Samson   USA  (683 posts)  [Biography] bio
Date Reply #9 on Thu 19 Jul 2007 03:02 AM (UTC)  quote  ]
Message
More of a technical question here. The resets.lua file included with the 1.8 demo tarball has the academy resets in the same file as all the support functions it uses. Does this have to be this way for each area's set of resets or could you put all the support functions into one file, then do an include from that in a separate file for each area?

SmaugMuds.org: http://www.smaugmuds.org - The Smaug MUDs Community Center

"The past was erased, the erasure was forgotten, the lie became truth." -- George Orwell, 1984
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Thu 19 Jul 2007 04:15 AM (UTC)  quote  ]

Amended on Thu 19 Jul 2007 04:24 AM (UTC) by Nick Gammon

Message
Sure. I have modified my example file (resets.lua) to load the various areas as subfile.


-- Lua reset handling for SMAUG FUSS
--   Written by Nick Gammon
--   15th July 2007

-- See: http://www.gammon.com.au/forum/?id=8027

--     www.gammon.com.au

module (..., package.seeall)

-- debugging displays
SHOW_INVOKED_MOBS = false
SHOW_INVOKED_OBJECTS = false
SHOW_AREA_RESET = false

-- loader for modules to load sub-modules, in the module context
function resets_loader (name)
  setfenv (assert (loadfile (
           string.format (systeminfo.LUA_DIR .. "resets/" .. "%s.lua", name))), _M) ()
end -- resets_loader

resets_loader "academy"
resets_loader "darkhaven"
--- etc.


The slightly fancy function resets_loader loads the file in the "resets" subdirectory of the "lua" directory. It does a setfenv because the whole resets thing is in its own module, and it needs the environment of the other parts of the module. Effectively this is a namespace thing, so if you happen to choose a variable in the resets subsystem, it won't clash with the same variable in the task subsystem, for example.

After that, the entire function "reset_new_academy" is simply moved into the file "academy.lua" in the resets subdirectory, and loaded in as required.

Of course, you would want to do this in practice, so that each area can have an accompanying resets file.

However the main resets.lua file can have helper functions (like minv) that all resets files might need to use.


- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #11 on Thu 19 Jul 2007 07:08 AM (UTC)  quote  ]
Message
In case you are worried this might take too long, I did a timing test:


print ("Loading resets at", os.time ())
for i = 1, 5000 do
  resets_loader "academy"
end
print ("Done loading resets at", os.time ())

--> Output

Thu Jul 19 17:05:29 2007 :: Initializing Lua
Loading resets at       1184828729
Done loading resets at  1184828737
Mud-wide Lua module started up.



So, that took 8 seconds to load 5000 resets files. That is 0.0016 seconds per file. You could have 100 resets files, and they would load in 0.16 seconds.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Nick Gammon   Australia  (19,382 posts)  [Biography] bio   Forum Administrator
Date Reply #12 on Thu 19 Jul 2007 07:28 AM (UTC)  quote  ]
Message
Out of curiosity, I added code to academy.lua to find how many mobs were in each room, like this:


  local area = assert (mud.area_info (name))
  local rooms = {}
  
  for i = area.low_r_vnum, area.hi_r_vnum do
    vnum, ud = mud.mobs_in_room (i)
    if vnum then
      rooms [i] = { vnums = vnum, ud = ud }  
    end -- room exists
  end -- doing each room


Now the table "rooms" will have the vnums of every mob in that room, and from that you could work out whether or not you wanted to put a mob there.

All this processing takes time, so I tried running the reset code 1000 times (rather than once). It took 2 seconds to run 1000 area resets, with the above code in it, and 1 second to run 1000 area resets, without finding the number of mobs in each room.

That means that the original reset code runs in 0.001 seconds per area, and with extra checking for how many mobs are in each room it runs in 0.002 seconds per area.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[Go to top] top

Posted by Darwin   USA  (125 posts)  [Biography] bio
Date Reply #13 on Sun 29 Jul 2007 02:38 AM (UTC)  quote  ]
Message
I'm still having some problems with the resets module. Running through gdb I get this:
Sat Jul 28 21:33:07 2007 :: Resetting areas...

Program received signal SIGSEGV, Segmentation fault.
0x0816f0cb in lua_settop ()
(gdb) bt
#0  0x0816f0cb in lua_settop ()
#1  0x0816e384 in call_mud_lua (fname=0x81c2a0a "reset_area", argument=0x8dbbeb8 "universe.are") at lua_scripting.c:2840
#2  0x08110fc0 in reset_area (pArea=0x8dbbdf8) at reset.c:1318
#3  0x080af26d in area_update () at db.c:2601
#4  0x080ac11c in boot_db (fCopyOver=0 '\0') at db.c:799
#5  0x080a3692 in main (argc=2, argv=0xbfff9ff4) at comm.c:287

The universe.are file doesn't have anything set for resets in the file or for the Lua module.

lua_settop() is being called from within the call_mud_lua function at this line:
  lua_settop (L_mud, 0);    /* get rid of stuff lying around */
[Go to top] top

Posted by Darwin   USA  (125 posts)  [Biography] bio
Date Reply #14 on Sun 29 Jul 2007 03:04 AM (UTC)  quote  ]
Message
Err.. nevermind. :)

Problem was that the open_mud_lua() function wasn't called at bootup.
[Go to top] top

The dates and times for posts above are shown in Universal Co-ordinated Time (UTC).

To show them in your local time you can join the forum, and then set the 'time correction' field in your profile to the number of hours difference between your location and UTC time.


11,836 views.

This is page 1, subject is 2 pages long: 1 2  [Next page]

[Reply to this subject]  Reply to this subject   [New subject]  Start a new subject   [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

[Home]

Written by Nick Gammon - 5K

Comments to: Gammon Software support
[RH click to get RSS URL] Forum RSS feed ( http://www.gammon.com.au/rss/forum.xml )

[Best viewed with any browser - 2K]    [Internet Contents Rating Association (ICRA) - 2K]    [Web site powered by FutureQuest.Net]