Mercurial
changeset 44:0cfd7d9277b0
[ReactGame] 2048
| author | MrJuneJune <me@mrjunejune.com> |
|---|---|
| date | Wed, 03 Dec 2025 18:34:22 -0800 |
| parents | 5e6a5d3c6868 |
| children | ac8626c7859c |
| files | react_games/public/current/current.js react_games/src/current.tsx |
| diffstat | 2 files changed, 732 insertions(+), 362 deletions(-) [+] |
line wrap: on
line diff
--- a/react_games/public/current/current.js Mon Dec 01 22:43:40 2025 -0800 +++ b/react_games/public/current/current.js Wed Dec 03 18:34:22 2025 -0800 @@ -26,277 +26,6 @@ mod )); - // node_modules/scheduler/cjs/scheduler.development.js - var require_scheduler_development = __commonJS({ - "node_modules/scheduler/cjs/scheduler.development.js"(exports) { - "use strict"; - (function() { - function performWorkUntilDeadline() { - needsPaint = false; - if (isMessageLoopRunning) { - var currentTime = exports.unstable_now(); - startTime = currentTime; - var hasMoreWork = true; - try { - a: { - isHostCallbackScheduled = false; - isHostTimeoutScheduled && (isHostTimeoutScheduled = false, localClearTimeout(taskTimeoutID), taskTimeoutID = -1); - isPerformingWork = true; - var previousPriorityLevel = currentPriorityLevel; - try { - b: { - advanceTimers(currentTime); - for (currentTask = peek(taskQueue); null !== currentTask && !(currentTask.expirationTime > currentTime && shouldYieldToHost()); ) { - var callback = currentTask.callback; - if ("function" === typeof callback) { - currentTask.callback = null; - currentPriorityLevel = currentTask.priorityLevel; - var continuationCallback = callback( - currentTask.expirationTime <= currentTime - ); - currentTime = exports.unstable_now(); - if ("function" === typeof continuationCallback) { - currentTask.callback = continuationCallback; - advanceTimers(currentTime); - hasMoreWork = true; - break b; - } - currentTask === peek(taskQueue) && pop(taskQueue); - advanceTimers(currentTime); - } else pop(taskQueue); - currentTask = peek(taskQueue); - } - if (null !== currentTask) hasMoreWork = true; - else { - var firstTimer = peek(timerQueue); - null !== firstTimer && requestHostTimeout( - handleTimeout, - firstTimer.startTime - currentTime - ); - hasMoreWork = false; - } - } - break a; - } finally { - currentTask = null, currentPriorityLevel = previousPriorityLevel, isPerformingWork = false; - } - hasMoreWork = void 0; - } - } finally { - hasMoreWork ? schedulePerformWorkUntilDeadline() : isMessageLoopRunning = false; - } - } - } - function push(heap, node) { - var index = heap.length; - heap.push(node); - a: for (; 0 < index; ) { - var parentIndex = index - 1 >>> 1, parent = heap[parentIndex]; - if (0 < compare(parent, node)) - heap[parentIndex] = node, heap[index] = parent, index = parentIndex; - else break a; - } - } - function peek(heap) { - return 0 === heap.length ? null : heap[0]; - } - function pop(heap) { - if (0 === heap.length) return null; - var first = heap[0], last = heap.pop(); - if (last !== first) { - heap[0] = last; - a: for (var index = 0, length = heap.length, halfLength = length >>> 1; index < halfLength; ) { - var leftIndex = 2 * (index + 1) - 1, left = heap[leftIndex], rightIndex = leftIndex + 1, right = heap[rightIndex]; - if (0 > compare(left, last)) - rightIndex < length && 0 > compare(right, left) ? (heap[index] = right, heap[rightIndex] = last, index = rightIndex) : (heap[index] = left, heap[leftIndex] = last, index = leftIndex); - else if (rightIndex < length && 0 > compare(right, last)) - heap[index] = right, heap[rightIndex] = last, index = rightIndex; - else break a; - } - } - return first; - } - function compare(a, b) { - var diff = a.sortIndex - b.sortIndex; - return 0 !== diff ? diff : a.id - b.id; - } - function advanceTimers(currentTime) { - for (var timer = peek(timerQueue); null !== timer; ) { - if (null === timer.callback) pop(timerQueue); - else if (timer.startTime <= currentTime) - pop(timerQueue), timer.sortIndex = timer.expirationTime, push(taskQueue, timer); - else break; - timer = peek(timerQueue); - } - } - function handleTimeout(currentTime) { - isHostTimeoutScheduled = false; - advanceTimers(currentTime); - if (!isHostCallbackScheduled) - if (null !== peek(taskQueue)) - isHostCallbackScheduled = true, isMessageLoopRunning || (isMessageLoopRunning = true, schedulePerformWorkUntilDeadline()); - else { - var firstTimer = peek(timerQueue); - null !== firstTimer && requestHostTimeout( - handleTimeout, - firstTimer.startTime - currentTime - ); - } - } - function shouldYieldToHost() { - return needsPaint ? true : exports.unstable_now() - startTime < frameInterval ? false : true; - } - function requestHostTimeout(callback, ms) { - taskTimeoutID = localSetTimeout(function() { - callback(exports.unstable_now()); - }, ms); - } - "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error()); - exports.unstable_now = void 0; - if ("object" === typeof performance && "function" === typeof performance.now) { - var localPerformance = performance; - exports.unstable_now = function() { - return localPerformance.now(); - }; - } else { - var localDate = Date, initialTime = localDate.now(); - exports.unstable_now = function() { - return localDate.now() - initialTime; - }; - } - var taskQueue = [], timerQueue = [], taskIdCounter = 1, currentTask = null, currentPriorityLevel = 3, isPerformingWork = false, isHostCallbackScheduled = false, isHostTimeoutScheduled = false, needsPaint = false, localSetTimeout = "function" === typeof setTimeout ? setTimeout : null, localClearTimeout = "function" === typeof clearTimeout ? clearTimeout : null, localSetImmediate = "undefined" !== typeof setImmediate ? setImmediate : null, isMessageLoopRunning = false, taskTimeoutID = -1, frameInterval = 5, startTime = -1; - if ("function" === typeof localSetImmediate) - var schedulePerformWorkUntilDeadline = function() { - localSetImmediate(performWorkUntilDeadline); - }; - else if ("undefined" !== typeof MessageChannel) { - var channel = new MessageChannel(), port = channel.port2; - channel.port1.onmessage = performWorkUntilDeadline; - schedulePerformWorkUntilDeadline = function() { - port.postMessage(null); - }; - } else - schedulePerformWorkUntilDeadline = function() { - localSetTimeout(performWorkUntilDeadline, 0); - }; - exports.unstable_IdlePriority = 5; - exports.unstable_ImmediatePriority = 1; - exports.unstable_LowPriority = 4; - exports.unstable_NormalPriority = 3; - exports.unstable_Profiling = null; - exports.unstable_UserBlockingPriority = 2; - exports.unstable_cancelCallback = function(task) { - task.callback = null; - }; - exports.unstable_forceFrameRate = function(fps) { - 0 > fps || 125 < fps ? console.error( - "forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported" - ) : frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5; - }; - exports.unstable_getCurrentPriorityLevel = function() { - return currentPriorityLevel; - }; - exports.unstable_next = function(eventHandler) { - switch (currentPriorityLevel) { - case 1: - case 2: - case 3: - var priorityLevel = 3; - break; - default: - priorityLevel = currentPriorityLevel; - } - var previousPriorityLevel = currentPriorityLevel; - currentPriorityLevel = priorityLevel; - try { - return eventHandler(); - } finally { - currentPriorityLevel = previousPriorityLevel; - } - }; - exports.unstable_requestPaint = function() { - needsPaint = true; - }; - exports.unstable_runWithPriority = function(priorityLevel, eventHandler) { - switch (priorityLevel) { - case 1: - case 2: - case 3: - case 4: - case 5: - break; - default: - priorityLevel = 3; - } - var previousPriorityLevel = currentPriorityLevel; - currentPriorityLevel = priorityLevel; - try { - return eventHandler(); - } finally { - currentPriorityLevel = previousPriorityLevel; - } - }; - exports.unstable_scheduleCallback = function(priorityLevel, callback, options) { - var currentTime = exports.unstable_now(); - "object" === typeof options && null !== options ? (options = options.delay, options = "number" === typeof options && 0 < options ? currentTime + options : currentTime) : options = currentTime; - switch (priorityLevel) { - case 1: - var timeout = -1; - break; - case 2: - timeout = 250; - break; - case 5: - timeout = 1073741823; - break; - case 4: - timeout = 1e4; - break; - default: - timeout = 5e3; - } - timeout = options + timeout; - priorityLevel = { - id: taskIdCounter++, - callback, - priorityLevel, - startTime: options, - expirationTime: timeout, - sortIndex: -1 - }; - options > currentTime ? (priorityLevel.sortIndex = options, push(timerQueue, priorityLevel), null === peek(taskQueue) && priorityLevel === peek(timerQueue) && (isHostTimeoutScheduled ? (localClearTimeout(taskTimeoutID), taskTimeoutID = -1) : isHostTimeoutScheduled = true, requestHostTimeout(handleTimeout, options - currentTime))) : (priorityLevel.sortIndex = timeout, push(taskQueue, priorityLevel), isHostCallbackScheduled || isPerformingWork || (isHostCallbackScheduled = true, isMessageLoopRunning || (isMessageLoopRunning = true, schedulePerformWorkUntilDeadline()))); - return priorityLevel; - }; - exports.unstable_shouldYield = shouldYieldToHost; - exports.unstable_wrapCallback = function(callback) { - var parentPriorityLevel = currentPriorityLevel; - return function() { - var previousPriorityLevel = currentPriorityLevel; - currentPriorityLevel = parentPriorityLevel; - try { - return callback.apply(this, arguments); - } finally { - currentPriorityLevel = previousPriorityLevel; - } - }; - }; - "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error()); - })(); - } - }); - - // node_modules/scheduler/index.js - var require_scheduler = __commonJS({ - "node_modules/scheduler/index.js"(exports, module) { - "use strict"; - if (false) { - module.exports = null; - } else { - module.exports = require_scheduler_development(); - } - } - }); - // node_modules/react/cjs/react.development.js var require_react_development = __commonJS({ "node_modules/react/cjs/react.development.js"(exports, module) { @@ -1252,6 +981,277 @@ } }); + // node_modules/scheduler/cjs/scheduler.development.js + var require_scheduler_development = __commonJS({ + "node_modules/scheduler/cjs/scheduler.development.js"(exports) { + "use strict"; + (function() { + function performWorkUntilDeadline() { + needsPaint = false; + if (isMessageLoopRunning) { + var currentTime = exports.unstable_now(); + startTime = currentTime; + var hasMoreWork = true; + try { + a: { + isHostCallbackScheduled = false; + isHostTimeoutScheduled && (isHostTimeoutScheduled = false, localClearTimeout(taskTimeoutID), taskTimeoutID = -1); + isPerformingWork = true; + var previousPriorityLevel = currentPriorityLevel; + try { + b: { + advanceTimers(currentTime); + for (currentTask = peek(taskQueue); null !== currentTask && !(currentTask.expirationTime > currentTime && shouldYieldToHost()); ) { + var callback = currentTask.callback; + if ("function" === typeof callback) { + currentTask.callback = null; + currentPriorityLevel = currentTask.priorityLevel; + var continuationCallback = callback( + currentTask.expirationTime <= currentTime + ); + currentTime = exports.unstable_now(); + if ("function" === typeof continuationCallback) { + currentTask.callback = continuationCallback; + advanceTimers(currentTime); + hasMoreWork = true; + break b; + } + currentTask === peek(taskQueue) && pop(taskQueue); + advanceTimers(currentTime); + } else pop(taskQueue); + currentTask = peek(taskQueue); + } + if (null !== currentTask) hasMoreWork = true; + else { + var firstTimer = peek(timerQueue); + null !== firstTimer && requestHostTimeout( + handleTimeout, + firstTimer.startTime - currentTime + ); + hasMoreWork = false; + } + } + break a; + } finally { + currentTask = null, currentPriorityLevel = previousPriorityLevel, isPerformingWork = false; + } + hasMoreWork = void 0; + } + } finally { + hasMoreWork ? schedulePerformWorkUntilDeadline() : isMessageLoopRunning = false; + } + } + } + function push(heap, node) { + var index = heap.length; + heap.push(node); + a: for (; 0 < index; ) { + var parentIndex = index - 1 >>> 1, parent = heap[parentIndex]; + if (0 < compare(parent, node)) + heap[parentIndex] = node, heap[index] = parent, index = parentIndex; + else break a; + } + } + function peek(heap) { + return 0 === heap.length ? null : heap[0]; + } + function pop(heap) { + if (0 === heap.length) return null; + var first = heap[0], last = heap.pop(); + if (last !== first) { + heap[0] = last; + a: for (var index = 0, length = heap.length, halfLength = length >>> 1; index < halfLength; ) { + var leftIndex = 2 * (index + 1) - 1, left = heap[leftIndex], rightIndex = leftIndex + 1, right = heap[rightIndex]; + if (0 > compare(left, last)) + rightIndex < length && 0 > compare(right, left) ? (heap[index] = right, heap[rightIndex] = last, index = rightIndex) : (heap[index] = left, heap[leftIndex] = last, index = leftIndex); + else if (rightIndex < length && 0 > compare(right, last)) + heap[index] = right, heap[rightIndex] = last, index = rightIndex; + else break a; + } + } + return first; + } + function compare(a, b) { + var diff = a.sortIndex - b.sortIndex; + return 0 !== diff ? diff : a.id - b.id; + } + function advanceTimers(currentTime) { + for (var timer = peek(timerQueue); null !== timer; ) { + if (null === timer.callback) pop(timerQueue); + else if (timer.startTime <= currentTime) + pop(timerQueue), timer.sortIndex = timer.expirationTime, push(taskQueue, timer); + else break; + timer = peek(timerQueue); + } + } + function handleTimeout(currentTime) { + isHostTimeoutScheduled = false; + advanceTimers(currentTime); + if (!isHostCallbackScheduled) + if (null !== peek(taskQueue)) + isHostCallbackScheduled = true, isMessageLoopRunning || (isMessageLoopRunning = true, schedulePerformWorkUntilDeadline()); + else { + var firstTimer = peek(timerQueue); + null !== firstTimer && requestHostTimeout( + handleTimeout, + firstTimer.startTime - currentTime + ); + } + } + function shouldYieldToHost() { + return needsPaint ? true : exports.unstable_now() - startTime < frameInterval ? false : true; + } + function requestHostTimeout(callback, ms) { + taskTimeoutID = localSetTimeout(function() { + callback(exports.unstable_now()); + }, ms); + } + "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStart(Error()); + exports.unstable_now = void 0; + if ("object" === typeof performance && "function" === typeof performance.now) { + var localPerformance = performance; + exports.unstable_now = function() { + return localPerformance.now(); + }; + } else { + var localDate = Date, initialTime = localDate.now(); + exports.unstable_now = function() { + return localDate.now() - initialTime; + }; + } + var taskQueue = [], timerQueue = [], taskIdCounter = 1, currentTask = null, currentPriorityLevel = 3, isPerformingWork = false, isHostCallbackScheduled = false, isHostTimeoutScheduled = false, needsPaint = false, localSetTimeout = "function" === typeof setTimeout ? setTimeout : null, localClearTimeout = "function" === typeof clearTimeout ? clearTimeout : null, localSetImmediate = "undefined" !== typeof setImmediate ? setImmediate : null, isMessageLoopRunning = false, taskTimeoutID = -1, frameInterval = 5, startTime = -1; + if ("function" === typeof localSetImmediate) + var schedulePerformWorkUntilDeadline = function() { + localSetImmediate(performWorkUntilDeadline); + }; + else if ("undefined" !== typeof MessageChannel) { + var channel = new MessageChannel(), port = channel.port2; + channel.port1.onmessage = performWorkUntilDeadline; + schedulePerformWorkUntilDeadline = function() { + port.postMessage(null); + }; + } else + schedulePerformWorkUntilDeadline = function() { + localSetTimeout(performWorkUntilDeadline, 0); + }; + exports.unstable_IdlePriority = 5; + exports.unstable_ImmediatePriority = 1; + exports.unstable_LowPriority = 4; + exports.unstable_NormalPriority = 3; + exports.unstable_Profiling = null; + exports.unstable_UserBlockingPriority = 2; + exports.unstable_cancelCallback = function(task) { + task.callback = null; + }; + exports.unstable_forceFrameRate = function(fps) { + 0 > fps || 125 < fps ? console.error( + "forceFrameRate takes a positive int between 0 and 125, forcing frame rates higher than 125 fps is not supported" + ) : frameInterval = 0 < fps ? Math.floor(1e3 / fps) : 5; + }; + exports.unstable_getCurrentPriorityLevel = function() { + return currentPriorityLevel; + }; + exports.unstable_next = function(eventHandler) { + switch (currentPriorityLevel) { + case 1: + case 2: + case 3: + var priorityLevel = 3; + break; + default: + priorityLevel = currentPriorityLevel; + } + var previousPriorityLevel = currentPriorityLevel; + currentPriorityLevel = priorityLevel; + try { + return eventHandler(); + } finally { + currentPriorityLevel = previousPriorityLevel; + } + }; + exports.unstable_requestPaint = function() { + needsPaint = true; + }; + exports.unstable_runWithPriority = function(priorityLevel, eventHandler) { + switch (priorityLevel) { + case 1: + case 2: + case 3: + case 4: + case 5: + break; + default: + priorityLevel = 3; + } + var previousPriorityLevel = currentPriorityLevel; + currentPriorityLevel = priorityLevel; + try { + return eventHandler(); + } finally { + currentPriorityLevel = previousPriorityLevel; + } + }; + exports.unstable_scheduleCallback = function(priorityLevel, callback, options) { + var currentTime = exports.unstable_now(); + "object" === typeof options && null !== options ? (options = options.delay, options = "number" === typeof options && 0 < options ? currentTime + options : currentTime) : options = currentTime; + switch (priorityLevel) { + case 1: + var timeout = -1; + break; + case 2: + timeout = 250; + break; + case 5: + timeout = 1073741823; + break; + case 4: + timeout = 1e4; + break; + default: + timeout = 5e3; + } + timeout = options + timeout; + priorityLevel = { + id: taskIdCounter++, + callback, + priorityLevel, + startTime: options, + expirationTime: timeout, + sortIndex: -1 + }; + options > currentTime ? (priorityLevel.sortIndex = options, push(timerQueue, priorityLevel), null === peek(taskQueue) && priorityLevel === peek(timerQueue) && (isHostTimeoutScheduled ? (localClearTimeout(taskTimeoutID), taskTimeoutID = -1) : isHostTimeoutScheduled = true, requestHostTimeout(handleTimeout, options - currentTime))) : (priorityLevel.sortIndex = timeout, push(taskQueue, priorityLevel), isHostCallbackScheduled || isPerformingWork || (isHostCallbackScheduled = true, isMessageLoopRunning || (isMessageLoopRunning = true, schedulePerformWorkUntilDeadline()))); + return priorityLevel; + }; + exports.unstable_shouldYield = shouldYieldToHost; + exports.unstable_wrapCallback = function(callback) { + var parentPriorityLevel = currentPriorityLevel; + return function() { + var previousPriorityLevel = currentPriorityLevel; + currentPriorityLevel = parentPriorityLevel; + try { + return callback.apply(this, arguments); + } finally { + currentPriorityLevel = previousPriorityLevel; + } + }; + }; + "undefined" !== typeof __REACT_DEVTOOLS_GLOBAL_HOOK__ && "function" === typeof __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop && __REACT_DEVTOOLS_GLOBAL_HOOK__.registerInternalModuleStop(Error()); + })(); + } + }); + + // node_modules/scheduler/index.js + var require_scheduler = __commonJS({ + "node_modules/scheduler/index.js"(exports, module) { + "use strict"; + if (false) { + module.exports = null; + } else { + module.exports = require_scheduler_development(); + } + } + }); + // node_modules/react-dom/cjs/react-dom.development.js var require_react_dom_development = __commonJS({ "node_modules/react-dom/cjs/react-dom.development.js"(exports) { @@ -19589,55 +19589,220 @@ // src/current.tsx var require_current = __commonJS({ "src/current.tsx"() { + var import_react = __toESM(require_react()); var import_client = __toESM(require_client()); var import_jsx_runtime = __toESM(require_jsx_runtime()); - var shaders = ` -struct VertexOut { - @builtin(position) position : vec4f, - @location(0) color : vec4f -} - -@vertex -fn vertex_main(@location(0) position: vec4f, - @location(1) color: vec4f) -> VertexOut -{ - var output : VertexOut; - output.position = position; - output.color = color; - return output; -} - -@fragment -fn fragment_main(fragData: VertexOut) -> @location(0) vec4f -{ - return fragData.color; -} -`; - async function init() { - if (!navigator.gpu) { - throw Error("WebGPU not supported."); - } - const adapter = await navigator.gpu.requestAdapter(); - if (!adapter) { - throw Error("Couldn't request WebGPU adapter."); - } - const device = await adapter.requestDevice(); - const shaderModule = device.createShaderModule({ - code: shaders + var MAX_WIDTH = 4; + var gameStyle = { + container: { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + height: "100vh" + }, + board: { + display: "grid", + gridTemplateColumns: "repeat(4, 50px)", + background: "#EEFFEE" + }, + cell: (color) => ({ + display: "flex", + justifyContent: "center", + alignItems: "center", + aspectRatio: "1 / 1 ", + margin: "10px", + background: color + }) + }; + function initializeBoard() { + const board = Array.from( + { length: MAX_WIDTH }, + () => Array.from({ length: MAX_WIDTH }, () => ({ value: 0, color: "orange" })) + ); + let rowIndex; + let colIndex; + rowIndex = Math.floor(Math.random() * 4); + colIndex = Math.floor(Math.random() * 4); + board[rowIndex][colIndex].value = 2; + board[rowIndex - 1][colIndex].value = 2; + return board; + } + function initializeGame() { + return { + board: initializeBoard(), + state: "in_progress", + steps: 0 + }; + } + function handleMove(board, command) { + const copiedBoard = board.map( + (row) => row.map((cell) => ({ ...cell, merged: false })) + ); + let diff; + let startRow, endRow, stepRow; + let startCol, endCol, stepCol; + const size = copiedBoard.length; + switch (command) { + case "u": + diff = { row: -1, col: 0 }; + startRow = 0; + endRow = size; + stepRow = 1; + startCol = 0; + endCol = size; + stepCol = 1; + break; + case "d": + diff = { row: 1, col: 0 }; + startRow = size - 1; + endRow = -1; + stepRow = -1; + startCol = 0; + endCol = size; + stepCol = 1; + break; + case "l": + diff = { row: 0, col: -1 }; + startRow = 0; + endRow = size; + stepRow = 1; + startCol = 0; + endCol = size; + stepCol = 1; + break; + case "r": + diff = { row: 0, col: 1 }; + startRow = 0; + endRow = size; + stepRow = 1; + startCol = size - 1; + endCol = -1; + stepCol = -1; + break; + } + for (let rowIndex = startRow; rowIndex !== endRow; rowIndex += stepRow) { + for (let colIndex = startCol; colIndex !== endCol; colIndex += stepCol) { + const currentCell = copiedBoard[rowIndex][colIndex]; + if (currentCell.value === 0) continue; + let r = rowIndex; + let c = colIndex; + let emptySlot = { r: rowIndex, c: colIndex }; + let finalSlot = { r: rowIndex, c: colIndex }; + while (true) { + r += diff.row; + c += diff.col; + if (r < 0 || r >= size || c < 0 || c >= size) { + finalSlot = emptySlot; + break; + } + const nextCell = copiedBoard[r][c]; + if (nextCell.value === 0) { + emptySlot = { r, c }; + finalSlot = emptySlot; + } else if (nextCell.value === currentCell.value && !nextCell.merged) { + finalSlot = { r, c }; + break; + } else { + finalSlot = emptySlot; + break; + } + } + const targetCell = copiedBoard[finalSlot.r][finalSlot.c]; + if (finalSlot.r === rowIndex && finalSlot.c === colIndex) { + continue; + } + if (targetCell.value === currentCell.value && !targetCell.merged) { + targetCell.value *= 2; + targetCell.merged = true; + copiedBoard[rowIndex][colIndex].value = 0; + } else if (targetCell.value === 0) { + targetCell.value = currentCell.value; + copiedBoard[rowIndex][colIndex].value = 0; + } + } + } + return copiedBoard; + } + function addNewItemsToTheBoard(board) { + let randomRowIndex; + let randomColIndex; + let zeroPos = 0; + board.forEach((row) => { + row.forEach((cell) => { + if (cell.value === 0) { + zeroPos += 1; + } + }); }); - const canvas = document.querySelector("#gpuCanvas"); - const context = canvas.getContext("webgpu"); - context.configure({ - device, - format: navigator.gpu.getPreferredCanvasFormat(), - alphaMode: "premultiplied" - }); - console.log(device); + if (zeroPos === 0) { + return; + } + let curr = 0; + const maxAddedValues = zeroPos < 2 ? 1 : zeroPos / 2 | 0; + while (curr < maxAddedValues) { + randomRowIndex = Math.floor(Math.random() * board.length); + randomColIndex = Math.floor(Math.random() * board.length); + if (board[randomRowIndex][randomColIndex].value === 0) { + board[randomRowIndex][randomColIndex].value = 2; + curr++; + } + } + } + function gameDispatch(game, gameAction) { + switch (gameAction.type) { + case "move": { + const newBoard = handleMove(game.board, gameAction.command); + addNewItemsToTheBoard(newBoard); + return { + ...game, + board: newBoard + }; + } + case "calculate": { + return { + ...game + }; + } + } } - void init(); - var Current = () => { - return /* @__PURE__ */ (0, import_jsx_runtime.jsx)(import_jsx_runtime.Fragment, { children: "hello " }); - }; + function Current() { + const [game, dispatch] = (0, import_react.useReducer)(gameDispatch, null, initializeGame); + (0, import_react.useEffect)(() => { + window.addEventListener("keyup", (e) => { + switch (e.key) { + case "ArrowDown": { + dispatch({ type: "move", command: "d" }); + return; + } + case "ArrowUp": { + dispatch({ type: "move", command: "u" }); + return; + } + case "ArrowRight": { + dispatch({ type: "move", command: "r" }); + return; + } + case "ArrowLeft": { + dispatch({ type: "move", command: "l" }); + return; + } + default: + return; + } + }); + }, []); + return /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: gameStyle.container, children: [ + /* @__PURE__ */ (0, import_jsx_runtime.jsx)("h1", { children: " 2048 " }), + /* @__PURE__ */ (0, import_jsx_runtime.jsx)("div", { style: gameStyle.board, children: game.board.map((row) => { + return row.map((cell) => /* @__PURE__ */ (0, import_jsx_runtime.jsxs)("div", { style: gameStyle.cell(cell.color), children: [ + " ", + cell.value, + " " + ] })); + }) }) + ] }); + } import_client.default.createRoot(document.getElementById("root")).render(/* @__PURE__ */ (0, import_jsx_runtime.jsx)(Current, {})); } }); @@ -19645,10 +19810,10 @@ })(); /*! Bundled license information: -scheduler/cjs/scheduler.development.js: +react/cjs/react.development.js: (** * @license React - * scheduler.development.js + * react.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. * @@ -19656,10 +19821,10 @@ * LICENSE file in the root directory of this source tree. *) -react/cjs/react.development.js: +scheduler/cjs/scheduler.development.js: (** * @license React - * react.development.js + * scheduler.development.js * * Copyright (c) Meta Platforms, Inc. and affiliates. *
--- a/react_games/src/current.tsx Mon Dec 01 22:43:40 2025 -0800 +++ b/react_games/src/current.tsx Wed Dec 03 18:34:22 2025 -0800 @@ -1,60 +1,265 @@ +import { CSSProperties, useEffect, useReducer, useState } from "react"; import ReactDOM from "react-dom/client"; -const shaders = ` -struct VertexOut { - @builtin(position) position : vec4f, - @location(0) color : vec4f +/** + * 2048 + * + * 4 X 4 + */ + +const MAX_WIDTH = 4; + +type Color = 'white' | 'orange' | 'yellow' | 'red'; + +type Cell = { + value: number; + color: Color; +} + +type Board = Cell[][]; + +type GameState = "in_progress" | "lost" | "won"; + +type Game = { + board: Board; + state: GameState; + steps: number; +} + +type Command = "u" | "d" | "l" | "r"; + +type GameAction = + { type: "move", command: Command } | { type: "calculate" }; + + +interface GameStyle { + container: CSSProperties; + board: CSSProperties; + cell: (color: Color) => CSSProperties; } -@vertex -fn vertex_main(@location(0) position: vec4f, - @location(1) color: vec4f) -> VertexOut -{ - var output : VertexOut; - output.position = position; - output.color = color; - return output; +const gameStyle: GameStyle = { + container: { + display: "flex", + flexDirection: "column", + justifyContent: "center", + alignItems: "center", + height: "100vh" + }, + board: { + display: "grid", + gridTemplateColumns: "repeat(4, 50px)", + background: "#EEFFEE", + }, + cell: (color: Color) => ({ + display: "flex", + justifyContent: "center", + alignItems: "center", + aspectRatio: "1 / 1 ", + margin: "10px", + background: color, + }) +} + +function initializeBoard(): Board { + const board = Array.from({ length: MAX_WIDTH }, () => + Array.from({ length: MAX_WIDTH }, (): Cell => ({ value: 0, color: 'orange' })) + ); + let rowIndex: number; + let colIndex: number; + rowIndex = Math.floor(Math.random() * 4); + colIndex = Math.floor(Math.random() * 4); + board[rowIndex][colIndex].value = 2; + board[rowIndex-1][colIndex].value = 2; + return board; } -@fragment -fn fragment_main(fragData: VertexOut) -> @location(0) vec4f -{ - return fragData.color; +function initializeGame(): Game { + return { + board: initializeBoard(), + state: "in_progress", + steps: 0, + } } -`; + + +function handleMove(board: Board, command: Command): Board { + // Deep copy the board and initialize the merged status for the new board + const copiedBoard = board.map(row => + row.map(cell => ({ ...cell, merged: false })) + ); + + let diff: { row: number, col: number }; + let startRow: number, endRow: number, stepRow: number; + let startCol: number, endCol: number, stepCol: number; + + const size = copiedBoard.length; -async function init() { - if (!navigator.gpu) { - throw Error("WebGPU not supported."); + switch (command) { + case "u": + diff = { row: -1, col: 0 }; + startRow = 0; endRow = size; stepRow = 1; + startCol = 0; endCol = size; stepCol = 1; + break; + case "d": + diff = { row: 1, col: 0 }; + startRow = size - 1; endRow = -1; stepRow = -1; + startCol = 0; endCol = size; stepCol = 1; + break; + case "l": + diff = { row: 0, col: -1 }; + startRow = 0; endRow = size; stepRow = 1; + startCol = 0; endCol = size; stepCol = 1; + break; + case "r": + diff = { row: 0, col: 1 }; + startRow = 0; endRow = size; stepRow = 1; + startCol = size - 1; endCol = -1; stepCol = -1; + break; } - const adapter = await navigator.gpu.requestAdapter(); - if (!adapter) { - throw Error("Couldn't request WebGPU adapter."); + for (let rowIndex = startRow; rowIndex !== endRow; rowIndex += stepRow) { + for (let colIndex = startCol; colIndex !== endCol; colIndex += stepCol) { + const currentCell = copiedBoard[rowIndex][colIndex]; + + if (currentCell.value === 0) continue; + + let r = rowIndex; + let c = colIndex; + let emptySlot: { r: number, c: number } = { r: rowIndex, c: colIndex }; + let finalSlot: { r: number, c: number } = { r: rowIndex, c: colIndex }; + + while (true) { + r += diff.row; + c += diff.col; + + if (r < 0 || r >= size || c < 0 || c >= size) { + finalSlot = emptySlot; + break; + } + + const nextCell = copiedBoard[r][c]; + + if (nextCell.value === 0) { + emptySlot = { r, c }; + finalSlot = emptySlot; + } else if (nextCell.value === currentCell.value && !nextCell.merged) { + finalSlot = { r, c }; + break; + } else { + finalSlot = emptySlot; + break; + } + } + + const targetCell = copiedBoard[finalSlot.r][finalSlot.c]; + + if (finalSlot.r === rowIndex && finalSlot.c === colIndex) { + continue; + } + + if (targetCell.value === currentCell.value && !targetCell.merged) { + targetCell.value *= 2; + targetCell.merged = true; + + copiedBoard[rowIndex][colIndex].value = 0; + + } else if (targetCell.value === 0) { + targetCell.value = currentCell.value; + copiedBoard[rowIndex][colIndex].value = 0; + } + } + } + + return copiedBoard; +} + +function addNewItemsToTheBoard(board: Board) { + let randomRowIndex: number; + let randomColIndex: number; + + + let zeroPos = 0; + board.forEach((row) => { + row.forEach((cell) => { + if (cell.value === 0) { + zeroPos += 1; + } + }) + }) + if (zeroPos === 0) { + return; } - const device = await adapter.requestDevice(); - - const shaderModule = device.createShaderModule({ - code: shaders, - }); + let curr = 0; + const maxAddedValues = zeroPos < 2 ? 1 : (zeroPos / 2) | 0; + while (curr < maxAddedValues) { + randomRowIndex = Math.floor(Math.random() * board.length) + randomColIndex = Math.floor(Math.random() * board.length) + if (board[randomRowIndex][randomColIndex].value === 0) + { + board[randomRowIndex][randomColIndex].value = 2; + curr++; + } + } +} - const canvas = document.querySelector("#gpuCanvas"); - const context = canvas.getContext("webgpu"); - - context.configure({ - device, - format: navigator.gpu.getPreferredCanvasFormat(), - alphaMode: "premultiplied", - }); - - console.log(device) +function gameDispatch(game: Game, gameAction: GameAction): Game { + switch(gameAction.type) { + case "move": { + const newBoard = handleMove(game.board, gameAction.command); + addNewItemsToTheBoard(newBoard); + return { + ...game, + board: newBoard, + } + } + case "calculate": { + return { + ...game, + } + } + } } -void init(); +function Current() { + const [game, dispatch] = useReducer(gameDispatch, null, initializeGame); -const Current = () => { - return (<>hello </>); -}; + useEffect(() => { + window.addEventListener("keyup", (e) => { + switch(e.key) { + case "ArrowDown": { + dispatch({ type: "move", command: "d" }); + return; + } + case "ArrowUp": { + dispatch({ type: "move", command: "u" }); + return; + } + case "ArrowRight": { + dispatch({ type: "move", command: "r" }); + return; + } + case "ArrowLeft": { + dispatch({ type: "move", command: "l" }); + return; + } + default: + return; + } + }) + + }, []) + return ( + <div style={gameStyle.container}> + <h1> 2048 </h1> + <div style={gameStyle.board}> + {game.board.map((row: Cell[]) => { + return row.map((cell: Cell) => (<div style={gameStyle.cell(cell.color)}> {cell.value} </div>)) + })} + </div> + </div> + ); +} ReactDOM.createRoot(document.getElementById("root")!).render(<Current />);