I'm working on a small, simple game (mostly to learn what's new in Java 8 and JavaFX). One of the features I have is the ability to seed the game's random number generator so you can play roughly the same game as a friend on a different system (think Minecraft Maps or The Binding of Isaac games).
I would like to add the ability to save the game to be resumed at a later time. After looking over the documentation for the java.util.Random class, I can't find a way to get the current seed of the random number generator. The only ways I have come up with to restore the random number generator after saving the game is to either access the seed via reflection at save time and use that, or to seed the initial seed at load time and just call nextInt() over and over again until we've rolled forward the random number generator enough to be where it was before the game was saved.
First of all, as #user2357112 points out, Random implements Serializable, and does so by writing the seed field (along with the nextNextGaussian and haveNextNextGaussian fields). Have you tried simply serializing it? That should 'just work'™. Other serializers, like Gson, also work. gson.fromJson(gson.toJson(r), Random.class); returns an identical object.
You don't necessarily need the same Random instance, just a consistent one. You could simply call nextLong() and write that value to your save file as random_seed or whatever. Then just initialize a Random instance with that seed, and now all runs loaded from that file will behave the same. If you wanted, you could even reset the Random instance in your currently running game to the same seed too.
On the other hand if you're generating maps or other seemingly-constant content randomly and want it to persist between loads, I'd think you'd do better to simply seed your Random at the start, and save that value like you describe. To save on computation you could do this in chunks smaller than a whole level. For example, split each level into 10ths, and use (and save) a different seed for each 10th. Then you just have to generate the portion the user's on now, and not the parts they've already crossed. If you were to only save the current state like you propose, the user couldn't go backwards in the map (which might not be a problem for your game in particular, but wouldn't be a great practice in general).
UX caveat: saving your game's randomness seems potentially over-engineered. As a user, I don't generally expect a save file to persist randomness. In fact, sometimes players take advantage of that, for instance if they die in a random encounter right after saving, reloading the game doesn't immediately drop them back into the same encounter. I would consider just leaving your game's Random unseeded and let each game be slightly unique.
Related
I'm trying to make a randomly-generated 2-d game, which I plan to do with a list of terrain to the right of the spawn point and a list of terrain to the left of the spawn point. However, I need these lists to not have a length limit, as I want the world to be infinite. If I can't find a way I will make the world "round" but infinite would be preferable. Is this possible?
An ArrayList is infinite... until memory runs out. But I guess that was not the question.
Update: Right, this is limited even though I argue nobody will notice the world restarting after two billion units.
Thought about that again. What you need is a random function that creates the same value again and again when you give it seed and current position. So you do not store the world, you recalculate it on the fly.
So you need an infinite counter only for the position in your world. The only challenge will be the storage of event results such us eaten mushrooms and destroyed bridges.
Storing all the data in a list will have a lot of limitations.
If you use an ArrayList, you can't have infinite elements.
If you use a LinkedList, you lose random access, so speed is a lot slower.
And for any list, RAM is an issue.
You'd be better off by splitting generated areas into chunks, then storing those to the harddrive.
Now, you'd still want a list of loaded areas, but this will be limited by a scope. If you're 2 game-miles to the East of some town, no point keeping the town information in reference (I hope).
One very popular game to this is Minecraft. Attempting to load the entire Minecraft world into your RAM won't happen - yet it still has the potential for infinite worlds.
If the world is going to be huge, I wouldn't store it in an ArrayList or a LinkedList. Instead you can make the whole world depend on a randomly selected long value seed. The terrain at position i can then be found using new Random(seed ^ i).nextInt() (or something). That way the world will be (effectively) infinite and you won't have to save the terrain in memory. Whenever you return to a previously visited part of the world it will be the same as it was before. The number of different worlds is 2^64 so you'd have to live a very long time before you saw the same world again.
ArrayList can contain up to 2^31 values (because length of array is integer, which is unsigned 4 byte structure).
However LinkedList is limitless, the only limit is the memory of JVM.
I'm implementing a genetic algorithm using Java programming language. As you know, there are some random events in the algorithm like roullete selection, crossover, mutation, etc. In order to generate a better probability distribution among these events, which approach should be better, to use a unique Random object or create a separate Random object for each event?
Use a single object. Random number generators are designed to have long periods -- using the same seeded instance, you get a good sequence of random digits out. If you're constantly creating and destroying them, you're only getting however much randomness there is in the seeding process, which may even be none. Imagine what happens if your RNG is seeded from the system clock, and you're doing it thousands of times per second, for instance.
Use a single Random stored globally, and refer to it everywhere you need randomness. What's more, initialize it with a known seed, and write this seed to a file along with the results of the genetic algorithm.
In addition to the benefits mentioned by deong, this lets you rerun the whole program exactly if you find some interesting outputs. It can be extremely frustrating with genetic algorithms to see an interesting result and then be unable to reproduce it, because it was a rare outcome. If you have the seed, you can just rerun the program deterministically.
If you want each run to use a new seed you can do it like this:
long seed = new Random().nextLong();
log("Seed for the current run is: " + seed);
Global.setRandom(new Random(seed));
That way you get a new random seed everytime, but you can still reconstruct a given run if you need to.
Note that the Random object should not be shared between two different runs. At the start of each run, you should create a new random object and make a note of the seed.
So I have some C code which calculate some results based on the number generated by srand(). If I use the same seed number, the result will always be the same.
Now I have an Android app load these C code via JNI. However, the results become different although the same seed number is being used. I have double checked the seed number to make sure it is the same. However, since both the Android program and the native code are pretty complicated, I am having a hard time to figure out what is causing this problem.
What I am sure is, we did not use function in the java program to generate random numbers. So presumably srand() is not called with a different seed number every time. Can other functions in Java or C change the random number generated by srand()?
Thanks!
Update:
I guess my question was a little confusing. To clarify, the results I am comparing are from the same platform, but different runs. The c code use rand() to get a number calculate a result based on that. So if the seed number of srand() is always the same, the number get by rand() should be the same and hence the results should be the same. but somehow even I use the same seed for srand(), the rand() give me different number... Any thought on that?
There are many different types of random number generators, and they are not all guaranteed to be the same from platform to platform. If having a cross platform 100% predictable solution is necessary for your project, you'll probably have to write your own.
It's really not as bad as it may sound...
I'd recommend looking up random number generation such as the Mersenne Twister algorithm (which is what I use in my projects), and write a small block of code that you can share amongst all your projects. This also gives you the benefit of being able to have multiple generators with varying seeds, which comes in really useful for something like a puzzle game, where you might want a predictably random set based on a specific seed to generate your puzzle, but another clock seeded generator for randomizing special FX or other game elements.
The pseudo-random algorithm implemented by rand() is determined by the C library, and there is no standard algorithm for it. You are absolutely not guaranteed to get the same sequence of numbers from one implementation to the next, and it sounds like the Android implementation differs from your development environment. If you need a predictable sequence across platforms, you should implement your own random number generator.
I'm making a bitmap editor where a document consists of several layers where each layer represents a bitmap. Each layer must have a unique ID compared to all other layers that currently exist in the document. I also need to take into account that I need to save and load documents along with the layer IDs.
I'm using the command pattern to store actions that are performed on the document and the unique IDs are used to keep track of which layer an action should be performed on.
At the moment, I just keep a counter called X, when a new layer is created its ID is set to X then X is incremented. When loading, I need to make sure X is set to an appropriate number so that new layers are given unique IDs i.e. I could save the value of X and restore that, or set X based on the biggest layer ID loaded.
Given X is a 32-bit number, the user will need to create 4,294,967,296 layers working on the same file before IDs start to be reused which will cause weird behaviour. Should I implement a better unique ID system or is this generally good enough?
I'm in Java so I could use the UUID library which creates 128 bit unique IDs according to a standard algorithm. This seems overkill though.
Is there some general approach to this kind of problem?
This is perfectly good enough. At a rate of ten new layers per second 24/365, which is silly, it'll run fine for roughly three years.
If you think you might manipulate layers programmatically, and thus have some possibility of having 2^32 layers in the lifetime of the image, then throw all the layer IDs into a HashSet when you read the file, and update that set when you add/remove layers. (You don't need to explicitly store the set; the ID associated with each mask is enough.) Then instead of taking "the next number", take "the next number not in the set". Having a counter is still useful, but whether you set it to 0 or (max+1) when you read a file is immaterial; it won't take a significant amount of time to find an empty space unless you envision bafflingly large numbers of layers present simultaneously.
But since you're using Java, you could just use a long instead of an int, and then you wouldn't ever (practically speaking) be able to overflow the number even if all you did was create a one-pixel mask and destroy it over and over again.
I'm creating a grid based game in Java and I want to implement game recording and playback. I'm not sure how to do this, although I've considered 2 ideas:
Several times every second, I'd record the entire game state. To play it back, I write a renderer to read the states and try to create a visual representation. With this, however, I'd likely have a large save file, and any playback attempts would likely have noticeable lag.
I could also write every key press and mouse click into the save file. This would give me a smaller file, and could play back with less lag. However, the slightest error at the start of the game (For example, shooting 1 millisecond later) would result in a vastly different game state several minutes into the game.
What, then, is the best way to implement game playback?
Edit- I'm not sure exactly how deterministic my game is, so I'm not sure the entire game can be pieced together exactly by recording only keystrokes and mouse clicks.
A good playback mechanism is not something that can be simply added to a game without major difiiculties. The best would be do design the game infrastructure with it in mind. The command pattern can be used to achieve such a game infrastructure.
For example:
public interface Command{
void execute();
}
public class MoveRightCommand implements Command {
private Grid theGrid;
private Player thePlayer;
public MoveRightCommand(Player player, Grid grid){
this.theGrid = grid;
this.thePlayer = player;
}
public void execute(){
player.modifyPosition(0, 1, 0, 0);
}
}
And then the command can be pushed in an execution queue both when the user presses a keyboard button, moves the mouse or without a trigger with the playback mechanism. The command object can have a time-stamp value (relative to the beginning of the playback) for precise playback...
Shawn Hargreaves had a recent post on his blog about how they implemented replay in MotoGP. Goes over several different approaches and their pros and cons.
http://blogs.msdn.com/shawnhar/archive/2009/03/20/motogp-replays.aspx
Assuming that your game is deterministic, it might be sufficient if you recorded the inputs of the users (option 2). However, you would need to make sure that you are recognizing the correct and consistent times for these events, such as when it was recognized by the server. I'm not sure how you handle events in the grid.
My worry is that if you don't have a mechanism that can uniformly reference timed events, there might be a problem with the way your code handles distributed users.
Consider a game like Halo 3 on the XBOX 360 for example - each client records his view of the game, including server-based corrections.
Why not record several times a second and then compress your output, or perhaps do this:
recordInitialState();
...
runs 30 times a second:
recordChangeInState(previousState, currentState);
...
If you only record the change in state with a timestamp(and each change is small, and if there is no change, then record nothing), you should end up with reasonable file sizes.
There is no need to save everything in the scene for every frame. Save changes incrementally and use some good interpolation techniques. I would not really use a command pattern based approach, but rather make checks at a fixed rate for every game object and see if it has changed any attribute. If there is a change that change is recorded in some good encoding and the replay won't even become that big.
How you approach this will depend greatly on the language you are using for your game, but in general terms there are many approaches, depending on if you want to use a lot of storage or want some delay. It would be helpful if you could give some thoughts as to what sacrifices you are willing to make.
But, it would seem the best approach may be to just save the input from the user, as was mentioned, and either store the positions of all the actors/sprites in the game at the same time, which is as simple as just saving direction, velocity and tile x,y, or, if everything can be deterministic then ignore the actors/sprites as you can get their information.
How non-deterministic your game is would also be useful to give a better suggestion.
If there is a great deal of dynamic motion, such as a crash derby, then you may want to save information each frame, as you should be updating the players/actors at a certain framerate.
I would simply say that the best way to record a replay of a game depends entirely on the nature of the game. Being grid based isn't the issue; the issue is how predictable behaviour is following a state change, how often there are new inputs to the system, whether there is random data being injected at any point, etc, You can store an entire chess game just by recording each move in turn, but that wouldn't work for a first person shooter where there are no clear turns. You could store a first person shooter by noting the exact time of each input, but that won't work for an RPG where the result of an input might be modified by the result of a random dice roll. Even the seemingly foolproof idea of taking a snapshot as often as possible isn't good enough if important information appears instantaneously and doesn't persist in any capturable form.
Interestingly this is very similar to the problem you get with networking. How does one computer ensure that another computer is made aware of the game state, without having to send that entire game state at an impractically high frequency? The typical approach ends up being a bespoke mixture of event notifications and state updates, which is probably what you'll need here.
I did this once by borrowing an idea from video compression: keyframes and intermediate frames. Basically, every few seconds you save the complete state of the world. Then, once per game update, you save all the changes to the world state that have happened since the last game update. The details (how often do you save keyframes? What exactly counts as a 'change to the world state'?) will depend on what sort of game information you need to preserve.
In our case, the world consisted of many, many game objects, most of which were holding still at any given time, so this approach saved us a lot of time and memory in recording the positions of objects that weren't moving. In yours the tradeoffs might be different.