Create a StreetDice Game Pt7

Today my goal was to start moving what code we have into an MVC architecture or pattern. We needed to move several functions into the game object. I also reviewed an several year old game RPG Dice Battle for clues on how to create closures to control scope and started to clean up the current code a bit.

Here is the final code at the end of the coding session:

//determine when to declare a variable and when to import?
// when you import it is just a code block
// when you declare a variable and require you bring in an object
//const { resolve } = require('path');
const readline = require('readline');

// simplified
//https://altcodeunicode.com/alt-codes-die-checkers-shogi-symbols/
// Players must first identify the player who will be shooting dice – the shooter. 

const rl = readline.createInterface({
  input: process.stdin,
  output: process.stdout
});

let game = {
  roundNumber: 0,
  players: [0,1],
  playersBanks: [20,20],
  bet: 0,
  point: undefined,
  currentShooter: undefined,
  currentDiceResult: undefined,
  currentGameResult: undefined, 
  getBet: function() {
    return this.bet;
  },
  setBet: function(player, amount) {
    // TODO: Need to add check to make sure player has enough in the bank, if not enough try a different bet also perhaps update to display bank for the shooter when making the bet.
    //console.log(`Player ${currentShooter+1}'s Bank Balance: `, game.playersBanks[currentShooter]);
    // TODO: Also need to check that the other player has enough to cover the bet.
    if (game.playersBanks[player] >= amount) {
      this.bet = amount;
      return this.bet;
    }

    return console.log(`Current bank balance: $${game.playersBanks[currentShooter]}. Not enough in bank. Please enter a bet you can cover.`);
    
  },
  getPlayerBank: function(player) {
    return this.playersBanks[player];
  },
  // Turn a number negative with:  -Math.abs(num); 
  // TODO: Rename as adjustPlayerBank
  setPlayerBank: function(player, amount) {
    this.playersBanks[player] += amount;
    return this.playersBanks[player]; //amount can be negative for a losing bet
  },
  rollDice: function(numDice, sides) {
    let diceArray = [];
    for (let i = 0; i < numDice; i++) {
      let dice = Math.floor(Math.random() * sides) + 1; // should be 1 - 6
      diceArray.push(dice);
    }
    return diceArray;
  },
  sumDice: function (diceArray) {
    let diceTotal = 0;
    for (let i = 0; i < diceArray.length;i++) {
      diceTotal += diceArray[i]
    }
    return diceTotal;
  },
  setPoint: function() {
    //this need to set a players point parameter (value) PROPERTY!
    this.point = this.currentDiceResult;
    //console.log(`Point is ${this.point}`);
    return this.point;
  },
  setShooter: function() {
    let shooterDetermined = false;
    let player0;
    let player1;
    //loop roll until see who goes first
    while (!shooterDetermined) {
      player0 = this.rollDice(1,6)[0];
      //console.log("Player 1: ", player0);
      player1 = this.rollDice(1,6)[0];
      //console.log("Player 2: ", player1);
      if ( player0 > player1) {
        // NOTE: UI Human Interface to allow player to click to roll
        //console.log('Player 1 goes first.')
        //shooterDetermined = true;
        this.currentShooter = 0;
        return this.currentShooter;
      } else if (player1 > player0) {
        // Computer rolls till outcome
        // console.log('Player 2 goes first.')
        //shooterDetermined = true;
        this.currentShooter = 1 
        return this.currentShooter;
      } 
    }
  }, 
  initGame: function() {
  console.log('Reset Game Values');
  },
  displayGameObject: function () {
    console.log("Game Object: ", this);
  }
}

// Part of Controller
function resolveBet(game) {
  console.log("Did the player win? ", (game.currentGameResult=='win'));
  //currentShooter, currentGameResult, bet
  if (game.currentGameResult == 'win') {
    // Define loser as opposite of winner if winner = currentShooter
    let loser = +!game.currentShooter;
    console.log("Loser: ", loser);
    // subtract money from loser bank v = +!v;
    console.log(game.setPlayerBank(loser, -game.bet)); 
    // add money to currentShooter bank
    console.log(game.setPlayerBank(game.currentShooter, game.bet));
  } else {
    // subtract money from currentShooter bank
    game.setPlayerBank(game.currentShooter, -game.bet);
    // add money to winner bank
    let winner = +!game.currentShooter;
    game.setPlayerBank(winner, game.bet); 
  }
  
  return console.log(game.playersBanks);
}


function resolveDice(game) {
  // this function needs to return whether it is a win a loss or a roll again
  // this function will take a dice total and the point if point is undefined the it is the first roll otherwise it is not the first roll
  // The come out roll comes next. 
  let roll = game.currentDiceResult;
  //let rollCount;
  let point = game.point;
  //roll = sumDice(rollDice(2,6));
  //rollCount++;
  // This is the game’s first roll and it could end the game if it is a 7, 11, 2, 3 or 12.
  //  The shooter and any other player who bet in favor of the shooter win the game if a 7 or 11 is rolled. 
  if (point == undefined) { //isFirstRoll = true
    if (roll == 7 || roll == 11) {
      game.currentGameResult = 'win';
      return console.log('Game Result: ', game.currentGameResult);
    }
  //  If a 2, 3 or 12 come up when the dice are rolled the shooter and other players who bet for him lose.
    if (roll == 2  || roll == 3  || roll == 12 ) { 
      game.currentGameResult = 'lose';
      return console.log('Game Result: ', game.currentGameResult);  
    }
    else {
      // A Point number, which is a number other than those mentioned above, must be set up. 
      setPoint(game);
    } 
} else {
  // So if the come out roll is not any of those numbers listed above that number will be designated as the point number.
  if (roll == 7) {
    //  The 7 is referred to an “Out 7” and once the shooter gets this before rolling the point he loses the game.
    game.currentGameResult = 'lose';
    return console.log('Game Result: ', game.currentGameResult);  
    // The shooter loses if the 7 comes up and wins if the Point is rolled. 
  } else if (roll == point) {
    // The roll is next and the goal is for the shooter to roll the number identified as the point before he rolls a 7.
    game.currentGameResult = 'win';
    return console.log('Game Result: ', game.currentGameResult);
  } 
}
return console.log('Roll again...');
}

// TODO: Add all console logs to this section to display different pieces of info to the screen.
// UI.CONTROLLER
let UIController = (function() {
  const DOMSTRINGS = {};
  return {
    //Object full of functions that will become methods of the UI Controller
  }
})();
// TODO: Create Game Controller
// Game CONTROLLER
let GameController = (function() {
 return {
   gameLoop: function(){
    // Roll against other player 
    // Set the Bet
    // Make sure that the "bet" is a number with number and return NaN if NaN
    // Roll the Dice
    // Display the Dice Roll
    // Resolve Roll
    // Resolve Bet or Re-Roll
    // if player wins keep rolling if lose other player is shooter
    // play continues until a player's bank goes to 0. 
   }
  }
})();

// Pass the UI Controller (VIEW) in to the GameController (CONTROLLER)
// This is the DEBUG CONTROLLER
var recursiveAsyncReadLine = function (game) {
  rl.question('MENU: \n 1. Set shooter \n 2. Roll Dice \n 3. Set Point \n 4. Resolve dice(game logic) \n 5. Set Bet \n 6. Resolve Bet\n 7. Display Game Object 8. Run Game \nEnter an option =>', function (entry) {
    if (entry == 'exit' || entry == 'quit') //we need some base case, for recursion
      return rl.close(); //closing RL and returning from function.
    // Create switch to run functions
    switch(entry) {
      case ('1'):
        game.currentShooter = game.setShooter();
        console.log(`Player ${game.currentShooter+1} is shooter.`);
        break;
      case ('2'):
        let diceResult = game.rollDice(2, 6);
        console.log("Roll Result: ", diceResult);
        game.currentDiceResult = game.sumDice(diceResult);
        console.log('Dice Total: ', game.currentDiceResult);
        break;
      case ('3'):
        game.setPoint();
        break;
      case ('4'):
        resolveDice(game);
        break;
      case ('5'):
        rl.question('Please enter Bet: ', function (bet) {
          // TODO: Make sure that the "bet" is a number with number and return NaN if NaN
          console.log(game.setBet(game.currentShooter, Number(bet)));
          recursiveAsyncReadLine(game);
        });
        break;
      case ('6'):
        resolveBet(game);
        console.log('Resolve the bet...');
        break;
      case ('7'):
        game.displayGameObject();
        break;
      default:
        // code block
        console.log('Invalid Response: ');
        break;
    }
    //displayGameObject(game);
    //console.log('Entry: ', entry);
    recursiveAsyncReadLine(game); //Calling this function again to ask new question
  });
};

recursiveAsyncReadLine(game); //we have to actually start our recursion somehow

rl.on("close", function() {
  console.log("\n Exiting Program... \n");
  process.exit(0);
});

Tomorrow the goal is to start building the UIController and also create the GameController which will take the game model and the UI controller.

No video today, I forgot to switch screens and recorded my face the whole time. Oof!