Task: Pig the dice game_Player


C++: #include <windows.h>
#include <iostream>
#include <string>


using namespace std;


const int PLAYERS = 4, MAX_POINTS = 100;


enum Moves { ROLL, HOLD };


class player
{
public:
    player()                     { current_score = round_score = 0; }
    void addCurrScore()          { current_score += round_score; }
    int getCurrScore()           { return current_score; }
    int getRoundScore()          { return round_score; }
    void addRoundScore( int rs ) { round_score += rs; }
    void zeroRoundScore()        { round_score = 0; }
    virtual int getMove() = 0;
    virtual ~player() {}

protected:
    int current_score, round_score;
};

class RAND_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;

	if( rand() % 10 < 5 ) return ROLL;
	if( round_score > 0 ) return HOLD;
	return ROLL;
    }
};

class Q2WIN_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;
		
	int q = MAX_POINTS - current_score;
	if( q < 6 ) return ROLL;
	q /= 4;
	if( round_score < q ) return ROLL;
	return HOLD;
    }
};

class AL20_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;

	if( round_score < 20 ) return ROLL;
	return HOLD;
    }
};

class AL20T_Player : public player
{
    virtual int getMove()
    {
	if( round_score + current_score >= MAX_POINTS ) return HOLD;

	int d = ( 100 * round_score ) / 20;
	if( round_score < 20 && d < rand() % 100 ) return ROLL;
	return HOLD;
    }
};

class Auto_pigGame
{
public:
    Auto_pigGame() 
    {
	_players[0] = new RAND_Player();
	_players[1] = new Q2WIN_Player();
	_players[2] = new AL20_Player();
        _players[3] = new AL20T_Player();
    }

    ~Auto_pigGame()
    {
	delete _players[0];
	delete _players[1];
	delete _players[2];
        delete _players[3];
    }

    void play()
    {
	int die, p = 0;
	bool endGame = false;

	while( !endGame )
	{
	    switch( _players[p]->getMove() )
	    {
		case ROLL:
	    	    die = rand() % 6 + 1;
		    if( die == 1 )
		    {
			cout << "Player " << p + 1 << " rolled " << die << " - current score: " << _players[p]->getCurrScore() << endl << endl;
			nextTurn( p );
			continue;
		    }
		    _players[p]->addRoundScore( die );
		    cout << "Player " << p + 1 << " rolled " << die << " - round score: " << _players[p]->getRoundScore() << endl;
		break;
		case HOLD:
	    	    _players[p]->addCurrScore();
		    cout << "Player " << p + 1 << " holds - current score: " << _players[p]->getCurrScore() << endl << endl;
		    if( _players[p]->getCurrScore() >= MAX_POINTS )
			endGame = true;
		    else nextTurn( p );

	    }
	}
	showScore();
    }

private:
    void nextTurn( int& p )
    {
	_players[p]->zeroRoundScore();
	++p %= PLAYERS;
    }

    void showScore()
    {
	cout << endl;
	cout << "Player   I (RAND): "  << _players[0]->getCurrScore() << endl;
	cout << "Player  II (Q2WIN): " << _players[1]->getCurrScore() << endl;
        cout << "Player III (AL20): " << _players[2]->getCurrScore() << endl;
	cout << "Player  IV (AL20T): "  << _players[3]->getCurrScore() << endl << endl << endl;

	system( "pause" );
    }

    player*	_players[PLAYERS];
};

int main( int argc, char* argv[] )
{
    srand( GetTickCount() );
    Auto_pigGame pg;
    pg.play();
    return 0;
}







Python: 



from random import randint
from collections import namedtuple
import random
from pprint import pprint as pp
from collections import Counter


playercount = 2
maxscore = 100
maxgames = 100000


Game = namedtuple('Game', 'players, maxscore, rounds')
Round = namedtuple('Round', 'who, start, scores, safe')


class Player():
    def __init__(self, player_index):
        self.player_index = player_index

    def __repr__(self):
        return '%s(%i)' % (self.__class__.__name__, self.player_index)

    def __call__(self, safescore, scores, game):
        'Returns boolean True to roll again'
        pass

class RandPlay(Player):
    def __call__(self, safe, scores, game):
        'Returns random boolean choice of whether to roll again'
        return bool(random.randint(0, 1))

class RollTo20(Player):
    def __call__(self, safe, scores, game):
        'Roll again if this rounds score < 20'
        return (((sum(scores) + safe[self.player_index]) < maxscore)    
                and(sum(scores) < 20))                                  

class Desparat(Player):
    def __call__(self, safe, scores, game):
        'Roll again if this rounds score < 20 or someone is within 20 of winning'
        return (((sum(scores) + safe[self.player_index]) < maxscore)    
                and( (sum(scores) < 20)                                 
                     or max(safe) >= (maxscore - 20)))                  


def game__str__(self):
    'Pretty printer for Game class'
    return ("Game(players=%r, maxscore=%i,\n  rounds=[\n    %s\n  ])"
            % (self.players, self.maxscore,
               ',\n    '.join(repr(round) for round in self.rounds)))
Game.__str__ = game__str__


def winningorder(players, safescores):
    'Return (players in winning order, their scores)'
    return tuple(zip(*sorted(zip(players, safescores),
                            key=lambda x: x[1], reverse=True)))

def playpig(game):
    
    players, maxscore, rounds = game
    playercount = len(players)
    safescore = [0] * playercount   
    player = 0                      
    scores=[]                       

    while max(safescore) < maxscore:
        startscore = safescore[player]
        rolling = players[player](safescore, scores, game)
        if rolling:
            rolled = randint(1, 6)
            scores.append(rolled)
            if rolled == 1:
                
                round = Round(who=players[player],
                              start=startscore,
                              scores=scores,
                              safe=safescore[player])
                rounds.append(round)
                scores, player = [], (player + 1) % playercount
        else:
            
            safescore[player] += sum(scores)
            round = Round(who=players[player],
                          start=startscore,
                          scores=scores,
                          safe=safescore[player])
            rounds.append(round)
            if safescore[player] >= maxscore:
                break
            scores, player = [], (player + 1) % playercount

    
    return winningorder(players, safescore)

if __name__ == '__main__':
    game = Game(players=tuple(RandPlay(i) for i in range(playercount)),
                maxscore=20,
                rounds=[])
    print('ONE GAME')
    print('Winning order: %r; Respective scores: %r\n' % playpig(game))
    print(game)
    game = Game(players=tuple(RandPlay(i) for i in range(playercount)),
                maxscore=maxscore,
                rounds=[])
    algos = (RollTo20, RandPlay, Desparat)
    print('\n\nMULTIPLE STATISTICS using %r\n  for %i GAMES'
          % (', '.join(p.__name__ for p in algos), maxgames,))
    winners = Counter(repr(playpig(game._replace(players=tuple(random.choice(algos)(i)
                                                               for i in range(playercount)),
                                                 rounds=[]))[0])
                      for i in range(maxgames))
    print('  Players(position) winning on left; occurrences on right:\n    %s'
          % ',\n    '.join(str(w) for w in winners.most_common()))