A little library to make the rock-paper-scissor logic simpler. Can be used for any number of odd elements (except 1, of course.)
If using the Twine desktop/web app, copy contents of rock-paper-scissors.js
to Story JavaScript
.
If using a compiler like Tweego, drop rock-paper-scissors.js
to your source folder.
The following example uses the 'extended' version of RPS, rock-paper-scissors-lizard-spock.
<<set _rps to new RPS([
"rock", "spock", "paper", "lizard", "scissors"
])>>
<<set _player to _rps.elements.random()>>
<<set _opponent to _rps.elements.random()>>
You played <<= _player>>.
They played <<= _opponent>>.
<<set _result to _rps.compare(_player, _opponent)>>
<<if _result gt 0>>
You win!
<<elseif _result lt 0>>
You lose...
<<else>>
It's a draw.
<</if>>
The RPS
object does the math to calculate the outcome of a match. Takes in the array of elements as an argument (see how to arrange the elements.)
NOTE: The elements do not have to be a string. Internally, a Map object is used, so the elements can be of any type.
Example:
var rpsTest = new RPS([
"rock", "paper", "scissors"
]);
Object Properties:
An array of the elements that was passed in as the argument while instantiating the RPS object.
Example:
var rpsTest = new RPS([
"rock", "paper", "scissors"
]);
rpsTest.elements; // returns ["rock", "paper", "scissors"]
Object Methods:
Calculates the outcome of a match.
Arguments:
p1
: (any) Element (of the pre-defined elements during instantiation) that 'player 1' chooses.p2
: (any) Element (of the pre-defined elements during instantiation) that 'player 2' chooses.
Returns:
- (integer) A single number which can be interpreted as follows:
- If positive, player 1 wins.
- If negative, player 1 loses.
- If zero, it's a draw.
Example:
var rpsTest = new RPS([
"rock", "paper", "scissors"
]);
rpsTest.compare("rock", "scissors"); // returns 1. And that's a win.
rpsTest.compare("rock", "paper"); // returns -1. A loss.
rpsTest.compare("rock", "rock"); // returns 0. A draw.
The way any RPS system works is as follows:
- There are an odd number of elements to keep the game balanced.
- Every element wins against half of the remaining elements, and loses to the other half.
To adhere to those principles, the order of the elements has to follow one simple rule:
No element should have its winning and losing brackets interleave.
That statement can be broken down further to these rules:
- Each element has to occur before the entire bracket of elements it loses to.
- Each element has to occur after the entire bracket of elements it wins against.
Of course, an array doesn't go on forever on both sides, nor does it make a closed loop, but for this implementation, arrays are cyclic and the positions can freely change given they stay in the same cyclic order. Which means, ABC
, BCA
, and CAB
are all the same.
Some examples:
-
Classic rock-paper-scissors:
- The array is
["rock", "paper", "scissors"]
. - Each element's winning match comes before it, and the losing match comes after.
- The array is
-
Rock-paper-scissors-lizard-spock:
- The array is
["rock", "spock", "paper", "lizard", "scissors"]
. - Same with this. Winning matches to the 'left', and losing matches to the 'right'.
- Note how the two new elements took positions between the existing ones. For the system to stay balanced, this is a guaranteed side-effect.
- The array is