mirror of
https://github.com/cassoule/flopobot_v2.git
synced 2026-01-18 16:37:40 +01:00
chore: solitaire auto-complete first steps
This commit is contained in:
File diff suppressed because one or more lines are too long
@@ -296,6 +296,71 @@ export function checkWinCondition(gameState) {
|
||||
return foundationCardCount === 52;
|
||||
}
|
||||
|
||||
/**
|
||||
* Checks if the game can be automatically solved (all tableau cards are face-up).
|
||||
* @param {Object} gameState - The current state of the game.
|
||||
* @returns {boolean} True if the game can be auto-solved.
|
||||
*/
|
||||
export function checkAutoSolve(gameState) {
|
||||
if (gameState.stockPile.length > 0 || gameState.wastePile.length > 0) return false;
|
||||
for (const pile of gameState.tableauPiles) {
|
||||
for (const card of pile) {
|
||||
if (!card.faceUp) return false;
|
||||
}
|
||||
}
|
||||
return true;
|
||||
}
|
||||
|
||||
export function autoSolveMoves(gameState) {
|
||||
const moves = [];
|
||||
const foundations = gameState.foundationPiles;
|
||||
const tableau = gameState.tableauPiles;
|
||||
|
||||
function canMoveToFoundation(card) {
|
||||
const foundationPile = foundations.find(pile => pile[pile.length - 1].suit === card.suit || pile.length === 0);
|
||||
if (foundationPile.length === 0) {
|
||||
return card.rank === 'A'; // Only Ace can be placed on empty foundation
|
||||
} else {
|
||||
const topCard = foundationPile[foundationPile.length - 1];
|
||||
return card.suit === topCard.suit && getRankValue(card.rank) === getRankValue(topCard.rank) + 1;
|
||||
}
|
||||
}
|
||||
|
||||
let moved;
|
||||
do {
|
||||
moved = false;
|
||||
|
||||
for (let i = 0; i < tableau.length; i++) {
|
||||
const column = tableau[i];
|
||||
if (column.length === 0) continue;
|
||||
|
||||
const card = column[column.length - 1]; // Top card of the tableau column
|
||||
const foundationIndex = foundations.findIndex(pile => pile[pile.length - 1].suit === card.suit || pile.length === 0);
|
||||
console.log(card.rank + card.suit + " to " + foundationIndex)
|
||||
if(canMoveToFoundation(card)) {
|
||||
tableau[i].pop()
|
||||
foundations[foundationIndex].push(card)
|
||||
console.log("moved" + card.rank + card.suit + " to " + foundationIndex)
|
||||
moved = true;
|
||||
moves.push({
|
||||
sourcePileType: 'tableauPiles',
|
||||
sourcePileIndex: i,
|
||||
sourceCardIndex: column.length - 1,
|
||||
destPileType: 'foundationPiles',
|
||||
destPileIndex: foundationIndex,
|
||||
cardsMoved: [card],
|
||||
cardWasFlipped: false,
|
||||
points: 11
|
||||
});
|
||||
}
|
||||
}
|
||||
} while (moved)//(foundations.reduce((acc, pile) => acc + pile.length, 0));
|
||||
|
||||
console.log("Auto-solve moves:");
|
||||
console.log(moves);
|
||||
return moves;
|
||||
}
|
||||
|
||||
/**
|
||||
* Reverts the game state to its previous state based on the last move in the history.
|
||||
* This function mutates the gameState object directly.
|
||||
|
||||
@@ -3,7 +3,7 @@ import express from 'express';
|
||||
// --- Game Logic Imports ---
|
||||
import {
|
||||
createDeck, shuffle, deal, isValidMove, moveCard, drawCard,
|
||||
checkWinCondition, createSeededRNG, seededShuffle, undoMove, draw3Cards
|
||||
checkWinCondition, createSeededRNG, seededShuffle, undoMove, draw3Cards, checkAutoSolve, autoSolveMoves
|
||||
} from '../../game/solitaire.js';
|
||||
|
||||
// --- Game State & Database Imports ---
|
||||
@@ -60,6 +60,7 @@ export function solitaireRoutes(client, io) {
|
||||
gameState.moves = 0;
|
||||
gameState.hist = [];
|
||||
gameState.hardMode = hardMode ?? false;
|
||||
gameState.autocompleting = false;
|
||||
activeSolitaireGames[userId] = gameState;
|
||||
|
||||
res.json({ success: true, gameState });
|
||||
@@ -94,6 +95,7 @@ export function solitaireRoutes(client, io) {
|
||||
seed: sotd.seed,
|
||||
hist: [],
|
||||
hardMode: false,
|
||||
autocompleting: false,
|
||||
};
|
||||
|
||||
activeSolitaireGames[userId] = gameState;
|
||||
@@ -140,6 +142,13 @@ export function solitaireRoutes(client, io) {
|
||||
moveCard(gameState, moveData);
|
||||
updateGameStats(gameState, 'move', moveData);
|
||||
|
||||
const canAutoSolve = checkAutoSolve(gameState);
|
||||
if (canAutoSolve) {
|
||||
gameState.autocompleting = true;
|
||||
// TODO: start auto-completing moves with interval
|
||||
autoSolveMoves(gameState)
|
||||
}
|
||||
|
||||
const win = checkWinCondition(gameState);
|
||||
if (win) {
|
||||
gameState.isDone = true;
|
||||
|
||||
Reference in New Issue
Block a user