Pages: 1 [2] 3
|
|
|
Author
|
Topic: Calling all Java programmers! (Read 8778 times)
|
Elvish Pillager
Enlightened
Offline
Posts: 625
|
Uh, what can't they see? Not a whole lot else, but that's not an argument for removing any of the parameters. Can you suggest any of those I should hide from the AI routines, without removing the ability for the AIs to actually function? The only one I can think of would be to remove the velocity and force the AI routines to calculate it themselves. That won't make too much of a difference however as the same values would be returned. I've played several AI-programming games before, most notably RoboWar - a game where your robot never gets to execute more than 50 instructions each frame and isn't completely guaranteed to be able to tell where the opponent is at all.
Such a game is defined by the limits on the AI. Another example: In principle, I could write an AI that calculates every possible series of moves for the rest of the game and uses game theory to determine the best possible move. It'd take forever, but in principle, it would always win at least 50% of the time. Sure, that's an extreme, but with the relatively naive processor-sharing system your game uses, part of the game is a contest of willingness to use more processor time.
Uh, doesn't UQM also give the AI player essentially complete knowledge? Yes, and it also gives the AI player free rein to cheat as much as it wants to.
For the purposes of this comment, two factors differentiate UQM from this game: First, AI writing is not the point of UQM, and second, UQM's melee is much more strategic - while this game would probably degenerate in much the same ways I described if human players were playing, either.
|
|
|
Logged
|
My team of four Androsynth and three Chmmr is the most unfair team ever! My mod
|
|
|
dpcamera
Zebranky food
Offline
Posts: 9
|
Ah well, it's at least helping me learn how to code in Java properly, and learn how to write a working game. Perhaps after this I'll go for a more interesting (human-playable) game.
Adding game elements is pretty easy - I already have code for an arbitrary number of planets with different masses in my latest working version code. However, I've run into a small problem that perhaps the UQM coders could help me out with.
My planets each have a mass (and radius, which is used for collision detection), as do each of my ships. I've tried using the "true" gravitational equation for force exerted on an orbiting object by a planet:
F = (GMm)/R^2
Where G is the gravitational constant, M is planet mass, m is ship mass and R is radius (distance from the planet).
To save on computation time, each planet also has a maximum "field of influence", inside which the gravity attraction is calculated, and outside it is not.
However, I can't seem to find values that give a good play experience - it ends up with either almost no attraction until the ships get in very close, or far too much and they're accelerated by phenomenal amounts. Any suggestions on how to make it more playable?
- Dean
|
|
|
Logged
|
|
|
|
Death 999
Global Moderator
Enlightened
Offline
Gender:
Posts: 3874
We did. You did. Yes we can. No.
|
One thing you could do to fix the processor stealing would be to give the physics and each AI its own thread, each of which has lower priority than a master thread. Each of the AI threads is a nontrivial class with member fields corresponding to the instructions the AI can give to the ship. The master thread divides each frame into two parts which are for the two AI's, and one for the physics. It lets each AI run for an equal amount of time, then yields its thread. When both sides have gotten their processing done, the physics takes over, advances a frame, with each AI's instructions being whatever it left in its member fields. Rinse and repeat, but next time make them think in the other order. Not perfect, but at least subjects each side to the same random influences.
As for gravity, crank up MG to keep the force nice and big, and crank up the radius of the planet to keep ships out of the region with high tides (i.e. regions of rapidly changing gravity force).
Once you have decent gravity, that may add enough strategy for it to be interesting.
if not, one thing you could do to fix it would be to have each ship be able to get into one of a few modes. The mode would be secret information. Changing mode would prevent firing for a while. Modes would be hard-coded into the rules. They could exchange range, speed of shot, power, and flexibility in aiming. These would make the game less symmetrical, and enable some moment-to-moment asymmetry with a minimum of programming effort.
|
|
|
Logged
|
|
|
|
|
dpcamera
Zebranky food
Offline
Posts: 9
|
As for gravity, crank up MG to keep the force nice and big, and crank up the radius of the planet to keep ships out of the region with high tides (i.e. regions of rapidly changing gravity force). Thank you, that's the sort of help I was looking for. I'll have to play with the parameters to get it realistic.
I've done a bit of code rework, to make it easier to code for. Now all "collidable" objects implement a simple ICollidable interface, so that two objects can be passed to Collisions.HasColided to test for a collision. Both IMVector and Vector also implement an IVector interface allowing the utility functions in Vector (Cross Product, Dot Product, Angle, etc) to work on either type.
As for the time slicing - it's pretty much irrelevant. For each game cycle, the system takes a snapshot of the game field and passes it to each AI in turn. Since it's all AI controlled the time taken to process each frame doesn't matter, as each AI gets the same informatio per cycle - that is, the second AI cannot see the action just taken by the first for the current frame, etc.
The one problem I do have, is with the passing of the data to the AIs. I was going for making it uncheatable by making seperate IM (Immutable) versions of the ship/bullet/team/etc objects, so that the actual game data couldn't be altered. Using subclassing would have worked just fine, but doesn't prevent the user from just casting back to the main supertype and fiddling with the data.
However, while the current solution works mostly, great, there's nothing stopping the AIs from messing with the IM arrays, and preventing the following AIs from seeing the correct data. Can anyone think of a solution to this? I could clone the IM array for each AI, but that seems rather crude.
- Dean
|
|
|
Logged
|
|
|
|
dpcamera
Zebranky food
Offline
Posts: 9
|
I've updated the zip on my site with the latest source code. I've added in vector operations (damn Java and it's lack of operator overloading!) as well as planets, gravity, collisions, etc.
Also added is scaling for the graphical viewer - you can specify a playing field size in Constants.java, as well as an applet (screen) size, and it will scale the graphics to fit.
Still need to figure out a better system than all the copying of data over to the IMx versions of the data types.
- Dean
|
|
|
Logged
|
|
|
|
Death 999
Global Moderator
Enlightened
Offline
Gender:
Posts: 3874
We did. You did. Yes we can. No.
|
As for the time slicing - it's pretty much irrelevant. For each game cycle, the system takes a snapshot of the game field and passes it to each AI in turn. Since it's all AI controlled the time taken to process each frame doesn't matter, as each AI gets the same informatio per cycle - that is, the second AI cannot see the action just taken by the first for the current frame, etc. Eh, that works until someone comes up with a way to make the AI better by spending a very large amount of processor time.
The one problem I do have, is with the passing of the data to the AIs. I was going for making it uncheatable by making seperate IM (Immutable) versions of the ship/bullet/team/etc objects, so that the actual game data couldn't be altered. Using subclassing would have worked just fine, but doesn't prevent the user from just casting back to the main supertype and fiddling with the data. And not only that, but you have the problem that even if it's private, the AI's can use reflection to rip out the data. But don't give up hope. There are two solutions. Both are ugly as hell, but there you go.
First: insulate the data from the AI's using the stack
public abstract class GameData { // lots of get methods, but no implementations }
public class ModifiableGameData extends GameData { // this class actually contains data; its get methods act 'normal' // and it actually has set methods and stuff. This is what the physics engine sees. }
public class DataWrapper extends GameData implements Runnable { private String requestedData; private Object ret; // 'get' methods set the requestedData to some value, then yield. // The thread has the ModifiableGameData the physics engine is using in its stack. // This thread is an infinite loop which looks at the requested data to find what aspect of its bullet it should put into ret. // Having done so, it yields. // Then the get method resumes and reads off the value in ret, then sets ret to null. }
Second: insulate the data from the AI's using RMI.
if you understand RMI, this should be fairly self-explanatory.
If you care about security, that's what you need. Anything less is trusting that the AI writer is being honest.
Note, if this is for a class project, actually implementing either of these schema could be good for bonus points.
(edited to fix spelling)
|
|
« Last Edit: November 20, 2007, 03:58:55 pm by Death 999 »
|
Logged
|
|
|
|
guesst
Enlightened
Offline
Gender:
Posts: 692
Ancient Shofixti Warrior
|
Wow, this thread has drawn the programmers out of the woodworks.
I stand corrected.
|
|
|
Logged
|
|
|
|
RTyp06
*Smell* controller
Offline
Posts: 491
|
guesst, you should try programming if you haven't. Programming computers is at least as cool as playing the tuba in high school band. And we all know what babe magnents they were!
|
|
|
Logged
|
|
|
|
dpcamera
Zebranky food
Offline
Posts: 9
|
Hmmm, that is an ugly solution. I'll probably keep it the way it is for this prototype, and keep the "correct" way in mind for when I make a proper game. This has been a great exercise - now I feel a little more confident in making real games such as (yet another) Super Melee clone. Thanks for all your help so far.
The reflections thing is interesting, and a little annoying. While I realize that the "private" attribute isn't designed for real module security, having an interface to extract the private data from a class negates the reason for including the darn keyword in the first place. They need a new "GoddamitSuperPrivateNoTouchingYouUrQuanJerks" attribute .
No, not a class project, purely for my own benefit. I like to make simple projects on the side to keep myself busy in the downtime at Uni, and to expand my abilities beyond my comfort zone. My last project was a very simple pure-software Java 3D model renderer (http://www.fourwalledcubicle.com/J3D.php), before that a failed Logic Simulator, etc.
- Dean
|
|
|
Logged
|
|
|
|
Death 999
Global Moderator
Enlightened
Offline
Gender:
Posts: 3874
We did. You did. Yes we can. No.
|
The point of the keyword is to establish that it is not a part of the class's interface. That is all.
Reflection is really necessary for serialization.
~~~~
I realized recently that those extreme solutions are not necessary in this case. It'd only be necessary if you needed to call methods on an object which must hide data (e.g. a crypto key); but the AI's don't need to do that. If you only want them not to be able to change it, you can pass each AI its own copy. If you want to obscure information, give the copy incomplete information.
Way to go, death, making things more complicated than necessary.
|
|
|
Logged
|
|
|
|
|
|
dpcamera
Zebranky food
Offline
Posts: 9
|
Yet to upload the new code, but I've added in a setting to make bullets affected by Planet gravity. That should make it quite challenging to code a good AI for - it's possible to shoot bullets around a planet if the gravity is strong enough.
- Dean
|
|
|
Logged
|
|
|
|
|
Pages: 1 [2] 3
|
|
|
|
|