fix: Hex Wars - Kopf nach Mine korrekt, volles Grid bei Spielende
This commit is contained in:
@@ -175,10 +175,16 @@ function getGameForUser(id, requesterId) {
|
|||||||
|
|
||||||
if (!terrain.length) return { ...game, myScore:0, oppScore:0 };
|
if (!terrain.length) return { ...game, myScore:0, oppScore:0 };
|
||||||
|
|
||||||
// Fog anwenden
|
// Bei beendetem Spiel: vollständiges Grid ohne Fog
|
||||||
const visible = computeFog(grid, requesterId);
|
let maskedGrid, maskedTerrain;
|
||||||
const maskedGrid = grid.map((row,r) => row.map((cell,c) => visible[r][c] ? cell : (cell===requesterId ? cell : 0)));
|
if (game.status === 'finished') {
|
||||||
const maskedTerrain = terrain.map((row,r) => row.map((cell,c) => visible[r][c] ? cell : -1));
|
maskedGrid = grid;
|
||||||
|
maskedTerrain = terrain;
|
||||||
|
} else {
|
||||||
|
const visible = computeFog(grid, requesterId);
|
||||||
|
maskedGrid = grid.map((row,r) => row.map((cell,c) => visible[r][c] ? cell : (cell===requesterId ? cell : 0)));
|
||||||
|
maskedTerrain = terrain.map((row,r) => row.map((cell,c) => visible[r][c] ? cell : -1));
|
||||||
|
}
|
||||||
|
|
||||||
// Kopf des anfragenden Spielers mitliefern (für Frontend-Validierung)
|
// Kopf des anfragenden Spielers mitliefern (für Frontend-Validierung)
|
||||||
const myHead = requesterId === game.owner_id ? game.owner_head : game.opp_head;
|
const myHead = requesterId === game.owner_id ? game.owner_head : game.opp_head;
|
||||||
@@ -356,13 +362,15 @@ router.post('/:id/move', authenticate, (req, res) => {
|
|||||||
let status = 'active';
|
let status = 'active';
|
||||||
let winnerId = null;
|
let winnerId = null;
|
||||||
|
|
||||||
// Köpfe nach Zug
|
// Effektiver Kopf nach Zug (bei Mine: zurückgesetzter Kopf, sonst neue Position)
|
||||||
const oppHeadStr = game.owner_id === me ? game.opp_head : game.owner_head;
|
const oppHeadStr = game.owner_id === me ? game.opp_head : game.owner_head;
|
||||||
const [oppHR, oppHC] = oppHeadStr ? oppHeadStr.split(',').map(Number) : [null, null];
|
const [oppHR, oppHC] = oppHeadStr ? oppHeadStr.split(',').map(Number) : [null, null];
|
||||||
const myNewHR = row, myNewHC = col;
|
const effectiveMyHeadStr = game.owner_id === me ? newOwnerHead : newOppHead;
|
||||||
|
const [effectiveMyHR, effectiveMyHC] = effectiveMyHeadStr
|
||||||
|
? effectiveMyHeadStr.split(',').map(Number) : [row, col];
|
||||||
|
|
||||||
// Spielende: niemand kann mehr ziehen
|
// Spielende: niemand kann mehr ziehen
|
||||||
if (!canMove(grid, terrain, opponent, oppHR, oppHC) && !canMove(grid, terrain, me, myNewHR, myNewHC)) {
|
if (!canMove(grid, terrain, opponent, oppHR, oppHC) && !canMove(grid, terrain, me, effectiveMyHR, effectiveMyHC)) {
|
||||||
status = 'finished';
|
status = 'finished';
|
||||||
} else if (!canMove(grid, terrain, opponent, oppHR, oppHC)) {
|
} else if (!canMove(grid, terrain, opponent, oppHR, oppHC)) {
|
||||||
nextTurn = me;
|
nextTurn = me;
|
||||||
|
|||||||
@@ -175,11 +175,15 @@ function GameBoard({ game, myId, onMove, toast }) {
|
|||||||
} catch {}
|
} catch {}
|
||||||
}, [game.last_event]);
|
}, [game.last_event]);
|
||||||
|
|
||||||
// Schlangen-Kopf aus Server-Response
|
// Schlangen-Köpfe aus Server-Response
|
||||||
const myHeadStr = game.myHead;
|
const myHeadStr = game.myHead;
|
||||||
const myHead = myHeadStr ? myHeadStr.split(',').map(Number) : null;
|
const myHead = myHeadStr ? myHeadStr.split(',').map(Number) : null;
|
||||||
const [myHR, myHC] = myHead ?? [null, null];
|
const [myHR, myHC] = myHead ?? [null, null];
|
||||||
|
|
||||||
|
const oppHeadStr = game.oppHead;
|
||||||
|
const oppHead = oppHeadStr ? oppHeadStr.split(',').map(Number) : null;
|
||||||
|
const [oppHR, oppHC] = oppHead ?? [null, null];
|
||||||
|
|
||||||
const isAdjacentToHead = (r, c) => {
|
const isAdjacentToHead = (r, c) => {
|
||||||
if (myHR === null) return false;
|
if (myHR === null) return false;
|
||||||
return Math.abs(r - myHR) <= 1 && Math.abs(c - myHC) <= 1 && !(r === myHR && c === myHC);
|
return Math.abs(r - myHR) <= 1 && Math.abs(c - myHC) <= 1 && !(r === myHR && c === myHC);
|
||||||
@@ -258,7 +262,8 @@ function GameBoard({ game, myId, onMove, toast }) {
|
|||||||
const clic = canClick(r, c);
|
const clic = canClick(r, c);
|
||||||
const isPend = pending?.row === r && pending?.col === c;
|
const isPend = pending?.row === r && pending?.col === c;
|
||||||
const isBlast = blastHighlight.has(`${r}-${c}`);
|
const isBlast = blastHighlight.has(`${r}-${c}`);
|
||||||
const isHead = myHR === r && myHC === c; // eigener Kopf
|
const isHead = myHR === r && myHC === c; // eigener Kopf
|
||||||
|
const isOppHead = game.status === 'finished' && oppHR === r && oppHC === c; // Gegner-Kopf nur bei Spielende
|
||||||
const isFog = t === T_FOG;
|
const isFog = t === T_FOG;
|
||||||
const isRock = t === T_ROCK;
|
const isRock = t === T_ROCK;
|
||||||
const isGold = t === T_GOLD;
|
const isGold = t === T_GOLD;
|
||||||
@@ -287,7 +292,8 @@ function GameBoard({ game, myId, onMove, toast }) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
if (isBlast) { bg = '#ff440066'; border = '2px solid #ff4400'; }
|
if (isBlast) { bg = '#ff440066'; border = '2px solid #ff4400'; }
|
||||||
if (isHead && !isPend) { border = `2px solid ${myColor}`; } // Kopf immer markieren
|
if (isOppHead) { border = `2px solid ${oppColor}`; }
|
||||||
|
if (isHead && !isPend) { border = `2px solid ${myColor}`; } // eigener Kopf
|
||||||
if (isPend) { bg = myColor; border = `2px solid ${myColor}`; }
|
if (isPend) { bg = myColor; border = `2px solid ${myColor}`; }
|
||||||
else if (clic && !isPend && !isBlast && !isHead) border = `1px solid ${myColor}44`;
|
else if (clic && !isPend && !isBlast && !isHead) border = `1px solid ${myColor}44`;
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user