Skip to content

Commit 8c88b70

Browse files
authored
Simplify Random API (#119)
* run random ops directly * make Random use global state to store / restore the PRNG state * move seed initialization to Game * inline fast-shuffle to fix Rollup issues * set Die default to D6 to avoid returning null
1 parent 67069bb commit 8c88b70

22 files changed

Lines changed: 344 additions & 310 deletions

docs/random.md

Lines changed: 11 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -19,36 +19,22 @@ This poses interesting challenges regarding the implementation.
1919
and thus must be pure. Calling `Math.random()` and other functions that
2020
maintain external state would make the game logic impure and not idempotent.
2121

22-
## Using Randomness in Games
23-
24-
[boardgame.io]() takes a rather unusual approach to randomness: It disallows getting random variables directly.
25-
Instead, a game can ask the engine to generate random numbers, and the engine will inject those into the game on the next move.
22+
### Using Randomness in Games
2623

2724
```js
2825
import { Random } from 'boardgame.io/core';
2926

30-
const SomeGame = Game({
27+
Game({
3128
moves: {
3229
rollDie(G, ctx) {
33-
// G.diceValue will contain the requested
34-
// die value at the end of this move.
35-
return Random.D6(G, 'diceValue');
36-
},
37-
},
38-
39-
flow: {
40-
onMove: G => {
41-
const dice = G.diceValue;
42-
// do something...
43-
return { ...G };
30+
return { ...G, dice: Random.D6() };
4431
},
4532
},
46-
// ...
4733
});
4834
```
4935

50-
This will place a request to a D6 dice roll inside `G`.
51-
While processing the move, the request gets evaluated and the result placed into `diceValue`, where it can be used.
36+
!> The PRNG state is maintained inside `ctx._random` by the `Random`
37+
package automatically.
5238

5339
### Shuffles
5440

@@ -67,33 +53,28 @@ const SomeGame = Game({
6753
}),
6854
moves: {
6955
shuffleDeck(G) {
70-
return Random.Shuffle(G, 'deck');
56+
return { ...G, deck: Random.Shuffle(G.deck) };
7157
},
7258
},
7359
});
7460
```
7561

76-
## Seed
62+
### Seed
7763

78-
The library uses a `seed` in `ctx` that is stripped before it
64+
The library uses a `seed` in `ctx._random` that is stripped before it
7965
is sent to the client. All the code that needs randomness uses this
8066
`seed` to generate random numbers.
8167

82-
You can override the initial `seed` in the `flow` section like this:
68+
You can override the initial `seed` like this:
8369

8470
```js
8571
Game({
72+
seed: <somevalue>
8673
...
87-
88-
flow: {
89-
seed: <somevalue>
90-
91-
...
92-
}
9374
})
9475
```
9576

96-
## Background
77+
### Background
9778

9879
There is an interesting background article by David Bau called [Random Seeds, Coded Hints, and Quintillions](http://davidbau.com/archives/2010/01/30/random_seeds_coded_hints_and_quintillions.html).
9980
Despite its age, this article gives insight on topics about randomness, like differentiating _local_ and _network_ entropy.
File renamed without changes.

examples/modules/shuffle/components/view.js renamed to examples/modules/random/components/view.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ const App = Client({
1919

2020
const SingleView = () => (
2121
<div style={{ padding: 50 }}>
22-
<App gameID="Shuffle" />
22+
<App gameID="Random" />
2323
</div>
2424
);
2525

Lines changed: 5 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -8,16 +8,18 @@
88

99
import { Game, Random } from 'boardgame.io/core';
1010

11-
const Shuffle = Game({
11+
const RandomExample = Game({
1212
name: 'shuffle',
1313

1414
setup: () => ({
1515
deck: ['a', 'b', 'c', 'd', 'e', 'f', 'g', 'h'],
1616
}),
1717

1818
moves: {
19-
shuffle: G => Random.Shuffle(G, 'deck'),
19+
shuffle: G => ({ ...G, deck: Random.Shuffle(G.deck) }),
20+
rollDie: (G, ctx, value) => ({ ...G, dice: Random.Die(value) }),
21+
rollD6: G => ({ ...G, dice: Random.D6() }),
2022
},
2123
});
2224

23-
export default Shuffle;
25+
export default RandomExample;
Lines changed: 2 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -10,8 +10,8 @@ import View from './components/view';
1010

1111
const routes = [
1212
{
13-
path: '/shuffle/cards',
14-
text: 'Shuffle Cards',
13+
path: '/random/main',
14+
text: 'Examples',
1515
component: View,
1616
},
1717
];

examples/modules/routes.js

Lines changed: 3 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,7 +10,7 @@ import tic_tac_toe from './tic-tac-toe';
1010
import chess from './chess';
1111
import phases from './phases';
1212
import liars_dice from './liars-dice';
13-
import shuffle from './shuffle';
13+
import random from './random';
1414

1515
const routes = [
1616
{
@@ -30,8 +30,8 @@ const routes = [
3030
routes: liars_dice.routes,
3131
},
3232
{
33-
name: 'Shuffle',
34-
routes: shuffle.routes,
33+
name: 'Random API',
34+
routes: random.routes,
3535
},
3636
];
3737

package-lock.json

Lines changed: 0 additions & 5 deletions
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 0 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -109,7 +109,6 @@
109109
"webpack": "^3.5.5"
110110
},
111111
"dependencies": {
112-
"fast-shuffle": "^1.0.4",
113112
"koa": "^2.3.0",
114113
"koa-router": "^7.2.1",
115114
"koa-socket": "^4.4.0",

rollup.npm.js

Lines changed: 0 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -32,7 +32,6 @@ const globals = {
3232
'react-json-view': 'ReactJson',
3333
mousetrap: 'Mousetrap',
3434
'socket.io-client': 'io',
35-
'fast-shuffle': 'shuffle',
3635
};
3736

3837
export default [
@@ -61,8 +60,6 @@ export default [
6160

6261
{
6362
input: 'packages/core.js',
64-
external: ['fast-shuffle'],
65-
globals: { 'fast-shuffle': 'shuffle' },
6663
output: { file: 'dist/core.js', format: 'umd' },
6764
name: 'Core',
6865
plugins: plugins,

0 commit comments

Comments
 (0)