game.cpp 8.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275
  1. #include "game.h"
  2. Game::Game()
  3. {
  4. // initialize the number of columns that each "color" will contain
  5. lastColumnIndex = CHECKBOXES - 1;
  6. // set up lockOut
  7. for(int i = 0; i<white1;i++)
  8. {
  9. lockOut.push_back(false);
  10. }
  11. // set the state of game [how to move from state to state ("game logic?")]
  12. state = NOT_STARTED;
  13. // dice have been initialized with random seed, copy this into entropyPool
  14. entropyPool = dice.roll();
  15. };
  16. bool Game::addPlayer(std::string name)
  17. {
  18. if(NOT_STARTED == state)
  19. {
  20. ScoreSheet newplayer(name);
  21. players.push_back(newplayer);
  22. fprintf (stdout, "added: %s to the game\n", name.c_str());
  23. return true;
  24. }
  25. else
  26. {
  27. fprintf(stdout, "player %s was not added to the game\n", name.c_str());
  28. return false;
  29. }
  30. };
  31. void Game::score()
  32. {
  33. // **CALCULATE EACH PLAYERS' SCORE**
  34. std::vector<int> pointsGuide = {0,1,3,6,10,15,21,28,36,45,55,66,78};
  35. // check players' card for marked boxes
  36. for(int i = 0;i <players.size();i++)
  37. {
  38. // clear each players' previous score
  39. players[i].score = 0;
  40. // calculate penalty amount
  41. players[i].score -= players[i].cumulativeOlok.penaltyCount*PENALTY_VALUE;
  42. // count the Xs of each "color" and give me a score
  43. for(int j = 0;j <white1;j++)
  44. {
  45. // determine if player qualifies for the lockout point (this is a rule)
  46. int lockoutPoint = players[i].cumulativeOlok.getLastIndex(j) == lastColumnIndex;
  47. // use pointsGuide to get the score for this user's "color" row
  48. players[i].score += pointsGuide[players[i].cumulativeOlok.getXCount(j) + lockoutPoint];
  49. }
  50. }
  51. // **CHECK IF GAME IS DONE**
  52. // check each player's card for penalties
  53. for(int i = 0;i<players.size();i++)
  54. {
  55. // check for maximum penalty to see if game is over
  56. if(players[i].cumulativeOlok.penaltyCount == MAX_PENALTY){state = FINISHED;}
  57. }
  58. // check for lockout to see if game is over
  59. int lockCount = 0;
  60. for(int i = 0;i<lockOut.size();i++)
  61. {
  62. if(true == lockOut[i]){lockCount++;}
  63. }
  64. if(MAX_LOCKOUT <= lockCount)
  65. {
  66. state = FINISHED;
  67. }
  68. }
  69. void Game::round()
  70. {
  71. // start all players' turns
  72. for(int i = 0; i <players.size();i++)
  73. {
  74. players[i].isTurnDone = false;
  75. }
  76. // roll the dice
  77. dice.roll();
  78. // check to see if all players are done with turn
  79. while(true)
  80. {
  81. bool temp = true;
  82. for(int i = 0; i <players.size();i++)
  83. {
  84. temp = temp && players[i].isTurnDone;
  85. }
  86. if(temp){break;}
  87. Sleep(1);
  88. }
  89. // save data from currentTurnOlok into cumulativeOlok
  90. for(int i = 0; i <players.size();i++)
  91. {
  92. players[i].cumulativeOlok.addOlok(players[i].currentTurnOlok);
  93. }
  94. // score the cards
  95. score();
  96. // go to next player's turn
  97. activePlayer++;
  98. activePlayer %= players.size();
  99. // adding in entropy from human players of THIS round to dice so they are slightly more random
  100. dice.diceTropy(entropyPool);
  101. }
  102. // generate text: per player(48boxes, penalty count), locked off rows, dice roll, game end(when it occurs) send it
  103. std::string Game::send()
  104. {
  105. std::string output;
  106. if(dice.dice.size()==0){fprintf(stdout, "kyle is cool\n");}
  107. // add dice values to output
  108. for(int i = 0; i < dice.dice.size(); i++)
  109. {
  110. output.push_back(dice.dice[i] + '0');
  111. }
  112. // look at each scoresheet
  113. for(int i = 0; i < players.size(); i++)
  114. {
  115. output.append(players[i].cumulativeOlok.toString());
  116. }
  117. // add locked off row to output
  118. for(int i = 0; i < lockOut.size();i++)
  119. {
  120. output.push_back(lockOut[i] ? 'T' : 'F');
  121. }
  122. // add game end to output
  123. output.push_back(state == FINISHED ? 'T' : 'F');
  124. // print everything needed to send current game state to players
  125. fprintf(stdout, "the output is: %s\n", output.c_str());
  126. return output;
  127. }
  128. // kyle's intention is to check off red 12 and blue 5
  129. // " 1143"
  130. // emma's intention is to take a penalty
  131. // "1"
  132. // convert a user string into a turn
  133. struct Turn Game::receive(std::string userInput)
  134. {
  135. Turn turnInProgress;
  136. // userinput is one, add a penalty
  137. if(1 == userInput.size())
  138. {
  139. turnInProgress.penalty = 1;
  140. }
  141. // userinput size is two, add one moves
  142. else if(2 == userInput.size())
  143. {
  144. turnInProgress.moves[0] = translateToMove(userInput);
  145. turnInProgress.numberOfMoves = 1;
  146. }
  147. // userinput size is four, add two moves
  148. else if(4 == userInput.size())
  149. {
  150. turnInProgress.moves[0] = translateToMove(userInput.substr(0,2));
  151. turnInProgress.moves[1] = translateToMove(userInput.substr(2,2));
  152. turnInProgress.numberOfMoves = 2;
  153. }
  154. else {fprintf(stdout, "Form an opinion: WRONG!");}
  155. // check the rules to make sure turn is valid
  156. if(true == checkTurn(0, turnInProgress))
  157. {
  158. // currentTurnOlok can only have one valid turn in it at a time
  159. players[0].currentTurnOlok.clear();
  160. // check the moves in turn
  161. for(int i = 0;i < turnInProgress.numberOfMoves;i++)
  162. {
  163. // add turn to currentTurnOlok
  164. players[0].currentTurnOlok.addX(turnInProgress.moves[i]);
  165. }
  166. // player chose to take a penalty
  167. players[0].currentTurnOlok.penaltyCount += turnInProgress.penalty;
  168. }
  169. // adding time to entropyPool to increase entropy in the system
  170. entropyPool += time(NULL);
  171. }
  172. bool Game::isMoveRepresentedInDie(int player, Turn turn)
  173. {
  174. // is this the non-active player
  175. if(player != activePlayer)
  176. {
  177. // if the move equals the sum of the two white die return true, if not return false
  178. return turn.moves[0].index == dice.dice[white1] + dice.dice[white2];
  179. }
  180. // otherwise this is the active player
  181. else
  182. {
  183. // if one move
  184. if(1 == turn.numberOfMoves)
  185. {
  186. // check sum of white die
  187. if(turn.moves[0].index != (dice.dice[white1] + dice.dice[white2]))
  188. {
  189. int c = turn.moves[1].color;
  190. // if any white die plus the colored die equals the move
  191. if(turn.moves[1].index == (dice.dice[white1] + dice.dice[c]) || turn.moves[1].index == (dice.dice[white2] + dice.dice[c]))
  192. {
  193. return true;
  194. }
  195. // colored die plus either white die was not a move
  196. else {return false;}
  197. }
  198. // otherwise the white sum die was a move
  199. else {return true;}
  200. }
  201. // if two moves
  202. else if(2 == turn.numberOfMoves)
  203. {
  204. // check first input with white die sum
  205. if(turn.moves[0].index != (dice.dice[white1] + dice.dice[white2]))
  206. {
  207. // white die sum was not a move
  208. return false;
  209. }
  210. else
  211. {
  212. int c = turn.moves[1].color;
  213. // check to see if color die + either white die sum equals a move
  214. if(turn.moves[1].index == (dice.dice[white1] + dice.dice[c]) || turn.moves[1].index == (dice.dice[white2] + dice.dice[c]))
  215. {
  216. return true;
  217. }
  218. else {return false;}
  219. }
  220. }
  221. }
  222. };
  223. bool Game::lockOutRule(int player, Turn turn)
  224. {
  225. // if the player has selected the last column, check it
  226. for(int i = 0; i<turn.moves.size(); i++)
  227. {
  228. // player can take their move in the last column if there are 5 recorded moves in that color
  229. if(LOCKOUT_QUALIFIER > players[player].cumulativeOlok.getXCount(turn.moves[i].color)
  230. {
  231. fprintf(stdout, "Player[%d] %s tried to check off column 12 without minimum X\n", player, players[player].savedName);
  232. return false;
  233. }
  234. }
  235. return true;
  236. }
  237. bool Game::leftToRightRule(int player, Turn turn)
  238. {
  239. for(int i = 0; i<turn.moves.size(); i++)
  240. {
  241. // player must add an x to olok from left to right
  242. if(players[player].cumulativeOlok.getLastIndex(turn.moves[i].color) > turn.moves[i].index)
  243. {
  244. fprintf(stdout,"Player[%d] %s not following left to right rule X\n", player, players[player].savedName);
  245. return false;
  246. }
  247. }
  248. return true;
  249. }
  250. bool Game::checkTurn (int player, Turn turn)
  251. {
  252. // check all rules for turn verification
  253. return lockOutRule( player, turn) && leftToRightRule( player, turn) && isMoveRepresentedInDie(player, turn);
  254. }
  255. void Game::addX(int player, int color, int index)
  256. {
  257. }
  258. struct Move Game::translateToMove(std::string temp)
  259. {
  260. int temp2 = stoi(temp);
  261. struct Move newMove;
  262. // find the color
  263. newMove.color = (temp2/colors);
  264. // find the index, subtracted 1 from checkboxes because it is lockout bonus box - only interested in scored boxes
  265. newMove.index = (temp2%(CHECKBOXES-1));
  266. return newMove;
  267. }