feat: add drag-and-drop reordering for Phase10 hand cards
- Implement pointer-based drag handlers for Phase10 player hand. - Add visual feedback including card scaling, rotation tilt, shadow, and slot indicators during drag. - Reorder hand array and animate cards to new positions on drop. - Prevent conflicts by ending active drags during scene transitions or state updates.
This commit is contained in:
parent
83ada10456
commit
d5a12ae559
|
|
@ -334,9 +334,9 @@ export function findLaydown(hand, phaseNum) {
|
||||||
const spec = getPhase(phaseNum);
|
const spec = getPhase(phaseNum);
|
||||||
if (!spec) return null;
|
if (!spec) return null;
|
||||||
|
|
||||||
// Per spec-group, enumerate candidate card subsets (sorted by wild-use asc).
|
// Backtracking combo search. Candidates are computed on-the-fly from the
|
||||||
const perGroupCandidates = spec.groups.map((s) => enumerateGroupCandidates(hand, s));
|
// cards not yet claimed by earlier groups, so wilds are allocated correctly
|
||||||
// Backtracking combo search.
|
// across groups regardless of which naturals each group consumes.
|
||||||
const used = new Set();
|
const used = new Set();
|
||||||
const out = [];
|
const out = [];
|
||||||
|
|
||||||
|
|
@ -348,12 +348,9 @@ export function findLaydown(hand, phaseNum) {
|
||||||
}
|
}
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
for (const cand of perGroupCandidates[idx]) {
|
const available = hand.filter((c) => !used.has(c.id));
|
||||||
let overlap = false;
|
const candidates = enumerateGroupCandidates(available, spec.groups[idx]);
|
||||||
for (const c of cand.cards) {
|
for (const cand of candidates) {
|
||||||
if (used.has(c.id)) { overlap = true; break; }
|
|
||||||
}
|
|
||||||
if (overlap) continue;
|
|
||||||
for (const c of cand.cards) used.add(c.id);
|
for (const c of cand.cards) used.add(c.id);
|
||||||
out.push({ kind: cand.kind, cards: cand.cards });
|
out.push({ kind: cand.kind, cards: cand.cards });
|
||||||
if (recurse(idx + 1)) return true;
|
if (recurse(idx + 1)) return true;
|
||||||
|
|
@ -380,6 +377,10 @@ function wilds(hand) {
|
||||||
function enumerateSetCandidates(hand, N) {
|
function enumerateSetCandidates(hand, N) {
|
||||||
const cands = [];
|
const cands = [];
|
||||||
const w = wilds(hand);
|
const w = wilds(hand);
|
||||||
|
// All-wild set: valid when paired with a group that contributes a natural.
|
||||||
|
if (w.length >= N) {
|
||||||
|
cands.push({ kind: 'set', cards: w.slice(0, N), wildsUsed: N, key: 'set:wild' });
|
||||||
|
}
|
||||||
for (let v = 1; v <= 12; v++) {
|
for (let v = 1; v <= 12; v++) {
|
||||||
const naturals = hand.filter((c) => c.value === v);
|
const naturals = hand.filter((c) => c.value === v);
|
||||||
if (naturals.length === 0) continue;
|
if (naturals.length === 0) continue;
|
||||||
|
|
@ -396,6 +397,10 @@ function enumerateSetCandidates(hand, N) {
|
||||||
function enumerateColorCandidates(hand, N) {
|
function enumerateColorCandidates(hand, N) {
|
||||||
const cands = [];
|
const cands = [];
|
||||||
const w = wilds(hand);
|
const w = wilds(hand);
|
||||||
|
// All-wild color group: valid when paired with a group that contributes a natural.
|
||||||
|
if (w.length >= N) {
|
||||||
|
cands.push({ kind: 'color', cards: w.slice(0, N), wildsUsed: N, key: 'color:wild' });
|
||||||
|
}
|
||||||
const colors = ['red', 'blue', 'yellow', 'green'];
|
const colors = ['red', 'blue', 'yellow', 'green'];
|
||||||
for (const col of colors) {
|
for (const col of colors) {
|
||||||
const naturals = hand.filter((c) => c.color === col);
|
const naturals = hand.filter((c) => c.color === col);
|
||||||
|
|
|
||||||
Loading…
Reference in New Issue