Skip to content

Commit

Permalink
Dev 367, DEV-320 remove board game_over detection (#35)
Browse files Browse the repository at this point in the history
* DEV-367 Adding game_end event data to game over message
* DEV-367 added new message to set the last frame when we received the end_game engine event message
* DEV-320 Removed the last frame/game over detection code the board was using.
  • Loading branch information
originalwebgurl authored Sep 22, 2021
1 parent e6250cb commit b07ee4a
Show file tree
Hide file tree
Showing 7 changed files with 51 additions and 66 deletions.
1 change: 1 addition & 0 deletions src/actions/action-types.js
Original file line number Diff line number Diff line change
Expand Up @@ -9,3 +9,4 @@ export const SET_CURRENT_FRAME = "SET_CURRENT_FRAME";
export const PAUSE_GAME = "PAUSE_GAME";
export const RESUME_GAME = "RESUME_GAME";
export const HIGHLIGHT_SNAKE = "HIGHLIGHT_SNAKE";
export const RECEIVE_EVENT_END = "RECEIVE_EVENT_END";
43 changes: 29 additions & 14 deletions src/actions/index.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { delay, getFrameByTurn, streamAllFrames } from "../utils/engine-client";
import { delay, getFrameByTurn, streamAllEvents } from "../utils/engine-client";
import { themes } from "../theme";
import * as types from "./action-types";

Expand Down Expand Up @@ -38,6 +38,13 @@ export const receiveFrame = (game, frame) => ({
frame
});

export const receiveEventEnd = (game, endEvent, frame) => ({
type: types.RECEIVE_EVENT_END,
game,
endEvent,
frame
});

export const setCurrentFrame = frame => ({
type: types.SET_CURRENT_FRAME,
frame
Expand Down Expand Up @@ -68,20 +75,28 @@ export const fetchFrames = () => {
dispatch(requestFrames());

try {
await streamAllFrames(engineUrl, gameId, (game, frame) => {
// Workaround for bug where turn exluded on turn 0
frame.Turn = frame.Turn || 0;
dispatch(receiveFrame(game, frame));

// Workaround to render the first frame into the board
if (frame.Turn === 0) {
const frame = getState().frames[0];
dispatch(setCurrentFrame(frame));

if (autoplay) {
dispatch(resumeGame());
dispatch(playFromFrame(frame));
await streamAllEvents(engineUrl, gameId, (game, eventType, eventData) => {
if (eventType === "frame") {
const frame = eventData;
// Workaround for bug where turn exluded on turn 0
frame.Turn = frame.Turn || 0;
dispatch(receiveFrame(game, frame));

// Workaround to render the first frame into the board
if (frame.Turn === 0) {
const frame = getState().frames[0];
dispatch(setCurrentFrame(frame));

if (autoplay) {
dispatch(resumeGame());
dispatch(playFromFrame(frame));
}
}
} else if (eventType === "game_end") {
const numFrames = getState().frames.length;
const frame = getState().frames[numFrames - 1];
frame.gameOver = true;
dispatch(receiveEventEnd(game, eventData, frame));
}
});
} catch (e) {
Expand Down
1 change: 1 addition & 0 deletions src/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -11,6 +11,7 @@ const initialState = {
options: null,
grid: [],
frames: [],
endEvent: {},
paused: true,
gameNotFound: false,
highlightedSnake: null,
Expand Down
9 changes: 8 additions & 1 deletion src/reducers/index.js
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,8 @@ const reducers = (state = {}, action) => {
return { ...state, paused: true };
case types.GAME_OVER:
windowPostMessage({
action: action.type
action: action.type,
endEvent: action.endEvent
});
return { ...state, paused: true };
case types.RESUME_GAME:
Expand All @@ -40,6 +41,12 @@ const reducers = (state = {}, action) => {
},
frames: [...state.frames, frame] // Be smart: this consumes A LOT of memory...
};
case types.RECEIVE_EVENT_END:
return {
...state,
endEvent: action.endEvent,
frames: [...state.frames, action.frame]
};
case types.REQUEST_FRAMES:
return { ...state };
case types.FETCH_FRAMES:
Expand Down
12 changes: 7 additions & 5 deletions src/utils/engine-client.js
Original file line number Diff line number Diff line change
Expand Up @@ -115,17 +115,19 @@ export function fetchGameInfo(baseUrl, gameId) {
return get(url);
}

export async function streamAllFrames(baseUrl, gameId, receiveFrame) {
export async function streamAllEvents(baseUrl, gameId, receiveEvent) {
const game = await fetchGameInfo(baseUrl, gameId);

let chain = Promise.resolve();
function onEngineEvent(engineEvent) {
if (engineEvent.Type && engineEvent.Type === "frame") {
const frame = engineEvent.Data || engineEvent;
if (engineEvent.Type) {
const eventData = engineEvent.Data || engineEvent;

chain = chain.then(async () => {
await prepareFrame(frame);
return receiveFrame(game, frame);
if (engineEvent.Type === "frame") {
await prepareFrame(eventData);
}
return receiveEvent(game, engineEvent.Type, eventData);
});
}
return engineEvent.Type && engineEvent.Type === "game_end";
Expand Down
8 changes: 4 additions & 4 deletions src/utils/engine-client.test.js
Original file line number Diff line number Diff line change
@@ -1,4 +1,4 @@
import { streamAllFrames } from "./engine-client";
import { streamAllEvents } from "./engine-client";
import { streamAll } from "../io/websocket";

jest.mock("../io/websocket", () => {
Expand Down Expand Up @@ -216,7 +216,7 @@ xit("doesn't break with zero snakes", async () => {
setupData(zeroSnakeData());

let received = 0;
await streamAllFrames("http://localhost", "123", (game, frame) => {
await streamAllEvents("http://localhost", "123", (game, frame) => {
received++;
expect(frame.Snakes).toHaveLength(0);
});
Expand All @@ -228,7 +228,7 @@ xit("gets frames w/ single snake", async () => {
setupData(singleSnakeData());

let received = 0;
await streamAllFrames("http://localhost", "123", (game, frame) => {
await streamAllEvents("http://localhost", "123", (game, frame) => {
received++;
expect(game.Game.ID).toEqual("123");
expect(frame.Snakes).toHaveLength(1);
Expand All @@ -241,7 +241,7 @@ xit("gets frames w/ multiple snakes", async () => {
setupData(multiSnakeData());

let received = 0;
await streamAllFrames("http://localhost", "123", (game, frame) => {
await streamAllEvents("http://localhost", "123", (game, frame) => {
received++;
expect(game.Game.ID).toEqual("123");
expect(frame.Snakes).toHaveLength(2);
Expand Down
43 changes: 1 addition & 42 deletions src/utils/game-state.js
Original file line number Diff line number Diff line change
Expand Up @@ -13,8 +13,7 @@ export function formatFrame(frame) {
turn: frame.Turn,
snakes: snakes,
food: formatPositions(frame.Food),
hazards: formatPositions(frame.Hazards),
gameOver: isLastFrameOfGame(frame)
hazards: formatPositions(frame.Hazards)
};
}

Expand Down Expand Up @@ -210,43 +209,3 @@ function cleanFrame(frame) {
food.Y = food.Y || 0;
}
}

function oneLeft(snakes) {
const alive = snakes.filter(s => !s.death);
return alive.length <= 1;
}

function getUniqueSquads(snakes) {
return snakes
.map(function(snake) {
return snake.squad;
})
.filter(function(value) {
return typeof value !== "undefined" && value !== "";
})
.filter(function(value, index, self) {
return self.indexOf(value) === index;
})
.sort();
}

export function isLastFrameOfGame(frame) {
const snakes = formatSnakes(frame.Snakes);
const aliveSnakes = snakes.filter(s => !s.death);

if (snakes.length === 0) {
return true;
}

const remainingSquads = getUniqueSquads(aliveSnakes);
if (remainingSquads.length > 0) {
// Squad game, we're done if one squad is left.
return remainingSquads.length === 1;
}

if (snakes.length === 1) {
return !!snakes[0].death;
}

return oneLeft(snakes);
}

0 comments on commit b07ee4a

Please sign in to comment.