123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319 |
- #include "game.h"
- Game::Game()
- {
- // initialize the number of columns that each "color" will contain
- lastColumnIndex = CHECKBOXES - 1;
- // set up lockOut
- for(int i = 0; i<white1;i++)
- {
- lockOut.push_back(false);
- }
- // set the state of game [how to move from state to state ("game logic?")]
- state = NOT_STARTED;
- // dice have been initialized with random seed, copy this into entropyPool
- entropyPool = dice.roll();
- };
- bool Game::addPlayer(std::string name)
- {
- if(NOT_STARTED == state)
- {
- // add a new player with a name they choose and a secret
- ScoreSheet newplayer(name, dice.roll());
- players.push_back(newplayer);
- fprintf (stdout, "added: %s to the game\n", name.c_str());
- return true;
- }
- else
- {
- fprintf(stdout, "player %s was not added to the game\n", name.c_str());
- return false;
- }
- };
- void Game::score()
- {
- // **CALCULATE EACH PLAYERS' SCORE**
- std::vector<int> pointsGuide = {0,1,3,6,10,15,21,28,36,45,55,66,78};
- // check players' card for marked boxes
- for(int i = 0;i <players.size();i++)
- {
- // clear each players' previous score
- players[i].score = 0;
- // calculate penalty amount
- players[i].score -= players[i].cumulativeOlok.penaltyCount*PENALTY_VALUE;
- // count the Xs of each "color" and give me a score
- for(int j = 0;j <white1;j++)
- {
- // determine if player qualifies for the lockout point (this is a rule)
- int lockoutPoint = players[i].cumulativeOlok.getLastIndex(j) == lastColumnIndex;
- // use pointsGuide to get the score for this user's "color" row
- players[i].score += pointsGuide[players[i].cumulativeOlok.getXCount(j) + lockoutPoint];
- }
- }
- // **CHECK IF GAME IS DONE**
- // check each player's card for penalties
- for(int i = 0;i<players.size();i++)
- {
- // check for maximum penalty to see if game is over
- if(players[i].cumulativeOlok.penaltyCount == MAX_PENALTY){state = FINISHED;}
- }
- // check for lockout to see if game is over
- int lockCount = 0;
- for(int i = 0;i<lockOut.size();i++)
- {
- if(true == lockOut[i]){lockCount++;}
- }
- if(MAX_LOCKOUT <= lockCount)
- {
- state = FINISHED;
- }
- }
- void Game::round()
- {
- // start all players' turns
- for(int i = 0; i <players.size();i++)
- {
- players[i].isTurnDone = false;
- }
- // roll the dice
- dice.roll();
- // check to see if all players are done with turn
- while(true)
- {
- bool temp = true;
- for(int i = 0; i <players.size();i++)
- {
- temp = temp && players[i].isTurnDone;
- }
- if(temp){break;}
- // technically this is a sleep, milliseconds is for how long
- somethingNeedDoing(1000 /* milliseconds */, storage);
- }
- // save data from currentTurnOlok into cumulativeOlok
- for(int i = 0; i <players.size();i++)
- {
- players[i].cumulativeOlok.addOlok(players[i].currentTurnOlok);
- }
- // score the cards
- score();
- // go to next player's turn
- activePlayer++;
- activePlayer %= players.size();
- // adding in entropy from human players of THIS round to dice so they are slightly more random
- dice.diceTropy(entropyPool);
- }
- // generate text: per player(48boxes, penalty count), locked off rows, dice roll, game end(when it occurs) send it
- std::string Game::send()
- {
- std::string output;
- if(dice.dice.size()==0){fprintf(stdout, "kyle is cool\n");}
- // add dice values to output
- for(int i = 0; i < dice.dice.size(); i++)
- {
- output.push_back(dice.dice[i] + '0');
- }
- // look at each scoresheet
- for(int i = 0; i < players.size(); i++)
- {
- output.append(players[i].cumulativeOlok.toString());
- }
- // add locked off row to output
- for(int i = 0; i < lockOut.size();i++)
- {
- output.push_back(lockOut[i] ? 'T' : 'F');
- }
- // add game end to output
- output.push_back(state == FINISHED ? 'T' : 'F');
- // print everything needed to send current game state to players
- fprintf(stdout, "the output is: %s\n", output.c_str());
- return output;
- }
- // kyle's intention is to check off red 12 and blue 5
- // " kylesecret,1143"
- // emma's intention is to take a penalty
- // "emmasecret,1"
- // convert a user string into a turn
- struct Turn Game::receive(std::string userInput)
- {
- Turn turnInProgress;
- std::string playerSecret, original = userInput;
- int playerNumber = -1, pos = 0;
- // check for user request to add themselves to game
- // userInput == add+stringOfAnyLength
- if("add" == userInput.substr(0,3))
- {
- // add player to game
- addPlayer(userInput.substr(3));
- ScoreSheet lastPlayer = players.back();
- // send player secret -> for now it is only printed below
- fprintf(stdout, "Player %s has a secret of: %d",lastPlayer.savedName, lastPlayer.secretNumber);
- return turnInProgress;
- }
- // look for the position of a comma in userInput
- for(int i = 0;i < userInput.size();i++)
- {
- // a comma is found, set position and stop
- if(',' == userInput[i])
- {
- pos = i; break;
- }
- }
- // assuming there is a comma and it is not the first character, split userInput into two parts on the comma
- if(0<pos)
- {
- playerSecret = userInput.substr(0,pos-1);
- userInput = userInput.substr(pos);
- int secret = stoi(playerSecret);
- // check each player's secret against submitted secret to find player number
- for(int i = 0;i < players.size(); i++)
- {
- if(secret == players[i].secretNumber)
- {
- playerNumber = i; break;
- }
- }
- }
- if(-1 == playerNumber)
- {
- fprintf(stdout, "Could not find player: %s", original);
- return turnInProgress;
- }
- // userinput is one, add a penalty
- if(1 == userInput.size())
- {
- turnInProgress.penalty = 1;
- }
- // userinput size is two, add one moves
- else if(2 == userInput.size())
- {
- turnInProgress.moves[0] = translateToMove(userInput);
- turnInProgress.numberOfMoves = 1;
- }
- // userinput size is four, add two moves
- else if(4 == userInput.size())
- {
- turnInProgress.moves[0] = translateToMove(userInput.substr(0,2));
- turnInProgress.moves[1] = translateToMove(userInput.substr(2,2));
- turnInProgress.numberOfMoves = 2;
- }
- else {fprintf(stdout, "Form an opinion: WRONG!");}
- // check the rules to make sure turn is valid
- if(true == checkTurn(playerNumber, turnInProgress))
- {
- // currentTurnOlok can only have one valid turn in it at a time
- players[playerNumber].currentTurnOlok.clear();
- // check the moves in turn
- for(int i = 0;i < turnInProgress.numberOfMoves;i++)
- {
- // add turn to currentTurnOlok
- players[playerNumber].currentTurnOlok.addX(turnInProgress.moves[i]);
- }
- // player chose to take a penalty
- players[playerNumber].currentTurnOlok.penaltyCount += turnInProgress.penalty;
- }
- // adding time to entropyPool to increase entropy in the system
- entropyPool += time(NULL);
- }
- bool Game::isMoveRepresentedInDie(int player, Turn turn)
- {
- // is this the non-active player
- if(player != activePlayer)
- {
- // if the move equals the sum of the two white die return true, if not return false
- return turn.moves[0].index == dice.dice[white1] + dice.dice[white2];
- }
- // otherwise this is the active player
- else
- {
- // if one move
- if(1 == turn.numberOfMoves)
- {
- // check sum of white die
- if(turn.moves[0].index != (dice.dice[white1] + dice.dice[white2]))
- {
- int c = turn.moves[1].color;
- // if any white die plus the colored die equals the move
- if(turn.moves[1].index == (dice.dice[white1] + dice.dice[c]) || turn.moves[1].index == (dice.dice[white2] + dice.dice[c]))
- {
- return true;
- }
- // colored die plus either white die was not a move
- else {return false;}
- }
- // otherwise the white sum die was a move
- else {return true;}
- }
- // if two moves
- else if(2 == turn.numberOfMoves)
- {
- // check first input with white die sum
- if(turn.moves[0].index != (dice.dice[white1] + dice.dice[white2]))
- {
- // white die sum was not a move
- return false;
- }
- else
- {
- int c = turn.moves[1].color;
- // check to see if color die + either white die sum equals a move
- if(turn.moves[1].index == (dice.dice[white1] + dice.dice[c]) || turn.moves[1].index == (dice.dice[white2] + dice.dice[c]))
- {
- return true;
- }
- else {return false;}
- }
-
- }
- }
- };
- bool Game::lockOutRule(int player, Turn turn)
- {
- // if the player has selected the last column, check it
- for(int i = 0; i<turn.moves.size(); i++)
- {
- // player can take their move in the last column if there are 5 recorded moves in that color
- if(LOCKOUT_QUALIFIER > players[player].cumulativeOlok.getXCount(turn.moves[i].color)
- {
- fprintf(stdout, "Player[%d] %s tried to check off column 12 without minimum X\n", player, players[player].savedName);
- return false;
- }
- }
- return true;
- }
- bool Game::leftToRightRule(int player, Turn turn)
- {
- for(int i = 0; i<turn.moves.size(); i++)
- {
- // player must add an x to olok from left to right
- if(players[player].cumulativeOlok.getLastIndex(turn.moves[i].color) > turn.moves[i].index)
- {
- fprintf(stdout,"Player[%d] %s not following left to right rule X\n", player, players[player].savedName);
- return false;
- }
- }
- return true;
- }
- bool Game::checkTurn (int player, Turn turn)
- {
- // check all rules for turn verification
- return lockOutRule( player, turn) && leftToRightRule( player, turn) && isMoveRepresentedInDie(player, turn);
- }
- void Game::addX(int player, int color, int index)
- {
- }
- struct Move Game::translateToMove(std::string temp)
- {
- int temp2 = stoi(temp);
- struct Move newMove;
- // find the color
- newMove.color = (temp2/colors);
- // find the index, subtracted 1 from checkboxes because it is lockout bonus box - only interested in scored boxes
- newMove.index = (temp2%(CHECKBOXES-1));
- return newMove;
- }
|