Socket
Socket
Sign inDemoInstall

gin-rummy

Package Overview
Dependencies
Maintainers
1
Versions
8
Alerts
File Explorer

Advanced tools

Socket logo

Install Socket

Detect and block malicious and high-risk dependencies

Install

gin-rummy - npm Package Compare versions

Comparing version 0.0.6 to 0.0.7

dist/components/LogSection.js

15

dist/components/App.js

@@ -26,4 +26,5 @@ "use strict";

const Card_1 = require("./Card");
const Log_1 = require("./Log");
const LogSection_1 = require("./LogSection");
const DiscardSection_1 = require("./DiscardSection");
const StockSection_1 = require("./StockSection");
const GameSummary_1 = require("./GameSummary");

@@ -37,7 +38,10 @@ const MultiHandDisplay_1 = require("./MultiHandDisplay");

const [, forceRender] = react_1.useReducer((s) => s + 1, 0);
const { cheatMode } = context_1.useConfig();
return (react_1.default.createElement(ink_1.Box, { flexDirection: "column" },
react_1.default.createElement(GameSummary_1.GameSummary, null),
game.outcome ? (react_1.default.createElement(MultiHandDisplay_1.MultiHandDisplay, null)) : (react_1.default.createElement(Card_1.PlayerHand, { hand: game.hands[0], playerIndex: 0 })),
game.outcome || cheatMode ? react_1.default.createElement(MultiHandDisplay_1.MultiHandDisplay, null) : null,
!game.outcome || cheatMode ? react_1.default.createElement(Card_1.PlayerHand, null) : null,
cheatMode ? react_1.default.createElement(StockSection_1.StockSection, null) : null,
react_1.default.createElement(DiscardSection_1.DiscardSection, null),
react_1.default.createElement(Log_1.LogSection, null),
react_1.default.createElement(LogSection_1.LogSection, null),
react_1.default.createElement(InputSection_1.InputSection, { forceRender: forceRender })));

@@ -47,5 +51,6 @@ };

const [showWelcome, setShowWelcome] = react_1.useState(true);
return (react_1.default.createElement(context_1.GameProvider, null,
react_1.default.createElement(context_1.SelectionProvider, null, showWelcome ? (react_1.default.createElement(WelcomePage_1.WelcomePage, { onReady: () => setShowWelcome(false) })) : (react_1.default.createElement(GameContent, null)))));
return (react_1.default.createElement(context_1.ConfigProvider, null,
react_1.default.createElement(context_1.GameProvider, null,
react_1.default.createElement(context_1.SelectionProvider, null, showWelcome ? (react_1.default.createElement(WelcomePage_1.WelcomePage, { onReady: () => setShowWelcome(false) })) : (react_1.default.createElement(GameContent, null))))));
};
exports.App = App;

@@ -22,12 +22,16 @@ "use strict";

? "#ff0000"
: "red"
: "#ee2222"
: isFocused
? "white"
: "#bbbbbb" },
? "#f2f2f2"
: "#dddddd" },
"\u00A0",
cards_1.getCardName(card),
react_1.default.createElement(ink_1.Text
// backgroundColor={isFocused ? "#444444" : undefined}
, {
// backgroundColor={isFocused ? "#444444" : undefined}
underline: isFocused }, cards_1.getCardName(card)),
"\u00A0"));
};
exports.CardComponent = CardComponent;
const colors = ["#332800", "#003333", "#330033"];
const colors = ["#241808", "#081d1d", "#1d081d"];
const Meld = ({ children, colorIndex, }) => {

@@ -38,3 +42,5 @@ return (react_1.default.createElement(ink_1.Box, null,

exports.Meld = Meld;
const PlayerHand = ({ hand, playerIndex, }) => {
const PlayerHand = () => {
const { game } = context_1.useGame();
const hand = game.hands[0];
const melds = [...hand.melds];

@@ -46,3 +52,3 @@ if (hand.deadwood.length) {

react_1.default.createElement(ink_1.Box, { justifyContent: "space-between", paddingBottom: 1 },
react_1.default.createElement(Player_1.Player, { playerIndex: playerIndex })),
react_1.default.createElement(Player_1.Player, { playerIndex: 0 })),
react_1.default.createElement(ink_1.Box, null, melds.length > 0 ? (addSpaceBetween(melds.map((s, i) => (react_1.default.createElement(exports.Meld, { key: `hand-comp-meld-${i}`, colorIndex: i }, s.map((c, i) => (react_1.default.createElement(exports.CardComponent, { key: `meld-card-${c[0]}-${c[1]}-${i}`, card: c, highlightSelected: true })))))))) : (react_1.default.createElement(ink_1.Text, null, "\u00A0")))));

@@ -49,0 +55,0 @@ };

@@ -22,5 +22,23 @@ "use strict";

Object.defineProperty(exports, "__esModule", { value: true });
exports.useCardSelection = exports.SelectionProvider = exports.useGame = exports.GameProvider = void 0;
exports.useCardSelection = exports.SelectionProvider = exports.useGame = exports.GameProvider = exports.useConfig = exports.ConfigProvider = void 0;
const ink_1 = require("ink");
const react_1 = __importStar(require("react"));
const game_1 = require("../game");
const configContext = react_1.createContext({
cheatMode: false,
});
const ConfigProvider = ({ children }) => {
const [cheatMode, setCheatMode] = react_1.useState(false);
ink_1.useInput((input, key) => {
if (key.ctrl && input === "u") {
setCheatMode(!cheatMode);
}
});
return (react_1.default.createElement(configContext.Provider, { value: { cheatMode } }, children));
};
exports.ConfigProvider = ConfigProvider;
const useConfig = () => {
return react_1.useContext(configContext);
};
exports.useConfig = useConfig;
// @ts-expect-error Allow erroneous default

@@ -27,0 +45,0 @@ const gameContext = react_1.createContext(null);

@@ -99,7 +99,7 @@ "use strict";

if (turnState.awaiting === "draw") {
const drawFrom = input === "1" || key.leftArrow
const drawFrom = game.stockAllowed && input === "s"
? "stock"
: input === "2" || key.rightArrow
: input === "d"
? "discard"
: input === "3" || key.downArrow
: input === "p"
? "pass"

@@ -188,3 +188,3 @@ : null;

return (react_1.default.createElement(react_1.default.Fragment, null,
react_1.default.createElement(ink_1.Text, null, "Your turn. Draw a card. Use arrow keys to select."),
react_1.default.createElement(ink_1.Text, null, "Your turn. Draw a card."),
confirming ? (react_1.default.createElement(ink_1.Text, null,

@@ -197,5 +197,5 @@ "Are you sure you want to",

"? (Press Enter to confirm. Any other key to return)")) : (react_1.default.createElement(ink_1.Text, null,
"Draw from",
game.stockAllowed ? " (←)Stock" : "",
" (\u2192)Discard (\u2193)Pass"))));
"Draw from the",
game.stockAllowed ? " (s)tock pile" : "",
", (d)iscard pile, or (p)ass"))));
}

@@ -208,3 +208,2 @@ if (game.nextAction === "discard") {

"Are you sure you want to discard",
" ",
react_1.default.createElement(Card_1.CardComponent, { card: selectedCard }),

@@ -211,0 +210,0 @@ "? (Press Enter to confirm. Any other key to return)")) : (react_1.default.createElement(ink_1.Text, null,

@@ -15,4 +15,4 @@ "use strict";

react_1.default.createElement(Card_1.HandComponent, { hand: game.hands[0], playerIndex: 0, hidden: false }),
react_1.default.createElement(Card_1.HandComponent, { hand: game.hands[1], playerIndex: 1, hidden: game.outcome ? false : true })));
react_1.default.createElement(Card_1.HandComponent, { hand: game.hands[1], playerIndex: 1, hidden: game.outcome ? false : false })));
}
exports.MultiHandDisplay = MultiHandDisplay;

@@ -8,3 +8,3 @@ "use strict";

function takeDrawTurn(state) {
const hand = new hand_1.Hand(state.hand);
const hand = new hand_1.Hand([...state.hand]);
const scoreWithout = hand.score;

@@ -14,5 +14,6 @@ hand.addCard(getLast(state.discard));

const scoreWithDiscard = hand.score;
const from = state.stockAllowed && scoreWithout <= scoreWithDiscard
? "stock"
: "discard";
let from = scoreWithout <= scoreWithDiscard ? "stock" : "discard";
if (from === "stock" && !state.stockAllowed) {
from = "pass";
}
const action = {

@@ -19,0 +20,0 @@ type: "draw",

"use strict";
Object.defineProperty(exports, "__esModule", { value: true });
exports.getScore = exports.getMelds = exports.getSets = exports.getSequences = exports.drawHands = exports.getShuffledDeck = exports.getDeckFromString = exports.printDeck = exports.getDeck = exports.shuffleDeck = exports.sortByRank = void 0;
exports.getScore = exports.getAllMelds = exports.getMelds = exports.getSets = exports.getSequences = exports.drawHands = exports.getShuffledDeck = exports.getDeckFromString = exports.printDeck = exports.getDeck = exports.shuffleDeck = exports.sortByRank = void 0;
const crypto_1 = require("crypto");

@@ -38,3 +38,6 @@ const cards_1 = require("./cards");

function getDeckFromString(str) {
const result = str.split(/[ ,]+/).map((n) => {
const result = str
.trim()
.split(/[\s,]+/)
.map((n) => {
return [

@@ -83,5 +86,9 @@ cards_1.rankNames.indexOf(n.slice(0, -1)),

const cards = bySuits[s];
if (cards.length === 0) {
// No cards in suit
continue;
}
const minForMeld = 3;
let count = 1;
let lastValue = byRank[0][0];
let lastValue = cards[0][0];
for (let i = 1; i <= cards.length; i++) {

@@ -139,2 +146,62 @@ if (cards[i] && cards[i][0] === lastValue + 1) {

exports.getMelds = getMelds;
function hasConflictingItems(a, b) {
for (let aItem of a) {
for (let bItem of b) {
if (aItem === bItem) {
return true;
}
}
}
return false;
}
// /**
// * Finds all possible combinations array of arrays after removing conflicting items
// * @param arr Array of arrays of items
// */
// function getCombinationsOfExclusionaryArrays<T>(
// aListofLists: T[][],
// bListofLists: T[][]
// ): T[][][] {
// for (let aList of aListofLists) {
// }
// return [arr];
// }
function getAllMelds(cards) {
const sets = getSets(cards);
const runs = getSequences(cards);
const melds = [...sets, ...runs];
let combinations = [melds];
function split(melds, set, run) {
return [
melds.filter((meld) => meld !== set),
melds.filter((meld) => meld !== run),
];
}
for (let run of runs) {
for (let set of sets) {
const isConflicting = hasConflictingItems(run, set);
if (isConflicting) {
combinations = combinations
.map((melds) => split(melds, set, run))
.flat(1);
}
}
}
const highestScoreMelds = combinations.reduce((a, b) => {
if (getScore(b.flat(1)) > getScore(a.flat(1))) {
return b;
}
return a;
});
// if (combinations.length > 1) {
// console.log({
// sets: sets.map(printDeck),
// runs: runs.map(printDeck),
// highestScoreMelds: highestScoreMelds.map(printDeck),
// combinations: combinations.map((comb) => comb.map(printDeck)),
// });
// }
return highestScoreMelds;
}
exports.getAllMelds = getAllMelds;
function getScore(cards) {

@@ -141,0 +208,0 @@ let score = 0;

@@ -38,7 +38,13 @@ "use strict";

this.handleDiscardAction(turn);
this.turns.push(turn);
}
if (turn.type === "draw") {
this.handleDrawAction(turn);
const card = this.handleDrawAction(turn);
if (card) {
this.turns.push({ ...turn, card });
}
else {
this.turns.push(turn);
}
}
this.turns.push(turn);
}

@@ -48,7 +54,7 @@ handleDrawAction(turn) {

if (turn.from === "pass") {
if (this.turnCount > 2) {
if (!this.stockAllowed && this.turnCount >= 2) {
this.stockAllowed = true;
}
this.handleEndTurn();
return;
return null;
}

@@ -67,2 +73,3 @@ if (turn.from === "stock" && !this.stockAllowed) {

this.nextAction = "discard";
return newCard;
}

@@ -69,0 +76,0 @@ handleDiscardAction(turn) {

@@ -9,4 +9,3 @@ "use strict";

this.lastDiscard = null;
this._sets = null;
this._sequences = null;
this._melds = null;
this._score = null;

@@ -31,22 +30,12 @@ this._deadwood = null;

clearCache() {
this._sets = null;
this._sequences = null;
this._melds = null;
this._deadwood = null;
this._score = null;
}
get sets() {
if (this._sets === null) {
this._sets = decks_1.getSets(this.cards);
get melds() {
if (this._melds === null) {
this._melds = decks_1.getAllMelds(this.cards);
}
return this._sets;
return this._melds;
}
get sequences() {
if (this._sequences === null) {
this._sequences = decks_1.getSequences(this.cards);
}
return this._sequences;
}
get melds() {
return [...this.sets, ...this.sequences];
}
get deadwood() {

@@ -53,0 +42,0 @@ if (this._deadwood === null) {

{
"name": "gin-rummy",
"version": "0.0.6",
"version": "0.0.7",
"main": "index.js",

@@ -17,2 +17,6 @@ "license": "MIT",

},
"repository": {
"type": "git",
"url": "https://github.com/jahredhope/gin-rummy.git"
},
"dependencies": {

@@ -19,0 +23,0 @@ "ink": "^3.0.8",

@@ -5,2 +5,4 @@ # gin-rummy

**Note:** This game is not complete. With some rules not yet implemented, and some interaction being less than refined. Hopefully it acts as a demonstration of Ink, interactive CLI applications, or just as a bit of fun.
### Getting Started

@@ -7,0 +9,0 @@

@@ -9,2 +9,3 @@ import { Card } from "./cards";

from: "discard" | "stock" | "pass";
card?: Card;
} & Ordered;

@@ -11,0 +12,0 @@ export type DiscardAction = {

@@ -8,3 +8,3 @@ import { Hand } from "./hand";

export function takeDrawTurn(state: TurnState): DrawAction {
const hand = new Hand(state.hand);
const hand = new Hand([...state.hand]);
const scoreWithout = hand.score;

@@ -14,6 +14,8 @@ hand.addCard(getLast(state.discard));

const scoreWithDiscard = hand.score;
const from =
state.stockAllowed && scoreWithout <= scoreWithDiscard
? "stock"
: "discard";
let from: "pass" | "stock" | "discard" =
scoreWithout <= scoreWithDiscard ? "stock" : "discard";
if (from === "stock" && !state.stockAllowed) {
from = "pass";
}
const action: DrawAction = {

@@ -20,0 +22,0 @@ type: "draw",

@@ -11,2 +11,3 @@ import { randomInt } from "crypto";

getCardName,
getSuitName,
} from "./cards";

@@ -48,8 +49,11 @@

export function getDeckFromString(str: string): Card[] {
const result = str.split(/[ ,]+/).map((n) => {
return [
rankNames.indexOf(n.slice(0, -1)),
-1 * suitNames.indexOf(n.slice(-1)) * altSuitNames.indexOf(n.slice(-1)),
];
}) as Card[];
const result = str
.trim()
.split(/[\s,]+/)
.map((n) => {
return [
rankNames.indexOf(n.slice(0, -1)),
-1 * suitNames.indexOf(n.slice(-1)) * altSuitNames.indexOf(n.slice(-1)),
];
}) as Card[];
return result;

@@ -99,5 +103,9 @@ }

const cards = bySuits[s];
if (cards.length === 0) {
// No cards in suit
continue;
}
const minForMeld = 3;
let count = 1;
let lastValue = byRank[0][0];
let lastValue = cards[0][0];
for (let i = 1; i <= cards.length; i++) {

@@ -154,2 +162,64 @@ if (cards[i] && cards[i][0] === lastValue + 1) {

function hasConflictingItems<T>(a: T[], b: T[]) {
for (let aItem of a) {
for (let bItem of b) {
if (aItem === bItem) {
return true;
}
}
}
return false;
}
// /**
// * Finds all possible combinations array of arrays after removing conflicting items
// * @param arr Array of arrays of items
// */
// function getCombinationsOfExclusionaryArrays<T>(
// aListofLists: T[][],
// bListofLists: T[][]
// ): T[][][] {
// for (let aList of aListofLists) {
// }
// return [arr];
// }
export function getAllMelds(cards: Card[]) {
const sets = getSets(cards);
const runs = getSequences(cards);
const melds: Card[][] = [...sets, ...runs];
let combinations: Card[][][] = [melds];
function split(melds: Card[][], set: Card[], run: Card[]) {
return [
melds.filter((meld) => meld !== set),
melds.filter((meld) => meld !== run),
];
}
for (let run of runs) {
for (let set of sets) {
const isConflicting = hasConflictingItems(run, set);
if (isConflicting) {
combinations = combinations
.map((melds) => split(melds, set, run))
.flat(1);
}
}
}
const highestScoreMelds = combinations.reduce((a, b) => {
if (getScore(b.flat(1)) > getScore(a.flat(1))) {
return b;
}
return a;
});
// if (combinations.length > 1) {
// console.log({
// sets: sets.map(printDeck),
// runs: runs.map(printDeck),
// highestScoreMelds: highestScoreMelds.map(printDeck),
// combinations: combinations.map((comb) => comb.map(printDeck)),
// });
// }
return highestScoreMelds;
}
export function getScore(cards: Card[]) {

@@ -156,0 +226,0 @@ let score = 0;

@@ -54,16 +54,21 @@ import { Card } from "./cards";

this.handleDiscardAction(turn);
this.turns.push(turn);
}
if (turn.type === "draw") {
this.handleDrawAction(turn);
const card = this.handleDrawAction(turn);
if (card) {
this.turns.push({ ...turn, card });
} else {
this.turns.push(turn);
}
}
this.turns.push(turn);
}
private handleDrawAction(turn: DrawAction) {
private handleDrawAction(turn: DrawAction): Card | null {
let newCard: Card | undefined;
if (turn.from === "pass") {
if (this.turnCount > 2) {
if (!this.stockAllowed && this.turnCount >= 2) {
this.stockAllowed = true;
}
this.handleEndTurn();
return;
return null;
}

@@ -81,2 +86,3 @@ if (turn.from === "stock" && !this.stockAllowed) {

this.nextAction = "discard";
return newCard!;
}

@@ -83,0 +89,0 @@ private handleDiscardAction(turn: DiscardAction) {

import { Card } from "./cards";
import { getSets, getSequences, getScore } from "./decks";
import { getSets, getSequences, getScore, getAllMelds } from "./decks";

@@ -11,4 +11,3 @@ export class Hand {

private _cards: Card[];
private _sets: Card[][] | null = null;
private _sequences: Card[][] | null = null;
private _melds: Card[][] | null = null;
private _score: number | null = null;

@@ -31,22 +30,12 @@ private _deadwood: Card[] | null = null;

private clearCache() {
this._sets = null;
this._sequences = null;
this._melds = null;
this._deadwood = null;
this._score = null;
}
private get sets() {
if (this._sets === null) {
this._sets = getSets(this.cards);
get melds(): Card[][] {
if (this._melds === null) {
this._melds = getAllMelds(this.cards);
}
return this._sets;
return this._melds;
}
private get sequences() {
if (this._sequences === null) {
this._sequences = getSequences(this.cards);
}
return this._sequences;
}
get melds() {
return [...this.sets, ...this.sequences];
}
get deadwood() {

@@ -53,0 +42,0 @@ if (this._deadwood === null) {

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

Sorry, the diff of this file is not supported yet

SocketSocket SOC 2 Logo

Product

  • Package Alerts
  • Integrations
  • Docs
  • Pricing
  • FAQ
  • Roadmap
  • Changelog

Packages

npm

Stay in touch

Get open source security insights delivered straight into your inbox.


  • Terms
  • Privacy
  • Security

Made with ⚡️ by Socket Inc