Page 1 of 1

Accurate slot game in EOS (Proof of concept)

Posted: Thu May 13, 2021 7:58 pm
by notSafeForDev
I got inspired after seeing Super Loser Slot by Shymaroon, to create a proof of concept for an accurate slot in EOS.

https://milovana.com/webteases/showteas ... 9db20e5c96

It features reels with repeating symbols and specific paylines, such as straight lines, V shapes and W shapes. It also has different payouts depending on the type and number of symbols on a payline.

Things can be tweaked easily such as the number of columns and rows, the paylines, the symbols on the reels and their values.

If you're interested in implementing this into a tease, feel free to send me a message if you need help.

Source code:

Code: Select all

// The current RTP (return to player) is at around 259% meaning the player will earn more and more over time
// Most online slot games have an RTP of around 96%, meaning the player will loose more than they win over time

// The win values for each symbol, 
// the array values represents 1 of a kind, 2 of a kind, 3 of a kind and so on.
// Each array should include the same number of values as the symbolCount
var symbolValues = {
  "💎": [0, 0, 25, 100, 500],
  "🔔": [0, 0, 10, 50, 200],
  "🍓": [0, 0, 3, 25, 100],
  "🍒": [0, 0, 2, 15, 50],
  "🍈": [0, 0, 1, 5, 20],
  "🍇": [0, 0, 1, 5, 20]
}

// Each array represents a diffrent pay line
// with each value in the array representing the symbol row on each column
var paylines = [
  [0, 0, 0, 0, 0], // - Straight row 0
  [1, 1, 1, 1, 1], // - Straight row 1
  [2, 2, 2, 2, 2], // - Straight row 2
  [3, 3, 3, 3, 3], // - Straight row 3
  [0, 1, 2, 1, 0], // v Shape rows 0,1,2
  [1, 2, 3, 2, 1], // v Shape rows 1,2,3
  [2, 1, 0, 1, 2], // ^ Shape rows 0,1,2
  [3, 2, 1, 2, 3], // ^ Shape rows 1,2,3
  [0, 1, 0, 1, 0], // w Shape rows 0,1
  [1, 2, 1, 2, 1], // w Shape rows 1,2
  [2, 3, 2, 3, 2], // w Shape rows 2,3
  [1, 0, 1, 0, 1], // ^^ Shape rows 0,1
  [2, 1, 2, 1, 2], // ^^ Shape rows 1,2
  [3, 2, 3, 2, 3] // ^^ Shape rows 2,3
]

// Used when displaying payline wins for symbols that are not apart of the win
var blankSymbol = "⬛"
// All the symbols on a reel, in the order that they appear in at any stopping position
var reel = ["💎", "🍓", "🍒", "🔔", "🍇", "🍈", "🍈", "🍒", "🍈", "🍓", "🍇", "🍈", "🍒", "🍇", "🍇", "🔔", "🍓", "🍒", "🍈", "🍇"]
// The number of reels that will spin
var rowCount = 4
// The number of symbols visible on the machine for each reel
var columnCount = 5
// The number of reels that have been stopped
var stoppedReelCount = 0
// All the symbols that the machine will stop on in a 2D array
var symbols = []
// Array of objects with columns and win
var wins = []
// The combined win value from all payline wins
var totalWin = 0
// Current payline win to display
var currentWinIndex = -1

// Initializes the symbols and wins, should be called on a page that starts the spin
function startSpin() {
  spinSymbols()
  updateWins()
}

// Sets the symbols that the machine will stop on
function spinSymbols() {
  symbols = []
  stoppedReelCount = 0
  for (var col = 0; col < columnCount; col++) {
    symbols.push([])
    var startIndex = randomInt(0, reel.length - 1)
    for (var row = 0; row < rowCount; row++) {
      symbols[col].push(getReelSymbol(startIndex + row))
    }
  }
}

// Stops the next reel, should be called on page that repeats until all reels have been stopped
function stopNextReel() {
  stoppedReelCount++
}

// Goes to the next win, should be called on a page that repeats until all payline wins have been presented
function gotoNextWin() {
  currentWinIndex++
}

// Returns true if all reels have been stopped
function isAllReelsStopped() {
  return stoppedReelCount === columnCount
}

// Returns true if there was any payline wins
function isWin() {
  return wins.length > 0
}

// Returns true if we have presented all payline wins
function hasPresentedAllWins() {
  return currentWinIndex >= this.wins.length - 1
}

// Updates the wins based on the symbols
function updateWins() {
  currentWinIndex = -1
  wins = []
  totalWin = 0

  for (var paylineIndex = 0; paylineIndex < paylines.length; paylineIndex++) {
    var firstRow = paylines[paylineIndex][0]
    var firstSymbol = symbols[0][firstRow]
    var paylineRows = [firstRow]

    for (var col = 1; col < columnCount; col++) {
      var row = paylines[paylineIndex][col]
      var symbol = symbols[col][row]
      if (symbol === firstSymbol) {
        paylineRows.push(row)
      } else {
        break
      }
    }

    var winAmount = symbolValues[firstSymbol][paylineRows.length - 1]
    if (winAmount > 0) {
      totalWin += winAmount
      wins.push({
        rows: paylineRows,
        win: winAmount,
        symbol: firstSymbol
      })
    }
  }
}

// Calculates the return to player, meaning how much they will win on average over time, 
// more than 1 means the player will win more than they loose
function calculateRTP(spins) {
  console.log("Depending on the amount of spins, calculating the RTP may take a while")
  // For an accurate RTP, use at least 1000000 spins

  var totalWinFromAllSpins = 0
  for (var i = 0; i < spins; i++) {
    startSpin()
    totalWinFromAllSpins += totalWin
  }

  console.log("RTP:", totalWinFromAllSpins / spins)
}

// Displays the symbols on a given row
function displaySymbols(row) {
  var symbolsToDisplay = []
  for (var col = 0; col < columnCount; col++) {
    if (col < stoppedReelCount) {
      symbolsToDisplay.push(symbols[col][row])
    } else {
      symbolsToDisplay.push(blankSymbol)
    }
  }
  return symbolsToDisplay.join(" ")
}

// Displays the symbols on a given row that are part of a specific win
function displayWinningSymbols(row) {
  var symbolsToDisplay = []
  var winRows = wins[currentWinIndex].rows
  for (var col = 0; col < columnCount; col++) {
    if (winRows.length > col && winRows[col] === row) {
      symbolsToDisplay.push(symbols[col][row])
    } else {
      symbolsToDisplay.push(blankSymbol)
    }
  }

  return symbolsToDisplay.join(" ")
}

// Displays the symbol you won on, how many and how much you won for it
function displayWinInfo() {
  var ofAKind = ""
  if (wins[currentWinIndex].rows.length === 3) {
    ofAKind = "Three of a kind "
  } else if (wins[currentWinIndex].rows.length === 4) {
    ofAKind = "Four of a kind "
  } else {
    ofAKind = "Five of a kind "
  }

  return ofAKind + wins[currentWinIndex].symbol + ": " + wins[currentWinIndex].win
}

// Returns the symbol on the reel at a given index, wraps around if the index is out of range
function getReelSymbol(index) {
  return reel[index % reel.length]
}

// Returns a random whole number from min up to and including max
function randomInt(min, max) {
  return min + Math.floor(Math.random() * (max - min + 1))
}

Re: Accurate slot game in EOS (Proof of concept)

Posted: Sun May 16, 2021 5:17 am
by OrgasmPhantasm
This is really cool! I hope someone uses it :)