What should be derived, and what should be set in stone?

This is a discussion on What should be derived, and what should be set in stone? within the Game Programming forums, part of the General Programming Boards category; As usual, I'll start with some code: Card_Game.h Code: #include <vector> #include "Player.h" #include "Hand.h" #include "Deck.h" #include "Setting.h" #include ...

  1. #1
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964

    What should be derived, and what should be set in stone?

    As usual, I'll start with some code:

    Card_Game.h
    Code:
    #include <vector>
    #include "Player.h"
    #include "Hand.h"
    #include "Deck.h"
    #include "Setting.h"
    #include "Resource_Manager.h"
    
    
    class Card_Game
    {
    public:
    	Card_Game(){}
    	~Card_Game(){}
    	virtual void init(){}
    	virtual void cleanup(){}
    	virtual void turn_logic(std::string player_id);
    	std::vector<std::string> m_vPlayer_List;
    	int get_setting(std::string name);
    protected:
    	int calculate_winnings();
    	void new_setting(std::string name, Setting * new_setting);
    	void initialize_players();
    	// Give player id a new hand
    	void give_player_hand(std::string player_id);
    	void shuffle_deck(int deck_id);
    	// Draw how_many cards to player id's hand_id from deck_idntyd
    	void draw_card(std::string player_id, int hand_id, int deck_id, int how_many);
    	void place_bet(std::string player_id, int bet);
    	// Split player's active hand
    	void split_hand(std::string player_id, int hand_id);
    	// check if hand value > check_value
    	bool check_hand_value(std::string player_id, int hand_id, int check_value);	
    
    	Resource_Manager< Player > m_rPlayers;
    	Resource_Manager< std::vector<Hand*> > m_rHands;
    	Resource_Manager< int* > m_rBets;
    	Resource_Manager< Deck* > m_rDecks;
    	Resource_Manager< Setting > m_rSettings;
    	std::vector< Deck* > m_vDeck;	
    
    };
    I was able to derive a card game from this class, Blackjack

    Code:
    #include "Card_Game.h"
    #include "Setting.h"
    class Blackjack_Game : public Card_Game
    {
    public:
    	Blackjack_Game(
    	{
    	}
    	void init()
    	{
    		new_setting( "Minimum Bet", new Integer_Setting(25) );
    
    
    	}
    	virtual void cleanup(){}
    	virtual void turn_logic(std::string player_id)
    	{
    		using namespace std;
    		int m_result;
    		while(!(cin >> m_result))
    		{
    			cin.clear();
    			cin.ignore();
    		}
    
    		switch(m_result)
    		{
    		case 1: 
    			draw_card(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 0, 1);
    			if(check_hand_value(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 21))
    			{
    				m_rPlayers.get_resource(player_id).px->m_winner = false;
    			}
    			break;
    		case 2: // stay hand
    			// while dealer has hand value less than 18
    			while(check_hand_value("Dealer", 0, 18))
    			{
    				draw_card("Dealer", 0, 0, 1); // (for dealer draw to 0 hand, from 0 deck, 1 card)
    			}
    			// if the dealer goes over 21
    			if (check_hand_value("Dealer", 0, 21))
    			{
    				// player wins
    				m_rPlayers.get_resource(player_id).px->m_winner = true;
    				//state_manager->change_state( Deal_State::instance(), game );
    			}
    			// if player's hand value is greater than the dealer's
    			else if( check_hand_value(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 
    				m_rHands.get_resource("Dealer").px->at(0)->point_value()))
    			{
    				// player wins
    				m_rPlayers.get_resource(player_id).px->m_winner = true;
    				//state_manager->change_state( Deal_State::instance(), game );
    			}
    			else 
    			{
    				// player loses
    				m_rPlayers.get_resource(player_id).px->m_winner = false;
    				//state_manager->change_state( Deal_State::instance(), game );
    			}
    			break;
    		
    		case 3: // double down?
    			/* THIS IS THE RULE */
    			if (m_rHands.get_resource(player_id).px->at(m_rPlayers.get_resource(player_id).px->m_active_hand)->get_size() == 2)
    			{
    				/* THIS IS THE ACTION TO TAKE IF CONDITIONS ARE MET */
    				//game->m_players[1].bet(game->m_players[1].m_bets[game->m_players[1].m_active_hand]);
    				draw_card(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand, 0, 1);
    
    				if( check_hand_value(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand,
    					m_rHands.get_resource("Dealer").px->at(0)->point_value()))  
    				{
    					// player wins
    					m_rPlayers.get_resource(player_id).px->m_winner = true;
    					//state_manager->change_state( Deal_State::instance(), game );
    				}
    				else
    				{
    					// player loses
    					m_rPlayers.get_resource(player_id).px->m_winner = false;
    					//state_manager->change_state( Deal_State::instance(), game );
    				}
    			}
    			else { break; }
    		case 4:// split hand
    			// make sure we have only 2 cards
    			/* THIS IS THE RULE*/
    			if (m_rHands.get_resource(player_id).px->at(m_rPlayers.get_resource(player_id).px->m_active_hand)->get_size() == 2)
    			{
    				//if we have two cards, make sure they are the same value
    				if(m_rHands.get_resource(player_id).px->at(m_rPlayers.get_resource(player_id).px->m_active_hand)->get_card(0) ==
    					m_rHands.get_resource(player_id).px->at(m_rPlayers.get_resource(player_id).px->m_active_hand)->get_card(1) )
    				{
    					/* THIS IS THE ACTION IF CONDITIONS ARE MET */
    					split_hand(player_id, m_rPlayers.get_resource(player_id).px->m_active_hand);
    				}
    			}
    			break;	
    		case 5: // fold
    			// player loses
    			m_rPlayers.get_resource(player_id).px->m_winner = false;
    			//state_manager->change_state( Deal_State::instance(), game );
    			break;
    		default:// invalid entry
    			std::cout << "Please enter 1 or 2.\n";
    			break;
    		}
    	}
    };
    And now I'll start listing things I'm unsure of and need some guidance in:

    A: Rules, in all card game's there is a set of rules, these limit the players possible actions.
    A1: The actions are combinations of simple game mechanics, see the protected items in Card_Game
    A2: The turn is the only actual verb function here, where the player performs actions according to the ruleset, this is also why I think that the player should hold the turn function, or perhaps a turn object.

    This way we leave the acting part to the player, but the thinking part to the game engine. In all card games a turn may not be played the same way, but the idea of a turn remains the same.

    So this leaves us with two undefined, or virtual objects/functions (not sure how to implement these): The actions a player can perform, and the ruleset. This is what I need some help on.

    Right now the way I have it setup, the turn is always changing depending on what card game we're playing, I disagree as that all player turns technically are just implementations of possible actions checked by a ruleset.

    That is one fat concept to grasp, even for myself. Are there any suggestions to get me started?

    For the rules, one concept I read about in the past comes to mind, Functors.
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

  2. #2
    Absent Minded Programmer
    Join Date
    May 2005
    Posts
    964
    An aim conversion with a friend provided me with a bit of insite (actually just talking to myself)

    shamino55: given the idea that all player turns are the same, they rely on possible actions (which are combinations of simple card game mechanics), checked by a ruleset, how would you go about implementing that?
    shamino55: i guess first I have to define the actions
    shamino55: hit, stay, double down, split hand, bet, surrender
    shamino55: those won't be virtual functions
    shamino55: they are particular usages of game mechanics
    shamino55: so I would imagine that they need to be implemented in the derived card game
    shamino55: defined ratrher
    shamino55: i'd say they're completely seperate from the ruleset, until they are implemented in a turn
    shamino55: so we need to pass the turn a ruleset
    shamino55: if the player held an enum of possible actions and a pointer to their active hand they could pass that over to the ruleset, and the ruleset could return a few pointers to the actual actions defined by the game
    shamino55: talk about elaborate and excessive, but i like it that way
    shamino55: its like a callback function
    shamino55: ooohhh the complexities
    shamino55: i'll give you time to read up
    !@#$)(*&: lol damn man sorry i been getting killed today
    shamino55: its coo, i think i talked myself through
    shamino55: the ruleset would also limit the players possible choices by running rules and stuff, so it will only return actions that the player can perform according to the state of his hand checked by the ruleset.
    shamino55: the trick is making that abstract enough to apply to all card games i suppose
    Sometimes I forget what I am doing when I enter a room, actually, quite often.

Popular pages Recent additions subscribe to a feed

1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21