1 /*
2    options.c
3 
4    The options screen loop.
5 
6    Copyright 2001, 2002, 2003, 2005, 2006, 2007, 2008, 2009, 2010.
7    Authors: Bill Kendrick, David Bruce, Tim Holy, Brendan Luchen.
8    Project email: <tuxmath-devel@lists.sourceforge.net>
9    Project website: http://tux4kids.alioth.debian.org
10 
11 options.c is part of "Tux, of Math Command", a.k.a. "tuxmath".
12 
13 Tuxmath is free software: you can redistribute it and/or modify
14 it under the terms of the GNU General Public License as published by
15 the Free Software Foundation; either version 3 of the License, or
16 (at your option) any later version.
17 
18 Tuxmath is distributed in the hope that it will be useful,
19 but WITHOUT ANY WARRANTY; without even the implied warranty of
20 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
21 GNU General Public License for more details.
22 
23 You should have received a copy of the GNU General Public License
24 along with this program.  If not, see <http://www.gnu.org/licenses/>.  */
25 
26 
27 
28 
29 #include <stdio.h>
30 #include <stdlib.h>
31 #include <string.h>
32 
33 //#include "SDL.h"
34 
35 #include "mathcards.h"
36 
37 #include "options.h"
38 #include "fileops.h"
39 #include "setup.h"
40 #include "game.h"
41 #include "globals.h"
42 //#include "tuxmath.h"
43 
44 /* FIXME figure out what oper_override is supposed to do and make sure */
45 /* this file behaves accordingly! */
46 
47 //int opers[NUM_OPERS], range_enabled[NUM_Q_RANGES];
48 
49 /* global debug masks */
50 //int debug_status;
51 
52 /* bitmasks for debugging options */
53 #define dstart  (1 << (START_CUSTOM_DEBUG))
54 const int debug_setup          = dstart << 0;
55 const int debug_fileops        = dstart << 1;
56 const int debug_multiplayer    = dstart << 2;
57 const int debug_titlescreen    = dstart << 3;
58 const int debug_options        = dstart << 4;
59 const int debug_text_and_intl  = dstart << 5;
60 const int debug_game           = dstart << 6;
61 const int debug_factoroids     = dstart << 7;
62 const int debug_lan            = dstart << 8;
63 const int debug_mathcards      = dstart << 9;
64 const int debug_highscore      = dstart << 10;
65 const int debug_lessons        = dstart << 11;
66 
67 /* extern'd constants */
68 
69 const char* const OPTION_TEXT[NUM_GLOBAL_OPTS+1] = {
70   "PER_USER_CONFIG",
71   "USE_SOUND",
72   "MENU_SOUND",
73   "MENU_MUSIC",
74   "FULLSCREEN",
75   "USE_KEYPAD",
76   "USE_IGLOOS",
77   "END_OF_OPTS"
78 };
79 
80 const int DEFAULT_GLOBAL_OPTS[NUM_GLOBAL_OPTS] = {
81   1,
82   1,
83   1,
84   1,
85   1,
86   0,
87   1
88 };
89 
90 
91 /* file scope only now that accessor functions used: */
92 static game_option_type* game_options = NULL;
93 static global_option_type* global_options = NULL;
94 
95 /*local function prototypes: */
96 static int int_to_bool(int i);
97 //static int find_and_set_option(const char* name, int val);
98 
99 
100 /********************************************************************/
101 /*  "Public Methods" for options struct:                            */
102 /********************************************************************/
103 
Opts_Initialize(void)104 int Opts_Initialize(void)
105 {
106   int i;
107 
108   /* Only allocate game_options if not already done: */
109   if(!game_options)
110     game_options = (game_option_type*)malloc(sizeof(game_option_type));
111   /* bail out if somehow malloc failed: */
112   if (!game_options)
113     return 0;
114 
115   /* Same routine for global options: */
116   if(!global_options)
117     global_options = (global_option_type*)malloc(sizeof(global_option_type));
118   if(!global_options)
119     return 0;
120 
121   /* set global program options */
122   for (i = 0; i < NUM_GLOBAL_OPTS; ++i)
123     global_options->iopts[i] = DEFAULT_GLOBAL_OPTS[i];
124 
125   /* set general game options */
126   global_options->iopts[PER_USER_CONFIG] = DEFAULT_PER_USER_CONFIG;
127   global_options->iopts[USE_SOUND] = DEFAULT_USE_SOUND;
128   global_options->iopts[MENU_SOUND] = DEFAULT_MENU_SOUND;
129   global_options->iopts[MENU_MUSIC] = DEFAULT_MENU_MUSIC;
130   global_options->iopts[FULLSCREEN] = DEFAULT_FULLSCREEN;
131   global_options->iopts[USE_KEYPAD] = DEFAULT_USE_KEYPAD;
132   global_options->iopts[USE_IGLOOS] = DEFAULT_USE_IGLOOS;
133   strncpy(game_options->lesson_title, DEFAULT_LESSON_TITLE,
134           sizeof(game_options->lesson_title));
135   strncpy(game_options->current_font_name, DEFAULT_FONT_NAME,
136           sizeof(game_options->current_font_name));
137   game_options->lan_mode = DEFAULT_LAN_MODE;
138   game_options->use_bkgd = DEFAULT_USE_BKGD;
139   game_options->help_mode = DEFAULT_HELP_MODE;
140   game_options->demo_mode = DEFAULT_DEMO_MODE;
141   game_options->oper_override = DEFAULT_OPER_OVERRIDE;
142   game_options->allow_pause = DEFAULT_ALLOW_PAUSE;
143   game_options->bonus_comet_interval = DEFAULT_BONUS_COMET_INTERVAL;
144   game_options->bonus_speed_ratio = DEFAULT_BONUS_SPEED_RATIO;
145   game_options->speed = DEFAULT_SPEED;
146   game_options->allow_speedup = DEFAULT_ALLOW_SPEEDUP;
147   game_options->speedup_factor = DEFAULT_SPEEDUP_FACTOR;
148   game_options->max_speed = DEFAULT_MAX_SPEED;
149   game_options->slow_after_wrong = DEFAULT_SLOW_AFTER_WRONG;
150   game_options->starting_comets = DEFAULT_STARTING_COMETS;
151   game_options->extra_comets_per_wave = DEFAULT_EXTRA_COMETS_PER_WAVE;
152   game_options->max_comets = DEFAULT_MAX_COMETS;
153   game_options->use_powerup_comets = DEFAULT_USE_POWERUP_COMETS;
154   game_options->powerup_freq = DEFAULT_POWERUP_FREQ;
155   game_options->save_summary = DEFAULT_SAVE_SUMMARY;
156   game_options->sound_hw_available = DEFAULT_SOUND_HW_AVAILABLE;
157   game_options->use_feedback = DEFAULT_USE_FEEDBACK;
158   game_options->danger_level = DEFAULT_DANGER_LEVEL;
159   game_options->danger_level_speedup = DEFAULT_DANGER_LEVEL_SPEEDUP;
160   game_options->danger_level_max = DEFAULT_DANGER_LEVEL_MAX;
161   game_options->city_expl_handicap = DEFAULT_CITY_EXPL_HANDICAP;
162   game_options->last_score = DEFAULT_LAST_SCORE;
163 
164   game_options->num_cities = DEFAULT_NUM_CITIES;   /* MUST BE AN EVEN NUMBER! */
165   game_options->max_city_colors = DEFAULT_MAX_CITY_COLORS;
166 
167   DEBUGCODE(debug_options)
168     print_game_options(stdout, 0);
169 
170   return 1;
171 }
172 
173 
Opts_Cleanup(void)174 void Opts_Cleanup(void)
175 {
176   if (game_options)
177   {
178     free(game_options);
179     game_options = 0;
180   }
181 }
182 
183 
184 //* "Set" functions for tuxmath options struct: */
Opts_MapTextToIndex(const char * text)185 unsigned int Opts_MapTextToIndex(const char* text)
186 {
187   int i;
188   for (i = 0; i < NUM_GLOBAL_OPTS; ++i)
189   {
190     if (0 == strcasecmp(text, OPTION_TEXT[i]) )
191     {
192       return i;
193     }
194   }
195   DEBUGMSG(debug_options, "'%s' isn't a global option\n", text);
196   return -1;
197 }
198 
Opts_GetGlobalOp(const char * text)199 int Opts_GetGlobalOp(const char* text)
200 {
201   int index = Opts_MapTextToIndex(text);
202   if (index < NUM_GLOBAL_OPTS)
203     return Opts_GetGlobalOpt(index);
204   return 0;
205 }
206 
Opts_GetGlobalOpt(unsigned int index)207 int Opts_GetGlobalOpt(unsigned int index)
208 {
209   if (index < NUM_GLOBAL_OPTS)
210     return global_options->iopts[index];
211   DEBUGMSG(debug_options, "Invalid global option index: %d\n", index);
212   return 0;
213 }
214 
Opts_SetGlobalOp(const char * text,int val)215 void Opts_SetGlobalOp(const char* text, int val)
216 {
217   int index = Opts_MapTextToIndex(text);
218   if (index < NUM_GLOBAL_OPTS)
219     Opts_SetGlobalOpt(index, val);
220 }
221 
Opts_SetGlobalOpt(unsigned int index,int val)222 void Opts_SetGlobalOpt(unsigned int index, int val)
223 {
224   if (index < NUM_GLOBAL_OPTS)
225   {
226     //Need to make sure we don't turn on sound options if sound
227     //system couldn't be set up:
228     if(index == USE_SOUND || index == MENU_SOUND || index == MENU_MUSIC)
229     {
230       if(!Opts_SoundHWAvailable())
231         val = 0;
232     }
233     global_options->iopts[index] = val;
234   }
235   else
236     DEBUGMSG(debug_options, "Invalid global option index: %d\n", index);
237 }
238 
239 
240 //void Opts_SetPerUserConfig(int val)
241 //{
242 //  global_options->iopts[PER_USER_CONFIG] = int_to_bool(val);
243 //}
244 //
245 //
246 //void Opts_SetUseSound(int val)
247 //{
248 //  if (val == -1)
249 //    global_options->iopts[USE_SOUND] = val;
250 //  else if (global_options->iopts[USE_SOUND] != -1)
251 //    global_options->iopts[USE_SOUND] = int_to_bool(val);
252 //}
253 //
254 //
255 //void Opts_SetMenuSound(int val)
256 //{
257 //  global_options->iopts[MENU_SOUND] = int_to_bool(val);
258 //}
259 //
260 //
261 //void Opts_SetMenuMusic(int val)
262 //{
263 //  global_options->iopts[MENU_MUSIC] = int_to_bool(val);
264 //}
265 
266 
267 ///* FIXME need to actually change screen resolution when this is called */
268 //void Opts_SetFullscreen(int val)
269 //{
270 //  global_options->iopts[FULLSCREEN] = int_to_bool(val);
271 //}
272 
Opts_SetLanMode(int val)273 void Opts_SetLanMode(int val)
274 {
275   game_options->lan_mode = int_to_bool(val);
276 }
277 
Opts_SetLessonTitle(char * title)278 void Opts_SetLessonTitle(char* title)
279 {
280   if (title && title[0] != '\0')
281   strncpy(game_options->lesson_title, title, sizeof(game_options->lesson_title));
282 }
283 
Opts_SetFontName(char * font_name)284 void Opts_SetFontName(char* font_name)
285 {
286   if (font_name && font_name[0] != '\0')
287   strncpy(game_options->current_font_name, font_name, sizeof(game_options->current_font_name));
288 }
289 
Opts_SetUseBkgd(int val)290 void Opts_SetUseBkgd(int val)
291 {
292   game_options->use_bkgd = int_to_bool(val);
293 }
294 
295 
Opts_SetHelpMode(int val)296 void Opts_SetHelpMode(int val)
297 {
298   game_options->help_mode = int_to_bool(val);
299 }
300 
301 
Opts_SetDemoMode(int val)302 void Opts_SetDemoMode(int val)
303 {
304   game_options->demo_mode = int_to_bool(val);
305 }
306 
307 
Opts_SetOperOverride(int val)308 void Opts_SetOperOverride(int val)
309 {
310   game_options->oper_override = int_to_bool(val);
311 }
312 
313 
314 //void Opts_SetUseKeypad(int val)
315 //{
316 //  global_options->iopts[USE_KEYPAD] = int_to_bool(val);
317 //}
318 
319 
Opts_SetAllowPause(int val)320 void Opts_SetAllowPause(int val)
321 {
322   game_options->allow_pause = int_to_bool(val);
323 }
324 
325 
326 //void Opts_SetUseIgloos(int val)
327 //{
328 //  global_options->iopts[USE_IGLOOS] = int_to_bool(val);
329 //}
330 
331 
Opts_SetBonusCometInterval(int val)332 void Opts_SetBonusCometInterval(int val)
333 {
334   if (val < 0)
335     val = 0;
336   game_options->bonus_comet_interval = val;
337 }
338 
339 
Opts_SetBonusSpeedRatio(float val)340 void Opts_SetBonusSpeedRatio(float val)
341 {
342   if (val < 1)
343   {
344     val = 1;
345     fprintf(stderr,"bonus_speed_ratio must be at least 1, resetting accordingly.\n");
346   }
347   if (val > MAX_BONUS_SPEED_RATIO)
348   {
349     val = MAX_BONUS_SPEED_RATIO;
350     fprintf(stderr,"Warning: requested bonus_speed_ratio above maximum, setting to %g.\n",MAX_BONUS_SPEED_RATIO);
351   }
352   game_options->bonus_speed_ratio = val;
353 }
354 
355 
Opts_SetSpeed(float val)356 void Opts_SetSpeed(float val)
357 {
358   if (val < MINIMUM_SPEED)
359   {
360     val = MINIMUM_SPEED;
361     fprintf(stderr,"Warning: requested speed below minimum, setting to %g.\n",MINIMUM_SPEED);
362   }
363   if (val > MAX_MAX_SPEED)
364   {
365     val = MAX_MAX_SPEED;
366     fprintf(stderr,"Warning: requested speed above Tuxmath's maximum, setting to %g.\n",MAX_MAX_SPEED);
367   }
368   if (val > Opts_MaxSpeed())
369   {
370     val = Opts_MaxSpeed();
371     fprintf(stderr,"Warning: requested speed above currently selected maximum, setting to %g.\n",
372             Opts_MaxSpeed());
373   }
374   game_options->speed = val;
375 }
376 
377 
Opts_SetAllowSpeedup(int val)378 void Opts_SetAllowSpeedup(int val)
379 {
380   game_options->allow_speedup = int_to_bool(val);
381 }
382 
383 
Opts_SetSpeedupFactor(float val)384 void Opts_SetSpeedupFactor(float val)
385 {
386   if (val < MIN_SPEEDUP_FACTOR)
387   {
388     val = MIN_SPEEDUP_FACTOR;
389     fprintf(stderr,"Warning: requested speedup factor below Tuxmath's minimum, setting to %g.\n",MIN_SPEEDUP_FACTOR);
390   }
391   if (val > MAX_SPEEDUP_FACTOR)
392   {
393     val = MAX_SPEEDUP_FACTOR;
394     fprintf(stderr,"Warning: requested speedup factor above Tuxmath's maximum, setting to %g.\n",MAX_SPEEDUP_FACTOR);
395   }
396   game_options->speedup_factor = val;
397 }
398 
399 
Opts_SetMaxSpeed(float val)400 void Opts_SetMaxSpeed(float val)
401 {
402   if (val < MINIMUM_SPEED)
403   {
404     val = MINIMUM_SPEED;
405     fprintf(stderr,"Warning: requested max speed below minimum, setting to %g.\n",
406             MINIMUM_SPEED);
407   }
408   if (val > MAX_MAX_SPEED)
409   {
410     val = MAX_MAX_SPEED;
411     fprintf(stderr,"Warning: requested max speed above Tuxmath's maximum, setting to %g.\n",
412             MAX_MAX_SPEED);
413   }
414   if (val < Opts_Speed())
415   {
416     val = Opts_Speed();
417     fprintf(stderr,"Warning: requested max speed less than current speed, setting to %g.\n",
418             Opts_MaxSpeed());
419   }
420   game_options->max_speed = val;
421 }
422 
423 
Opts_SetSlowAfterWrong(int val)424 void Opts_SetSlowAfterWrong(int val)
425 {
426   game_options->slow_after_wrong = int_to_bool(val);
427 }
428 
429 
Opts_SetStartingComets(int val)430 void Opts_SetStartingComets(int val)
431 {
432   if (val < MIN_COMETS)
433   {
434     val = MIN_COMETS;
435     fprintf(stderr,"Warning: requested starting comets below Tuxmath's minimum, setting to %d.\n",
436             MIN_COMETS);
437   }
438   if (val > MAX_MAX_COMETS)
439   {
440     val = MAX_MAX_COMETS;
441     fprintf(stderr,"Warning: requested starting comets above Tuxmath's maximum, setting to %d.\n",
442             MAX_MAX_COMETS);
443   }
444   if (val > Opts_MaxComets())
445   {
446     val = Opts_MaxComets();
447     fprintf(stderr,"Warning: requested starting comets above currently selected maximum, setting to %d.\n",
448             Opts_MaxComets());
449   }
450   game_options->starting_comets = val;
451 }
452 
453 
Opts_SetExtraCometsPerWave(int val)454 void Opts_SetExtraCometsPerWave(int val)
455 {
456   if (val < 0)
457   {
458     val = 0;
459     fprintf(stderr,"Warning: requested extra comets below Tuxmath's minimum, setting to %d.\n",
460             0);
461   }
462   if (val > MAX_MAX_COMETS)
463   {
464     val = MAX_MAX_COMETS;
465     fprintf(stderr,"Warning: requested extra comets above Tuxmath's maximum, setting to %d.\n",
466             MAX_MAX_COMETS);
467   }
468   if (val > Opts_MaxComets())
469   {
470     val = Opts_MaxComets();
471     fprintf(stderr,"Warning: requested extra comets above currently selected maximum, setting to %d.\n",
472             Opts_MaxComets());
473   }
474   game_options->extra_comets_per_wave = val;
475 }
476 
477 
Opts_SetMaxComets(int val)478 void Opts_SetMaxComets(int val)
479 {
480   if (val < MIN_COMETS)
481   {
482     val = MIN_COMETS;
483     fprintf(stderr,"Warning: requested max comets below Tuxmath's minimum, setting to %d.\n",
484             MIN_COMETS);
485   }
486   if (val > MAX_MAX_COMETS)
487   {
488     val = MAX_MAX_COMETS;
489     fprintf(stderr,"Warning: requested max comets above Tuxmath's maximum, setting to %d.\n",
490             MAX_MAX_COMETS);
491   }
492   game_options->max_comets = val;
493 }
494 
Opts_SetUsePowerupComets(int val)495 void Opts_SetUsePowerupComets(int val)
496 {
497   game_options->use_powerup_comets = int_to_bool(val);
498 }
499 
Opts_SetPowerupFreq(int val)500 void Opts_SetPowerupFreq(int val)
501 {
502   if(val > 0)
503     game_options->powerup_freq = val;
504   else
505     fprintf(stderr,"Warning: requested powerup frequency illegal, setting to %d.\n",
506             DEFAULT_POWERUP_FREQ);
507 
508 }
509 
510 
Opts_SetNextMission(char * str)511 void Opts_SetNextMission(char* str)
512 {
513   int len = strlen(str);
514   if (len < PATH_MAX)
515   {
516     strcpy(game_options->next_mission, str);
517   }
518   else
519   {
520     fprintf(stderr,"Warning: Opts_SetNextMission() - string invalid or overflow\n");
521   }
522 }
523 
524 
Opts_SetSaveSummary(int val)525 void Opts_SetSaveSummary(int val)
526 {
527   game_options->save_summary = int_to_bool(val);
528 }
529 
530 
Opts_SetUseFeedback(int val)531 void Opts_SetUseFeedback(int val)
532 {
533   game_options->use_feedback = int_to_bool(val);
534 }
535 
536 
Opts_SetDangerLevel(float val)537 void Opts_SetDangerLevel(float val)
538 {
539   if (val < 0)
540   {
541     val = 0;
542     fprintf(stderr,"Warning: danger level must be between 0 and 1, setting to 0.\n");
543   }
544   if (val > 1)
545   {
546     val = 1;
547     fprintf(stderr,"Warning: danger level must be between 0 and 1, setting to 1.\n");
548   }
549   game_options->danger_level = val;
550 }
551 
552 
Opts_SetDangerLevelSpeedup(float val)553 void Opts_SetDangerLevelSpeedup(float val)
554 {
555       if (val < 1)
556       {
557         val = 1;
558         fprintf(stderr,"Warning: danger_level_speedup must be at least 1, setting to 1.\n");
559       }
560   game_options->danger_level_speedup = val;
561 }
562 
563 
Opts_SetDangerLevelMax(float val)564 void Opts_SetDangerLevelMax(float val)
565 {
566   if (val < 0)
567   {
568     val = 0;
569     fprintf(stderr,"Warning: danger level max must be between 0 and 1, setting to 0.\n");
570   }
571   if (val > 1)
572   {
573     val = 1;
574     fprintf(stderr,"Warning: danger level max must be between 0 and 1, setting to 1.\n");
575   }
576   game_options->danger_level_max = val;
577 }
578 
579 
Opts_SetCityExplHandicap(float val)580 void Opts_SetCityExplHandicap(float val)
581 {
582   if (val < 0)
583   {
584     val = 0;
585     fprintf(stderr,"Warning: city_explode_handicap level set below minimum, setting to 0.\n");
586   }
587   game_options->city_expl_handicap = val;
588 }
589 
590 
591 
592 /* whether sound system is successfully initialized and sound files loaded: */
593 /* this flag is set by the program, not the user, and is not in the config file. */
Opts_SetSoundHWAvailable(int val)594 void Opts_SetSoundHWAvailable(int val)
595 {
596   game_options->sound_hw_available = int_to_bool(val);
597 }
598 
599 /* Allows game() to store score for high score table code: */
Opts_SetLastScore(int val)600 void Opts_SetLastScore(int val)
601 {
602   game_options->last_score = val;
603 }
604 
Opts_SetKeepScore(int val)605 void Opts_SetKeepScore(int val)
606 {
607   game_options->keep_score = val;
608 }
609 
610 
611 /* "Get" functions for tuxmath options struct: */
612 //int Opts_PerUserConfig(void)
613 //{
614 //  if (!game_options)
615 //  {
616 //    fprintf(stderr, "\nOpts_PerUserConfig(): game_options not valid!\n");
617 //    return GAME_OPTS_INVALID;
618 //  }
619 //  return global_options->iopts[PER_USER_CONFIG];
620 //}
621 //
622 //
623 //int Opts_UseSound(void)
624 //{
625 //  if (!game_options)
626 //  {
627 //    fprintf(stderr, "\nOpts_UseSound(): game_options not valid!\n");
628 //    return GAME_OPTS_INVALID;
629 //  }
630 //  return global_options->iopts[USE_SOUND] > 0;
631 //}
632 //
633 //
634 //int Opts_MenuSound(void)
635 //{
636 //  if (!game_options)
637 //  {
638 //    fprintf(stderr, "\nOpts_MenuSound(): game_options not valid!\n");
639 //    return GAME_OPTS_INVALID;
640 //  }
641 //  return global_options->iopts[MENU_SOUND];
642 //}
643 //
644 //
645 //int Opts_MenuMusic(void)
646 //{
647 //  if (!game_options)
648 //  {
649 //    fprintf(stderr, "\nOpts_MenuMusic(): game_options not valid!\n");
650 //    return GAME_OPTS_INVALID;
651 //  }
652 //  return global_options->iopts[MENU_MUSIC];
653 //}
654 //
655 //
656 //int Opts_Fullscreen(void)
657 //{
658 //  if (!game_options)
659 //  {
660 //    fprintf(stderr, "\nOpts_Fullscreen(): game_options not valid!\n");
661 //    return GAME_OPTS_INVALID;
662 //  }
663 //  return global_options->iopts[FULLSCREEN];
664 //}
665 
666 
Opts_LanMode(void)667 int Opts_LanMode(void)
668 {
669   if (!game_options)
670   {
671     fprintf(stderr, "\nOpts_LanMode(): game_options not valid!\n");
672     return GAME_OPTS_INVALID;
673   }
674   return game_options->lan_mode;
675 }
676 
677 
Opts_LessonTitle(void)678 const char* Opts_LessonTitle(void)
679 {
680   if (!game_options)
681   {
682     fprintf(stderr, "\nOpts_LessonTitle(): game_options not valid!\n");
683     return NULL;
684   }
685   return (const char*) game_options->lesson_title;
686 }
687 
688 
Opts_FontName(void)689 const char* Opts_FontName(void)
690 {
691   if (!game_options)
692   {
693     fprintf(stderr, "\nOpts_FontName(): game_options not valid!\n");
694     return NULL;
695   }
696   return (const char*) game_options->current_font_name;
697 }
698 
Opts_UseBkgd(void)699 int Opts_UseBkgd(void)
700 {
701   if (!game_options)
702   {
703     fprintf(stderr, "\nOpts_UserBkgd(): game_options not valid!\n");
704     return GAME_OPTS_INVALID;
705   }
706   return game_options->use_bkgd;
707 }
708 
709 
Opts_HelpMode(void)710 int Opts_HelpMode(void)
711 {
712   if (!game_options)
713   {
714     fprintf(stderr, "\nOpts_HelpMode(): game_options not valid!\n");
715     return GAME_OPTS_INVALID;
716   }
717   return game_options->help_mode;
718 }
719 
720 
Opts_DemoMode(void)721 int Opts_DemoMode(void)
722 {
723   if (!game_options)
724   {
725     fprintf(stderr, "\nOpts_DemoMode(): game_options not valid!\n");
726     return GAME_OPTS_INVALID;
727   }
728   return game_options->demo_mode;
729 }
730 
731 
Opts_OperOverride(void)732 int Opts_OperOverride(void)
733 {
734   if (!game_options)
735   {
736     fprintf(stderr, "\nOpts_OperOverride(): game_options not valid!\n");
737     return GAME_OPTS_INVALID;
738   }
739   return game_options->oper_override;
740 }
741 
742 
743 //int Opts_UseKeypad(void)
744 //{
745 //  if (!game_options)
746 //  {
747 //    fprintf(stderr, "\nOpts_UseKeypad(): game_options not valid!\n");
748 //    return GAME_OPTS_INVALID;
749 //  }
750 //  return global_options->iopts[USE_KEYPAD];
751 //}
752 //
753 //
Opts_AllowPause(void)754 int Opts_AllowPause(void)
755 {
756   if (!game_options)
757   {
758     fprintf(stderr, "\nOpts_AllowPause(): game_options not valid!\n");
759     return GAME_OPTS_INVALID;
760   }
761   return game_options->allow_pause;
762 }
763 
764 
765 //int Opts_UseIgloos(void)
766 //{
767 //  if (!game_options)
768 //  {
769 //    fprintf(stderr, "\nOpts_UseIgloos(): game_options not valid!\n");
770 //    return GAME_OPTS_INVALID;
771 //  }
772 //  return global_options->iopts[USE_IGLOOS];
773 //}
774 
Opts_BonusCometInterval(void)775 int Opts_BonusCometInterval(void)
776 {
777   if (!game_options)
778   {
779     fprintf(stderr, "\nOpts_BonusCometInterval(): game_options not valid!\n");
780     return GAME_OPTS_INVALID;
781   }
782   return game_options->bonus_comet_interval;
783 }
784 
785 
Opts_BonusSpeedRatio(void)786 float Opts_BonusSpeedRatio(void)
787 {
788   if (!game_options)
789   {
790     fprintf(stderr, "\nOpts_BonusSpeedRatio(): game_options not valid!\n");
791     return GAME_OPTS_INVALID;
792   }
793   return game_options->bonus_speed_ratio;
794 }
795 
796 
Opts_Speed(void)797 float Opts_Speed(void)
798 {
799   if (!game_options)
800   {
801     fprintf(stderr, "\nOpts_Speed(): game_options not valid!\n");
802     return GAME_OPTS_INVALID;
803   }
804   return game_options->speed;
805 }
806 
807 
Opts_AllowSpeedup(void)808 int Opts_AllowSpeedup(void)
809 {
810   if (!game_options)
811   {
812     fprintf(stderr, "\nOpts_AllowSpeedup(): game_options not valid!\n");
813     return GAME_OPTS_INVALID;
814   }
815   return game_options->allow_speedup;
816 }
817 
818 
Opts_SpeedupFactor(void)819 float Opts_SpeedupFactor(void)
820 {
821   if (!game_options)
822   {
823     fprintf(stderr, "\nOpts_SpeedupFactor(): game_options not valid!\n");
824     return GAME_OPTS_INVALID;
825   }
826   return game_options->speedup_factor;
827 }
828 
829 
Opts_MaxSpeed(void)830 float Opts_MaxSpeed(void)
831 {
832   if (!game_options)
833   {
834     fprintf(stderr, "\nOpts_MaxSpeed(): game_options not valid!\n");
835     return GAME_OPTS_INVALID;
836   }
837   return game_options->max_speed;
838 }
839 
840 
Opts_SlowAfterWrong(void)841 int Opts_SlowAfterWrong(void)
842 {
843   if (!game_options)
844   {
845     fprintf(stderr, "\nOpts_SlowAfterWrong(): game_options not valid!\n");
846     return GAME_OPTS_INVALID;
847   }
848   return game_options->slow_after_wrong;
849 }
850 
851 
Opts_StartingComets(void)852 int Opts_StartingComets(void)
853 {
854   if (!game_options)
855   {
856     fprintf(stderr, "\nOpts_StartingComets(): game_options not valid!\n");
857     return GAME_OPTS_INVALID;
858   }
859   return game_options->starting_comets;
860 }
861 
862 
Opts_ExtraCometsPerWave(void)863 int Opts_ExtraCometsPerWave(void)
864 {
865   if (!game_options)
866   {
867     fprintf(stderr, "\nOpts_ExtraCometsPerWave(): game_options not valid!\n");
868     return GAME_OPTS_INVALID;
869   }
870   return game_options->extra_comets_per_wave;
871 }
872 
873 
Opts_MaxComets(void)874 int Opts_MaxComets(void)
875 {
876   if (!game_options)
877   {
878     fprintf(stderr, "\nOpts_MaxComets(): game_options not valid!\n");
879     return GAME_OPTS_INVALID;
880   }
881   return game_options->max_comets;
882 }
883 
Opts_UsePowerupComets(void)884 int Opts_UsePowerupComets(void)
885 {
886     if (!game_options)
887     {
888 	fprintf(stderr, "\nOpts_UsePowerupComets(): game_options not valid!\n");
889 	return GAME_OPTS_INVALID;
890     }
891     return game_options->use_powerup_comets;
892 }
893 
Opts_PowerupFreq(void)894 int Opts_PowerupFreq(void)
895 {
896     if (!game_options)
897     {
898 	fprintf(stderr, "\nOpts_PowerupFreq(): game_options not valid!\n");
899 	return GAME_OPTS_INVALID;
900     }
901     return game_options->powerup_freq;
902 }
903 
Opts_NextMission(void)904 const char* Opts_NextMission(void)
905 {
906     if (!game_options)
907     {
908 	fprintf(stderr, "\nOpts_NextMission(): game_options not valid!\n");
909 	return NULL;
910     }
911     return (const char*) game_options->next_mission;
912 }
913 
914 
Opts_SaveSummary(void)915 int Opts_SaveSummary(void)
916 {
917     if (!game_options)
918     {
919 	fprintf(stderr, "\nOpts_SaveSummary(): game_options not valid!\n");
920 	return GAME_OPTS_INVALID;
921     }
922     return game_options->save_summary;
923 }
924 
925 
Opts_LastScore(void)926 int Opts_LastScore(void)
927 {
928     if (!game_options)
929     {
930 	fprintf(stderr, "\nOpts_LastScore(): game_options not valid!\n");
931 	return GAME_OPTS_INVALID;
932     }
933     return game_options->last_score;
934 }
935 
936 
Opts_UseFeedback(void)937 int Opts_UseFeedback(void)
938 {
939     if (!game_options)
940     {
941 	fprintf(stderr, "\nOpts_UseFeedback(): game_options not valid!\n");
942 	return GAME_OPTS_INVALID;
943     }
944     return game_options->use_feedback;
945 }
946 
947 
Opts_DangerLevel(void)948 float Opts_DangerLevel(void)
949 {
950     if (!game_options)
951     {
952 	fprintf(stderr, "\nOpts_DangerLevel(): game_options not valid!\n");
953 	return GAME_OPTS_INVALID;
954     }
955     return game_options->danger_level;
956 }
957 
958 
Opts_DangerLevelSpeedup(void)959 float Opts_DangerLevelSpeedup(void)
960 {
961     if (!game_options)
962     {
963 	fprintf(stderr, "\nOpts_DangerLevelSpeedup(): game_options not valid!\n");
964 	return GAME_OPTS_INVALID;
965     }
966     return game_options->danger_level_speedup;
967 }
968 
969 
Opts_DangerLevelMax(void)970 float Opts_DangerLevelMax(void)
971 {
972     if (!game_options)
973     {
974 	fprintf(stderr, "\nOpts_DangerLevelMax(): game_options not valid!\n");
975 	return GAME_OPTS_INVALID;
976     }
977     return game_options->danger_level_max;
978 }
979 
980 
Opts_CityExplHandicap(void)981 float Opts_CityExplHandicap(void)
982 {
983     if (!game_options)
984     {
985 	fprintf(stderr, "\nOpts_CityExplHandicap(): game_options not valid!\n");
986 	return GAME_OPTS_INVALID;
987     }
988     return game_options->city_expl_handicap;
989 }
990 
991 
992 
993 /* whether sound system is successfully initialized and sound files loaded: */
994 /* this flag is set by the program, not the user, and is not in the config file. */
Opts_SoundHWAvailable(void)995 int Opts_SoundHWAvailable(void)
996 {
997     if (!game_options)
998     {
999 	fprintf(stderr, "\nOpts_SoundHWAvailable(): game_options not valid!\n");
1000 	return GAME_OPTS_INVALID;
1001     }
1002     return game_options->sound_hw_available;
1003 }
1004 
1005 
1006 /* Returns true if only if the player wants to use sound */
1007 /* and the sound system is actually available:           */
Opts_UsingSound(void)1008 int Opts_UsingSound(void)
1009 {
1010     if (!game_options)
1011     {
1012 	fprintf(stderr, "\nOpts_UsingSound(): game_options not valid!\n");
1013 	return GAME_OPTS_INVALID;
1014     }
1015     return (global_options->iopts[USE_SOUND]>0 && game_options->sound_hw_available);
1016 }
1017 
Opts_KeepScore(void)1018 int Opts_KeepScore(void)
1019 {
1020     if (!game_options)
1021     {
1022 	fprintf(stderr, "\nOpts_KeepScore(): game_options not valid!\n");
1023 	return GAME_OPTS_INVALID;
1024     }
1025     return game_options->keep_score;
1026 }
1027 /********************************************************************/
1028 /*  "private methods" (static functions only visible in options.c)  */
1029 /********************************************************************/
1030 
1031 
1032 
1033 
1034 
1035 /* to prevent option settings in math_opts from getting set to */
1036 /* values other than 0 or 1                                    */
int_to_bool(int i)1037 int int_to_bool(int i)
1038 {
1039     if (i)
1040 	return 1;
1041     else
1042 	return 0;
1043 }
1044 
1045 ///* determine which option class a name belongs to, and set it */
1046 ///* accordingly. Returns 1 on success, 0 on failure            */
1047 //static int find_and_set_option(const char* name, int val)
1048 //{
1049 //  int index = -1;
1050 //
1051 //  if ((index = MC_MapTextToIndex(name)) != -1) //is it a math opt?
1052 //    MC_SetOpt(index, val);
1053 //  else if ((index = Opts_MapTextToIndex(name)) != -1) //is it a global opt?
1054 //    Opts_SetGlobalOpt(index, val);
1055 //  else //no? oh well.
1056 //    return 0;
1057 //
1058 //  return 1;
1059 //}
1060 
1061 /* prints struct to stream: */
print_game_options(FILE * fp,int verbose)1062 void print_game_options(FILE* fp, int verbose)
1063 {
1064     /* bail out if no struct */
1065     if (!game_options)
1066     {
1067 	fprintf(stderr, "print_game_options(): invalid game_option_type struct");
1068 	return;
1069     }
1070 
1071     if(verbose)
1072     {
1073 	fprintf (fp, "\n############################################################\n"
1074 		"#                                                          #\n"
1075 		"#                 General Game Options                     #\n"
1076 		"#                                                          #\n"
1077 		"# The following options are boolean (true/false) variables #\n"
1078 		"# that control various aspects of Tuxmath's behavior.      #\n"
1079 		"# The program writes the values to the file as either '0'  #\n"
1080 		"# or '1'. However, the program accepts 'n', 'no', 'f', and #\n"
1081 		"# 'false' as synonyms for '0', and similarly accepts 'y',  #\n"
1082 		"# 'yes', 't', and 'true' as synonyms for '1' (all case-    #\n"
1083 		"# insensitive).                                            #\n"
1084 		"############################################################\n\n");
1085     }
1086 
1087     if(verbose)
1088     {
1089 	fprintf (fp, "############################################################\n"
1090 		"# 'PER_USER_CONFIG' determines whether Tuxmath will look   #\n"
1091 		"# in the user's home directory for settings. Default is 1  #\n"
1092 		"# (yes). If deselected, the program will ignore the user's #\n"
1093 		"# .tuxmath file and use the the global settings in the     #\n"
1094 		"# installation-wide config file.                           #\n"
1095 		"# This setting cannot be changed by an ordinary user.      #\n"
1096 		"############################################################\n");
1097     }
1098     fprintf(fp, "PER_USER_CONFIG = %d\n", global_options->iopts[PER_USER_CONFIG]);
1099 
1100     if(verbose)
1101     {
1102 	fprintf (fp, "\n# Self-explanatory, default is 1:\n");
1103     }
1104     fprintf(fp, "USE_SOUND = %d\n", global_options->iopts[USE_SOUND]>0);
1105 
1106     if(verbose)
1107     {
1108 	fprintf (fp, "\n# Use FULLSCREEN at 640x480 resolution instead of\n"
1109 		"640x480 window. Default is 1 (FULLSCREEN). Change to 0\n"
1110 		"if SDL has trouble with FULLSCREEN on your system.\n");
1111     }
1112     fprintf(fp, "FULLSCREEN = %d\n", global_options->iopts[FULLSCREEN]);
1113 
1114     if(verbose)
1115     {
1116 	fprintf (fp, "\n# Use 640x480 jpg image for background; default is 1.\n");
1117     }
1118     fprintf(fp, "use_bkgd = %d\n", game_options->use_bkgd);
1119 
1120     if(verbose)
1121     {
1122 	fprintf (fp, "\n# Program runs as demo; default is 0.\n");
1123     }
1124     fprintf(fp, "demo_mode = %d\n", game_options->demo_mode);
1125 
1126     if(verbose)
1127     {
1128 	fprintf (fp, "\n# Use operator selection from command line; default is 0.\n");
1129     }
1130     fprintf(fp, "oper_override = %d\n", game_options->oper_override);
1131 
1132     if(verbose)
1133     {
1134 	fprintf (fp, "\n# Display onscreen numeric keypad; default is 0.\n");
1135     }
1136     fprintf(fp, "USE_KEYPAD = %d\n", global_options->iopts[USE_KEYPAD]);
1137 
1138     if(verbose)
1139     {
1140 	fprintf (fp, "\n############################################################\n"
1141 		"# The next settings determine the speed and number         #\n"
1142 		"# of comets.  The speed settings are float numbers (mean-  #\n"
1143 		"# ing decimals allowed). The comet settings are integers.  #\n"
1144 		"#                                                          #\n"
1145 		"# Starting comet speed and max comet speed are generally   #\n"
1146 		"# applicable. The main choice is whether you want to use   #\n"
1147 		"# feedback, i.e., to adjust the speed automatically based  #\n"
1148 		"# on the player's performance.                             #\n"
1149 		"#                                                          #\n"
1150 		"# Without feedback, the speed increases by a user-         #\n"
1151 		"# settable factor ('speedup_factor'), with an option       #\n"
1152 		"# ('slow_after_wrong') to go back to the starting speed    #\n"
1153 		"# when a city gets hit.                                    #\n"
1154 		"#                                                          #\n"
1155 		"# With feedback, you set a desired 'danger level,' which   #\n"
1156 		"# determines how close the comets should typically         #\n"
1157 		"# approach the cities before the player succeeds in        #\n"
1158 		"# destroying them.  The game will adjust its speed         #\n"
1159 		"# accordingly, getting faster when the player is easily    #\n"
1160 		"# stopping the comets, and slowing down when there are     #\n"
1161 		"# too many close calls or hits. You can also have the      #\n"
1162 		"# danger level increase with each wave.                    #\n"
1163 		"############################################################\n");
1164     }
1165 
1166     if(verbose)
1167     {
1168 	fprintf (fp, "\n# Whether to increase speed and number of comets with \n"
1169 		"# each wave.  May want to turn this off for smaller kids.\n"
1170 		"# Default is 1 (allow game to speed up)\n");
1171     }
1172     fprintf(fp, "allow_speedup = %d\n", game_options->allow_speedup);
1173 
1174 
1175     fprintf(fp, "slow_after_wrong = %d\n", game_options->slow_after_wrong);
1176 
1177     if(verbose)
1178     {
1179 	fprintf (fp, "\n# Starting comet speed. Default is 1.\n");
1180     }
1181     fprintf(fp, "speed = %f\n", game_options->speed);
1182 
1183     if(verbose)
1184     {
1185 	fprintf (fp, "\n# If feedback is not used but 'allow_speedup' is\n"
1186 		"# enabled, the comet speed will be\n"
1187 		"# multiplied by this factor with each new wave.\n"
1188 		"# Default is 1.2 (i.e. 20 percent increase per wave)\n");
1189     }
1190     fprintf(fp, "speedup_factor = %f\n", game_options->speedup_factor);
1191 
1192     if(verbose)
1193     {
1194 	fprintf (fp, "\n# Maximum speed. Default is 10.\n");
1195     }
1196     fprintf(fp, "max_speed = %f\n", game_options->max_speed);
1197 
1198     if(verbose)
1199     {
1200 	fprintf (fp, "\n# Number of comets for first wave. Default is 2.\n");
1201     }
1202     fprintf(fp, "starting_comets = %d\n", game_options->starting_comets);
1203 
1204     if(verbose)
1205     {
1206 	fprintf (fp, "\n# Comets to add for each successive wave. Default is 2.\n");
1207     }
1208     fprintf(fp, "extra_comets_per_wave = %d\n", game_options->extra_comets_per_wave);
1209 
1210     if(verbose)
1211     {
1212 	fprintf (fp, "\n# Maximum number of comets. Default is 10.\n");
1213     }
1214     fprintf(fp, "max_comets = %d\n", game_options->max_comets);
1215 
1216     if(verbose)
1217     {
1218 	fprintf (fp, "\n# Use feedback? Default (for now) is false, 0.\n");
1219     }
1220     fprintf(fp, "use_feedback = %d\n", game_options->use_feedback);
1221 
1222 
1223     if(verbose)
1224     {
1225 	fprintf (fp, "\n# (Feedback) Set the desired danger level.\n"
1226 		"# 0 = too safe, comets typically exploded right at the very top\n"
1227 		"# 1 = too dangerous, comets typically exploded at the moment they hit cities\n"
1228 		"# Set it somewhere between these extremes. As a guideline, early\n"
1229 		"# elementary kids might feel comfortable around 0.2-0.3, older kids\n"
1230 		"# at around 0.4-0.6. Default 0.35.\n");
1231     }
1232     fprintf(fp, "danger_level = %f\n", game_options->danger_level);
1233 
1234     if(verbose)
1235     {
1236 	fprintf (fp, "\n# (Feedback) Set danger level speedup.\n"
1237 		"# The margin of safety will decrease by this factor each wave.\n"
1238 		"# Default 1.1. Note 1 = no increase in danger level.\n");
1239     }
1240     fprintf(fp, "danger_level_speedup = %f\n", game_options->danger_level_speedup);
1241 
1242     if(verbose)
1243     {
1244 	fprintf (fp, "\n# (Feedback) Set the maximum danger level.\n"
1245 		"# Default 0.9.\n");
1246     }
1247     fprintf(fp, "danger_level_max = %f\n", game_options->danger_level_max);
1248 
1249     if (verbose)
1250     {
1251 	fprintf (fp, "\n# (Feedback) Set the handicap for hitting cities.\n"
1252 		"# When bigger than 0, this causes the game to slow down\n"
1253 		"# by an extra amount after a wave in which one or more\n"
1254 		"# cities get hit. Note that this is similar to slow_after_wrong,\n"
1255 		"# but allows for more gradual changes.\n"
1256 		"# Default 0 (no extra handicap).\n");
1257     }
1258     fprintf(fp, "city_explode_handicap = %f\n", game_options->city_expl_handicap);
1259 
1260     /*
1261        fprintf(fp, "num_cities = %d\n", game_options->num_cities);
1262        fprintf(fp, "num_bkgds = %d\n", game_options->num_bkgds);
1263        fprintf(fp, "max_city_colors = %d\n", game_options->max_city_colors);
1264        */
1265 }
1266