Example of using STL in SMAUG

Posted by Nick Gammon on Wed 21 Jan 2004 01:45 AM — 2 posts, 8,581 views.

Australia Forum Administrator #0
The example below illustrates using the Standard Template Library (STL) to manipulate the objects in your inventory.

It adds a new verb (stltest) which you can type to put it through its paces.

It uses a vector which is quickly loaded from the current player's inventory (in 2 lines) and is then sorted into different orders.

The sort itself is very simple (one line) and is assisted by a "compare less" function object which should be pretty self-explanatory. You can add to it to sort on different fields.

It also illustrates a "print" function object which lets you send the vector contents to the player in one line.



This it the file stltest.cpp ...


#include <sys/types.h>
#include <ctype.h>
#include <stdio.h>
#include <string.h>
#include <time.h>
#include <sys/stat.h>
#include "mud.h"

#include <string>
#include <vector>
#include <algorithm>
#include <iterator>
#include <functional>
#include <iostream>
#include <sstream>

using namespace std;

// this define lets you create a string on-the-fly
// you can use output modifiers in the string, eg.
// string mystr = MAKE_STRING (
//    "hello " << boolalpha << true << hex << 1234 << octal << 3456 << dec
//    << 123456 << scientific << 123.45 << fixed << 1234.567 " );
//
// see: ios_base::fmtflags for more details

#define MAKE_STRING(msg) \
   (((ostringstream&) (ostringstream() << boolalpha << msg)).str())

//-------------------------------------------------------------------------
// function object to print one object 
//-------------------------------------------------------------------------
class fPrint 
  {

  // remember who to print to (set in constructor)
  CHAR_DATA * m_ch;

  public:

  // constructor - remember which player to send to
  fPrint (CHAR_DATA * ch) : m_ch (ch) {};

  // show this object
  void operator() (const OBJ_DATA * obj)
    {
    string s = MAKE_STRING (
              "object: '" << obj->description 
              << "', level " << obj->level 
              << ", weight " << obj->weight 
              << endl );
    send_to_char (s.c_str (), m_ch);
    };

  };  // end of class fPrint

//-------------------------------------------------------------------------
// sort sequence
//-------------------------------------------------------------------------
enum { 
      obj_sort_description,
      obj_sort_level,
      obj_sort_weight,
    };

//-------------------------------------------------------------------------
// function object obj_less determine if one object is less than another
// - the sort sequence is provided in the constructor
//-------------------------------------------------------------------------
    
struct obj_less : binary_function<OBJ_DATA *, OBJ_DATA *, bool>
  {
  const int m_iSequence;
  
  // constructor
  obj_less (const int iSequence) : m_iSequence (iSequence) {};
  
  bool operator() (const OBJ_DATA * obj1, const OBJ_DATA * obj2) const
    {  
    switch (m_iSequence)
      {
      case obj_sort_description:
          return strcmp (obj1->description, obj2->description) < 0;    
          
      case obj_sort_level:
          return obj1->level < obj2->level;
          
      case obj_sort_weight:
          return obj1->weight < obj2->weight;
                          
      };  // end of switch on sequence
    
    // default to sort on level if switch doesn't match
    return obj1->level < obj2->level;
    } // end of operator()
  }; // end of obj_less

//-------------------------------------------------------------------------
// do_stltest - shows my inventory in various ways
//-------------------------------------------------------------------------

void do_stltest( CHAR_DATA *ch, char *argument )
{

// vector to hold however many objects we are carrying
vector <OBJ_DATA *> v;

//-------------------------------------------------------------------------
// add object list to vector
//-------------------------------------------------------------------------
for (OBJ_DATA * obj = ch->first_carrying; obj; obj = obj->next_content)
  v.push_back (obj);

//-------------------------------------------------------------------------
// original order
//-------------------------------------------------------------------------

send_to_char ("\n\nObjects in original order ... \n\n", ch);

// display them
for_each (v.begin (), v.end (), fPrint (ch));

//-------------------------------------------------------------------------
// description order
//-------------------------------------------------------------------------

send_to_char ("\n\nObjects sorted into description order ... \n\n", ch);

// sort into description order
sort (v.begin (), v.end (), obj_less (obj_sort_description));

// display them
for_each (v.begin (), v.end (), fPrint (ch));

//-------------------------------------------------------------------------
// level order
//-------------------------------------------------------------------------

send_to_char ("\n\nObjects sorted into level order ... \n\n", ch);

// sort into level order
sort (v.begin (), v.end (), obj_less (obj_sort_level));

// display them
for_each (v.begin (), v.end (), fPrint (ch));

//-------------------------------------------------------------------------
// weight order
//-------------------------------------------------------------------------

send_to_char ("\n\nObjects sorted into weight order ... \n\n", ch);

// sort into weight order
sort (v.begin (), v.end (), obj_less (obj_sort_weight));

// display them
for_each (v.begin (), v.end (), fPrint (ch));

//-------------------------------------------------------------------------
// shuffle them
//-------------------------------------------------------------------------

send_to_char ("\n\nObjects shuffled ... \n\n", ch);

random_shuffle (v.begin (), v.end ());

// display them
for_each (v.begin (), v.end (), fPrint (ch));

}




Changes to tables.c ...


*** ../src.orig/tables.c        2004-01-21 13:03:44.000000000 +1100
--- tables.c    2004-01-21 13:05:44.000000000 +1100
***************
*** 681,686 ****
--- 681,687 ----
        if ( !str_cmp( name, "do_supplicate" ))         return do_supplicate;
        if ( !str_cmp( name, "do_switch" ))             return do_switch;
        if ( !str_cmp( name, "do_showlayers" ))         return do_showlayers;
+       if ( !str_cmp( name, "do_stltest" ))            return do_stltest;
        break;
      case 't':
        if ( !str_cmp( name, "do_tamp" ))               return do_tamp;
***************
*** 1316,1321 ****
--- 1317,1323 ----
      if ( skill == do_supplicate )     return "do_supplicate";
      if ( skill == do_switch )         return "do_switch";
      if ( skill == do_showlayers )     return "do_showlayers";
+     if ( skill == do_stltest )                return "do_stltest";
      if ( skill == do_tamp )           return "do_tamp";
      if ( skill == do_tell )           return "do_tell";
      if ( skill == do_think )          return "do_think";




Add this to commands.dat ...


#COMMAND
Name        stltest~
Code        do_stltest
Position    100
Level       51
Log         1
End




Example of testing it ...

stltest
Log: Lordrom: stltest


Objects in original order ...

object: 'A book with "DON'T PANIC, LOOK AT ME!" written on the cover lies here.', level 0, weight 1
object: 'A blade of metallic stone protrudes from a leather-wrapped hilt.', level 1, weight 2
object: 'A strong metal collar from the academy', level 1, weight 5
object: 'A pair of kid gloves from the Academy lie here', level 1, weight 2
object: 'A charm bracelet from the academy lies here', level 1, weight 2
object: 'A pair of black combat boots from the Academy lies here', level 1, weight 3
object: 'A set of mail leggings has fallen here.', level 12, weight 4
object: 'A cherry pie makes your mouth water.', level 0, weight 1
object: 'A large marble fountain gushes forth here.', level 1, weight 500
object: 'A large chocolate cake awaits someone to eat it.', level 0, weight 1
object: 'Some sort of dried meat is on the ground here.', level 0, weight 1


Objects sorted into description order ...

object: 'A blade of metallic stone protrudes from a leather-wrapped hilt.', level 1, weight 2
object: 'A book with "DON'T PANIC, LOOK AT ME!" written on the cover lies here.', level 0, weight 1
object: 'A charm bracelet from the academy lies here', level 1, weight 2
object: 'A cherry pie makes your mouth water.', level 0, weight 1
object: 'A large chocolate cake awaits someone to eat it.', level 0, weight 1
object: 'A large marble fountain gushes forth here.', level 1, weight 500
object: 'A pair of black combat boots from the Academy lies here', level 1, weight 3
object: 'A pair of kid gloves from the Academy lie here', level 1, weight 2
object: 'A set of mail leggings has fallen here.', level 12, weight 4
object: 'A strong metal collar from the academy', level 1, weight 5
object: 'Some sort of dried meat is on the ground here.', level 0, weight 1


Objects sorted into level order ...

object: 'A book with "DON'T PANIC, LOOK AT ME!" written on the cover lies here.', level 0, weight 1
object: 'A cherry pie makes your mouth water.', level 0, weight 1
object: 'A large chocolate cake awaits someone to eat it.', level 0, weight 1
object: 'Some sort of dried meat is on the ground here.', level 0, weight 1
object: 'A blade of metallic stone protrudes from a leather-wrapped hilt.', level 1, weight 2
object: 'A charm bracelet from the academy lies here', level 1, weight 2
object: 'A large marble fountain gushes forth here.', level 1, weight 500
object: 'A pair of black combat boots from the Academy lies here', level 1, weight 3
object: 'A pair of kid gloves from the Academy lie here', level 1, weight 2
object: 'A strong metal collar from the academy', level 1, weight 5
object: 'A set of mail leggings has fallen here.', level 12, weight 4


Objects sorted into weight order ...

object: 'A book with "DON'T PANIC, LOOK AT ME!" written on the cover lies here.', level 0, weight 1
object: 'A cherry pie makes your mouth water.', level 0, weight 1
object: 'A large chocolate cake awaits someone to eat it.', level 0, weight 1
object: 'Some sort of dried meat is on the ground here.', level 0, weight 1
object: 'A blade of metallic stone protrudes from a leather-wrapped hilt.', level 1, weight 2
object: 'A charm bracelet from the academy lies here', level 1, weight 2
object: 'A pair of kid gloves from the Academy lie here', level 1, weight 2
object: 'A pair of black combat boots from the Academy lies here', level 1, weight 3
object: 'A set of mail leggings has fallen here.', level 12, weight 4
object: 'A strong metal collar from the academy', level 1, weight 5
object: 'A large marble fountain gushes forth here.', level 1, weight 500


Objects shuffled ...

object: 'Some sort of dried meat is on the ground here.', level 0, weight 1
object: 'A book with "DON'T PANIC, LOOK AT ME!" written on the cover lies here.', level 0, weight 1
object: 'A strong metal collar from the academy', level 1, weight 5
object: 'A set of mail leggings has fallen here.', level 12, weight 4
object: 'A blade of metallic stone protrudes from a leather-wrapped hilt.', level 1, weight 2
object: 'A charm bracelet from the academy lies here', level 1, weight 2
object: 'A large marble fountain gushes forth here.', level 1, weight 500
object: 'A pair of black combat boots from the Academy lies here', level 1, weight 3
object: 'A cherry pie makes your mouth water.', level 0, weight 1
object: 'A large chocolate cake awaits someone to eat it.', level 0, weight 1
object: 'A pair of kid gloves from the Academy lie here', level 1, weight 2


Amended on Wed 21 Jan 2004 02:07 AM by Nick Gammon
Australia Forum Administrator #1
You would need to add the file stltest.cpp into your Makefile, and also convert the entire project to C++ (see recent post on that subject).

Also add this to mud.h:

DECLARE_DO_FUN( do_stltest );