Skip to content

Instantly share code, notes, and snippets.

@FireyFly
Forked from yorickvP/rps.js
Last active December 16, 2015 11:19
Show Gist options
  • Save FireyFly/5426471 to your computer and use it in GitHub Desktop.
Save FireyFly/5426471 to your computer and use it in GitHub Desktop.
function RPS(count) {
this.players = count
this.score = range(count).map(Const(0))
this.moves = range(count).map(limit(Array,0))
}
RPS.prototype.beats = { "rock": "scissors",
"paper": "rock",
"scissors": "paper" }
RPS.prototype.wins = function (p1, p2) {
return (this.beats[p1] == p2)
}
RPS.prototype.calcScore = function (winners, move) {
return contains(winners, move)? 1 : 0
}
// if the weapons don't form a cycle, the upper one wins
// otherwise, it's a draw
RPS.prototype.winningWeapons = function (moves) {
var uniqueMoves = uniqes(moves)
, wins = this.wins.bind(this)
return uniqueMoves.filter(function (weapon) {
// every move is beaten by this one, or it is this one
// but it needs to beat at least one move
var others = uniqueMoves.filter(function (move) {
return move != weapon
})
return others.length > 0 &&
others.every(wins.bind(0, weapon))
})
//-- Helpers ---------------
function uniques(arr) {
return arr.filter(function (x, i) {
// make sure that `x` isn't in the tail of the array
return !contains(arr, x, i+1)
})
}
}
RPS.prototype.move = function(moves) {
this.moves.forEach(function (x) {
x.push(x)
})
// for (var i = 0; i < this.players; i++)
// this.moves[i].push(moves[i])
var winners = this.winningWeapons(moves)
, scores = moves.map(this.calcScore.bind(this, winners))
this.score = this.score.map(function (x, i) {
return x + scores[i]
})
// return all the winning players
var winning_players = moves.reduce(function (p, c, i) {
return contains(winners, c)? p.concat([i])
: /*else*/ p
}, [])
return winning_players
}
RPS.prototype.AI = function() {
return randomElementOf(Object.keys(this.beats))
}
if (module && module.exports) {
module.exports = RPS
}
// example usage:
// game = RPS(2) // 2 is the number of players
// game.move(["scissors", game.AI()])
// the return object is an array of the winning players
// score is inside game.score
//-- Helpers ---------------
// Returns an array [0..n-1].
function range(n) {
var res = []
for (var i=0; i<n; i++) { res.push(i) }
return res
}
// Returns a function which always returns `x`.
function Const(x) { return function () { return x } }
// Predicate that checks whether `elem` occurs in `arr` (starting at `offset`).
function contains(arr, elem, offset) {
return arr.indexOf(elem, offset) >= 0
}
// Limits a function to taking `count` arguments.
function limit(f, count) {
return function (/*...*/) {
var args = Array.prototype.slice.call(arguments, 0, count)
return f.apply(this, args)
}
}
// Returns a randomly-chosen element of `arr`.
function randomElementOf(arr) {
return arr[arr.length * Math.random() | 0]
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment