1+ class MillionaireGame {
2+ constructor ( ) {
3+ this . currentQuestion = 0 ;
4+ this . currentPrize = 0 ;
5+ this . isGameActive = false ;
6+ this . helpLinesUsed = {
7+ fiftyFifty : false ,
8+ phoneFriend : false ,
9+ askAudience : false ,
10+ askHost : false
11+ } ;
12+ this . moneyLadder = [ 500 , 1000 , 5000 , 10000 , 25000 , 50000 , 100000 , 250000 , 500000 , 1000000 ] ;
13+ this . safeHavens = [ 1000 , 50000 ] ;
14+
15+ this . initializeElements ( ) ;
16+ this . attachEventListeners ( ) ;
17+ }
18+
19+ initializeElements ( ) {
20+ this . questionElement = document . getElementById ( 'question' ) ;
21+ this . answerButtons = Array . from ( document . getElementsByClassName ( 'answer-button' ) ) ;
22+ this . moneyItems = Array . from ( document . getElementsByClassName ( 'money-item' ) ) ;
23+ this . currentPrizeElement = document . getElementById ( 'current-prize' ) ;
24+ this . messageElement = document . getElementById ( 'message' ) ;
25+ this . startButton = document . getElementById ( 'start-game' ) ;
26+ this . quitButton = document . getElementById ( 'quit-game' ) ;
27+
28+ // Help line buttons
29+ this . fiftyFiftyButton = document . getElementById ( 'fifty-fifty' ) ;
30+ this . phoneFriendButton = document . getElementById ( 'phone-friend' ) ;
31+ this . askAudienceButton = document . getElementById ( 'ask-audience' ) ;
32+ this . askHostButton = document . getElementById ( 'ask-host' ) ;
33+ }
34+
35+ attachEventListeners ( ) {
36+ this . startButton . addEventListener ( 'click' , ( ) => this . startGame ( ) ) ;
37+ this . quitButton . addEventListener ( 'click' , ( ) => this . quitGame ( ) ) ;
38+ this . answerButtons . forEach ( button => {
39+ button . addEventListener ( 'click' , ( ) => this . handleAnswer ( button ) ) ;
40+ } ) ;
41+
42+ // Help line event listeners
43+ this . fiftyFiftyButton . addEventListener ( 'click' , ( ) => this . useFiftyFifty ( ) ) ;
44+ this . phoneFriendButton . addEventListener ( 'click' , ( ) => this . usePhoneFriend ( ) ) ;
45+ this . askAudienceButton . addEventListener ( 'click' , ( ) => this . useAskAudience ( ) ) ;
46+ this . askHostButton . addEventListener ( 'click' , ( ) => this . useAskHost ( ) ) ;
47+ }
48+
49+ async startGame ( ) {
50+ this . isGameActive = true ;
51+ this . currentQuestion = 0 ;
52+ this . currentPrize = 0 ;
53+ this . helpLinesUsed = {
54+ fiftyFifty : false ,
55+ phoneFriend : false ,
56+ askAudience : false ,
57+ askHost : false
58+ } ;
59+
60+ this . startButton . style . display = 'none' ;
61+ this . quitButton . style . display = 'block' ;
62+ this . currentPrizeElement . textContent = '0' ;
63+
64+ await this . loadNextQuestion ( ) ;
65+ }
66+
67+ quitGame ( ) {
68+ const guaranteedPrize = this . getGuaranteedPrize ( ) ;
69+ this . showMessage ( `Game Over! You're walking away with $${ guaranteedPrize . toLocaleString ( ) } ` ) ;
70+ this . resetGame ( ) ;
71+ }
72+
73+ resetGame ( ) {
74+ this . isGameActive = false ;
75+ this . startButton . style . display = 'block' ;
76+ this . quitButton . style . display = 'none' ;
77+ this . answerButtons . forEach ( button => {
78+ button . disabled = false ;
79+ button . className = 'answer-button' ;
80+ button . textContent = button . getAttribute ( 'data-index' ) === '0' ? 'A: ' :
81+ button . getAttribute ( 'data-index' ) === '1' ? 'B: ' :
82+ button . getAttribute ( 'data-index' ) === '2' ? 'C: ' : 'D: ' ;
83+ } ) ;
84+ this . enableAllHelpLines ( ) ;
85+ this . updateMoneyLadder ( - 1 ) ;
86+ }
87+
88+ async loadNextQuestion ( ) {
89+ const difficulty = Math . min ( 9 , Math . floor ( this . currentQuestion / 2 ) ) ;
90+ const prompt = `Generate a multiple choice trivia question for "Who Wants to Be a Millionaire?"
91+ Difficulty level: ${ difficulty } /9 (0 being easiest, 9 being hardest).
92+ Format: Return a JSON object with the following structure:
93+ {
94+ "question": "The question text",
95+ "answers": ["correct answer", "wrong answer 1", "wrong answer 2", "wrong answer 3"],
96+ "correctIndex": 0
97+ }
98+ Make sure the question is challenging but fair, and all answers are plausible.` ;
99+
100+ try {
101+ const response = await fetch ( 'https://text.pollinations.ai/' , {
102+ method : 'POST' ,
103+ headers : {
104+ 'Content-Type' : 'application/json' ,
105+ } ,
106+ body : JSON . stringify ( {
107+ messages : [
108+ { role : 'system' , content : 'You are a game show question writer.' } ,
109+ { role : 'user' , content : prompt }
110+ ] ,
111+ jsonMode : true
112+ } ) ,
113+ } ) ;
114+
115+ const data = await response . json ( ) ;
116+ this . currentQuestionData = data ;
117+
118+ // Update UI with new question
119+ this . questionElement . textContent = data . question ;
120+ this . answerButtons . forEach ( ( button , index ) => {
121+ button . textContent = `${ String . fromCharCode ( 65 + index ) } : ${ data . answers [ index ] } ` ;
122+ button . disabled = false ;
123+ button . className = 'answer-button' ;
124+ } ) ;
125+
126+ this . updateMoneyLadder ( this . currentQuestion ) ;
127+ } catch ( error ) {
128+ console . error ( 'Error loading question:' , error ) ;
129+ this . showMessage ( 'Error loading question. Please try again.' ) ;
130+ }
131+ }
132+
133+ async handleAnswer ( button ) {
134+ if ( ! this . isGameActive ) return ;
135+
136+ const selectedIndex = parseInt ( button . getAttribute ( 'data-index' ) ) ;
137+ button . classList . add ( 'selected' ) ;
138+ this . answerButtons . forEach ( btn => btn . disabled = true ) ;
139+
140+ // Dramatic pause
141+ await new Promise ( resolve => setTimeout ( resolve , 2000 ) ) ;
142+
143+ if ( selectedIndex === this . currentQuestionData . correctIndex ) {
144+ button . classList . add ( 'correct' ) ;
145+ this . currentPrize = this . moneyLadder [ this . currentQuestion ] ;
146+ this . currentPrizeElement . textContent = this . currentPrize . toLocaleString ( ) ;
147+
148+ if ( this . currentQuestion === this . moneyLadder . length - 1 ) {
149+ this . showMessage ( 'Congratulations! You\'ve won the million dollars!' ) ;
150+ this . resetGame ( ) ;
151+ } else {
152+ this . currentQuestion ++ ;
153+ await new Promise ( resolve => setTimeout ( resolve , 1500 ) ) ;
154+ await this . loadNextQuestion ( ) ;
155+ }
156+ } else {
157+ button . classList . add ( 'wrong' ) ;
158+ const correctButton = this . answerButtons [ this . currentQuestionData . correctIndex ] ;
159+ correctButton . classList . add ( 'correct' ) ;
160+
161+ const guaranteedPrize = this . getGuaranteedPrize ( ) ;
162+ this . showMessage ( `Game Over! You walk away with $${ guaranteedPrize . toLocaleString ( ) } ` ) ;
163+ await new Promise ( resolve => setTimeout ( resolve , 2000 ) ) ;
164+ this . resetGame ( ) ;
165+ }
166+ }
167+
168+ getGuaranteedPrize ( ) {
169+ let guaranteedPrize = 0 ;
170+ for ( let i = 0 ; i < this . currentQuestion ; i ++ ) {
171+ if ( this . safeHavens . includes ( this . moneyLadder [ i ] ) ) {
172+ guaranteedPrize = this . moneyLadder [ i ] ;
173+ }
174+ }
175+ return guaranteedPrize ;
176+ }
177+
178+ updateMoneyLadder ( currentQuestionIndex ) {
179+ this . moneyItems . forEach ( ( item , index ) => {
180+ item . classList . remove ( 'active' ) ;
181+ if ( index === currentQuestionIndex ) {
182+ item . classList . add ( 'active' ) ;
183+ }
184+ } ) ;
185+ }
186+
187+ showMessage ( message ) {
188+ this . messageElement . textContent = message ;
189+ }
190+
191+ // Help Line Implementations
192+ async useFiftyFifty ( ) {
193+ if ( this . helpLinesUsed . fiftyFifty || ! this . isGameActive ) return ;
194+
195+ this . helpLinesUsed . fiftyFifty = true ;
196+ this . fiftyFiftyButton . disabled = true ;
197+
198+ const correctIndex = this . currentQuestionData . correctIndex ;
199+ const wrongIndices = [ 0 , 1 , 2 , 3 ] . filter ( i => i !== correctIndex ) ;
200+ const indicesToKeep = [ correctIndex , wrongIndices [ Math . floor ( Math . random ( ) * wrongIndices . length ) ] ] ;
201+
202+ this . answerButtons . forEach ( ( button , index ) => {
203+ if ( ! indicesToKeep . includes ( index ) ) {
204+ button . disabled = true ;
205+ button . style . opacity = '0.3' ;
206+ }
207+ } ) ;
208+ }
209+
210+ async usePhoneFriend ( ) {
211+ if ( this . helpLinesUsed . phoneFriend || ! this . isGameActive ) return ;
212+
213+ this . helpLinesUsed . phoneFriend = true ;
214+ this . phoneFriendButton . disabled = true ;
215+
216+ const prompt = `As an expert friend, analyze this question and provide your thoughts:
217+ Question: ${ this . currentQuestionData . question }
218+ Options: ${ this . answerButtons . map ( b => b . textContent ) . join ( ', ' ) }
219+ Provide a natural response as if you're on the phone, with about 80% accuracy.` ;
220+
221+ try {
222+ const response = await fetch ( 'https://text.pollinations.ai/' , {
223+ method : 'POST' ,
224+ headers : { 'Content-Type' : 'application/json' } ,
225+ body : JSON . stringify ( {
226+ messages : [
227+ { role : 'system' , content : 'You are an expert friend helping on Who Wants to Be a Millionaire.' } ,
228+ { role : 'user' , content : prompt }
229+ ]
230+ } ) ,
231+ } ) ;
232+
233+ const data = await response . json ( ) ;
234+ this . showMessage ( `Friend says: ${ data . content } ` ) ;
235+ } catch ( error ) {
236+ this . showMessage ( 'Sorry, couldn\'t reach your friend. Try another lifeline!' ) ;
237+ }
238+ }
239+
240+ async useAskAudience ( ) {
241+ if ( this . helpLinesUsed . askAudience || ! this . isGameActive ) return ;
242+
243+ this . helpLinesUsed . askAudience = true ;
244+ this . askAudienceButton . disabled = true ;
245+
246+ const correctIndex = this . currentQuestionData . correctIndex ;
247+ const percentages = Array ( 4 ) . fill ( 0 ) ;
248+ const difficulty = Math . min ( 9 , Math . floor ( this . currentQuestion / 2 ) ) ;
249+
250+ // Audience is more accurate on easier questions
251+ const accuracy = 1 - ( difficulty * 0.08 ) ; // 92% accurate at easiest, 20% at hardest
252+ const correctPercentage = Math . floor ( accuracy * 100 ) ;
253+ percentages [ correctIndex ] = correctPercentage ;
254+
255+ // Distribute remaining percentage among wrong answers
256+ const remaining = 100 - correctPercentage ;
257+ const wrongIndices = [ 0 , 1 , 2 , 3 ] . filter ( i => i !== correctIndex ) ;
258+ wrongIndices . forEach ( ( index , i ) => {
259+ percentages [ index ] = i === wrongIndices . length - 1
260+ ? remaining - wrongIndices . slice ( 0 , - 1 ) . reduce ( ( sum , idx ) => sum + percentages [ idx ] , 0 )
261+ : Math . floor ( remaining / ( wrongIndices . length - i ) ) ;
262+ } ) ;
263+
264+ const audienceResults = this . answerButtons . map ( ( button , index ) =>
265+ `${ button . textContent . split ( ':' ) [ 0 ] } : ${ percentages [ index ] } %`
266+ ) . join ( '\n' ) ;
267+
268+ this . showMessage ( `Audience Results:\n${ audienceResults } ` ) ;
269+ }
270+
271+ async useAskHost ( ) {
272+ if ( this . helpLinesUsed . askHost || ! this . isGameActive ) return ;
273+
274+ this . helpLinesUsed . askHost = true ;
275+ this . askHostButton . disabled = true ;
276+
277+ const prompt = `As the game show host, provide a helpful but indirect hint about this question:
278+ Question: ${ this . currentQuestionData . question }
279+ Options: ${ this . answerButtons . map ( b => b . textContent ) . join ( ', ' ) }
280+ Give a clever hint that helps narrow down the options without directly revealing the answer.` ;
281+
282+ try {
283+ const response = await fetch ( 'https://text.pollinations.ai/' , {
284+ method : 'POST' ,
285+ headers : { 'Content-Type' : 'application/json' } ,
286+ body : JSON . stringify ( {
287+ messages : [
288+ { role : 'system' , content : 'You are the host of Who Wants to Be a Millionaire.' } ,
289+ { role : 'user' , content : prompt }
290+ ]
291+ } ) ,
292+ } ) ;
293+
294+ const data = await response . json ( ) ;
295+ this . showMessage ( `Host: ${ data . content } ` ) ;
296+ } catch ( error ) {
297+ this . showMessage ( 'The host seems to be at a loss for words!' ) ;
298+ }
299+ }
300+
301+ enableAllHelpLines ( ) {
302+ Object . keys ( this . helpLinesUsed ) . forEach ( helpLine => {
303+ this . helpLinesUsed [ helpLine ] = false ;
304+ } ) ;
305+ this . fiftyFiftyButton . disabled = false ;
306+ this . phoneFriendButton . disabled = false ;
307+ this . askAudienceButton . disabled = false ;
308+ this . askHostButton . disabled = false ;
309+ }
310+ }
311+
312+ // Initialize the game when the page loads
313+ document . addEventListener ( 'DOMContentLoaded' , ( ) => {
314+ window . game = new MillionaireGame ( ) ;
315+ } ) ;
0 commit comments