User prompt
Arregla el bug que el tiempo empieza a subir cuando se tiran los dados y no como un proceso secundario
User prompt
Haz que el tiempo suba desde que se ejecuta el juego y no desde que se toca la pantalla ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Agrega un texto arriba del todo mostrando el tiempo jugado, que se actualice cada segundo(guarda el valor) ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Agrega un texto arriba del todo como de cronómetro: 000:00:00. Que se actualice cada segundo y guarda el valor ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Utiliza la fórmula: "P(\text{exactamente } k) = \frac{1}{6^8} \cdot \sum_{\substack{n_1 + \cdots + n_6 = 8 \\ \max(n_i) = k}} \binom{8}{n_1, ..., n_6}" para la posibilidad de coincidir los dados
User prompt
Agrega más partículas ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Agrega partículas, cuando finaliza el tiro, al grupo más grande ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Agrega partículas, cuando finaliza el tiro, al grupo más grande ↪💡 Consider importing and using the following plugins: @upit/tween.v1
User prompt
Cambia los textos a inglés
User prompt
Please fix the bug: 'TypeError: Cannot set properties of undefined (setting 'fill')' in or related to this line: 'probabilityNumberText.style.fill = redColor;' Line Number: 256
User prompt
Arregla el error que hace que todo el texto tenga el mismo color
User prompt
Cambia los colores de la posibilidad así: posibilidad(negro): 1 (amarillo) en (negro) N (rojo pastel, mientras más difícil más rojo será)
User prompt
Agrega una fuente más Soft y dale colores a los textos
User prompt
Agranda el texto y replaza la manera de mostrar como posibilidad:
User prompt
Please fix the bug: 'Uncaught RangeError: Maximum call stack size exceeded' in or related to this line: 'var matchingCount = countMatchingDice();' Line Number: 214
User prompt
Agrega un texto abajo de la pantalla que diga la posibilidad de que haya tocado dicho cantidad de dados iguales en los 8 dados
User prompt
Agrega un texto abajo que pone la posibilidad que de que haya tocado dicho grupo de dados (en: 1(color amarillo) en xxxx (color rojo)
User prompt
Haz que los valores mejor, anterior y actual se guarden y carguen ↪💡 Consider importing and using the following plugins: @upit/storage.v1
User prompt
Haz que anterior copie el valor de actual cuando se toca para cambiar los dados, y haz que actual vuelva a 0/8 hasta que finalice el cambio de dados y tome el nuevo valor
User prompt
Haz que siempre que cambie actual, ese valor pase a ser valor del anterior
User prompt
Modifica el texto de 0/8 de la siguiente forma: Best: 0/8
User prompt
Agrega al texto de 0/8 el mejor y el actual, los dos en la misma fila tipo actual: 0/8 - mejor: 0/8
Code edit (1 edits merged)
Please save this source code
/**** * Plugins ****/ var tween = LK.import("@upit/tween.v1"); var storage = LK.import("@upit/storage.v1"); /**** * Classes ****/ var Dice = Container.expand(function () { var self = Container.call(this); // Add numeric variable valor self.valor = 1; // Add rolling animation variables self.isRolling = false; self.rollCount = 0; self.rollTarget = 0; self.rollTimer = 0; var diceGraphics = self.attachAsset('Dice' + self.valor, { anchorX: 0.5, anchorY: 0.5 }); // Method to update dice visual based on valor self.updateVisual = function () { // Create new graphics based on valor first var newGraphics = self.attachAsset('Dice' + self.valor, { anchorX: 0.5, anchorY: 0.5 }); // Remove old graphics after new one is created self.removeChild(diceGraphics); // Update reference to new graphics diceGraphics = newGraphics; // Add bounce effect when value changes during rolling if (self.isRolling) { self.playDiceSound(); diceGraphics.scaleX = 1; diceGraphics.scaleY = 1; tween(diceGraphics, { scaleX: 1.2, scaleY: 1.2 }, { duration: 100, easing: tween.bounceOut, onFinish: function onFinish() { tween(diceGraphics, { scaleX: 1, scaleY: 1 }, { duration: 100, easing: tween.bounceOut }); } }); } }; // Method to play dice sound self.playDiceSound = function () { LK.getSound('Roll').play(); }; // Method to start rolling animation self.startRoll = function () { self.isRolling = true; self.rollCount = 0; self.rollTarget = Math.floor(Math.random() * 7) + 6; // 6 to 12 rolls self.rollTimer = 0; }; // Update method for rolling animation self.update = function () { if (self.isRolling) { var rollSpeed = Math.floor(self.rollCount * 1.5) + 3; // Start fast, get slower if (self.rollTimer >= rollSpeed) { self.valor = Math.floor(Math.random() * 6) + 1; self.updateVisual(); self.rollCount++; self.rollTimer = 0; if (self.rollCount >= self.rollTarget) { self.isRolling = false; } } else { self.rollTimer++; } } }; return self; }); var Particle = Container.expand(function () { var self = Container.call(this); var particleGraphics = self.attachAsset('Particula', { anchorX: 0.5, anchorY: 0.5 }); // Initialize particle properties self.velocityX = (Math.random() - 0.5) * 10; self.velocityY = Math.random() * -8 - 2; self.gravity = 0.3; self.life = 1.0; self.fadeSpeed = Math.random() * 0.02 + 0.01; // Randomize initial scale and color with more variety var initialScale = Math.random() * 0.6 + 0.2; particleGraphics.scaleX = initialScale; particleGraphics.scaleY = initialScale; var colors = [0xFFD700, 0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE00, 0xF38BA8, 0xFF9500, 0x8E44AD, 0xE74C3C]; particleGraphics.tint = colors[Math.floor(Math.random() * colors.length)]; // Add rotation and pulsing effect self.rotationSpeed = (Math.random() - 0.5) * 0.2; self.pulseSpeed = Math.random() * 0.1 + 0.05; self.pulseOffset = Math.random() * Math.PI * 2; self.update = function () { // Update position self.x += self.velocityX; self.y += self.velocityY; self.velocityY += self.gravity; // Add rotation particleGraphics.rotation += self.rotationSpeed; // Add pulsing effect var pulseScale = 1 + Math.sin(LK.ticks * self.pulseSpeed + self.pulseOffset) * 0.2; // Update life and fade self.life -= self.fadeSpeed; particleGraphics.alpha = Math.max(0, self.life); // Scale down over time with pulse effect var scale = initialScale * self.life * pulseScale; particleGraphics.scaleX = scale; particleGraphics.scaleY = scale; // Remove when life is over if (self.life <= 0) { self.destroy(); } }; return self; }); /**** * Initialize Game ****/ // Create array to hold all dice var game = new LK.Game({ backgroundColor: 0xFFFFFF }); /**** * Game Code ****/ // Create array to hold all dice var diceArray = []; // Create array to hold particles var particles = []; // Add lanzamiento boolean variable var lanzamiento = false; // Add timer to enforce minimum 1 second wait between rolls var lastRollFinishTime = 0; var minimumWaitTime = 1000; // 1 second in milliseconds // Add best score tracking - load from storage with defaults var bestScore = storage.bestScore || 0; var previousScore = storage.previousScore || 0; var actualScore = storage.actualScore || 0; // Calculate center positions for two columns var centerX = 2048 / 2; var centerY = 2732 / 2; var columnSpacing = 330; // Space between columns var rowSpacing = 300; // Space between rows // Create matching dice counter text var counterText = new Text2('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: ' + actualScore + '/8', { size: 80, fill: 0x2E7D32, align: 'center', font: "'Helvetica Neue', 'Arial', sans-serif" }); counterText.anchor.set(0.5, 0); counterText.y = 100; // Move down to make space for status text LK.gui.top.addChild(counterText); // Create status text above dice var statusText = new Text2('Tap to roll', { size: 60, fill: 0x1976D2, font: "'Helvetica Neue', 'Arial', sans-serif" }); statusText.anchor.set(0.5, 0.5); statusText.x = centerX; statusText.y = centerY - 700; // Position above dice grid game.addChild(statusText); // Create countdown text var countdownText = new Text2('', { size: 50, fill: 0xF57C00, font: "'Helvetica Neue', 'Arial', sans-serif" }); countdownText.anchor.set(0.5, 0.5); countdownText.x = centerX; countdownText.y = centerY - 640; // Position below status text game.addChild(countdownText); // Create probability text at bottom of screen var probabilityText = new Text2('', { size: 80, fill: 0x7B1FA2, align: 'center', font: "'Helvetica Neue', 'Arial', sans-serif" }); probabilityText.anchor.set(0.5, 1); probabilityText.x = centerX; probabilityText.y = 2732 - 50; // Position at bottom with margin game.addChild(probabilityText); // Function to count matching dice function countMatchingDice() { var counts = {}; // Count occurrences of each dice value for (var i = 0; i < diceArray.length; i++) { var value = diceArray[i].valor; counts[value] = (counts[value] || 0) + 1; } // Find the highest count var maxCount = 0; for (var value in counts) { if (counts[value] > maxCount) { maxCount = counts[value]; } } return maxCount; } // Function to calculate factorial function factorial(n) { if (n <= 1) return 1; var result = 1; for (var i = 2; i <= n; i++) { result *= i; } return result; } // Function to calculate multinomial coefficient function multinomial(n, counts) { var result = factorial(n); for (var i = 0; i < counts.length; i++) { result /= factorial(counts[i]); } return result; } // Function to generate all partitions of 8 with maximum value k function generatePartitions(sum, maxValue, numSlots) { var partitions = []; function backtrack(remaining, currentPartition, maxSoFar, slot) { if (slot === numSlots) { if (remaining === 0 && maxSoFar === maxValue) { partitions.push(currentPartition.slice()); } return; } for (var i = 0; i <= remaining; i++) { currentPartition[slot] = i; var newMaxSoFar = Math.max(maxSoFar, i); if (newMaxSoFar <= maxValue) { backtrack(remaining - i, currentPartition, newMaxSoFar, slot + 1); } } } var partition = new Array(numSlots); backtrack(sum, partition, 0, 0); return partitions; } // Function to calculate probability of getting exactly N matching dice in 8 rolls function calculateProbability(n) { if (n < 1 || n > 8) return 0; // Using the formula: P(exactly k) = (1/6^8) * sum of multinomial coefficients // where the sum is over all partitions with maximum value k var partitions = generatePartitions(8, n, 6); var sum = 0; for (var i = 0; i < partitions.length; i++) { sum += multinomial(8, partitions[i]); } var probability = sum / Math.pow(6, 8); return probability; } // Function to update probability display function updateProbabilityDisplay() { var matchingCount = countMatchingDice(); var probability = calculateProbability(matchingCount); var oneInX = Math.round(1 / probability); probabilityText.setText('Probability:\n1 in ' + oneInX); } // Function to create particles for largest matching group function createParticlesForLargestGroup() { var counts = {}; // Count occurrences of each dice value for (var i = 0; i < diceArray.length; i++) { var value = diceArray[i].valor; counts[value] = (counts[value] || 0) + 1; } // Find the highest count and value var maxCount = 0; var maxValue = 0; for (var value in counts) { if (counts[value] > maxCount) { maxCount = counts[value]; maxValue = parseInt(value); } } // Create particles for each die in the largest group for (var i = 0; i < diceArray.length; i++) { var dice = diceArray[i]; if (dice.valor == maxValue && counts[maxValue] == maxCount && maxCount > 1) { // Create 8-12 particles per die in largest group var particleCount = Math.floor(Math.random() * 5) + 8; for (var p = 0; p < particleCount; p++) { var particle = new Particle(); particle.x = dice.x + (Math.random() - 0.5) * 80; particle.y = dice.y + (Math.random() - 0.5) * 80; // Add tween animation to particles for extra visual effect tween(particle, { scaleX: Math.random() * 0.5 + 0.8, scaleY: Math.random() * 0.5 + 0.8, rotation: Math.random() * Math.PI * 2 }, { duration: 1000 + Math.random() * 500, easing: tween.easeOut }); game.addChild(particle); particles.push(particle); } } } } // Function to apply tint colors to dice based on matching groups function applyDiceTints() { var counts = {}; // Count occurrences of each dice value for (var i = 0; i < diceArray.length; i++) { var value = diceArray[i].valor; counts[value] = (counts[value] || 0) + 1; } // Find the highest count and value var maxCount = 0; var maxValue = 0; for (var value in counts) { if (counts[value] > maxCount) { maxCount = counts[value]; maxValue = parseInt(value); } } // Generate random colors for smaller groups var randomColors = [0xFF6B6B, 0x4ECDC4, 0x45B7D1, 0x96CEB4, 0xFECE00, 0xF38BA8]; var colorIndex = 0; var usedColors = {}; // Apply tints to all dice for (var i = 0; i < diceArray.length; i++) { var dice = diceArray[i]; var value = dice.valor; if (value == maxValue && counts[value] == maxCount) { // Largest group gets soft yellow tint dice.children[0].tint = 0xFFFF99; // Soft yellow } else if (counts[value] > 1) { // Smaller matching groups get random colors if (!usedColors[value]) { usedColors[value] = randomColors[colorIndex % randomColors.length]; colorIndex++; } dice.children[0].tint = usedColors[value]; } else { // Single dice get no tint (white) dice.children[0].tint = 0xFFFFFF; } } } // Create 8 dice in two columns (4 rows each) for (var col = 0; col < 2; col++) { for (var row = 0; row < 4; row++) { var dice = new Dice(); // Assign random valor from 1 to 6 dice.valor = Math.floor(Math.random() * 6) + 1; // Update visual based on valor dice.updateVisual(); // Position dice in grid dice.x = centerX + (col - 0.5) * columnSpacing; dice.y = centerY + (row - 1.5) * rowSpacing; // Add to game and array game.addChild(dice); diceArray.push(dice); } // Game update method to handle dice rolling game.update = function () { // Update status and countdown text based on current state var currentTime = Date.now(); var timeSinceLastRoll = currentTime - lastRollFinishTime; var timeRemaining = minimumWaitTime - timeSinceLastRoll; if (lanzamiento) { // Currently rolling statusText.setText('Rolling dice...'); countdownText.setText(''); } else if (timeRemaining > 0) { // Waiting period - show countdown statusText.setText('Wait to roll'); var secondsRemaining = timeRemaining / 1000; countdownText.setText(secondsRemaining.toFixed(2) + 's'); } else { // Ready to roll statusText.setText('Tap to roll'); countdownText.setText(''); } // Check if all dice have finished rolling if (lanzamiento) { var allFinished = true; for (var i = 0; i < diceArray.length; i++) { if (diceArray[i].isRolling) { allFinished = false; break; } } // Reset lanzamiento when all dice are done if (allFinished) { lanzamiento = false; // Record the time when rolling finished lastRollFinishTime = Date.now(); // Update counter text with matching dice count var matchingCount = countMatchingDice(); actualScore = matchingCount; // Update best score if current is better if (matchingCount > bestScore) { bestScore = matchingCount; } // Save scores to storage storage.bestScore = bestScore; storage.previousScore = previousScore; storage.actualScore = actualScore; counterText.setText('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: ' + matchingCount + '/8'); // Apply tint colors to dice based on matching groups applyDiceTints(); // Create particles for largest matching group createParticlesForLargestGroup(); // Create extra celebration particles for high scores if (matchingCount >= 4) { var burstCount = matchingCount * 3; // More particles for higher scores for (var b = 0; b < burstCount; b++) { var burstParticle = new Particle(); burstParticle.x = centerX + (Math.random() - 0.5) * 300; burstParticle.y = centerY + (Math.random() - 0.5) * 200; burstParticle.velocityX = (Math.random() - 0.5) * 15; burstParticle.velocityY = Math.random() * -12 - 3; // Add sparkle effect with tweening tween(burstParticle, { rotation: Math.PI * 4, scaleX: 0.1, scaleY: 0.1 }, { duration: 2000, easing: tween.easeOut }); game.addChild(burstParticle); particles.push(burstParticle); } } // Update probability display updateProbabilityDisplay(); } } // Clean up destroyed particles for (var i = particles.length - 1; i >= 0; i--) { if (particles[i].destroyed) { particles.splice(i, 1); } } }; // Add screen tap handler for lanzamiento event game.down = function (x, y, obj) { // Check if enough time has passed since last roll finished var currentTime = Date.now(); var timeSinceLastRoll = currentTime - lastRollFinishTime; // Only allow new roll if not currently rolling AND minimum wait time has passed if (!lanzamiento && timeSinceLastRoll >= minimumWaitTime) { // Copy current score to previous score when starting new roll var currentMatchingCount = countMatchingDice(); previousScore = currentMatchingCount; // Save previous score to storage storage.previousScore = previousScore; // Update counter text to show actual as 0/8 during rolling counterText.setText('Best: ' + bestScore + '/8\nPrevious: ' + previousScore + '/8 - Current: 0/8'); lanzamiento = true; // Start rolling animation for all dice for (var i = 0; i < diceArray.length; i++) { diceArray[i].startRoll(); } } }; }
===================================================================
--- original.js
+++ change.js
@@ -216,35 +216,59 @@
}
}
return maxCount;
}
+// Function to calculate factorial
+function factorial(n) {
+ if (n <= 1) return 1;
+ var result = 1;
+ for (var i = 2; i <= n; i++) {
+ result *= i;
+ }
+ return result;
+}
+// Function to calculate multinomial coefficient
+function multinomial(n, counts) {
+ var result = factorial(n);
+ for (var i = 0; i < counts.length; i++) {
+ result /= factorial(counts[i]);
+ }
+ return result;
+}
+// Function to generate all partitions of 8 with maximum value k
+function generatePartitions(sum, maxValue, numSlots) {
+ var partitions = [];
+ function backtrack(remaining, currentPartition, maxSoFar, slot) {
+ if (slot === numSlots) {
+ if (remaining === 0 && maxSoFar === maxValue) {
+ partitions.push(currentPartition.slice());
+ }
+ return;
+ }
+ for (var i = 0; i <= remaining; i++) {
+ currentPartition[slot] = i;
+ var newMaxSoFar = Math.max(maxSoFar, i);
+ if (newMaxSoFar <= maxValue) {
+ backtrack(remaining - i, currentPartition, newMaxSoFar, slot + 1);
+ }
+ }
+ }
+ var partition = new Array(numSlots);
+ backtrack(sum, partition, 0, 0);
+ return partitions;
+}
// Function to calculate probability of getting exactly N matching dice in 8 rolls
function calculateProbability(n) {
if (n < 1 || n > 8) return 0;
- if (n === 1) {
- // Probability of getting exactly 1 of each value (all different) is very low for 8 dice
- // This is a complex calculation, we'll use approximation
- return 0.015; // ~1.5%
+ // Using the formula: P(exactly k) = (1/6^8) * sum of multinomial coefficients
+ // where the sum is over all partitions with maximum value k
+ var partitions = generatePartitions(8, n, 6);
+ var sum = 0;
+ for (var i = 0; i < partitions.length; i++) {
+ sum += multinomial(8, partitions[i]);
}
- // For n matching dice, we use binomial probability
- // P(X = n) = C(8,n) * (1/6)^n * (5/6)^(8-n) * 6 (for any of the 6 faces)
- // Simplified approximation for display purposes
- var probabilities = {
- 2: 0.372,
- // ~37.2%
- 3: 0.139,
- // ~13.9%
- 4: 0.0347,
- // ~3.47%
- 5: 0.00695,
- // ~0.695%
- 6: 0.00116,
- // ~0.116%
- 7: 0.000139,
- // ~0.0139%
- 8: 0.0000214 // ~0.00214%
- };
- return probabilities[n] || 0;
+ var probability = sum / Math.pow(6, 8);
+ return probability;
}
// Function to update probability display
function updateProbabilityDisplay() {
var matchingCount = countMatchingDice();