/
Square.vue
148 lines (136 loc) · 5.24 KB
/
Square.vue
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
<template>
<div
ref="mainRef"
:class="{
'bg-stone-500': thisIsPossibleSpace,
'bg-stone-300': !thisIsPossibleSpace,
'bg-stone-400': (isDragging ? (checkersSettings.highlightMovesWhileDragging && thisIsAvailableSpaceForDrag) : (checkersSettings.highlightMoves && availableSpaces.includes(id)))
}"
class="border border-stone-600 flex items-center justify-center"
style="width: 12.5%; height: 100%;"
:data-id="id"
>
<slot v-if="thisIsPossibleSpace"></slot>
</div>
</template>
<script lang="ts" setup>
import { isPossibleSpace, emitter, piecesCurrentPlaces, checkersSettings, playerForPieceId, availableSpaces, spacesThatCanMove, score, piecesThatAreKings, spacesThatCanJump } from '@/experiments/checkers'
import { getNumbersFromPlace, placeBetweenPlaces } from "@/experiments/checkers/board"
import { computed, ref, watch, provide, toRef, onBeforeUnmount } from 'vue'
import Sortable from 'sortablejs'
const props = defineProps({
row: {
type: Number,
required: true,
},
col: {
type: Number,
required: true,
}
})
const emit = defineEmits([
'drag-started',
'drag-ended'
])
const id = computed(() => `${props.row}${props.col}`)
const thisIsPossibleSpace = computed(() => isPossibleSpace(props.row, props.col))
const mainRef = ref<HTMLElement|null>(null)
type DragStarted = {
row: number,
col: number,
pieceId: string,
availableMoves: string[],
}
const sortable = ref<Sortable|null>(null)
watch(
() => [mainRef.value, spacesThatCanMove.value[id.value], checkersSettings.value],
() => {
if (mainRef.value) {
if (sortable.value) sortable.value.destroy()
sortable.value = new Sortable(mainRef.value, {
group: {
name: "pieces",
pull: () => !!spacesThatCanMove.value[id.value],
put: () => thisIsAvailableSpaceForDrag.value
},
animation: 350,
disabled: !checkersSettings.value.running
|| (piecesCurrentPlaces.value[id.value] && !spacesThatCanMove.value[id.value])
|| (piecesCurrentPlaces.value[id.value] && (checkersSettings.value.forceJumps && Object.keys(spacesThatCanJump.value).length) && !spacesThatCanMove.value[id.value].jumpOptions.length),
onStart(event) {
event.item.style.zIndex = '10'
let player = event.item.dataset.player
let availableMoves = checkersSettings.value.forceJumps && spacesThatCanJump.value[id.value] ? spacesThatCanMove.value[id.value]?.jumpOptions : spacesThatCanMove.value[id.value]?.moveOptions
emitter.emit('drag-started', {
row: props.row,
col: props.col,
pieceId: event.item.dataset.pieceId,
player,
availableMoves,
} as DragStarted)
},
onEnd(event) {
emitter.emit('drag-ended')
},
onAdd(event) {
let previousSpace = event.from.dataset.id
if (!previousSpace) return
let prevExploded = getNumbersFromPlace(previousSpace)
let nextExploded = getNumbersFromPlace(id.value)
let isMoreThanOneJump = Math.abs(nextExploded[0] - prevExploded[0]) > 1 && Math.abs(nextExploded[1] - prevExploded[1]) > 1
if (isMoreThanOneJump) {
let placeBetween = placeBetweenPlaces(previousSpace, id.value)
delete piecesCurrentPlaces.value[placeBetween]
score.value[checkersSettings.value.activePlayer]++
}
let pieceId = event.item.dataset.pieceId
piecesCurrentPlaces.value[id.value] = pieceId
// Make king
if (pieceId
&& (
(id.value[0] == '0' && checkersSettings.value.activePlayer == 'red')
|| (id.value[0] == '7' && checkersSettings.value.activePlayer == 'black')
)
) {
piecesThatAreKings.value[pieceId] = true
}
// If forceJumps && another jump is available, keep current player
// If not forceJumps, and allowMultipleJumps, and another jump is available... the game must hand the turn management over to the players
// Unless we count it by the 'onMove' of the sortables vvv
checkersSettings.value.activePlayer = checkersSettings.value.activePlayer == 'black' ? 'red' : 'black'
},
onRemove(event) {
delete piecesCurrentPlaces.value[id.value]
},
onMove(evt) {
// See if there are any _more_ jumps to move. If so, add them to .availableJumps now,
// also remove them if we move to a different place
}
})
}
},
{ deep: true, immediate: true }
)
const isDragging = ref(false)
const thisIsAvailableSpaceForDrag = ref(false)
function onDragStarted(payload: DragStarted) {
isDragging.value = true
if (payload.availableMoves.includes(id.value)) {
thisIsAvailableSpaceForDrag.value = true
} else {
thisIsAvailableSpaceForDrag.value = false
}
}
emitter.on('drag-started', onDragStarted)
function onDragEnded() {
isDragging.value = false
thisIsAvailableSpaceForDrag.value = false
}
emitter.on('drag-ended', onDragEnded)
onBeforeUnmount(() => {
emitter.off('drag-started', onDragStarted)
emitter.off('drag-ended', onDragEnded)
})
provide('row', toRef(props, 'row'))
provide('col', toRef(props, 'col'))
</script>