ID:154043
 
I am probably sure I've babbled about this in the past, but I think I'm at a point where I can actually begin to do some serious coding/experimentation, so I'll rehash it one more time to see if I've missed anything...

In a nutshell here's the game idea, followed by the problem in question:

I'm thinking of having a ship map (probably start with just a bridge section) where each player who is a 'crew member' on that ship performs a specific function (helm, science, tactical, engineering, etc.) and it is necessary to work as a team to achieve some goal (explore, rescue, defend, etc.), either with other 'ships' or against them.

(Yes, yes, I know some of you are going to say "but no-one will want to play as a team in a sci-fi game! They'll all want to be captain!" - and I know that is a possibility, but it won't stop me that easily...)

Instead of hosting a big graphical universe map (which would be bandwidth prohibitive anyway), I was thinking of a 'universe server' - essentially a DreamDaemon server (correct me if I get the terms mixed up) that stores a 3D array of coordinates representing the universe. This server tracks and updates the locations of all the ships and planets and what-not in the universe. This info is made available to ships as navigation data, science data, etc...

Now here is a part I am unsure about - what are the opinions of the following two implemtations:

Client/Server - where the same 'universe server' also is the 'ship server' (maybe as a separate daemon for each ship on the same computer), dealing with all the processing required for people to move about and function on the ship, as well as tracking the ship(s) through the universe.

I'm not sure if I like this idea because of all the potential processing involved - especially if a lot of ships (and people) are logged in. But it does keep everything in one place...

Server/Server - the 'Captain' actually hosts a 'ship server' for his ship on his own computer (registerd with the universe server of course) that all the 'crew' joins (logs into). This ship server communicates with the universe server for tracking ship position and getting various mission-related data (encounters?).

I am leaning a bit towards this later concept because it puts all of the ship-centric processing on the client (which isn't much more than moving the players around and communicating with the universe server at this point in development), and leaves the universe to tend to itself - which will have enough to take of on its own. A bad side would be if someone hosts a ship on a 56K line through AOL and has a crew of 10 - any lag might make it unplay-able. But I would not recommend this to anyone with less than ISDN speed anyway...

Questions, comments, improvements?
I'd go with server/server, myself. A large universe (depending on how dynamic it is) would take a dedicated server, if not more. BYOND sends a lot of information, which may be quite superfluous in this type of game where all you know is what you're able to gather from equipment.

-AbyssDragon
In response to AbyssDragon
And for testing purposes I will keep the initial universe at 1000x1000x1000 (for the future off-chance that I decide to make a graphical map for some reason), and expand with other 1K-cubed (?) universes connected to each other. Ideally these 'quadrants' will hand off a ship to its neighbor quadrant to give the possibility of an near infinite universe to explore in...
In response to digitalmouse
Ooh, ooh, I have an idea! I can't tell whether it applies because server stuff is beyond my experience though. Use what Noctis uses and have a fractal universe! That means you don't have to store anything about the universe, just load it up based on the rand_seed(). It will always be the same, because random numbers with a set random seed are always the same. Just use some number like x*y*z coordinates to get the number for the random seed.

Okay, I don't think that makes sense.

Basically, whenever you load up a planet from scratch, set the random seed to the planet's coordinates (like x * y * z).

Then, load the details about the planet randomly. The "random" statistics will be the same every time you load the planet, because the random numbers always come out the same. So long as the planet's location never changes.

You can do all kinds of features in the galaxy like that, and because it's fractal based, you can go as deep as the programmer (you) is willing to let you go.

That eliminates the need to store any information about the universe on a server somewhere. All you need to keep track of is which ships are where...

Well, I don't know if that helps...but it's nifty anyway.
In response to Foomer
Foomer wrote:
Well, I don't know if that helps...but it's nifty anyway.

True - I like the idea alot. But, in theory, the planets will be revolving around stars (albeit slowly), so I don't know how much of that can be applied. At least the random-ness of the initial universe creation could be done I suppose... my biggest concern in this post is how best to deal with server/server links - whether it be a ship-to-universe, ship-to-ship, or universe-to-universe communications...
If playability depends on the connection speed of the player acting as captain, that would go a long way towards solving the "who gets to be captain" debate...

I've given a lot of thought towards this sort of game, so if you need anyone to bounce ideas off of, feel free to impose.
In response to Lesbian Assassin
Lesbian Assassin wrote:
I've given a lot of thought towards this sort of game, so
if you need anyone to bounce ideas off of, feel free to
impose.

Thanks for the offer, and expect a lot of bouncing in the future (err...that did not sound right, but you get my meaning).

Although the replies here have been few, I think I will take a crack at the server/server concept. By just moving all the character-related logic to a separate 'ship server' will cut down on a lot of the universe server's responsibility. And yes, if you have only a 56K modem and a crew of 10, you may not be captain very long... there could be enough lag that you would have a mutiny and never know it until it was too late! But now that I think about it, even guys with slow connections shouldn't be to bad as long as the bridge and player functions do not become too complex.

Going the server/server route also means that if I make the 'ship server' generic enough (basically the map changes, but all other logic remains), this type of server could also be a world-server (including moons, asteroids, Dyson spheres, etc.), spacestation-server, wormhole-server, etc. These later servers would probably be best hosted on dedicated server machines (for example all world-servers on one computer, spacestation-servers on another, etc.), unless someone would like to host a world-server locally (but I don't like that because the 'world' would not likely be online all the time...imagine a world that appears and disappears in the universe).

This now takes me to: how would one track the player as it moves from ship to ship, or ship to world, etc.? When the idea of just a ship-server came to me, I thought it would be easy enough to just have the player log into their ship when they want to play. But now with the possibility of these other types of servers, that doesn't make sense - no reason to have the player try to remember where to login to the universe. Also giving them control of where they can login would easily lead to abuse (get killed on the planet? No problem, just log back into your ship!).

So I guess there needs to be a central player tracking function in the universe server that deals with entering the universe. At that point the universe could look up in a table to see where that player last was, then transfer them to the server they belong in...

And again, this leads into another question of how to deal with non-persistent ships in a persistent universe - do we force the ship back to a starbase or some similar 'port of call' before logging off, or just put the ship in some sort of stasis when the captain is offline?

Ugg...while all this theory babble is nice - implementing these ideas comes down to what to do first! And how best to do it. Right now, I'm playing with Z's RPG tutorial to refresh my memory on how to make maps and get characters to move around in them. Once that is going well, I can then look at the universe server and ship-to-universe communications...

In response to Foomer
That does sound like an interesting idea, but how do you handle players interacting with the planet? If they change it from its initial state then the planet will reset each time it is loaded.

I suppose it would still work for unexplored planets but most people wouldn't care if unexplored planets remain the same :p

It could be very useful for loading solar systems and other unchangeable (yet initially random) things though (assuming there are no death stars in the game...).

Actually, now that I think about it this could still save a lot of memory, at least when your talking about something with a billion places. Using it to "store" information about the planets size, climate, radius of orbit, and other unchanging aspects could really add up.

I may have to steal this idea for map generation, it would beat actually saving a good map that was created...
In response to English
English wrote:
That does sound like an interesting idea, but how do you
handle players interacting with the planet? If they
change it from its initial state then the planet will
reset each time it is loaded.

I think in my case I would use random universes for the initial seeding of the persistent universe, spawning the appropriate number of 'world-servers' (daemons) on the fly when the universe is created. If the game only lasts for 1 month (for example), then I would just kill off the old universe and randomly recreate the new one to start a whole new game...

I am hoping to be able to just start with a single universe (using a 1K-cubed randomized array), and grow dynamically from there. As starships reach the 'edge' I would spawn a new random 'quadrant' that connects to the previous one. Then *never* shut down the whole universe (ideally)...
In response to digitalmouse
Ooo!! New thought! What about for each race of spacefarers there is a separate 'quadrant' as 'home'? (Randomly spaced throughout a particular 'universe' (metaverse?))

Then as they explore other quadrants they may run into other space travelers (other players/ships) doing the same thing - connecting the various quadrants between them!

Hmmm...
In response to English
English wrote:
That does sound like an interesting idea, but how do you handle players interacting with the planet? If they change it from its initial state then the planet will reset each time it is loaded.

You can save the changes to the planet like you would normally save anything else. Just the planet for a savefile after loading it, and apply any necessary changes. Even if you want to "destroy" a star in the game, you can just have players load the savefile for [star x, y, z] before it will tell them what they see at x, y, z, and if the savefile says that the star no longer exists, then that's what they see, a star that no longer exists.

Actually, now that I think about it this could still save a lot of memory, at least when your talking about something with a billion places. Using it to "store" information about the planets size, climate, radius of orbit, and other unchanging aspects could really add up.

I may have to steal this idea for map generation, it would beat actually saving a good map that was created...

Since it uses fractal stuff, the universe can effectively be infinite, since fractals are infinite. All you really need to support it is a number grid that's large enough. (2,000,000,000 x 2,000,000,000 x 2,000,000,000 tends to be the largest, unless you can get some 8 byte numbers going somehow). The only real filesize drain is whatever you store in savefiles. So the more changes you allow in the game, the larger the same will end up being.

I was going to write an article about this for BYONDscape, but I doubt by own ability to write it properly. If someone else wants to expand on this with some ideas, go ahead.

One thing that I've decided this could be especially useful is for faster loading of map files, potentially. Right now I've barely started a little game that generates maps (similar to Spuzzum's text-only random map generator) based on about 10 variables and a random seed. If the player doesn't specify a random seed when generating the map, the map chooses a random seed between 1 and 99999999 or something. Then, when the player saves and loads the map, no map data is actually saved. It just saved the random seed, and uses that to generate the map next time the player loads it. All objects can be saved to a list and replaced on the map after that.

[Edit]

Here's an article at GameSutra that discusses what I'm talking about:

http://www.gamasutra.com/features/19990917/infinite_01.htm
In response to digitalmouse
But, in theory, the planets will be revolving around stars (albeit slowly), so I don't know how much of that can be applied.

No problem. Instead of basing the generation code on the planet's current location, just give every planet a unique sequential ID number, find a good hashing function that will convert it to a very different number, and use that as the basis for your calculations.
In response to digitalmouse
Ah! Here's something that could use a bit of public input...

Ships of 'Enterprise' size need room to move about, and putting a substantial amount of the universe in one quadrant (say the whole Sol system) makes things a bit crowded to manuever around in.

I guess this is a question of scale. Should a 1000x1000x1000 'quadrant' be 1 light-year? half ly? quarter ly? 1 AU? half-AU? Should I even bother limiting the 3D universe array to only 1000^3?

There needs to be sufficient resolution to allow ships in the same quadrant (or within short distance sensor range to each other) to see motion of other vessels relative to themselves in tactical displays... but not so 'high-res' that it takes hours in real-time to cross the quadrant at high speed. I would think one quadrant should be crossable at top speed in a maximum of 7-10 minutes in real-time. 3-5 minutes may be more practical.

I was trying to remember how long it took StarTrek ships to cover the distance to the nearest start (about 4-5 ly) at max speed - and came across a Warp Speed calculator that says 5 ly at Warp 5 (214 times the speed of light) would take a little over 8.5 days... Warp 9 (1516 times speed of light) for the same distance is about a 1 day trip... that same calculator suggested 2 minutes, 40 seconds to cross the solar system at Full Impulse, so that may be a good benchmark for travel time across the quadrant, since it nears my earlier suggestion of 3-5 minutes...

Comments, thoughts?

In response to digitalmouse
Yes, persistence is where you run into many pitfalls. I'm getting ready for work now, but I will post my thoughts on the subject later.

I've always thought it would be neat to make a space-sim based on a universe like AD&D's Spelljammer... each "solar system" is a self-contained void suspended within an impenetrable sphere of black crystal... the crystals themselves float and bob in a magical flow. Ships (many of which resemble sailing ships) navigate both the void inside the crystals and the flow without... some pseudo-Victorian ideas about physics mean that any ship has enough gravity to hold people to the deck, and capture a sizable atmosphere, too.
In response to Lesbian Assassin
if I get the generic routines right for the client-server and universe-server coding, this universe model could easily apply to a SpellJammer universe as well... in fact I'm already thinking about a sailing ship sim with a similar layout: a client run 'sailing ship-server' that interacts with 'island-servers' (which would include continents since they could be thought of as very big islands), and are tracked by an 'ocean-server'... instead of 'short-range sensors' you would have 'view to horizon'... in fact this might be easier to do since you really would not need the 3D universe tracking (unless you wanted to track ships that were sinking, hot-air ballons, or underwater treasure...
In response to Foomer
Someone brought up a point that I'm curious about now. Are the random numbers generated by a set rand_seed() based on the program, or do they use variables in the computer running the program?

If I generate something based on rand_seed(1000) on one computer, will it generate the same exact thing for every other computer?
In response to Foomer
It is system dependant, so it may not create the same series of numbers on varying systems. Im trying to work out one of my own at the moment.
In response to Flick
Is it possible to setup a "random" number generator based on the code then? (It probably is, I just don't know how they work.)
In response to Foomer
Foomer wrote:
Is it possible to setup a "random" number generator based on the code then? (It probably is, I just don't know how they work.)

I made a Fibonacci-based pseudo-random number generator of my own, mostly as a little exercise, but it repeats its sequence after a few dozen numbers, so it's of little use.


/This is a Fibonacci-based pseudo-random number generator.
// The results will seem fairly random, but there is the added advantage
// that the same rolls will *always* occur in the same order. There is
// no difference between operating systems, either.

//If you want to get a different series of random numbers, just change
// the three seeds below:

var/first_seed = 123
var/second_seed = 456
var/third_seed = 789


proc/pseudorand(min, max)
var/first_num = first_seed
var/second_num = second_seed
var/third_num = third_seed

var/first_digit = 0
first_digit += round(first_num/100)*100
first_digit += round(second_num/100)*100
first_digit += round(third_num/100)*100
first_num %= 100
second_num%= 100
third_num %= 100
first_digit %= 1000

var/second_digit = 0
second_digit += round(first_num/10)*10
second_digit += round(second_num/10)*10
second_digit += round(third_num/10)*10
first_num %= 10
second_num%= 10
third_num %= 10
second_digit %= 100

var/third_digit = 0
third_digit += first_num
third_digit += second_num
third_digit += third_num
first_num %= 100
second_num%= 100
third_num %= 100
third_digit %= 10

var/floating_point = (first_digit + second_digit + third_digit) / 1000

var/num = round( ((max - min) * floating_point) + min)

first_seed = second_seed
second_seed = third_seed
third_seed = first_digit + second_digit + third_digit

return(num)


mob/verb/test_pseudorand()
pseudorand(1,1000)

var/num = 1
while(first_seed != 123 || second_seed != 456 || third_seed != 789)
pseudorand(1,1000)
num++
usr << num