mirror of
https://github.com/AndrioCelos/TableturfBattleApp.git
synced 2026-08-21 18:34:00 -05:00
@@ -3,7 +3,7 @@ class Card {
|
||||
name: string;
|
||||
rarity: Rarity;
|
||||
specialCost: number;
|
||||
grid: Space[][];
|
||||
grid: readonly (readonly Space[])[];
|
||||
size: number;
|
||||
|
||||
private minX: number;
|
||||
|
||||
41
TableturfBattleClient/src/CardList.ts
Normal file
41
TableturfBattleClient/src/CardList.ts
Normal file
@@ -0,0 +1,41 @@
|
||||
class CardList {
|
||||
readonly listElement: HTMLElement;
|
||||
readonly sortBox: HTMLSelectElement;
|
||||
readonly cardButtons: CardButton[] = [ ];
|
||||
|
||||
static readonly cardSortOrders: { [key: string]: ((a: Card, b: Card) => number) | undefined } = {
|
||||
'number': (a, b) => a.number - b.number,
|
||||
'name': (a, b) => a.name.localeCompare(b.name),
|
||||
'size': (a, b) => a.size != b.size ? a.size - b.size : a.number - b.number,
|
||||
'rarity': (a, b) => a.rarity != b.rarity ? a.rarity - b.rarity : a.number - b.number,
|
||||
}
|
||||
|
||||
constructor(listElement: HTMLElement, sortBox: HTMLSelectElement) {
|
||||
this.listElement = listElement;
|
||||
this.sortBox = sortBox;
|
||||
|
||||
sortBox.addEventListener('change', () => {
|
||||
const sortOrder = CardList.cardSortOrders[sortBox.value];
|
||||
if (sortOrder) {
|
||||
clearChildren(listElement);
|
||||
this.cardButtons.sort((a, b) => sortOrder(a.card, b.card));
|
||||
for (const button of this.cardButtons)
|
||||
listElement.appendChild(button.element);
|
||||
}
|
||||
});
|
||||
|
||||
for (const label in CardList.cardSortOrders) {
|
||||
const option = document.createElement('option');
|
||||
option.value = label;
|
||||
option.innerText = label;
|
||||
sortBox.appendChild(option);
|
||||
}
|
||||
}
|
||||
|
||||
static fromId(id: string, sortBoxId: string) { return new CardList(document.getElementById(id)!, document.getElementById(sortBoxId) as HTMLSelectElement); }
|
||||
|
||||
add(button: CardButton) {
|
||||
this.cardButtons.push(button);
|
||||
this.listElement.appendChild(button.element);
|
||||
}
|
||||
}
|
||||
@@ -17,7 +17,7 @@ let currentGame: {
|
||||
let enterGameTimeout: number | null = null;
|
||||
let currentReplay: {
|
||||
turns: Move[][],
|
||||
placements: { placements: Placement[], specialSpacesActivated: Point[] }[],
|
||||
placements: PlacementResults[],
|
||||
initialDrawOrder: number[][],
|
||||
drawOrder: number[][]
|
||||
} | null = null;
|
||||
|
||||
@@ -1,14 +1,18 @@
|
||||
/// <reference path="../CardList.ts"/>
|
||||
|
||||
const deckNameLabel2 = document.getElementById('deckName2')!;
|
||||
const deckEditSize = document.getElementById('deckEditSize')!;
|
||||
const deckCardListEdit = document.getElementById('deckCardListEdit')!;
|
||||
const cardList = document.getElementById('cardList')!;
|
||||
const cardList = CardList.fromId('cardList', 'cardListSortBox');
|
||||
const deckTestButton = document.getElementById('deckTestButton') as HTMLButtonElement;
|
||||
const deckSaveButton = document.getElementById('deckSaveButton') as HTMLButtonElement;
|
||||
const deckCancelButton = document.getElementById('deckCancelButton') as HTMLButtonElement;
|
||||
const deckCardListBackButton = document.getElementById('deckCardListBackButton') as HTMLLinkElement;
|
||||
const cardListSortBox = document.getElementById('cardListSortBox') as HTMLSelectElement;
|
||||
const testStageSelectionList = document.getElementById('testStageSelectionList')!;
|
||||
const testStageButtons: StageButton[] = [ ];
|
||||
const testStageSelectionDialog = document.getElementById('testStageSelectionDialog') as HTMLDialogElement;
|
||||
|
||||
const cardButtons: CardButton[] = [ ];
|
||||
const deckEditCardButtons: (CardButton | HTMLLabelElement)[] = [ ];
|
||||
|
||||
let selectedDeckCardIndex: number | null = null;
|
||||
@@ -54,10 +58,10 @@ function createDeckEditCardButton(index: number, card: number) {
|
||||
}
|
||||
|
||||
selectedDeckCardIndex = index;
|
||||
for (const button2 of cardButtons) {
|
||||
for (const button2 of cardList.cardButtons) {
|
||||
button2.checked = button2.card.number == card;
|
||||
}
|
||||
cardList.parentElement!.classList.add('selecting');
|
||||
cardList.listElement.parentElement!.classList.add('selecting');
|
||||
}
|
||||
});
|
||||
return button;
|
||||
@@ -82,10 +86,10 @@ function createDeckEditEmptySlotButton(index: number) {
|
||||
}
|
||||
|
||||
selectedDeckCardIndex = index;
|
||||
for (const button2 of cardButtons) {
|
||||
for (const button2 of cardList.cardButtons) {
|
||||
button2.checked = false;
|
||||
}
|
||||
cardList.parentElement!.classList.add('selecting');
|
||||
cardList.listElement.parentElement!.classList.add('selecting');
|
||||
}
|
||||
});
|
||||
element.appendChild(input);
|
||||
@@ -122,10 +126,10 @@ function initCardDatabase(cards: Card[]) {
|
||||
for (const card of cards) {
|
||||
const button = new CardButton('radio', card);
|
||||
button.inputElement.name = 'deckEditorCardList';
|
||||
cardButtons.push(button);
|
||||
cardList.add(button);
|
||||
button.inputElement.addEventListener('input', () => {
|
||||
if (button.inputElement.checked) {
|
||||
for (const button2 of cardButtons) {
|
||||
for (const button2 of cardList.cardButtons) {
|
||||
if (button2 != button)
|
||||
button2.checked = false;
|
||||
}
|
||||
@@ -143,14 +147,14 @@ function initCardDatabase(cards: Card[]) {
|
||||
deckEditCardButtons[selectedDeckCardIndex] = button3;
|
||||
deckEditUpdateSize();
|
||||
|
||||
cardList.parentElement!.classList.remove('selecting');
|
||||
cardList.listElement.parentElement!.classList.remove('selecting');
|
||||
if (!deckModified) {
|
||||
deckModified = true;
|
||||
window.addEventListener('beforeunload', onBeforeUnload_deckEditor);
|
||||
}
|
||||
}
|
||||
});
|
||||
cardList.appendChild(button.element);
|
||||
addTestCard(card);
|
||||
}
|
||||
}
|
||||
|
||||
@@ -164,24 +168,7 @@ deckCardListBackButton.addEventListener('click', e => {
|
||||
(o as HTMLElement).classList.remove('checked');
|
||||
}
|
||||
}
|
||||
cardList.parentElement!.classList.remove('selecting');
|
||||
});
|
||||
|
||||
const cardSortOrders: { [key: string]: ((a: Card, b: Card) => number) | undefined } = {
|
||||
'number': (a, b) => a.number - b.number,
|
||||
'name': (a, b) => a.name.localeCompare(b.name),
|
||||
'size': (a, b) => a.size != b.size ? a.size - b.size : a.number - b.number,
|
||||
'rarity': (a, b) => a.rarity != b.rarity ? a.rarity - b.rarity : a.number - b.number,
|
||||
}
|
||||
|
||||
cardListSortBox.addEventListener('change', () => {
|
||||
const sortOrder = cardSortOrders[cardListSortBox.value];
|
||||
if (sortOrder) {
|
||||
clearChildren(cardList);
|
||||
cardButtons.sort((a, b) => sortOrder(a.card, b.card));
|
||||
for (const button of cardButtons)
|
||||
cardList.appendChild(button.element);
|
||||
}
|
||||
cardList.listElement.parentElement!.classList.remove('selecting');
|
||||
});
|
||||
|
||||
function stopEditingDeck() {
|
||||
@@ -195,3 +182,39 @@ function onBeforeUnload_deckEditor(e: BeforeUnloadEvent) {
|
||||
e.preventDefault();
|
||||
return 'You have unsaved changes to your deck that will be lost. Are you sure you want to continue?';
|
||||
}
|
||||
|
||||
function addTestStage(stage: Stage) {
|
||||
const button = new StageButton(stage);
|
||||
testStageButtons.push(button);
|
||||
button.inputElement.name = 'stage';
|
||||
button.inputElement.addEventListener('input', () => {
|
||||
if (button.inputElement.checked) {
|
||||
stageRandomLabel.classList.remove('checked');
|
||||
for (const button2 of testStageButtons) {
|
||||
if (button2 != button)
|
||||
button2.element.classList.remove('checked');
|
||||
}
|
||||
|
||||
clearChildren(testDeckList);
|
||||
testDeckCardButtons.splice(0);
|
||||
|
||||
for (const el of deckEditCardButtons) {
|
||||
const card = (el as CardButton).card;
|
||||
if (card) {
|
||||
addTestDeckCard(card);
|
||||
}
|
||||
}
|
||||
|
||||
testStageSelectionDialog.close();
|
||||
initTest(stage);
|
||||
}
|
||||
});
|
||||
button.setStartSpaces(2);
|
||||
testStageSelectionList.appendChild(button.element);
|
||||
}
|
||||
|
||||
deckTestButton.addEventListener('click', _ => {
|
||||
for (const button of testStageButtons)
|
||||
button.checked = false;
|
||||
testStageSelectionDialog.showModal();
|
||||
});
|
||||
|
||||
@@ -38,6 +38,20 @@ const showDeckCloseButton = document.getElementById('showDeckCloseButton') as HT
|
||||
const playContainers = Array.from(document.getElementsByClassName('playContainer')) as HTMLDivElement[];
|
||||
playContainers.sort((a, b) => parseInt(a.dataset.index || '0') - parseInt(b.dataset.index || '0'));
|
||||
|
||||
const testControls = document.getElementById('testControls')!;
|
||||
const testDeckList = document.getElementById('testDeckList')!;
|
||||
const testAllCardsList = CardList.fromId('testAllCardsList', 'testAllCardsListSortBox');
|
||||
const testPlacementList = document.getElementById('testPlacementList')!;
|
||||
const testDeckButton = CheckButton.fromId('testDeckButton');
|
||||
const testDeckContainer = document.getElementById('testDeckContainer')!;
|
||||
const testAllCardsButton = CheckButton.fromId('testAllCardsButton');
|
||||
const testAllCardsContainer = document.getElementById('testAllCardsContainer')!;
|
||||
const testUndoButton = document.getElementById('testUndoButton') as HTMLButtonElement;
|
||||
const testBackButton = document.getElementById('testBackButton') as HTMLButtonElement;
|
||||
const testDeckCardButtons: CardButton[] = [ ];
|
||||
const testPlacements: { card: Card, placementResults: PlacementResults }[] = [ ];
|
||||
const testCardListBackdrop = document.getElementById('testCardListBackdrop')!;
|
||||
|
||||
let testMode = false;
|
||||
let canPlay = false;
|
||||
|
||||
@@ -55,23 +69,60 @@ cols[4][4] = Space.SpecialInactive2;
|
||||
board.resize(cols);
|
||||
|
||||
function initGame() {
|
||||
testMode = false;
|
||||
gamePage.classList.remove('deckTest');
|
||||
playControls.hidden = false;
|
||||
resultContainer.hidden = true;
|
||||
replayControls.hidden = true;
|
||||
gameButtonsContainer.hidden = false;
|
||||
testControls.hidden = true;
|
||||
showPage('game');
|
||||
}
|
||||
|
||||
function initReplay() {
|
||||
testMode = false;
|
||||
gamePage.classList.remove('deckTest');
|
||||
playControls.hidden = true;
|
||||
resultContainer.hidden = true;
|
||||
replayControls.hidden = false;
|
||||
gameButtonsContainer.hidden = true;
|
||||
testControls.hidden = true;
|
||||
canPlay = false;
|
||||
showPage('game');
|
||||
clearPlayContainers();
|
||||
turnNumberLabel.setTurnNumber(1);
|
||||
}
|
||||
|
||||
function initTest(stage: Stage) {
|
||||
currentGame = { id: 'test', maxPlayers: 2, players: [ ], webSocket: null, turnNumber: 1, me: { playerIndex: 0, move: null, deck: null, hand: null, cardsUsed: [ ] } };
|
||||
board.resize(stage.copyGrid());
|
||||
const startSpaces = stage.getStartSpaces(2);
|
||||
for (let i = 0; i < 2; i++)
|
||||
board.grid[startSpaces[i].x][startSpaces[i].y] = Space.SpecialInactive1 | i;
|
||||
board.refresh();
|
||||
|
||||
for (var o of playerBars)
|
||||
o.element.hidden = true;
|
||||
testMode = true;
|
||||
testPlacements.splice(0);
|
||||
clearChildren(testPlacementList);
|
||||
gamePage.classList.add('deckTest');
|
||||
gamePage.dataset.myPlayerIndex = '0';
|
||||
gamePage.dataset.uiBaseColourIsSpecialColour = 'true';
|
||||
playControls.hidden = true;
|
||||
resultContainer.hidden = true;
|
||||
replayControls.hidden = true;
|
||||
gameButtonsContainer.hidden = false;
|
||||
testControls.hidden = false;
|
||||
clearPlayContainers();
|
||||
turnNumberLabel.setTurnNumber(null);
|
||||
showPage('game');
|
||||
|
||||
testDeckButton.checked = true;
|
||||
testAllCardsButton.checked = false;
|
||||
setTestListPage(false);
|
||||
}
|
||||
|
||||
replayNextButton.addEventListener('click', _ => {
|
||||
if (currentGame == null || currentReplay == null || currentGame.turnNumber > 12) return;
|
||||
|
||||
@@ -152,27 +203,10 @@ replayPreviousButton.addEventListener('click', _ => {
|
||||
el.innerText = '';
|
||||
}
|
||||
|
||||
// Unwind the turn.
|
||||
for (const p of result.specialSpacesActivated) {
|
||||
const space = board.grid[p.x][p.y];
|
||||
const player2 = currentGame.players[space & 3];
|
||||
player2.specialPoints--;
|
||||
player2.totalSpecialPoints--;
|
||||
board.grid[p.x][p.y] &= ~4;
|
||||
}
|
||||
currentGame.turnNumber--;
|
||||
|
||||
for (let i = result.placements.length - 1; i >= 0; i--) {
|
||||
const placement = result.placements[i];
|
||||
for (const p of placement.spacesAffected) {
|
||||
if (p.oldState == undefined) throw new TypeError('oldState missing');
|
||||
board.grid[p.space.x][p.space.y] = p.oldState;
|
||||
}
|
||||
}
|
||||
|
||||
undoTurn(result);
|
||||
currentGame!.turnNumber--;
|
||||
gamePage.classList.remove('gameEnded');
|
||||
turnNumberLabel.setTurnNumber(currentGame.turnNumber);
|
||||
board.refresh();
|
||||
turnNumberLabel.setTurnNumber(currentGame!.turnNumber);
|
||||
|
||||
for (let i = 0; i < currentGame.players.length; i++) {
|
||||
const move = currentReplay.turns[currentGame.turnNumber - 1][i];
|
||||
@@ -186,6 +220,28 @@ replayPreviousButton.addEventListener('click', _ => {
|
||||
}
|
||||
});
|
||||
|
||||
function undoTurn(turn: PlacementResults) {
|
||||
for (const p of turn.specialSpacesActivated) {
|
||||
const space = board.grid[p.x][p.y];
|
||||
const player2 = currentGame!.players[space & 3];
|
||||
if (player2) {
|
||||
player2.specialPoints--;
|
||||
player2.totalSpecialPoints--;
|
||||
}
|
||||
board.grid[p.x][p.y] &= ~4;
|
||||
}
|
||||
|
||||
for (let i = turn.placements.length - 1; i >= 0; i--) {
|
||||
const placement = turn.placements[i];
|
||||
for (const p of placement.spacesAffected) {
|
||||
if (p.oldState == undefined) throw new TypeError('oldState missing');
|
||||
board.grid[p.space.x][p.space.y] = p.oldState;
|
||||
}
|
||||
}
|
||||
|
||||
board.refresh();
|
||||
}
|
||||
|
||||
replayFlipBox.addEventListener('input', _ => {
|
||||
if (currentGame == null || currentReplay == null) return;
|
||||
if (replayAnimationAbortController) {
|
||||
@@ -203,6 +259,96 @@ replayFlipBox.addEventListener('input', _ => {
|
||||
board.resize();
|
||||
});
|
||||
|
||||
function addTestDeckCard(card: Card) {
|
||||
const button = new CardButton('radio', cardDatabase.get(card.number));
|
||||
button.inputElement.name = 'deckEditorTestSelectedCard'
|
||||
testDeckList.appendChild(button.element);
|
||||
testDeckCardButtons.push(button);
|
||||
button.inputElement.addEventListener('input', () => {
|
||||
if (button.checked) {
|
||||
for (const button2 of testDeckCardButtons.concat(testAllCardsList.cardButtons)) {
|
||||
if (button2 != button)
|
||||
button2.element.classList.remove('checked');
|
||||
}
|
||||
board.cardPlaying = card;
|
||||
if (isNaN(board.highlightX) || isNaN(board.highlightY)) {
|
||||
board.highlightX = board.startSpaces[board.playerIndex!].x - (board.flip ? 4 : 3);
|
||||
board.highlightY = board.startSpaces[board.playerIndex!].y - (board.flip ? 4 : 3);
|
||||
}
|
||||
board.cardRotation = board.flip ? 2 : 0;
|
||||
board.refreshHighlight();
|
||||
board.table.focus();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
function addTestCard(card: Card) {
|
||||
const button = new CardButton('radio', cardDatabase.get(card.number));
|
||||
button.inputElement.name = 'deckEditorTestSelectedCard'
|
||||
testAllCardsList.add(button);
|
||||
button.inputElement.addEventListener('input', () => {
|
||||
if (button.checked) {
|
||||
for (const button2 of testDeckCardButtons.concat(testAllCardsList.cardButtons)) {
|
||||
if (button2 != button)
|
||||
button2.element.classList.remove('checked');
|
||||
}
|
||||
board.cardPlaying = card;
|
||||
if (isNaN(board.highlightX) || isNaN(board.highlightY)) {
|
||||
board.highlightX = board.startSpaces[board.playerIndex!].x - (board.flip ? 4 : 3);
|
||||
board.highlightY = board.startSpaces[board.playerIndex!].y - (board.flip ? 4 : 3);
|
||||
}
|
||||
board.cardRotation = board.flip ? 2 : 0;
|
||||
board.refreshHighlight();
|
||||
board.table.focus();
|
||||
if (!testCardListBackdrop.hidden) {
|
||||
testCardListBackdrop.hidden = true;
|
||||
gamePage.removeChild(testAllCardsContainer);
|
||||
testControls.appendChild(testAllCardsContainer);
|
||||
setTestListPage(false);
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
testUndoButton.addEventListener('click', _ => {
|
||||
const turn = testPlacements.pop();
|
||||
if (turn) {
|
||||
undoTurn(turn.placementResults);
|
||||
testPlacementList.removeChild(testPlacementList.firstChild!);
|
||||
|
||||
for (const button of testDeckCardButtons.concat(testAllCardsList.cardButtons)) {
|
||||
if (button.card.number == turn.card.number)
|
||||
button.enabled = true;
|
||||
}
|
||||
|
||||
testUndoButton.disabled = testPlacements.length == 0;
|
||||
}
|
||||
});
|
||||
|
||||
testBackButton.addEventListener('click', _ => {
|
||||
showPage('deckEdit');
|
||||
});
|
||||
|
||||
testDeckButton.input.addEventListener('input', _ => {
|
||||
if (testDeckButton.checked) setTestListPage(false);
|
||||
});
|
||||
testAllCardsButton.input.addEventListener('input', _ => {
|
||||
if (testAllCardsButton.checked) setTestListPage(true);
|
||||
});
|
||||
function setTestListPage(showAllCards: boolean) {
|
||||
testDeckButton.checked = !showAllCards;
|
||||
testAllCardsButton.checked = showAllCards;
|
||||
testDeckContainer.hidden = showAllCards
|
||||
testAllCardsContainer.hidden = !showAllCards;
|
||||
}
|
||||
|
||||
document.getElementById('testAllCardsMobileButton')!.addEventListener('click', _ => {
|
||||
setTestListPage(true);
|
||||
testControls.removeChild(testAllCardsContainer);
|
||||
gamePage.appendChild(testAllCardsContainer);
|
||||
testCardListBackdrop.hidden = false;
|
||||
});
|
||||
|
||||
function loadPlayers(players: Player[]) {
|
||||
gamePage.dataset.players = players.length.toString();
|
||||
for (let i = 0; i < players.length; i++) {
|
||||
@@ -359,6 +505,7 @@ function showResult() {
|
||||
|
||||
function clearShowDeck() {
|
||||
showDeckContainer.hidden = true;
|
||||
testCardListBackdrop.hidden = true;
|
||||
clearChildren(showDeckListElement);
|
||||
showDeckButtons.splice(0);
|
||||
}
|
||||
@@ -522,7 +669,26 @@ board.onclick = (x, y) => {
|
||||
if (testMode) {
|
||||
const move: PlayMove = { card: board.cardPlaying, isPass: false, x, y, rotation: board.cardRotation, isSpecialAttack: false };
|
||||
const r = board.makePlacements([ move ]);
|
||||
testPlacements.push({ card: board.cardPlaying, placementResults: r });
|
||||
board.refresh();
|
||||
|
||||
var li = document.createElement('div');
|
||||
li.innerText = board.cardPlaying.name;
|
||||
if (testDeckCardButtons.find(b => b.card.number == board.cardPlaying!.number))
|
||||
li.classList.add('deckCard');
|
||||
else
|
||||
li.classList.add('externalCard');
|
||||
testPlacementList.insertBefore(li, testPlacementList.firstChild);
|
||||
|
||||
for (const button of testDeckCardButtons.concat(testAllCardsList.cardButtons)) {
|
||||
if (button.card.number == board.cardPlaying.number) {
|
||||
button.checked = false;
|
||||
button.enabled = false;
|
||||
}
|
||||
}
|
||||
|
||||
board.cardPlaying = null;
|
||||
testUndoButton.disabled = false;
|
||||
} else if (canPlay) {
|
||||
canPlay = false;
|
||||
// Send the play to the server.
|
||||
@@ -580,9 +746,11 @@ function focusFirstEnabledHandCard() {
|
||||
function toggleShowDeck() {
|
||||
if (showDeckContainer.hidden) {
|
||||
showDeckContainer.hidden = false;
|
||||
testCardListBackdrop.hidden = false;
|
||||
showDeckCloseButton.focus();
|
||||
} else {
|
||||
showDeckContainer.hidden = true;
|
||||
testCardListBackdrop.hidden = true;
|
||||
focusFirstEnabledHandCard();
|
||||
}
|
||||
}
|
||||
@@ -596,7 +764,7 @@ rotateRightButton.addEventListener('click', () => {
|
||||
board.refreshHighlight();
|
||||
});
|
||||
gameDeckButton.addEventListener('click', toggleShowDeck);
|
||||
showDeckCloseButton.addEventListener('click', () => showDeckContainer.hidden = true);
|
||||
showDeckCloseButton.addEventListener('click', toggleShowDeck);
|
||||
|
||||
document.addEventListener('keydown', e => {
|
||||
if (!pages.get('game')!.hidden) {
|
||||
|
||||
@@ -213,6 +213,7 @@ function initStageDatabase(stages: Stage[]) {
|
||||
});
|
||||
button.setStartSpaces(2);
|
||||
stageList.appendChild(button.element);
|
||||
addTestStage(stage);
|
||||
}
|
||||
document.getElementById('stageListLoadingSection')!.hidden = true;
|
||||
}
|
||||
|
||||
@@ -255,7 +255,7 @@ function loadReplay(base64: string) {
|
||||
webSocket: null
|
||||
};
|
||||
|
||||
board.resize(stage.grid);
|
||||
board.resize(stage.copyGrid());
|
||||
const startSpaces = stage.getStartSpaces(numPlayers);
|
||||
for (let i = 0; i < numPlayers; i++)
|
||||
board.grid[startSpaces[i].x][startSpaces[i].y] = Space.SpecialInactive1 | i;
|
||||
|
||||
@@ -2,3 +2,8 @@ interface Placement {
|
||||
players: number[],
|
||||
spacesAffected: { space: Point, newState: Space, oldState?: Space }[]
|
||||
}
|
||||
|
||||
interface PlacementResults {
|
||||
placements: Placement[],
|
||||
specialSpacesActivated: Point[]
|
||||
}
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
class Stage {
|
||||
name: string;
|
||||
grid: Space[][];
|
||||
grid: readonly (readonly Space[])[];
|
||||
startSpaces: Point[][];
|
||||
|
||||
constructor(name: string, grid: Space[][], startSpaces: Point[][]) {
|
||||
@@ -21,4 +21,8 @@ class Stage {
|
||||
}
|
||||
return list!;
|
||||
}
|
||||
|
||||
copyGrid() {
|
||||
return Array.from(this.grid, a => a.slice(0));
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user