I am writing a mini card game for my RPG. Rules are simple: 2 cards are drawn randomly and highest card wins. Cards have ranks (2 - 14, where 14 is Ace) and suits (1-4 where 4 is highest spades)) However, if player is about to lose, player luck stats kick in which will help.
For testing purposes player luck value is set to 5, which will give max increase to card rank +4 (e.g if I had 2 of hearts, I will get 6 of hearts), however max rank can be 10. if cards of same rank drawn, then cards will be swapped so that player has highest rank.
While testing, I am observing very inconsistent behavior:
- On many occasions for loop will fail to locate an adjusted card in array
- On one occasion I had SAME (same rank, same suit) card drawn twice from deck (10 of spades) despite of having splice().
Problem 1 happens way more often that problem 2 and I am at a loss.
Here is the code:
var gamingParlor = {
cards: {
s2: {suit: 4, rank: 2, name: '2 of spades'},
s3: {suit: 4, rank: 3, name: '3 of spades'},
s4: {suit: 4, rank: 4, name: '4 of spades'},
s5: {suit: 4, rank: 5, name: '5 of spades'},
s6: {suit: 4, rank: 6, name: '6 of spades'},
s7: {suit: 4, rank: 7, name: '7 of spades'},
s8: {suit: 4, rank: 8, name: '8 of spades'},
s9: {suit: 4, rank: 9, name: '9 of spades'},
s10: {suit: 4, rank: 10, name: '10 of spades'},
s11: {suit: 4, rank: 11, name: 'Jack of spades'},
s12: {suit: 4, rank: 12, name: 'Queen of spades'},
s13: {suit: 4, rank: 13, name: 'king of spades'},
s14: {suit: 4, rank: 14, name: 'Ace of spades'},
h2: {suit: 3, rank: 2, name: '2 of hearts'},
h3: {suit: 3, rank: 3, name: '3 of hearts'},
h4: {suit: 3, rank: 4, name: '4 of hearts'},
h5: {suit: 3, rank: 5, name: '5 of hearts'},
h6: {suit: 3, rank: 6, name: '6 of hearts'},
h7: {suit: 3, rank: 7, name: '7 of hearts'},
h8: {suit: 3, rank: 8, name: '8 of hearts'},
h9: {suit: 3, rank: 9, name: '9 of hearts'},
h10: {suit: 3, rank: 10, name: '10 of hearts'},
h11: {suit: 3, rank: 11, name: 'Jack of hearts'},
h12: {suit: 3, rank: 12, name: 'Queen of hearts'},
h13: {suit: 3, rank: 13, name: 'king of hearts'},
h14: {suit: 3, rank: 14, name: 'Ace of hearts'}
},
playGame: function(stakeValue){
var cardDeck = [];
for (var key in gamingParlor.cards){
cardDeck.push(gamingParlor.cards[key]);
}
console.log('Deck length is: ' +cardDeck.length);
var playerCard = cardDeck[Math.floor(Math.random()*cardDeck.length)];
console.log('player: ' +playerCard.name);
var playerCardIndex = cardDeck.indexOf(playerCard);
console.log('Player card index is' +playerCardIndex);
cardDeck.splice(playerCardIndex, 1);
console.log(cardDeck.length);
var oponentCard = cardDeck[Math.floor(Math.random()*cardDeck.length)];
console.log('opponent: ' +oponentCard.name);
if (playerCard.rank > oponentCard.rank){ // (1) No action needed - player wins naturally
console.log('Player wins on highest rank naturally');
}else if (playerCard.rank < oponentCard.rank) { // player will lose if luck does not kick in
if (player.stats.luck.counter > 1){ //player luck kicks in and there might be card adjustment
if (playerCard.rank < gameConfig.bonus.maxCardRank){ //there is space for further rank increase and adjustment will be made
playerCard.rank = playerCard.rank + gameConfig.bonus.cardRankIncrease;
console.log('player got initial card rank increase. rank before adjustment is: ' + playerCard.rank);
console.log('player card rank now is ' + playerCard.rank);
if (playerCard.rank > gameConfig.bonus.maxCardRank){ //ensure that rank after increase does not exceed max allowed value
playerCard.rank = gameConfig.bonus.maxCardRank
console.log('Rank exceeded, adjusting to maxRank: ' + playerCard.rank);
console.log('suit is:' +playerCard.suit);
}
if (playerCard.rank === oponentCard.rank && playerCard.suit === oponentCard.suit ){ //check if there is card collision after adjustment.
console.log('Player loses. There is card collision after adjustment');
console.log('Player card is: ' + playerCard.name);
console.log('Oponent card is: ' + oponentCard.name);
} else { //no card collision
console.log('No card collision after adjustment. Will update card and resove game now');
for (var i=0; i < cardDeck.length; i++){
if (cardDeck[i].rank === playerCard.rank && cardDeck[i].suit === playerCard.suit){ //locate new card in the deck
playerCard.name = cardDeck[i].name; //update player card property. URL goes here.
console.log('After foor loop - Player card is: ' + playerCard.name);
} else {
console.log('foor loop - card not found! ERROR!');
}
}
if (playerCard.rank > oponentCard.rank){
console.log('Player wins naturally due to higher after adjustment');
console.log('Player card is: ' + playerCard.name);
console.log('Opponent card is: ' + oponentCard.name);
} else if (playerCard.rank < oponentCard.rank){
console.log('Oponent wins naturally due to higher rank after adjustment');
console.log('Player card is: ' + playerCard.name);
console.log('Opponent card is: ' + oponentCard.name);
} else { //ranks are the same but suits are not.
if (playerCard.suit > oponentCard.suit){
console.log('Player wins due to higher suit');
console.log('Player card is: ' + playerCard.name);
console.log('Opponent card is: ' + oponentCard.name);
} else {
console.log('Opponent wins due to higher suit');
console.log('Player card is: ' + playerCard.name);
console.log('Opponent card is: ' + oponentCard.name);
}
}
}
}else { //rank cannot be increased as player already got a card >= 10
console.log('Player looses. Although luck kicks in, player already has a high enough card');
}
}else { //player does not have sufficient luck to affect ranking
console.log('Player loses - insufficient luck to affect ranking');
}
}else { // ranks are the same
if (playerCard.suit > oponentCard.suit){ // player wins naturally due to highest suit
console.log('Player wins due to highest suit');
}else { // player will lose if luck does not kick in
if(player.stats.luck.counter > 0) { // player luck kicks in
console.log('Ranks are same and player got a lower suit, but player has luck and cards will be swapped');
var tmp = playerCard; //swap reference to objects
playerCard = oponentCard;
oponentCard = tmp;
console.log('Player wins. Card is now: ' + playerCard.name);
console.log('Opponent loses. Card is now: ' + oponentCard.name);
}else { // player luck does not kick in
console.log('Player loses. Ranks are same but player is out of luck and got lower suit');
}
}
}
console.log('Cards are now graphically dealt, revealed and removed one after another');
} //function end
};
And here is a log of a real test I did where FOR loop failed:
city.js:143 Deck length is: 26Deck length is: 26
city.js:145 player: 3 of hearts
city.js:147 Player card index is14
city.js:149 25
city.js:151 opponent: 5 of spades
city.js:161 player got initial card rank increase. rank before adjustment is: 7
city.js:162 player card rank now is 7
city.js:174 No card collision after adjustment. Will update card and resove game now
city.js:149 25
city.js:180 foor loop - card not found! ERROR!
city.js:187 Player wins naturally due to higher after adjustment
city.js:188 Player card is: 3 of hearts
city.js:189 Opponent card is: 5 of spades
city.js:235 Cards are now graphically dealt, revealed and removed one after another
cardDeck[i].rank === playerCard.rank && cardDeck[i].suit === playerCard.suit){
– Cooper Buckinghamfor loop
runs the array is really messed up. Some objects are missing and others are duplicated instead. I will consider alternative handling of array, will try to construct it outside the function just in case. – Vadimster