Skip to content

PixievoltNo1/zapster-solitaire-logic

Repository files navigation

This package provides the game logic of Zapster Solitaire, my original solitaire/patience game, as well as utilities and examples for bot play. I made it available in the hopes of seeing fellow coders develop better bot players or interesting game variations with it.

Learn how to play Zapster Solitaire or play the Web version.

Everything here is for use by fellow code nerds. If you only want to play Zapster Solitaire without doing any coding, use the Web version above (not open source).

This project has a Code of Conduct. By participating in the Git repo or issues tracker, you agree to be as courteous, welcoming, and generally a lovely person as its terms require. 😊

Rules implementation: zapster.mjs

This module implements everything needed to play Zapster Solitaire, and it's the exact same module used by the Web version.

Card objects

Each object represents one card, and a given card's object will be reused as it reappears throughout the state and moveLog objects. It has these properties:

  • rank: Can be any of the values passed to start as settings.ranks.
  • suit: An integer in the range 0-3. It doesn't matter which suit you map to which integer, but the mapping the web game uses is 0 = hearts, 1 = spades, 2 = diamonds, and 3 = clubs.

Exported variable: state

Object

The state of the game in progress. It starts as null and is replaced with a new object whenever start and resumeGame are called. It is mutated as the current game progresses. Its properties are:

  • drawPile: An array representing the draw pile. The contents of this array should be considered private, but you can use state.drawPile.length to see how many cards remain.
  • noOfCells: The number of cells the player currently has.
  • cellCards: An array of cards currently placed in the cells. It only has elements for cells that have a card.
  • zaps: The number of zaps the player has left to use.

Exported function: start

Parameter: settings (object)
No return value

Starts a new game. settings requires the following properties:

  • decks: The number of copies of a deck that will be shuffled into the draw pile.
  • startingZaps: The number of available zaps at the start of the game.
  • startingCells: The number of cells at the start of the game.
  • ranks: An array of the card ranks that will be included in each deck copy. Any positive integer or string can be used as a rank, but only "J", "Q", and "K" will have the powers of Jacks, Queens, and Kings respectively, and only ranks that are numbers will be used by Jack and Queen powers. To use the "Aces have the number 1" rule, 1 must be used instead of "A".

Exported constant: stdSettings

Object

Has the properties quick and marathon. Each has an object usable as the settings parameter to the above start function, reflecting the settings used for the standard Quick and Marathon modes.

Exported function: draw

No parameters
No return value

Performs a draw move in the current game, and updates moveLog with the results.

Exported function: zap

Parameter: target (card)
No return value

Uses a zap on target (which must be an object held in state.cellCards), and updates moveLog with the results.

Exported variable: moveLog

Object

The results of the most recent move. Replaced with a new object for each move. Has the following properties:

  • (optional) drew: The card drawn at the start of a draw move.
  • (optional) zapped: The chosen card for a zap move.
  • (optional) discards: An array of cards sent from the cells to the trash. Doesn't contain moveLog.drew or moveLog.zapped. For draw moves, the absence of this property means the drawn card matched nothing and was placed in a cell. For zap moves, this property always exists but may be an empty array.
  • (optional) jackPower: An object representing the results of a Jack's power. Contains these properties:
    • success: A boolean indicating whether there was a numbered card for this power to use.
    • (optional) usedValueOf: The card whose number was used for this power.
    • (optional) draws: An array of cards drawn via this power.
  • (optional) queenPower: An object representing the results of a Queen's power. Contains these properties:
    • success: As for jackPower.
    • (optional) usedValueOf: As for jackPower.
    • (optional) changedFrom: The previous number of cells the player had.
  • (optional) kingPower: true if a King's power granted a zap.
  • (optional) won: true if the game ended with the player's victory!
  • (optional) lost: An array of cards that couldn't be placed in cells, resulting in the player losing the game.

Exported function: analyze

No parameters
Returns an object

Determines various pieces of data about the game in progress that players would find interesting. In the web game, this function provides the data for the "Cards to Draw" feature. The returned object has these properties:

  • drawPileCounts: An object with a property for each rank in the game settings, where each value is the number of cards of that rank remaining in the draw pile. (Someone playing this game in real life could figure this out by adding together the cards in the trash pile and cells, and subtracting them all from the cards they know they started with.)
  • cellCounts: Like drawPileCounts, but instead counting cards in the cells.
  • (optional) jackPower: Present if there's a Jack and a numbered card in the cells. It's an object detailing what happens if the Jack's power were activated now, with the following properties:
    • draws: The number of cards to be drawn, before applying the rule "If there are not enough cards remaining in the draw pile, draw all of them".
    • loseOnDraw: A boolean indicating whether you would lose if your next move were a draw, and the drawn card were a Jack. Calculated after applying the rule mentioned above, with the draw pile not having the drawn Jack.
  • (optional) queenPower: Like jackPower, but for Queens. The object has these properties:
    • cells: The number of cells you would have.
    • lose: A boolean indicating whether this power would make you lose the game.

Exported function: hasPower

Parameter: card ([card]#card-objects())
Returns a boolean

Check whether card has a power.

Exported function: suspendGame

No parameters
Returns an object

Mutates state into a form more suitable for serializing to JSON, returns it, and sets state to null. Pass the returned object to resumeGame below to continue the game.

Exported function: resumeGame

Parameters: data (object returned by suspendGame above), settings
No return value

Mutates data to reverse the changes of suspendGame and sets it to state, allowing the game to proceed. settings must be the same object used in the start call that started the game.

Bot proving grounds: botTrial.mjs

This is a CLI app for testing bot players for Zapster Solitaire. See its dedicated README for more info. It is not designed to be imported by another module.

Stricter rules enforcement: strictEnforcement.mjs

As zapster.mjs is made for use by a web app that already prevents illegal moves, it does not enforce these rules by default:

  • You cannot make any more moves once you've won or lost.
  • You must have at least one zap remaining to use a zap.
  • A card must be in a cell in order to zap it.

If you're writing a bot for Zapster and you want to avoid accidentally breaking these rules, you can import strictEnforcement.mjs. Its default export is a function that takes a zapster.mjs exports object (as you'd get from import * as myObject from "./zapster.mjs"; or await import("./zapster.mjs")), and returns an object that has the same interface but will throw errors when any rule above is broken. If you're using the botTrial.mjs app, it will do this for you when you use the --strict option.

Game design change proposal: zapster_proposal.mjs

This module implements a new version of the game rules - in short, aces are out, 10s are in, and starting cells are increased to 7. It is otherwise fully interchangeable with zapster.mjs, and bot authors are invited to play against both rulesets. It is hoped that for the best human & bot players, the new rules will increase the winrate but not to 100%, and the rate of losing to Jack powers will see no more than a slight increase.

About

Implementation of the rules of Zapster Solitaire

Resources

License

Code of conduct

Stars

Watchers

Forks

Packages

No packages published