Game Development Community

Turn based control

by Todd Barron · in Torque Game Engine · 04/23/2006 (9:53 am) · 8 replies

I'm working on porting my turn-based strategy game to Torque and am wondering if anyone else has tried to do this? If you have, where do you go to control the "flow" of the engine? In my 2D version I control everything through a main game function that lets me control everything (main()). Is there a way to proceduraly control Torque? It seems very difficult so far just to do simple things like stop the action to put a menu on-screen (or to stop things in order to process the AI turn.) Any resources pointing to examples of this would be appreciated.

#1
04/23/2006 (10:24 am)
The way I've done turn-based stuff in the past is pretty simple, but it does the job.

First, every client connected to the game would start off assuming that it is not his turn. In this state, most GUI elements are hidden and the player isn't allowed to move his pieces/men/whatever.

Once the game starts, the server informs the clients whose turn it is via a call to CommandToClient. When a player's client recieves this message, and it's his turn, all of the GUI elements that he needs to perform his turn are made visible, and the client allows orders/moves/etc to be made. All of the other clients are left in the previously mentioned disabled state until it's their turn.

Every time a move is made, the client makes a call to CommandToServer with the neccesary information, and the server, verifying that the command is from the "active" player, moves the piece/unit/whatever. Due to the way torque's networking works, when you move an object on the server, all of the clients will see the change as well.

When the player's turn is over, send out another CommandToClient letting everyone know that it's the next person's turn. If the next person happens to be computer controlled you start your AI processing on the server, and every human player is put into thier disabled state. If your AI is just a small script function, you would just call it. If it takes some time, you could use the Schedule() function to spread processing out over multiple frames, or do something more sophisticated by modding the engine.

In other words, if it's not a player's turn ignore all of their actions. Use CommandToServer/Client to inform the clients of whose turn it is and to inform the server of the clients' moves.

EDIT: clarification, grammar, spelling
#2
04/23/2006 (11:29 am)
It might depend on whether it's 2D or 3D, and what the actual game objects are. My game runs forward one game second when all moves are submitted. A lot of the game objects like vehicles, characters, smoke emitters, etc. are 'frozen' until this happens. Other objects such as the sky, and cameras, run in realtime. I could dig out the key engine functions that had to be changed for this, if it's similar to what you need.
#3
04/23/2006 (11:40 am)
@Drew: How are you determining if the player is AI controlled versus a Human?

@Sam: How do you freeze the world as you mention?

Thanks for the info so far, very helpful. :)
#4
04/23/2006 (12:09 pm)
It really does depend on how your game is set up. But if you would like a dummy client to control your AI units, you can connect an AI client with:

aiConnect("Fluffy");

That client will be treated the exact same way the other clients are. In starter.fps, for instance, it will spawn an Orc at a normal player spawn point. In cases where you want an AI client to be treated in a special way, you can check to see if a client is AI with:

%client.isAIControlled();

I'm assuming you want to treat the AI in the exact same way players are treated with the exception that it's AI controlled. If your game is more Fallout than Final Fantasy Tactics, ie the computer is not "just another player" then this is probably the wrong way to design it.
#5
04/23/2006 (1:10 pm)
@Drew: Where would you put the aiConnect("Fluffy"); code? Sorry in advance for the n00b question, jut got TGE/TGS last week.
#6
04/23/2006 (4:20 pm)
Todd,

Basically if you look in the engine in game/gameProcess.cc, you'll see ProcessList::advanceServerTime() and ProcessList::advanceClientTime() functions

In here you'll see all objects in the simulation are iterated through and their processTick() methods called.

What I have done is leave the 'realtime' objects as they were, and added an extra loop that iterates through 'non-realtime' objects, only calling their processTick() methods in accordance with a global variable I call "gDarkwindTimeElapsed" (darkwind being my game's name). This global is set to a value of 32 each time we want time to roll forward 1 second (32 ticks in Torque), and the advanceServerTime() and advanceClientTime() loops therefore know when we want them to call processTick on the non-realtime objects.
#7
04/23/2006 (4:35 pm)
@Sam: VERY HELPFUL Sam. I'm looking at the code now. Thanks a bunch.
#8
04/23/2006 (11:54 pm)
Naturally, you'd want the AI to connect at the beginning of the game.

In starter.fps/server/scripts/game.cs there's a function named "startGame," which is a good place to put it. The FPS kit's AIManager is created at the end of that function. You'll either want to either replace the creation of the AIManager with the aiconnect code, or to modify that AIManager to do what you want it to do.

Take a look at the AIManager's code (in aiPlayer.cs) before you replace it, though. It might be easier to modify it instead, depending on what your game is going to do.

Regardless, those are the two popular methods of controlling AI that I've seen. Some people like to have a controlling client, while others just like to use the AIManager and avoid the overhead of an additional client.