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();