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


Register forum user name Search FAQ

Gammon Forum

[Folder]  Entire forum
-> [Folder]  Programming
. -> [Folder]  General
. . -> [Subject]  Combining Ruby and C++

Combining Ruby and C++

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page


Pages: 1 2  

Posted by Nick Cash   USA  (626 posts)  [Biography] bio
Date Mon 31 Jul 2006 09:06 AM (UTC)
Message
I've been playing with some ideas in my head for quite some time now. Interfacing two languages in a MUD server is one of them.

I don't know much on this subject, so any general knowledge about interfacing languages would be good.

I have read most of MUD Programming by Ron Penton, where in BetterMUD he interfaced C++ and Python. This allowed him to use Python to handle most of the game logic, which I must say is very nifty. It seemed like a lot of work getting the accessors to work and using SWIG to generate the interface though.

Even so, how exactly does it work? That is, how could Python (or, in my case, Ruby) modify any actual game data in the C++ server? Do the script functions just call C++ equivalents that really do the work?

Also, if the server were to run using MySQL as its database and it sent queries for all of the required changes and information, would it be more effecient to design a database manipulation library for the scripting library and skip the process of interfacing the two completely (apart from having the server call the scripts)? It seems that keeping all data within the database would be preferable if the game got large since the database can more effeciently manage the data, data access, and other database elements. Consolidating all information to the database itself would also promote web integration (mainly administration and/or building).

Also, any word on the BabbleMUD Wiki and/or forum? I would certainly like to read your comments on design and whatever else.

~Nick Cash
http://www.nick-cash.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #1 on Mon 31 Jul 2006 10:06 AM (UTC)
Message
Quote:

That is, how could Python (or, in my case, Ruby) modify any actual game data in the C++ server? Do the script functions just call C++ equivalents that really do the work?


These are deep questions and I will respond in more detail tomorrow.

A fundamental question is, which "script space" will hold your real game data? I have been working fairly recently on a server written in Lua, where the real data would be in Lua variables.

If the "real data" is in C or C++ variables, then yes, the Ruby/Python/Lua scripts would need interfaces that modified the real data.

I suppose it depends on what you define as "the work". If the bulk of the calculations are done in your script language, and at the end it gets the server to modify a C++ structure, you could argue that the work is being done in scripting, and the data storage in C++. A similar remark would apply to MySQL.

For me, using Lua solved various problems, like being able to add additional pieces of data at a later date, something which is hard if you have fixed C or C++ structures. It is a bit easier with SQL, but you still have to modify the tables to allow for the new data.

- Nick Gammon

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

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #2 on Mon 31 Jul 2006 02:25 PM (UTC)
Message
The problem is that (as usual, unfortunately) there isn't really any one set way of doing things. The SWIG picture is one where the scripting language has 'proxies' for the C++ data structures, and changing the Python/whatever object will change the C++ object, and similarly calling a method on the scripting object will invoke a C++ method.

The job of SWIG (the binding, as it's known) is to create the interfaces to make this kind of conversion possible. For instance, if I call a method from Lua, somebody has to figure out how to convert the Lua data types into C++ data types. Usually this isn't that hard (number to number, string to string) but for bigger objects it can be quite hard (e.g. passing tables around).


Other ways of doing things can be quite different. Nick and I have been tending towards putting more and more into Lua and leaving C++ for the 'bare essentials', the things that need to go really fast and that do not benefit from scripting anyway. In fact we might not use C++ at all, since MUDs don't really need as much speed as, say, a 3D game.

To answer your question regarding the database, generally you want to avoid interfaces if you don't need them. If you're going to call C++ from Ruby just to invoke MySQL, you might as well invoke MySQL directly from Ruby. There's no need for the extra layer of indirection.

I'll probably be releasing the wiki information by this weekend. I had some permission issues to work out but I think I'm pretty much done with those. Thanks for your continued interest. :-)

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

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

Posted by Ked   Russia  (524 posts)  [Biography] bio
Date Reply #3 on Mon 31 Jul 2006 04:50 PM (UTC)
Message
I think what Nick and Ksilyan are saying can be boiled down to a question of whether you want to embed a Ruby interpreter in a C++ server or extend a Ruby server with C++ "utility" code.

The basic idea behind both embedding and extending, as Ksilyan said, is translation of data types. Scripting language's types are translated to C/C++/Fortran/whatever's types, either directly where direct correspondence can be found (i.e. int to an int, string to a string) with some additional mucking using mechanisms provided by the scripting language's API library, or manually when complex types are involved (i.e. tables, classes, etc.)

The same thing, only in reverse, happens when script's types need to be converted to C types. Here, most scripting languages also provide helper functions for translating simple types and complex ones have to be massaged manually until their constituents are fit to be passed to API type conversion functions and stored in some C/C++/whatever structure.

Knowing nothing about how Ruby interfaces with compiled languages, I've played with extending Lua and Python quite a bit, and both these languages use the same basic mechanism for embedding and extending: dynamic libraries. In Lua's case, the library exposes a single function that routes all calls from the script to internal functions. Python uses direct access by exporting all symbols that should be visible from the script. Worthy of mention also is the fact that Lua's extension mechanism is far simpler than that of Python, the latter having hordes of conversion and memory allocation functions in the API, a dozen for each type and situation. But Python has better extension tools: Pyrex and ctypes, while Lua has none of the kind, as far as I know. The two languages also differ in the way arguments are passed to and fro: directly, using special PyObject's in Python, and through a "stack" object in Lua (emulating the actual machine function calls). Ruby probably uses one of these.

Since a function call from Python/Lua to C/C++ is internally just a call to a function exported by a library loaded by the Python/Lua interpreter, once Python/Lua types are handled and converted to their C/C++ equivalents, you can do whatever you want in the "C/C++ space", assuming that you could do it when calling a DLL function from a normal C/C++ program, including any modifications to static or allocated memory objects (your C++ MUD data).

As far as using a RDBMS for storage: if you are extending (meaning that your server is written in an interpreted language) then Python/Lua and probably Ruby too already have libraries that interface with most of the popular DBs, allowing you to execute SQL statements, establish connections, whatever. Python even has a standard API that most modern DB bindings follow, so you could make the choice of the particular RDBMS transparent to your application, switching betwen MySQl, PostgreSQL, Oracle, etc. as you please. It also has higher level libraries that already abstract the actual RDBMS, like SQLAlchemy or the db part of the Django web framework (which simply rocks and should be copied over and over).

Lastly, in my layman's opinion, coding a MUD in Python (or Lua or Ruby) is much more fun and is much more original and stylish than doing it in C++, due to the sexiness of the languages and the toys they offer :)
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #4 on Mon 31 Jul 2006 05:07 PM (UTC)
Message
Quote:
then Python/Lua and probably Ruby too already have libraries that interface with most of the popular DBs, allowing you to execute SQL statements, establish connections, whatever.
Lua has the luasql library from the Kepler Project. Here's their website: http://www.keplerproject.org/luasql/

They claim that they can "connect to ODBC, ADO, Oracle, MySQL, SQLite, JDBC, and PostgreSQL databases", so it should work just fine for Lua.

Quote:
Lastly, in my layman's opinion, coding a MUD in Python (or Lua or Ruby) is much more fun and is much more original and stylish than doing it in C++, due to the sexiness of the languages and the toys they offer :)
Beyond those aspects (and having fun is definitely important) I think there are several purely technical reasons that make interpreted languages very well suited to the relatively dynamic needs of a MUD codebase. Dynamic typing is one example. I have found that a lot of what I've needed to do in my C++ codebase is reimplement parts of interpreters, especially when it comes to making a more powerful scripting language (to replace mudprog, that is).

Speaking of mudprog, that's a fairly good way of looking at how all this stuff fits together. Mudprog is an example of a very simple embedding; the real work is all done in C, with some "functions" exposed (they aren't really functions, though) to the scripting engine.

A more interesting embedding would do the exact same thing as mudprog, but with a much more powerful language (such as Python, Ruby, Lua, ...). The if checks would use real functions instead of the fake-not-functions; the C/C++ host application would expose more of the data. All the 'real work' would still be done in C/C++, and data would be stored in C/C++, but the scripting environment would become much more powerful and therefore much more interesting for the game and builders.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

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

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #5 on Tue 01 Aug 2006 06:50 AM (UTC)
Message
I agree with most of what has been written above. As usual, it is a case of choosing the right tool for the job.

Considerations would be:


  • Number of players expected (a scripted MUD might handle 20 to 100 players but not 200 to 1000).

  • Whether you want to be able to easily expand the MUD, or are going to do extensive design first, so that it should be fairly static once written.

  • How important it is to save changes the moment they occur (like, obtaining a hard-to-get item moments before the MUD crashes). If you want to save madly, then possibly an SQL database would be the way to go.


Quote:

In Lua's case, the library exposes a single function that routes all calls from the script to internal functions.


Actually the single function adds all of the (relevant) functions in the DLL to a table (eg. the io table), so once that initial call has been made, effectively all the functions in the DLL are now exposed, and can be called directly.

- Nick Gammon

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

Posted by Nick Cash   USA  (626 posts)  [Biography] bio
Date Reply #6 on Wed 09 Aug 2006 05:09 AM (UTC)
Message
Sorry for such a late reply! Life certainly picks up in a hurry.

The more I think about it the more it seems like doing a pure query interface would work best. It seems like interfacing the two languages would just be a hassle if I plan to make that type of move anyway.

That said, I am unsure exactly how to implement things (which is quite alright, as we are deep within the planning stage). We want the core functionality of the game to be in C++, mainly socket handling. Almost all other game logic would be handled in Ruby scripts.

What do you think would be the best implementation? It seems easy enough to call ruby and specify a script from C++, but that probably be quite as dynamic as we are looking for. On the other hand, we could probably embed a Ruby interpreter in the game core and run some sort of master Ruby script.

Regardless of what implementation is decided, it seems that I will at least need to interface the socket handling with Ruby.

Quote:

Quote:

That is, how could Python (or, in my case, Ruby) modify any actual game data in the C++ server? Do the script functions just call C++ equivalents that really do the work?


These are deep questions and I will respond in more detail tomorrow.


Any more details?

Thanks for the words of wisdom, as always.

~Nick Cash
http://www.nick-cash.com
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #7 on Wed 09 Aug 2006 05:00 PM (UTC)
Message
Life does have a tendency to do that. :-)

Sockets in C++ makes sense; I think having "systems-level" stuff be in C++ is generally a good idea. But even there, many scripting languages provide that functionality natively or with extensions. The more you put in C++, the more you'll have to port if/when you change hardware, operating systems, etc. The main advantage to a scripting package is that it hides a lot of that complexity. (Of course, C++ libraries also exist for this stuff...)


A common design is for things like AI to be scripted. So, every actor would have a script attached to it, with callbacks for various things. Think of it like mudprogs, actually: an NPC would have several functions attached that are called on certain triggers. You can use a model like this with a main loop in C++ or in the interpreted language.

Quote:
it seems that I will at least need to interface the socket handling with Ruby


That depends. In fact, you might not want to do that at all. Ruby could handle input strings, sure, but it wouldn't have to know anything about pulling bytes off of sockets. If you do the sockets in C++, you could raise an event (on the player's attached script, for example) whenever a line of input has been received.

Sorry for being a little brief at the moment; life has also caught up with me. :-) And after moving for the second half of my internship, I don't have internet access at home anymore. Grumble.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

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

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #8 on Wed 09 Aug 2006 10:35 PM (UTC)
Message
Quote:

We want the core functionality of the game to be in C++, mainly socket handling. Almost all other game logic would be handled in Ruby scripts.


I was planning something similar, although I think "core functionality" depends on your definition. If "almost all" logic is in Ruby, I would say your core functionality is in Ruby.

I have been experimenting with a Lua MUD (I know this isn't Ruby, but the idea is similar). I obtained a DLL from the Lua downloads site that provides all the TCP/IP functionality I need. In fact, to load that, all I had to do is this:


  print "Loading sockets library..."
  
  -- load  luasocket namespace
  socket = require("socket")
  print ("Socket library version:", socket._VERSION)
  


From then on, I was able to poll for incoming connections, see if there was text arriving, or send outgoing text, all in Lua, using the socket library.

After that, for reasons I described earlier, all the data storage was in Lua tables, so the need to convert to/from C++ didn't arise.

I also used the coroutines functionality in Lua to make processing new players much easier. Rather than have the rather convoluted "nanny" routine that SMAUG uses, with all its states, and having to remember what the player typed last time through, it can be done by making the whole connection process into a coroutine, and then yielding when more input from the player is required. See below for how I did that:


function NewConnection (line, client)
local name

  Send (client, messages.welcome)
  
  -- get name
  while true do
    Send (client, "Your name? (Enter 'new' to create a new character) ...", true)
    name = coroutine.yield ()

    local ok, err = validname (name)
    
    if ok then
      name = capitalize (name)
      if name == "New" then
        break
      end -- special name
      
      if yes_no (client, "You are called " .. name .. ", right? ...") then
        break
      end -- they agreed to that name
      
    else
      Send (client, err)
      
    end -- good name entered
      
  end -- while getting name

  local char -- the character s/he is
  
  if name == "New" then
    char = NewCharacter (client)
  else
    char = ExistingCharacter (client, name)
  end   

  if not char then
    Send (client, "Press <enter> to restart the connection process ...")
    return
  end
    
  print (char.name, "has entered the game.")
  Send (client, "Welcome to " .. config.mudname)
  char.connected_time = os.time ()
  char.client = client  -- point our character to the controlling client
  client.char = char    -- tell the client which character it is
  char.playing = true   -- they are on now
  client.handler = CommandHandler

end -- NewConnection



Notice how I simply ask their name and yield until I get a response? The low-level TCP socket handler simply breaks input into lines, and when a line has arrived resumes the current coroutine with that line. This could be the "new player" handler, or simply the command processor.

We can do a similar thing to get a yes/no response from the player (as called from above):


-- get a yes/no reponse from the client
function yes_no (client, query)
local reply

  while true do
    Send (client, query, true)
    reply = trim (coroutine.yield ())
    
    if reply == "yes" or reply == "y" then
      return true
    elseif reply == "no" or reply == "n" then
      return false
    end -- if good reply
    Send (client, "Please reply 'yes' or 'no'.")
  end -- while loop
  
end -- yes_no


This sends the query, and then yields until it gets a reply. Then if the reply is not yes/y/no/n then it resends the query and loops. Nice and easy to see how it is working.

I'm not sure if Ruby has coroutines, and if not maybe consider Lua instead. A quick search on the web seems to indicate that Ruby does have coroutines, and probably an interface for TCP/IP as well, so that is probably all you really need.

Quote:

I am unsure exactly how to implement things ...


Welcome to the club! I am also thinking deeply about the best way of implementing (as is Ksilyan). A couple of things you might want to think about are:


  • How are you going to store data? One big file? Lots of small files?

    Here is one example of a problem area. I was initially planning to keep each player's data in its own file (like SMAUG does), but what happens if you want to (say) send mail to another player? Without his file loaded, you don't even know if he exists, or maybe does not accept mail from you, or is in the wrong faction, or something.

  • How are you planning to handle the difference between prototype objects (eg. the design for a short sword, or a level 5 naga), and the instances of them (eg. 100 players have the sword, there are 10 naga in a room)?

  • What, if any, event model do you want? For example, if I hit a naga with my sword. Who notifies other players that "Nick hits naga with sword"? The enactor (Nick)? The room? The naga? The player who is in the room with Nick? Maybe the act of hitting something raises an event, that other things in the room detect.



Good luck with the project, I hope you have lots of time on your hands. ;)

- Nick Gammon

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

Posted by Nick Cash   USA  (626 posts)  [Biography] bio
Date Reply #9 on Thu 03 Apr 2008 01:42 AM (UTC)
Message
I've actually come to a good point on this (finally) to ask more questions. I have sockets, logging, and database support programmed in C++. I'm at the point where I truly need to embed the interpreter before I continue for things to be as dynamic and amazing as possible.

Since most of my data is stored in a MySQL database, I see little reason to interface ruby and C++ explicitly other then the need for ruby to print messages to the socket on occasion, which only requires ruby to pass a string to a single C++ function. However, knowing I will have instances of rooms, objects, npcs, and perhaps other things allocated in C++ (all presumably with their own logic scripts), it seems like the wrong approach to take. The ruby embedding interface is pretty awful, and it gives me the option of losing control over my program and turning it over to the interpreter, or having to hard code every script I'd like to call, not to mention none of the scripts will have any access to data allocated in C++.

Is there a better solution? Does lua implement better? Should I work on this the other way around, programming most everything in ruby and extending the ruby code so sockets and what else I have are in C/C++?

I don't really want to be dependent on foreign libraries, such as SWIG. If there isn't an elegant way to do it I'll just have to make one.

~Nick Cash
http://www.nick-cash.com
[Go to top] top

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #10 on Thu 03 Apr 2008 02:59 AM (UTC)
Message
Ked's earlier reply is still relevant. You need to decide if you want most of your code in Ruby (or Lua or whatever), and extend that will some C++ code, or have most of your code in C++ and call a few scripts here and there to do things like mob progs.

Lua has excellent interfacing methods (and they are well documented too), because it was really designed to be interfaced from the start. You can do what MUSHclient does, and have most code in C++, and call Lua scripts from time to time.

Or, you can do what I did with an experimental Lua MUD, and have virtually everything in Lua, with some support code in C++ where required, for example, sockets.

If you go the hybrid approach you have problems with getting stuff (eg. details about what a mob is currently doing) from the C++ side to the scripting side, and back again. That is why I felt more comfortable doing virtually everything in Lua.

- Nick Gammon

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

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #11 on Thu 03 Apr 2008 04:46 AM (UTC)
Message
I agree that it's extremely important to make a decision about where the data lies, and then stick to it. Having data spread out over the two languages will be very messy. If the data is C++, you need to have a good API in Lua for manipulating it.

I never really did figure out a way to handle this that I like a lot. Storing everything in Lua is very good at the beginning but I find it hard to grow due to the lack of compile-time checking. But storing it in C++ -- which gets you compile-time checking -- means you lose part of the point of using Lua in the first place, which is the ability to rapidly add fields and other data at runtime.

I'm thinking that you could get some degree of runtime checking by using metatables, or a static analysis tool of some sort, but the former might be expensive in overhead whereas the latter would be difficult to implement.

A hybrid approach could be made to work if you use metatables cleverly, but as Nick said you'll have quite a bit of work to get data from one end to the other.

The Quake2 engine used the following rough separation:

1. Core engine (you couldn't touch this)
Contained fundamental physics of objects: positions, time callback pointers, collision callback pointers, velocities, etc.

2. Game logic (you had the C .dll source for this)
Implemented the above callbacks; implemented the command handlers for pressing keys and so forth.



Basically, the core engine provided the framework, and you added your game-specific stuff to the game logic DLL.

In a MUD setting, I suppose this would be comparable to laying down the physics of rooms, exits, world position, etc. in the core engine (presumably the C++ side of things) and then having everything else (HP, mana, etc.) be in Lua.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

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

Posted by Nick Cash   USA  (626 posts)  [Biography] bio
Date Reply #12 on Thu 03 Apr 2008 08:32 PM (UTC)
Message
The Quake2 engine sounds similar to what I would like. The problem I'm having I guess is wrapping my head around how exactly this will all work. Are you suggesting the logic and everything is stuck into a DLL that the engine calls? This seems like a far more elegant solution, but I am unsure how to use Ruby to generate a DLL that will interface with C++.

This seems like it would work well in general for players, but knowing I will have NPCs and other things allocated, how would the Ruby code in the DLL get access to that data?

This may be the most complex design topic I've ever faced. So very interesting, yet confusing at times.

~Nick Cash
http://www.nick-cash.com
[Go to top] top

Posted by David Haley   USA  (3,881 posts)  [Biography] bio
Date Reply #13 on Thu 03 Apr 2008 08:52 PM (UTC)
Message
The Quake2 system used a DLL because that is the easiest (only?) way in C to swap out the game logic while not letting modders touch the core engine. When you installed a mod, you would use a different DLL, which implemented the game callbacks as it saw fit.

For instance, to make bouncing rockets, you would change the source code for the rocket collision callback, and recompute the new velocity vector based on impact vector etc.

For a scripting language -- Ruby, Lua, whatever -- you probably wouldn't use the DLL approach because you can load a script when the program starts. So the script becomes the DLL. That script would (presumably) load up other scripts to implement the game logic as needed.

I think that players and NPCs would be treated the same way. For example, your core engine could have the notion of a "game entity" which could be an object, a room, a character (I prefer the term 'actor' personally), etc. Let's consider actors: an actor could have a callback for damage being inflicted on that actor. That callback would be implemented in the scripting language by a function called (e.g.) handle_damage that takes as arguments (e.g.) the actor inflicting damage, the victim of the damage, the amount of damage being dealt, the type of damage, etc.

For accessing data, Quake2 solved it by having a C structure the first part of which you could not touch. It used a clever trick of C whereby you can "add" fields to a structure by having another structure the first part of which is the original structure but that adds its own fields. Since the fields are laid out in the same order, anything that uses the new structure can be oblivious to the fact that there are new fields, because the fields it knows about will be at the same memory offsets from the structure beginning.

If that didn't make any sense, basically Quake2 sticks all data in the same C structure, and you have access to it from C.

Scripting languages make things complicated because you actually have two separate spaces in which to store data. One solution is to have it all in C++ and use accessors to grab the data; that is complicated because you need to translate the data appropriately etc. Another solution is to put everything in the scripting language, but then you need to access it from the C++ side, which also entails translation.

I think that in practice, however, the core data will not be accessed that often by the game logic. There is a relatively small number of functions that need to know about the core concepts, but a remarkable amount of logic can be implemented with relatively little access to actual core data. A combat system, for instance, doesn't need to know that much about the core data. (That depends, I suppose, on what data is considered "core"...)

And yes, I agree: this is a very hard design problem... I've been thinking about it for many years and have yet to find a solution that I truly like. I suspect though that this might be a case of "analysis paralysis" and the best thing might be to just forge ahead and see what happens, learning from mistakes as necessary.

David Haley aka Ksilyan
Head Programmer,
Legends of the Darkstone

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

Posted by Nick Gammon   Australia  (22,975 posts)  [Biography] bio   Forum Administrator
Date Reply #14 on Thu 03 Apr 2008 08:57 PM (UTC)

Amended on Thu 03 Apr 2008 08:58 PM (UTC) by Nick Gammon

Message
I presume he means a script that the engine calls, written in Ruby. Thus the game engine fires up, loads and compiles the script, accepts incoming connections, and then looks for appropriate functions in the script file to handle them (eg. function "HandleNewConnection").

As for the variables, well this is the big issue. Once you have a script engine you have multiple variable "spaces". MUSHclient is a classic example of that, where there is the C++ variable space which holds things like the scrollback buffer (amongst many others), and the variable spaces for each script engine (eg. one per world, and one per plugin).

You need to provide some sort of interface to get/receive from one space to another. For example, in MUSHclient you can use GetInfo, to find out, in a script, things that are stored in the main C++ variables. Then you might use SetVariable / AddTrigger / AddAlias to let a script cause C++ variable(s) to be changed. You might make interfaces that work the other way, in MUSHclient plugin callbacks are effectively that, as the main C++ code calls a plugin script (eg. on world connect) giving it the opportunity to modify script variables.

The postings I did recently about adding Lua to SMAUG show how you might interface a script engine with a C engine. Again, I had to make interfaces that let each "side" talk to each other.

You might want to minimize the amount of information that needs to be exchanged between script side and C++ side. One way is to store almost everything on the script side, or alternatively store most things on the C++ side.

There are pros and cons for both approaches, some considerations would be:


  • Speed
  • Flexibility
  • Whether recompilation is needed if you change something
  • Ease of coding
  • Ease of maintenance
  • Ease of debugging
  • Portability
  • How errors are handled
  • Reliability
  • Memory use


In my SMAUG implementation I actually used a separate script space per player. As David and others have pointed out, this is rather inefficient of memory, however it has certain advantages. Ease of coding, ease of recovery from errors that only affect one player are a couple of them.

However this approach would break somewhat in situations (like combat) where you needed simultaneous access to variables for multiple players / NPCs.

[EDIT] My reply was being written as David posted his, so I don't address anything David said above.

- Nick Gammon

www.gammon.com.au, www.mushclient.com
[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.


63,080 views.

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

It is now over 60 days since the last post. This thread is closed.     [Refresh] Refresh page

Go to topic:           Search the forum


[Go to top] top

Quick links: MUSHclient. MUSHclient help. Forum shortcuts. Posting templates. Lua modules. Lua documentation.

Information and images on this site are licensed under the Creative Commons Attribution 3.0 Australia License unless stated otherwise.

[Home]


Written by Nick Gammon - 5K   profile for Nick Gammon on Stack Exchange, a network of free, community-driven Q&A sites   Marriage equality

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

[Best viewed with any browser - 2K]    [Hosted at HostDash]