• Announcements

    • khawk

      Download the Game Design and Indie Game Marketing Freebook   07/19/17

      GameDev.net and CRC Press have teamed up to bring a free ebook of content curated from top titles published by CRC Press. The freebook, Practices of Game Design & Indie Game Marketing, includes chapters from The Art of Game Design: A Book of Lenses, A Practical Guide to Indie Game Marketing, and An Architectural Approach to Level Design. The GameDev.net FreeBook is relevant to game designers, developers, and those interested in learning more about the challenges in game development. We know game development can be a tough discipline and business, so we picked several chapters from CRC Press titles that we thought would be of interest to you, the GameDev.net audience, in your journey to design, develop, and market your next game. The free ebook is available through CRC Press by clicking here. The Curated Books The Art of Game Design: A Book of Lenses, Second Edition, by Jesse Schell Presents 100+ sets of questions, or different lenses, for viewing a game’s design, encompassing diverse fields such as psychology, architecture, music, film, software engineering, theme park design, mathematics, anthropology, and more. Written by one of the world's top game designers, this book describes the deepest and most fundamental principles of game design, demonstrating how tactics used in board, card, and athletic games also work in video games. It provides practical instruction on creating world-class games that will be played again and again. View it here. A Practical Guide to Indie Game Marketing, by Joel Dreskin Marketing is an essential but too frequently overlooked or minimized component of the release plan for indie games. A Practical Guide to Indie Game Marketing provides you with the tools needed to build visibility and sell your indie games. With special focus on those developers with small budgets and limited staff and resources, this book is packed with tangible recommendations and techniques that you can put to use immediately. As a seasoned professional of the indie game arena, author Joel Dreskin gives you insight into practical, real-world experiences of marketing numerous successful games and also provides stories of the failures. View it here. An Architectural Approach to Level Design This is one of the first books to integrate architectural and spatial design theory with the field of level design. The book presents architectural techniques and theories for level designers to use in their own work. It connects architecture and level design in different ways that address the practical elements of how designers construct space and the experiential elements of how and why humans interact with this space. Throughout the text, readers learn skills for spatial layout, evoking emotion through gamespaces, and creating better levels through architectural theory. View it here. Learn more and download the ebook by clicking here. Did you know? GameDev.net and CRC Press also recently teamed up to bring GDNet+ Members up to a 20% discount on all CRC Press books. Learn more about this and other benefits here.
Sign in to follow this  
Followers 0
PortalofKnowledge

Turn-based Game Design Help

7 posts in this topic

I am have trouble creating a simple turn based multiplayer game. Simplified Game Spec: Each player has 3 actions they can perform; a0 a1 a2 Game starts and waits for player0 to act. player0's action is recorded and the game steps to the next player, player1, and waits for player1's action. player1's action is recorded. If player1 is the last player round0 is finished and round1 starts. Game steps back to player0 and waits for their action. This repeats for 3 rounds after which win conditions are evaluated and the winner is announced. The game then starts again. I have implemented player actions and winning conditions but having difficulties getting my head around implementing stepping through players and rounds. I have tried giving each player a isActive bool field and constantly checking for it and if it's true then it's that player's turn, if not then that player can't act but finding it difficult in C# Forms creating this. Can someone suggest the best way to achieve what I described and maybe point me in the right dirrection as to how to start implementing it. Thanks alot
0

Share this post


Link to post
Share on other sites
Who 'owns' the Player objects? Let that code keep track of the active player, and check which one is next.

For example, if you have a Game class of some sort, which contains the list of players, it would keep a reference to the active player. Once that player submits his action, the game then sets the next player as the active player. If it was the last player in the list, the next round is started.
0

Share this post


Link to post
Share on other sites
If you take a look at the rules for most boardgames (i.e., something from here), they'll have a numbered list of steps, or "phases", that each player transitions through during their turn. At each phase they can possibly make decisions and perform actions. Each one can also have a list of sub-phases. Your code for a turn-based game will closely mimic such a structure, where each phase of a turn has some state and logic associated with it that knows how to handle that phase. Once the player has gone through all phases for a turn, you switch active players and start a new turn.
0

Share this post


Link to post
Share on other sites
Thanks for your help. I have created a State enum. Please take a look, feedback welcome. Would I create a "phase" class? Seems like sub-phases could inherit from that base class? Is that sound design?

 

using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Linq;
using System.Text;
using System.Windows.Forms;

namespace TurnBasedGamePlay
{
public partial class Form1 : Form
{
public Game game = new Game();

public Form1()
{
InitializeComponent();
textBox.Text += game.rprt;
}

private void p1_Click(object sender, EventArgs e)
{
if (game.gameState == Game.State.P1)
{
game.p1.action();
game.changeState();
game.rprt += "Player1 took their turn" + Environment.NewLine;
}
else if (game.gameState == Game.State.END)
{
game.rprt += "The Game is Over!" + Environment.NewLine;
}
else
{
game.rprt += "Player1 tried to play when it wasn't their turn!" + Environment.NewLine;
}

setAutoScroll();
}

private void p2_Click(object sender, EventArgs e)
{
if (game.gameState == Game.State.P2)
{
game.p1.action();
game.changeState();
game.rprt += "Player2 took their turn" + Environment.NewLine;
}
else if (game.gameState == Game.State.END)
{
game.rprt += "The Game is Over!" + Environment.NewLine;
}
else
{
game.rprt += " Player2 tried to play when it wasn't their turn!" + Environment.NewLine;
}

setAutoScroll();
}

private void startButton_Click(object sender, EventArgs e)
{
game.setStartState();
setAutoScroll();
startButton.Enabled = false;
endButton.Enabled = true;
}

public void setAutoScroll()
{
textBox.Text = game.rprt;
textBox.SelectionStart = textBox.Text.Length;
textBox.ScrollToCaret();
textBox.Refresh();
}

private void endButton_Click(object sender, EventArgs e)
{
game.setEndState();
setAutoScroll();
endButton.Enabled = false;
startButton.Enabled = true;
}
}
}

public class Game
{
public enum State { START, P1, P2, END }
public State gameState;
public string rprt;
private string currentStateMsg;

public Player p1 = new Player();
public Player p2 = new Player();

public Game()
{
rprt = "Game Constructed." + Environment.NewLine;
currentStateMsg = "State changed. Current State is: ";
}

public string report()
{
rprt += gameState.ToString() + Environment.NewLine;
return rprt;
}

public void setStartState()
{
gameState = State.P1;
rprt += "Game Started! " + currentStateMsg + gameState.ToString() + Environment.NewLine;
}

public void setEndState()
{
gameState = State.END;
rprt += "Game Finished. " + currentStateMsg + gameState.ToString() + Environment.NewLine;
}

public void changeState()
{
if (gameState == State.START)
{
gameState = State.P1;
rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P1)
{
gameState = State.P2;
rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P2)
{
gameState = State.P1;
rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else
{
rprt += "Something went wrong! Current State is: " + gameState.ToString() + Environment.NewLine;
}
}
}


public class Player
{
public string Name { get; set; }
public int MyInt { get; set; }

public Player()
{

}

public void action()
{
//do stuff
}


}




Thanks

EDIT: Source tags!
0

Share this post


Link to post
Share on other sites
In the case of most turn based games, the overall game state is basically whichever players turn it currently is. This might be an enum if you are absolutely certain that there will never be more than a particular number of players. You might also have it as an index into an array of players. Some games have some actions where something happens after all players have moved for a round.

If a turn has phases, then it might be better described as a "Turn State" of that player's turn. Ergo, while the game has a game state of whose turn it is and some other game level concepts like that, each player's turn can have a similar state variable that governs the state of their turn.

In other words, the game as a whole is a finite state machine, and the player is also a finite state machine. You don't have to use the overall game state to track turn phase.
0

Share this post


Link to post
Share on other sites
An index into an array of players seems like a better option. Allowing me to change the number of players easily if need be.

However my changeState() method assumes a set number of players. (In my code, 2 players)

How would I change Game State with an unknown number of players? I have got the behaviour using a PlayerCount and StateCount (increases by 1 after each state change) but there must be a more elegant way to do it? It handles up to 5 players. Increasing the number of players though to say 10 would be a pain and alot of work.

It's one ugly method and I can't quite follow what I did even though I wrote it! So feel to ask any questions. I feel I am quite comfortable with the c# language but really struggling in creating elegant smart algorithms and general design of my projects.


public void changeState()
{
if (gameState == State.START)
{
gameState = State.P1;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P1)
{
gameState = State.P2;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;
rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P2 && PlayerCount == 2 && StateCounter == 8)
{
gameState = State.END;
rounds = Rounds.END;
rprt += "Bet Round State: (Should be END)" + rounds.ToString() + Environment.NewLine;
StateCounter = 0;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;
rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P2 && PlayerCount == 2 && StateCounter == 6)
{
gameState = State.P1;

rounds = Rounds.ROUND4;
rprt += "Bet Round State: (Should be ROUND4)" + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P2 && PlayerCount == 2 && StateCounter == 4)
{
gameState = State.P1;

rounds = Rounds.ROUND3;
rprt += "Bet Round State: (Should be ROUND3)" + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P2 && PlayerCount == 2)
{
gameState = State.P1;

rounds = Rounds.ROUND2;
rprt += "Bet Round State: (Should be ROUND2)" + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P2)
{
gameState = State.P3;

StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && PlayerCount == 3 && StateCounter == 12)
{
gameState = State.END;

rounds = Rounds.END;
rprt += "Bet Round State: (Should be END)" + rounds.ToString() + Environment.NewLine;
StateCounter = 0;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && PlayerCount == 3 && StateCounter == 9)
{
gameState = State.P1;

rounds = Rounds.ROUND4;
rprt += "Bet Round State: (Should be ROUND4)" + rounds.ToString() + Environment.NewLine;
StateCounter++; //
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && PlayerCount == 3 && StateCounter == 6)
{
gameState = State.P1;

rounds = Rounds.ROUND3;
rprt += "Bet Round State: (Should be ROUND3)" + rounds.ToString() + Environment.NewLine;
StateCounter++; //
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && PlayerCount == 3)
{
gameState = State.P1;

rounds = Rounds.ROUND2;
rprt += "Bet Round State: (Should be ROUND2)" + rounds.ToString() + Environment.NewLine;
StateCounter++; //4
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && StateCounter == 10)
{
rounds = Rounds.ROUND3;
rprt += "Bet Round State: (Should be ROUND3)" + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;
gameState = State.P4;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && StateCounter == 15)
{
rounds = Rounds.ROUND4;
rprt += "Bet Round State: (Should be ROUND4)" + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;
gameState = State.P4;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3 && StateCounter == 20)
{
//End - Evaluate Winner
gameState = State.END;
rounds = Rounds.END;
rprt += "Bet Round State: (Should be END) " + rounds.ToString() + Environment.NewLine;
StateCounter = 0;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P3)
{
gameState = State.P4;

StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P4 && PlayerCount == 4 && StateCounter == 16)
{
gameState = State.END;
rounds = Rounds.END;
rprt += "Bet Round State: (Should be END) " + rounds.ToString() + Environment.NewLine;
StateCounter = 0;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P4 && PlayerCount == 4 && StateCounter == 12)
{
gameState = State.P1;
rounds = Rounds.ROUND4;
rprt += "Bet Round State: (Should be ROUND4) " + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P4 && PlayerCount == 4 && StateCounter == 8)
{
gameState = State.P1;
rounds = Rounds.ROUND3;
rprt += "Bet Round State: (Should be ROUND3) " + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P4 && PlayerCount == 4)
{
gameState = State.P1;
rounds = Rounds.ROUND2;
rprt += "Bet Round State: (Should be ROUND2) " + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P4)
{
gameState = State.P5;

StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P5 && StateCounter == 5)
{
rounds = Rounds.ROUND2;
rprt += "Bet Round State: (Should be ROUND2) " + rounds.ToString() + Environment.NewLine;
StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;
gameState = State.P4;
rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}
else if (gameState == State.P5)
{
gameState = State.P1;

StateCounter++;
rprt += "StateCounter: " + StateCounter.ToString() + Environment.NewLine;

rprt += currentStateMsg + gameState.ToString() + Environment.NewLine;
}

else
{
rprt += "Game Ended! " + gameState.ToString() + Environment.NewLine;
}
}





Thanks
0

Share this post


Link to post
Share on other sites
If you want a variable number players you need to make things as general as possible. One way to do that is to index your players through a List.

Here's one way you can do this:
 
public class Game
{
private List<Player> players;
private Player currentPlayer;

public void InitializeGame(int numOfPlayers)
{
players = new List<Player>();

// Create an instance of the player class for each player
for(int i=0; i < numOfPlayers; i++)
{
players.add(new Player());
}

currentPlayer = players[0];
}
}


Within your change state function you can now reference the player by simply checking who the current player is.
0

Share this post


Link to post
Share on other sites
After reading over your posts a bit more, I would suggest making the GameState not contain the player numbers. Instead try something like this: (Add this to my previous code)


public class Game

{
public enum GameState { START, MIDROUND, END }
public GameState gameState;

private List<Player> activePlayers; // Players left in the round
private List<Player> players; // All players in the game
private Player currentPlayer;

private int round;
private const int maxRounds = 3;

public void InitializeGame(int numOfPlayers)
{
players = new List<Player>();
activePlayers = new List<Player>();

// Create an instance of the player class for each player
for(int i=0; i < numOfPlayers; i++)
{
Player player = new Player();
players.add(player);
}

// Set the necessary variables for a new game
currentPlayer = players[0];
gameState = GameState.START;
round = 0;

// Start the game here
changeState();
}

public void changeState()
{
if(gameState == GameState.START)
{
// Begins each round by incrementing the round number
round++;

// Refill the active players for the round
foreach(Player player in players)
activePlayers.add(player);

// Check if the maximum rounds has been reached
if(rounds > maxRounds)
{
gameState = GameState.END;
changeState();
}
else
gameState = GameState.MIDROUND;


}
else if(gameState == GameState.MIDROUND)
{
activePlayers.RemoveAt(0);
// Check if all players have played the round
if(activePlayers.Count == 0)
{
gameState = GameState.START;
changeState();
}
else
{
currentPlayer = activePlayers[0];
}
}
else if(gameState == GameState.END)
{
// Determine winner here
}
}
}






On each button click, make sure its the right player and then call changeState().

(Note: made a few changes)

[Edited by - Xyran on March 18, 2010 9:15:02 PM]
0

Share this post


Link to post
Share on other sites

Create an account or sign in to comment

You need to be a member in order to leave a comment

Create an account

Sign up for a new account in our community. It's easy!


Register a new account

Sign in

Already have an account? Sign in here.


Sign In Now
Sign in to follow this  
Followers 0