Welcome, Guest. Please login or register.
Did you miss your activation email?

Login with username, password and session length

 
Advanced search

1057461 Posts in 42961 Topics- by 34894 Members - Latest Member: ReverendTed

October 25, 2014, 08:21:32 PM
TIGSource ForumsDeveloperTechnical (Moderators: Glaiel-Gamer, ThemsAllTook)Best form of IPC for a decentralized roguelike? (linux, maybe windows)
Pages: [1]
Print
Author Topic: Best form of IPC for a decentralized roguelike? (linux, maybe windows)  (Read 853 times)
SplinterOfChaos
Level 3
***


hakusa@gmail.com
View Profile Email
« on: February 11, 2012, 03:18:45 PM »

I've got a project to create a roguelike that in some way abstracts the UI from the engine and the engine from map creation, line-of-site, etc. To narrow the focus, i first want to just get the UI (player's client) and engine working.

My current idea is to make the client basically a program that decides what one character (player, monsters) will do for its turn and waits until it can move again. So each monster has a client, and so does the player. The player's client prints the map, waits for input, sends it to the engine, and tells the player what happened. The monster's client does the same except without printing the map and using AI instead of keyboard input.

Before i go any futher, if this seems somehow an obfuscated way of doing things, my goal is to learn, not write a roguelike. It's the journy, not the destination.

And so i need to choose what form of ipc fits this model best.

  • My first attempt used pipes because they're simplest and i wrote a UI for the player and a program to pipe in instructions such as where to put the map and player. While this works, it only allows one client--communicating through stdin and out.
  • I've thought about making the engine a daemon that looks in a spool where clients, when started, create unique-per-client temp files to give instructions to the engine and recieve feedback.
  • Lastly, i've done a little introductory programing with sockets. They seem like they might be the way to go, and would allow the game to perhaps someday be run over a net. I'd like to, if possible, use a simpler solution, and since i'm unfamiliar with them, it's more error prone.

I'm always open to suggestions.
Logged

mihai
Level 1
*

meeshoo_17
View Profile WWW Email
« Reply #1 on: February 12, 2012, 08:55:34 AM »

Let me see if I understand. So you have this server process in which all game logic takes place. Then you have many clients which connect to it through a protocol. Some of these clients are AI and one (or maybe more, why not) are human players. When the game runs, the server iterates through all the clients connected to it and asks them for their next input (move). After it collects all input from everybody it can simulate a complete game turn. Is this how your game works?
Logged

SplinterOfChaos
Level 3
***


hakusa@gmail.com
View Profile Email
« Reply #2 on: February 12, 2012, 10:16:23 AM »

Yes but client X-1 has to move before client X can so X knows what the whole board looks like before planning out any sort of strategy.

I had a discussion with a friend last night about D&D and i think it'll make more sense if i explain it this way: think of the engine is the dungeon master. The players tell the DM what move they want to make and the DM tells them what the outcome was. The analogy could go futher: the character, rule, and (i forget the third'sname) books could be separate databases referenced by the DM.

So in terms of IPC, the DM sets the map, the client reads it and strategizes. The map would probably just be a regular file in this case.

Quote
Then you have many clients which connect to it through a protocol

I don't know how they'll connect yet. No code has been written. I did have an experiment using pipes, but it didn't seem like the right way to do it.
« Last Edit: February 12, 2012, 10:22:09 AM by SplinterOfChaos » Logged

BorisTheBrave
Level 10
*****


View Profile WWW
« Reply #3 on: February 12, 2012, 10:16:54 AM »

You should probably abstract the connection, you don't literally want every monster to be a separate process, and so you can test the game before you've got the IPC sorted.

Sockets are pretty much the standard way to communicate, and I think they are more similar between platforms than pipes are. As you say, they are also a proper "duplex" connection, which makes a lot of things easier.

If you weren't explicitly looking to learn sockets, I'd recommend using a library. ZMQ, for example, is a lightweight abstraction of sockets that would be pretty handy for you, hiding some of the boring parts. You'll probably also need a serialization library.
Logged
mihai
Level 1
*

meeshoo_17
View Profile WWW Email
« Reply #4 on: February 12, 2012, 12:46:35 PM »

Well, if I were you, I would make the DM be a service (as in a web service/WCF service, whatever) and the clients be applications which communicate with the service through standard protocols like SOAP. This way you could run it all on a computer, or use it over web. Of course you can do it with sockets, but I find it a little overboard for a turn based game like this.
Logged

_Tommo_
Level 8
***


frn frn frn


View Profile WWW
« Reply #5 on: February 12, 2012, 01:08:50 PM »

Well, if I were you, I would make the DM be a service (as in a web service/WCF service, whatever) and the clients be applications which communicate with the service through standard protocols like SOAP. This way you could run it all on a computer, or use it over web. Of course you can do it with sockets, but I find it a little overboard for a turn based game like this.

well, SOAP is much more "overboard" than socket, as it's exchanging xml-serialized objects over a HTTP connection over a socket.
Much more overboard, indeed, while much easier to code Gentleman
Logged

mihai
Level 1
*

meeshoo_17
View Profile WWW Email
« Reply #6 on: February 12, 2012, 01:19:23 PM »

well, SOAP is much more "overboard" than socket, as it's exchanging xml-serialized objects over a HTTP connection over a socket.
Much more overboard, indeed, while much easier to code Gentleman

Sorry about not specifying the meaning of "overboard" in my statement (I do know what SOAP is, I use it at my job from time to time). By overboard I meant easy and fast to implement. Why do complicated things in a turn based game in which speed is not essential. On the other side, communication issues are easy to debug in this scenario, as information is just strings of plain xml.

I would see anything more than this as early optimization. If however an unacceptable slowdown is noticed, since game code would be separated from data transmission code, it can be optimized/replaced with something fast.

Logged

SplinterOfChaos
Level 3
***


hakusa@gmail.com
View Profile Email
« Reply #7 on: February 12, 2012, 03:34:02 PM »

Looking into SOAP... Wikipedia says "a protocol specification for exchanging structured information in the implementation of Web Services in computer networks." OK, sounds interesting. "It relies on Extensible Markup Language (XML)" OH GOD NO!

I don't know what it is, but XML makes me want to bash my head in with a hammer. It's like a middle-ground between difficult to read for a human and difficult to read for a computer.

But really, i want you to be able to take the log of messages passed between the DM and clients to look like an actual game of D&D with simple messages passed back and forth like "move north" or "cast freeze on koboltA". This type of message is easy for both humans and computers to be programmed to understand.
Logged

mihai
Level 1
*

meeshoo_17
View Profile WWW Email
« Reply #8 on: February 12, 2012, 03:57:14 PM »

SOAP is the packaging, and it is XML. However, the whole content of that xml can be a single string with your message if you want it to be. It is not like you have to build a sophisticated xml or something.

Example here.

Anyway, if you don't want it, then indeed pipes (which are basically using files internally) are your best bet if you want something simple. However either you are going pipes or sockets, you will still have to design and implement a simple communication protocol because your communication is asynchronous. You must have a handshake logic(which is basically a client registering into DM) and then a logic for message synchronization like this:

1. client locked in waiting for input
2. server sends current map to client and locks for response
3. client does all internal strategy logic and sends response and locks again
and so on.

(It's been a while since I haven't worked with piped on linux systems Smiley)

Another solution that actually uses sockets underneath is RPC (remote procedure call). This one uses proxy object within a process to call methods on an object found in another process, or even on another machine. Once all is setup, you won't basically see it in your code differently, it is just like calling methods on any other internal object instance. This will save you the process of handling all communication protocol because you can put all in a simple method call like GetActionForMapState(map_state) made by DM on the client proxy.

Here is a useful explanation I think: http://www.linuxjournal.com/article/2204
Logged

mcc
Level 10
*****


glitch


View Profile WWW Email
« Reply #9 on: February 12, 2012, 05:11:27 PM »

So...

1. I have heard very good things about http://www.zeromq.org/ . What is neat about that is it is a message passing framework which can be used for IPC or cross-thread communication or network communication.

2. Soap is often very easy to use (it depends on what your programming environment is-- it will be harder to use with C++) but you should be aware of the problems SOAP can have when there are NATs in the mix.

3. I think the basic thing you're trying to do is not a good idea. I do not understand what you are gaining by separating out these components into actually separate processes. The only advantage I see to this is to create the possibility of some of these components running on different machines. And even this is something that only makes sense in certain limited ways (i.e. allowing players to connect their own entities to the world is neat, but having your own hosted in-game elements be on different machines is pointless). If your goal is to have the different components of the game (engine, maps, line of sight) be abstract and separable, that's great! There are several good ways to accomplish this goal that do not require the abstract elements to be in different processes, and putting them in different processes opens you up to an entire class of concurrency-related bugs that there is no justification for living with in a turn-based rpg.
Logged

My projects:<br />Games: Jumpman Retro-futuristic platforming iJumpman iPhone version Drumcircle PC+smartphone music toy<br />More: RUN HELLO
eclectocrat
Level 5
*****


Most of your personality is unconscious.


View Profile
« Reply #10 on: February 12, 2012, 06:02:39 PM »

Don't settle on an implementation right now. Just make an abstract interface that can be specialized for various comm types. Start out with simple threads and queue's and you can later experiment with more complex stuff like IPC.

Code:
class CommPort
{
public:
  // ...
  virtual Message* decodeNext ( );
};
class ThreadCommPort : public CommPort;
class PipeCommPort : public CommPort;
class SocketCommPort : public CommPort;

I just pulled this out of my ass, but I used a similar structure when creating an audio server that could read from several threads or processes at the same time. You've got to start by defining an internal message format that all comm ports will decode to.

Good luck!
Logged

I make Mysterious Castle, a Tactics-Roguelike
SplinterOfChaos
Level 3
***


hakusa@gmail.com
View Profile Email
« Reply #11 on: February 12, 2012, 06:27:00 PM »

SOAP is the packaging, and it is XML. However, the whole content of that xml can be a single string with your message if you want it to be. It is not like you have to build a sophisticated xml or something.

Example here.

That still doesn't look like the script in a D&D game.

Quote
Anyway, if you don't want it, then indeed pipes ... if you want something simple.
Smiley The simplist solution that correctly solves a problem is always the best.

Quote
You must have a handshake logic(which is basically a client registering into DM) and then a logic for message synchronization like this:

1. client locked in waiting for input
2. server sends current map to client and locks for response
3. client does all internal strategy logic and sends response and locks again
and so on.

(It's been a while since I haven't worked with piped on linux systems Smiley)

Actually, this is the part i haven't looked into enough. I'm not sure how the executable the player runs will either start the server if it hadn't been already and be the UI. The only difference between the player's client and that of the moster's should be that the player has a UI and no AI (though, both could be hacked in/out) so monster clients should be able to spawn a server equally. Or, i could go the rout of every client not spawned by the server spawns a UI which only draws the screen for NPCs, and accepts input for players then passes that input to the client.

Quote
Another solution that actually uses sockets underneath is RPC (remote procedure call). ...

That might be interesting to learn about... Not for this project's current state, but in the future. But it'd be easy to just send a large char[] holding more or equal to twice the largest (implemented) command.


So...

1. I have heard very good things about http://www.zeromq.org/ . What is neat about that is it is a message passing framework which can be used for IPC or cross-thread communication or network communication.
That looks really, really interesting. I especially love their political diatribe in the introduction: http://zguide.zeromq.org/chapter:all

Does it require that the client and server both use its library? It'd be interesting to write/rewrite DMs and clients in different languages, using different libraries. (That way, i could test it out on a working system instead of building the game around it.)

Quote
3. I think the basic thing you're trying to do is not a good idea. I do not understand what you are gaining by separating out these components into actually separate processes. The only advantage I see to this is to create the possibility of some of these components running on different machines. And even this is something that only makes sense in certain limited ways (i.e. allowing players to connect their own entities to the world is neat, but having your own hosted in-game elements be on different machines is pointless). If your goal is to have the different components of the game (engine, maps, line of sight) be abstract and separable, that's great! There are several good ways to accomplish this goal that do not require the abstract elements to be in different processes, and putting them in different processes opens you up to an entire class of concurrency-related bugs that there is no justification for living with in a turn-based rpg.

As i said, the goal is to learn, not to create a rogue. Therefore, it's irrelevant whether i fail or succeed, it's flawless or buggy. Also, the idea that a program should be monolithic, bloated, and do everything is one i cannot get behind. Programs should be small, do their thing, and do it well. They should work together with well-defined interfaces that allow parts to be modifiable and interchangeable without leading to system instability. Not only is this a concept that seems to no longer be taught, but no longer fallowed as many of the programs we use are incredibly bloated, monolithic, and do everything, but nothing well.

But since i was taught to build monolithic programs and games are rarely done in any other way, i thought it'd be a neat experiment. Besides, the features i've been thinking about, like connecting multiple players, are side-effects of doing it this way, not goals.
Logged

SplinterOfChaos
Level 3
***


hakusa@gmail.com
View Profile Email
« Reply #12 on: February 12, 2012, 06:32:52 PM »

Code:
...

I just pulled this out of my ass, but I used a similar structure when creating an audio server that could read from several threads or processes at the same time. You've got to start by defining an internal message format that all comm ports will decode to.

This is similar to how brogue abstracts between an SDL, nCurses, and OpenGL renderer. I thought i'd do that or write completely separate clients for each, which would allow different features like pop-up text-boxes in ncurses, drawn over the map, or pop-up windows in SDL or OpenGL.
Logged

Pages: [1]
Print
Jump to:  

Theme orange-lt created by panic