// Burton Method LSAT Learning Games // Built with Phaser 3 let currentGame = null; // ============================================ // GAME DATA - LSAT Content // ============================================ const flawTypes = [ { name: "Causation ≠ Correlation", short: "CAUSE", color: 0xff6b6b }, { name: "Overgeneralization", short: "GENERAL", color: 0x4ecdc4 }, { name: "Ad Hominem", short: "AD HOM", color: 0xf9d423 }, { name: "Circular Reasoning", short: "CIRCULAR", color: 0x667eea }, { name: "Sampling Error", short: "SAMPLE", color: 0x44a08d }, ]; const flawExamples = [ { text: "Coffee sales increased when crime dropped. Coffee prevents crime!", flaw: "CAUSE" }, { text: "My friend tried it and failed, so it never works.", flaw: "GENERAL" }, { text: "You can't trust his argument - he's biased.", flaw: "AD HOM" }, { text: "This policy is good because it's beneficial.", flaw: "CIRCULAR" }, { text: "3 people I know love it, so everyone must.", flaw: "SAMPLE" }, { text: "The rooster crows before sunrise, so roosters cause the sun to rise.", flaw: "CAUSE" }, { text: "One study showed X, therefore X is always true.", flaw: "GENERAL" }, { text: "She's wrong because she profits from being right.", flaw: "AD HOM" }, { text: "We should do this because it's the right thing to do.", flaw: "CIRCULAR" }, { text: "All my Twitter followers agree, so the public agrees.", flaw: "SAMPLE" }, ]; const premiseConclusion = [ { sentence: "Therefore, we should invest more in education.", type: "conclusion" }, { sentence: "Studies show reading improves cognitive function.", type: "premise" }, { sentence: "Thus, the policy will fail.", type: "conclusion" }, { sentence: "Crime rates dropped 15% last year.", type: "premise" }, { sentence: "Hence, immediate action is required.", type: "conclusion" }, { sentence: "The company's revenue increased by 20%.", type: "premise" }, { sentence: "So it follows that exercise benefits everyone.", type: "conclusion" }, { sentence: "Research indicates a strong correlation.", type: "premise" }, { sentence: "Consequently, the law should be changed.", type: "conclusion" }, { sentence: "Historical data supports this trend.", type: "premise" }, ]; const assumptionQuestions = [ { premise: "All successful lawyers read extensively.", conclusion: "Maria will be a successful lawyer.", assumption: "Maria reads extensively.", wrong: ["Maria is smart.", "Lawyers work hard.", "Reading is easy."] }, { premise: "This diet helped celebrities lose weight.", conclusion: "This diet will help you lose weight.", assumption: "What works for celebrities will work for regular people.", wrong: ["Celebrities are healthy.", "Diets always work.", "You want to lose weight."] }, { premise: "Sales increased after the ad campaign launched.", conclusion: "The ad campaign caused sales to increase.", assumption: "Nothing else caused the sales increase.", wrong: ["Ads are expensive.", "Sales always increase.", "The campaign was creative."] }, ]; const speedQuestions = [ { stimulus: "Anyone who exercises regularly has better health. John exercises regularly.", question: "What must be true?", correct: "John has better health.", wrong: ["John is an athlete.", "Exercise is difficult.", "Health requires diet too."] }, { stimulus: "The cafe's profits rose after extending hours. The manager claims the extended hours caused the profit increase.", question: "What would WEAKEN this argument?", correct: "A new office building opened nearby during the same period.", wrong: ["The cafe serves good coffee.", "Profits are important.", "Hours were extended by 2."] }, { stimulus: "All birds can fly. Penguins are birds.", question: "What is the FLAW in concluding penguins can fly?", correct: "The premise 'all birds can fly' is false.", wrong: ["Penguins are cute.", "Flying is hard.", "Birds have feathers."] }, ]; // ============================================ // FLAW FIGHTER GAME // ============================================ class FlawFighterScene extends Phaser.Scene { constructor() { super({ key: 'FlawFighter' }); } create() { this.score = 0; this.lives = 3; this.currentQuestion = 0; // Background this.cameras.main.setBackgroundColor('#1a1a2e'); // Title this.add.text(400, 30, '🎯 FLAW FIGHTER', { fontSize: '28px', fontFamily: 'Arial', color: '#ffffff', fontStyle: 'bold' }).setOrigin(0.5); // Score and Lives this.scoreText = this.add.text(20, 20, 'Score: 0', { fontSize: '20px', color: '#4ecdc4' }); this.livesText = this.add.text(680, 20, '❤️❤️❤️', { fontSize: '20px' }); // Question area this.questionBg = this.add.rectangle(400, 150, 700, 100, 0x16213e, 0.9); this.questionText = this.add.text(400, 150, '', { fontSize: '16px', color: '#ffffff', wordWrap: { width: 650 }, align: 'center' }).setOrigin(0.5); // Instruction this.add.text(400, 220, 'Click the correct flaw type!', { fontSize: '14px', color: '#888888' }).setOrigin(0.5); // Flaw buttons this.buttons = []; flawTypes.forEach((flaw, i) => { const x = 90 + (i * 160); const btn = this.add.rectangle(x, 320, 140, 60, flaw.color) .setInteractive({ useHandCursor: true }) .on('pointerdown', () => this.selectFlaw(flaw.short)) .on('pointerover', () => btn.setScale(1.1)) .on('pointerout', () => btn.setScale(1)); this.add.text(x, 320, flaw.short, { fontSize: '14px', color: '#ffffff', fontStyle: 'bold' }).setOrigin(0.5); this.buttons.push(btn); }); // Feedback text this.feedbackText = this.add.text(400, 400, '', { fontSize: '24px', color: '#4ecdc4', fontStyle: 'bold' }).setOrigin(0.5); // Start first question this.nextQuestion(); } nextQuestion() { if (this.currentQuestion >= flawExamples.length) { this.endGame(); return; } const q = flawExamples[this.currentQuestion]; this.questionText.setText(`"${q.text}"`); this.currentFlaw = q.flaw; this.feedbackText.setText(''); } selectFlaw(selected) { if (selected === this.currentFlaw) { this.score += 100; this.scoreText.setText(`Score: ${this.score}`); this.feedbackText.setText('✅ CORRECT!').setColor('#4ecdc4'); // Flash effect this.cameras.main.flash(200, 0, 255, 0, true); } else { this.lives--; this.livesText.setText('❤️'.repeat(this.lives)); this.feedbackText.setText(`❌ Wrong! It was ${this.currentFlaw}`).setColor('#ff6b6b'); this.cameras.main.shake(200, 0.01); if (this.lives <= 0) { this.endGame(); return; } } this.currentQuestion++; this.time.delayedCall(1500, () => this.nextQuestion()); } endGame() { this.questionText.setText(''); this.feedbackText.setText(`GAME OVER!\n\nFinal Score: ${this.score}\n\nClick to play again`) .setColor('#ffffff') .setFontSize('28px'); this.input.once('pointerdown', () => { this.scene.restart(); }); } } // ============================================ // PREMISE SORTER GAME // ============================================ class PremiseSorterScene extends Phaser.Scene { constructor() { super({ key: 'PremiseSorter' }); } create() { this.score = 0; this.currentIndex = 0; this.shuffledItems = Phaser.Utils.Array.Shuffle([...premiseConclusion]); this.cameras.main.setBackgroundColor('#0d1b2a'); // Title this.add.text(400, 30, '📦 PREMISE SORTER', { fontSize: '28px', fontFamily: 'Arial', color: '#ffffff', fontStyle: 'bold' }).setOrigin(0.5); this.scoreText = this.add.text(20, 20, 'Score: 0', { fontSize: '20px', color: '#4ecdc4' }); // Instruction this.add.text(400, 70, 'Is this a PREMISE (support) or CONCLUSION (claim)?', { fontSize: '16px', color: '#888888' }).setOrigin(0.5); // Sentence display this.sentenceBg = this.add.rectangle(400, 180, 700, 120, 0x1b263b, 0.95); this.sentenceText = this.add.text(400, 180, '', { fontSize: '20px', color: '#ffffff', wordWrap: { width: 650 }, align: 'center' }).setOrigin(0.5); // Drop zones this.premiseZone = this.add.rectangle(200, 350, 250, 100, 0x4ecdc4) .setInteractive({ useHandCursor: true }) .on('pointerdown', () => this.selectType('premise')) .on('pointerover', () => this.premiseZone.setAlpha(0.8)) .on('pointerout', () => this.premiseZone.setAlpha(1)); this.add.text(200, 350, '📋 PREMISE\n(Support/Evidence)', { fontSize: '18px', color: '#ffffff', fontStyle: 'bold', align: 'center' }).setOrigin(0.5); this.conclusionZone = this.add.rectangle(600, 350, 250, 100, 0xf9d423) .setInteractive({ useHandCursor: true }) .on('pointerdown', () => this.selectType('conclusion')) .on('pointerover', () => this.conclusionZone.setAlpha(0.8)) .on('pointerout', () => this.conclusionZone.setAlpha(1)); this.add.text(600, 350, '🎯 CONCLUSION\n(Main Claim)', { fontSize: '18px', color: '#ffffff', fontStyle: 'bold', align: 'center' }).setOrigin(0.5); // Feedback this.feedbackText = this.add.text(400, 450, '', { fontSize: '24px', fontStyle: 'bold' }).setOrigin(0.5); // Progress this.progressText = this.add.text(400, 480, '', { fontSize: '14px', color: '#666666' }).setOrigin(0.5); this.nextSentence(); } nextSentence() { if (this.currentIndex >= this.shuffledItems.length) { this.endGame(); return; } const item = this.shuffledItems[this.currentIndex]; this.sentenceText.setText(`"${item.sentence}"`); this.currentType = item.type; this.feedbackText.setText(''); this.progressText.setText(`${this.currentIndex + 1} / ${this.shuffledItems.length}`); } selectType(selected) { if (selected === this.currentType) { this.score += 100; this.scoreText.setText(`Score: ${this.score}`); this.feedbackText.setText('✅ CORRECT!').setColor('#4ecdc4'); this.cameras.main.flash(200, 0, 255, 0, true); } else { this.feedbackText.setText(`❌ Nope! It's a ${this.currentType.toUpperCase()}`).setColor('#ff6b6b'); this.cameras.main.shake(200, 0.01); } this.currentIndex++; this.time.delayedCall(1200, () => this.nextSentence()); } endGame() { this.sentenceText.setText(''); this.feedbackText.setText(`🎉 COMPLETE!\n\nScore: ${this.score}/${this.shuffledItems.length * 100}\n\nClick to play again`) .setColor('#ffffff') .setFontSize('24px'); this.input.once('pointerdown', () => this.scene.restart()); } } // ============================================ // ASSUMPTION HUNTER GAME // ============================================ class AssumptionHunterScene extends Phaser.Scene { constructor() { super({ key: 'AssumptionHunter' }); } create() { this.score = 0; this.currentQ = 0; this.shuffledQs = Phaser.Utils.Array.Shuffle([...assumptionQuestions]); this.cameras.main.setBackgroundColor('#2d132c'); this.add.text(400, 30, '🔍 ASSUMPTION HUNTER', { fontSize: '28px', color: '#ffffff', fontStyle: 'bold' }).setOrigin(0.5); this.scoreText = this.add.text(20, 20, 'Score: 0', { fontSize: '20px', color: '#f9d423' }); // Argument display this.add.text(400, 70, 'Find the HIDDEN ASSUMPTION:', { fontSize: '16px', color: '#888888' }).setOrigin(0.5); this.premiseText = this.add.text(400, 120, '', { fontSize: '16px', color: '#4ecdc4', wordWrap: { width: 650 }, align: 'center' }).setOrigin(0.5); this.conclusionText = this.add.text(400, 170, '', { fontSize: '16px', color: '#f9d423', wordWrap: { width: 650 }, align: 'center' }).setOrigin(0.5); // Answer buttons this.answerButtons = []; for (let i = 0; i < 4; i++) { const y = 250 + (i * 55); const btn = this.add.rectangle(400, y, 650, 45, 0x4a1942) .setInteractive({ useHandCursor: true }) .on('pointerover', () => btn.setFillStyle(0x6b2d5c)) .on('pointerout', () => btn.setFillStyle(0x4a1942)); const txt = this.add.text(400, y, '', { fontSize: '14px', color: '#ffffff', wordWrap: { width: 620 }, align: 'center' }).setOrigin(0.5); this.answerButtons.push({ btn, txt, index: i }); } this.feedbackText = this.add.text(400, 480, '', { fontSize: '20px', fontStyle: 'bold' }).setOrigin(0.5); this.nextQuestion(); } nextQuestion() { if (this.currentQ >= this.shuffledQs.length) { this.endGame(); return; } const q = this.shuffledQs[this.currentQ]; this.premiseText.setText(`Premise: "${q.premise}"`); this.conclusionText.setText(`Conclusion: "${q.conclusion}"`); // Shuffle answers const answers = [q.assumption, ...q.wrong]; Phaser.Utils.Array.Shuffle(answers); this.correctAnswer = answers.indexOf(q.assumption); this.answerButtons.forEach((ab, i) => { ab.txt.setText(answers[i]); ab.btn.removeAllListeners('pointerdown'); ab.btn.on('pointerdown', () => this.selectAnswer(i)); }); this.feedbackText.setText(''); } selectAnswer(index) { if (index === this.correctAnswer) { this.score += 150; this.scoreText.setText(`Score: ${this.score}`); this.feedbackText.setText('✅ You found the assumption!').setColor('#4ecdc4'); this.cameras.main.flash(200, 0, 255, 0, true); } else { this.feedbackText.setText('❌ That\'s not the hidden link...').setColor('#ff6b6b'); this.cameras.main.shake(200, 0.01); } this.currentQ++; this.time.delayedCall(1500, () => this.nextQuestion()); } endGame() { this.premiseText.setText(''); this.conclusionText.setText(''); this.answerButtons.forEach(ab => ab.txt.setText('')); this.feedbackText.setText(`🎉 HUNT COMPLETE!\n\nScore: ${this.score}\n\nClick to play again`) .setColor('#ffffff') .setFontSize('24px'); this.input.once('pointerdown', () => this.scene.restart()); } } // ============================================ // SPEED LR GAME // ============================================ class SpeedLRScene extends Phaser.Scene { constructor() { super({ key: 'SpeedLR' }); } create() { this.score = 0; this.timeLeft = 60; this.currentQ = 0; this.shuffledQs = Phaser.Utils.Array.Shuffle([...speedQuestions]); this.cameras.main.setBackgroundColor('#1a1a2e'); this.add.text(400, 25, '⚡ SPEED LR', { fontSize: '28px', color: '#ffffff', fontStyle: 'bold' }).setOrigin(0.5); this.scoreText = this.add.text(20, 15, 'Score: 0', { fontSize: '18px', color: '#4ecdc4' }); this.timerText = this.add.text(700, 15, '⏱️ 60s', { fontSize: '18px', color: '#ff6b6b' }); // Timer event this.timerEvent = this.time.addEvent({ delay: 1000, callback: () => { this.timeLeft--; this.timerText.setText(`⏱️ ${this.timeLeft}s`); if (this.timeLeft <= 10) this.timerText.setColor('#ff0000'); if (this.timeLeft <= 0) this.endGame(); }, loop: true }); // Stimulus this.stimulusBg = this.add.rectangle(400, 120, 720, 80, 0x16213e); this.stimulusText = this.add.text(400, 120, '', { fontSize: '14px', color: '#ffffff', wordWrap: { width: 680 }, align: 'center' }).setOrigin(0.5); // Question this.questionText = this.add.text(400, 180, '', { fontSize: '16px', color: '#f9d423', fontStyle: 'bold' }).setOrigin(0.5); // Answers this.answerButtons = []; for (let i = 0; i < 4; i++) { const y = 240 + (i * 55); const btn = this.add.rectangle(400, y, 680, 45, 0x0f3460) .setInteractive({ useHandCursor: true }) .on('pointerover', () => btn.setFillStyle(0x1a5276)) .on('pointerout', () => btn.setFillStyle(0x0f3460)); const txt = this.add.text(400, y, '', { fontSize: '13px', color: '#ffffff', wordWrap: { width: 650 }, align: 'center' }).setOrigin(0.5); this.answerButtons.push({ btn, txt }); } this.feedbackText = this.add.text(400, 470, '', { fontSize: '20px', fontStyle: 'bold' }).setOrigin(0.5); this.nextQuestion(); } nextQuestion() { if (this.currentQ >= this.shuffledQs.length) { // Loop questions this.currentQ = 0; Phaser.Utils.Array.Shuffle(this.shuffledQs); } const q = this.shuffledQs[this.currentQ]; this.stimulusText.setText(q.stimulus); this.questionText.setText(q.question); const answers = [q.correct, ...q.wrong]; Phaser.Utils.Array.Shuffle(answers); this.correctIndex = answers.indexOf(q.correct); this.answerButtons.forEach((ab, i) => { ab.txt.setText(answers[i]); ab.btn.removeAllListeners('pointerdown'); ab.btn.on('pointerdown', () => this.selectAnswer(i)); }); this.feedbackText.setText(''); } selectAnswer(index) { if (index === this.correctIndex) { this.score += 100; this.timeLeft += 5; // Bonus time! this.scoreText.setText(`Score: ${this.score}`); this.feedbackText.setText('✅ +100 pts, +5 sec!').setColor('#4ecdc4'); } else { this.timeLeft -= 3; this.feedbackText.setText('❌ -3 seconds!').setColor('#ff6b6b'); } this.currentQ++; this.time.delayedCall(800, () => this.nextQuestion()); } endGame() { this.timerEvent.remove(); this.stimulusText.setText(''); this.questionText.setText(''); this.answerButtons.forEach(ab => ab.txt.setText('')); this.feedbackText.setText(`⏱️ TIME'S UP!\n\nFinal Score: ${this.score}\n\nClick to play again`) .setColor('#ffffff') .setFontSize('24px'); this.input.once('pointerdown', () => this.scene.restart()); } } // ============================================ // GAME LAUNCHER // ============================================ function startGame(type) { if (currentGame) { currentGame.destroy(true); } const config = { type: Phaser.AUTO, width: 800, height: 500, parent: 'game-area', backgroundColor: '#1a1a2e', scene: [] }; switch(type) { case 'flaw': config.scene = [FlawFighterScene]; break; case 'premise': config.scene = [PremiseSorterScene]; break; case 'assumption': config.scene = [AssumptionHunterScene]; break; case 'speed': config.scene = [SpeedLRScene]; break; } currentGame = new Phaser.Game(config); } // Start with a welcome message document.getElementById('game-area').innerHTML = `
🐝

Welcome to Burton Method Games!

Learn LSAT logic through play

👆 Select a game above to begin

`;