-
Notifications
You must be signed in to change notification settings - Fork 710
New issue
Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.
By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.
Already on GitHub? Sign in to your account
Prep for GameLog stuff: Introduce ContextEnhancer #261
Merged
nicolodavis
merged 12 commits into
boardgameio:master
from
Stefan-Hanke:allow_payload_in_move
Aug 24, 2018
Merged
Changes from 6 commits
Commits
Show all changes
12 commits
Select commit
Hold shift + click to select a range
fabe18c
make random.update take and return state to make it consistent with e…
Stefan-Hanke 95e4de9
Merge branch 'master' into allow_payload_in_move
Stefan-Hanke 6172403
centralize attach/detach APIs from a context
Stefan-Hanke 4a05858
use ApiContext when processing events
Stefan-Hanke 1359c0c
use ApiContext while processing moves also
Stefan-Hanke a7c2b9c
dissolve update() method specialized to the init code
Stefan-Hanke 07ba146
incorporate review comments
Stefan-Hanke dbbf540
Merge branch 'master' into allow_payload_in_move
Stefan-Hanke 2cbfde6
introduce updateAndDetach since both operations come directly after a…
Stefan-Hanke 996797e
allow to disable event update
Stefan-Hanke 028742c
bring branch coverage back to 100% by removing default value
Stefan-Hanke 7f31d59
Merge branch 'master' into allow_payload_in_move
Stefan-Hanke File filter
Filter by extension
Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
There are no files selected for viewing
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Original file line number | Diff line number | Diff line change |
---|---|---|
|
@@ -11,6 +11,36 @@ import * as Actions from './action-types'; | |
import { Random } from './random'; | ||
import { Events } from './events'; | ||
|
||
/** | ||
* This class is used to attach/detach various utility objects | ||
* onto a ctx, without having to manually attach/detach them | ||
* all separately. | ||
*/ | ||
class ContextEnhancer { | ||
constructor(ctx, game, player) { | ||
this.random = new Random(ctx); | ||
this.events = new Events(game.flow, player); | ||
} | ||
|
||
attachToContext(ctx) { | ||
let ctxWithAPI = this.random.attach(ctx); | ||
ctxWithAPI = this.events.attach(ctxWithAPI); | ||
return ctxWithAPI; | ||
} | ||
|
||
detachFromContext(ctx) { | ||
let ctxWithoutAPI = Random.detach(ctx); | ||
ctxWithoutAPI = Events.detach(ctxWithoutAPI); | ||
return ctxWithoutAPI; | ||
} | ||
|
||
update(state) { | ||
let newState = this.events.update(state); | ||
newState = this.random.update(newState); | ||
return newState; | ||
} | ||
} | ||
|
||
/** | ||
* CreateGameReducer | ||
* | ||
|
@@ -32,8 +62,8 @@ export function CreateGameReducer({ game, numPlayers, multiplayer }) { | |
} | ||
ctx._random = { seed }; | ||
|
||
const random = new Random(ctx); | ||
let ctxWithAPI = random.attach(ctx); | ||
const apiCtx = new ContextEnhancer(ctx, game, ctx.currentPlayer); | ||
let ctxWithAPI = apiCtx.attachToContext(ctx); | ||
|
||
const initial = { | ||
// User managed state. | ||
|
@@ -58,18 +88,17 @@ export function CreateGameReducer({ game, numPlayers, multiplayer }) { | |
_initial: {}, | ||
}; | ||
|
||
const events = new Events(game.flow, ctx.currentPlayer); | ||
ctxWithAPI = events.attach(ctxWithAPI); | ||
|
||
const state = game.flow.init({ G: initial.G, ctx: ctxWithAPI }); | ||
|
||
const { ctx: ctxWithEvents } = events.update(state); | ||
initial.G = state.G; | ||
initial._undo = state._undo; | ||
|
||
// TODO liked to use apiCtx.update() here also, albeit | ||
// this code is more intricate than it looks. | ||
const { ctx: ctxWithEvents } = apiCtx.events.update(state); | ||
initial.ctx = ctxWithEvents; | ||
initial.ctx = random.update(initial.ctx); | ||
initial.ctx = Random.detach(initial.ctx); | ||
initial.ctx = Events.detach(initial.ctx); | ||
initial.ctx = apiCtx.random.update(initial).ctx; | ||
initial.ctx = apiCtx.detachFromContext(initial.ctx); | ||
There was a problem hiding this comment. Choose a reason for hiding this commentThe reason will be displayed to describe this comment to others. Learn more. state = apiCtx.update(state);
initial.ctx = state.ctx;
initial.ctx = apiCtx.detachFromContext(initial.ctx); should work here. A more interesting observation is given that |
||
|
||
const deepCopy = obj => parse(stringify(obj)); | ||
initial._initial = deepCopy(initial); | ||
|
@@ -107,27 +136,19 @@ export function CreateGameReducer({ game, numPlayers, multiplayer }) { | |
|
||
state = { ...state, deltalog: undefined }; | ||
|
||
// Initialize PRNG from ctx. | ||
const random = new Random(state.ctx); | ||
// Initialize Events API. | ||
const events = new Events(game.flow, action.payload.playerID); | ||
// Attach Random API to ctx. | ||
state = { ...state, ctx: random.attach(state.ctx) }; | ||
// Attach Events API to ctx. | ||
state = { ...state, ctx: events.attach(state.ctx) }; | ||
const apiCtx = new ContextEnhancer( | ||
state.ctx, | ||
game, | ||
action.payload.playerID | ||
); | ||
apiCtx.attachToContext(state.ctx); | ||
|
||
// Update state. | ||
let newState = game.flow.processGameEvent(state, action); | ||
// Trigger any events that were called via the Events API. | ||
newState = events.update(newState); | ||
// Update ctx with PRNG state. | ||
let ctx = random.update(newState.ctx); | ||
// Detach Random API from ctx. | ||
ctx = Random.detach(ctx); | ||
// Detach Events API from ctx. | ||
ctx = Events.detach(ctx); | ||
|
||
return { ...newState, ctx, _stateID: state._stateID + 1 }; | ||
|
||
newState = apiCtx.update(newState); | ||
apiCtx.detachFromContext(newState.ctx); | ||
|
||
return { ...newState, _stateID: state._stateID + 1 }; | ||
} | ||
|
||
case Actions.MAKE_MOVE: { | ||
|
@@ -156,14 +177,12 @@ export function CreateGameReducer({ game, numPlayers, multiplayer }) { | |
|
||
state = { ...state, deltalog: undefined }; | ||
|
||
// Initialize PRNG from ctx. | ||
const random = new Random(state.ctx); | ||
// Initialize Events API. | ||
const events = new Events(game.flow, action.payload.playerID); | ||
// Attach Random API to ctx. | ||
let ctxWithAPI = random.attach(state.ctx); | ||
// Attach Events API to ctx. | ||
ctxWithAPI = events.attach(ctxWithAPI); | ||
const apiCtx = new ContextEnhancer( | ||
state.ctx, | ||
game, | ||
action.payload.playerID | ||
); | ||
let ctxWithAPI = apiCtx.attachToContext(state.ctx); | ||
|
||
// Process the move. | ||
let G = game.processMove(state.G, action.payload, ctxWithAPI); | ||
|
@@ -172,12 +191,9 @@ export function CreateGameReducer({ game, numPlayers, multiplayer }) { | |
return state; | ||
} | ||
|
||
// Update ctx with PRNG state. | ||
let ctx = random.update(state.ctx); | ||
// Detach Random API from ctx. | ||
ctx = Random.detach(ctx); | ||
// Detach Events API from ctx. | ||
ctx = Events.detach(ctx); | ||
// don't call into update here, just update the random state. | ||
let ctx = apiCtx.random.update(state).ctx; | ||
ctx = apiCtx.detachFromContext(ctx); | ||
|
||
// Undo changes to G if the move should not run on the client. | ||
if ( | ||
|
@@ -199,13 +215,13 @@ export function CreateGameReducer({ game, numPlayers, multiplayer }) { | |
} | ||
|
||
// Allow the flow reducer to process any triggers that happen after moves. | ||
state = { ...state, ctx: random.attach(state.ctx) }; | ||
state = { ...state, ctx: events.attach(state.ctx) }; | ||
state = game.flow.processMove(state, action.payload); | ||
state = events.update(state); | ||
state = { ...state, ctx: random.update(state.ctx) }; | ||
state = { ...state, ctx: Random.detach(state.ctx) }; | ||
state = { ...state, ctx: Events.detach(state.ctx) }; | ||
ctxWithAPI = apiCtx.attachToContext(state.ctx); | ||
state = game.flow.processMove( | ||
{ ...state, ctx: ctxWithAPI }, | ||
action.payload | ||
); | ||
state = apiCtx.update(state); | ||
state.ctx = apiCtx.detachFromContext(state.ctx); | ||
|
||
return state; | ||
} | ||
|
Add this suggestion to a batch that can be applied as a single commit.
This suggestion is invalid because no changes were made to the code.
Suggestions cannot be applied while the pull request is closed.
Suggestions cannot be applied while viewing a subset of changes.
Only one suggestion per line can be applied in a batch.
Add this suggestion to a batch that can be applied as a single commit.
Applying suggestions on deleted lines is not supported.
You must change the existing code in this line in order to create a valid suggestion.
Outdated suggestions cannot be applied.
This suggestion has been applied or marked resolved.
Suggestions cannot be applied from pending reviews.
Suggestions cannot be applied on multi-line comments.
Suggestions cannot be applied while the pull request is queued to merge.
Suggestion cannot be applied right now. Please check back later.
There was a problem hiding this comment.
Choose a reason for hiding this comment
The reason will be displayed to describe this comment to others. Learn more.
This can be written more concisely as: