Skip to content

Commit

Permalink
Misc. fixes from Card reducer initial commit
Browse files Browse the repository at this point in the history
  • Loading branch information
Zamiell committed Jun 30, 2020
1 parent 79760ac commit eeaaf3a
Show file tree
Hide file tree
Showing 11 changed files with 43 additions and 33 deletions.
2 changes: 1 addition & 1 deletion client/src/game/reducers/cardsReducer.test.ts
Expand Up @@ -20,7 +20,7 @@ const gameState = initialGameState(defaultMetadata);

describe('cardsReducer', () => {
describe('holder', () => {
test('is correct when drawn', () => {
test('is equal to the player index when drawn', () => {
const deck: CardState[] = [cardInitialState(0), cardInitialState(1)];
expect(deck[0].holder).toBeNull();

Expand Down
2 changes: 2 additions & 0 deletions client/src/game/reducers/cardsReducer.ts
Expand Up @@ -125,7 +125,9 @@ const cardsReducer = produce((

export default cardsReducer;

// -------
// Helpers
// -------

function getCard(deck: Draft<CardState[]>, order: number) {
const card = deck[order];
Expand Down
4 changes: 2 additions & 2 deletions client/src/game/reducers/replayReducer.test.ts
Expand Up @@ -8,7 +8,7 @@ import { // Direct import instead of namespace import for compactness
hypoBack,
hypoEnd,
} from '../../../test/testActions';
import testGame from '../../../test_data/test_game.json';
import testGame from '../../../test_data/up_or_down.json';
import ClueType from '../types/ClueType';
import GameMetadata from '../types/GameMetadata';
import State from '../types/State';
Expand All @@ -21,7 +21,7 @@ let metadata: GameMetadata;
describe('replayReducer', () => {
// Initialize the state before each test
beforeAll(() => {
// Load the game and start a replay
// Load the game and start a replay
testState = loadGameJSON(testGame);
testState = stateReducer(testState, startReplay());
metadata = testState.metadata;
Expand Down
4 changes: 2 additions & 2 deletions client/src/game/reducers/turnReducer.test.ts
Expand Up @@ -24,7 +24,7 @@ describe('turnReducer', () => {

for (let i = 0; i < 3; i++) {
state = turnReducer(state, play(0, 0, 1, 0), defaultMetadata, 1); // Play that red 1
state = turnReducer(state, draw(0, 1, 0, 0), defaultMetadata, 1); // Draw a red 1
state = turnReducer(state, draw(0, 1, 0, 0), defaultMetadata, 1); // Draw another red 1
}

expect(state.turn).toBe(3);
Expand Down Expand Up @@ -55,7 +55,7 @@ describe('turnReducer', () => {

const playCard = () => {
state = turnReducer(state, play(0, 0, 1, 0), defaultMetadata, 1); // Play that red 1
state = turnReducer(state, draw(0, 1, 0, 0), defaultMetadata, 1); // Draw a red 1
state = turnReducer(state, draw(0, 1, 0, 0), defaultMetadata, 1); // Draw another red 1
};
expect(state.currentPlayerIndex).toBe(1);
playCard();
Expand Down
42 changes: 26 additions & 16 deletions client/src/game/rules/applyClueCore.ts
Expand Up @@ -34,8 +34,6 @@ export function applyClueCore(
? applyColorClue(state, variant, calculatePossibilities, clue, positive)
: applyRankClue(state, variant, calculatePossibilities, clue, positive);

// Mark to retroactively apply color/rank clues when we return from this function

// Reapply rank clues if we removed a special suit
const shouldReapplyRankClues = calculatePossibilities
&& suitsRemoved
Expand All @@ -52,14 +50,13 @@ export function applyClueCore(
let possibleCards = state.possibleCards;

if (calculatePossibilities) {
// Remove any card possibilities for removed suits/ranks

// Now that this card has been given a clue and we have more information,
// make a map of card possibilities that are now impossible

This comment has been minimized.

Copy link
@robertos

robertos Jun 30, 2020

Collaborator

the map is already full of stuff from previous functions. i didn't make an effort to consolidate that, but it would definitely make sense

for (const suitRemoved of suitsRemoved) {
for (const rank of variant.ranks) {
impossibleCards.push({ suit: suitRemoved, rank });
}
}

for (const rankRemoved of ranksRemoved) {
for (let suitIndex = 0; suitIndex < variant.suits.length; suitIndex++) {
impossibleCards.push({ suit: suitIndex, rank: rankRemoved });
Expand Down Expand Up @@ -175,8 +172,10 @@ function applyColorClue(
).map(getIndex);
}

if (calculatePossibilities
&& (variant.specialAllClueColors || variant.specialNoClueColors)) {
if (
calculatePossibilities
&& (variant.specialAllClueColors || variant.specialNoClueColors)
) {
// We only need to run this early possibility removal for variants with special ranks
// touched by all or no color clues
for (const rank of possibleRanks) {
Expand All @@ -189,9 +188,11 @@ function applyColorClue(
}
}

if (positive
if (
positive
&& possibleRanks.includes(variant.specialRank)
&& variant.specialAllClueColors) {
&& variant.specialAllClueColors
) {
// Some variants have specific ranks touched by all colors
// If this is the case, and this is a positive color clue,
// we cannot remove any color pips from the card
Expand All @@ -200,9 +201,11 @@ function applyColorClue(
possibleSuits,
(suit: Suit) => !suit.noClueColors,
).map(getIndex);
} else if (!positive
} else if (
!positive
&& possibleRanks.includes(variant.specialRank)
&& variant.specialNoClueColors) {
&& variant.specialNoClueColors
) {
// Some variants have specific ranks touched by no colors
// If this is the case, and this is a negative color clue,
// we cannot remove any color pips from the card
Expand Down Expand Up @@ -232,8 +235,10 @@ function applyColorClue(
(rank: number) => rank === variant.specialRank,
);
}
} else if (possibleRanks.length === 1
&& state.rank === variant.specialRank) {
} else if (
possibleRanks.length === 1
&& state.rank === variant.specialRank
) {
// Negative color to a known special rank means that we can remove all suits
// other that the ones that are never touched by color clues
const moreSuitsRemoved = filterInPlace(
Expand Down Expand Up @@ -348,12 +353,14 @@ function applyRankClue(

// Handle the special case where two positive rank clues should "fill in" a card of a
// multi-rank suit
if (positive
if (
positive
&& state.rankClueMemory.positiveClues.length >= 1
&& !(
possibleRanks.includes(variant.specialRank)
&& variant.specialAllClueRanks
)) {
)
) {
const moreSuitsRemoved = filterInPlace(
possibleSuits,
(suit: Suit) => suit.allClueRanks,
Expand All @@ -364,7 +371,8 @@ function applyRankClue(

// Handle the special case where all negative rank clues should "fill in" a card of a
// rank-less suit
if (!positive
if (
!positive
&& !variant.rankCluesTouchNothing
&& state.rankClueMemory.negativeClues.length === variant.ranks.length - 1
// We know that any special rank can be given as a rank clue
Expand Down Expand Up @@ -437,6 +445,8 @@ function removePossibility(
return cardsLeft;
}

// This function is temporary because eventually all state changes will be performed inside of a
// proper reducer function (using Redux)
export const removePossibilityTemp = produce((
state: Draft<CardState>,
suitIndex: number,
Expand Down
12 changes: 5 additions & 7 deletions client/src/game/ui/HanabiCard.ts
Expand Up @@ -105,10 +105,10 @@ export default class HanabiCard extends Konva.Group implements NodeWithTooltip {
this.add(this.bare);

this.cluedBorder = HanabiCardInit.cluedBorder();
this.finesseBorder = HanabiCardInit.finesseBorder();
this.chopMoveBorder = HanabiCardInit.chopMoveBorder();
this.add(this.cluedBorder);
this.finesseBorder = HanabiCardInit.finesseBorder();
this.add(this.finesseBorder);
this.chopMoveBorder = HanabiCardInit.chopMoveBorder();
this.add(this.chopMoveBorder);

const arrowElements = HanabiCardInit.directionArrow(globals.variant);
Expand Down Expand Up @@ -155,8 +155,6 @@ export default class HanabiCard extends Konva.Group implements NodeWithTooltip {
this.empathy = false;
this.doMisplayAnimation = false;

// Reset all memory of clues and possibilities

// Possible suits and ranks (based on clues given) are tracked separately
// from knowledge of the true suit and rank
const possibleSuits = globals.variant.suits.slice().map((_, i) => i);
Expand All @@ -173,8 +171,8 @@ export default class HanabiCard extends Konva.Group implements NodeWithTooltip {
});
});

// Mark all rank pips as visible. Note that since we're using an array
// as map, there will be gaps on the values
// Mark all rank pips as visible
// Note that since we are using an array as a map, there will be gaps on the values
const rankPipStates: PipState[] = [];
possibleRanks.forEach((r) => { rankPipStates[r] = r >= 1 && r <= 5 ? 'Visible' : 'Hidden'; });

Expand Down Expand Up @@ -1062,7 +1060,7 @@ export default class HanabiCard extends Konva.Group implements NodeWithTooltip {
const nextRankNeeded = lastPlayedRank! + 1;
const count = this.state.possibleCards[suitIndex][nextRankNeeded];
if (count === undefined) {
throw new Error(`Failed to get an entry for Suit: ${suitIndex} Rank:${nextRankNeeded} from the "possibleCards" map for card ${this.state.order}.`);
throw new Error(`Failed to get an entry for Suit: ${suitIndex} and Rank: ${nextRankNeeded} from the "possibleCards" map for card ${this.state.order}.`);
}
if (count > 0) {
potentiallyPlayable = true;
Expand Down
4 changes: 2 additions & 2 deletions client/src/game/ui/convert.ts
Expand Up @@ -29,8 +29,8 @@ export const msgSuitToSuit = (
) => {
if (
msgSuit === null
|| msgSuit < 0
|| msgSuit >= variant.suits.length
|| msgSuit < 0
|| msgSuit >= variant.suits.length
) {
return null;
}
Expand Down
2 changes: 1 addition & 1 deletion client/test/loadGameJSON.ts
Expand Up @@ -9,7 +9,7 @@ import GameMetadata from '../src/game/types/GameMetadata';
import Options from '../src/game/types/Options';
import SimpleCard from '../src/game/types/SimpleCard';
import State from '../src/game/types/State';
import testGame from '../test_data/test_game.json';
import testGame from '../test_data/up_or_down.json';

type JSONGame = typeof testGame;

Expand Down
2 changes: 1 addition & 1 deletion client/test_data/pink_rainbow_ones.json
Expand Up @@ -507,4 +507,4 @@
"i5\u0026gt;?"
]
]
}
}
File renamed without changes.
2 changes: 1 addition & 1 deletion spell_check/spell_check.sh
Expand Up @@ -14,9 +14,9 @@ FILES=$(find "$DIR" -type f \
-not -path "$DIR/backups/*" \
-not -path "$DIR/client/lib/*" \
-not -path "$DIR/client/node_modules/*" \
-not -path "$DIR/client/test_data/*" \
-not -path "$DIR/client/webpack_output/*" \
-not -path "$DIR/client/package-lock.json" \
-not -path "$DIR/client/test_data/*" \
-not -path "$DIR/data/ongoing_tables/*" \
-not -path "$DIR/data/specific_deals/*" \
-not -path "$DIR/data/emojis.json" \
Expand Down

0 comments on commit eeaaf3a

Please sign in to comment.