GameMachine.js 5.4 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. var Card = require('./Card.js');
  2. class GameMachine {
  3. constructor() {
  4. this.state = {
  5. board: new Board(),
  6. players: [],
  7. hash: "0123456789"
  8. };
  9. }
  10. setState(state) {
  11. this.state = { ...this.state, ...state};
  12. }
  13. setBoard(board) {
  14. this.state = { ...this.state, board};
  15. }
  16. setPlayers(players) {
  17. this.state = { ...this.state, players};
  18. }
  19. runMove(move) {
  20. move.performMove(this.state.board);
  21. }
  22. }
  23. class Board {
  24. constructor() {
  25. this.data = [];
  26. this.owners = [];
  27. // These 2 to be updated after every move
  28. this.triggerPaths = []; // like attackVectors
  29. this.plusPaths = []; // like attackVectors
  30. for (var i=0; i < 9; i += 1) {
  31. this.triggerPaths[i] = [];
  32. this.plusPaths[i] = {
  33. winner: -1,
  34. sums: []
  35. }
  36. }
  37. }
  38. debug() {
  39. console.log('BOARD');
  40. console.log('---------------------------');
  41. console.log('Cards :');
  42. let s = '';
  43. for(var i=0,j=0;i<this.data.length;i+=1) {
  44. s += this.owners[i] + ':' + this.data[i] + '\t';
  45. j += 1;
  46. if(j%3===0)s += '\n';
  47. }
  48. console.log(s);
  49. console.log('---------------------------');
  50. console.log('Triggers');
  51. console.log('---------------------------');
  52. s = '';
  53. for(var i=0,j=0;i<this.triggerPaths.length;i+=1) {
  54. s += '[' + this.triggerPaths[i] + ']' + '\t\t';
  55. j += 1;
  56. if(j%3===0)s += '\n';
  57. }
  58. console.log(s);
  59. console.log('---------------------------');
  60. console.log('Pluspaths');
  61. console.log('---------------------------');
  62. s = '';
  63. for(var i=0,j=0;i<this.plusPaths.length;i+=1) {
  64. s += '[' + (this.plusPaths[i].winner) + ']' + '\t\t';
  65. j += 1;
  66. if(j%3===0)s += '\n';
  67. }
  68. console.log(s);
  69. console.log('---------------------------');
  70. }
  71. putCard(card, position, player) { // position = 0-9
  72. this.data[ position ] = card;
  73. this.owners[position] = player;
  74. this._calculatePlusAndTriggers(position);
  75. this._analyze(position);
  76. }
  77. _calculatePlusAndTriggers(position) {
  78. const attacker = this.data[position];
  79. for (let j = 0; j < 4; j += 1) {
  80. if ( Board.ATTACK_VECTORS[position][j] === 0 ) continue;
  81. const dx = this._getDisplacement(j);
  82. const attackedCard = this.data[position + dx];
  83. const defendJ = ( j + 2 ) % 4;
  84. if (attackedCard) {
  85. const sum = attacker.attack[j] + attackedCard.attack[defendJ];
  86. this.plusPaths[ position ].sums[j] = sum;
  87. this.plusPaths[ position + dx].sums[defendJ] = sum;
  88. this.triggerPaths[ position ][j] = attacker.attack[j] - attackedCard.attack[defendJ];
  89. this.triggerPaths[position + dx][defendJ] = -this .triggerPaths[position][j]; // opposite to the above
  90. }
  91. }
  92. }
  93. _getDisplacement(j) {
  94. switch(j) {
  95. case 0: return 1;//return {x: 1, y:0};
  96. case 1: return -3;//return {x: 0, y:1};
  97. case 2: return -1;//return {x: -1, y:0};
  98. case 3: return 3;//return {x: 0, y:-1};
  99. default: throw Error("Cannot _getDisplacement of this value: " + j);
  100. }
  101. }
  102. _flipCard(position, combo, owner) {
  103. // change owner!
  104. this.owners[position] = owner;
  105. if(combo) this._analyze(position, combo);
  106. }
  107. _analyze(position, combo) {
  108. // check rules!
  109. if( this._checkSameRule(position) && !combo ) {
  110. // Apply Same Rule
  111. this._applySameRule(position);
  112. } else if ( this._checkPlusRule(position) && !combo ) {
  113. // Apply Plus Rule
  114. this._applyPlusRule(position);
  115. } else {
  116. this._applyAttackRule(position);
  117. }
  118. }
  119. _applyAttackRule(position) { //seems ok
  120. if ( !this.triggerPaths[position] ) return;
  121. for (let j = 0; j < 4; j += 1) {
  122. if ( Board.ATTACK_VECTORS[position][j] === 0 ) continue;
  123. const dx = this._getDisplacement(j);
  124. if ( this.triggerPaths[position][j] > 0 ) {
  125. this._flipCard(position + dx, false, this.owners[position]);
  126. }
  127. }
  128. }
  129. _applySameRule(position) {
  130. for (let j = 0; j < 4; j += 1) {
  131. if ( Board.ATTACK_VECTORS[position][j] === 0 ) continue;
  132. const dx = this._getDisplacement(j);
  133. if ( this.triggerPaths[position][j] === 0 ) {
  134. this._flipCard(position + dx, true, this.owners[position]);
  135. }
  136. }
  137. }
  138. _applyPlusRule(position) {
  139. for (let j = 0; j < 4; j += 1) { // this for loop can be fixed seems obsolete & slow
  140. if ( Board.ATTACK_VECTORS[position][j] === 0 ) continue;
  141. const dx = this._getDisplacement(j);
  142. if ( this.plusPaths[position].sums[j] === this.plusPaths[position].winner ) {
  143. this._flipCard(position + dx, true, this.owners[position]);
  144. }
  145. }
  146. }
  147. _checkSameRule(position) {
  148. const card = this.data[position];
  149. let sames = 0;
  150. for (let j = 0; j < 4; j += 1) {
  151. if ( Board.ATTACK_VECTORS[position][j] === 0 ) continue;
  152. if (this.triggerPaths[position] &&
  153. this.triggerPaths[position][j] === 0) {
  154. sames += 1;
  155. }
  156. }
  157. return sames > 1;
  158. }
  159. _checkPlusRule(position) { // refactor plz // need fix (problem double plus a.k.a. four side attack)
  160. const card = this.data[position];
  161. let pluses = {};
  162. let sum = -1;
  163. for (let j = 0; j < 4; j += 1) {
  164. if ( Board.ATTACK_VECTORS[position][j] === 0 ) continue;
  165. if(sum = this.plusPaths[position].sums[j])
  166. pluses[sum] = (pluses[sum] || 0) + 1;
  167. }
  168. for (var i in pluses) {
  169. if (pluses[i] > 1) {
  170. this.plusPaths[position].winner = parseInt(i);
  171. console.log(i);
  172. return true;
  173. }
  174. }
  175. this.plusPaths[position].winner = -1;
  176. return false;
  177. }
  178. isEmpty(position) {
  179. return !!this.data[position];
  180. }
  181. }
  182. // START From top left goin row row
  183. Board.ATTACK_VECTORS = [
  184. // [R, U, L, D] // right up left down
  185. [1, 0, 0, 1],
  186. [1, 0, 1, 1],
  187. [0, 0, 1, 1],
  188. [1, 1, 0, 1],
  189. [1, 1, 1, 1],
  190. [0, 1, 1, 1],
  191. [1, 1, 0, 0],
  192. [1, 1, 1, 0],
  193. [0, 1, 1, 0]
  194. ];
  195. module.exports = {
  196. GameMachine
  197. };