[Tux4kids-commits] r589 - in tuxmath/trunk: . data/missions data/missions/arcade data/missions/campaign data/missions/campaign/ace data/missions/campaign/cadet data/missions/campaign/commando data/missions/campaign/ranger data/missions/campaign/scout data/missions/lessons mingw src
cheezmeister-guest at alioth.debian.org
cheezmeister-guest at alioth.debian.org
Wed Aug 6 02:55:08 UTC 2008
Author: cheezmeister-guest
Date: 2008-08-06 02:55:05 +0000 (Wed, 06 Aug 2008)
New Revision: 589
Added:
tuxmath/trunk/data/missions/arcade/commando
tuxmath/trunk/data/missions/campaign/Makefile.am
tuxmath/trunk/data/missions/campaign/ace/Makefile.am
tuxmath/trunk/data/missions/campaign/cadet/Makefile.am
tuxmath/trunk/data/missions/campaign/commando/Makefile.am
tuxmath/trunk/data/missions/campaign/ranger/Makefile.am
tuxmath/trunk/data/missions/campaign/scout/Makefile.am
Modified:
tuxmath/trunk/configure
tuxmath/trunk/configure.ac
tuxmath/trunk/data/missions/Makefile.am
tuxmath/trunk/data/missions/arcade/Makefile.am
tuxmath/trunk/data/missions/arcade/ace
tuxmath/trunk/data/missions/arcade/ranger
tuxmath/trunk/data/missions/arcade/scout
tuxmath/trunk/data/missions/arcade/space_cadet
tuxmath/trunk/data/missions/lessons/Makefile.am
tuxmath/trunk/data/missions/lessons/lesson00
tuxmath/trunk/data/missions/lessons/lesson01
tuxmath/trunk/data/missions/lessons/lesson02
tuxmath/trunk/data/missions/lessons/lesson03
tuxmath/trunk/data/missions/lessons/lesson04
tuxmath/trunk/data/missions/lessons/lesson05
tuxmath/trunk/data/missions/lessons/lesson06
tuxmath/trunk/data/missions/lessons/lesson07
tuxmath/trunk/data/missions/lessons/lesson08
tuxmath/trunk/data/missions/lessons/lesson08.1
tuxmath/trunk/data/missions/lessons/lesson09
tuxmath/trunk/data/missions/lessons/lesson10
tuxmath/trunk/data/missions/lessons/lesson11
tuxmath/trunk/data/missions/lessons/lesson12
tuxmath/trunk/data/missions/lessons/lesson13
tuxmath/trunk/data/missions/lessons/lesson14
tuxmath/trunk/data/missions/lessons/lesson15
tuxmath/trunk/data/missions/lessons/lesson16
tuxmath/trunk/data/missions/lessons/lesson17
tuxmath/trunk/data/missions/lessons/lesson18
tuxmath/trunk/data/missions/lessons/lesson19
tuxmath/trunk/data/missions/lessons/lesson20
tuxmath/trunk/data/missions/lessons/lesson21
tuxmath/trunk/data/missions/lessons/lesson22
tuxmath/trunk/data/missions/lessons/lesson23
tuxmath/trunk/data/missions/lessons/lesson24
tuxmath/trunk/data/missions/lessons/lesson25
tuxmath/trunk/data/missions/lessons/lesson26
tuxmath/trunk/data/missions/lessons/lesson27
tuxmath/trunk/data/missions/lessons/lesson28
tuxmath/trunk/data/missions/lessons/lesson29
tuxmath/trunk/data/missions/lessons/lesson30
tuxmath/trunk/data/missions/lessons/lesson31
tuxmath/trunk/data/missions/lessons/lesson32
tuxmath/trunk/data/missions/lessons/lesson33
tuxmath/trunk/data/missions/lessons/lesson34
tuxmath/trunk/data/missions/lessons/lesson35
tuxmath/trunk/data/missions/lessons/lesson36
tuxmath/trunk/data/missions/lessons/lesson37
tuxmath/trunk/data/missions/lessons/lesson38
tuxmath/trunk/data/missions/lessons/lesson39
tuxmath/trunk/data/missions/lessons/lesson40
tuxmath/trunk/data/missions/lessons/lesson41
tuxmath/trunk/data/missions/lessons/lesson42
tuxmath/trunk/data/missions/lessons/lesson43
tuxmath/trunk/data/missions/lessons/lesson44
tuxmath/trunk/data/missions/lessons/lesson45
tuxmath/trunk/data/missions/lessons/lesson46
tuxmath/trunk/data/missions/lessons/lesson47
tuxmath/trunk/data/missions/lessons/lesson48
tuxmath/trunk/data/missions/lessons/lesson49
tuxmath/trunk/data/missions/lessons/lesson50
tuxmath/trunk/data/missions/lessons/lesson51
tuxmath/trunk/data/missions/lessons/lesson52
tuxmath/trunk/data/missions/lessons/lesson53
tuxmath/trunk/data/missions/lessons/lesson54
tuxmath/trunk/mingw/SDL_win32_main.c
tuxmath/trunk/src/ConvertUTF.c
tuxmath/trunk/src/ConvertUTF.h
tuxmath/trunk/src/Makefile.in
tuxmath/trunk/src/SDL_extras.c
tuxmath/trunk/src/audio.c
tuxmath/trunk/src/campaign.c
tuxmath/trunk/src/credits.c
tuxmath/trunk/src/fileops.c
tuxmath/trunk/src/fileops.h
tuxmath/trunk/src/game.c
tuxmath/trunk/src/gettext.h
tuxmath/trunk/src/highscore.c
tuxmath/trunk/src/loaders.c
tuxmath/trunk/src/mathcards.c
tuxmath/trunk/src/mathcards.h
tuxmath/trunk/src/options.c
tuxmath/trunk/src/pixels.c
tuxmath/trunk/src/scandir.c
tuxmath/trunk/src/setup.c
tuxmath/trunk/src/titlescreen.c
tuxmath/trunk/src/titlescreen.h
tuxmath/trunk/src/tuxmath.h
tuxmath/trunk/src/tuxmathadmin.c
tuxmath/trunk/src/tuxmathrc.rc
Log:
Merged mathcards branch back into trunk! As best I can tell, this
iteration is stable.
Modified: tuxmath/trunk/configure
===================================================================
--- tuxmath/trunk/configure 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/configure 2008-08-06 02:55:05 UTC (rev 589)
@@ -17132,7 +17132,7 @@
# Create Makefiles
# ---------------------------------------------------------------
-ac_config_files="$ac_config_files Makefile data/Makefile data/fonts/Makefile data/images/Makefile data/images/backgrounds/Makefile data/images/cities/Makefile data/images/comets/Makefile data/images/icons/Makefile data/images/igloos/Makefile data/images/penguins/Makefile data/images/sprites/Makefile data/images/status/Makefile data/images/title/Makefile data/images/tux/Makefile data/missions/Makefile data/missions/arcade/Makefile data/missions/lessons/Makefile data/sounds/Makefile doc/Makefile nsis/tuxmath.nsi nsis/tuxmath_with_conf.nsi src/Makefile intl/Makefile po/Makefile.in"
+ac_config_files="$ac_config_files Makefile data/Makefile data/fonts/Makefile data/images/Makefile data/images/backgrounds/Makefile data/images/cities/Makefile data/images/comets/Makefile data/images/icons/Makefile data/images/igloos/Makefile data/images/penguins/Makefile data/images/sprites/Makefile data/images/status/Makefile data/images/title/Makefile data/images/tux/Makefile data/missions/Makefile data/missions/arcade/Makefile data/missions/campaign/Makefile data/missions/campaign/ace/Makefile data/missions/campaign/cadet/Makefile data/missions/campaign/commando/Makefile data/missions/campaign/ranger/Makefile data/missions/campaign/scout/Makefile data/missions/lessons/Makefile data/sounds/Makefile doc/Makefile nsis/tuxmath.nsi nsis/tuxmath_with_conf.nsi src/Makefile intl/Makefile po/Makefile.in"
cat >confcache <<\_ACEOF
@@ -17759,6 +17759,12 @@
"data/images/tux/Makefile") CONFIG_FILES="$CONFIG_FILES data/images/tux/Makefile" ;;
"data/missions/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/Makefile" ;;
"data/missions/arcade/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/arcade/Makefile" ;;
+ "data/missions/campaign/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/campaign/Makefile" ;;
+ "data/missions/campaign/ace/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/campaign/ace/Makefile" ;;
+ "data/missions/campaign/cadet/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/campaign/cadet/Makefile" ;;
+ "data/missions/campaign/commando/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/campaign/commando/Makefile" ;;
+ "data/missions/campaign/ranger/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/campaign/ranger/Makefile" ;;
+ "data/missions/campaign/scout/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/campaign/scout/Makefile" ;;
"data/missions/lessons/Makefile") CONFIG_FILES="$CONFIG_FILES data/missions/lessons/Makefile" ;;
"data/sounds/Makefile") CONFIG_FILES="$CONFIG_FILES data/sounds/Makefile" ;;
"doc/Makefile") CONFIG_FILES="$CONFIG_FILES doc/Makefile" ;;
Modified: tuxmath/trunk/configure.ac
===================================================================
--- tuxmath/trunk/configure.ac 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/configure.ac 2008-08-06 02:55:05 UTC (rev 589)
@@ -219,6 +219,12 @@
data/images/tux/Makefile
data/missions/Makefile
data/missions/arcade/Makefile
+data/missions/campaign/Makefile
+data/missions/campaign/ace/Makefile
+data/missions/campaign/cadet/Makefile
+data/missions/campaign/commando/Makefile
+data/missions/campaign/ranger/Makefile
+data/missions/campaign/scout/Makefile
data/missions/lessons/Makefile
data/sounds/Makefile
doc/Makefile
Modified: tuxmath/trunk/data/missions/Makefile.am
===================================================================
--- tuxmath/trunk/data/missions/Makefile.am 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -1,7 +1,7 @@
## Makefile.am for tuxmath - data/missions:
## Process with Automake to create Makefile.in
-SUBDIRS = arcade lessons
+SUBDIRS = arcade campaign lessons
missionsdir = $(pkgdatadir)/missions
Modified: tuxmath/trunk/data/missions/arcade/Makefile.am
===================================================================
--- tuxmath/trunk/data/missions/arcade/Makefile.am 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/arcade/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -4,6 +4,7 @@
arcadedir = $(pkgdatadir)/missions/arcade
dist_arcade_DATA = ace \
+ commando \
ranger \
scout \
space_cadet
Modified: tuxmath/trunk/data/missions/arcade/ace
===================================================================
--- tuxmath/trunk/data/missions/arcade/ace 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/arcade/ace 2008-08-06 02:55:05 UTC (rev 589)
@@ -8,6 +8,8 @@
multiplication_allowed = 1
division_allowed = 1
allow_negatives = 1
+max_formula_nums = 2
+min_formula_nums = 2
min_augend = -20
max_augend = 20
min_addend = -20
Copied: tuxmath/trunk/data/missions/arcade/commando (from rev 584, tuxmath/branches/mathcards_newarch/data/missions/arcade/commando)
===================================================================
--- tuxmath/trunk/data/missions/arcade/commando (rev 0)
+++ tuxmath/trunk/data/missions/arcade/commando 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,61 @@
+# arcade commando lesson file
+
+play_through_list = 0
+allow_speedup = 1
+use_feedback = 0
+addition_allowed = 1
+subtraction_allowed = 1
+multiplication_allowed = 1
+division_allowed = 1
+allow_negatives = 1
+min_formula_nums = 3
+max_formula_nums = 4
+min_augend = -20
+max_augend = 20
+min_addend = -20
+max_addend = 20
+min_minuend = -20
+max_minuend = 20
+min_subtrahend = 0
+max_subtrahend = 20
+min_multiplier = -20
+max_multiplier = 20
+min_multiplicand = -20
+max_multiplicand = 20
+min_divisor = -20
+max_divisor = 20
+min_quotient = -20
+max_quotient = 20
+use_bkgd = 1
+demo_mode = 0
+save_summary = 1
+question_copies = 1
+repeat_wrongs = 1
+copies_repeated_wrongs = 1
+format_add_answer_last = 1
+format_add_answer_first = 1
+format_add_answer_middle = 1
+format_sub_answer_last = 1
+format_sub_answer_first = 1
+format_sub_answer_middle = 1
+format_mult_answer_last = 1
+format_mult_answer_first = 1
+format_mult_answer_middle = 1
+format_div_answer_last = 1
+format_div_answer_first = 1
+format_div_answer_middle = 1
+randomize = 1
+max_answer = 400
+starting_comets = 2
+extra_comets_per_wave = 2
+max_comets = 10
+speed = 0.25
+max_speed = 10.00
+speedup_factor = 1.125
+slow_after_wrong = 0
+max_questions = 25000
+bonus_comet_interval = 20
+fraction_to_keep = 1
+allow_pause = 0
+bonus_speed_ratio = 2.0
+
Modified: tuxmath/trunk/data/missions/arcade/ranger
===================================================================
--- tuxmath/trunk/data/missions/arcade/ranger 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/arcade/ranger 2008-08-06 02:55:05 UTC (rev 589)
@@ -8,6 +8,8 @@
multiplication_allowed = 1
division_allowed = 1
allow_negatives = 0
+max_formula_nums = 2
+min_formula_nums = 2
min_augend = 0
max_augend = 20
min_addend = 0
Modified: tuxmath/trunk/data/missions/arcade/scout
===================================================================
--- tuxmath/trunk/data/missions/arcade/scout 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/arcade/scout 2008-08-06 02:55:05 UTC (rev 589)
@@ -8,6 +8,8 @@
multiplication_allowed = 0
division_allowed = 0
allow_negatives = 0
+max_formula_nums = 2
+min_formula_nums = 2
min_augend = 0
max_augend = 10
min_addend = 0
Modified: tuxmath/trunk/data/missions/arcade/space_cadet
===================================================================
--- tuxmath/trunk/data/missions/arcade/space_cadet 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/arcade/space_cadet 2008-08-06 02:55:05 UTC (rev 589)
@@ -8,6 +8,8 @@
multiplication_allowed = 0
division_allowed = 0
allow_negatives = 0
+max_formula_nums = 2
+min_formula_nums = 2
min_augend = 0
max_augend = 10
min_addend = 0
Copied: tuxmath/trunk/data/missions/campaign/Makefile.am (from rev 588, tuxmath/branches/mathcards_newarch/data/missions/campaign/Makefile.am)
===================================================================
--- tuxmath/trunk/data/missions/campaign/Makefile.am (rev 0)
+++ tuxmath/trunk/data/missions/campaign/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,8 @@
+## Makefile.am for tuxmath - data/missions/campaign:
+## Process with Automake to create Makefile.in
+
+SUBDIRS = ace cadet commando ranger scout
+
+campaigndir = $(pkgdatadir)/missions/campaign
+
+dist_campaign_DATA = campaign
Copied: tuxmath/trunk/data/missions/campaign/ace/Makefile.am (from rev 588, tuxmath/branches/mathcards_newarch/data/missions/campaign/ace/Makefile.am)
===================================================================
--- tuxmath/trunk/data/missions/campaign/ace/Makefile.am (rev 0)
+++ tuxmath/trunk/data/missions/campaign/ace/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,10 @@
+## Makefile.am for tuxmath - data/missions/campaign/ace:
+## Process with Automake to create Makefile.in
+
+campaignacedir = $(pkgdatadir)/missions/campaign/ace
+
+dist_campaignace_DATA = ace \
+ bonus \
+ round1 \
+ round2 \
+ round3
Copied: tuxmath/trunk/data/missions/campaign/cadet/Makefile.am (from rev 588, tuxmath/branches/mathcards_newarch/data/missions/campaign/cadet/Makefile.am)
===================================================================
--- tuxmath/trunk/data/missions/campaign/cadet/Makefile.am (rev 0)
+++ tuxmath/trunk/data/missions/campaign/cadet/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,10 @@
+## Makefile.am for tuxmath - data/missions/campaign/ace:
+## Process with Automake to create Makefile.in
+
+campaigncadetdir = $(pkgdatadir)/missions/campaign/cadet
+
+dist_campaigncadet_DATA = cadet \
+ bonus \
+ round1 \
+ round2 \
+ round3
Copied: tuxmath/trunk/data/missions/campaign/commando/Makefile.am (from rev 588, tuxmath/branches/mathcards_newarch/data/missions/campaign/commando/Makefile.am)
===================================================================
--- tuxmath/trunk/data/missions/campaign/commando/Makefile.am (rev 0)
+++ tuxmath/trunk/data/missions/campaign/commando/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,9 @@
+## Makefile.am for tuxmath - data/missions/campaign/commando:
+## Process with Automake to create Makefile.in
+
+campaigncommandodir = $(pkgdatadir)/missions/campaign/commando
+
+dist_campaigncommando_DATA = commando \
+ round1 \
+ round2 \
+ round3
Copied: tuxmath/trunk/data/missions/campaign/ranger/Makefile.am (from rev 588, tuxmath/branches/mathcards_newarch/data/missions/campaign/ranger/Makefile.am)
===================================================================
--- tuxmath/trunk/data/missions/campaign/ranger/Makefile.am (rev 0)
+++ tuxmath/trunk/data/missions/campaign/ranger/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,10 @@
+## Makefile.am for tuxmath - data/missions/campaign/ranger:
+## Process with Automake to create Makefile.in
+
+campaignrangerdir = $(pkgdatadir)/missions/campaign/ranger
+
+dist_campaignranger_DATA = ranger \
+ bonus \
+ round1 \
+ round2 \
+ round3
Copied: tuxmath/trunk/data/missions/campaign/scout/Makefile.am (from rev 588, tuxmath/branches/mathcards_newarch/data/missions/campaign/scout/Makefile.am)
===================================================================
--- tuxmath/trunk/data/missions/campaign/scout/Makefile.am (rev 0)
+++ tuxmath/trunk/data/missions/campaign/scout/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -0,0 +1,10 @@
+## Makefile.am for tuxmath - data/missions/campaign/scout:
+## Process with Automake to create Makefile.in
+
+campaignscoutdir = $(pkgdatadir)/missions/campaign/scout
+
+dist_campaignscout_DATA = scout \
+ bonus \
+ round1 \
+ round2 \
+ round3
Modified: tuxmath/trunk/data/missions/lessons/Makefile.am
===================================================================
--- tuxmath/trunk/data/missions/lessons/Makefile.am 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/Makefile.am 2008-08-06 02:55:05 UTC (rev 589)
@@ -1,9 +1,6 @@
## Makefile.am for tuxmath - data/missions/lessons:
## Process with Automake to create Makefile.in
-
-
-
lessonsdir = $(pkgdatadir)/missions/lessons
dist_lessons_DATA = lesson00 \
Modified: tuxmath/trunk/data/missions/lessons/lesson00
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson00 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson00 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 400
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson01
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson01 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson01 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 400
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson02
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson02 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson02 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 400
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson03
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson03 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson03 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 10
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson04
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson04 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson04 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 15
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson05
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson05 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson05 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 20
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson06
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson06 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson06 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson07
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson07 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson07 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson08
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson08 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson08 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson08.1
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson08.1 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson08.1 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson09
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson09 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson09 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson10
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson10 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson10 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson11
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson11 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson11 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson12
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson12 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson12 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson13
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson13 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson13 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson14
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson14 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson14 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson15
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson15 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson15 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson16
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson16 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson16 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson17
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson17 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson17 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson18
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson18 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson18 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson19
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson19 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson19 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson20
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson20 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson20 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson21
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson21 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson21 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson22
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson22 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson22 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson23
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson23 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson23 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson24
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson24 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson24 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson25
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson25 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson25 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson26
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson26 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson26 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson27
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson27 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson27 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson28
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson28 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson28 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson29
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson29 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson29 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson30
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson30 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson30 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson31
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson31 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson31 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson32
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson32 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson32 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson33
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson33 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson33 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson34
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson34 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson34 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson35
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson35 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson35 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson36
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson36 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson36 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson37
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson37 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson37 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson38
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson38 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson38 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson39
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson39 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson39 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson40
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson40 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson40 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson41
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson41 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson41 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson42
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson42 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson42 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson43
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson43 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson43 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson44
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson44 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson44 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson45
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson45 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson45 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 400
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson46
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson46 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson46 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson47
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson47 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson47 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson48
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson48 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson48 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson49
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson49 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson49 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson50
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson50 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson50 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson51
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson51 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson51 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson52
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson52 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson52 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson53
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson53 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson53 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Modified: tuxmath/trunk/data/missions/lessons/lesson54
===================================================================
--- tuxmath/trunk/data/missions/lessons/lesson54 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/data/missions/lessons/lesson54 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,6 +45,8 @@
max_answer = 999
max_questions = 5000
randomize = 1
+comprehensive = 1
+avg_list_length = 42
starting_comets = 2
extra_comets_per_wave = 2
max_comets = 10
Property changes on: tuxmath/trunk/mingw/SDL_win32_main.c
___________________________________________________________________
Name: svn:executable
+ *
Modified: tuxmath/trunk/src/ConvertUTF.c
===================================================================
--- tuxmath/trunk/src/ConvertUTF.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/ConvertUTF.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -26,10 +26,10 @@
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
Sept 2001: fixed const & error conditions per
- mods suggested by S. Parent & A. Lillich.
+ mods suggested by S. Parent & A. Lillich.
June 2002: Tim Dodd added detection and handling of incomplete
- source sequences, enhanced error detection, added casts
- to eliminate compiler warnings.
+ source sequences, enhanced error detection, added casts
+ to eliminate compiler warnings.
July 2003: slight mods to back out aggressive FFFE detection.
Jan 2004: updated switches in from-UTF8 conversions.
Oct 2004: updated to use UNI_MAX_LEGAL_UTF32 in UTF-32 conversions.
@@ -53,52 +53,52 @@
#define UNI_SUR_HIGH_END (UTF32)0xDBFF
#define UNI_SUR_LOW_START (UTF32)0xDC00
#define UNI_SUR_LOW_END (UTF32)0xDFFF
-#define false 0
-#define true 1
+#define false 0
+#define true 1
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF16 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch;
- if (target >= targetEnd) {
- result = targetExhausted; break;
- }
- ch = *source++;
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_LEGAL_UTF32) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- --source; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
+ UTF32 ch;
+ if (target >= targetEnd) {
+ result = targetExhausted; break;
+ }
+ ch = *source++;
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32; 0xffff or 0xfffe are both reserved values */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_LEGAL_UTF32) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ --source; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
}
*sourceStart = source;
*targetStart = target;
@@ -108,48 +108,48 @@
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF32 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF32* target = *targetStart;
UTF32 ch, ch2;
while (source < sourceEnd) {
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- if (target >= targetEnd) {
- source = oldSource; /* Back up source pointer! */
- result = targetExhausted; break;
- }
- *target++ = ch;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ if (target >= targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ *target++ = ch;
}
*sourceStart = source;
*targetStart = target;
@@ -188,7 +188,7 @@
* in a UTF-8 sequence.
*/
static const UTF32 offsetsFromUTF8[6] = { 0x00000000UL, 0x00003080UL, 0x000E2080UL,
- 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
+ 0x03C82080UL, 0xFA082080UL, 0x82082080UL };
/*
* Once the bits are split out into bytes of UTF-8, this is a mask OR-ed
@@ -212,67 +212,67 @@
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF16toUTF8 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF16* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
- ch = *source++;
- /* If we have a surrogate pair, convert to UTF32 first. */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
- /* If the 16 bits following the high surrogate are in the source buffer... */
- if (source < sourceEnd) {
- UTF32 ch2 = *source;
- /* If it's a low surrogate, convert to UTF32. */
- if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
- ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
- + (ch2 - UNI_SUR_LOW_START) + halfBase;
- ++source;
- } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- } else { /* We don't have the 16 bits following the high surrogate. */
- --source; /* return to the high surrogate */
- result = sourceExhausted;
- break;
- }
- } else if (flags == strictConversion) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /* Figure out how many bytes the result will require */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- }
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ const UTF16* oldSource = source; /* In case we have to back up because of target overflow. */
+ ch = *source++;
+ /* If we have a surrogate pair, convert to UTF32 first. */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_HIGH_END) {
+ /* If the 16 bits following the high surrogate are in the source buffer... */
+ if (source < sourceEnd) {
+ UTF32 ch2 = *source;
+ /* If it's a low surrogate, convert to UTF32. */
+ if (ch2 >= UNI_SUR_LOW_START && ch2 <= UNI_SUR_LOW_END) {
+ ch = ((ch - UNI_SUR_HIGH_START) << halfShift)
+ + (ch2 - UNI_SUR_LOW_START) + halfBase;
+ ++source;
+ } else if (flags == strictConversion) { /* it's an unpaired high surrogate */
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ } else { /* We don't have the 16 bits following the high surrogate. */
+ --source; /* return to the high surrogate */
+ result = sourceExhausted;
+ break;
+ }
+ } else if (flags == strictConversion) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_LOW_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /* Figure out how many bytes the result will require */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch < (UTF32)0x110000) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ }
- target += bytesToWrite;
- if (target > targetEnd) {
- source = oldSource; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ source = oldSource; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8)(ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
@@ -297,19 +297,19 @@
const UTF8 *srcptr = source+length;
switch (length) {
default: return false;
- /* Everything else falls through when "true"... */
+ /* Everything else falls through when "true"... */
case 4: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 3: if ((a = (*--srcptr)) < 0x80 || a > 0xBF) return false;
case 2: if ((a = (*--srcptr)) > 0xBF) return false;
- switch (*source) {
- /* no fall-through in this inner switch */
- case 0xE0: if (a < 0xA0) return false; break;
- case 0xED: if (a > 0x9F) return false; break;
- case 0xF0: if (a < 0x90) return false; break;
- case 0xF4: if (a > 0x8F) return false; break;
- default: if (a < 0x80) return false;
- }
+ switch (*source) {
+ /* no fall-through in this inner switch */
+ case 0xE0: if (a < 0xA0) return false; break;
+ case 0xED: if (a > 0x9F) return false; break;
+ case 0xF0: if (a < 0x90) return false; break;
+ case 0xF4: if (a > 0x8F) return false; break;
+ default: if (a < 0x80) return false;
+ }
case 1: if (*source >= 0x80 && *source < 0xC2) return false;
}
@@ -326,7 +326,7 @@
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd) {
int length = trailingBytesForUTF8[*source]+1;
if (source+length > sourceEnd) {
- return false;
+ return false;
}
return isLegalUTF8(source, length);
}
@@ -334,70 +334,70 @@
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF16 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF16* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (! isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (! isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 4: ch += *source++; ch <<= 6; /* remember, illegal UTF-8 */
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = (UTF16)ch; /* normal case */
- }
- } else if (ch > UNI_MAX_UTF16) {
- if (flags == strictConversion) {
- result = sourceIllegal;
- source -= (extraBytesToRead+1); /* return to the start */
- break; /* Bail out; shouldn't continue */
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- /* target is a character in range 0xFFFF - 0x10FFFF. */
- if (target + 1 >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up source pointer! */
- result = targetExhausted; break;
- }
- ch -= halfBase;
- *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
- *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
- }
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_BMP) { /* Target is a character <= 0xFFFF */
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = (UTF16)ch; /* normal case */
+ }
+ } else if (ch > UNI_MAX_UTF16) {
+ if (flags == strictConversion) {
+ result = sourceIllegal;
+ source -= (extraBytesToRead+1); /* return to the start */
+ break; /* Bail out; shouldn't continue */
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ /* target is a character in range 0xFFFF - 0x10FFFF. */
+ if (target + 1 >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up source pointer! */
+ result = targetExhausted; break;
+ }
+ ch -= halfBase;
+ *target++ = (UTF16)((ch >> halfShift) + UNI_SUR_HIGH_START);
+ *target++ = (UTF16)((ch & halfMask) + UNI_SUR_LOW_START);
+ }
}
*sourceStart = source;
*targetStart = target;
@@ -407,50 +407,50 @@
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF32toUTF8 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF32* source = *sourceStart;
UTF8* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch;
- unsigned short bytesToWrite = 0;
- const UTF32 byteMask = 0xBF;
- const UTF32 byteMark = 0x80;
- ch = *source++;
- if (flags == strictConversion ) {
- /* UTF-16 surrogate values are illegal in UTF-32 */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- --source; /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- }
- }
- /*
- * Figure out how many bytes the result will require. Turn any
- * illegally large UTF32 things (> Plane 17) into replacement chars.
- */
- if (ch < (UTF32)0x80) { bytesToWrite = 1;
- } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
- } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
- } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
- } else { bytesToWrite = 3;
- ch = UNI_REPLACEMENT_CHAR;
- result = sourceIllegal;
- }
-
- target += bytesToWrite;
- if (target > targetEnd) {
- --source; /* Back up source pointer! */
- target -= bytesToWrite; result = targetExhausted; break;
- }
- switch (bytesToWrite) { /* note: everything falls through. */
- case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
- case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
- }
- target += bytesToWrite;
+ UTF32 ch;
+ unsigned short bytesToWrite = 0;
+ const UTF32 byteMask = 0xBF;
+ const UTF32 byteMark = 0x80;
+ ch = *source++;
+ if (flags == strictConversion ) {
+ /* UTF-16 surrogate values are illegal in UTF-32 */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ --source; /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ }
+ }
+ /*
+ * Figure out how many bytes the result will require. Turn any
+ * illegally large UTF32 things (> Plane 17) into replacement chars.
+ */
+ if (ch < (UTF32)0x80) { bytesToWrite = 1;
+ } else if (ch < (UTF32)0x800) { bytesToWrite = 2;
+ } else if (ch < (UTF32)0x10000) { bytesToWrite = 3;
+ } else if (ch <= UNI_MAX_LEGAL_UTF32) { bytesToWrite = 4;
+ } else { bytesToWrite = 3;
+ ch = UNI_REPLACEMENT_CHAR;
+ result = sourceIllegal;
+ }
+
+ target += bytesToWrite;
+ if (target > targetEnd) {
+ --source; /* Back up source pointer! */
+ target -= bytesToWrite; result = targetExhausted; break;
+ }
+ switch (bytesToWrite) { /* note: everything falls through. */
+ case 4: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 3: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 2: *--target = (UTF8)((ch | byteMark) & byteMask); ch >>= 6;
+ case 1: *--target = (UTF8) (ch | firstByteMark[bytesToWrite]);
+ }
+ target += bytesToWrite;
}
*sourceStart = source;
*targetStart = target;
@@ -460,59 +460,59 @@
/* --------------------------------------------------------------------- */
ConversionResult ConvertUTF8toUTF32 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags) {
ConversionResult result = conversionOK;
const UTF8* source = *sourceStart;
UTF32* target = *targetStart;
while (source < sourceEnd) {
- UTF32 ch = 0;
- unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
- if (source + extraBytesToRead >= sourceEnd) {
- result = sourceExhausted; break;
- }
- /* Do this check whether lenient or strict */
- if (! isLegalUTF8(source, extraBytesToRead+1)) {
- result = sourceIllegal;
- break;
- }
- /*
- * The cases all fall through. See "Note A" below.
- */
- switch (extraBytesToRead) {
- case 5: ch += *source++; ch <<= 6;
- case 4: ch += *source++; ch <<= 6;
- case 3: ch += *source++; ch <<= 6;
- case 2: ch += *source++; ch <<= 6;
- case 1: ch += *source++; ch <<= 6;
- case 0: ch += *source++;
- }
- ch -= offsetsFromUTF8[extraBytesToRead];
+ UTF32 ch = 0;
+ unsigned short extraBytesToRead = trailingBytesForUTF8[*source];
+ if (source + extraBytesToRead >= sourceEnd) {
+ result = sourceExhausted; break;
+ }
+ /* Do this check whether lenient or strict */
+ if (! isLegalUTF8(source, extraBytesToRead+1)) {
+ result = sourceIllegal;
+ break;
+ }
+ /*
+ * The cases all fall through. See "Note A" below.
+ */
+ switch (extraBytesToRead) {
+ case 5: ch += *source++; ch <<= 6;
+ case 4: ch += *source++; ch <<= 6;
+ case 3: ch += *source++; ch <<= 6;
+ case 2: ch += *source++; ch <<= 6;
+ case 1: ch += *source++; ch <<= 6;
+ case 0: ch += *source++;
+ }
+ ch -= offsetsFromUTF8[extraBytesToRead];
- if (target >= targetEnd) {
- source -= (extraBytesToRead+1); /* Back up the source pointer! */
- result = targetExhausted; break;
- }
- if (ch <= UNI_MAX_LEGAL_UTF32) {
- /*
- * UTF-16 surrogate values are illegal in UTF-32, and anything
- * over Plane 17 (> 0x10FFFF) is illegal.
- */
- if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
- if (flags == strictConversion) {
- source -= (extraBytesToRead+1); /* return to the illegal value itself */
- result = sourceIllegal;
- break;
- } else {
- *target++ = UNI_REPLACEMENT_CHAR;
- }
- } else {
- *target++ = ch;
- }
- } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
- result = sourceIllegal;
- *target++ = UNI_REPLACEMENT_CHAR;
- }
+ if (target >= targetEnd) {
+ source -= (extraBytesToRead+1); /* Back up the source pointer! */
+ result = targetExhausted; break;
+ }
+ if (ch <= UNI_MAX_LEGAL_UTF32) {
+ /*
+ * UTF-16 surrogate values are illegal in UTF-32, and anything
+ * over Plane 17 (> 0x10FFFF) is illegal.
+ */
+ if (ch >= UNI_SUR_HIGH_START && ch <= UNI_SUR_LOW_END) {
+ if (flags == strictConversion) {
+ source -= (extraBytesToRead+1); /* return to the illegal value itself */
+ result = sourceIllegal;
+ break;
+ } else {
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
+ } else {
+ *target++ = ch;
+ }
+ } else { /* i.e., ch > UNI_MAX_LEGAL_UTF32 */
+ result = sourceIllegal;
+ *target++ = UNI_REPLACEMENT_CHAR;
+ }
}
*sourceStart = source;
*targetStart = target;
@@ -525,14 +525,14 @@
The fall-through switches in UTF-8 reading code save a
temp variable, some decrements & conditionals. The switches
are equivalent to the following loop:
- {
- int tmpBytesToRead = extraBytesToRead+1;
- do {
- ch += *source++;
- --tmpBytesToRead;
- if (tmpBytesToRead) ch <<= 6;
- } while (tmpBytesToRead > 0);
- }
+ {
+ int tmpBytesToRead = extraBytesToRead+1;
+ do {
+ ch += *source++;
+ --tmpBytesToRead;
+ if (tmpBytesToRead) ch <<= 6;
+ } while (tmpBytesToRead > 0);
+ }
In UTF-8 writing code, the switches on "bytesToWrite" are
similarly unrolled loops.
Modified: tuxmath/trunk/src/ConvertUTF.h
===================================================================
--- tuxmath/trunk/src/ConvertUTF.h 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/ConvertUTF.h 2008-08-06 02:55:05 UTC (rev 589)
@@ -45,12 +45,12 @@
the respective buffers.
Input parameters:
- sourceStart - pointer to a pointer to the source buffer.
- The contents of this are modified on return so that
- it points at the next thing to be converted.
- targetStart - similarly, pointer to pointer to the target buffer.
- sourceEnd, targetEnd - respectively pointers to the ends of the
- two buffers, for overflow checking only.
+ sourceStart - pointer to a pointer to the source buffer.
+ The contents of this are modified on return so that
+ it points at the next thing to be converted.
+ targetStart - similarly, pointer to pointer to the target buffer.
+ sourceEnd, targetEnd - respectively pointers to the ends of the
+ two buffers, for overflow checking only.
These conversion functions take a ConversionFlags argument. When this
flag is set to strict, both irregular sequences and isolated surrogates
@@ -67,15 +67,15 @@
they constitute an error.
Output parameters:
- The value "sourceIllegal" is returned from some routines if the input
- sequence is malformed. When "sourceIllegal" is returned, the source
- value will point to the illegal value that caused the problem. E.g.,
- in UTF-8 when a sequence is malformed, it points to the start of the
- malformed sequence.
+ The value "sourceIllegal" is returned from some routines if the input
+ sequence is malformed. When "sourceIllegal" is returned, the source
+ value will point to the illegal value that caused the problem. E.g.,
+ in UTF-8 when a sequence is malformed, it points to the start of the
+ malformed sequence.
Author: Mark E. Davis, 1994.
Rev History: Rick McGowan, fixes & updates May 2001.
- Fixes & updates, Sept 2001.
+ Fixes & updates, Sept 2001.
------------------------------------------------------------------------ */
@@ -87,10 +87,10 @@
bit mask & shift operations.
------------------------------------------------------------------------ */
-typedef unsigned long UTF32; /* at least 32 bits */
-typedef unsigned short UTF16; /* at least 16 bits */
-typedef unsigned char UTF8; /* typically 8 bits */
-typedef unsigned char Boolean; /* 0 or 1 */
+typedef unsigned long UTF32; /* at least 32 bits */
+typedef unsigned short UTF16; /* at least 16 bits */
+typedef unsigned char UTF8; /* typically 8 bits */
+typedef unsigned char Boolean; /* 0 or 1 */
/* Some fundamental constants */
#define UNI_REPLACEMENT_CHAR (UTF32)0x0000FFFD
@@ -100,15 +100,15 @@
#define UNI_MAX_LEGAL_UTF32 (UTF32)0x0010FFFF
typedef enum {
- conversionOK, /* conversion successful */
- sourceExhausted, /* partial character in source, but hit end */
- targetExhausted, /* insuff. room in target for conversion */
- sourceIllegal /* source sequence is illegal/malformed */
+ conversionOK, /* conversion successful */
+ sourceExhausted, /* partial character in source, but hit end */
+ targetExhausted, /* insuff. room in target for conversion */
+ sourceIllegal /* source sequence is illegal/malformed */
} ConversionResult;
typedef enum {
- strictConversion = 0,
- lenientConversion
+ strictConversion = 0,
+ lenientConversion
} ConversionFlags;
/* This is for C++ and does no harm in C */
@@ -117,28 +117,28 @@
#endif
ConversionResult ConvertUTF8toUTF16 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF16toUTF8 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
ConversionResult ConvertUTF8toUTF32 (
- const UTF8** sourceStart, const UTF8* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+ const UTF8** sourceStart, const UTF8* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF8 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
-
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF8** targetStart, UTF8* targetEnd, ConversionFlags flags);
+
ConversionResult ConvertUTF16toUTF32 (
- const UTF16** sourceStart, const UTF16* sourceEnd,
- UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
+ const UTF16** sourceStart, const UTF16* sourceEnd,
+ UTF32** targetStart, UTF32* targetEnd, ConversionFlags flags);
ConversionResult ConvertUTF32toUTF16 (
- const UTF32** sourceStart, const UTF32* sourceEnd,
- UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
+ const UTF32** sourceStart, const UTF32* sourceEnd,
+ UTF16** targetStart, UTF16* targetEnd, ConversionFlags flags);
Boolean isLegalUTF8Sequence(const UTF8 *source, const UTF8 *sourceEnd);
Modified: tuxmath/trunk/src/Makefile.in
===================================================================
--- tuxmath/trunk/src/Makefile.in 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/Makefile.in 2008-08-06 02:55:05 UTC (rev 589)
@@ -69,9 +69,9 @@
am__objects_1 = tuxmath.$(OBJEXT) setup.$(OBJEXT) \
titlescreen.$(OBJEXT) game.$(OBJEXT) options.$(OBJEXT) \
credits.$(OBJEXT) highscore.$(OBJEXT) loaders.$(OBJEXT) \
- audio.$(OBJEXT) mathcards.$(OBJEXT) fileops.$(OBJEXT) \
- ConvertUTF.$(OBJEXT) SDL_extras.$(OBJEXT) lessons.$(OBJEXT) \
- scandir.$(OBJEXT) pixels.$(OBJEXT)
+ audio.$(OBJEXT) mathcards.$(OBJEXT) campaign.$(OBJEXT) \
+ fileops.$(OBJEXT) ConvertUTF.$(OBJEXT) SDL_extras.$(OBJEXT) \
+ lessons.$(OBJEXT) scandir.$(OBJEXT) pixels.$(OBJEXT)
am_TuxMath_OBJECTS = $(am__objects_1)
TuxMath_OBJECTS = $(am_TuxMath_OBJECTS)
TuxMath_LDADD = $(LDADD)
@@ -79,9 +79,9 @@
am_tuxmath_OBJECTS = tuxmath.$(OBJEXT) setup.$(OBJEXT) \
titlescreen.$(OBJEXT) game.$(OBJEXT) options.$(OBJEXT) \
credits.$(OBJEXT) highscore.$(OBJEXT) loaders.$(OBJEXT) \
- audio.$(OBJEXT) mathcards.$(OBJEXT) fileops.$(OBJEXT) \
- ConvertUTF.$(OBJEXT) SDL_extras.$(OBJEXT) lessons.$(OBJEXT) \
- scandir.$(OBJEXT) pixels.$(OBJEXT)
+ audio.$(OBJEXT) mathcards.$(OBJEXT) campaign.$(OBJEXT) \
+ fileops.$(OBJEXT) ConvertUTF.$(OBJEXT) SDL_extras.$(OBJEXT) \
+ lessons.$(OBJEXT) scandir.$(OBJEXT) pixels.$(OBJEXT)
tuxmath_OBJECTS = $(am_tuxmath_OBJECTS)
tuxmath_LDADD = $(LDADD)
tuxmath_DEPENDENCIES =
@@ -274,6 +274,7 @@
loaders.c \
audio.c \
mathcards.c \
+ campaign.c \
fileops.c \
ConvertUTF.c \
SDL_extras.c \
@@ -291,6 +292,7 @@
options.h \
setup.h \
titlescreen.h \
+ campaign.h \
tuxmath.h \
ConvertUTF.h \
SDL_extras.h \
@@ -378,6 +380,7 @@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/ConvertUTF.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/SDL_extras.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/audio.Po at am__quote@
+ at AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/campaign.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/credits.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/fileops.Po at am__quote@
@AMDEP_TRUE@@am__include@ @am__quote at ./$(DEPDIR)/game.Po at am__quote@
Modified: tuxmath/trunk/src/SDL_extras.c
===================================================================
--- tuxmath/trunk/src/SDL_extras.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/SDL_extras.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -152,92 +152,92 @@
note: you can have it flip both
**********************/
SDL_Surface* Flip( SDL_Surface *in, int x, int y ) {
- SDL_Surface *out, *tmp;
- SDL_Rect from_rect, to_rect;
- Uint32 flags;
- Uint32 colorkey=0;
+ SDL_Surface *out, *tmp;
+ SDL_Rect from_rect, to_rect;
+ Uint32 flags;
+ Uint32 colorkey=0;
- /* --- grab the settings for the incoming pixmap --- */
+ /* --- grab the settings for the incoming pixmap --- */
- SDL_LockSurface(in);
- flags = in->flags;
+ SDL_LockSurface(in);
+ flags = in->flags;
- /* --- change in's flags so ignore colorkey & alpha --- */
+ /* --- change in's flags so ignore colorkey & alpha --- */
- if (flags & SDL_SRCCOLORKEY) {
- in->flags &= ~SDL_SRCCOLORKEY;
- colorkey = in->format->colorkey;
- }
- if (flags & SDL_SRCALPHA) {
- in->flags &= ~SDL_SRCALPHA;
- }
+ if (flags & SDL_SRCCOLORKEY) {
+ in->flags &= ~SDL_SRCCOLORKEY;
+ colorkey = in->format->colorkey;
+ }
+ if (flags & SDL_SRCALPHA) {
+ in->flags &= ~SDL_SRCALPHA;
+ }
- SDL_UnlockSurface(in);
+ SDL_UnlockSurface(in);
- /* --- create our new surface --- */
+ /* --- create our new surface --- */
- out = SDL_CreateRGBSurface(
- SDL_SWSURFACE,
- in->w, in->h, 32, rmask, gmask, bmask, amask);
+ out = SDL_CreateRGBSurface(
+ SDL_SWSURFACE,
+ in->w, in->h, 32, rmask, gmask, bmask, amask);
- /* --- flip horizontally if requested --- */
+ /* --- flip horizontally if requested --- */
- if (x) {
- from_rect.h = to_rect.h = in->h;
- from_rect.w = to_rect.w = 1;
- from_rect.y = to_rect.y = 0;
- from_rect.x = 0;
- to_rect.x = in->w - 1;
+ if (x) {
+ from_rect.h = to_rect.h = in->h;
+ from_rect.w = to_rect.w = 1;
+ from_rect.y = to_rect.y = 0;
+ from_rect.x = 0;
+ to_rect.x = in->w - 1;
- do {
- SDL_BlitSurface(in, &from_rect, out, &to_rect);
- from_rect.x++;
- to_rect.x--;
- } while (to_rect.x >= 0);
- }
+ do {
+ SDL_BlitSurface(in, &from_rect, out, &to_rect);
+ from_rect.x++;
+ to_rect.x--;
+ } while (to_rect.x >= 0);
+ }
- /* --- flip vertically if requested --- */
+ /* --- flip vertically if requested --- */
- if (y) {
- from_rect.h = to_rect.h = 1;
- from_rect.w = to_rect.w = in->w;
- from_rect.x = to_rect.x = 0;
- from_rect.y = 0;
- to_rect.y = in->h - 1;
+ if (y) {
+ from_rect.h = to_rect.h = 1;
+ from_rect.w = to_rect.w = in->w;
+ from_rect.x = to_rect.x = 0;
+ from_rect.y = 0;
+ to_rect.y = in->h - 1;
- do {
- SDL_BlitSurface(in, &from_rect, out, &to_rect);
- from_rect.y++;
- to_rect.y--;
- } while (to_rect.y >= 0);
- }
+ do {
+ SDL_BlitSurface(in, &from_rect, out, &to_rect);
+ from_rect.y++;
+ to_rect.y--;
+ } while (to_rect.y >= 0);
+ }
- /* --- restore colorkey & alpha on in and setup out the same --- */
+ /* --- restore colorkey & alpha on in and setup out the same --- */
- SDL_LockSurface(in);
+ SDL_LockSurface(in);
- if (flags & SDL_SRCCOLORKEY) {
- in->flags |= SDL_SRCCOLORKEY;
- in->format->colorkey = colorkey;
- tmp = SDL_DisplayFormat(out);
- SDL_FreeSurface(out);
- out = tmp;
- out->flags |= SDL_SRCCOLORKEY;
- out->format->colorkey = colorkey;
- } else if (flags & SDL_SRCALPHA) {
- in->flags |= SDL_SRCALPHA;
- tmp = SDL_DisplayFormatAlpha(out);
- SDL_FreeSurface(out);
- out = tmp;
- } else {
- tmp = SDL_DisplayFormat(out);
- SDL_FreeSurface(out);
- out = tmp;
- }
+ if (flags & SDL_SRCCOLORKEY) {
+ in->flags |= SDL_SRCCOLORKEY;
+ in->format->colorkey = colorkey;
+ tmp = SDL_DisplayFormat(out);
+ SDL_FreeSurface(out);
+ out = tmp;
+ out->flags |= SDL_SRCCOLORKEY;
+ out->format->colorkey = colorkey;
+ } else if (flags & SDL_SRCALPHA) {
+ in->flags |= SDL_SRCALPHA;
+ tmp = SDL_DisplayFormatAlpha(out);
+ SDL_FreeSurface(out);
+ out = tmp;
+ } else {
+ tmp = SDL_DisplayFormat(out);
+ SDL_FreeSurface(out);
+ out = tmp;
+ }
- SDL_UnlockSurface(in);
+ SDL_UnlockSurface(in);
- return out;
+ return out;
}
/* Blend two surfaces together. The third argument is between 0.0 and
@@ -274,7 +274,7 @@
// Check that both images have the same width dimension
if (S1->w != S2->w) {
printf("S1->w %d, S2->w %d; S1->h %d, S2->h %d\n",
- S1->w,S2->w,S1->h,S2->h);
+ S1->w,S2->w,S1->h,S2->h);
printf("Both images must have the same width dimensions\n");
return S1;
}
@@ -434,9 +434,9 @@
int inRect( SDL_Rect r, int x, int y) {
- if ((x < r.x) || (y < r.y) || (x > r.x + r.w) || (y > r.y + r.h))
- return 0;
- return 1;
+ if ((x < r.x) || (y < r.y) || (x > r.x + r.w) || (y > r.y + r.h))
+ return 0;
+ return 1;
}
/* Darkens the screen by a factor of 2^bits */
@@ -530,7 +530,7 @@
/* current colorspace: */
void (*putpixel) (SDL_Surface*, int, int, Uint32);
Uint32(*getpixel) (SDL_Surface*, int, int);
-
+
float xscale, yscale;
int x, y;
int floor_x, ceil_x,
@@ -548,8 +548,8 @@
/* Create surface for zoom: */
- s = SDL_CreateRGBSurface(src->flags, /* SDL_SWSURFACE, */
- new_w, new_h, src->format->BitsPerPixel,
+ s = SDL_CreateRGBSurface(src->flags, /* SDL_SWSURFACE, */
+ new_w, new_h, src->format->BitsPerPixel,
src->format->Rmask,
src->format->Gmask,
src->format->Bmask,
@@ -558,8 +558,8 @@
if (s == NULL)
{
fprintf(stderr, "\nError: Can't build zoom surface\n"
- "The Simple DirectMedia Layer error that occurred was:\n"
- "%s\n\n", SDL_GetError());
+ "The Simple DirectMedia Layer error that occurred was:\n"
+ "%s\n\n", SDL_GetError());
return NULL;
// cleanup();
// exit(1);
@@ -647,310 +647,6 @@
return s;
}
-//FIXME: everything below is slightly modified code from pixels.c and would do
-// better to be included as such.
-#if 0 //selectively omit from here to the end of file until pixels.c is in
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-
-/*
- pixels.c
-
- For Tux Paint
- Pixel read/write functions
-
- Copyright (c) 2002-2006 by Bill Kendrick and others
- bill at newbreedsoftware.com
- http://www.newbreedsoftware.com/tuxpaint/
-
- This program is free software; you can redistribute it and/or modify
- it under the terms of the GNU General Public License as published by
- the Free Software Foundation; either version 2 of the License, or
- (at your option) any later version.
-
- This program is distributed in the hope that it will be useful,
- but WITHOUT ANY WARRANTY; without even the implied warranty of
- MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- GNU General Public License for more details.
-
- You should have received a copy of the GNU General Public License
- along with this program; if not, write to the Free Software
- Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
- (See COPYING.txt)
-
- June 14, 2002 - February 17, 2006
- $Id: pixels.c,v 1.3 2006/08/27 21:00:55 wkendrick Exp $
-*/
-
-#include "pixels.h"
-#include "compiler.h"
-//#include "debug.h"
-
-/* Draw a single pixel into the surface: */
-void putpixel8(SDL_Surface * surface, int x, int y, Uint32 pixel)
-{
- Uint8 *p;
-
-// printf("putpixel8() called\n");
-
- /* Assuming the X/Y values are within the bounds of this surface... */
- if (
- (((unsigned) x < (unsigned) surface->w)
- && ((unsigned) y < (unsigned) surface->h)))
- {
- // Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- x); /* Go in X pixels */
-
-
- /* Set the (correctly-sized) piece of data in the surface's RAM
- * to the pixel value sent in: */
-
- *p = pixel;
- }
-}
-
-/* Draw a single pixel into the surface: */
-void putpixel16(SDL_Surface * surface, int x, int y, Uint32 pixel)
-{
- Uint8 *p;
-
-// printf("putpixel16() called\n");
-
- /* Assuming the X/Y values are within the bounds of this surface... */
- if (
- (((unsigned) x < (unsigned) surface->w)
- && ((unsigned) y < (unsigned) surface->h)))
- {
- // Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 2)); /* Go in X pixels */
-
-
- /* Set the (correctly-sized) piece of data in the surface's RAM
- * to the pixel value sent in: */
-
- *(Uint16 *) p = pixel;
- }
-}
-
-/* Draw a single pixel into the surface: */
-void putpixel24(SDL_Surface * surface, int x, int y, Uint32 pixel)
-{
- Uint8 *p;
-
-// printf("putpixel24() called\n");
-
- /* Assuming the X/Y values are within the bounds of this surface... */
- if (
- (((unsigned) x < (unsigned) surface->w)
- && ((unsigned) y < (unsigned) surface->h)))
- {
- // Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 3)); /* Go in X pixels */
-
-
- /* Set the (correctly-sized) piece of data in the surface's RAM
- * to the pixel value sent in: */
-
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
- {
- p[0] = (pixel >> 16) & 0xff;
- p[1] = (pixel >> 8) & 0xff;
- p[2] = pixel & 0xff;
- }
- else
- {
- p[0] = pixel & 0xff;
- p[1] = (pixel >> 8) & 0xff;
- p[2] = (pixel >> 16) & 0xff;
- }
-
- }
-}
-
-/* Draw a single pixel into the surface: */
-void putpixel32(SDL_Surface * surface, int x, int y, Uint32 pixel)
-{
- Uint8 *p;
-
-// printf("putpixel32() called\n");
-
- /* Assuming the X/Y values are within the bounds of this surface... */
- if (
- (((unsigned) x < (unsigned) surface->w)
- && ((unsigned) y < (unsigned) surface->h)))
- {
- // Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 4)); /* Go in X pixels */
-
-
- /* Set the (correctly-sized) piece of data in the surface's RAM
- * to the pixel value sent in: */
-
- *(Uint32 *) p = pixel; // 32-bit display
- }
-}
-
-/* Get a pixel: */
-Uint32 getpixel8(SDL_Surface * surface, int x, int y)
-{
- Uint8 *p;
-
-// printf("getpixel8() called\n");
-
- /* get the X/Y values within the bounds of this surface */
- if ((unsigned) x < (unsigned) surface->w)
- x = (x < 0) ? 0 : surface->w - 1;
- if ((unsigned) y < (unsigned) surface->h)
- y = (y < 0) ? 0 : surface->h - 1;
-
- /* Set a pointer to the exact location in memory of the pixel
- in question: */
-
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- x); /* Go in X pixels */
-
-
- /* Return the correctly-sized piece of data containing the
- * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
- * RGB value) */
-
- return (*p);
-}
-
-/* Get a pixel: */
-Uint32 getpixel16(SDL_Surface * surface, int x, int y)
-{
- Uint8 *p;
-
-// printf("getpixel16() called\n");
-
- /* get the X/Y values within the bounds of this surface */
- if ((unsigned) x < (unsigned) surface->w)
- x = (x < 0) ? 0 : surface->w - 1;
- if ((unsigned) y < (unsigned) surface->h)
- y = (y < 0) ? 0 : surface->h - 1;
-
- /* Set a pointer to the exact location in memory of the pixel
- in question: */
-
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 2)); /* Go in X pixels */
-
-
- /* Return the correctly-sized piece of data containing the
- * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
- * RGB value) */
-
- return (*(Uint16 *) p);
-}
-
-/* Get a pixel: */
-Uint32 getpixel24(SDL_Surface * surface, int x, int y)
-{
- Uint8 *p;
- Uint32 pixel;
-
-// printf("getpixel24() called\n");
-
- /* get the X/Y values within the bounds of this surface */
- if ((unsigned) x < (unsigned) surface->w)
- x = (x < 0) ? 0 : surface->w - 1;
- if ((unsigned) y < (unsigned) surface->h)
- y = (y < 0) ? 0 : surface->h - 1;
-
- /* Set a pointer to the exact location in memory of the pixel
- in question: */
-
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 3)); /* Go in X pixels */
-
-
- /* Return the correctly-sized piece of data containing the
- * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
- * RGB value) */
-
- /* Depending on the byte-order, it could be stored RGB or BGR! */
-
- if (SDL_BYTEORDER == SDL_BIG_ENDIAN)
- pixel = p[0] << 16 | p[1] << 8 | p[2];
- else
- pixel = p[0] | p[1] << 8 | p[2] << 16;
-
- return pixel;
-}
-
-/* Get a pixel: */
-Uint32 getpixel32(SDL_Surface * surface, int x, int y)
-{
- Uint8 *p;
-
-// printf("getpixel32() called\n");
-
- /* get the X/Y values within the bounds of this surface */
- if ((unsigned) x < (unsigned) surface->w)
- x = (x < 0) ? 0 : surface->w - 1;
- if ((unsigned) y < (unsigned) surface->h)
- y = (y < 0) ? 0 : surface->h - 1;
-
- /* Set a pointer to the exact location in memory of the pixel
- in question: */
-
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 4)); /* Go in X pixels */
-
-
- /* Return the correctly-sized piece of data containing the
- * pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
- * RGB value) */
-
- return *(Uint32 *) p; // 32-bit display
-}
-
-/* Function pointer arrays to allow correct function */
-/* to be used according to colorspace: */
-void (*putpixels[]) (SDL_Surface *, int, int, Uint32) =
-{
- putpixel8,
- putpixel8,
- putpixel16,
- putpixel24,
- putpixel32
-};
-
-Uint32(*getpixels[])(SDL_Surface *, int, int) =
-{
- getpixel8,
- getpixel8,
- getpixel16,
- getpixel24,
- getpixel32
-};
-
-#endif
Modified: tuxmath/trunk/src/audio.c
===================================================================
--- tuxmath/trunk/src/audio.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/audio.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -25,7 +25,7 @@
#include "titlescreen.h"
-Mix_Music *music;
+Mix_Music *music;
void playsound(int snd)
{
@@ -59,12 +59,12 @@
* loaded using the audioMusicLoad function
*/
void audioMusicUnload( void ) {
- if (!Opts_UsingSound()) return;
+ if (!Opts_UsingSound()) return;
- if ( defaultMusic )
- Mix_FreeMusic( defaultMusic );
+ if ( defaultMusic )
+ Mix_FreeMusic( defaultMusic );
- defaultMusic=NULL;
+ defaultMusic=NULL;
}
/* audioMusicPlay attempts to play the passed music data.
@@ -73,8 +73,8 @@
* Note: loops == -1 means forever
*/
void audioMusicPlay( Mix_Music *musicData, int loops ) {
- if (!Opts_UsingSound()) return;
+ if (!Opts_UsingSound()) return;
- audioMusicUnload();
- Mix_PlayMusic( musicData, loops );
+ audioMusicUnload();
+ Mix_PlayMusic( musicData, loops );
}
Modified: tuxmath/trunk/src/campaign.c
===================================================================
--- tuxmath/trunk/src/campaign.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/campaign.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -10,6 +10,8 @@
void briefPlayer(int stage); //show text introducing the given stage
void readStageSettings(int stage);
void readRoundSettings(int stage, int round);
+void showGameOver();
+void showGameWon();
char* stagenames[NUM_STAGES] = {"cadet", "scout", "ranger", "ace", "commando"};
@@ -18,7 +20,7 @@
int i, j;
int gameresult = 0, endcampaign = 0;
char roundmessage[10];
-
+ char* endtext[2] = {"Congratulations! You win!", NULL};
printf("Entering start_campaign()\n");
@@ -45,7 +47,7 @@
;
else if (gameresult == GAME_OVER_LOST)
{
- //TODO game over sequence
+ showGameOver();
endcampaign = 1;
}
else if (gameresult == GAME_OVER_ERROR)
@@ -63,12 +65,19 @@
return;
}
+ //if we've beaten the last stage, there is no bonus, skip to win sequence
+ if (i == NUM_STAGES - 1)
+ {
+ showGameWon();
+ break;
+ }
//bonus round
readStageSettings(i);
readRoundSettings(i, -1);
game_set_start_message("Bonus", "", "", "");
game();
- }
+ }
+ scroll_text(endtext, screen->clip_rect, 3);
}
void briefPlayer(int stage)
@@ -120,3 +129,15 @@
snprintf(fn,PATH_MAX, "campaign/%s/round%d", stagenames[stage], round);
read_named_config_file(fn);
}
+
+void showGameOver()
+{
+ char* text[2] = {"Sorry, try again!", NULL};
+ scroll_text(text, screen->clip_rect, 3);
+}
+
+void showGameWon()
+{
+ char* text[2] = {"Mission accomplished. The galaxy is safe!", NULL};
+ scroll_text(text, screen->clip_rect, 3);
+}
Modified: tuxmath/trunk/src/credits.c
===================================================================
--- tuxmath/trunk/src/credits.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/credits.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -478,7 +478,8 @@
while (!done);
return quit;
}
-#if 0
+#if 0 //really cool effect, but not translatable. I'll leave it in in case we
+ //decide to use it e.g. only for English
void draw_text(char * str, int offset)
{
int i, c, x, y, cur_x, start, hilite;
Modified: tuxmath/trunk/src/fileops.c
===================================================================
--- tuxmath/trunk/src/fileops.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/fileops.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -161,8 +161,8 @@
*/
static HRESULT ReadRegistry(const char *key, const char *option, char *value, int size)
{
- LONG res;
- HKEY hKey = NULL;
+ LONG res;
+ HKEY hKey = NULL;
res = RegOpenKeyEx(HKEY_CURRENT_USER, key, 0, KEY_READ, &hKey);
if (res != ERROR_SUCCESS)
@@ -1189,12 +1189,11 @@
/* terminate string here: */
*value_end = 0;
- #ifdef TUXMATH_DEBUG
- printf("parameter = '%s'\t, length = %zu\n", parameter, strlen(parameter));
- printf("value = '%s'\t, length = %zu\t, atoi() = %d\t, atof() = %.2f\n", value, strlen(value), atoi(value), atof(value));
- #endif
+ tmdprintf("parameter = '%s'\t, length = %zu\n", parameter, strlen(parameter));
+ tmdprintf("value = '%s'\t, length = %zu\t, atoi() = %d\t, atof() = %.2f\n", value, strlen(value), atoi(value), atof(value));
+
/* Now ready to handle each name/value pair! */
-
+
/* Set general game_options struct (see tuxmath.h): */
if(0 == strcasecmp(parameter, "per_user_config"))
{
@@ -1212,14 +1211,14 @@
/* Only let administrator change this setting */
if (file_type == GLOBAL_CONFIG_FILE && user_data_dir == NULL)
{
- /* Check to see whether the specified homedir exists */
- dir = opendir(value);
- if (dir == NULL)
- fprintf(stderr,"homedir: %s is not a directory, or it could not be read\n", value);
- else {
- set_user_data_dir(value); /* copy the homedir setting */
- closedir(dir);
- }
+ /* Check to see whether the specified homedir exists */
+ dir = opendir(value);
+ if (dir == NULL)
+ fprintf(stderr,"homedir: %s is not a directory, or it could not be read\n", value);
+ else {
+ set_user_data_dir(value); /* copy the homedir setting */
+ closedir(dir);
+ }
}
}
@@ -1380,324 +1379,28 @@
Opts_SetMaxComets(atoi(value));
}
-
- /* Begin setting of math question options (see mathcards.h): */
-
- /* General math options */
-
- else if(0 == strcasecmp(parameter, "allow_negatives"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetAllowNegatives(v);
- }
-
- else if(0 == strcasecmp(parameter, "max_answer"))
- {
- MC_SetMaxAnswer(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_questions"))
- {
- MC_SetMaxQuestions(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "play_through_list"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetPlayThroughList(v);
- }
-
- else if(0 == strcasecmp(parameter, "repeat_wrongs"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetRepeatWrongs(v);
- }
-
- else if(0 == strcasecmp(parameter, "copies_repeated_wrongs"))
- {
- MC_SetCopiesRepeatedWrongs(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "question_copies"))
- {
- MC_SetQuestionCopies(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "randomize"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetRandomize(v);
- }
-
- else if(0 == strcasecmp(parameter, "fraction_to_keep"))
- {
- MC_SetFractionToKeep(atof(value));
- }
-
- else if(0 == strcasecmp(parameter, "format_answer_last"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatAnswerLast(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_answer_first"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatAnswerFirst(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_answer_middle"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatAnswerMiddle(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_add_answer_last"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatAddAnswerLast(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_add_answer_first"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatAddAnswerFirst(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_add_answer_middle"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatAddAnswerMiddle(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_sub_answer_last"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatSubAnswerLast(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_sub_answer_first"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatSubAnswerFirst(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_sub_answer_middle"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatSubAnswerMiddle(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_mult_answer_last"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatMultAnswerLast(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_mult_answer_first"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatMultAnswerFirst(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_mult_answer_middle"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatMultAnswerMiddle(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_div_answer_last"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatDivAnswerLast(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_div_answer_first"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatDivAnswerFirst(v);
- }
-
- else if(0 == strcasecmp(parameter, "format_div_answer_middle"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetFormatDivAnswerMiddle(v);
- }
-
-
- /* Set the allowed math operations: */
-
-
- else if(0 == strcasecmp(parameter, "addition_allowed"))
- {
- MC_SetAddAllowed(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "subtraction_allowed"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetSubAllowed(v);
- }
-
- else if(0 == strcasecmp(parameter, "multiplication_allowed"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetMultAllowed(v);
- }
-
- else if(0 == strcasecmp(parameter, "division_allowed"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetDivAllowed(v);
- }
-
- else if(0 == strcasecmp(parameter, "typing_practice_allowed"))
- {
- int v = str_to_bool(value);
- if (v != -1)
- MC_SetTypingAllowed(v);
- }
-
- /* Set min and max for addition: */
-
-
- else if(0 == strcasecmp(parameter, "min_augend"))
- {
- MC_SetAddMinAugend(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_augend"))
- {
- MC_SetAddMaxAugend(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "min_addend"))
- {
- MC_SetAddMinAddend(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_addend"))
- {
- MC_SetAddMaxAddend(atoi(value));
- }
-
-
- /* Set min and max for subtraction: */
-
-
- else if(0 == strcasecmp(parameter, "min_minuend"))
- {
- MC_SetSubMinMinuend(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_minuend"))
- {
- MC_SetSubMaxMinuend(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "min_subtrahend"))
- {
- MC_SetSubMinSubtrahend(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_subtrahend"))
- {
- MC_SetSubMaxSubtrahend(atoi(value));
- }
-
-
- /* Set min and max for multiplication: */
-
-
- else if(0 == strcasecmp(parameter, "min_multiplier"))
- {
- MC_SetMultMinMultiplier(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_multiplier"))
- {
- MC_SetMultMaxMultiplier(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "min_multiplicand"))
- {
- MC_SetMultMinMultiplicand(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_multiplicand"))
- {
- MC_SetMultMaxMultiplicand(atoi(value));
- }
-
-
- /* Set min and max for division: */
-
-
- else if(0 == strcasecmp(parameter, "min_divisor"))
- {
- MC_SetDivMinDivisor(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "min_quotient"))
- {
- MC_SetDivMinQuotient(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_divisor"))
- {
- MC_SetDivMaxDivisor(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_quotient"))
- {
- MC_SetDivMaxQuotient(atoi(value));
- }
-
-
- /* Set min and max for typing practice: */
-
-
- else if(0 == strcasecmp(parameter, "min_typing_num"))
- {
- MC_SetTypeMin(atoi(value));
- }
-
- else if(0 == strcasecmp(parameter, "max_typing_num"))
- {
- MC_SetTypeMax(atoi(value));
- }
-
else
{
- #ifdef TUXMATH_DEBUG
- printf("parameter not recognized: %s\n", parameter);
- #endif
+ MC_SetOp(parameter, atoi(value) ); //automatically handles bad parameters
}
free(parameter);
}
-
+ //handle min > max by disallowing operation
+ if (MC_GetOpt(MIN_AUGEND) > MC_GetOpt(MAX_AUGEND) ||
+ MC_GetOpt(MIN_ADDEND) > MC_GetOpt(MAX_ADDEND) )
+ MC_SetOpt(ADDITION_ALLOWED, 0);
+ if (MC_GetOpt(MIN_MINUEND) > MC_GetOpt(MAX_MINUEND) ||
+ MC_GetOpt(MIN_SUBTRAHEND) > MC_GetOpt(MAX_SUBTRAHEND) )
+ MC_SetOpt(SUBTRACTION_ALLOWED, 0);
+ if (MC_GetOpt(MIN_MULTIPLICAND) > MC_GetOpt(MAX_MULTIPLICAND) ||
+ MC_GetOpt(MIN_MULTIPLIER) > MC_GetOpt(MAX_MULTIPLIER) )
+ MC_SetOpt(MULTIPLICATION_ALLOWED, 0);
+ if (MC_GetOpt(MIN_DIVISOR) > MC_GetOpt(MAX_DIVISOR) ||
+ MC_GetOpt(MIN_QUOTIENT) > MC_GetOpt(MAX_QUOTIENT) )
+ MC_SetOpt(DIVISION_ALLOWED, 0);
+ if (MC_GetOpt(MIN_TYPING_NUM) > MC_GetOpt(MAX_TYPING_NUM) )
+ MC_SetOpt(TYPING_PRACTICE_ALLOWED, 0);
+
#ifdef TUXMATH_DEBUG
printf("\nAfter file read in:\n");
write_config_file(stdout, 0);
@@ -1747,475 +1450,271 @@
/* human-readable file. */
int write_config_file(FILE *fp, int verbose)
{
- #ifdef TUXMATH_DEBUG
- printf("\nEntering write_config_file()\n");
- #endif
+ int i, vcommentsprimed = 0;
+ static char* vcomments[NOPTS]; //comments when writing out verbose
+ if (!vcommentsprimed) //we only want to initialize these once
+ {
+ vcommentsprimed = 1;
+ for (i = 0; i < NOPTS; ++i)
+ vcomments[i] = NULL;
+ vcomments[PLAY_THROUGH_LIST] =
+ "############################################################\n"
+ "# #\n"
+ "# Tuxmath Configuration File #\n"
+ "# #\n"
+ "# The behavior of Tuxmath can be controlled to a great #\n"
+ "# extent by editing this file with any and saving it in #\n"
+ "# the default options location ($HOME/.tuxmath/options). #\n"
+ "# The file consists of 'NAME = VALUE' pairs, one pair per #\n"
+ "# line. Each option is one of the following types: #\n"
+ "# #\n"
+ "# boolean: 1 (synonyms 'true', 'T', 'yes', 'Y', 'on') #\n"
+ "# or #\n"
+ "# 0 (synonyms 'false, 'F', 'no', 'N', 'off') #\n"
+ "# integer (i.e. non-fractional numbers) #\n"
+ "# float (i.e decimal fractions) #\n"
+ "# #\n"
+ "# Lines beginning with '#' or ';' are ignored as comments. #\n"
+ "# The synonyms for boolean '0' and '1' are accepted as #\n"
+ "# input, but always written as '0' or '1' when Tuxmath #\n"
+ "# writes a config file to disk. #\n"
+ "# The file is organized with the more important options #\n"
+ "# first. #\n"
+ "############################################################\n"
+ "\n"
+ "############################################################\n"
+ "# #\n"
+ "# Game Mode #\n"
+ "# #\n"
+ "# Parameter: play_through_list (Boolean) #\n"
+ "# Default: 1 #\n"
+ "# #\n"
+ "# Tuxmath generates a list of math questions based on #\n"
+ "# parameters set below. By default, (play_through_list = #\n"
+ "# 1) the questions are asked in a random order. #\n"
+ "# Correctly answered questions are removed from the list. #\n"
+ "# If the player fails to correctly answer a question #\n"
+ "# before it hits a city, the question will be reinserted #\n"
+ "# into the list in a random location. #\n"
+ "# The player wins if all questions are answered correctly #\n"
+ "# before the cities are destroyed. #\n"
+ "# #\n"
+ "# Alternatively, Tuxmath can be played in 'Arcade Mode' #\n"
+ "# by setting play_through_list = 0 (i.e. 'false'). If this #\n"
+ "# is done, all questions will be randomly reinserted into #\n"
+ "# the list whether or not they are answered correctly, and #\n"
+ "# the game continues as long as there is a surviving city. #\n"
+ "############################################################\n"
+ "\n";
+
+ vcomments[ADDITION_ALLOWED] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Selecting Math Operations #\n"
+ "# #\n"
+ "# Parameter: addition_allowed (boolean) #\n"
+ "# Default: 1 #\n"
+ "# Parameter: subtraction_allowed (boolean) #\n"
+ "# Default: 1 #\n"
+ "# Parameter: multiplication_allowed (boolean) #\n"
+ "# Default: 1 #\n"
+ "# Parameter: division_allowed (boolean) #\n"
+ "# Default: 1 #\n"
+ "# #\n"
+ "# These options enable questions for each of the four math #\n"
+ "# operations. All are 1 (yes) by default. #\n"
+ "############################################################\n\n";
+ vcomments[TYPING_PRACTICE_ALLOWED] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Typing Practice #\n"
+ "# #\n"
+ "# Parameter: typing_practice_allowed (boolean) #\n"
+ "# Default: 0 #\n"
+ "# #\n"
+ "# This option simply displays numbers for the youngest #\n"
+ "# players to type in to learn the keyboard. #\n"
+ "############################################################\n\n";
+ vcomments[ALLOW_NEGATIVES] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Negative Number Support #\n"
+ "# #\n"
+ "# Parameter: allow_negatives (boolean) #\n"
+ "# Default: 0 #\n"
+ "# #\n"
+ "# 'allow_negatives' allows or disallows use of negative #\n"
+ "# numbers as both operands and answers. Default is 0 #\n"
+ "# (no), which disallows questions like: #\n"
+ "# 2 - 4 = ? #\n"
+ "# Note: this option must be enabled in order to set the #\n"
+ "# operand ranges to include negatives. If it is changed #\n"
+ "# from 1 (yes) to 0 (no), any negative operand limits will #\n"
+ "# be reset to 0. #\n"
+ "############################################################\n\n";
+ vcomments[MIN_AUGEND] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Minimum and Maximum Values for Operand Ranges #\n"
+ "# #\n"
+ "# Parameters: (multiple - all integer type) #\n"
+ "# #\n"
+ "# Operand limits can be set to any integer up to the #\n"
+ "# value of 'max_answer'. Tuxmath will generate questions #\n"
+ "# for every value in the specified range. The maximum must #\n"
+ "# be greater than or equal to the corresponding minimum #\n"
+ "# for any questions to be generated for that operation. #\n"
+ "# Defaults are 0 for minima and 12 for maxima. #\n"
+ "# #\n"
+ "# Note: 'allow_negatives' must be set to 1 for negative #\n"
+ "# values to be accepted (see 'Advanced Options'). #\n"
+ "############################################################\n"
+ "\n# Addition operands:\n"
+ "# augend + addend = sum\n\n";
+ vcomments[MIN_MINUEND] =
+ "\n# Subtraction operands:\n"
+ "# minuend - subtrahend = difference\n\n";
+ vcomments[MIN_MULTIPLIER] =
+ "\n# Multiplication operands:\n"
+ "# multiplier * multiplicand = product\n\n";
+ vcomments[MIN_DIVISOR] =
+ "\n# Division operands:\n"
+ "# dividend / divisor = quotiend\n\n";
+ vcomments[MIN_TYPING_NUM] =
+ "\n# Typing practice:\n";
+ vcomments[QUESTION_COPIES] =
+ "\n\n\n############################################################\n"
+ "# #\n"
+ "# Advanced Options #\n"
+ "# #\n"
+ "# The remaining settings further customize Tuxmath's #\n"
+ "# behavior. Most users will probably not change them. #\n"
+ "############################################################\n\n";
+
+ "\n############################################################\n"
+ "# #\n"
+ "# Advanced Math Question List Options #\n"
+ "# #\n"
+ "# Parameter: question_copies (integer) #\n"
+ "# Default: 1 #\n"
+ "# Parameter: repeat_wrongs (boolean) #\n"
+ "# Default: 1 #\n"
+ "# Parameter: copies_repeated_wrongs (integer) #\n"
+ "# Default: 1 #\n"
+ "# Parameter: fraction_to_keep (float) #\n"
+ "# Default: 1 #\n"
+ "# #\n"
+ "# These settings offer further control over the question #\n"
+ "# list and are generally only useful if 'play_through_list'#\n"
+ "# is enabled (as it is by default). #\n"
+ "# #\n"
+ "# 'question_copies' is the number of times each question #\n"
+ "# is put into the initial list. It can be 1 to 10. #\n"
+ "# #\n"
+ "# 'repeat_wrongs' determines whether questions the player #\n"
+ "# failed to answer correctly will be asked again. #\n"
+ "# #\n"
+ "# 'copies_repeated_wrongs' gives the number of times a #\n"
+ "# missed question will reappear. This can be set anywhere #\n"
+ "# from 1 to 10. #\n"
+ "# #\n"
+ "# 'fraction_to_keep' allows a list to be generated that #\n"
+ "# consists of a randomly-selected subset of the questions #\n"
+ "# fitting the criteria. The parameter is a float that #\n"
+ "# must be greater than 0 and less than or equal to 1. For #\n"
+ "# example, a value of 0.1 means 10%% of the questions #\n"
+ "# meeting the criteria will go into the list. #\n"
+ "# #\n"
+ "# The defaults for these values result in a 'mission' #\n"
+ "# for Tux that is accomplished by answering all #\n"
+ "# questions correctly with at least one surviving city. #\n"
+ "############################################################\n\n";
+ vcomments[FORMAT_ADD_ANSWER_LAST] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Math Question Formats #\n"
+ "# #\n"
+ "# The 'format_<op>_answer_<place> options control #\n"
+ "# generation of questions with the answer in different #\n"
+ "# places in the equation. i.e.: #\n"
+ "# #\n"
+ "# format_add_answer_last: 2 + 2 = ? #\n"
+ "# format_add_answer_first: ? + 2 = 4 #\n"
+ "# format_add_answer_middle: 2 + ? = 4 #\n"
+ "# #\n"
+ "# By default, 'format_answer_first' is enabled and the #\n"
+ "# other two formats are disabled. Note that the options #\n"
+ "# are not mutually exclusive - the question list may #\n"
+ "# contain questions with different formats. #\n"
+ "# #\n"
+ "# The formats are set independently for each of the four #\n"
+ "# math operations. All parameters are type 'boolean'. #\n"
+ "############################################################\n\n";
+ vcomments[MAX_ANSWER] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Parameter: max_answer (integer) #\n"
+ "# Default: 999 #\n"
+ "# #\n"
+ "# 'max_answer' is the largest absolute value allowed in #\n"
+ "# any value in a question (not only the answer). Default #\n"
+ "# is 999, which is as high as it can be set. It can be set #\n"
+ "# lower to fine-tune the list for certain 'lessons'. #\n"
+ "############################################################\n\n";
+ vcomments[MAX_QUESTIONS] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Parameter: max_questions (integer) #\n"
+ "# Default: 5000 #\n"
+ "# #\n"
+ "# 'max_questions' is limit of the length of the question #\n"
+ "# list. Default is 5000 - only severe taskmasters will #\n"
+ "# need to raise it! #\n"
+ "############################################################\n\n";
+ vcomments[RANDOMIZE] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Parameter: randomize (boolean) #\n"
+ "# Default: 1 #\n"
+ "# #\n"
+ "# If 'randomize' selected, the list will be shuffled #\n"
+ "# at the start of the game. Otherwise, the questions #\n"
+ "# appear in the order the program generates them. #\n"
+ "############################################################\n\n";
+
+ }
+
+ tmdprintf("\nEntering write_config_file()\n");
/* get out if file pointer null */
if(!fp)
{
fprintf (stderr, "write_config_file() - file pointer invalid/n");
-
- #ifdef TUXMATH_DEBUG
- printf("Leaving write_config_file()\n");
- #endif
-
+ tmdprintf("Leaving write_config_file()\n");
return 0;
}
-
- if (verbose)
+
+ for (i = 0; i < NOPTS; ++i) //for each option
{
- fprintf(fp,
- "############################################################\n"
- "# #\n"
- "# Tuxmath Configuration File #\n"
- "# #\n"
- "# The behavior of Tuxmath can be controlled to a great #\n"
- "# extent by editing this file with any and saving it in #\n"
- "# the default options location ($HOME/.tuxmath/options). #\n"
- "# The file consists of 'NAME = VALUE' pairs, one pair per #\n"
- "# line. Each option is one of the following types: #\n"
- "# #\n"
- "# boolean: 1 (synonyms 'true', 'T', 'yes', 'Y', 'on') #\n"
- "# or #\n"
- "# 0 (synonyms 'false, 'F', 'no', 'N', 'off') #\n"
- "# integer (i.e. non-fractional numbers) #\n"
- "# float (i.e decimal fractions) #\n"
- "# #\n"
- "# Lines beginning with '#' or ';' are ignored as comments. #\n"
- "# The synonyms for boolean '0' and '1' are accepted as #\n"
- "# input, but always written as '0' or '1' when Tuxmath #\n"
- "# writes a config file to disk. #\n"
- "# The file is organized with the more important options #\n"
- "# first. #\n"
- "############################################################\n"
- "\n"
- );
+ if (verbose && vcomments[i]) //comment goes before
+ fprintf(fp, vcomments[i]);
+ fprintf(fp, "%s = %d\n", MC_OPTION_TEXT[i], MC_GetOpt(i) );
}
-
+
if (verbose)
{
- fprintf(fp,
- "############################################################\n"
- "# #\n"
- "# Game Mode #\n"
- "# #\n"
- "# Parameter: play_through_list (Boolean) #\n"
- "# Default: 1 #\n"
- "# #\n"
- "# Tuxmath generates a list of math questions based on #\n"
- "# parameters set below. By default, (play_through_list = #\n"
- "# 1) the questions are asked in a random order. #\n"
- "# Correctly answered questions are removed from the list. #\n"
- "# If the player fails to correctly answer a question #\n"
- "# before it hits a city, the question will be reinserted #\n"
- "# into the list in a random location. #\n"
- "# The player wins if all questions are answered correctly #\n"
- "# before the cities are destroyed. #\n"
- "# #\n"
- "# Alternatively, Tuxmath can be played in 'Arcade Mode' #\n"
- "# by setting play_through_list = 0 (i.e. 'false'). If this #\n"
- "# is done, all questions will be randomly reinserted into #\n"
- "# the list whether or not they are answered correctly, and #\n"
- "# the game continues as long as there is a surviving city. #\n"
- "############################################################\n"
- "\n"
- );
+ //allow_speedup comment
}
- fprintf (fp, "play_through_list = %d\n", MC_PlayThroughList());
-
-
+ fprintf(fp, "allow_speedup = %d\n", Opts_AllowSpeedup() );
+
if (verbose)
{
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Speed and Number of Comets #\n"
- "# #\n"
- "# Parameter: allow_speedup (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: use_feedback (boolean) #\n"
- "# Default: 0 #\n"
- "# #\n"
- "# By default, the comets become faster and more numerous #\n"
- "# with each succeeding. The increase can be prevented #\n"
- "# by setting 'allow_speedup' to 0. #\n"
- "# #\n"
- "# If 'allow_speedup' is enabled, it is also possible to #\n"
- "# dynamically adjust the speed to the player's performance #\n"
- "# by setting 'use_feedback' to 1. This feature attempts #\n"
- "# to speed the game up if it is too easy for the player, #\n"
- "# and to slow it down if the player is having trouble. #\n"
- "# #\n"
- "# Many additional parameters under 'Advanced Options' can #\n"
- "# be used to fine-tune these behaviors. #\n"
- "############################################################\n\n");
- }
-
- fprintf(fp, "allow_speedup = %d\n", Opts_AllowSpeedup());
- fprintf(fp, "use_feedback = %d\n", Opts_UseFeedback());
-
-
+ //use_sound comment
+ }
+ fprintf(fp, "use_sound = %d\n", Opts_UseSound() );
+
if (verbose)
{
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Selecting Math Operations #\n"
- "# #\n"
- "# Parameter: addition_allowed (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: subtraction_allowed (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: multiplication_allowed (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: division_allowed (boolean) #\n"
- "# Default: 1 #\n"
- "# #\n"
- "# These options enable questions for each of the four math #\n"
- "# operations. All are 1 (yes) by default. #\n"
- "############################################################\n\n");
- }
-
- fprintf(fp, "addition_allowed = %d\n", MC_AddAllowed());
- fprintf(fp, "subtraction_allowed = %d\n", MC_SubAllowed());
- fprintf(fp, "multiplication_allowed = %d\n", MC_MultAllowed());
- fprintf(fp, "division_allowed = %d\n", MC_DivAllowed());
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Typing Practice #\n"
- "# #\n"
- "# Parameter: typing_practice_allowed (boolean) #\n"
- "# Default: 0 #\n"
- "# #\n"
- "# This option simply displays numbers for the youngest #\n"
- "# players to type in to learn the keyboard. #\n"
- "############################################################\n\n");
- }
-
- fprintf(fp, "typing_practice_allowed = %d\n", MC_TypingAllowed());
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Negative Number Support #\n"
- "# #\n"
- "# Parameter: allow_negatives (boolean) #\n"
- "# Default: 0 #\n"
- "# #\n"
- "# 'allow_negatives' allows or disallows use of negative #\n"
- "# numbers as both operands and answers. Default is 0 #\n"
- "# (no), which disallows questions like: #\n"
- "# 2 - 4 = ? #\n"
- "# Note: this option must be enabled in order to set the #\n"
- "# operand ranges to include negatives. If it is changed #\n"
- "# from 1 (yes) to 0 (no), any negative operand limits will #\n"
- "# be reset to 0. #\n"
- "############################################################\n\n");
- }
-
- fprintf (fp, "allow_negatives = %d\n", MC_AllowNegatives());
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Minimum and Maximum Values for Operand Ranges #\n"
- "# #\n"
- "# Parameters: (multiple - all integer type) #\n"
- "# #\n"
- "# Operand limits can be set to any integer up to the #\n"
- "# value of 'max_answer'. Tuxmath will generate questions #\n"
- "# for every value in the specified range. The maximum must #\n"
- "# be greater than or equal to the corresponding minimum #\n"
- "# for any questions to be generated for that operation. #\n"
- "# Defaults are 0 for minima and 12 for maxima. #\n"
- "# #\n"
- "# Note: 'allow_negatives' must be set to 1 for negative #\n"
- "# values to be accepted (see 'Advanced Options'). #\n"
- "############################################################\n");
- }
-
- if (verbose)
- {
- fprintf(fp, "\n# Addition operands:\n"
- "# augend + addend = sum\n\n");
- }
- fprintf(fp, "min_augend = %d\n", MC_AddMinAugend());
- fprintf(fp, "max_augend = %d\n", MC_AddMaxAugend());
- fprintf(fp, "min_addend = %d\n", MC_AddMinAddend());
- fprintf(fp, "max_addend = %d\n", MC_AddMaxAddend());
-
- if (verbose)
- {
- fprintf(fp, "\n# Subtraction operands:"
- "\n# minuend - subtrahend = difference\n\n");
- }
- fprintf(fp, "min_minuend = %d\n", MC_SubMinMinuend());
- fprintf(fp, "max_minuend = %d\n", MC_SubMaxMinuend());
- fprintf(fp, "min_subtrahend = %d\n", MC_SubMinSubtrahend());
- fprintf(fp, "max_subtrahend = %d\n", MC_SubMaxSubtrahend());
-
- if (verbose)
- {
- fprintf(fp, "\n# Multiplication operands:"
- "\n# multiplier * multiplicand = product\n\n");
- }
- fprintf(fp, "min_multiplier = %d\n", MC_MultMinMultiplier());
- fprintf(fp, "max_multiplier = %d\n", MC_MultMaxMultiplier());
- fprintf(fp, "min_multiplicand = %d\n", MC_MultMinMultiplicand());
- fprintf(fp, "max_multiplicand = %d\n", MC_MultMaxMultiplicand());
-
- if (verbose)
- {
- fprintf(fp, "\n# Division operands:"
- "\n# dividend/divisor = quotient\n\n");
- }
- fprintf(fp, "min_divisor = %d\n",MC_DivMinDivisor());
- fprintf(fp, "max_divisor = %d\n", MC_DivMaxDivisor());
- fprintf(fp, "min_quotient = %d\n", MC_DivMinQuotient());
- fprintf(fp, "max_quotient = %d\n", MC_DivMaxQuotient());
-
- if (verbose)
- {
- fprintf(fp, "\n# Typing practice:\n\n");
- }
- fprintf(fp, "min_typing_num = %d\n",MC_TypeMin());
- fprintf(fp, "max_typing_num = %d\n", MC_TypeMax());
-
- if (verbose)
- {
- fprintf (fp, "\n\n############################################################\n"
- "# #\n"
- "# General Game Options #\n"
- "# #\n"
- "# Parameter: use_sound (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: menu_sound (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: menu_music (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: fullscreen (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: demo_mode (boolean) #\n"
- "# Default: 0 #\n"
- "# Parameter: use_keypad (boolean) #\n"
- "# Default: 0 #\n"
- "# Parameter: allow_pause (boolean) #\n"
- "# Default: 0 #\n"
- "# Parameter: use_igloos (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: save_game_summary (boolean) #\n"
- "# Default: 1 #\n"
- "# #\n"
- "# These parameters control various aspects of Tuxmath's #\n"
- "# not directly related to the math question to be asked. #\n"
- "############################################################\n");
-
- }
- if (verbose)
- {
- fprintf (fp, "\n# Use game sounds and background music if possible:\n");
- }
- fprintf(fp, "use_sound = %d\n", Opts_UseSound());
- fprintf(fp, "menu_sound = %d\n", Opts_MenuSound());
- fprintf(fp, "menu_music = %d\n", Opts_MenuMusic());
-
- if (verbose)
- {
- fprintf (fp, "\n# Use fullscreen at 640x480 resolution instead of\n"
- "# 640x480 window. Change to 0 if SDL has trouble with\n"
- "# fullscreen on your system:\n");
- }
- fprintf(fp, "fullscreen = %d\n", Opts_Fullscreen());
-
- if (verbose)
- {
- fprintf (fp, "\n# Display jpg images for background:\n");
- }
- fprintf(fp, "use_bkgd = %d\n", Opts_UseBkgd());
-
- if (verbose)
- {
- fprintf (fp, "\n# Run Tuxmath as demo (i.e. without user input):\n");
- }
- fprintf(fp, "demo_mode = %d\n", Opts_DemoMode());
-
- if (verbose)
- {
- fprintf (fp, "\n# Display onscreen numeric keypad - allows mouse-only\n"
- "# gameplay or use with touchscreens:\n");
- }
- fprintf(fp, "use_keypad = %d\n", Opts_UseKeypad());
-
- if (verbose)
- {
- fprintf (fp, "\n# Allow 'Pause' feature - should disable this\n"
- "# when competing for high scores!\n");
- }
- fprintf(fp, "allow_pause = %d\n", Opts_AllowPause());
-
- if (verbose)
- {
- fprintf (fp, "\n# Use newer graphics where Tux defends igloo-\n"
- "# dwelling penguins (for those who find the older\n"
- "# images of exploding cities to be distasteful)\n");
- }
- fprintf(fp, "use_igloos = %d\n", Opts_UseIgloos());
-
- if (verbose)
- {
- fprintf (fp, "\n# By default, Tuxmath saves summaries of the last\n"
- "# ten games in the user's .tuxmath directory. Set\n"
- "# this parameter to '0' to turn off.\n");
- }
- fprintf(fp, "save_summary = %d\n", Opts_SaveSummary());
-
- if (verbose)
- {
- fprintf (fp, "\n\n\n############################################################\n"
- "# #\n"
- "# Advanced Options #\n"
- "# #\n"
- "# The remaining settings further customize Tuxmath's #\n"
- "# behavior. Most users will probably not change them. #\n"
- "############################################################\n\n");
- }
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Advanced Math Question List Options #\n"
- "# #\n"
- "# Parameter: question_copies (integer) #\n"
- "# Default: 1 #\n"
- "# Parameter: repeat_wrongs (boolean) #\n"
- "# Default: 1 #\n"
- "# Parameter: copies_repeated_wrongs (integer) #\n"
- "# Default: 1 #\n"
- "# Parameter: fraction_to_keep (float) #\n"
- "# Default: 1 #\n"
- "# #\n"
- "# These settings offer further control over the question #\n"
- "# list and are generally only useful if 'play_through_list'#\n"
- "# is enabled (as it is by default). #\n"
- "# #\n"
- "# 'question_copies' is the number of times each question #\n"
- "# is put into the initial list. It can be 1 to 10. #\n"
- "# #\n"
- "# 'repeat_wrongs' determines whether questions the player #\n"
- "# failed to answer correctly will be asked again. #\n"
- "# #\n"
- "# 'copies_repeated_wrongs' gives the number of times a #\n"
- "# missed question will reappear. This can be set anywhere #\n"
- "# from 1 to 10. #\n"
- "# #\n"
- "# 'fraction_to_keep' allows a list to be generated that #\n"
- "# consists of a randomly-selected subset of the questions #\n"
- "# fitting the criteria. The parameter is a float that #\n"
- "# must be greater than 0 and less than or equal to 1. For #\n"
- "# example, a value of 0.1 means 10%% of the questions #\n"
- "# meeting the criteria will go into the list. #\n"
- "# #\n"
- "# The defaults for these values result in a 'mission' #\n"
- "# for Tux that is accomplished by answering all #\n"
- "# questions correctly with at least one surviving city. #\n"
- "############################################################\n\n");
- }
-
- fprintf (fp, "question_copies = %d\n", MC_QuestionCopies());
- fprintf (fp, "repeat_wrongs = %d\n", MC_RepeatWrongs());
- fprintf (fp, "copies_repeated_wrongs = %d\n", MC_CopiesRepeatedWrongs());
- fprintf (fp, "fraction_to_keep = %.2f\n", MC_FractionToKeep());
-
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Math Question Formats #\n"
- "# #\n"
- "# The 'format_<op>_answer_<place> options control #\n"
- "# generation of questions with the answer in different #\n"
- "# places in the equation. i.e.: #\n"
- "# #\n"
- "# format_add_answer_last: 2 + 2 = ? #\n"
- "# format_add_answer_first: ? + 2 = 4 #\n"
- "# format_add_answer_middle: 2 + ? = 4 #\n"
- "# #\n"
- "# By default, 'format_answer_first' is enabled and the #\n"
- "# other two formats are disabled. Note that the options #\n"
- "# are not mutually exclusive - the question list may #\n"
- "# contain questions with different formats. #\n"
- "# #\n"
- "# The formats are set independently for each of the four #\n"
- "# math operations. All parameters are type 'boolean'. #\n"
- "############################################################\n\n");
- }
-
- fprintf (fp, "format_add_answer_last = %d\n", MC_FormatAddAnswerLast());
- fprintf (fp, "format_add_answer_first = %d\n", MC_FormatAddAnswerFirst());
- fprintf (fp, "format_add_answer_middle = %d\n", MC_FormatAddAnswerMiddle());
- fprintf (fp, "format_sub_answer_last = %d\n", MC_FormatSubAnswerLast());
- fprintf (fp, "format_sub_answer_first = %d\n", MC_FormatSubAnswerFirst());
- fprintf (fp, "format_sub_answer_middle = %d\n", MC_FormatSubAnswerMiddle());
- fprintf (fp, "format_mult_answer_last = %d\n", MC_FormatMultAnswerLast());
- fprintf (fp, "format_mult_answer_first = %d\n", MC_FormatMultAnswerFirst());
- fprintf (fp, "format_mult_answer_middle = %d\n", MC_FormatMultAnswerMiddle());
- fprintf (fp, "format_div_answer_last = %d\n", MC_FormatDivAnswerLast());
- fprintf (fp, "format_div_answer_first = %d\n", MC_FormatDivAnswerFirst());
- fprintf (fp, "format_div_answer_middle = %d\n", MC_FormatDivAnswerMiddle());
-
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Parameter: max_answer (integer) #\n"
- "# Default: 999 #\n"
- "# #\n"
- "# 'max_answer' is the largest absolute value allowed in #\n"
- "# any value in a question (not only the answer). Default #\n"
- "# is 999, which is as high as it can be set. It can be set #\n"
- "# lower to fine-tune the list for certain 'lessons'. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "max_answer = %d\n", MC_MaxAnswer());
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Parameter: max_questions (integer) #\n"
- "# Default: 5000 #\n"
- "# #\n"
- "# 'max_questions' is limit of the length of the question #\n"
- "# list. Default is 5000 - only severe taskmasters will #\n"
- "# need to raise it! #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "max_questions = %d\n", MC_MaxQuestions());
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Parameter: randomize (boolean) #\n"
- "# Default: 1 #\n"
- "# #\n"
- "# If 'randomize' selected, the list will be shuffled #\n"
- "# at the start of the game. Otherwise, the questions #\n"
- "# appear in the order the program generates them. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "randomize = %d\n", MC_Randomize());
-
-
- if (verbose)
- {
fprintf (fp, "\n############################################################\n"
"# #\n"
"# Advanced Comet Speed Options #\n"
@@ -2607,7 +2106,7 @@
fp = fopen(filepath1, "a"); /* "a" means append to end of file */
if (fp) {
if (write_column_names) {
- fprintf(fp,"\"User\",\"Mission\",\"Date\",\"Completed?\",\"Number answered\",\"Percent correct\",\"Time per question\"\n");
+ fprintf(fp,"\"User\",\"Mission\",\"Date\",\"Completed?\",\"Number answered\",\"Percent correct\",\"Time per question\"\n");
}
mission_name = strdup(last_config_file_name);
fprintf(fp,"\"%s\",\"%s\",%d/%d/%d,%d,%d,%d,%g\n", get_user_name(), get_file_name(mission_name), datetime.tm_year+1900, datetime.tm_mon+1, datetime.tm_mday, MC_MissionAccomplished(), total_answered, ((MC_NumAnsweredCorrectly() * 100)/ total_answered), median_time);
@@ -3076,7 +2575,7 @@
if (sounds[i] == NULL)
{
fprintf(stderr,
- "\nError: I couldn't load a sound file:\n"
+ "\nError: I couldn't load a sound file:\n"
"%s\n"
"The Simple DirectMedia error that occured was:\n"
"%s\n\n", sound_filenames[i], SDL_GetError());
@@ -3102,7 +2601,7 @@
if (musics[i] == NULL)
{
fprintf(stderr,
- "\nError: I couldn't load a music file:\n"
+ "\nError: I couldn't load a music file:\n"
"%s\n"
"The Simple DirectMedia error that occured was:\n"
"%s\n\n", music_filenames[i], SDL_GetError());
@@ -3111,12 +2610,12 @@
if (i == NUM_MUSICS - 1)
{
- dest.x = 0;
- dest.y = (screen->h) - 10;
- dest.w = ((screen->w) * (i + 1 + NUM_IMAGES + NUM_SOUNDS)) / total_files;
- dest.h = 10;
-
- SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 255, 0));
+ dest.x = 0;
+ dest.y = (screen->h) - 10;
+ dest.w = ((screen->w) * (i + 1 + NUM_IMAGES + NUM_SOUNDS)) / total_files;
+ dest.h = 10;
+
+ SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 255, 0));
SDL_UpdateRect(screen, dest.x, dest.y, dest.w, dest.h);
}
}
Modified: tuxmath/trunk/src/fileops.h
===================================================================
--- tuxmath/trunk/src/fileops.h 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/fileops.h 2008-08-06 02:55:05 UTC (rev 589)
@@ -1,11 +1,11 @@
/*
C Interface: fileops.h
-Description: File operations - together, fileops.h and fileops.c contain
-all code involving disk operations. The older header files images.h and
+Description: File operations - together, fileops.h and fileops.c contain
+all code involving disk operations. The older header files images.h and
sounds.h have been incorporated here. The intention is to make it easier to
-port tuxmath to other operating systems, as code to read and write as
-well as paths and file locations may be more OS-dependent.
+port tuxmath to other operating systems, as code to read and write as
+well as paths and file locations may be more OS-dependent.
Author: David Bruce <dbruce at tampabay.rr.com>, (C) 2006
@@ -13,8 +13,8 @@
Copyright: See COPYING file that comes with this distribution (briefly, GNU GPL)
*/
-#ifndef CONFIG_H
-#define CONFIG_H
+#ifndef FILEOPS_H
+#define FILEOPS_H
#include "tuxmath.h"
@@ -235,7 +235,8 @@
int write_user_config_file(void);
int read_high_scores(void);
int append_high_scores(int tableid,int score,char *player_name);
-void set_high_score_path(void);
+void set_high_score_path(void);
+void set_user_data_dir(const char* dirname);
int write_goldstars(void);
/* These functions are used by titlescreen() to assist with the login */
Modified: tuxmath/trunk/src/game.c
===================================================================
--- tuxmath/trunk/src/game.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/game.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -42,8 +42,8 @@
#define FPS 15 /* 15 frames per second */
#define MS_PER_FRAME (1000 / FPS)
-#define CITY_EXPL_START 3 * 5 /* Must be mult. of 5 (number of expl frames) */
-#define ANIM_FRAME_START 4 * 2 /* Must be mult. of 2 (number of tux frames) */
+#define CITY_EXPL_START (3 * 5) /* Must be mult. of 5 (number of expl frames) */
+#define ANIM_FRAME_START (4 * 2) /* Must be mult. of 2 (number of tux frames) */
#define GAMEOVER_COUNTER_START 40
#define LEVEL_START_WAIT_START 20
#define LASER_START 5
@@ -61,12 +61,6 @@
const int SND_IGLOO_SIZZLE = SND_SIZZLE;
const int IMG_CITY_NONE = 0;
-char operchars[4] = {
- "+-*/"
-};
-
-
-
typedef struct comet_type {
int alive;
int expl;
@@ -118,7 +112,7 @@
static float comet_feedback_height;
static float danger_level;
-static int digits[3];
+static int digits[MC_MAX_DIGITS];
static comet_type* comets = NULL;
static city_type* cities = NULL;
@@ -133,8 +127,9 @@
SDL_Surface* current_bkgd()
{ return screen->flags & SDL_FULLSCREEN ? scaled_bkgd : bkgd; }
-static game_message s1, s2, s3, s4, s5;
-static int start_message_chosen = 0;
+static game_message s1, s2, s3, s4, s5;
+static int start_message_chosen = 0;
+
typedef struct {
int x_is_blinking;
@@ -167,7 +162,7 @@
static int check_exit_conditions(void);
static void draw_numbers(const char* str, int x, int y);
-static void game_set_message(game_message *,char *,int x, int y);
+static void game_set_message(game_message *,const char *,int x, int y);
static void game_clear_message(game_message*);
static void game_write_message(const game_message* msg);
static void game_write_messages(void);
@@ -187,7 +182,7 @@
static void game_key_event(SDLKey key);
static void free_on_exit(void);
-static void help_add_comet(int a,int oper,int b,int c);
+static void help_add_comet(const char* formula_str, const char* ans_str);
static int help_renderframe_exit(void);
static void game_recalc_positions(void);
@@ -277,7 +272,7 @@
{
if (!Mix_PlayingMusic())
{
- Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
+ Mix_PlayMusic(musics[MUS_GAME + (rand() % 3)], 0);
}
}
#endif
@@ -291,7 +286,7 @@
// or you leave tuxmath running for 49 days...)
now_time = (last_time+MS_PER_FRAME) - now_time; // this holds the delay
if (now_time > MS_PER_FRAME)
- now_time = MS_PER_FRAME;
+ now_time = MS_PER_FRAME;
SDL_Delay(now_time);
}
}
@@ -380,7 +375,7 @@
now_time = SDL_GetTicks();
if (now_time < last_time + MS_PER_FRAME)
- SDL_Delay(last_time + MS_PER_FRAME - now_time);
+ SDL_Delay(last_time + MS_PER_FRAME - now_time);
}
while (looping);
break;
@@ -424,7 +419,7 @@
now_time = SDL_GetTicks();
if (now_time < last_time + MS_PER_FRAME)
- SDL_Delay(last_time + MS_PER_FRAME - now_time);
+ SDL_Delay(last_time + MS_PER_FRAME - now_time);
}
while (looping);
@@ -464,29 +459,31 @@
else
{
/* return to title() screen: */
-
return game_status;
}
}
-/*
-Set one to four lines of text to display at the game's start. Eventually
-this should stylishly fade out over the first few moments of the game.
+
+/*
+Set one to four lines of text to display at the game's start. Eventually
+this should stylishly fade out over the first few moments of the game.
*/
-void game_set_start_message(const char* m1, const char* m2,
- const char* m3, const char* m4)
-{
- game_set_message(&s1, m1, screen->w / 2 - 40, RES_Y * 0 / 4);
- game_set_message(&s2, m2, screen->w / 2 - 40, RES_Y * 1 / 4);
- game_set_message(&s3, m3, screen->w / 2 - 40, RES_Y * 2 / 4);
- game_set_message(&s4, m4, screen->w / 2 - 40, RES_Y * 3 / 4);
- start_message_chosen = 1;
-}
+void game_set_start_message(const char* m1, const char* m2,
+ const char* m3, const char* m4)
+{
+ game_set_message(&s1, m1, screen->w / 2 - 40, RES_Y * 0 / 4);
+ game_set_message(&s2, m2, screen->w / 2 - 40, RES_Y * 1 / 4);
+ game_set_message(&s3, m3, screen->w / 2 - 40, RES_Y * 2 / 4);
+ game_set_message(&s4, m4, screen->w / 2 - 40, RES_Y * 3 / 4);
+ start_message_chosen = 1;
+}
int game_initialize(void)
{
int i,img;
+
+ tmdprintf("Entering game_initialize()\n");
+
/* Clear window: */
-
SDL_FillRect(screen, NULL, SDL_MapRGB(screen->format, 0, 0, 0));
SDL_Flip(screen);
@@ -495,6 +492,18 @@
SDL_quit_received = 0;
escape_received = 0;
+ /* Start MathCards backend: */
+ /* FIXME may need to move this into tuxmath.c to accomodate option */
+ /* to use MC_StartUsingWrongs() */
+ /* NOTE MC_StartGame() will return 0 if the list length is zero due */
+ /* (for example) to all math operations being deselected */
+ if (!MC_StartGame())
+ {
+ tmdprintf("\nMC_StartGame() failed!");
+ fprintf(stderr, "\nMC_StartGame() failed!");
+ return 0;
+ }
+
/* Allocate memory */
comets = NULL; // set in case allocation fails partway through
cities = NULL;
@@ -505,6 +514,21 @@
printf("Allocation of comets failed");
return 0;
}
+ else {
+ for (i = 0; i < MAX_MAX_COMETS; ++i)
+ {
+ comets[i].flashcard = MC_AllocateFlashcard();
+ if (!MC_FlashCardGood(&comets[i].flashcard) )
+ {
+ //something's wrong
+ printf("Allocation of flashcard %d failed\n", i);
+ for (; i >= 0; --i) //free anything we've already gotten
+ MC_FreeFlashcard(&comets[i].flashcard);
+ return 0;
+ }
+ }
+ }
+
cities = (city_type *) malloc(NUM_CITIES * sizeof(city_type));
if (cities == NULL) {
printf("Allocation of cities failed");
@@ -521,20 +545,7 @@
return 0;
}
- /* Start MathCards backend: */
- /* FIXME may need to move this into tuxmath.c to accomodate option */
- /* to use MC_StartUsingWrongs() */
- /* NOTE MC_StartGame() will return 0 if the list length is zero due */
- /* (for example) to all math operations being deselected */
- if (!MC_StartGame())
- {
-#ifdef TUXMATH_DEBUG
- printf("\nMC_StartGame() failed!");
-#endif
- fprintf(stderr, "\nMC_StartGame() failed!");
- return 0;
- }
-
+
/* Write pre-game info to game summary file: */
if (Opts_SaveSummary())
{
@@ -606,9 +617,7 @@
if (Opts_BonusCometInterval()) {
bonus_comet_counter = Opts_BonusCometInterval() + 1;
-#ifdef TUXMATH_DEBUG
- printf("\nInitializing with bonus_comet_counter = %d\n",bonus_comet_counter);
-#endif
+ tmdprintf("\nInitializing with bonus_comet_counter = %d\n",bonus_comet_counter);
}
extra_life_earned = 0;
cloud.status = EXTRA_LIFE_OFF;
@@ -631,15 +640,15 @@
tux_anim = -1;
tux_anim_frame = 0;
- // Initialize the messages
- if (!start_message_chosen)
- {
- game_clear_message(&s1);
- game_clear_message(&s2);
- game_clear_message(&s3);
- game_clear_message(&s4);
+ // Initialize the messages
+ game_clear_message(&s5);
+ if (!start_message_chosen)
+ {
+ game_clear_message(&s1);
+ game_clear_message(&s2);
+ game_clear_message(&s3);
+ game_clear_message(&s4);
}
- game_clear_message(&s5);
help_controls.x_is_blinking = 0;
help_controls.extra_life_is_blinking = 0;
@@ -730,7 +739,7 @@
// Bring in a comet
speed = 2;
- help_add_comet(2,MC_OPER_ADD,1,3);
+ help_add_comet("2 + 1 = ?", "3");
help_controls.laser_enabled = 1;
level_start_wait = 0;
@@ -773,7 +782,7 @@
return;
game_clear_message(&s5);
- help_add_comet(3,MC_OPER_MULT,3,9);
+ help_add_comet("3 * 3 = ?", "9");
comets[0].y = 2*(screen->h)/3; // start it low down
while (!(comets[0].expl) && !(quit_help = help_renderframe_exit())); // wait 3 secs
if (quit_help)
@@ -798,7 +807,7 @@
return;
game_clear_message(&s3);
- help_add_comet(56,MC_OPER_DIV,8,7);
+ help_add_comet("56 / 8 = ?", "7");
comets[0].y = 2*(screen->h)/3; // start it low down
while (comets[0].alive && !(quit_help = help_renderframe_exit()));
if (quit_help)
@@ -811,7 +820,7 @@
help_controls.laser_enabled = 1;
game_set_message(&s1,_("You can fix the igloos"),left_edge,100);
game_set_message(&s2,_("by stopping bonus comets."),left_edge,135);
- help_add_comet(2,MC_OPER_ADD,2,4);
+ help_add_comet("2 + 2 = ?", "4");
comets[0].bonus = 1;
frame_start = frame;
while (comets[0].alive && (frame-frame_start < 50) && !(quit_help = help_renderframe_exit()));
@@ -883,32 +892,27 @@
return (game_status != GAME_IN_PROGRESS);
}
-void help_add_comet(int a,int oper,int b,int c)
+/* explicitly create a comet with a hardcoded problem */
+void help_add_comet(const char* formula_str, const char* ans_str)
{
- char probstr[MC_FORMULA_LEN];
- char ansstr[MC_ANSWER_LEN];
+// char probstr[MC_FORMULA_LEN];
+// char ansstr[MC_ANSWER_LEN];
comets[0].alive = 1;
comets[0].expl = 0;
- comets[0].answer = c;
+ comets[0].answer = atoi(ans_str);
num_comets_alive = 1;
comets[0].city = 0;
comets[0].x = cities[0].x;
comets[0].y = 0;
comets[0].zapped = 0;
comets[0].bonus = 0;
- comets[0].flashcard.num1 = a;
- comets[0].flashcard.num2 = b;
- comets[0].flashcard.num3 = c;
- comets[0].flashcard.operation = oper;
- comets[0].flashcard.format = MC_FORMAT_ANS_LAST;
- snprintf(probstr,MC_FORMULA_LEN,"%d %c %d = ?",a,operchars[oper],b);
- strncpy(comets[0].flashcard.formula_string,probstr,MC_FORMULA_LEN);
- snprintf(ansstr,MC_ANSWER_LEN,"%d",c);
- strncpy(comets[0].flashcard.answer_string,ansstr,MC_ANSWER_LEN);
+
+ strncpy(comets[0].flashcard.formula_string,formula_str,MC_MaxFormulaSize() );
+ strncpy(comets[0].flashcard.answer_string,ans_str,MC_MaxAnswerSize() );
}
-void game_set_message(game_message *msg,char *txt,int x,int y)
+void game_set_message(game_message *msg,const char *txt,int x,int y)
{
msg->x = x;
msg->y = y;
@@ -935,9 +939,7 @@
else
rect.x = msg->x; // left justified
rect.y = msg->y;
-
SDL_SetAlpha(surf, SDL_SRCALPHA, msg->alpha);
-
SDL_BlitSurface(surf, NULL, screen, &rect);
SDL_FreeSurface(surf);
//SDL_UpdateRect(screen, rect.x, rect.y, rect.w, rect.h);
@@ -996,8 +998,8 @@
picked_comet = (rand() % MAX_COMETS);
if (!(comets[picked_comet].alive &&
- comets[picked_comet].expl < COMET_EXPL_END)
- || comets[picked_comet].y < 80)
+ comets[picked_comet].expl < COMET_EXPL_END)
+ || comets[picked_comet].y < 80)
{
picked_comet = -1;
}
@@ -1006,7 +1008,7 @@
/* found a comet to blow up! */
demo_answer = comets[picked_comet].answer;
if ((rand() % 3) < 1)
- demo_answer--; // sometimes get it wrong on purpose
+ demo_answer--; // sometimes get it wrong on purpose
#ifdef TUXMATH_DEBUG
printf("Demo mode, comet %d attacked with answer %d\n",picked_comet,demo_answer);
@@ -1069,7 +1071,8 @@
void game_handle_answer(void)
{
- int i, num, lowest, lowest_y;
+ int i, j, lowest, lowest_y;
+ char ans[MC_MAX_DIGITS+2]; //extra space for negative, and for final '\0'
Uint32 ctime;
if (!doing_answer)
@@ -1078,15 +1081,40 @@
}
doing_answer = 0;
-
+/*
num = (digits[0] * 100 +
digits[1] * 10 +
digits[2]);
+*/
/* negative answer support DSB */
+
+ ans[0] = '-'; //for math questions only, this is just replaced.
+ for (i = 0; i < MC_MAX_DIGITS - 1 && !digits[i]; ++i); //skip leading 0s
+ for (j = neg_answer_picked ? 1 : 0; i < MC_MAX_DIGITS; ++i, ++j)
+ ans[j] = digits[i] + '0';
+ ans[j] = '\0';
+
+/*
if (neg_answer_picked)
{
- num = -num;
+ ans[0] = '-';
+ for (i = j = 0; i < MC_MAX_DIGITS; ++i)
+ {
+ if (digits[i] == 0)
+ continue;
+ ans[++j] = digits[i] + '0';
+ }
}
+ else
+ {
+ for (i = j = 0; i < MC_MAX_DIGITS; ++i)
+ {
+ if (digits[i] == 0)
+ continue;
+ ans[j++] = digits[i] + '0';
+ }
+ }
+*/
/* Pick the lowest comet which has the right answer: */
/* FIXME: do we want it to prefer bonus comets to regular comets? */
@@ -1095,9 +1123,11 @@
for (i = 0; i < MAX_COMETS; i++)
{
+ mcdprintf("Comparing '%s' with '%s'\n", comets[i].flashcard.answer_string, ans);
if (comets[i].alive &&
comets[i].expl < COMET_EXPL_END &&
- comets[i].answer == num &&
+ //comets[i].answer == num &&
+ 0 == strncmp(comets[i].flashcard.answer_string, ans, MC_MAX_DIGITS+1) &&
comets[i].y > lowest_y)
{
lowest = i;
@@ -1158,9 +1188,10 @@
/* [ add = 25, sub = 50, mul = 75, div = 100 ] */
/* [ the higher the better ] */
- add_score(((25 * (comets[lowest].flashcard.operation + 1)) *
- (screen->h - comets[lowest].y + 1)) /
- screen->h);
+ /* FIXME looks like it might score a bit differently based on screen mode? */
+ add_score(25 * comets[lowest].flashcard.difficulty *
+ (screen->h - comets[lowest].y + 1) /
+ screen->h);
}
else
{
@@ -1180,9 +1211,8 @@
}
/* Clear digits: */
- digits[0] = 0;
- digits[1] = 0;
- digits[2] = 0;
+ for (i = 0; i < MC_MAX_DIGITS; ++i)
+ digits[i] = 0;
neg_answer_picked = 0;
}
@@ -1197,7 +1227,7 @@
s3.alpha -= SDL_ALPHA_OPAQUE / LEVEL_START_WAIT_START;
s4.alpha -= SDL_ALPHA_OPAQUE / LEVEL_START_WAIT_START;
tmdprintf("alpha = %d\n", s1.alpha);
-
+
level_start_wait--;
if (level_start_wait > LEVEL_START_WAIT_START / 4)
tux_img = IMG_TUX_RELAX1;
@@ -1278,8 +1308,8 @@
/* Make bonus comet move faster at chosen ratio: */
if (comets[i].bonus)
{
- comets[i].y += speed * Opts_BonusSpeedRatio() *
- city_expl_height / (RES_Y - images[IMG_CITY_BLUE]->h);
+ comets[i].y += speed * Opts_BonusSpeedRatio() *
+ city_expl_height / (RES_Y - images[IMG_CITY_BLUE]->h);
}
else /* Regular comet: */
{
@@ -1289,61 +1319,61 @@
/* Does it threaten a city? */
if (comets[i].y > 3 * screen->h / 4)
- cities[this_city].threatened = 1;
+ cities[this_city].threatened = 1;
/* Did it hit a city? */
if (comets[i].y >= city_expl_height &&
- comets[i].expl < COMET_EXPL_END)
+ comets[i].expl < COMET_EXPL_END)
{
/* Tell MathCards about it - question not answered correctly: */
MC_NotAnsweredCorrectly(&(comets[i].flashcard));
- /* Store the time the question was present on screen (do this */
- /* in a way that avoids storing it if the time wrapped around */
- ctime = SDL_GetTicks();
- if (ctime > comets[i].time_started) {
- MC_AddTimeToList((float)(ctime - comets[i].time_started)/1000);
- }
+ /* Store the time the question was present on screen (do this */
+ /* in a way that avoids storing it if the time wrapped around */
+ ctime = SDL_GetTicks();
+ if (ctime > comets[i].time_started) {
+ MC_AddTimeToList((float)(ctime - comets[i].time_started)/1000);
+ }
/* Record data for speed feedback */
- /* Do this only for cities that are alive; dead cities */
+ /* Do this only for cities that are alive; dead cities */
/* might not get much protection from the player */
- if (Opts_UseFeedback() && cities[this_city].hits_left) {
- comet_feedback_number++;
+ if (Opts_UseFeedback() && cities[this_city].hits_left) {
+ comet_feedback_number++;
comet_feedback_height += 1.0 + Opts_CityExplHandicap();
#ifdef FEEDBACK_DEBUG
- printf("Added comet feedback with height %g\n",
+ printf("Added comet feedback with height %g\n",
1.0 + Opts_CityExplHandicap());
#endif
- }
+ }
/* Disable shields/destroy city/create steam cloud: */
if (cities[this_city].hits_left)
- {
- cities[this_city].status = CITY_EXPLODING;
- if (Opts_UseIgloos()) {
- playsound(SND_IGLOO_SIZZLE);
- cities[this_city].counter = IGLOO_SWITCH_START;
- steam[this_city].status = STEAM_ON;
- steam[this_city].counter = STEAM_START;
- }
- else {
- if (cities[comets[i].city].hits_left == 2) {
- playsound(SND_SHIELDSDOWN);
- cities[this_city].counter = 1; /* Will act immediately */
- }
- else {
- playsound(SND_EXPLOSION);
- cities[this_city].counter = CITY_EXPL_START;
- }
- }
- cities[this_city].hits_left--;
- }
+ {
+ cities[this_city].status = CITY_EXPLODING;
+ if (Opts_UseIgloos()) {
+ playsound(SND_IGLOO_SIZZLE);
+ cities[this_city].counter = IGLOO_SWITCH_START;
+ steam[this_city].status = STEAM_ON;
+ steam[this_city].counter = STEAM_START;
+ }
+ else {
+ if (cities[comets[i].city].hits_left == 2) {
+ playsound(SND_SHIELDSDOWN);
+ cities[this_city].counter = 1; /* Will act immediately */
+ }
+ else {
+ playsound(SND_EXPLOSION);
+ cities[this_city].counter = CITY_EXPL_START;
+ }
+ }
+ cities[this_city].hits_left--;
+ }
- /* If this was a bonus comet, restart the counter */
- if (comets[i].bonus)
- bonus_comet_counter = Opts_BonusCometInterval()+1;
+ /* If this was a bonus comet, restart the counter */
+ if (comets[i].bonus)
+ bonus_comet_counter = Opts_BonusCometInterval()+1;
/* If slow_after_wrong selected, set flag to go back to starting speed and */
/* number of attacking comets: */
@@ -1364,22 +1394,22 @@
if (comets[i].expl >= COMET_EXPL_END)
{
comets[i].expl--;
- if (comets[i].expl < COMET_EXPL_END) {
- comets[i].alive = 0;
- if (bonus_comet_counter > 1 && comets[i].zapped) {
- bonus_comet_counter--;
+ if (comets[i].expl < COMET_EXPL_END) {
+ comets[i].alive = 0;
+ if (bonus_comet_counter > 1 && comets[i].zapped) {
+ bonus_comet_counter--;
#ifdef TUXMATH_DEBUG
- printf("\nbonus_comet_counter is now %d\n",bonus_comet_counter);
+ printf("\nbonus_comet_counter is now %d\n",bonus_comet_counter);
#endif
- }
- if (comets[i].bonus && comets[i].zapped) {
- playsound(SND_EXTRA_LIFE);
- extra_life_earned = 1;
+ }
+ if (comets[i].bonus && comets[i].zapped) {
+ playsound(SND_EXTRA_LIFE);
+ extra_life_earned = 1;
#ifdef TUXMATH_DEBUG
- printf("\nExtra life earned!");
+ printf("\nExtra life earned!");
#endif
- }
- }
+ }
+ }
}
}
}
@@ -1403,9 +1433,9 @@
{
if (num_comets_alive == 0)
{
- if (!check_extra_life()) {
- /* Time for the next wave! */
- wave++;
+ if (!check_extra_life()) {
+ /* Time for the next wave! */
+ wave++;
reset_level();
}
}
@@ -1435,61 +1465,61 @@
{
cities[i].counter--;
if (cities[i].counter == 0) {
- if (cities[i].hits_left)
- cities[i].status = CITY_PRESENT;
- else {
- if (Opts_UseIgloos()) {
- cities[i].status = CITY_EVAPORATING;
- cities[i].counter = EVAPORATING_COUNTER_START;
- cities[i].img = IMG_IGLOO_MELTED1;
- } else {
- cities[i].status = CITY_GONE;
- cities[i].img = IMG_CITY_NONE;
- }
- }
+ if (cities[i].hits_left)
+ cities[i].status = CITY_PRESENT;
+ else {
+ if (Opts_UseIgloos()) {
+ cities[i].status = CITY_EVAPORATING;
+ cities[i].counter = EVAPORATING_COUNTER_START;
+ cities[i].img = IMG_IGLOO_MELTED1;
+ } else {
+ cities[i].status = CITY_GONE;
+ cities[i].img = IMG_CITY_NONE;
+ }
+ }
}
}
/* Choose the correct city/igloo image */
if (Opts_UseIgloos()) {
if (cities[i].status == CITY_EVAPORATING) {
- /* Handle the evaporation animation */
- cities[i].layer = 0; /* these have to be drawn below the penguin */
- cities[i].counter--;
- if (cities[i].counter == 0) {
- cities[i].img--;
- if (cities[i].img < IMG_IGLOO_MELTED3) {
- cities[i].img = IMG_CITY_NONE;
- cities[i].status = CITY_GONE;
- }
- else
- cities[i].counter = EVAPORATING_COUNTER_START;
- }
- } else {
- if (cities[i].status != CITY_GONE) {
- cities[i].layer = 1; /* these have to be drawn above the penguin */
- cities[i].img = IMG_IGLOO_MELTED1 + cities[i].hits_left;
- /* If we're in the middle of an "explosion," don't switch to the
- new igloo. Note the steam may have a different counter than
- the igloo on this matter; the switch is designed to occur
- halfway through the steam cloud. */
- if (cities[i].status == CITY_EXPLODING)
- cities[i].img++;
- }
+ /* Handle the evaporation animation */
+ cities[i].layer = 0; /* these have to be drawn below the penguin */
+ cities[i].counter--;
+ if (cities[i].counter == 0) {
+ cities[i].img--;
+ if (cities[i].img < IMG_IGLOO_MELTED3) {
+ cities[i].img = IMG_CITY_NONE;
+ cities[i].status = CITY_GONE;
+ }
+ else
+ cities[i].counter = EVAPORATING_COUNTER_START;
+ }
+ } else {
+ if (cities[i].status != CITY_GONE) {
+ cities[i].layer = 1; /* these have to be drawn above the penguin */
+ cities[i].img = IMG_IGLOO_MELTED1 + cities[i].hits_left;
+ /* If we're in the middle of an "explosion," don't switch to the
+ new igloo. Note the steam may have a different counter than
+ the igloo on this matter; the switch is designed to occur
+ halfway through the steam cloud. */
+ if (cities[i].status == CITY_EXPLODING)
+ cities[i].img++;
+ }
}
}
else {
/* We're using the original "city" graphics */
cities[i].layer = 0; /* No layering needed */
if (cities[i].hits_left)
- cities[i].img = IMG_CITY_BLUE;
+ cities[i].img = IMG_CITY_BLUE;
else if (cities[i].status == CITY_EXPLODING)
- cities[i].img = (IMG_CITY_BLUE_EXPL5 - (cities[i].counter / (CITY_EXPL_START / 5)));
+ cities[i].img = (IMG_CITY_BLUE_EXPL5 - (cities[i].counter / (CITY_EXPL_START / 5)));
else
- cities[i].img = IMG_CITY_BLUE_DEAD;
+ cities[i].img = IMG_CITY_BLUE_DEAD;
/* Change image to appropriate color: */
cities[i].img = cities[i].img + ((wave % MAX_CITY_COLORS) *
- (IMG_CITY_GREEN - IMG_CITY_BLUE));
+ (IMG_CITY_GREEN - IMG_CITY_BLUE));
}
}
@@ -1512,26 +1542,26 @@
penguins[i].status = PENGUIN_DUCKING;
else if (!cities[i].threatened && penguins[i].status == PENGUIN_DUCKING) {
if (cities[i].hits_left == 2)
- penguins[i].status = PENGUIN_HAPPY;
+ penguins[i].status = PENGUIN_HAPPY;
else
- penguins[i].status = PENGUIN_GRUMPY;
+ penguins[i].status = PENGUIN_GRUMPY;
}
switch (penguins[i].status) {
case PENGUIN_HAPPY:
penguins[i].img = IMG_PENGUIN_FLAPDOWN;
if (rand() % FLAPPING_INTERVAL == 0) {
- penguins[i].status = PENGUIN_FLAPPING;
- penguins[i].counter = FLAPPING_START;
+ penguins[i].status = PENGUIN_FLAPPING;
+ penguins[i].counter = FLAPPING_START;
}
break;
case PENGUIN_FLAPPING:
if (penguins[i].counter % 4 >= 2)
- penguins[i].img = IMG_PENGUIN_FLAPUP;
+ penguins[i].img = IMG_PENGUIN_FLAPUP;
else
- penguins[i].img = IMG_PENGUIN_FLAPDOWN;
+ penguins[i].img = IMG_PENGUIN_FLAPDOWN;
penguins[i].counter--;
if (penguins[i].counter == 0)
- penguins[i].status = PENGUIN_HAPPY;
+ penguins[i].status = PENGUIN_HAPPY;
break;
case PENGUIN_DUCKING:
penguins[i].img = IMG_PENGUIN_INCOMING;
@@ -1539,59 +1569,59 @@
case PENGUIN_GRUMPY:
penguins[i].img = IMG_PENGUIN_GRUMPY;
if (rand() % FLAPPING_INTERVAL == 0) {
- penguins[i].status = PENGUIN_WORRIED;
- penguins[i].counter = FLAPPING_START;
+ penguins[i].status = PENGUIN_WORRIED;
+ penguins[i].counter = FLAPPING_START;
}
break;
case PENGUIN_WORRIED:
penguins[i].img = IMG_PENGUIN_WORRIED;
penguins[i].counter--;
if (penguins[i].counter == 0)
- penguins[i].status = PENGUIN_GRUMPY;
+ penguins[i].status = PENGUIN_GRUMPY;
break;
case PENGUIN_STANDING_UP:
penguins[i].img = IMG_PENGUIN_STANDING_UP;
penguins[i].counter--;
if (penguins[i].counter == 0)
- penguins[i].status = PENGUIN_WALKING_OFF;
+ penguins[i].status = PENGUIN_WALKING_OFF;
break;
case PENGUIN_SITTING_DOWN:
penguins[i].img = IMG_PENGUIN_SITTING_DOWN;
penguins[i].counter--;
if (penguins[i].counter == 0) {
- penguins[i].status = PENGUIN_FLAPPING;
- penguins[i].counter = FLAPPING_START;
+ penguins[i].status = PENGUIN_FLAPPING;
+ penguins[i].counter = FLAPPING_START;
}
break;
case PENGUIN_WALKING_ON:
walk_counter = (penguins[i].counter % 8)/2;
if (walk_counter == 3)
- walk_counter = 1;
+ walk_counter = 1;
penguins[i].img = IMG_PENGUIN_WALK_ON1 + walk_counter;
penguins[i].counter++;
direction = 2*(i < NUM_CITIES/2)-1; /* +1 for walk right, -1 for left */
penguins[i].x += direction*PENGUIN_WALK_SPEED;
if (direction*penguins[i].x >= direction*cities[i].x) {
- penguins[i].status = PENGUIN_SITTING_DOWN;
- penguins[i].counter = STANDING_COUNTER_START;
- penguins[i].x = cities[i].x;
+ penguins[i].status = PENGUIN_SITTING_DOWN;
+ penguins[i].counter = STANDING_COUNTER_START;
+ penguins[i].x = cities[i].x;
}
penguins[i].layer = 3; /* Stand in front of steam */
break;
case PENGUIN_WALKING_OFF:
walk_counter = (penguins[i].counter % 8)/2;
if (walk_counter == 3)
- walk_counter = 1;
+ walk_counter = 1;
penguins[i].img = IMG_PENGUIN_WALK_OFF1 + walk_counter;
penguins[i].counter++;
direction = 1-2*(i < NUM_CITIES/2);
penguins[i].x += direction*PENGUIN_WALK_SPEED;
if (direction < 0) {
- if (penguins[i].x + images[IMG_PENGUIN_WALK_OFF1]->w/2 < 0)
- penguins[i].status = PENGUIN_OFFSCREEN;
+ if (penguins[i].x + images[IMG_PENGUIN_WALK_OFF1]->w/2 < 0)
+ penguins[i].status = PENGUIN_OFFSCREEN;
} else {
- if (penguins[i].x - images[IMG_PENGUIN_WALK_OFF1]->w/2 > screen->w)
- penguins[i].status = PENGUIN_OFFSCREEN;
+ if (penguins[i].x - images[IMG_PENGUIN_WALK_OFF1]->w/2 > screen->w)
+ penguins[i].status = PENGUIN_OFFSCREEN;
}
penguins[i].layer = 3;
break;
@@ -1612,16 +1642,16 @@
if (steam[i].counter) {
steam[i].counter--;
if (!steam[i].counter) {
- steam[i].status = STEAM_OFF;
- if (cloud.status != EXTRA_LIFE_ON || cloud.city != i) {
- /* The penguin was ducking, now we can stop */
+ steam[i].status = STEAM_OFF;
+ if (cloud.status != EXTRA_LIFE_ON || cloud.city != i) {
+ /* The penguin was ducking, now we can stop */
if (cities[i].hits_left)
penguins[i].status = PENGUIN_GRUMPY;
else {
penguins[i].status = PENGUIN_STANDING_UP;
- penguins[i].counter = STANDING_COUNTER_START;
- }
- }
+ penguins[i].counter = STANDING_COUNTER_START;
+ }
+ }
}
}
if (steam[i].status == STEAM_OFF)
@@ -1650,8 +1680,8 @@
fewest_index = -1;
for (i = 0; i < NUM_CITIES; i++) {
if (cities[i].hits_left < fewest_hits_left) {
- fewest_hits_left = cities[i].hits_left;
- fewest_index = i;
+ fewest_hits_left = cities[i].hits_left;
+ fewest_index = i;
}
}
if (fewest_hits_left == 2)
@@ -1708,28 +1738,28 @@
// Cloud is "parked," handle the snowfall and igloo rebuilding
cities[cloud.city].status = CITY_REBUILDING;
igloo_top = screen->h - igloo_vertical_offset
- - images[IMG_IGLOO_INTACT]->h;
+ - images[IMG_IGLOO_INTACT]->h;
for (i = 0, num_below_igloo = 0; i < NUM_SNOWFLAKES; i++) {
- cloud.snowflake_y[i] += SNOWFLAKE_SPEED;
- if (cloud.snowflake_y[i] > igloo_top)
- num_below_igloo++;
+ cloud.snowflake_y[i] += SNOWFLAKE_SPEED;
+ if (cloud.snowflake_y[i] > igloo_top)
+ num_below_igloo++;
}
if (cloud.snowflake_y[NUM_SNOWFLAKES-1] > igloo_top) {
- cities[cloud.city].hits_left = 2;
- cities[cloud.city].img = IMG_IGLOO_INTACT; // completely rebuilt
+ cities[cloud.city].hits_left = 2;
+ cities[cloud.city].img = IMG_IGLOO_INTACT; // completely rebuilt
} else if (cities[cloud.city].hits_left == 0) {
- // We're going to draw one of the blended igloos
- // FIXME: It's a hack to encode a blended igloo with a negative number!
- penguins[cloud.city].layer = 0;
- cities[cloud.city].layer = 1;
- if (num_below_igloo < 3)
- num_below_igloo = 0; // Don't show progress until a few have fallen
- cities[cloud.city].img = -((float) (num_below_igloo)/NUM_SNOWFLAKES) * NUM_BLENDED_IGLOOS;
+ // We're going to draw one of the blended igloos
+ // FIXME: It's a hack to encode a blended igloo with a negative number!
+ penguins[cloud.city].layer = 0;
+ cities[cloud.city].layer = 1;
+ if (num_below_igloo < 3)
+ num_below_igloo = 0; // Don't show progress until a few have fallen
+ cities[cloud.city].img = -((float) (num_below_igloo)/NUM_SNOWFLAKES) * NUM_BLENDED_IGLOOS;
}
if (cloud.snowflake_y[NUM_SNOWFLAKES-1] > screen->h - igloo_vertical_offset) {
- /* exit rebuilding when last snowflake at igloo bottom */
- cloud.status = EXTRA_LIFE_OFF;
- cities[cloud.city].status = CITY_PRESENT;
+ /* exit rebuilding when last snowflake at igloo bottom */
+ cloud.status = EXTRA_LIFE_OFF;
+ cities[cloud.city].status = CITY_PRESENT;
}
}
}
@@ -1756,9 +1786,9 @@
if (laser.alive)
{
draw_line(laser.x1, laser.y1, laser.x2, laser.y2,
- 255 / ((LASER_START + 1) - laser.alive),
- 192 / ((LASER_START + 1) - laser.alive),
- 64);
+ 255 / ((LASER_START + 1) - laser.alive),
+ 192 / ((LASER_START + 1) - laser.alive),
+ 64);
}
/* Draw numeric keypad: */
@@ -1766,7 +1796,7 @@
{
/* pick image to draw: */
int keypad_image;
- if (MC_AllowNegatives())
+ if (MC_GetOpt(ALLOW_NEGATIVES) )
{
/* draw regular keypad */
keypad_image = IMG_KEYPAD;
@@ -1846,7 +1876,7 @@
void game_draw_comets(void)
{
- int i,j, img, max_layer,offset;
+ int i, img;
SDL_Rect dest;
char* comet_str;
@@ -1860,7 +1890,7 @@
/* Decide which image to display: */
img = IMG_COMET1 + ((frame + i) % 3);
/* Display the formula (flashing, in the bottom half
- of the screen) */
+ of the screen) */
if (comets[i].y < screen->h / 2 || frame % 8 < 6)
{
comet_str = comets[i].flashcard.formula_string;
@@ -1900,7 +1930,7 @@
/* Decide which image to display: */
img = IMG_COMET1 + ((frame + i) % 3);
/* Display the formula (flashing, in the bottom half
- of the screen) */
+ of the screen) */
if (comets[i].y < screen->h / 2 || frame % 8 < 6)
{
comet_str = comets[i].flashcard.formula_string;
@@ -1949,84 +1979,84 @@
max_layer = 0;
do {
for (i = 0; i < NUM_CITIES; i++) {
- if (cities[i].status != CITY_GONE && cities[i].layer > max_layer)
- max_layer = cities[i].layer;
- if (penguins[i].status != PENGUIN_OFFSCREEN && penguins[i].layer > max_layer)
- max_layer = penguins[i].layer;
- if (steam[i].status == STEAM_ON && steam[i].layer > max_layer)
- max_layer = steam[i].layer;
- if (cities[i].layer == current_layer &&
- cities[i].img != IMG_CITY_NONE) {
- // Handle the blended igloo images, which are encoded
- // (FIXME) with a negative image number
- if (cities[i].img <= 0)
- this_image = blended_igloos[-cities[i].img];
- else
- this_image = images[cities[i].img];
- //this_image = blended_igloos[frame % NUM_BLENDED_IGLOOS];
- dest.x = cities[i].x - (this_image->w / 2);
- dest.y = (screen->h) - (this_image->h) - igloo_vertical_offset;
- if (cities[i].img == IMG_IGLOO_MELTED3 ||
- cities[i].img == IMG_IGLOO_MELTED2)
- dest.y -= (images[IMG_IGLOO_MELTED1]->h - this_image->h)/2;
- dest.w = (this_image->w);
- dest.h = (this_image->h);
- SDL_BlitSurface(this_image, NULL, screen, &dest);
- }
- if (penguins[i].layer == current_layer &&
- penguins[i].status != PENGUIN_OFFSCREEN) {
- this_image = images[penguins[i].img];
- if (penguins[i].status == PENGUIN_WALKING_OFF ||
- penguins[i].status == PENGUIN_WALKING_ON) {
- /* With walking penguins, we have to use flipped images
- when it's walking left. The other issue is that the
- images are of different widths, so aligning on the
- center produces weird forward-backward walking. The
- reliable way is the align them all on the tip of the
- beak (the right border of the unflipped image) */
- dest.x = penguins[i].x - (this_image->w / 2);
- dest.y = (screen->h) - (this_image->h);
- if ((i<NUM_CITIES/2 && penguins[i].status==PENGUIN_WALKING_OFF) ||
- (i>=NUM_CITIES/2 && penguins[i].status==PENGUIN_WALKING_ON)) {
- /* walking left */
- this_image = flipped_images[flipped_img_lookup[penguins[i].img]];
- dest.x = penguins[i].x - images[IMG_PENGUIN_WALK_OFF2]->w/2;
- } else
- dest.x = penguins[i].x - this_image->w
- + images[IMG_PENGUIN_WALK_OFF2]->w/2; /* walking right */
- }
- else {
- dest.x = penguins[i].x - (this_image->w / 2);
- dest.y = (screen->h) - (5*(this_image->h))/4 - igloo_vertical_offset;
- }
- dest.w = (this_image->w);
- dest.h = (this_image->h);
- SDL_BlitSurface(this_image, NULL, screen, &dest);
- }
- if (steam[i].layer == current_layer &&
- steam[i].status == STEAM_ON) {
- this_image = images[steam[i].img];
- dest.x = cities[i].x - (this_image->w / 2);
- dest.y = (screen->h) - this_image->h - ((4 * images[IMG_IGLOO_INTACT]->h) / 7);
- dest.w = (this_image->w);
- dest.h = (this_image->h);
- SDL_BlitSurface(this_image, NULL, screen, &dest);
- }
+ if (cities[i].status != CITY_GONE && cities[i].layer > max_layer)
+ max_layer = cities[i].layer;
+ if (penguins[i].status != PENGUIN_OFFSCREEN && penguins[i].layer > max_layer)
+ max_layer = penguins[i].layer;
+ if (steam[i].status == STEAM_ON && steam[i].layer > max_layer)
+ max_layer = steam[i].layer;
+ if (cities[i].layer == current_layer &&
+ cities[i].img != IMG_CITY_NONE) {
+ // Handle the blended igloo images, which are encoded
+ // (FIXME) with a negative image number
+ if (cities[i].img <= 0)
+ this_image = blended_igloos[-cities[i].img];
+ else
+ this_image = images[cities[i].img];
+ //this_image = blended_igloos[frame % NUM_BLENDED_IGLOOS];
+ dest.x = cities[i].x - (this_image->w / 2);
+ dest.y = (screen->h) - (this_image->h) - igloo_vertical_offset;
+ if (cities[i].img == IMG_IGLOO_MELTED3 ||
+ cities[i].img == IMG_IGLOO_MELTED2)
+ dest.y -= (images[IMG_IGLOO_MELTED1]->h - this_image->h)/2;
+ dest.w = (this_image->w);
+ dest.h = (this_image->h);
+ SDL_BlitSurface(this_image, NULL, screen, &dest);
+ }
+ if (penguins[i].layer == current_layer &&
+ penguins[i].status != PENGUIN_OFFSCREEN) {
+ this_image = images[penguins[i].img];
+ if (penguins[i].status == PENGUIN_WALKING_OFF ||
+ penguins[i].status == PENGUIN_WALKING_ON) {
+ /* With walking penguins, we have to use flipped images
+ when it's walking left. The other issue is that the
+ images are of different widths, so aligning on the
+ center produces weird forward-backward walking. The
+ reliable way is the align them all on the tip of the
+ beak (the right border of the unflipped image) */
+ dest.x = penguins[i].x - (this_image->w / 2);
+ dest.y = (screen->h) - (this_image->h);
+ if ((i<NUM_CITIES/2 && penguins[i].status==PENGUIN_WALKING_OFF) ||
+ (i>=NUM_CITIES/2 && penguins[i].status==PENGUIN_WALKING_ON)) {
+ /* walking left */
+ this_image = flipped_images[flipped_img_lookup[penguins[i].img]];
+ dest.x = penguins[i].x - images[IMG_PENGUIN_WALK_OFF2]->w/2;
+ } else
+ dest.x = penguins[i].x - this_image->w
+ + images[IMG_PENGUIN_WALK_OFF2]->w/2; /* walking right */
+ }
+ else {
+ dest.x = penguins[i].x - (this_image->w / 2);
+ dest.y = (screen->h) - (5*(this_image->h))/4 - igloo_vertical_offset;
+ }
+ dest.w = (this_image->w);
+ dest.h = (this_image->h);
+ SDL_BlitSurface(this_image, NULL, screen, &dest);
+ }
+ if (steam[i].layer == current_layer &&
+ steam[i].status == STEAM_ON) {
+ this_image = images[steam[i].img];
+ dest.x = cities[i].x - (this_image->w / 2);
+ dest.y = (screen->h) - this_image->h - ((4 * images[IMG_IGLOO_INTACT]->h) / 7);
+ dest.w = (this_image->w);
+ dest.h = (this_image->h);
+ SDL_BlitSurface(this_image, NULL, screen, &dest);
+ }
}
current_layer++;
} while (current_layer <= max_layer);
if (cloud.status == EXTRA_LIFE_ON) {
/* Render cloud & snowflakes */
for (i = 0; i < NUM_SNOWFLAKES; i++) {
- if (cloud.snowflake_y[i] > cloud.y &&
- cloud.snowflake_y[i] < screen->h - igloo_vertical_offset) {
- this_image = images[IMG_SNOW1+cloud.snowflake_size[i]];
- dest.x = cloud.snowflake_x[i] - this_image->w/2 + cloud.x;
- dest.y = cloud.snowflake_y[i] - this_image->h/2;
- dest.w = this_image->w;
- dest.h = this_image->h;
- SDL_BlitSurface(this_image, NULL, screen, &dest);
- }
+ if (cloud.snowflake_y[i] > cloud.y &&
+ cloud.snowflake_y[i] < screen->h - igloo_vertical_offset) {
+ this_image = images[IMG_SNOW1+cloud.snowflake_size[i]];
+ dest.x = cloud.snowflake_x[i] - this_image->w/2 + cloud.x;
+ dest.y = cloud.snowflake_y[i] - this_image->h/2;
+ dest.w = this_image->w;
+ dest.h = this_image->h;
+ SDL_BlitSurface(this_image, NULL, screen, &dest);
+ }
}
this_image = images[IMG_CLOUD];
dest.x = cloud.x - this_image->w/2;
@@ -2049,19 +2079,19 @@
/* Draw sheilds: */
if (cities[i].hits_left > 1) {
- for (j = (frame % 3); j < images[IMG_SHIELDS]->h; j = j + 3) {
- src.x = 0;
- src.y = j;
- src.w = images[IMG_SHIELDS]->w;
- src.h = 1;
+ for (j = (frame % 3); j < images[IMG_SHIELDS]->h; j = j + 3) {
+ src.x = 0;
+ src.y = j;
+ src.w = images[IMG_SHIELDS]->w;
+ src.h = 1;
- dest.x = cities[i].x - (images[IMG_SHIELDS]->w / 2);
- dest.y = (screen->h) - (images[IMG_SHIELDS]->h) + j;
- dest.w = src.w;
- dest.h = src.h;
+ dest.x = cities[i].x - (images[IMG_SHIELDS]->w / 2);
+ dest.y = (screen->h) - (images[IMG_SHIELDS]->h) + j;
+ dest.w = src.w;
+ dest.h = src.h;
- SDL_BlitSurface(images[IMG_SHIELDS], &src, screen, &dest);
- }
+ SDL_BlitSurface(images[IMG_SHIELDS], &src, screen, &dest);
+ }
}
}
}
@@ -2087,7 +2117,7 @@
/* If we are playing through a defined list of questions */
/* without "recycling", display number of remaining questions: */
- if (MC_PlayThroughList())
+ if (MC_GetOpt(PLAY_THROUGH_LIST) )
{
draw_question_counter();
}
@@ -2105,7 +2135,7 @@
dest.y = images[IMG_EXTRA_LIFE]->h/4;
dest.h = images[IMG_EXTRA_LIFE]->h/2;
dest.w = ((Opts_BonusCometInterval() + 1 - bonus_comet_counter)
- * images[IMG_EXTRA_LIFE]->w) / Opts_BonusCometInterval();
+ * images[IMG_EXTRA_LIFE]->w) / Opts_BonusCometInterval();
SDL_FillRect(screen, &dest, SDL_MapRGB(screen->format, 0, 255, 0));
}
@@ -2127,7 +2157,7 @@
/* Draw "score" label: */
dest.x = (screen->w - ((images[IMG_NUMBERS]->w / 10) * 7) -
- images[IMG_SCORE]->w -
+ images[IMG_SCORE]->w -
images[IMG_STOP]->w - 5);
dest.y = 0;
dest.w = images[IMG_SCORE]->w;
@@ -2281,23 +2311,16 @@
}
num_comets_alive = 0;
- /* Clear LED digits: */
+ /* Clear LED F: */
- digits[0] = 0;
- digits[1] = 0;
- digits[2] = 0;
+ for (i = 0; i < MC_MAX_DIGITS; ++i)
+ digits[i] = 0;
neg_answer_picked = 0;
/* Load random background image, but ensure it's different from this one: */
for (i = last_bkgd; i == last_bkgd; i = rand() % NUM_BKGDS);
-// do
-// {
-// /* Don't pick the same one as last time... */
-// i = rand() % NUM_BKGDS;
-// }
-// while (i == last_bkgd);
last_bkgd = i;
@@ -2322,10 +2345,10 @@
if (bkgd == NULL || scaled_bkgd == NULL)
{
fprintf(stderr,
- "\nWarning: Could not load background image:\n"
- "%s\n"
- "The Simple DirectMedia error that ocurred was: %s\n",
- fname, SDL_GetError());
+ "\nWarning: Could not load background image:\n"
+ "%s\n"
+ "The Simple DirectMedia error that ocurred was: %s\n",
+ fname, SDL_GetError());
Opts_SetUseBkgd(0);
}
}
@@ -2362,70 +2385,70 @@
if (use_feedback)
{
- #ifdef FEEDBACK_DEBUG
- printf("Evaluating feedback...\n old danger level = %g,",danger_level);
+ #ifdef FEEDBACK_DEBUG
+ printf("Evaluating feedback...\n old danger level = %g,",danger_level);
#endif
/* Update our danger level, i.e., the target height */
- danger_level = 1 - (1-danger_level) /
- Opts_DangerLevelSpeedup();
- if (danger_level > Opts_DangerLevelMax())
- danger_level = Opts_DangerLevelMax();
+ danger_level = 1 - (1-danger_level) /
+ Opts_DangerLevelSpeedup();
+ if (danger_level > Opts_DangerLevelMax())
+ danger_level = Opts_DangerLevelMax();
- #ifdef FEEDBACK_DEBUG
- printf(" new danger level = %g.\n",danger_level);
- #endif
+ #ifdef FEEDBACK_DEBUG
+ printf(" new danger level = %g.\n",danger_level);
+ #endif
- /* Check to see whether we have any feedback data. If not, skip it. */
- if (comet_feedback_number == 0)
+ /* Check to see whether we have any feedback data. If not, skip it. */
+ if (comet_feedback_number == 0)
{
- use_feedback = 0; /* No comets above living cities, skip feedback */
+ use_feedback = 0; /* No comets above living cities, skip feedback */
- #ifdef FEEDBACK_DEBUG
- printf("No feedback data available, aborting.\n\n");
- #endif
- }
- else
+ #ifdef FEEDBACK_DEBUG
+ printf("No feedback data available, aborting.\n\n");
+ #endif
+ }
+ else
{
- /* Compute the average height of comet destruction. */
- comet_avg_height = comet_feedback_height/comet_feedback_number;
+ /* Compute the average height of comet destruction. */
+ comet_avg_height = comet_feedback_height/comet_feedback_number;
- /* Determine how this average height compares with target. */
- height_differential = comet_avg_height - danger_level;
+ /* Determine how this average height compares with target. */
+ height_differential = comet_avg_height - danger_level;
- /* Set the speed so that we move halfway towards the target */
- /* height. That makes the changes a bit more conservative. */
+ /* Set the speed so that we move halfway towards the target */
+ /* height. That makes the changes a bit more conservative. */
- #ifdef FEEDBACK_DEBUG
- printf(" comet average height = %g, height differential = %g.\n",
+ #ifdef FEEDBACK_DEBUG
+ printf(" comet average height = %g, height differential = %g.\n",
comet_avg_height, height_differential);
- printf(" old speed = %g,",speed);
- #endif
+ printf(" old speed = %g,",speed);
+ #endif
- speed *= (1 - height_differential/danger_level/2);
+ speed *= (1 - height_differential/danger_level/2);
- /* Enforce bounds on speed */
- if (speed < MINIMUM_SPEED)
- speed = MINIMUM_SPEED;
- if (speed > Opts_MaxSpeed())
- speed = Opts_MaxSpeed();
+ /* Enforce bounds on speed */
+ if (speed < MINIMUM_SPEED)
+ speed = MINIMUM_SPEED;
+ if (speed > Opts_MaxSpeed())
+ speed = Opts_MaxSpeed();
- #ifdef FEEDBACK_DEBUG
- printf(" new speed = %g.\n",speed);
- printf("Feedback evaluation complete.\n\n");
- #endif
- }
+ #ifdef FEEDBACK_DEBUG
+ printf(" new speed = %g.\n",speed);
+ printf("Feedback evaluation complete.\n\n");
+ #endif
+ }
}
if (!use_feedback)
{
/* This is not an "else" because we might skip feedback */
- /* when comet_feedback_number == 0 */
- speed = speed * Opts_SpeedupFactor();
- if (speed > Opts_MaxSpeed())
- {
- speed = Opts_MaxSpeed();
- }
+ /* when comet_feedback_number == 0 */
+ speed = speed * Opts_SpeedupFactor();
+ if (speed > Opts_MaxSpeed())
+ {
+ speed = Opts_MaxSpeed();
+ }
}
}
}
@@ -2484,32 +2507,33 @@
/* If we make it to here, create a new comet! */
- /* The answer may be num1, num2, or num3, depending on format. */
- switch (comets[found].flashcard.format)
- {
- case MC_FORMAT_ANS_LAST: /* e.g. num1 + num2 = ? */
- {
- comets[found].answer = comets[found].flashcard.num3;
- break;
- }
- case MC_FORMAT_ANS_MIDDLE: /* e.g. num1 + ? = num3 */
- {
- comets[found].answer = comets[found].flashcard.num2;
- break;
- }
- case MC_FORMAT_ANS_FIRST: /* e.g. ? + num2 = num3 */
- {
- comets[found].answer = comets[found].flashcard.num1;
- break;
- }
- default: /* should not get to here if MathCards behaves correctly */
- {
- fprintf(stderr, "\nadd_comet() - invalid question format");
- return 0;
- }
- }
+ comets[found].answer = comets[found].flashcard.answer;
+// /* The answer may be num1, num2, or num3, depending on format. */
+// switch (comets[found].flashcard.format)
+// {
+// case MC_FORMAT_ANS_LAST: /* e.g. num1 + num2 = ? */
+// {
+// comets[found].answer = comets[found].flashcard.num3;
+// break;
+// }
+// case MC_FORMAT_ANS_MIDDLE: /* e.g. num1 + ? = num3 */
+// {
+// comets[found].answer = comets[found].flashcard.num2;
+// break;
+// }
+// case MC_FORMAT_ANS_FIRST: /* e.g. ? + num2 = num3 */
+// {
+// comets[found].answer = comets[found].flashcard.num1;
+// break;
+// }
+// default: /* should not get to here if MathCards behaves correctly */
+// {
+// fprintf(stderr, "\nadd_comet() - invalid question format");
+// return 0;
+// }
+// }
+
-
comets[found].alive = 1;
num_comets_alive++;
@@ -2610,9 +2634,9 @@
for (j = 0; j < 4; j++)
{
if (str[i] == operchars[j])
- {
- c = 10 + j;
- }
+ {
+ c = 10 + j;
+ }
}
}
@@ -2630,7 +2654,7 @@
dest.h = src.h;
SDL_BlitSurface(images[IMG_NUMS], &src,
- screen, &dest);
+ screen, &dest);
/* Move the 'cursor' one character width: */
cur_x = cur_x + char_width;
}
@@ -2664,31 +2688,31 @@
/* Determine which character to display: */
if (str[i] >= '0' && str[i] <= '9')
- c = str[i] - '0';
+ c = str[i] - '0';
/* Display this character! */
if (c != -1)
- {
- src.x = c * (images[IMG_NUMBERS]->w / 10);
- src.y = 0;
- src.w = (images[IMG_NUMBERS]->w / 10);
- src.h = images[IMG_NUMBERS]->h;
+ {
+ src.x = c * (images[IMG_NUMBERS]->w / 10);
+ src.y = 0;
+ src.w = (images[IMG_NUMBERS]->w / 10);
+ src.h = images[IMG_NUMBERS]->h;
- dest.x = cur_x;
- dest.y = y;
- dest.w = src.w;
- dest.h = src.h;
+ dest.x = cur_x;
+ dest.y = y;
+ dest.w = src.w;
+ dest.h = src.h;
- SDL_BlitSurface(images[IMG_NUMBERS], &src,
- screen, &dest);
+ SDL_BlitSurface(images[IMG_NUMBERS], &src,
+ screen, &dest);
/* Move the 'cursor' one character width: */
- cur_x = cur_x + (images[IMG_NUMBERS]->w / 10);
- }
+ cur_x = cur_x + (images[IMG_NUMBERS]->w / 10);
+ }
}
}
@@ -2734,11 +2758,11 @@
while (SDL_PollEvent(&event))
{
if (event.type == SDL_KEYDOWN)
- pause_done = 1;
+ pause_done = 1;
else if (event.type == SDL_QUIT)
{
SDL_quit_received = 1;
- pause_quit = 1;
+ pause_quit = 1;
}
}
@@ -2940,17 +2964,17 @@
/* begin drawing so as to center display depending on whether minus */
/* sign needed (4 digit slots) or not (3 digit slots) DSB */
- if (MC_AllowNegatives())
+ if (MC_GetOpt(ALLOW_NEGATIVES) )
dest.x = ((screen->w - ((images[IMG_LEDNUMS]->w) / 10) * 4) / 2);
else
dest.x = ((screen->w - ((images[IMG_LEDNUMS]->w) / 10) * 3) / 2);
- for (i = -1; i < 3; i++) /* -1 is special case to allow minus sign */
+ for (i = -1; i < MC_MAX_DIGITS; i++) /* -1 is special case to allow minus sign */
/* with minimal modification of existing code DSB */
{
if (-1 == i)
{
- if (MC_AllowNegatives())
+ if (MC_GetOpt(ALLOW_NEGATIVES))
{
if (neg_answer_picked)
src.x = (images[IMG_LED_NEG_SIGN]->w) / 2;
@@ -3021,7 +3045,7 @@
/* make sure keypad image is valid and has non-zero dimensions: */
/* FIXME maybe this checking should be done once at the start */
/* of game() rather than with every mouse click */
- if (MC_AllowNegatives())
+ if (MC_GetOpt(ALLOW_NEGATIVES))
{
if (!images[IMG_KEYPAD])
return;
@@ -3167,7 +3191,7 @@
/* on-screen keypad */
void game_key_event(SDLKey key)
{
-
+ int i;
key_pressed = 1; // Signal back in cases where waiting on any key
if (key == SDLK_ESCAPE)
@@ -3244,29 +3268,37 @@
if (key >= SDLK_0 && key <= SDLK_9)
{
/* [0]-[9]: Add a new digit: */
- digits[0] = digits[1];
- digits[1] = digits[2];
- digits[2] = key - SDLK_0;
+ for (i = 0; i < MC_MAX_DIGITS-1; ++i)
+ digits[i] = digits[i+1];
+ digits[MC_MAX_DIGITS-1] = key - SDLK_0;
+
+// digits[0] = digits[1];
+// digits[1] = digits[2];
+// digits[2] = key - SDLK_0;
tux_pressing = 1;
}
else if (key >= SDLK_KP0 && key <= SDLK_KP9)
{
/* Keypad [0]-[9]: Add a new digit: */
- digits[0] = digits[1];
- digits[1] = digits[2];
- digits[2] = key - SDLK_KP0;
+ for (i = 0; i < MC_MAX_DIGITS-1; ++i)
+ digits[i] = digits[i+1];
+ digits[MC_MAX_DIGITS-1] = key - SDLK_KP0;
+
+// digits[0] = digits[1];
+// digits[1] = digits[2];
+// digits[2] = key - SDLK_KP0;
tux_pressing = 1;
}
/* support for negative answer input DSB */
else if ((key == SDLK_MINUS || key == SDLK_KP_MINUS)
- && MC_AllowNegatives()) /* do nothing unless neg answers allowed */
+ && MC_GetOpt(ALLOW_NEGATIVES) ) /* do nothing unless neg answers allowed */
{
/* allow player to make answer negative: */
neg_answer_picked = 1;
tux_pressing = 1;
}
else if ((key == SDLK_PLUS || key == SDLK_KP_PLUS)
- && MC_AllowNegatives()) /* do nothing unless neg answers allowed */
+ && MC_GetOpt(ALLOW_NEGATIVES) ) /* do nothing unless neg answers allowed */
{
/* allow player to make answer positive: */
neg_answer_picked = 0;
@@ -3274,17 +3306,16 @@
}
else if (key == SDLK_BACKSPACE ||
key == SDLK_CLEAR ||
- key == SDLK_DELETE)
+ key == SDLK_DELETE)
{
/* [BKSP]: Clear digits! */
- digits[0] = 0;
- digits[1] = 0;
- digits[2] = 0;
+ for (i = 0; i < MC_MAX_DIGITS; ++i)
+ digits[i] = 0;
tux_pressing = 1;
}
else if (key == SDLK_RETURN ||
key == SDLK_KP_ENTER ||
- key == SDLK_SPACE)
+ key == SDLK_SPACE)
{
/* [ENTER]: Accept digits! */
doing_answer = 1;
@@ -3296,6 +3327,7 @@
void add_score(int inc)
{
score += inc;
+ tmdprintf("Score is now: %d\n", score);
}
@@ -3311,8 +3343,9 @@
comets[i].x = 0;
comets[i].y = 0;
comets[i].answer = 0;
- strncpy(comets[i].flashcard.formula_string, " ", MC_FORMULA_LEN);
- strncpy(comets[i].flashcard.answer_string, " ", MC_ANSWER_LEN);
+// strncpy(comets[i].flashcard.formula_string, " ", max_formula_size);
+// strncpy(comets[i].flashcard.answer_string, " ", max_answer_size);
+ MC_ResetFlashCard(&(comets[i].flashcard) );
comets[i].bonus = 0;
}
}
@@ -3342,6 +3375,9 @@
void free_on_exit(void)
{
+ int i;
+ for (i = 0; i < MAX_MAX_COMETS; ++i)
+ MC_FreeFlashcard(&(comets[i].flashcard));
free(comets);
free(cities);
free(penguins);
Modified: tuxmath/trunk/src/gettext.h
===================================================================
--- tuxmath/trunk/src/gettext.h 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/gettext.h 2008-08-06 02:55:05 UTC (rev 589)
@@ -127,8 +127,8 @@
#endif
static const char *
pgettext_aux (const char *domain,
- const char *msg_ctxt_id, const char *msgid,
- int category)
+ const char *msg_ctxt_id, const char *msgid,
+ int category)
{
const char *translation = dcgettext (domain, msg_ctxt_id, category);
if (translation == msg_ctxt_id)
@@ -146,9 +146,9 @@
#endif
static const char *
npgettext_aux (const char *domain,
- const char *msg_ctxt_id, const char *msgid,
- const char *msgid_plural, unsigned long int n,
- int category)
+ const char *msg_ctxt_id, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
{
const char *translation =
dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
@@ -185,8 +185,8 @@
#endif
static const char *
dcpgettext_expr (const char *domain,
- const char *msgctxt, const char *msgid,
- int category)
+ const char *msgctxt, const char *msgid,
+ int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
@@ -208,10 +208,10 @@
translation = dcgettext (domain, msg_ctxt_id, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
- free (msg_ctxt_id);
+ free (msg_ctxt_id);
#endif
if (translation != msg_ctxt_id)
- return translation;
+ return translation;
}
return msgid;
}
@@ -230,9 +230,9 @@
#endif
static const char *
dcnpgettext_expr (const char *domain,
- const char *msgctxt, const char *msgid,
- const char *msgid_plural, unsigned long int n,
- int category)
+ const char *msgctxt, const char *msgid,
+ const char *msgid_plural, unsigned long int n,
+ int category)
{
size_t msgctxt_len = strlen (msgctxt) + 1;
size_t msgid_len = strlen (msgid) + 1;
@@ -254,10 +254,10 @@
translation = dcngettext (domain, msg_ctxt_id, msgid_plural, n, category);
#if !_LIBGETTEXT_HAVE_VARIABLE_SIZE_ARRAYS
if (msg_ctxt_id != buf)
- free (msg_ctxt_id);
+ free (msg_ctxt_id);
#endif
if (!(translation == msg_ctxt_id || translation == msgid_plural))
- return translation;
+ return translation;
}
return (n == 1 ? msgid : msgid_plural);
}
Modified: tuxmath/trunk/src/highscore.c
===================================================================
--- tuxmath/trunk/src/highscore.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/highscore.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -140,7 +140,7 @@
/* "Right" button - go to next page: */
if (inRect( rightRect, event.button.x, event.button.y ))
{
- if (diff_level < ACE_HIGH_SCORE)
+ if (diff_level < NUM_HIGH_SCORE_LEVELS - 1)
{
diff_level++;
if (Opts_MenuSound())
@@ -187,7 +187,7 @@
SDL_BlitSurface(images[IMG_LEFT], NULL, screen, &leftRect);
}
/* Draw regular or grayed-out right arrow: */
- if (diff_level == ACE_HIGH_SCORE)
+ if (diff_level == NUM_HIGH_SCORE_LEVELS - 1)
{
if (images[IMG_RIGHT_GRAY])
SDL_BlitSurface(images[IMG_RIGHT_GRAY], NULL, screen, &rightRect);
@@ -242,6 +242,9 @@
break;
case ACE_HIGH_SCORE:
srfc = BlackOutline(_("Ace"), title_font, &white);
+ break;
+ case COMMANDO_HIGH_SCORE:
+ srfc = BlackOutline(_("Commando"), title_font, &white);
break;
default:
srfc = BlackOutline(_("Space Cadet"), title_font, &white);
@@ -311,7 +314,7 @@
case 0: tux_frame = 1; break;
case TUX1: tux_frame = 2; break;
case TUX2: tux_frame = 3; break;
- case TUX3: tux_frame = 4; break;
+ case TUX3: tux_frame = 4; break;
case TUX4: tux_frame = 3; break;
case TUX5: tux_frame = 2; break;
default: tux_frame = 0;
@@ -568,7 +571,7 @@
case 0: tux_frame = 1; break;
case TUX1: tux_frame = 2; break;
case TUX2: tux_frame = 3; break;
- case TUX3: tux_frame = 4; break;
+ case TUX3: tux_frame = 4; break;
case TUX4: tux_frame = 3; break;
case TUX5: tux_frame = 2; break;
default: tux_frame = 0;
@@ -624,7 +627,7 @@
/* Make sure diff_level is valid: */
if (diff_level < 0
- || diff_level > ACE_HIGH_SCORE)
+ || diff_level >= NUM_HIGH_SCORE_LEVELS)
{
fprintf(stderr, "In insert_score(), diff_level invalid!\n");
return 0;
@@ -703,6 +706,11 @@
{
fprintf(fp, "\nAce:\n");
break;
+ }
+ case COMMANDO_HIGH_SCORE:
+ {
+ fprintf(fp, "\nCommando:\n");
+ break;
}
}
@@ -777,9 +785,9 @@
{
/* Make sure diff_level is valid: */
if (diff_level < 0
- || diff_level > ACE_HIGH_SCORE)
+ || diff_level >= NUM_HIGH_SCORE_LEVELS)
{
- fprintf(stderr, "In HS_Score(), diff_level invalid!\n");
+ fprintf(stderr, "In HS_Score(), diff_level = %d, invalid!\n", diff_level);
return -1;
}
@@ -800,7 +808,7 @@
{
/* Make sure diff_level is valid: */
if (diff_level < 0
- || diff_level > ACE_HIGH_SCORE)
+ || diff_level >= NUM_HIGH_SCORE_LEVELS)
{
fprintf(stderr, "In HS_Score(), diff_level invalid!\n");
return NULL;
Modified: tuxmath/trunk/src/loaders.c
===================================================================
--- tuxmath/trunk/src/loaders.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/loaders.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -32,13 +32,13 @@
/* FIXME Doesn't seem to work consistently on all versions of Windows */
/* check to see if file exists, if so return true */
// int checkFile( const char *file ) {
-// static struct stat fileStats;
+// static struct stat fileStats;
//
-// fileStats.st_mode = 0;
+// fileStats.st_mode = 0;
//
-// stat( file, &fileStats );
-//
-// return (S_IFREG & fileStats.st_mode);
+// stat( file, &fileStats );
+//
+// return (S_IFREG & fileStats.st_mode);
// }
@@ -88,7 +88,7 @@
int max( int n1, int n2 ) {
- return (n1 > n2 ? n1 : n2);
+ return (n1 > n2 ? n1 : n2);
}
@@ -132,7 +132,7 @@
/* FIXME checkFile() not working right in Win32 - skipping. */
/***********************
- LoadImage : Load an image and set transparent if requested
+ LoadImage : Load an image and set transparent if requested
************************/
SDL_Surface* LoadImage( char *datafile, int mode )
{
@@ -211,7 +211,7 @@
}
/***********************
- LoadBkgd() : a wrapper for LoadImage() that scales the
+ LoadBkgd() : a wrapper for LoadImage() that scales the
image to the size of the screen using zoom(), taken
from TuxPaint
************************/
@@ -284,54 +284,62 @@
sprite* FlipSprite( sprite *in, int X, int Y ) {
- sprite *out;
+ sprite *out;
- out = malloc(sizeof(sprite));
- if (in->default_img != NULL)
- out->default_img = Flip( in->default_img, X, Y );
- else
- out->default_img = NULL;
- for ( out->num_frames=0; out->num_frames<in->num_frames; out->num_frames++ )
- out->frame[out->num_frames] = Flip( in->frame[out->num_frames], X, Y );
- out->cur = 0;
- return out;
+ out = malloc(sizeof(sprite));
+ if (in->default_img != NULL)
+ out->default_img = Flip( in->default_img, X, Y );
+ else
+ out->default_img = NULL;
+ for ( out->num_frames=0; out->num_frames<in->num_frames; out->num_frames++ )
+ out->frame[out->num_frames] = Flip( in->frame[out->num_frames], X, Y );
+ out->cur = 0;
+ return out;
}
sprite* LoadSprite( char* name, int MODE ) {
- sprite *new_sprite;
- char fn[PATH_MAX];
- int x;
+ sprite *new_sprite;
+ char fn[PATH_MAX];
+ int x;
- /* JA --- HACK check out what has changed with new code */
+ /* JA --- HACK check out what has changed with new code */
- new_sprite = malloc(sizeof(sprite));
+ new_sprite = malloc(sizeof(sprite));
- sprintf(fn, "%sd.png", name); // The 'd' means the default image
- new_sprite->default_img = LoadImage( fn, MODE|IMG_NOT_REQUIRED );
- for (x = 0; x < MAX_SPRITE_FRAMES; x++) {
- sprintf(fn, "%s%d.png", name, x);
- new_sprite->frame[x] = LoadImage( fn, MODE|IMG_NOT_REQUIRED );
- if ( new_sprite->frame[x] == NULL ) {
- new_sprite->cur = 0;
- new_sprite->num_frames = x;
- break;
- }
- }
+ sprintf(fn, "%sd.png", name); // The 'd' means the default image
+ new_sprite->default_img = LoadImage( fn, MODE|IMG_NOT_REQUIRED );
+ for (x = 0; x < MAX_SPRITE_FRAMES; x++) {
+ sprintf(fn, "%s%d.png", name, x);
+ new_sprite->frame[x] = LoadImage( fn, MODE|IMG_NOT_REQUIRED );
+ if ( new_sprite->frame[x] == NULL ) {
+ new_sprite->cur = 0;
+ new_sprite->num_frames = x;
+ break;
+ }
+ }
-
- return new_sprite;
+
+ return new_sprite;
}
void FreeSprite( sprite *gfx ) {
- int x;
- for (x = 0; x < gfx->num_frames; x++)
- SDL_FreeSurface( gfx->frame[x] );
- SDL_FreeSurface( gfx->default_img );
- free(gfx);
+ int x;
+ if (!gfx)
+ return;
+ printf("Freeing image");
+ tmdprintf(" at %p", gfx);
+ for (x = 0; x < gfx->num_frames; x++)
+ {
+ printf(".");
+ SDL_FreeSurface( gfx->frame[x] );
+ }
+ SDL_FreeSurface( gfx->default_img );
+ printf("done\n");
+ free(gfx);
}
void next_frame(sprite* s)
@@ -341,7 +349,7 @@
}
/***************************
- LoadSound : Load a sound/music patch from a file.
+ LoadSound : Load a sound/music patch from a file.
****************************/
Mix_Chunk* LoadSound( char *datafile )
{
@@ -359,8 +367,8 @@
}
/************************
- LoadMusic : Load
- music from a datafile
+ LoadMusic : Load
+ music from a datafile
*************************/
Mix_Music *LoadMusic(char *datafile )
{
Modified: tuxmath/trunk/src/mathcards.c
===================================================================
--- tuxmath/trunk/src/mathcards.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/mathcards.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -1,3078 +1,2077 @@
-/*
-* C Implementation: mathcards.c
-*
-* Description: implementation of backend for a flashcard-type math game.
- Developed as an enhancement to Bill Kendrick's "Tux of Math Command"
- (aka tuxmath). (If tuxmath were a C++ program, this would be a C++ class).
- MathCards could be used as the basis for similar games using a different interface.
-
-*
-*
-* Author: David Bruce <dbruce at tampabay.rr.com>, (C) 2005
-*
-* Copyright: See COPYING file that comes with this distribution. (Briefly, GNU GPL).
-*
-*/
-#include <stdio.h>
-#include <stdlib.h>
-#include <string.h>
-#include <time.h>
-
-#include "mathcards.h"
-
-/* "Globals" for mathcards.c: */
-MC_Options* math_opts = 0;
-MC_MathQuestion* question_list = 0;
-MC_MathQuestion* wrong_quests = 0;
-MC_MathQuestion* next_wrong_quest = 0;
-int initialized = 0;
-int quest_list_length = 0;
-int answered_correctly = 0;
-int answered_wrong = 0;
-int questions_pending = 0;
-int unanswered = 0;
-int starting_length = 0;
-
-/* For keeping track of timing data */
-float* time_per_question_list = NULL;
-int length_time_per_question_list = 0;
-int length_alloc_time_per_question_list = 0;
-
-/* "private" function prototypes: */
-/* */
-/* these are for internal use by MathCards only - like */
-/* the private functions of a C++ class. Declared static */
-/* to give file scope rather than extern scope. */
-
-static MC_MathQuestion* generate_list(void);
-static void clear_negatives(void);
-static int validate_question(int n1, int n2, int n3);
-static MC_MathQuestion* create_node(int n1, int n2, int op, int ans, int f);
-static MC_MathQuestion* create_node_from_card(MC_FlashCard* flashcard);
-static MC_MathQuestion* insert_node(MC_MathQuestion* first, MC_MathQuestion* current, MC_MathQuestion* new_node);
-static MC_MathQuestion* append_node(MC_MathQuestion* list, MC_MathQuestion* new_node);
-static MC_MathQuestion* remove_node(MC_MathQuestion* first, MC_MathQuestion* n);
-static MC_MathQuestion* delete_list(MC_MathQuestion* list);
-static int copy_node(MC_MathQuestion* original, MC_MathQuestion* copy);
-static int list_length(MC_MathQuestion* list);
-static int randomize_list(MC_MathQuestion** list);
-
-int comp_randomizer(const void *a, const void *b);
-static MC_MathQuestion* pick_random(int length, MC_MathQuestion* list);
-static int compare_node(MC_MathQuestion* first, MC_MathQuestion* other);
-static int already_in_list(MC_MathQuestion* list, MC_MathQuestion* ptr);
-static int int_to_bool(int i);
-static int sane_value(int i);
-static int abs_value(int i);
-static int randomly_keep(void);
-static int floatCompare(const void *v1,const void *v2);
-
-static void print_list(FILE* fp,MC_MathQuestion* list);
-void print_vect_list(FILE* fp, MC_MathQuestion** vect, int length);
-static void print_node(FILE* fp, MC_MathQuestion* ptr);
-
-/* these functions are dead code unless compiling with debug turned on: */
-#ifdef MC_DEBUG
-static void print_card(MC_FlashCard card);
-static void print_counters(void);
-static MC_MathQuestion* create_node_copy(MC_MathQuestion* other);
-
-static MC_FlashCard* create_card_from_node(MC_MathQuestion* node);
-#endif
-
-/* MC_Initialize() sets up the struct containing all of */
-/* settings regarding math questions. It should be */
-/* called before any other function. Many of the other */
-/* functions will not work properly if MC_Initialize() */
-/* has not been called. It only needs to be called once, */
-/* i.e when the program is starting, not at the beginning*/
-/* of each math game for the player. Returns 1 if */
-/* successful, 0 otherwise. */
-int MC_Initialize(void)
-{
- #ifdef MC_DEBUG
- printf("\nEntering MC_Initialize()");
- #endif
-
- /* check flag to see if we did this already */
- if (initialized)
- {
-
- #ifdef MC_DEBUG
- printf("\nAlready initialized");
- MC_PrintMathOptions(stdout, 0);
- printf("\nLeaving MC_Initialize()\n");
- #endif
-
- return 1;
- }
- math_opts = malloc(sizeof(MC_Options));
- /* bail out if no struct */
- if (!math_opts)
- {
-
- #ifdef MC_DEBUG
- printf("\nError: math_opts null or invalid");
- printf("\nLeaving MC_Initialize()\n");
- #endif
-
- fprintf(stderr, "\nUnable to initialize math_options");
+/*
+* C Implementation: mathcards.c
+*
+* Description: implementation of backend for a flashcard-type math game.
+ Developed as an enhancement to Bill Kendrick's "Tux of Math Command"
+ (aka tuxmath). (If tuxmath were a C++ program, this would be a C++ class).
+ MathCards could be used as the basis for similar games using a different interface.
+
+*
+*
+* Author: David Bruce <dbruce at tampabay.rr.com>, (C) 2005
+*
+* Copyright: See COPYING file that comes with this distribution. (Briefly, GNU GPL).
+*
+*/
+#include <stdio.h>
+#include <stdlib.h>
+#include <string.h>
+#include <math.h>
+#include <time.h>
+
+#include "mathcards.h"
+
+/* extern'd constants */
+
+const char* const MC_OPTION_TEXT[NOPTS+1] = {
+"PLAY_THROUGH_LIST",
+"QUESTION_COPIES",
+"REPEAT_WRONGS",
+"COPIES_REPEATED_WRONGS",
+"ALLOW_NEGATIVES",
+"MAX_ANSWER",
+"MAX_QUESTIONS",
+"MAX_FORMULA_NUMS",
+"MIN_FORMULA_NUMS",
+
+"FORMAT_ANSWER_LAST",
+"FORMAT_ANSWER_FIRST",
+"FORMAT_ANSWER_MIDDLE",
+"FORMAT_ADD_ANSWER_LAST",
+"FORMAT_ADD_ANSWER_FIRST",
+"FORMAT_ADD_ANSWER_MIDDLE",
+"FORMAT_SUB_ANSWER_LAST",
+"FORMAT_SUB_ANSWER_FIRST",
+"FORMAT_SUB_ANSWER_MIDDLE",
+"FORMAT_MULT_ANSWER_LAST",
+"FORMAT_MULT_ANSWER_FIRST",
+"FORMAT_MULT_ANSWER_MIDDLE",
+"FORMAT_DIV_ANSWER_LAST",
+"FORMAT_DIV_ANSWER_FIRST",
+"FORMAT_DIV_ANSWER_MIDDLE",
+
+"ADDITION_ALLOWED",
+"SUBTRACTION_ALLOWED",
+"MULTIPLICATION_ALLOWED",
+"DIVISION_ALLOWED",
+"TYPING_PRACTICE_ALLOWED",
+"ARITHMETIC_ALLOWED",
+"COMPARISON_ALLOWED",
+
+"MIN_AUGEND",
+"MAX_AUGEND",
+"MIN_ADDEND",
+"MAX_ADDEND",
+
+"MIN_MINUEND",
+"MAX_MINUEND",
+"MIN_SUBTRAHEND",
+"MAX_SUBTRAHEND",
+
+"MIN_MULTIPLIER",
+"MAX_MULTIPLIER",
+"MIN_MULTIPLICAND",
+"MAX_MULTIPLICAND",
+
+"MIN_DIVISOR",
+"MAX_DIVISOR",
+"MIN_QUOTIENT",
+"MAX_QUOTIENT",
+
+"MIN_TYPING_NUM",
+"MAX_TYPING_NUM",
+
+"MIN_COMPARATOR" ,
+"MAX_COMPARATOR" ,
+"MIN_COMPARISAND",
+"MAX_COMPARISAND",
+
+"RANDOMIZE",
+
+"COMPREHENSIVE",
+"AVG_LIST_LENGTH",
+"VARY_LIST_LENGTH",
+
+"END_OF_OPTS"
+};
+
+const int MC_DEFAULTS[] = {
+ 1, //PLAY_THROUGH_LIST
+ 1, //QUESTION_COPIES
+ 1, //REPEAT_WRONGS
+ 1, //COPIES_REPEATED_WRONGS
+ 0, //ALLOW_NEGATIVES
+ 999, //MAX_ANSWER
+ 5000, //MAX_QUESTIONS
+ 2, //MAX_FORMULA_NUMS
+ 2, //MIN_FORMULA_NUMS
+ //
+ 1, //FORMAT_ANSWER_LAST
+ 0, //FORMAT_ANSWER_FIRST
+ 0, //FORMAT_ANSWER_MIDDLE
+ 1, //FORMAT_ADD_ANSWER_LAST
+ 0, //FORMAT_ADD_ANSWER_FIRST
+ 0, //FORMAT_ADD_ANSWER_MIDDLE
+ 1, //FORMAT_SUB_ANSWER_LAST
+ 0, //FORMAT_SUB_ANSWER_FIRST
+ 0, //FORMAT_SUB_ANSWER_MIDDLE
+ 1, //FORMAT_MULT_ANSWER_LAST
+ 0, //FORMAT_MULT_ANSWER_FIRST
+ 0, //FORMAT_MULT_ANSWER_MIDDLE
+ 1, //FORMAT_DIV_ANSWER_LAST
+ 0, //FORMAT_DIV_ANSWER_FIRST
+ 0, //FORMAT_DIV_ANSWER_MIDDLE
+ //
+ 1, //ADDITION_ALLOWED
+ 1, //SUBTRACTION_ALLOWED
+ 1, //MULTIPLICATION_ALLOWED
+ 1, //DIVISION_ALLOWED
+
+ 0, //TYPING_PRACTICE_ALLOWED
+ 1, //ARITHMETIC_ALLOWED
+ 0, //COMPARISON_ALLOWED
+ //
+ 0, //MIN_AUGEND
+ 12, //MAX_AUGEND
+ 0, //MIN_ADDEND
+ 12, //MAX_ADDEND
+ //
+ 0, //MIN_MINUEND
+ 12, //MAX_MINUEND
+ 0, //MIN_SUBTRAHEND
+ 12, //MAX_SUBTRAHEND
+ //
+ 0, //MIN_MULTIPLIER
+ 12, //MAX_MULTIPLIER
+ 0, //MIN_MULTIPLICAND
+ 12, //MAX_MULTIPLICAND
+ //
+ 0, //MIN_DIVISOR
+ 12, //MAX_DIVISOR
+ 0, //MIN_QUOTIENT
+ 12, //MAX_QUOTIENT
+ //
+ 0, //MIN_TYPING_NUM
+ 12, //MAX_TYPING_NUM
+ //
+ 0, //MIN_COMPARATOR
+ 12, //MAX_COMPARATOR
+ 0, //MIN_COMPARISAND
+ 12, //MAX_COMPARISAND
+
+ 1, //RANDOMIZE
+
+ 0, //COMPREHENSIVE
+ 100, //AVG_LIST_LENGTH
+ 1 //VARY_LIST_LENGTH
+};
+
+
+
+/* "Globals" for mathcards.c: */
+#define PI_VAL 3.1415927
+#define NPRIMES 9
+const int smallprimes[NPRIMES] = {2, 3, 5 ,7, 11, 13, 17, 19, 23};
+const char operchars[4] = "+-*/";
+
+MC_Options* math_opts = 0;
+MC_MathQuestion* question_list = 0;
+MC_MathQuestion* wrong_quests = 0;
+MC_MathQuestion* next_wrong_quest = 0;
+int initialized = 0;
+int quest_list_length = 0;
+int answered_correctly = 0;
+int answered_wrong = 0;
+int questions_pending = 0;
+int unanswered = 0;
+int starting_length = 0;
+int max_formula_size = 0; //max length in chars of a flashcard's formula
+int max_answer_size = 0; //and of its answer
+
+/* For keeping track of timing data */
+float* time_per_question_list = NULL;
+int length_time_per_question_list = 0;
+int length_alloc_time_per_question_list = 0;
+
+const MC_FlashCard DEFAULT_CARD = {NULL,NULL,0,0}; //empty card to signal error
+
+/* "private" function prototypes: */
+/* */
+/* these are for internal use by MathCards only - like */
+/* the private functions of a C++ class. Declared static */
+/* to give file scope rather than extern scope. */
+
+static MC_MathQuestion* generate_list(void);
+static void clear_negatives(void);
+static int validate_question(int n1, int n2, int n3);
+static MC_MathQuestion* create_node(int n1, int n2, int op, int ans, int f);
+static MC_MathQuestion* create_node_from_card(const MC_FlashCard* flashcard);
+static MC_MathQuestion* insert_node(MC_MathQuestion* first, MC_MathQuestion* current, MC_MathQuestion* new_node);
+static MC_MathQuestion* append_node(MC_MathQuestion* list, MC_MathQuestion* new_node);
+static MC_MathQuestion* remove_node(MC_MathQuestion* first, MC_MathQuestion* n);
+static MC_MathQuestion* delete_list(MC_MathQuestion* list);
+static int copy_node(MC_MathQuestion* original, MC_MathQuestion* copy);
+static int list_length(MC_MathQuestion* list);
+static int randomize_list(MC_MathQuestion** list);
+
+int comp_randomizer(const void *a, const void *b);
+static MC_MathQuestion* pick_random(int length, MC_MathQuestion* list);
+static int compare_node(MC_MathQuestion* first, MC_MathQuestion* other);
+static int already_in_list(MC_MathQuestion* list, MC_MathQuestion* ptr);
+static int int_to_bool(int i);
+static int sane_value(int i);
+static int abs_value(int i);
+static int log10i(int i);
+static int floatCompare(const void *v1,const void *v2);
+
+static void print_list(FILE* fp,MC_MathQuestion* list);
+void print_vect_list(FILE* fp, MC_MathQuestion** vect, int length);
+
+/* these functions are dead code unless compiling with debug turned on: */
+#ifdef MC_DEBUG
+static void print_card(MC_FlashCard card);
+static void print_counters(void);
+static MC_MathQuestion* create_node_copy(MC_MathQuestion* other);
+static MC_FlashCard create_card_from_node(MC_MathQuestion* node);
+#endif
+
+/* Functions for new mathcards architecture */
+static void free_node(MC_MathQuestion* mq); //wrapper for free() that also frees card
+static MC_FlashCard generate_random_flashcard(void);
+static MC_FlashCard generate_random_ooo_card_of_length(int length, int reformat);
+static void copy_card(const MC_FlashCard* src, MC_FlashCard* dest); //deep copy a flashcard
+static MC_MathQuestion* allocate_node(void); //allocate space for a node
+static int compare_card(const MC_FlashCard* a, const MC_FlashCard* b); //test for identical cards
+static int find_divisor(int a);
+static MC_MathQuestion* add_all_valid(MC_ProblemType pt, MC_MathQuestion* list, MC_MathQuestion* end_of_list);
+static MC_MathQuestion* find_node(const MC_MathQuestion* list, int num);
+
+/* MC_Initialize() sets up the struct containing all of */
+/* settings regarding math questions. It should be */
+/* called before any other function. Many of the other */
+/* functions will not work properly if MC_Initialize() */
+/* has not been called. It only needs to be called once, */
+/* i.e when the program is starting, not at the beginning*/
+/* of each math game for the player. Returns 1 if */
+/* successful, 0 otherwise. */
+int MC_Initialize(void)
+{
+ int i;
+
+ mcdprintf("\nEntering MC_Initialize()");
+ /* check flag to see if we did this already */
+ if (initialized)
+ {
+
+ #ifdef MC_DEBUG
+ printf("\nAlready initialized");
+ MC_PrintMathOptions(stdout, 0);
+ printf("\nLeaving MC_Initialize()\n");
+ #endif
+
+ return 1;
+ }
+ math_opts = malloc(sizeof(MC_Options));
+ /* bail out if no struct */
+ if (!math_opts)
+ {
+
+ mcdprintf("\nError: math_opts null or invalid");
+ mcdprintf("\nLeaving MC_Initialize()\n");
+
+ fprintf(stderr, "\nUnable to initialize math_options");
+ return 0;
+ }
+
+ /* set defaults */
+ for (i = 0; i < NOPTS; ++i)
+ {
+ math_opts->iopts[i] = MC_DEFAULTS[i];
+ }
+
+ /* if no negatives to be used, reset any negatives to 0 */
+ if (!math_opts->iopts[ALLOW_NEGATIVES])
+ {
+ clear_negatives();
+ }
+
+ initialized = 1;
+
+ #ifdef MC_DEBUG
+ MC_PrintMathOptions(stdout, 0);
+ printf("\nLeaving MC_Initialize()\n");
+ #endif
+
+ return 1;
+}
+
+
+
+/* MC_StartGame() generates the list of math questions */
+/* based on existing settings. It should be called at */
+/* the beginning of each math game for the player. */
+/* Returns 1 if resultant list contains 1 or more */
+/* questions, 0 if list empty or not generated */
+/* successfully. */
+int MC_StartGame(void)
+{
+ mcdprintf("\nEntering MC_StartGame()");
+
+ /* if math_opts not set up yet, initialize it: */
+ if (!initialized)
+ {
+
+ mcdprintf("\nNot initialized - calling MC_Initialize()");
+
+ MC_Initialize();
+ }
+
+ if (!math_opts)
+ {
+ mcdprintf("\nCould not initialize - bailing out");
+ mcdprintf("\nLeaving MC_StartGame()\n");
+
+ return 0;
+ }
+ /* we know math_opts exists if we make it to here */
+ srand(time(NULL));
+
+ /* clear out old lists if starting another game: (if not done already) */
+ delete_list(question_list);
+ question_list = NULL;
+ delete_list(wrong_quests);
+ wrong_quests = NULL;
+
+ /* clear the time list */
+ if (time_per_question_list != NULL) {
+ free(time_per_question_list);
+ time_per_question_list = NULL;
+ length_time_per_question_list = 0;
+ length_alloc_time_per_question_list = 0;
+ }
+
+ /* determine how much space needed for strings, based on user options */
+ max_formula_size = MC_GetOpt(MAX_FORMULA_NUMS)
+ * (log10i(MC_GLOBAL_MAX) + 4) //sign/operator/spaces
+ + 1; //question mark for answer
+ max_answer_size = (int)(log10i(MC_GLOBAL_MAX) ) + 2; //negative sign + digit
+
+ mcdprintf("max answer, formula size: %d, %d\n",
+ max_answer_size, max_formula_size);
+ /* set up new list with pointer to top: */
+ question_list = generate_list();
+
+ next_wrong_quest = 0;
+ /* initialize counters for new game: */
+ quest_list_length = list_length(question_list);
+ /* Note: the distinction between quest_list_length and */
+ /* unanswered is that the latter includes questions */
+ /* that are currently "in play" by the user interface - */
+ /* it is only decremented when an answer to the question*/
+ /* is received. */
+ unanswered = starting_length = quest_list_length;
+ answered_correctly = 0;
+ answered_wrong = 0;
+ questions_pending = 0;
+
+ #ifdef MC_DEBUG
+ print_counters();
+ #endif
+
+ /* make sure list now exists and has non-zero length: */
+ if (question_list && quest_list_length)
+ {
+ mcdprintf("\nGame set up successfully");
+ mcdprintf("\nLeaving MC_StartGame()\n");
+
+ return 1;
+ }
+ else
+ {
+ mcdprintf("\nGame NOT set up successfully - no valid list");
+ mcdprintf("\nLeaving MC_StartGame()\n");
+
+ return 0;
+ }
+}
+
+/* MC_StartGameUsingWrongs() is like MC_StartGame(), */
+/* but uses the incorrectly answered questions from the */
+/* previous game for the question list as a review form */
+/* of learning. If there were no wrong answers (or no */
+/* previous game), it behaves just like MC_StartGame(). */
+/* FIXME wonder if it should return a different value if */
+/* the list is created from settings because there is no */
+/* valid wrong question list? */
+int MC_StartGameUsingWrongs(void)
+{
+ mcdprintf("\nEntering MC_StartGameUsingWrongs()");
+
+ /* Note: if not initialized, control will pass to */
+ /* MC_StartGame() via else clause so don't need to test */
+ /* for initialization here */
+ if (wrong_quests &&
+ list_length(wrong_quests))
+ {
+ mcdprintf("\nNon-zero length wrong_quests list found, will");
+ mcdprintf("\nuse for new game list:");
+
+ /* initialize lists for new game: */
+ delete_list(question_list);
+ if(!randomize_list(&wrong_quests)) {
+ fprintf(stderr, "Error during randomization of wrong_quests!\n");
+ /* Punt on trying wrong question list, just run normal game */
+ return MC_StartGame();
+ }
+ question_list = wrong_quests;
+ wrong_quests = 0;
+ next_wrong_quest = 0;
+ /* initialize counters for new game: */
+ quest_list_length = list_length(question_list);
+ unanswered = starting_length = quest_list_length;
+ answered_correctly = 0;
+ answered_wrong = 0;
+ questions_pending = 0;
+
+ #ifdef MC_DEBUG
+ print_counters();
+ print_list(stdout, question_list);
+ printf("\nLeaving MC_StartGameUsingWrongs()\n");
+ #endif
+
+ return 1;
+ }
+ else /* if no wrong_quests list, go to MC_StartGame() */
+ /* to set up list based on math_opts */
+ {
+ mcdprintf("\nNo wrong questions to review - generate list from math_opts\n");
+ mcdprintf("\nLeaving MC_StartGameUsingWrongs()\n");
+
+ return MC_StartGame();
+ }
+}
+
+
+/* MC_NextQuestion() takes a pointer to an allocated */
+/* MC_MathQuestion struct and fills in the fields for */
+/* use by the user interface program. It basically is */
+/* like taking the next flashcard from the pile. The */
+/* node containing the question is removed from the list.*/
+/* Returns 1 if question found, 0 if list empty/invalid */
+/* or if argument pointer is invalid. */
+int MC_NextQuestion(MC_FlashCard* fc)
+{
+ mcdprintf("\nEntering MC_NextQuestion()\n");
+
+ /* (so we can free the node after removed from list:) */
+ MC_MathQuestion* ptr;
+ ptr = question_list;
+
+ if (!fc )
+ {
+ fprintf(stderr, "\nNull MC_FlashCard* argument!\n");
+ mcdprintf("\nLeaving MC_NextQuestion()\n");
+ return 0;
+ }
+
+ if (!question_list ||
+/* !next_question || */
+ !list_length(question_list) )
+ {
+ mcdprintf("\nquestion_list invalid or empty");
+ mcdprintf("\nLeaving MC_NextQuestion()\n");
+
+ return 0;
+ }
+
+ /* 'draw' - copy over the first question */
+ copy_card(&question_list->card, fc);
+
+ /* 'discard' - take first question node out of list and free it */
+ question_list = remove_node(question_list, question_list);
+ free_node(ptr);
+ quest_list_length--;
+ questions_pending++;
+
+ #ifdef MC_DEBUG
+ printf("\nnext question is:");
+ print_card(*fc);
+ print_counters();
+ printf("\n\nLeaving MC_NextQuestion()\n");
+ #endif
+
+ return 1;
+}
+
+/* MC_AnsweredCorrectly() is how the user interface */
+/* tells MathCards that the question has been answered */
+/* correctly. Returns 1 if no errors. */
+int MC_AnsweredCorrectly(MC_FlashCard* fc)
+{
+ mcdprintf("\nEntering MC_AnsweredCorrectly()");
+
+ if (!fc)
+ {
+ fprintf(stderr, "\nMC_AnsweredCorrectly() passed invalid pointer as argument!\n");
+
+ mcdprintf("\nInvalid MC_FlashCard* argument!");
+ mcdprintf("\nLeaving MC_AnsweredCorrectly()\n");
+
+ return 0;
+ }
+
+ #ifdef MC_DEBUG
+ printf("\nQuestion was:");
+ print_card(*fc);
+ #endif
+
+ answered_correctly++;
+ questions_pending--;
+
+ if (!math_opts->iopts[PLAY_THROUGH_LIST])
+ /* reinsert question into question list at random location */
+ {
+ mcdprintf("\nReinserting question into list");
+
+ MC_MathQuestion* ptr1;
+ MC_MathQuestion* ptr2;
+ /* make new node using values from flashcard */
+ ptr1 = create_node_from_card(fc);
+ /* put it into list */
+ ptr2 = pick_random(quest_list_length, question_list);
+ question_list = insert_node(question_list, ptr2, ptr1);
+ quest_list_length++;
+ /* unanswered does not change - was not decremented when */
+ /* question allocated! */
+ }
+ else
+ {
+ mcdprintf("\nNot reinserting question into list");
+ /* not recycling questions so fewer questions remain: */
+ unanswered--;
+ }
+
+ #ifdef MC_DEBUG
+ print_counters();
+ printf("\nLeaving MC_AnsweredCorrectly()\n");
+ #endif
+
+ return 1;
+}
+
+/* MC_NotAnsweredCorrectly() is how the user interface */
+/* tells MathCards that the player failed to answer the */
+/* question correctly. Returns 1 if no errors. */
+/* Note: this gets triggered only if a player's city */
+/* gets hit by a question, not if they "miss". */
+int MC_NotAnsweredCorrectly(MC_FlashCard* fc)
+{
+ mcdprintf("\nEntering MC_NotAnsweredCorrectly()");
+
+ if (!fc)
+ {
+ fprintf(stderr, "\nMC_NotAnsweredCorrectly() passed invalid pointer as argument!\n");
+
+ mcdprintf("\nInvalid MC_FlashCard* argument!");
+ mcdprintf("\nLeaving MC_NotAnsweredCorrectly()\n");
+
+ return 0;
+ }
+
+ #ifdef MC_DEBUG
+ printf("\nQuestion was:");
+ print_card(*fc);
+ #endif
+
+ answered_wrong++;
+ questions_pending--;
+
+ /* add question to wrong_quests list: */
+
+ MC_MathQuestion* ptr1;
+ MC_MathQuestion* ptr2;
+
+ ptr1 = create_node_from_card(fc);
+
+ if (!already_in_list(wrong_quests, ptr1)) /* avoid duplicates */
+ {
+ mcdprintf("\nAdding to wrong_quests list");
+ wrong_quests = append_node(wrong_quests, ptr1);
+ }
+ else /* avoid memory leak */
+ {
+ free(ptr1);
+ }
+
+ /* if desired, put question back in list so student sees it again */
+ if (math_opts->iopts[REPEAT_WRONGS])
+ {
+ int i;
+
+ mcdprintf("\nAdding %d copies to question_list:", math_opts->iopts[COPIES_REPEATED_WRONGS]);
+
+ /* can put in more than one copy (to drive the point home!) */
+ for (i = 0; i < math_opts->iopts[COPIES_REPEATED_WRONGS]; i++)
+ {
+ ptr1 = create_node_from_card(fc);
+ ptr2 = pick_random(quest_list_length, question_list);
+ question_list = insert_node(question_list, ptr2, ptr1);
+ quest_list_length++;
+ }
+ /* unanswered stays the same if a single copy recycled or */
+ /* increases by 1 for each "extra" copy reinserted: */
+ unanswered += (math_opts->iopts[COPIES_REPEATED_WRONGS] - 1);
+ }
+ else
+ {
+ mcdprintf("\nNot repeating wrong answers\n");
+
+ /* not repeating questions so list gets shorter: */
+ unanswered--;
+ }
+
+ #ifdef MC_DEBUG
+ print_counters();
+ printf("\nLeaving MC_NotAnswered_Correctly()\n");
+ #endif
+
+ return 1;
+
+}
+
+/* Tells user interface if all questions have been answered correctly! */
+/* Requires that at list contained at least one question to start with */
+/* and that wrongly answered questions have been recycled. */
+int MC_MissionAccomplished(void)
+{
+ if (starting_length
+ && math_opts->iopts[REPEAT_WRONGS]
+ && !unanswered)
+ {
+ return 1;
+ }
+ else
+ {
+ return 0;
+ }
+}
+
+/* Returns number of questions left (either in list */
+/* or "in play") */
+int MC_TotalQuestionsLeft(void)
+{
+ return unanswered;
+}
+
+/* Returns number of questions left in list, NOT */
+/* including questions currently "in play". */
+int MC_ListQuestionsLeft(void)
+{
+ return quest_list_length;
+}
+
+
+/* Store the amount of time a given flashcard was */
+/* visible on the screen. Returns 1 if the request */
+/* succeeds, 0 otherwise. */
+int MC_AddTimeToList(float t)
+{
+ int newsize = 0;
+ float *newlist;
+
+ /* This list will be allocated in an STL-like manner: when the */
+ /* list gets full, allocate an additional amount of storage equal */
+ /* to the current size of the list, so that only O(logN) allocations */
+ /* will ever be needed. We therefore have to keep track of 2 sizes: */
+ /* the allocated size, and the actual number of items currently on */
+ /* the list. */
+ if (length_time_per_question_list >= length_alloc_time_per_question_list) {
+ /* The list is full, allocate more space */
+ newsize = 2*length_time_per_question_list;
+ if (newsize == 0)
+ newsize = 100;
+ newlist = realloc(time_per_question_list,newsize*sizeof(float));
+ if (newlist == NULL) {
+ #ifdef MC_DEBUG
+ printf("\nError: allocation for time_per_question_list failed\n");
+ #endif
+ return 0;
+ }
+ time_per_question_list = newlist;
+ length_alloc_time_per_question_list = newsize;
+ }
+
+ /* Append the time to the list */
+ time_per_question_list[length_time_per_question_list++] = t;
+ return 1;
+}
+
+/* Frees heap memory used in program: */
+void MC_EndGame(void)
+{
+ delete_list(question_list);
+ question_list = 0;
+ delete_list(wrong_quests);
+ wrong_quests = 0;
+
+ if (math_opts)
+ {
+ free(math_opts);
+ math_opts = 0;
+ }
+
+ free(time_per_question_list);
+ time_per_question_list = NULL;
+ length_alloc_time_per_question_list = 0;
+ length_time_per_question_list = 0;
+
+ initialized = 0;
+}
+
+
+
+/* prints struct to file */
+void MC_PrintMathOptions(FILE* fp, int verbose)
+{
+ int i, vcommentsprimed = 0;
+ //comments when writing out verbose...perhaps they can go somewhere less conspicuous
+ static char* vcomments[NOPTS];
+ if (!vcommentsprimed) //we only want to initialize these once
+ {
+ vcommentsprimed = 1;
+ for (i = 0; i < NOPTS; ++i)
+ vcomments[i] = NULL;
+ vcomments[PLAY_THROUGH_LIST] =
+ "\n############################################################\n"
+ "# #\n"
+ "# General Math Options #\n"
+ "# #\n"
+ "# If 'play_through_list' is true, Tuxmath will ask each #\n"
+ "# question in an internally-generated list. The list is #\n"
+ "# generated based on the question ranges selected below. #\n"
+ "# The game ends when no questions remain. #\n"
+ "# If 'play_through_list' is false, the game continues #\n"
+ "# until all cities are destroyed. #\n"
+ "# Default is 1 (i.e. 'true' or 'yes'). #\n"
+ "# #\n"
+ "# 'question_copies' is the number of times each question #\n"
+ "# will be asked. It can be 1 to 10 - Default is 1. #\n"
+ "# #\n"
+ "# 'repeat_wrongs' tells Tuxmath whether to reinsert #\n"
+ "# incorrectly answered questions into the list to be #\n"
+ "# asked again. Default is 1 (yes). #\n"
+ "# #\n"
+ "# 'copies_repeated_wrongs' gives the number of times an #\n"
+ "# incorrectly answered question will reappear. Default #\n"
+ "# is 1. #\n"
+ "# #\n"
+ "# The defaults for these values result in a 'mission' #\n"
+ "# for Tux that is accomplished by answering all #\n"
+ "# questions correctly with at least one surviving city. #\n"
+ "############################################################\n\n";
+
+ vcomments[FORMAT_ADD_ANSWER_LAST] =
+ "\n############################################################\n"
+ "# The 'format_<op>_answer_<place> options control #\n"
+ "# generation of questions with the answer in different #\n"
+ "# places in the equation. i.e.: #\n"
+ "# #\n"
+ "# format_add_answer_last: 2 + 2 = ? #\n"
+ "# format_add_answer_first: ? + 2 = 4 #\n"
+ "# format_add_answer_middle: 2 + ? = 4 #\n"
+ "# #\n"
+ "# By default, 'format_answer_first' is enabled and the #\n"
+ "# other two formats are disabled. Note that the options #\n"
+ "# are not mutually exclusive - the question list may #\n"
+ "# contain questions with different formats. #\n"
+ "# #\n"
+ "# The formats are set independently for each of the four #\n"
+ "# math operations. #\n"
+ "############################################################\n\n";
+
+ vcomments[ALLOW_NEGATIVES] =
+ "\n############################################################\n"
+ "# 'allow_negatives' allows or disallows use of negative #\n"
+ "# numbers as both operands and answers. Default is 0 #\n"
+ "# (no), which disallows questions like: #\n"
+ "# 2 - 4 = ? #\n"
+ "# Note: this option must be enabled in order to set the #\n"
+ "# operand ranges to include negatives (see below). If it #\n"
+ "# is changed from 1 (yes) to 0 (no), any negative #\n"
+ "# operand limits will be reset to 0. #\n"
+ "############################################################\n\n";
+
+ vcomments[MAX_ANSWER] =
+ "\n############################################################\n"
+ "# 'max_answer' is the largest absolute value allowed in #\n"
+ "# any value in a question (not only the answer). Default #\n"
+ "# is 144. It can be set as high as 999. #\n"
+ "############################################################\n\n";
+
+ vcomments[MAX_QUESTIONS] =
+ "\n############################################################\n"
+ "# 'max_questions' is limit of the length of the question #\n"
+ "# list. Default is 5000 - only severe taskmasters will #\n"
+ "# need to raise it. #\n"
+ "############################################################\n\n";
+
+ vcomments[RANDOMIZE] =
+ "\n############################################################\n"
+ "# If 'randomize' selected, the list will be shuffled #\n"
+ "# at the start of the game. Default is 1 (yes). #\n"
+ "############################################################\n\n";
+
+ vcomments[ADDITION_ALLOWED] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Math Operations Allowed #\n"
+ "# #\n"
+ "# These options enable questions for each of the four math #\n"
+ "# operations. All are 1 (yes) by default. #\n"
+ "############################################################\n\n";
+
+ vcomments[MIN_AUGEND] =
+ "\n############################################################\n"
+ "# #\n"
+ "# Minimum and Maximum Values for Operand Ranges #\n"
+ "# #\n"
+ "# Operand limits can be set to any integer up to the #\n"
+ "# value of 'max_answer'. If 'allow_negatives' is set to 1 #\n"
+ "# (yes), either negative or positive values can be used. #\n"
+ "# Tuxmath will generate questions for every value in the #\n"
+ "# specified range. The maximum must be greater than or #\n"
+ "# equal to the corresponding minimum for any questions to #\n"
+ "# be generated for that operation. #\n"
+ "############################################################\n\n";
+
+ }
+
+
+ mcdprintf("\nEntering MC_PrintMathOptions()\n");
+
+ /* bail out if no struct */
+ if (!math_opts)
+ {
+ fprintf(stderr, "\nMath Options struct does not exist!\n");
+ return;
+ }
+
+ for (i = 0; i < NOPTS; ++i)
+ {
+ if (verbose && vcomments[i] != NULL)
+ fprintf(fp, vcomments[i]);
+ fprintf(fp, "%s = %d\n", MC_OPTION_TEXT[i], math_opts->iopts[i]);
+ }
+ mcdprintf("\nLeaving MC_PrintMathOptions()\n");
+}
+
+
+
+int MC_PrintQuestionList(FILE* fp)
+{
+ if (fp && question_list)
+ {
+ print_list(fp, question_list);
+ return 1;
+ }
+ else
+ {
+ fprintf(stderr, "\nFile pointer and/or question list invalid\n");
+ return 0;
+ }
+}
+
+int MC_PrintWrongList(FILE* fp)
+{
+ if (!fp)
+ {
+ fprintf(stderr, "File pointer invalid\n");
+ return 0;
+ }
+
+ if (wrong_quests)
+ {
+ print_list(fp, wrong_quests);
+ }
+ else
+ {
+ fprintf(fp, "\nNo wrong questions!\n");
+ }
+
+ return 1;
+}
+
+
+int MC_StartingListLength(void)
+{
+ return starting_length;
+}
+
+
+int MC_WrongListLength(void)
+{
+ return list_length(wrong_quests);
+}
+
+int MC_NumAnsweredCorrectly(void)
+{
+ return answered_correctly;
+}
+
+
+int MC_NumNotAnsweredCorrectly(void)
+{
+ return answered_wrong;
+}
+
+
+/* Report the median time per question */
+float MC_MedianTimePerQuestion(void)
+{
+ if (length_time_per_question_list == 0)
+ return 0;
+
+ qsort(time_per_question_list,length_time_per_question_list,sizeof(float),floatCompare);
+ return time_per_question_list[length_time_per_question_list/2];
+}
+
+/* Implementation of "private methods" - (cannot be called from outside
+of this file) */
+
+
+
+/* Resets negative values to zero - used when allow_negatives deselected. */
+void clear_negatives(void)
+{
+ int i;
+ for (i = MIN_AUGEND; i <= MAX_TYPING_NUM; ++i)
+ if (math_opts->iopts[i]< 0)
+ math_opts->iopts[i]= 0;
+}
+
+/* this is used by generate_list to see if a possible question */
+/* meets criteria to be added to the list or not: */
+int validate_question(int n1, int n2, int n3)
+{
+ /* make sure none of values exceeds max_answer using absolute */
+ /* value comparison: */
+ if (abs_value(n1) > abs_value(math_opts->iopts[MAX_ANSWER])
+ || abs_value(n2) > abs_value(math_opts->iopts[MAX_ANSWER])
+ || abs_value(n3) > abs_value(math_opts->iopts[MAX_ANSWER]))
+ {
+ return 0;
+ }
+ /* make sure none of values are negative if negatives not allowed: */
+ if (!math_opts->iopts[ALLOW_NEGATIVES])
+ {
+ if (n1 < 0 || n2 < 0 || n3 < 0)
+ {
+ return 0;
+ }
+ }
+ return 1;
+}
+
+/* create a new node and return a pointer to it */
+MC_MathQuestion* create_node(int n1, int n2, int op, int ans, int f)
+{
+ MC_MathQuestion* ptr = NULL;
+
+ ptr = (MC_MathQuestion*)malloc(sizeof(MC_MathQuestion));
+
+ if (!ptr)
+ {
+ fprintf(stderr, "create_node() - malloc() failed!\n");
+ return NULL;
+ }
+
+ ptr->card = MC_AllocateFlashcard();
+ ptr->next = NULL;
+ ptr->previous = NULL;
+
+ snprintf(ptr->card.formula_string, max_formula_size, "%d %c %d = ?",
+ n1, op < MC_NUM_OPERS ? operchars[op] : '\0', n2);
+ snprintf(ptr->card.answer_string, max_formula_size, "%d", ans);
+ ptr->card.difficulty = 25 * (op + 1);
+
+
+ /* ptr should now point to a properly constructed node: */
+ return ptr;
+}
+
+MC_MathQuestion* create_node_from_card(const MC_FlashCard* flashcard)
+{
+ MC_MathQuestion* ret = allocate_node();
+ copy_card(flashcard, &(ret->card));
+ return ret;
+}
+
+/* FIXME take care of strings */
+/* this one copies the contents, including pointers; both nodes must be allocated */
+int copy_node(MC_MathQuestion* original, MC_MathQuestion* copy)
+{
+ if (!original)
+ {
+ fprintf(stderr, "\nIn copy_node(): invalid 'original' pointer arg.\n");
+ return 0;
+ }
+ if (!copy)
+ {
+ fprintf(stderr, "\nIn copy_node(): invalid 'copy' pointer arg.\n");
+ return 0;
+ }
+
+ copy_card(&(original->card), &(copy->card) );
+
+ copy->next = original->next;
+ copy->previous = original->previous;
+ copy->randomizer = original->randomizer;
+ return 1;
+}
+
+
+
+
+/* this puts the node into the list AFTER the node pointed to by current */
+/* and returns a pointer to the top of the modified list */
+MC_MathQuestion* insert_node(MC_MathQuestion* first, MC_MathQuestion* current, MC_MathQuestion* new_node)
+{
+ /* return pointer to list unchanged if new_node doesn't exist*/
+ if (!new_node)
+ return first;
+ /* if current doesn't exist, new_node is first */
+ if (!current)
+ {
+ new_node->previous = 0;
+ new_node->next =0;
+ first = new_node;
+ return first;
+ }
+
+ if (current->next) /* avoid error if at end of list */
+ current->next->previous = new_node;
+ new_node->next = current->next;
+ current->next = new_node;
+ new_node->previous = current;
+ return first;
+}
+
+
+
+/* adds the new node to the end of the list */
+MC_MathQuestion* append_node(MC_MathQuestion* list, MC_MathQuestion* new_node)
+{
+ MC_MathQuestion* ptr;
+ /* return pointer to list unchanged if new_node doesn't exist*/
+ if (!new_node)
+ {
+ return list;
+ }
+
+ /* if list does not exist, new_node is the first (and only) node */
+ if (!list)
+ {
+ return new_node;
+ }
+ /* otherwise, go to end of list */
+ ptr = list;
+ while (ptr->next)
+ {
+ ptr = ptr->next;
+ }
+
+ ptr->next = new_node;
+ new_node->previous = ptr;
+ new_node->next = 0;
+ return list;
+}
+
+
+
+/* this takes the node out of the list but does not delete it */
+/* and returns a pointer to the top of the modified list */
+MC_MathQuestion* remove_node(MC_MathQuestion* first, MC_MathQuestion* n)
+{
+ if (!n || !first)
+ return first;
+ /* special case if first node being removed */
+ if (n == first)
+ first = first->next;
+
+ if (n->previous)
+ n->previous->next = n->next;
+ if (n->next)
+ n->next->previous = n->previous;
+ n->previous = 0;
+ n->next = 0;
+ return first;
+}
+
+
+
+/* frees memory for entire list and returns null pointer */
+MC_MathQuestion* delete_list(MC_MathQuestion* list)
+{
+ MC_MathQuestion* tmp_ptr;
+ while (list)
+ {
+ tmp_ptr = list->next;
+ free_node (list);
+ list = tmp_ptr;
+ }
+ return list;
+}
+
+
+
+void print_list(FILE* fp, MC_MathQuestion* list)
+{
+ if (!list)
+ {
+ fprintf(fp, "\nprint_list(): list empty or pointer invalid\n");
+ return;
+ }
+
+ MC_MathQuestion* ptr = list;
+ while (ptr)
+ {
+ fprintf(stderr, "%s\n", ptr->card.formula_string);
+ ptr = ptr->next;
+ }
+}
+
+void print_vect_list(FILE* fp, MC_MathQuestion** vect, int length)
+{
+ if (!vect)
+ {
+ fprintf(fp, "\nprint_vect_list(): list empty or pointer invalid\n");
+ return;
+ }
+
+ int i = 0;
+ mcdprintf("Entering print_vect_list()\n");
+ for(i = 0; i < length; i++)
+ fprintf(fp, "%s\n", vect[i]->card.formula_string);
+
+ mcdprintf("Leaving print_vect_list()\n");
+}
+
+#ifdef MC_DEBUG
+void print_card(MC_FlashCard card)
+{
+ printf("\nprint_card():");
+ printf("formula_string = %s, answer_string = %s\n",
+ card.formula_string, card.answer_string);
+}
+
+/* This sends the values of all "global" counters and the */
+/* lengths of the question lists to stdout - for debugging */
+void print_counters(void)
+{
+ printf("\nquest_list_length = \t%d", quest_list_length);
+ printf("\nlist_length(question_list) = \t%d", list_length(question_list));
+ printf("\nstarting_length = \t%d", starting_length);
+ printf("\nunanswered = \t%d", unanswered);
+ printf("\nanswered_correctly = \t%d", answered_correctly);
+ printf("\nanswered_wrong = \t%d", answered_wrong);
+ printf("\nlist_length(wrong_quests) = \t%d", list_length(wrong_quests));
+ printf("\nquestions_pending = \t%d", questions_pending);
+}
+
+/* a "copy constructor", so to speak */
+/* FIXME should properly return newly allocated list if more than one node DSB */
+MC_MathQuestion* create_node_copy(MC_MathQuestion* other)
+{
+ MC_MathQuestion* ret = allocate_node();
+ if (ret)
+ copy_card(&(other->card), &(ret->card) );
+ return ret;
+}
+
+/* FIXME take care of strings */
+
+MC_FlashCard create_card_from_node(MC_MathQuestion* node)
+{
+ MC_FlashCard fc;
+ if (!node)
+ return DEFAULT_CARD;
+ fc = MC_AllocateFlashcard();
+ copy_card(&(node->card), &fc);
+ return fc;
+}
+#endif
+
+int list_length(MC_MathQuestion* list)
+{
+ int length = 0;
+ while (list)
+ {
+ length++;
+ list = list->next;
+ }
+ return length;
+}
+
+
+
+
+
+
+/* This is a new implementation written in an attempt to avoid */
+/* the O(n^2) performance problems seen with the old randomization */
+/* function. The list is created as a vector, but is for now still */
+/* made a linked list to minimize changes needed elsewhere. */
+/* The argument is a pointer to the top of the old list. This extra */
+/* level of indirection allows the list to be shuffled "in-place". */
+/* The function returns 1 if successful, 0 on errors. */
+
+static int randomize_list(MC_MathQuestion** old_list)
+{
+ MC_MathQuestion* old_tmp = *old_list;
+ MC_MathQuestion** tmp_vect = NULL;
+
+ int i = 0;
+ if (!old_list || !*old_list) //invalid/empty list
return 0;
- }
-
- /* set general math options */
- math_opts->play_through_list = DEFAULT_PLAY_THROUGH_LIST;
- math_opts->repeat_wrongs = DEFAULT_REPEAT_WRONGS;
- math_opts->copies_repeated_wrongs = DEFAULT_COPIES_REPEATED_WRONGS;
- math_opts->allow_negatives = DEFAULT_ALLOW_NEGATIVES;
- math_opts->max_answer = DEFAULT_MAX_ANSWER;
- math_opts->max_questions = DEFAULT_MAX_QUESTIONS;
- math_opts->question_copies = DEFAULT_QUESTION_COPIES;
- math_opts->randomize = DEFAULT_RANDOMIZE;
- math_opts->fraction_to_keep = DEFAULT_FRACTION_TO_KEEP;
- /* set question formats: */
- math_opts->format_add_answer_last = DEFAULT_FORMAT_ADD_ANSWER_LAST;
- math_opts->format_add_answer_first = DEFAULT_FORMAT_ADD_ANSWER_FIRST;
- math_opts->format_add_answer_middle = DEFAULT_FORMAT_ADD_ANSWER_MIDDLE;
- math_opts->format_sub_answer_last = DEFAULT_FORMAT_SUB_ANSWER_LAST;
- math_opts->format_sub_answer_first = DEFAULT_FORMAT_SUB_ANSWER_FIRST;
- math_opts->format_sub_answer_middle = DEFAULT_FORMAT_SUB_ANSWER_MIDDLE;
- math_opts->format_mult_answer_last = DEFAULT_FORMAT_MULT_ANSWER_LAST;
- math_opts->format_mult_answer_first = DEFAULT_FORMAT_MULT_ANSWER_FIRST;
- math_opts->format_mult_answer_middle = DEFAULT_FORMAT_MULT_ANSWER_MIDDLE;
- math_opts->format_div_answer_last = DEFAULT_FORMAT_DIV_ANSWER_LAST;
- math_opts->format_div_answer_first = DEFAULT_FORMAT_DIV_ANSWER_FIRST;
- math_opts->format_div_answer_middle = DEFAULT_FORMAT_DIV_ANSWER_MIDDLE;
-
- /* set addition options: */
- math_opts->addition_allowed = DEFAULT_ADDITION_ALLOWED;
- math_opts->min_augend = DEFAULT_MIN_AUGEND;
- math_opts->max_augend = DEFAULT_MAX_AUGEND;
- math_opts->min_addend = DEFAULT_MIN_ADDEND;
- math_opts->max_addend = DEFAULT_MAX_ADDEND;
- /* set subtraction options: */
- math_opts->subtraction_allowed = DEFAULT_SUBTRACTION_ALLOWED;
- math_opts->min_minuend = DEFAULT_MIN_MINUEND;
- math_opts->max_minuend = DEFAULT_MAX_MINUEND;
- math_opts->min_subtrahend = DEFAULT_MIN_SUBTRAHEND;
- math_opts->max_subtrahend = DEFAULT_MAX_SUBTRAHEND;
- /* set multiplication options: */
- math_opts->multiplication_allowed = DEFAULT_MULTIPLICATION_ALLOWED;
- math_opts->min_multiplier = DEFAULT_MIN_MULTIPLIER;
- math_opts->max_multiplier = DEFAULT_MAX_MULTIPLIER;
- math_opts->min_multiplicand = DEFAULT_MIN_MULTIPLICAND;
- math_opts->max_multiplicand = DEFAULT_MAX_MULTIPLICAND;
- /* set division options: */
- math_opts->division_allowed = DEFAULT_DIVISION_ALLOWED;
- math_opts->min_divisor = DEFAULT_MIN_DIVISOR;
- math_opts->max_divisor = DEFAULT_MAX_DIVISOR;
- math_opts->min_quotient = DEFAULT_MIN_QUOTIENT;
- math_opts->max_quotient = DEFAULT_MAX_QUOTIENT;
- /* set typing practice options: */
- math_opts->typing_practice_allowed = DEFAULT_TYPING_PRACTICE_ALLOWED;
- math_opts->min_typing_num = DEFAULT_MIN_TYPING_NUM;
- math_opts->max_typing_num = DEFAULT_MAX_TYPING_NUM;
-
- /* if no negatives to be used, reset any negatives to 0 */
- if (!math_opts->allow_negatives)
- {
- clear_negatives();
- }
-
- initialized = 1;
-
- #ifdef MC_DEBUG
- MC_PrintMathOptions(stdout, 0);
- printf("\nLeaving MC_Initialize()\n");
- #endif
-
- return 1;
-}
-
-
-
-/* MC_StartGame() generates the list of math questions */
-/* based on existing settings. It should be called at */
-/* the beginning of each math game for the player. */
-/* Returns 1 if resultant list contains 1 or more */
-/* questions, 0 if list empty or not generated */
-/* successfully. */
-int MC_StartGame(void)
-{
- #ifdef MC_DEBUG
- printf("\nEntering MC_StartGame()");
- #endif
-
- /* if math_opts not set up yet, initialize it: */
- if (!initialized)
- {
-
- #ifdef MC_DEBUG
- printf("\nNot initialized - calling MC_Initialize()");
- #endif
-
- MC_Initialize();
- }
-
- if (!math_opts)
- {
- #ifdef MC_DEBUG
- printf("\nCould not initialize - bailing out");
- printf("\nLeavinging MC_StartGame()\n");
- #endif
-
- return 0;
- }
- /* we know math_opts exists if we make it to here */
- /* clear out old lists if starting another game: (if not done already) */
- delete_list(question_list);
- question_list = NULL;
- delete_list(wrong_quests);
- wrong_quests = NULL;
+ int old_length = list_length(old_tmp);
+
+ /* set random seed: */
+ srand(time(0));
+
+
+ /* Allocate vector and set ptrs to nodes in old list: */
+
+ /* Allocate a list of pointers, not space for the nodes themselves: */
+ tmp_vect = (MC_MathQuestion**)malloc(sizeof(MC_MathQuestion*) * old_length);
+ /* Set each pointer in the vector to the corresponding node: */
+ for (i = 0; i < old_length; i++)
+ {
+ tmp_vect[i] = old_tmp;
+ tmp_vect[i]->randomizer = rand();
+ old_tmp = old_tmp->next;
+ }
+
+ /* Now simply sort on 'tmp_vect[i]->randomizer' to shuffle list: */
+ qsort(tmp_vect, old_length,
+ sizeof(MC_MathQuestion*),
+ comp_randomizer);
+
+ /* Re-create pointers to provide linked-list functionality: */
+ /* (stop at 'old_length-1' because we dereference tmp_vect[i+1]) */
+ for(i = 0; i < old_length - 1; i++)
+ {
+ if (!tmp_vect[i])
+ {
+ fprintf(stderr, "Invalid pointer!\n");
+ return 0;
+ }
+ tmp_vect[i]->next = tmp_vect[i+1];
+ tmp_vect[i+1]->previous = tmp_vect[i];
+ }
+ /* Handle end cases: */
+ tmp_vect[0]->previous = NULL;
+ tmp_vect[old_length-1]->next = NULL;
+
+ /* Now arrange for arg pointer to indirectly point to first element! */
+ *old_list = tmp_vect[0];
+ free(tmp_vect);
+ return 1;
+}
+
+
+
+/* This is needed for qsort(): */
+int comp_randomizer (const void* a, const void* b)
+{
+
+ int int1 = (*(const struct MC_MathQuestion **) a)->randomizer;
+ int int2 = (*(const struct MC_MathQuestion **) b)->randomizer;
+
+ if (int1 > int2)
+ return 1;
+ else if (int1 == int2)
+ return 0;
+ else
+ return -1;
+}
+
+MC_MathQuestion* pick_random(int length, MC_MathQuestion* list)
+{
+ int i;
+ int rand_node;
+
+ /* set random seed DSB */
+ srand(time(0));
+
+ /* if length is zero, get out to avoid divide-by-zero error */
+ if (0 == length)
+ {
+ return list;
+ }
+
+ rand_node = rand() % length;
+
+ for (i=1; i < rand_node; i++)
+ {
+ if (list)
+ list = list->next;
+ }
+
+ return list;
+}
+
+/* compares fields other than pointers */
+int compare_node(MC_MathQuestion* first, MC_MathQuestion* other)
+{
+ if (!first || !other)
+ return 0;
+ if (compare_card(&(first->card), &(first->card) ) ) //cards are equal
+ return 1;
+ else
+ return 0;
+}
+
+/* check to see if list already contains an identical node */
+int already_in_list(MC_MathQuestion* list, MC_MathQuestion* ptr)
+{
+ if (!list || !ptr)
+ return 0;
+
+ while (list)
+ {
+ if (compare_node(list, ptr))
+ return 1;
+ list = list->next;
+ }
+ return 0;
+}
+
+/* to prevent option settings in math_opts from getting set to */
+/* values other than 0 or 1 */
+int int_to_bool(int i)
+{
+ if (i)
+ return 1;
+ else
+ return 0;
+}
+
+/* prevent values from getting into math_opts that are outside */
+/* the range that can be handled by the program (i.e. more */
+/* than three digits; also disallow negatives if that has been */
+/* selected. */
+int sane_value(int i)
+{
+ if (i > MC_GLOBAL_MAX)
+ i = MC_GLOBAL_MAX;
+ else if (i < -MC_GLOBAL_MAX)
+ i = -MC_GLOBAL_MAX;
+
+ if (i < 0
+ && math_opts
+ && !math_opts->iopts[ALLOW_NEGATIVES])
+ {
+ i = 0;
+ }
+
+ return i;
+}
+
+int abs_value(int i)
+{
+ if (i > 0)
+ return i;
+ else
+ return -i;
+}
+
+int log10i(int i) //base 10 logarithm for ints
+{
+ int j;
+ for (j = 0; i > 0; i /= 10, ++j);
+ return j;
+}
+
+/* Compares two floats (needed for sorting in MC_MedianTimePerQuestion) */
+int floatCompare(const void *v1,const void *v2)
+{
+ float f1,f2;
+
+ f1 = *((float *) v1);
+ f2 = *((float *) v2);
+
+ if (f1 < f2)
+ return -1;
+ else if (f1 > f2)
+ return 1;
+ else
+ return 0;
+}
+
+
+
+/****************************************************
+Functions for new mathcards architecture
+****************************************************/
+
+void copy_card(const MC_FlashCard* src, MC_FlashCard* dest)
+{
+ if (!src || !dest)
+ return;
+ mcdprintf("Copying '%s' to '%s', ", src->formula_string,dest->formula_string);
+ mcdprintf("copying '%s' to '%s'\n", src->answer_string, dest->answer_string);
+ strncpy(dest->formula_string, src->formula_string, max_formula_size);
+ strncpy(dest->answer_string, src->answer_string, max_answer_size);
+ mcdprintf("Card is: '%s', '%s'\n", dest->formula_string, dest->answer_string);
+ dest->answer = src->answer;
+ dest->difficulty = src->difficulty;
+}
+
+void free_node(MC_MathQuestion* mq) //no, not that freenode.
+{
+ if (!mq)
+ return;
+ MC_FreeFlashcard(&(mq->card) );
+ free(mq);
+}
+
+MC_MathQuestion* allocate_node()
+{
+ MC_MathQuestion* ret = NULL;
+ ret = malloc(sizeof(MC_MathQuestion) );
+ if (!ret)
+ {
+ printf("Could not allocate space for a new node!\n");
+ return NULL;
+ }
- /* clear the time list */
- if (time_per_question_list != NULL) {
- free(time_per_question_list);
- time_per_question_list = NULL;
- length_time_per_question_list = 0;
- length_alloc_time_per_question_list = 0;
- }
-
- /* set up new list with pointer to top: */
- question_list = generate_list();
-
- next_wrong_quest = 0;
- /* initialize counters for new game: */
- quest_list_length = list_length(question_list);
- /* Note: the distinction between quest_list_length and */
- /* unanswered is that the latter includes questions */
- /* that are currently "in play" by the user interface - */
- /* it is only decremented when an answer to the question*/
- /* is received. */
- unanswered = starting_length = quest_list_length;
- answered_correctly = 0;
- answered_wrong = 0;
- questions_pending = 0;
-
- #ifdef MC_DEBUG
- print_counters();
- #endif
-
- /* make sure list now exists and has non-zero length: */
- if (question_list && quest_list_length)
- {
- #ifdef MC_DEBUG
- printf("\nGame set up successfully");
- printf("\nLeaving MC_StartGame()\n");
- #endif
-
- return 1;
- }
- else
- {
- #ifdef MC_DEBUG
- printf("\nGame NOT set up successfully - no valid list");
- printf("\nLeaving MC_StartGame()\n");
- #endif
-
- return 0;
- }
-}
-
-/* MC_StartGameUsingWrongs() is like MC_StartGame(), */
-/* but uses the incorrectly answered questions from the */
-/* previous game for the question list as a review form */
-/* of learning. If there were no wrong answers (or no */
-/* previous game), it behaves just like MC_StartGame(). */
-/* FIXME wonder if it should return a different value if */
-/* the list is created from settings because there is no */
-/* valid wrong question list? */
-int MC_StartGameUsingWrongs(void)
-{
- #ifdef MC_DEBUG
- printf("\nEntering MC_StartGameUsingWrongs()");
- #endif
-
- /* Note: if not initialized, control will pass to */
- /* MC_StartGame() via else clause so don't need to test */
- /* for initialization here */
- if (wrong_quests &&
- list_length(wrong_quests))
- {
- #ifdef MC_DEBUG
- printf("\nNon-zero length wrong_quests list found, will");
- printf("\nuse for new game list:");
- #endif
-
- /* initialize lists for new game: */
- delete_list(question_list);
- if(!randomize_list(&wrong_quests)) {
- fprintf(stderr, "Error during randomization of wrong_quests!\n");
- /* Punt on trying wrong question list, just run normal game */
- return MC_StartGame();
- }
- question_list = wrong_quests;
- wrong_quests = 0;
- next_wrong_quest = 0;
- /* initialize counters for new game: */
- quest_list_length = list_length(question_list);
- unanswered = starting_length = quest_list_length;
- answered_correctly = 0;
- answered_wrong = 0;
- questions_pending = 0;
-
- #ifdef MC_DEBUG
- print_counters();
- print_list(stdout, question_list);
- printf("\nLeaving MC_StartGameUsingWrongs()\n");
- #endif
-
- return 1;
- }
- else /* if no wrong_quests list, go to MC_StartGame() */
- /* to set up list based on math_opts */
- {
- #ifdef MC_DEBUG
- printf("\nNo wrong questions to review - generate list from math_opts\n");
- printf("\nLeaving MC_StartGameUsingWrongs()\n");
- #endif
-
- return MC_StartGame();
- }
-}
-
-
-/* MC_NextQuestion() takes a pointer to an allocated */
-/* MC_MathQuestion struct and fills in the fields for */
-/* use by the user interface program. It basically is */
-/* like taking the next flashcard from the pile. The */
-/* node containing the question is removed from the list.*/
-/* Returns 1 if question found, 0 if list empty/invalid */
-/* or if argument pointer is invalid. */
-int MC_NextQuestion(MC_FlashCard* fc)
-{
- #ifdef MC_DEBUG
- printf("\nEntering MC_NextQuestion()");
- #endif
-
- /* (so we can free the node after removed from list:) */
- MC_MathQuestion* ptr;
- ptr = question_list;
-
- if (!fc )
- {
- fprintf(stderr, "\nInvalid MC_FlashCard* argument!\n");
-
- #ifdef MC_DEBUG
- printf("\nInvalid MC_FlashCard* argument!");
- printf("\nLeaving MC_NextQuestion()\n");
- #endif
-
- return 0;
- }
-
- if (!question_list ||
-/* !next_question || */
- !list_length(question_list) )
- {
- #ifdef MC_DEBUG
- printf("\nquestion_list invalid or empty");
- printf("\nLeaving MC_NextQuestion()\n");
- #endif
-
- return 0;
- }
- /* FIXME: could clean this up a bit with a copy_card() function */
- fc->num1 = question_list->card.num1;
- fc->num2 = question_list->card.num2;
- fc->num3 = question_list->card.num3;
- fc->operation = question_list->card.operation;
- fc->format = question_list->card.format;
- strncpy(fc->formula_string, question_list->card.formula_string, MC_FORMULA_LEN);
- strncpy(fc->answer_string, question_list->card.answer_string, MC_ANSWER_LEN);
-
- /* take first question node out of list and free it: */
- question_list = remove_node(question_list, question_list);
- free(ptr);
- quest_list_length--;
- questions_pending++;
-
- #ifdef MC_DEBUG
- printf("\nnext question is:");
- print_card(*fc);
- print_counters();
- printf("\nLeaving MC_NextQuestion()\n");
- #endif
-
- return 1;
-}
-
-/* MC_AnsweredCorrectly() is how the user interface */
-/* tells MathCards that the question has been answered */
-/* correctly. Returns 1 if no errors. */
-int MC_AnsweredCorrectly(MC_FlashCard* fc)
-{
- #ifdef MC_DEBUG
- printf("\nEntering MC_AnsweredCorrectly()");
- #endif
-
- if (!fc)
- {
- fprintf(stderr, "\nMC_AnsweredCorrectly() passed invalid pointer as argument!\n");
-
- #ifdef MC_DEBUG
- printf("\nInvalid MC_FlashCard* argument!");
- printf("\nLeaving MC_AnsweredCorrectly()\n");
- #endif
-
- return 0;
- }
-
- #ifdef MC_DEBUG
- printf("\nQuestion was:");
- print_card(*fc);
- #endif
+ ret->card = MC_AllocateFlashcard();
+ ret->next = ret->previous = NULL;
- answered_correctly++;
- questions_pending--;
-
- if (!math_opts->play_through_list)
- /* reinsert question into question list at random location */
- {
- #ifdef MC_DEBUG
- printf("\nReinserting question into list");
- #endif
-
- MC_MathQuestion* ptr1;
- MC_MathQuestion* ptr2;
- /* make new node using values from flashcard */
- ptr1 = create_node_from_card(fc);
- /* put it into list */
- ptr2 = pick_random(quest_list_length, question_list);
- question_list = insert_node(question_list, ptr2, ptr1);
- quest_list_length++;
- /* unanswered does not change - was not decremented when */
- /* question allocated! */
- }
- else
- {
- #ifdef MC_DEBUG
- printf("\nNot reinserting question into list");
- #endif
- /* not recycling questions so fewer questions remain: */
- unanswered--;
- }
-
- #ifdef MC_DEBUG
- print_counters();
- printf("\nLeaving MC_AnsweredCorrectly()\n");
- #endif
-
- return 1;
-}
-
-/* MC_NotAnsweredCorrectly() is how the user interface */
-/* tells MathCards that the player failed to answer the */
-/* question correctly. Returns 1 if no errors. */
-/* Note: this gets triggered only if a player's city */
-/* gets hit by a question, not if they "miss". */
-int MC_NotAnsweredCorrectly(MC_FlashCard* fc)
+ return ret;
+}
+
+/*
+The function that does the central dirty work pertaining to flashcard
+creation. Extensible to just about any kind of math problem, perhaps
+with the exception of those with multiple answers, such as "8 + 2 > ?"
+Simply specify how the problem is presented to the user, and the
+answer the game should look for, as strings.
+*/
+MC_FlashCard generate_random_flashcard(void)
+{
+ int num;
+ int length;
+ MC_ProblemType pt;
+ MC_FlashCard ret;
+
+ mcdprintf("Entering generate_random_flashcard()\n");
+
+
+
+ do
+ pt = rand() % MC_NUM_PTYPES;
+ while ( (pt == MC_PT_TYPING && !MC_GetOpt(TYPING_PRACTICE_ALLOWED) ) ||
+ (pt == MC_PT_ARITHMETIC && !MC_GetOpt(ADDITION_ALLOWED) &&
+ !MC_GetOpt(SUBTRACTION_ALLOWED) &&
+ !MC_GetOpt(MULTIPLICATION_ALLOWED) &&
+ !MC_GetOpt(DIVISION_ALLOWED) ) ||
+ (pt == MC_PT_COMPARISON && !MC_GetOpt(COMPARISON_ALLOWED) )
+ );
+
+ if (pt == MC_PT_TYPING) //typing practice
+ {
+ mcdprintf("Generating typing question\n");
+ ret = MC_AllocateFlashcard();
+ num = rand() % (MC_GetOpt(MAX_TYPING_NUM)-MC_GetOpt(MIN_TYPING_NUM) + 1)
+ + MC_GetOpt(MIN_TYPING_NUM);
+ snprintf(ret.formula_string, max_formula_size, "%d", num);
+ snprintf(ret.answer_string, max_answer_size, "%d", num);
+ ret.answer = num;
+ ret.difficulty = 10;
+ }
+ else //if (pt == MC_PT_ARITHMETIC)
+ {
+ mcdprintf("Generating arithmetic question");
+ length = rand() % (MC_GetOpt(MAX_FORMULA_NUMS) -
+ MC_GetOpt(MIN_FORMULA_NUMS) + 1) //avoid div by 0
+ + MC_GetOpt(MIN_FORMULA_NUMS);
+ mcdprintf(" of length %d", length);
+ ret = generate_random_ooo_card_of_length(length, 1);
+ #ifdef MC_DEBUG
+ print_card(ret);
+ #endif
+ }
+ //TODO comparison problems (e.g. "6 ? 9", "<")
+
+ mcdprintf("Exiting generate_random_flashcard()\n");
+
+ return ret;
+}
+
+/*
+Recursively generate an order of operations problem. Hopefully this won't
+raise performance issues. Difficulty is calculated based on the length of
+the formula and on the operators used. Problems have a 'base' difficulty of
+1 for binary operations, 3 for 3 numbers, 6, 10, etc. Each operator adds to
+the score: 0, 1, 2, and 3 respectively for addition, subtraction,
+multiplication and division.If reformat is 0, FORMAT_ANS_LAST will be used,
+otherwise a format is chosen at random.
+*/
+MC_FlashCard generate_random_ooo_card_of_length(int length, int reformat)
{
- #ifdef MC_DEBUG
- printf("\nEntering MC_NotAnsweredCorrectly()");
- #endif
-
- if (!fc)
- {
- fprintf(stderr, "\nMC_NotAnsweredCorrectly() passed invalid pointer as argument!\n");
-
- #ifdef MC_DEBUG
- printf("\nInvalid MC_FlashCard* argument!");
- printf("\nLeaving MC_NotAnsweredCorrectly()\n");
- #endif
-
- return 0;
- }
-
- #ifdef MC_DEBUG
- printf("\nQuestion was:");
- print_card(*fc);
- #endif
-
- answered_wrong++;
- questions_pending--;
-
- /* add question to wrong_quests list: */
-
- MC_MathQuestion* ptr1;
- MC_MathQuestion* ptr2;
-
- ptr1 = create_node_from_card(fc);
-
- if (!already_in_list(wrong_quests, ptr1)) /* avoid duplicates */
- {
- #ifdef MC_DEBUG
- printf("\nAdding to wrong_quests list");
- #endif
-
- wrong_quests = append_node(wrong_quests, ptr1);
- }
- else /* avoid memory leak */
- {
- free(ptr1);
- }
-
- /* if desired, put question back in list so student sees it again */
- if (math_opts->repeat_wrongs)
- {
- int i;
-
- #ifdef MC_DEBUG
- printf("\nAdding %d copies to question_list:", math_opts->copies_repeated_wrongs);
- #endif
-
- /* can put in more than one copy (to drive the point home!) */
- for (i = 0; i < math_opts->copies_repeated_wrongs; i++)
- {
- ptr1 = create_node_from_card(fc);
- ptr2 = pick_random(quest_list_length, question_list);
- question_list = insert_node(question_list, ptr2, ptr1);
- quest_list_length++;
+ int format = 0;
+ int r1 = 0;
+ int r2 = 0;
+ int ans = 0;
+ char tempstr[max_formula_size];
+ MC_FlashCard ret;
+ MC_Operation op;
+
+ printf(".");
+ if (length > MAX_FORMULA_NUMS)
+ return DEFAULT_CARD;
+ if (length <= 2)
+ {
+ mcdprintf("\n");
+ ret = MC_AllocateFlashcard();
+ for (op = rand() % MC_NUM_OPERS; //pick a random operation
+ MC_GetOpt(op + ADDITION_ALLOWED) == 0; //make sure it's allowed
+ op = rand() % MC_NUM_OPERS);
+
+ mcdprintf("Operation is %c\n", operchars[op]);
+ /*
+ if (op == MC_OPER_ADD)
+ {
+ r1 = rand() % (math_opts->iopts[MAX_AUGEND] - math_opts->iopts[MIN_AUGEND] + 1) + math_opts->iopts[MIN_AUGEND];
+ r2 = rand() % (math_opts->iopts[MAX_ADDEND] - math_opts->iopts[MIN_ADDEND] + 1) + math_opts->iopts[MIN_ADDEND];
+ ans = r1 + r2;
+ }
+ else if (op == MC_OPER_SUB)
+ {
+ r1 = rand() % (math_opts->iopts[MAX_MINUEND] - math_opts->iopts[MIN_MINUEND] + 1) + math_opts->iopts[MIN_MINUEND];
+ r2 = rand() % (math_opts->iopts[MAX_SUBTRAHEND] - math_opts->iopts[MIN_SUBTRAHEND] + 1) + math_opts->iopts[MIN_SUBTRAHEND];
+ ans = r1 - r2;
+ }
+ else if (op == MC_OPER_MULT)
+ {
+ r1 = rand() % (math_opts->iopts[MAX_MULTIPLIER] - math_opts->iopts[MIN_MULTIPLIER] + 1) + math_opts->iopts[MIN_MULTIPLIER];
+ r2 = rand() % (math_opts->iopts[MAX_MULTIPLICAND] - math_opts->iopts[MIN_MULTIPLICAND] + 1) + math_opts->iopts[MIN_MULTIPLICAND];
+ ans = r1 * r2;
+ }
+ else if (op == MC_OPER_DIV)
+ {
+ ans = rand() % (math_opts->iopts[MAX_QUOTIENT] - math_opts->iopts[MIN_QUOTIENT] + 1) + math_opts->iopts[MIN_QUOTIENT];
+ r2 = rand() % (math_opts->iopts[MAX_DIVISOR] - math_opts->iopts[MIN_DIVISOR] + 1) + math_opts->iopts[MIN_DIVISOR];
+ if (r2 == 0)
+ r2 = 1;
+ r1 = ans * r2;
}
- /* unanswered stays the same if a single copy recycled or */
- /* increases by 1 for each "extra" copy reinserted: */
- unanswered += (math_opts->copies_repeated_wrongs - 1);
- }
- else
- {
- #ifdef MC_DEBUG
- printf("\nNot repeating wrong answers\n");
- #endif
-
- /* not repeating questions so list gets shorter: */
- unanswered--;
- }
-
- #ifdef MC_DEBUG
- print_counters();
- printf("\nLeaving MC_NotAnswered_Correctly()\n");
- #endif
-
- return 1;
-
-}
-
-/* Tells user interface if all questions have been answered correctly! */
-/* Requires that at list contained at least one question to start with */
-/* and that wrongly answered questions have been recycled. */
-int MC_MissionAccomplished(void)
-{
- if (starting_length
- && math_opts->repeat_wrongs
- && !unanswered)
- {
- return 1;
- }
- else
- {
- return 0;
- }
-}
-
-/* Returns number of questions left (either in list */
-/* or "in play") */
-int MC_TotalQuestionsLeft(void)
-{
- return unanswered;
-}
-
-/* Returns number of questions left in list, NOT */
-/* including questions currently "in play". */
-int MC_ListQuestionsLeft(void)
-{
- return quest_list_length;
-}
-
-
-/* Store the amount of time a given flashcard was */
-/* visible on the screen. Returns 1 if the request */
-/* succeeds, 0 otherwise. */
-int MC_AddTimeToList(float t)
-{
- int newsize = 0;
- float *newlist;
-
- /* This list will be allocated in an STL-like manner: when the */
- /* list gets full, allocate an additional amount of storage equal */
- /* to the current size of the list, so that only O(logN) allocations */
- /* will ever be needed. We therefore have to keep track of 2 sizes: */
- /* the allocated size, and the actual number of items currently on */
- /* the list. */
- if (length_time_per_question_list >= length_alloc_time_per_question_list) {
- /* The list is full, allocate more space */
- newsize = 2*length_time_per_question_list;
- if (newsize == 0)
- newsize = 100;
- newlist = realloc(time_per_question_list,newsize*sizeof(float));
- if (newlist == NULL) {
- #ifdef MC_DEBUG
- printf("\nError: allocation for time_per_question_list failed\n");
- #endif
- return 0;
+ */
+ if (op > MC_OPER_DIV || op < MC_OPER_ADD)
+ {
+ mcdprintf("Invalid operator: value %d\n", op);
+ return DEFAULT_CARD;
}
- time_per_question_list = newlist;
- length_alloc_time_per_question_list = newsize;
- }
-
- /* Append the time to the list */
- time_per_question_list[length_time_per_question_list++] = t;
- return 1;
-}
-
-/* Frees heap memory used in program: */
-void MC_EndGame(void)
-{
- delete_list(question_list);
- question_list = 0;
- delete_list(wrong_quests);
- wrong_quests = 0;
-
- if (math_opts)
- {
- free(math_opts);
- math_opts = 0;
- }
-
- free(time_per_question_list);
- time_per_question_list = NULL;
- length_alloc_time_per_question_list = 0;
- length_time_per_question_list = 0;
-
- initialized = 0;
-}
-
-
-/* Simple Get()- and Set()-style functions for math options settings: */
-
-
-/* Set general math options: */
-void MC_SetMaxAnswer(int max)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMaxAnswer(): math_opts not valid!\n");
- return;
- }
- math_opts->max_answer = sane_value(max);
-}
-
-
-void MC_SetMaxQuestions(int max)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMaxQuestions(): math_opts not valid!\n");
- return;
- }
- if (max < 0)
- {
- fprintf(stderr, "\nMC_SetMaxQuestions(): max_questions cannot be negative!\n");
- return;
- }
- math_opts->max_questions = max;
-}
-
-void MC_SetAllowNegatives(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetAllowNegatives(): math_opts not valid!\n");
- return;
- }
- math_opts->allow_negatives = int_to_bool(opt);
- if (!opt)
- {
- clear_negatives();
- }
-}
-
-
-void MC_SetPlayThroughList(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetPlayThroughList(): math_opts not valid!\n");
- return;
- }
- math_opts->play_through_list = int_to_bool(opt);
-}
-
-
-void MC_SetRepeatWrongs(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetRepeatWrongs(): math_opts not valid!\n");
- return;
- }
- math_opts->repeat_wrongs = int_to_bool(opt);
-}
-
-
-void MC_SetCopiesRepeatedWrongs(int copies)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetCopiesRepeatedWrongs(): math_opts not valid!\n");
- return;
- }
- /* number of copies must be between 1 and 10: */
- if (copies < 1)
- copies = 1;
- if (copies > 10)
- copies = 10;
- math_opts->copies_repeated_wrongs = copies;
-}
-
-
-
-/*NOTE - list can contain more than one format */
-void MC_SetFormatAnswerLast(int opt) /* Enable questions like: a + b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatAnswerLast(): math_opts not valid!\n");
- return;
- }
-
- MC_SetFormatAddAnswerLast(opt);
- MC_SetFormatSubAnswerLast(opt);
- MC_SetFormatMultAnswerLast(opt);
- MC_SetFormatDivAnswerLast(opt);
-}
-
-
-void MC_SetFormatAnswerFirst(int opt) /* Enable questions like: ? + b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatAnswerFirst(): math_opts not valid!\n");
- return;
- }
-
- MC_SetFormatAddAnswerFirst(opt);
- MC_SetFormatSubAnswerFirst(opt);
- MC_SetFormatMultAnswerFirst(opt);
- MC_SetFormatDivAnswerFirst(opt);
-}
-
-
-void MC_SetFormatAnswerMiddle(int opt) /* Enable questions like: a + ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatAnswerMiddle(): math_opts not valid!\n");
- return;
- }
-
- MC_SetFormatAddAnswerMiddle(opt);
- MC_SetFormatSubAnswerMiddle(opt);
- MC_SetFormatMultAnswerMiddle(opt);
- MC_SetFormatDivAnswerMiddle(opt);
-}
-
-
-
-/* Addition-specific question formats: */
-void MC_SetFormatAddAnswerLast(int opt) /* Enable questions like: a + b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatAddAnswerLast(): math_opts not valid!\n");
- return;
- }
- math_opts->format_add_answer_last = int_to_bool(opt);
-}
-
-
-void MC_SetFormatAddAnswerFirst(int opt) /* Enable questions like: ? + b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatAddAnswerFirst(): math_opts not valid!\n");
- return;
- }
- math_opts->format_add_answer_first = int_to_bool(opt);
-}
-
-
-void MC_SetFormatAddAnswerMiddle(int opt) /* Enable questions like: a + ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatAddAnswerMiddle(): math_opts not valid!\n");
- return;
- }
- math_opts->format_add_answer_middle = int_to_bool(opt);
-}
-
-
-
-/* Subtraction-specific question formats: */
-void MC_SetFormatSubAnswerLast(int opt) /* Enable questions like: a - b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatSubAnswerLast(): math_opts not valid!\n");
- return;
- }
- math_opts->format_sub_answer_last = int_to_bool(opt);
-}
-
-
-void MC_SetFormatSubAnswerFirst(int opt) /* Enable questions like: ? - b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatSubAnswerFirst(): math_opts not valid!\n");
- return;
- }
- math_opts->format_sub_answer_first = int_to_bool(opt);
-}
-
-
-void MC_SetFormatSubAnswerMiddle(int opt) /* Enable questions like: a - ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatSubAnswerMiddle(): math_opts not valid!\n");
- return;
- }
- math_opts->format_sub_answer_middle = int_to_bool(opt);
-}
-
-
-
-/* Multiplication-specific question formats: */
-void MC_SetFormatMultAnswerLast(int opt) /* Enable questions like: a * b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatMultAnswerLast(): math_opts not valid!\n");
- return;
- }
- math_opts->format_mult_answer_last = int_to_bool(opt);
-}
-
-
-void MC_SetFormatMultAnswerFirst(int opt) /* Enable questions like: ? * b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatMultAnswerFirst(): math_opts not valid!\n");
- return;
- }
- math_opts->format_mult_answer_first = int_to_bool(opt);
-}
-
-
-void MC_SetFormatMultAnswerMiddle(int opt) /* Enable questions like: a * ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatMultAnswerMiddle(): math_opts not valid!\n");
- return;
- }
- math_opts->format_mult_answer_middle = int_to_bool(opt);
-}
-
-
-/* Division-specific question formats: */
-void MC_SetFormatDivAnswerLast(int opt) /* Enable questions like: a / b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatDivAnswerLast(): math_opts not valid!\n");
- return;
- }
- math_opts->format_div_answer_last = int_to_bool(opt);
-}
-
-
-void MC_SetFormatDivAnswerFirst(int opt) /* Enable questions like: ? / b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatDivAnswerFirst(): math_opts not valid!\n");
- return;
- }
- math_opts->format_div_answer_first = int_to_bool(opt);
-}
-
-
-void MC_SetFormatDivAnswerMiddle(int opt) /* Enable questions like: a / ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetFormatDivAnswerMiddle(): math_opts not valid!\n");
- return;
- }
- math_opts->format_div_answer_middle = int_to_bool(opt);
-}
-
-
-
-void MC_SetQuestionCopies(int copies) /* how many times each question is put in list */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetQuestionCopies(): math_opts not valid!\n");
- return;
- }
- /* number of copies must be between 1 and 10: */
- if (copies < 1)
- copies = 1;
- if (copies > 10)
- copies = 10;
- math_opts->question_copies = copies;
-}
-
-
-void MC_SetRandomize(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetRandomize(): math_opts not valid!\n");
- return;
- }
- math_opts->randomize = int_to_bool(opt);
-}
-
-void MC_SetFractionToKeep(float fract)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetRandomize(): math_opts not valid!\n");
- return;
- }
- /* must be between 0 and 1: */
- if (fract < 0)
- fract = 0;
- if (fract > 1)
- fract = 1;
- math_opts->fraction_to_keep = fract;
-}
-
-
-/* Set math operations to be used in game: */
-void MC_SetAddAllowed(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetAddAllowed(): math_opts not valid!\n");
- return;
- }
- math_opts->addition_allowed = int_to_bool(opt);
-}
-
-
-void MC_SetSubAllowed(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetSubAllowed(): math_opts not valid!\n");
- return;
- }
- math_opts->subtraction_allowed = int_to_bool(opt);
-}
-
-
-void MC_SetMultAllowed(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMultAllowed(): math_opts not valid!\n");
- return;
- }
- math_opts->multiplication_allowed = int_to_bool(opt);
-}
-
-
-void MC_SetDivAllowed(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetDivAllowed(): math_opts not valid!\n");
- return;
- }
- math_opts->division_allowed = int_to_bool(opt);
-}
-
-
-void MC_SetTypingAllowed(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetTypingAllowed(): math_opts not valid!\n");
- return;
- }
- math_opts->typing_practice_allowed = int_to_bool(opt);
-}
-
-
-
-/* Set min and max for addition: */
-void MC_SetAddMin(int opt)
-{
- MC_SetAddMinAugend(opt);
- MC_SetAddMinAddend(opt);
-}
-
-
-void MC_SetAddMinAugend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetAddMinAugend(): math_opts not valid!\n");
- return;
- }
- math_opts->min_augend = sane_value(opt);
-}
-
-
-void MC_SetAddMinAddend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetAddMinAddend(): math_opts not valid!\n");
- return;
- }
- math_opts->min_addend = sane_value(opt);
-}
-
-
-void MC_SetAddMax(int opt)
-{
- MC_SetAddMaxAugend(opt);
- MC_SetAddMaxAddend(opt);
-}
-
-
-void MC_SetAddMaxAugend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetAddMaxAugend(): math_opts not valid!\n");
- return;
- }
- math_opts->max_augend = sane_value(opt);
-}
-
-
-void MC_SetAddMaxAddend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetAddMaxAddend(): math_opts not valid!\n");
- return;
- }
- math_opts->max_addend = sane_value(opt);
-}
-
-
-
-
-/* Set min and max for subtraction: */
-void MC_SetSubMin(int opt)
-{
- MC_SetSubMinMinuend(opt);
- MC_SetSubMinSubtrahend(opt);
-}
-
-
-void MC_SetSubMinMinuend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MC_SetSubMinMinuend(): math_opts not valid!\n");
- return;
- }
- math_opts->min_minuend = sane_value(opt);
-}
-
-
-void MC_SetSubMinSubtrahend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetSubMinSubtrahend(): math_opts not valid!\n");
- return;
- }
- math_opts->min_subtrahend = sane_value(opt);
-}
-
-
-void MC_SetSubMax(int opt)
-{
- MC_SetSubMaxMinuend(opt);
- MC_SetSubMaxSubtrahend(opt);
-}
-
-
-void MC_SetSubMaxMinuend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetSubMaxMinuend(): math_opts not valid!\n");
- return;
- }
- math_opts->max_minuend = sane_value(opt);
-}
-
-
-void MC_SetSubMaxSubtrahend(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetSubMaxSubtrahend(): math_opts not valid!\n");
- return;
- }
- math_opts->max_subtrahend = sane_value(opt);
-}
-
-
-
-
-/* Set min and max for multiplication: */
-void MC_SetMultMin(int opt)
-{
- MC_SetMultMinMultiplier(opt);
- MC_SetMultMinMultiplicand(opt);
-}
-
-
-void MC_SetMultMinMultiplier(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMultMinMultiplier(): math_opts not valid!\n");
- return;
- }
- math_opts->min_multiplier = sane_value(opt);
-}
-
-
-void MC_SetMultMinMultiplicand(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMultMinMultiplicand(): math_opts not valid!\n");
- return;
- }
- math_opts->min_multiplicand = sane_value(opt);
-}
-
-
-void MC_SetMultMax(int opt)
-{
- MC_SetMultMaxMultiplier(opt);
- MC_SetMultMaxMultiplicand(opt);
-}
-
-
-void MC_SetMultMaxMultiplier(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMultMaxMultiplier(): math_opts not valid!\n");
- return;
- }
- math_opts->max_multiplier = sane_value(opt);
-}
-
-
-void MC_SetMultMaxMultiplicand(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetMultMaxMultiplicand(): math_opts not valid!\n");
- return;
- }
- math_opts->max_multiplicand = sane_value(opt);
-}
-
-
-
-
-/* Set min and max for division: */
-void MC_SetDivMin(int opt)
-{
- MC_SetDivMinDivisor(opt);
- MC_SetDivMinQuotient(opt);
-}
-
-
-void MC_SetDivMinDivisor(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetDivMinDivisor(): math_opts not valid!\n");
- return;
- }
- math_opts->min_divisor = sane_value(opt);
-}
-
-
-void MC_SetDivMinQuotient(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetDivMinQuotient(): math_opts not valid!\n");
- return;
- }
- math_opts->min_quotient = sane_value(opt);
-}
-
-
-void MC_SetDivMax(int opt)
-{
- MC_SetDivMaxDivisor(opt);
- MC_SetDivMaxQuotient(opt);
-}
-
-
-void MC_SetDivMaxDivisor(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetDivMaxDivisor(): math_opts not valid!\n");
- return;
- }
- math_opts->max_divisor = sane_value(opt);
-}
-
-
-void MC_SetDivMaxQuotient(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetDivMaxQuotient(): math_opts not valid!\n");
- return;
- }
- math_opts->max_quotient = sane_value(opt);
-}
-
-
-/* Set min and max for division: */
-void MC_SetTypeMin(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetTypeMin(): math_opts not valid!\n");
- return;
- }
- math_opts->min_typing_num = sane_value(opt);
-}
-
-
-void MC_SetTypeMax(int opt)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SetTypeMax(): math_opts not valid!\n");
- return;
- }
- math_opts->max_typing_num = sane_value(opt);
-}
-
-
-/*"Get" type methods to query option parameters */
-
-/* Query general math options: */
-int MC_MaxAnswer(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MaxAnswer(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_answer;
-}
-
-
-int MC_MaxQuestions(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MaxQuestions(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_questions;
-}
-
-
-int MC_AllowNegatives(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_AllowNegatives(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->allow_negatives;
-}
-
-
-int MC_PlayThroughList(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_PlayThroughList(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->play_through_list;
-}
-
-
-int MC_RepeatWrongs(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_RepeatWrongs(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->repeat_wrongs;
-}
-
-
-int MC_CopiesRepeatedWrongs(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_CopiesRepeatedWrongs(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->copies_repeated_wrongs;
-}
-
-
-float MC_FractionToKeep(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FractionToKeep(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->fraction_to_keep;
-}
-
-
-
-int MC_FormatAddAnswerLast(void) /* a + b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatAddAnswerLast(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_add_answer_last;
-}
-
-
-int MC_FormatAddAnswerFirst(void) /* ? + b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatAddAnswerFirst(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_add_answer_first;
-}
-
-
-int MC_FormatAddAnswerMiddle(void) /* a + ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatAddAnswerMiddle(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_add_answer_middle;
-}
-
-
-int MC_FormatSubAnswerLast(void) /* a - b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatSubAnswerLast(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_sub_answer_last;
-}
-
-
-int MC_FormatSubAnswerFirst(void) /* ? - b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatSubAnswerFirst(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_sub_answer_first;
-}
-
-
-int MC_FormatSubAnswerMiddle(void) /* a - ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatSubAnswerMiddle(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_sub_answer_middle;
-}
-
-int MC_FormatMultAnswerLast(void) /* a * b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatMultAnswerLast(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_mult_answer_last;
-}
-
-
-int MC_FormatMultAnswerFirst(void) /* ? * b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatMultAnswerFirst(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_mult_answer_first;
-}
-
-
-int MC_FormatMultAnswerMiddle(void) /* a * ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatMultAnswerMiddle(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_mult_answer_middle;
-}
-
-
-int MC_FormatDivAnswerLast(void) /* a / b = ? */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatDivAnswerLast(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_div_answer_last;
-}
-
-
-int MC_FormatDivAnswerFirst(void) /* ? / b = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatDivAnswerFirst(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_div_answer_first;
-}
-
-
-int MC_FormatDivAnswerMiddle(void) /* a / ? = c */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_FormatAnswerMiddle(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->format_add_answer_middle;
-}
-
-
-
-int MC_QuestionCopies(void) /* how many times each question is put in list */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_QuestionCopies(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->question_copies;
-}
-
-
-int MC_Randomize(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_Randomize(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->randomize;
-}
-
-
-
-/* Query the allowed math operations: */
-int MC_AddAllowed(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_AddAllowed(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->addition_allowed;
-}
-
-
-int MC_SubAllowed(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SubAllowed(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->subtraction_allowed;
-}
-
-
-int MC_MultAllowed(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MultAllowed(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->multiplication_allowed;
-}
-
-
-int MC_DivAllowed(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_DivAllowed(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->division_allowed;
-}
-
-
-int MC_TypingAllowed(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_TypeAllowed(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->typing_practice_allowed;
-}
-
-
-/* Query min and max for addition: */
-int MC_AddMinAugend(void) /* the "augend" is the first addend i.e. "a" in "a + b = c" */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_AddMinAugend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_augend;
-}
-
-
-int MC_AddMinAddend(void) /* options for the other addend */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_AddMinAddend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_addend;
-}
-
-
-int MC_AddMaxAugend(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_AddMaxAugend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_augend;
-}
-
-
-int MC_AddMaxAddend(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_AddMaxAddend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_addend;
-}
-
-
-
-/* Query min and max for subtraction: */
-int MC_SubMinMinuend(void) /* minuend - subtrahend = difference */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SubMinMinuend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_minuend;
-}
-
-
-int MC_SubMinSubtrahend(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SubMinSubtrahend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_subtrahend;
-}
-
-
-
-int MC_SubMaxMinuend(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SubMaxMinuend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_minuend;
-}
-
-
-
-int MC_SubMaxSubtrahend(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_SubMaxSubtrahend(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_subtrahend;
-}
-
-
-
-/* Query min and max for multiplication: */
-int MC_MultMinMultiplier(void) /* multiplier * multiplicand = product */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MultMinMultiplier(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_multiplier;
-}
-
-
-int MC_MultMinMultiplicand(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MultMinMultiplicand(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_multiplicand;
-}
-
-
-
-int MC_MultMaxMultiplier(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MultMaxMultiplier(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_multiplier;
-}
-
-
-
-int MC_MultMaxMultiplicand(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_MultMaxMultiplicand(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_multiplicand;
-}
-
-
-
-/* Query min and max for division: */
-int MC_DivMinDivisor(void) /* dividend/divisor = quotient */
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_DivMinDivisor(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_divisor;
-}
-
-
-int MC_DivMinQuotient(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_DivMinQuotient(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_quotient;
-}
-
-
-int MC_DivMaxDivisor(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_DivMaxDivisor(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_divisor;
-}
-
-
-int MC_DivMaxQuotient(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_DivMaxQuotient(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_quotient;
-}
-
-
-/* Query min and max for typing practice: */
-int MC_TypeMin(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_TypeMin(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->min_typing_num;
-}
-
-
-int MC_TypeMax(void)
-{
- if (!math_opts)
- {
- fprintf(stderr, "\nMC_TypeMax(): math_opts not valid!\n");
- return MC_MATH_OPTS_INVALID;
- }
- return math_opts->max_typing_num;
-}
-
-
-/* prints struct to file */
-void MC_PrintMathOptions(FILE* fp, int verbose)
-{
- #ifdef MC_DEBUG
- printf("\nEntering MC_PrintMathOptions()\n");
- #endif
-
- /* bail out if no struct */
- if (!math_opts)
- {
- fprintf(stderr, "\nMath Options struct does not exist!\n");
- return;
- }
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# General Math Options #\n"
- "# #\n"
- "# If 'play_through_list' is true, Tuxmath will ask each #\n"
- "# question in an internally-generated list. The list is #\n"
- "# generated based on the question ranges selected below. #\n"
- "# The game ends when no questions remain. #\n"
- "# If 'play_through_list' is false, the game continues #\n"
- "# until all cities are destroyed. #\n"
- "# Default is 1 (i.e. 'true' or 'yes'). #\n"
- "# #\n"
- "# 'question_copies' is the number of times each question #\n"
- "# will be asked. It can be 1 to 10 - Default is 1. #\n"
- "# #\n"
- "# 'repeat_wrongs' tells Tuxmath whether to reinsert #\n"
- "# incorrectly answered questions into the list to be #\n"
- "# asked again. Default is 1 (yes). #\n"
- "# #\n"
- "# 'copies_repeated_wrongs' gives the number of times an #\n"
- "# incorrectly answered question will reappear. Default #\n"
- "# is 1. #\n"
- "# #\n"
- "# The defaults for these values result in a 'mission' #\n"
- "# for Tux that is accomplished by answering all #\n"
- "# questions correctly with at least one surviving city. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "play_through_list = %d\n", math_opts->play_through_list);
- fprintf (fp, "question_copies = %d\n", math_opts->question_copies);
- fprintf (fp, "repeat_wrongs = %d\n", math_opts->repeat_wrongs);
- fprintf (fp, "copies_repeated_wrongs = %d\n", math_opts->copies_repeated_wrongs);
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# The 'format_<op>_answer_<place> options control #\n"
- "# generation of questions with the answer in different #\n"
- "# places in the equation. i.e.: #\n"
- "# #\n"
- "# format_add_answer_last: 2 + 2 = ? #\n"
- "# format_add_answer_first: ? + 2 = 4 #\n"
- "# format_add_answer_middle: 2 + ? = 4 #\n"
- "# #\n"
- "# By default, 'format_answer_first' is enabled and the #\n"
- "# other two formats are disabled. Note that the options #\n"
- "# are not mutually exclusive - the question list may #\n"
- "# contain questions with different formats. #\n"
- "# #\n"
- "# The formats are set independently for each of the four #\n"
- "# math operations. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "format_add_answer_last = %d\n", math_opts->format_add_answer_last);
- fprintf (fp, "format_add_answer_first = %d\n", math_opts->format_add_answer_first);
- fprintf (fp, "format_add_answer_middle = %d\n", math_opts->format_add_answer_middle);
- fprintf (fp, "format_sub_answer_last = %d\n", math_opts->format_sub_answer_last);
- fprintf (fp, "format_sub_answer_first = %d\n", math_opts->format_sub_answer_first);
- fprintf (fp, "format_sub_answer_middle = %d\n", math_opts->format_sub_answer_middle);
- fprintf (fp, "format_mult_answer_last = %d\n", math_opts->format_mult_answer_last);
- fprintf (fp, "format_mult_answer_first = %d\n", math_opts->format_mult_answer_first);
- fprintf (fp, "format_mult_answer_middle = %d\n", math_opts->format_mult_answer_middle);
- fprintf (fp, "format_div_answer_last = %d\n", math_opts->format_div_answer_last);
- fprintf (fp, "format_div_answer_first = %d\n", math_opts->format_div_answer_first);
- fprintf (fp, "format_div_answer_middle = %d\n", math_opts->format_div_answer_middle);
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# 'allow_negatives' allows or disallows use of negative #\n"
- "# numbers as both operands and answers. Default is 0 #\n"
- "# (no), which disallows questions like: #\n"
- "# 2 - 4 = ? #\n"
- "# Note: this option must be enabled in order to set the #\n"
- "# operand ranges to include negatives (see below). If it #\n"
- "# is changed from 1 (yes) to 0 (no), any negative #\n"
- "# operand limits will be reset to 0. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "allow_negatives = %d\n", math_opts->allow_negatives);
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# 'max_answer' is the largest absolute value allowed in #\n"
- "# any value in a question (not only the answer). Default #\n"
- "# is 144. It can be set as high as 999. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "max_answer = %d\n", math_opts->max_answer);
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# 'max_questions' is limit of the length of the question #\n"
- "# list. Default is 5000 - only severe taskmasters will #\n"
- "# need to raise it. #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "max_questions = %d\n", math_opts->max_questions);
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# If 'randomize' selected, the list will be shuffled #\n"
- "# at the start of the game. Default is 1 (yes). #\n"
- "############################################################\n\n");
- }
- fprintf (fp, "randomize = %d\n", math_opts->randomize);
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Math Operations Allowed #\n"
- "# #\n"
- "# These options enable questions for each of the four math #\n"
- "# operations. All are 1 (yes) by default. #\n"
- "############################################################\n\n");
- }
- fprintf(fp, "addition_allowed = %d\n", math_opts->addition_allowed);
- fprintf(fp, "subtraction_allowed = %d\n", math_opts->subtraction_allowed);
- fprintf(fp, "multiplication_allowed = %d\n", math_opts->multiplication_allowed);
- fprintf(fp, "division_allowed = %d\n", math_opts->division_allowed);
-
-
- if (verbose)
- {
- fprintf (fp, "\n############################################################\n"
- "# #\n"
- "# Minimum and Maximum Values for Operand Ranges #\n"
- "# #\n"
- "# Operand limits can be set to any integer up to the #\n"
- "# value of 'max_answer'. If 'allow_negatives' is set to 1 #\n"
- "# (yes), either negative or positive values can be used. #\n"
- "# Tuxmath will generate questions for every value in the #\n"
- "# specified range. The maximum must be greater than or #\n"
- "# equal to the corresponding minimum for any questions to #\n"
- "# be generated for that operation. #\n"
- "############################################################\n\n");
- }
- fprintf(fp, "\n# Addition operands: augend + addend = sum\n");
- fprintf(fp, "min_augend = %d\n", math_opts->min_augend);
- fprintf(fp, "max_augend = %d\n", math_opts->max_augend);
- fprintf(fp, "min_addend = %d\n", math_opts->min_addend);
- fprintf(fp, "max_addend = %d\n", math_opts->max_addend);
-
- fprintf(fp, "\n# Subtraction operands: minuend - subtrahend = difference\n");
- fprintf(fp, "min_minuend = %d\n", math_opts->min_minuend);
- fprintf(fp, "max_minuend = %d\n", math_opts->max_minuend);
- fprintf(fp, "min_subtrahend = %d\n", math_opts->min_subtrahend);
- fprintf(fp, "max_subtrahend = %d\n", math_opts->max_subtrahend);
-
- fprintf(fp, "\n# Multiplication operands: multiplier * multiplicand = product\n");
- fprintf(fp, "min_multiplier = %d\n", math_opts->min_multiplier);
- fprintf(fp, "max_multiplier = %d\n", math_opts->max_multiplier);
- fprintf(fp, "min_multiplicand = %d\n", math_opts->min_multiplicand);
- fprintf(fp, "max_multiplicand = %d\n", math_opts->max_multiplicand);
-
- fprintf(fp, "\n# Division operands: dividend/divisor = quotient\n");
- fprintf(fp, "min_divisor = %d\n",math_opts->min_divisor);
- fprintf(fp, "max_divisor = %d\n", math_opts->max_divisor);
- fprintf(fp, "min_quotient = %d\n", math_opts->min_quotient);
- fprintf(fp, "max_quotient = %d\n", math_opts->max_quotient);
-
- fprintf(fp, "\n# Typing practice:\n");
- fprintf(fp, "min_typing_num = %d\n",math_opts->min_typing_num);
- fprintf(fp, "max_typing_num = %d\n",math_opts->max_typing_num);
-
- #ifdef MC_DEBUG
- printf("\nLeaving MC_PrintMathOptions()\n");
- #endif
-}
-
-
-
-int MC_PrintQuestionList(FILE* fp)
-{
- if (fp && question_list)
- {
- print_list(fp, question_list);
- return 1;
- }
- else
- {
- fprintf(stderr, "\nFile pointer and/or question list invalid\n");
- return 0;
- }
-}
-
-int MC_PrintWrongList(FILE* fp)
-{
- if (!fp)
- {
- fprintf(stderr, "File pointer invalid\n");
- return 0;
- }
-
- if (wrong_quests)
- {
- print_list(fp, wrong_quests);
- }
- else
- {
- fprintf(fp, "\nNo wrong questions!\n");
- }
-
- return 1;
-}
-
-
-int MC_StartingListLength(void)
-{
- return starting_length;
-}
-
-
-int MC_WrongListLength(void)
-{
- return list_length(wrong_quests);
-}
-
-int MC_NumAnsweredCorrectly(void)
-{
- return answered_correctly;
-}
-
-
-int MC_NumNotAnsweredCorrectly(void)
-{
- return answered_wrong;
-}
-
-
-/* Report the median time per question */
-float MC_MedianTimePerQuestion(void)
-{
- if (length_time_per_question_list == 0)
- return 0;
-
- qsort(time_per_question_list,length_time_per_question_list,sizeof(float),floatCompare);
- return time_per_question_list[length_time_per_question_list/2];
-}
-
-/* Implementation of "private methods" - (cannot be called from outside
-of this file) */
-
-
-
-/* Resets negative values to zero - used when allow_negatives deselected. */
-void clear_negatives(void)
-{
- if (math_opts->min_augend < 0)
- math_opts->min_augend = 0;
- if (math_opts->max_augend < 0)
- math_opts->max_augend = 0;
- if (math_opts->min_addend < 0)
- math_opts->min_addend = 0;
- if (math_opts->max_addend < 0)
- math_opts->max_addend = 0;
-
- if (math_opts->min_minuend < 0)
- math_opts->min_minuend = 0;
- if (math_opts->max_minuend < 0)
- math_opts->max_minuend = 0;
- if (math_opts->min_subtrahend < 0)
- math_opts->min_subtrahend = 0;
- if (math_opts->max_subtrahend < 0)
- math_opts->max_subtrahend = 0;
-
- if (math_opts->min_multiplier < 0)
- math_opts->min_multiplier = 0;
- if (math_opts->max_multiplier < 0)
- math_opts->max_multiplier = 0;
- if (math_opts->min_multiplicand < 0)
- math_opts->min_multiplicand = 0;
- if (math_opts->max_multiplicand < 0)
- math_opts->max_multiplicand = 0;
-
- if (math_opts->min_divisor < 0)
- math_opts->min_divisor = 0;
- if (math_opts->max_divisor < 0)
- math_opts->max_divisor = 0;
- if (math_opts->min_quotient < 0)
- math_opts->min_quotient = 0;
- if (math_opts->max_quotient < 0)
- math_opts->max_quotient = 0;
-
- if (math_opts->min_typing_num < 0)
- math_opts->min_typing_num = 0;
- if (math_opts->max_typing_num < 0)
- math_opts->max_typing_num = 0;
-}
-
-/* using parameters from the mission struct, create linked list of "flashcards" */
-/* FIXME should figure out how to proceed correctly if we run out of memory */
-/* FIXME very redundant code - figure out way to iterate through different */
-/* math operations and question formats */
-MC_MathQuestion* generate_list(void)
-{
- MC_MathQuestion* top_of_list = NULL;
- MC_MathQuestion* end_of_list = NULL;
- MC_MathQuestion* tmp_ptr = NULL;
-
- int i, j, k;
- int length = 0;
-
- #ifdef MC_DEBUG
- printf("\nEntering generate_list()");
- MC_PrintMathOptions(stdout, 0);
- #endif
-
- /* add nodes for each math operation allowed */
-
- #ifdef MC_DEBUG
- printf("\ngenerating addition questions\n");
- #endif
-
- if (math_opts->addition_allowed)
- {
- #ifdef MC_DEBUG
- printf("\nAddition problems");
- #endif
- for (i = math_opts->min_augend; i <= math_opts->max_augend; i++)
+ //choose two numbers in the proper range and get their result
+
+ else
{
- for (j = math_opts->min_addend; j <= math_opts->max_addend; j++)
- {
- /* check if max_answer exceeded or if question */
- /* contains undesired negative values: */
- if (validate_question(i, j, i + j))
- {
- /* put in the desired number of copies: */
- for (k = 0; k < math_opts->question_copies; k++)
- {
- /* put in questions in each selected format: */
+ r1 = rand() % (math_opts->iopts[MAX_AUGEND+4*op] - math_opts->iopts[MIN_AUGEND+4*op] + 1) + math_opts->iopts[MIN_AUGEND+4*op];
+ r2 = rand() % (math_opts->iopts[MAX_ADDEND+4*op] - math_opts->iopts[MIN_ADDEND+4*op] + 1) + math_opts->iopts[MIN_ADDEND+4*op];
- /* questions like num1 + num2 = ? */
- if (math_opts->format_add_answer_last)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_LAST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like num1 + ? = num3 */
- if (math_opts->format_add_answer_middle)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_MIDDLE);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like ? + num2 = num3 */
- if (math_opts->format_add_answer_first)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
-
- {
- tmp_ptr = create_node(i, j, MC_OPER_ADD, i + j, MC_FORMAT_ANS_FIRST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
- }
- }
- }
- }
- }
-
- #ifdef MC_DEBUG
- printf("generating subtraction questions\n");
- #endif
-
- if (math_opts->subtraction_allowed)
- {
- #ifdef MC_DEBUG
- printf("\nSubtraction problems");
- #endif
- for (i = math_opts->min_minuend; i <= math_opts->max_minuend; i++)
- {
- for (j = math_opts->min_subtrahend; j <= math_opts->max_subtrahend; j++)
+ if (op == MC_OPER_ADD)
+ ans = r1 + r2;
+ if (op == MC_OPER_SUB)
+ ans = r1 - r2;
+ if (op == MC_OPER_MULT)
+ ans = r1 * r2;
+ if (op == MC_OPER_DIV)
{
- /* check if max_answer exceeded or if question */
- /* contains undesired negative values: */
- if (validate_question(i, j, i - j))
- {
- /* put in the desired number of copies: */
- for (k = 0; k < math_opts->question_copies; k++)
- {
- /* put in questions in each selected format: */
-
- /* questions like num1 - num2 = ? */
- if (math_opts->format_sub_answer_last)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
-
- {
- tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_LAST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like num1 - ? = num3 */
- if (math_opts->format_sub_answer_middle)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
-
- {
- tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_MIDDLE);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like ? - num2 = num3 */
- if (math_opts->format_sub_answer_first)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, j, MC_OPER_SUB, i - j, MC_FORMAT_ANS_FIRST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
- }
- }
+ if (r2 == 0)
+ r2 = 1;
+ ret.difficulty = r1;
+ r1 *= r2;
+ ans = ret.difficulty;
}
- }
- }
+ }
- #ifdef MC_DEBUG
- printf("generating multiplication questions\n");
- #endif
- if (math_opts->multiplication_allowed)
- {
- #ifdef MC_DEBUG
- printf("\nMultiplication problems");
- #endif
- for (i = math_opts->min_multiplier; i <= math_opts->max_multiplier; i++)
- {
- for (j = math_opts->min_multiplicand; j <= math_opts->max_multiplicand; j++)
- {
- /* check if max_answer exceeded or if question */
- /* contains undesired negative values: */
- if (validate_question(i, j, i * j))
- {
- /* put in the desired number of copies: */
- for (k = 0; k < math_opts->question_copies; k++)
- {
- /* put in questions in each selected format: */
+ mcdprintf("Constructing answer_string\n");
+ snprintf(ret.answer_string, max_answer_size+1, "%d", ans);
+ mcdprintf("Constructing formula_string\n");
+ snprintf(ret.formula_string, max_formula_size, "%d %c %d",
+ r1, operchars[op], r2);
+ ret.answer = ans;
+ ret.difficulty = op + 1;
- /* questions like num1 x num2 = ? */
- if (math_opts->format_mult_answer_last)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_LAST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like num1 x ? = num3 */
- /* (no questions like 0 x ? = 0) because answer indeterminate */
- if ((math_opts->format_mult_answer_middle)
- && (i != 0))
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_MIDDLE);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like ? x num2 = num3 */
- /* (no questions like ? X 0 = 0) because answer indeterminate */
- if ((math_opts->format_mult_answer_first)
- && (j != 0))
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, j, MC_OPER_MULT, i * j, MC_FORMAT_ANS_FIRST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
- }
- }
- }
- }
- }
-
- #ifdef MC_DEBUG
- printf("generating division questions\n");
- #endif
-
- if (math_opts->division_allowed)
+ }
+ else //recurse
+ {
+ ret = generate_random_ooo_card_of_length(length - 1, 0);
+
+ if (strchr(ret.formula_string, '+') || strchr(ret.formula_string, '-') )
+ {
+ //if the expression has addition or subtraction, we can't assume that
+ //introducing multiplication or division will produce a predictable
+ //result, so we'll limit ourselves to more addition/subtraction
+ for (op = rand() % 2 ? MC_OPER_ADD : MC_OPER_SUB;
+ MC_GetOpt(op + ADDITION_ALLOWED) == 0;
+ op = rand() % 2 ? MC_OPER_ADD : MC_OPER_SUB);
+
+ }
+ else
+ {
+ //the existing expression can be treated as a number in itself, so we
+ //can do anything to it and be confident of the result.
+ for (op = rand() % MC_NUM_OPERS; //pick a random operation
+ MC_GetOpt(op + ADDITION_ALLOWED) == 0; //make sure it's allowed
+ op = rand() % MC_NUM_OPERS);
+ }
+ mcdprintf("Next operation is %c,", operchars[op]);
+
+ //pick the next operand
+ if (op == MC_OPER_ADD)
+ {
+ r1 = rand() % (math_opts->iopts[MAX_AUGEND] - math_opts->iopts[MIN_AUGEND] + 1) + math_opts->iopts[MIN_AUGEND];
+ ret.answer += r1;
+ }
+ else if (op == MC_OPER_SUB)
+ {
+ r1 = rand() % (math_opts->iopts[MAX_SUBTRAHEND] - math_opts->iopts[MIN_SUBTRAHEND] + 1) + math_opts->iopts[MIN_SUBTRAHEND];
+ ret.answer -= r1;
+ }
+ else if (op == MC_OPER_MULT)
+ {
+ r1 = rand() % (math_opts->iopts[MAX_MULTIPLICAND] - math_opts->iopts[MIN_MULTIPLICAND] + 1) + math_opts->iopts[MIN_AUGEND];
+ ret.answer *= r1;
+ }
+ else if (op == MC_OPER_DIV)
+ {
+ r1 = find_divisor(ret.answer);
+ ret.answer /= r1;
+ }
+ else
+ {
+ ; //invalid operator
+ }
+ mcdprintf(" operand is %d\n", r1);
+ mcdprintf("Answer: %d\n", ret.answer);
+
+ //next append or prepend the new number (might need optimization)
+ if (op == MC_OPER_SUB || op == MC_OPER_DIV || //noncommutative, append only
+ rand() % 2)
+ {
+ snprintf(tempstr, max_formula_size, "%s %c %d", //append
+ ret.formula_string, operchars[op], r1);
+ strncpy(ret.formula_string, tempstr, max_formula_size);
+ }
+ else //we're prepending
+ {
+ snprintf(tempstr, max_formula_size, "%d %c %s", //append
+ r1, operchars[op], ret.formula_string);
+ strncpy(ret.formula_string, tempstr, max_formula_size);
+ }
+
+ //finally update the answer and score
+ snprintf(ret.answer_string, max_answer_size, "%d", ret.answer);
+ ret.difficulty += (length - 1) + op;
+ }
+
+ if (reformat)
{
- #ifdef MC_DEBUG
- printf("\nDivision problems");
- #endif
- for (i = math_opts->min_quotient; i <= math_opts->max_quotient; i++)
- {
- for (j = math_opts->min_divisor; j <= math_opts->max_divisor; j++)
- {
- /* check if max_answer exceeded or if question */
- /* contains undesired negative values: */
- if (j /* must avoid division by zero: */
- &&
- validate_question(i * j, j, i)) /* division problems are generated as multiplication */
- {
- /* put in the desired number of copies: */
- for (k = 0; k < math_opts->question_copies; k++)
- {
- /* put in questions in each selected format: */
-
- /* questions like num1 / num2 = ? */
- if (math_opts->format_div_answer_last)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_LAST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like num1 / ? = num3 */
- if ((math_opts->format_div_answer_middle)
- && (i)) /* This avoids creating indeterminate questions: 0/? = 0 */
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_MIDDLE);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
-
- /* questions like ? / num2 = num3 */
- if (math_opts->format_div_answer_first)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i * j, j, MC_OPER_DIV, i, MC_FORMAT_ANS_FIRST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
- }
- }
- }
- }
+ mcdprintf("Reformatting...\n");
+ do {
+ format = rand() % MC_NUM_FORMATS;
+ } while (!MC_GetOpt(FORMAT_ANSWER_LAST + format) &&
+ !MC_GetOpt(FORMAT_ADD_ANSWER_LAST + op * 3 + format) );
+
+ strncat(ret.formula_string, " = ?", max_formula_size - strlen(ret.formula_string) );
+ reformat_arithmetic(&ret, format );
}
-
- #ifdef MC_DEBUG
- printf("generating typing practice questions\n");
- #endif
-
- if (math_opts->typing_practice_allowed)
- {
- #ifdef MC_DEBUG
- printf("\nTyping problems");
- #endif
- for (i = math_opts->min_typing_num; i <= math_opts->max_typing_num; i++)
- {
- /* check if max_answer exceeded or if question */
- /* contains undesired negative values: */
- if (validate_question(i, i, i))
- {
- /* put in the desired number of copies: */
- for (k = 0; k < math_opts->question_copies; k++)
- {
- /* make sure max_questions not exceeded, */
- /* also check if question being randomly kept or discarded: */
- if ((length < math_opts->max_questions)
- && randomly_keep())
- {
- tmp_ptr = create_node(i, i, MC_OPER_TYPING_PRACTICE, i, MC_FORMAT_ANS_LAST);
- top_of_list = insert_node(top_of_list, end_of_list, tmp_ptr);
- end_of_list = tmp_ptr;
- length++;
- }
- }
- }
- }
- }
- #ifdef MC_DEBUG
- length = list_length(top_of_list);
- printf("\nlength before randomization:\t%d", length);
- #endif
-
- /* now shuffle list if desired: */
- if (math_opts->randomize)
- {
- if(!randomize_list(&top_of_list))
- {
- fprintf(stderr, "Error during list randomization!\n");
- return NULL;
- }
- }
-
- #ifdef MC_DEBUG
- length = list_length(top_of_list);
- printf("\nlength after randomization:\t%d", length);
- printf("\nLeaving generate_list()\n");
- #endif
-
- return top_of_list;
-}
-
-
-/* this is used by generate_list to see if a possible question */
-/* meets criteria to be added to the list or not: */
-int validate_question(int n1, int n2, int n3)
-{
- /* make sure none of values exceeds max_answer using absolute */
- /* value comparison: */
- if (abs_value(n1) > abs_value(math_opts->max_answer)
- || abs_value(n2) > abs_value(math_opts->max_answer)
- || abs_value(n3) > abs_value(math_opts->max_answer))
- {
- return 0;
- }
- /* make sure none of values are negative if negatives not allowed: */
- if (!math_opts->allow_negatives)
- {
- if (n1 < 0 || n2 < 0 || n3 < 0)
- {
- return 0;
- }
- }
- return 1;
-}
-
-/* create a new node and return a pointer to it */
-MC_MathQuestion* create_node(int n1, int n2, int op, int ans, int f)
-{
- MC_MathQuestion* ptr = NULL;
-
- ptr = (MC_MathQuestion*)malloc(sizeof(MC_MathQuestion));
-
- if (!ptr)
- {
- fprintf(stderr, "create_node() - malloc() failed!\n");
- return NULL;
- }
-
- ptr->card.num1 = n1;
- ptr->card.num2 = n2;
- ptr->card.num3 = ans;
- ptr->card.operation = op;
- ptr->card.format = f;
- ptr->next = NULL;
- ptr->previous = NULL;
-
-
- /* creating formula_string and answer_string is a little more work: */
- {
- char oper_char;
- /* find out correct operation character */
- switch (op)
- {
- case MC_OPER_ADD:
+ return ret;
+}
+
+MC_MathQuestion* generate_list(void)
+{
+ int i;
+ int length = MC_GetOpt(AVG_LIST_LENGTH);
+ int cl; //raw length
+ double r1, r2, delta, var; //randomizers for list length
+ MC_MathQuestion* list = NULL;
+ MC_MathQuestion* end_of_list = NULL;
+ MC_MathQuestion* tnode = NULL;
+
+ MC_PrintMathOptions(stdout, 0);
+ if (!(MC_GetOpt(ARITHMETIC_ALLOWED) ||
+ MC_GetOpt(TYPING_PRACTICE_ALLOWED) ||
+ MC_GetOpt(COMPARISON_ALLOWED) ) )
+ return NULL;
+
+ //randomize list length by a "bell curve" centered on average
+ if (length && MC_GetOpt(VARY_LIST_LENGTH) )
+ {
+ r1 = (double)rand() / RAND_MAX / 2 + 0.5; //interval (0, 1)
+ r2 = (double)rand() / RAND_MAX / 2 + 0.5; //interval (0, 1)
+ mcdprintf("Randoms chosen: %5f, %5f\n", r1, r2);
+ delta = sqrt(-2 * log(r1) ) * cos(2 * PI_VAL * r2); //standard normal dist.
+ var = length / 10.0; //variance
+ delta = delta * var;
+ mcdprintf("Delta of average is %5f\n", delta);
+ length += delta;
+ if (length < 0)
+ length = 1; //just in case...
+ }
+
+ if (MC_GetOpt(COMPREHENSIVE) ) //generate all
+ {
+ for (i = MC_PT_TYPING; i < MC_NUM_PTYPES; ++i)
+ {
+ if (!MC_GetOpt(i + TYPING_PRACTICE_ALLOWED) )
+ continue;
+
+ list = add_all_valid(i, list, end_of_list);
+
+ }
+
+ if (MC_GetOpt(RANDOMIZE) )
{
- oper_char = '+';
- break;
- }
- case MC_OPER_SUB:
+ mcdprintf("Randomizing list\n");
+ randomize_list(&list);
+ }
+
+ if (length)
+ {
+ cl = list_length(list);
+ if (length > cl) //if not enough questions, pad out with randoms
{
- oper_char = '-';
- break;
- }
- case MC_OPER_MULT:
+ mcdprintf("Padding out list from %d to %d questions\n", cl, length);
+ for (i = cl; i < length; ++i)
+ {
+ tnode = malloc(sizeof(MC_MathQuestion) );
+ tnode->card = generate_random_flashcard();
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ mcdprintf("%d...", list_length(list) );
+ }
+ }
+ else if (length < cl) //if too many questions, chop off tail end of list
{
- oper_char = '*';
- break;
+ mcdprintf("Cutting list to %d questions\n", length);
+ end_of_list = find_node(list, length);
+ delete_list(end_of_list->next);
+ end_of_list->next = NULL;
}
- case MC_OPER_DIV:
- {
- oper_char = '/';
- break;
- }
- case MC_OPER_TYPING_PRACTICE:
- {
- snprintf(ptr->card.formula_string, MC_FORMULA_LEN, "%d",ptr->card.num1);
- snprintf(ptr->card.answer_string, MC_ANSWER_LEN, "%d",ptr->card.num1);
- return ptr; /* Don't need to look at formats for this case. */
- }
- default:
- {
- fprintf(stderr, "\nIn create_node(): invalid math operation\n");
- free(ptr);
- ptr = 0;
-
- return 0;
- }
- }
-
- switch (f) /* f is format argument */
- {
- case MC_FORMAT_ANS_LAST: /* e.g. num1 + num2 = ? */
- {
- snprintf(ptr->card.formula_string, MC_FORMULA_LEN,"%d %c %d = ?",
- ptr->card.num1,
- oper_char,
- ptr->card.num2);
- snprintf(ptr->card.answer_string, MC_ANSWER_LEN, "%d",ptr->card.num3);
- break;
- }
- case MC_FORMAT_ANS_MIDDLE: /* e.g. num1 + ? = num3 */
- {
- snprintf(ptr->card.formula_string, MC_FORMULA_LEN,"%d %c ? = %d",
- ptr->card.num1,
- oper_char,
- ptr->card.num3);
- snprintf(ptr->card.answer_string, MC_ANSWER_LEN, "%d",ptr->card.num2);
- break;
- }
- case MC_FORMAT_ANS_FIRST: /* e.g. ? + num2 = num3 */
- {
- snprintf(ptr->card.formula_string, MC_FORMULA_LEN,"? %c %d = %d",
- oper_char,
- ptr->card.num2,
- ptr->card.num3);
- snprintf(ptr->card.answer_string, MC_ANSWER_LEN, "%d",ptr->card.num1);
- break;
- }
- default: /* should not get to here if MathCards behaves correctly */
- {
- fprintf(stderr, "\ncreate_node() - invalid question format\n");
- free(ptr);
- ptr = 0;
-
-
- return 0;
- }
- }
- }
-
- /* ptr should now point to a properly constructed node: */
- return ptr;
-}
-
-
-#ifdef MC_DEBUG
-/* a "copy constructor", so to speak */
-/* FIXME should properly return newly allocated list if more than one node DSB */
-MC_MathQuestion* create_node_copy(MC_MathQuestion* other)
-{
- return create_node(other->card.num1,
- other->card.num2,
- other->card.operation,
- other->card.num3,
- other->card.format);
-}
-#endif
-
-MC_MathQuestion* create_node_from_card(MC_FlashCard* flashcard)
-{
- return create_node(flashcard->num1,
- flashcard->num2,
- flashcard->operation,
- flashcard->num3,
- flashcard->format);
-}
-
-#ifdef MC_DEBUG
-/* FIXME take care of strings */
-
-MC_FlashCard* create_card_from_node(MC_MathQuestion* node)
-{
- MC_FlashCard* fc;
- if (!node)
- return 0;
- fc = malloc(sizeof(MC_FlashCard));
- fc->num1 = node->card.num1;
- fc->num2 = node->card.num2;
- fc->num3 = node->card.num3;
- fc->operation = node->card.operation;
- fc->format = node->card.format;
- return fc;
-}
-#endif
-
-
-/* FIXME take care of strings */
-/* this one copies the contents, including pointers; both nodes must be allocated */
-int copy_node(MC_MathQuestion* original, MC_MathQuestion* copy)
-{
- if (!original)
+ }
+ }
+
+ else
+ {
+
+
+ for (i = 0; i < length; ++i)
+ {
+ tnode = malloc(sizeof(MC_MathQuestion) );
+ tnode->card = generate_random_flashcard();
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ }
+ }
+ return list;
+}
+
+static int compare_card(const MC_FlashCard* a, const MC_FlashCard* b)
+{
+ if (strncmp(a->formula_string, b->formula_string, max_formula_size) )
+ return 1;
+ if (strncmp(a->answer_string, b->answer_string, max_answer_size) )
+ return 1;
+ if (a->answer != b->answer);
+ return 1;
+
+ return 0; //the cards are identical
+}
+
+/* Public functions */
+
+/* allocate space for an MC_Flashcard */
+MC_FlashCard MC_AllocateFlashcard(void)
+{
+ MC_FlashCard ret;
+ mcdprintf("Allocating %d + %d bytes for flashcard\n",
+ max_formula_size + 1, max_answer_size + 1);
+ ret.formula_string = malloc( (max_formula_size + 1) * sizeof(char));
+ ret.answer_string = malloc( (max_answer_size + 1) * sizeof(char));
+ if (!ret.formula_string || !ret.answer_string)
+ {
+ free(ret.formula_string);
+ free(ret.answer_string);
+ printf("Couldn't allocate space for a new flashcard!\n");
+ ret = DEFAULT_CARD;
+ }
+ return ret;
+}
+
+void MC_FreeFlashcard(MC_FlashCard* fc)
+{
+ if (!fc)
+ return;
+ mcdprintf("Freeing formula_string\n");
+ if (fc->formula_string)
+ {
+ free(fc->formula_string);
+ fc->formula_string = NULL;
+ }
+ mcdprintf("Freeing answer_string\n");
+ if (fc->answer_string)
+ {
+ free(fc->answer_string);
+ fc->answer_string = NULL;
+ }
+}
+
+unsigned int MC_MapTextToIndex(const char* text)
+{
+ int i;
+ for (i = 0; i < NOPTS; ++i)
+ {
+ if (!strcasecmp(text, MC_OPTION_TEXT[i]) )
+ return i;
+ }
+ printf("Sorry, don't recognize option '%s'\n", text);
+ return NOT_VALID_OPTION;
+}
+
+//TODO more intuitive function names for access by index vs. by text
+void MC_SetOpt(unsigned int index, int val)
+{
+ if (index >= NOPTS)
+ {
+ mcdprintf("Invalid option index: %d\n", index);
+ return;
+ }
+ math_opts->iopts[index] = val;
+}
+
+void MC_SetOp(const char* param, int val)
+{
+ MC_SetOpt(MC_MapTextToIndex(param), val);
+}
+
+int MC_GetOpt(unsigned int index)
+{
+ if (index >= NOPTS)
+ {
+ mcdprintf("Invalid option index: %d\n", index);
+ return MC_MATH_OPTS_INVALID;
+ }
+ if (!math_opts)
+ {
+ printf("Invalid options list!\n");
+ return MC_MATH_OPTS_INVALID;
+ }
+ return math_opts->iopts[index];
+}
+
+int MC_GetOp(const char* param)
+{
+ return MC_GetOpt(MC_MapTextToIndex(param) );
+}
+
+int MC_VerifyOptionListSane(void)
+{
+ return strcmp(MC_OPTION_TEXT[NOPTS], "END_OF_OPTS") == 0;
+}
+
+int MC_MaxFormulaSize(void)
+{
+ return max_formula_size;
+}
+
+int MC_MaxAnswerSize(void)
+{
+ return max_answer_size;
+}
+
+void MC_ResetFlashCard(MC_FlashCard* fc)
+{
+ if (!fc || !fc->formula_string || !fc->answer_string)
+ return;
+ strncpy(fc->formula_string, " ", max_formula_size);
+ strncpy(fc->answer_string, " ", max_answer_size);
+ fc->answer = 0;
+ fc->difficulty = 0;
+}
+
+int MC_FlashCardGood(const MC_FlashCard* fc)
+{
+ return fc && fc->formula_string && fc->answer_string;
+}
+
+int find_divisor(int a)
+{
+ int div = 1; //the divisor to return
+ int i;
+ for (i = 0; i < NPRIMES; ++i) //test each prime
+ if (a % smallprimes[i] == 0) //if it is a prime factor,
+ if (rand() % (i + 1) == 0) //maybe we'll keep it
+ if (div * smallprimes[i] <= MC_GetOpt(MAX_DIVISOR) ) //if we can,
+ div *= smallprimes[i]; //update our real divisor
+ //FIXME ensure div meets minimum divisor if possible (it might not be)
+ return div;
+}
+
+MC_MathQuestion* add_all_valid(MC_ProblemType pt, MC_MathQuestion* list, MC_MathQuestion* end_of_list)
+{
+ int i, j;
+ int ans = 0, tmp;
+ MC_Operation k;
+ MC_MathQuestion* tnode;
+
+ mcdprintf("Entering add_all_valid(%d)\n", pt);
+
+ if (!MC_GetOpt(pt + TYPING_PRACTICE_ALLOWED) )
+ return list;
+
+ if (pt == MC_PT_TYPING)
{
- fprintf(stderr, "\nIn copy_node(): invalid 'original' pointer arg.\n");
- return 0;
- }
- if (!copy)
- {
- fprintf(stderr, "\nIn copy_node(): invalid 'copy' pointer arg.\n");
- return 0;
- }
-
- copy->card.num1 = original->card.num1;
- copy->card.num2 = original->card.num2;
- copy->card.num3 = original->card.num3;
- copy->card.operation = original->card.operation;
- copy->card.format = original->card.format;
- strncpy(copy->card.formula_string,
- original->card.formula_string,
- MC_FORMULA_LEN);
- strncpy(copy->card.answer_string,
- original->card.answer_string,
- MC_ANSWER_LEN);
- copy->next = original->next;
- copy->previous = original->previous;
- copy->randomizer = original->randomizer;
- return 1;
-}
-
-
-
-
-/* this puts the node into the list AFTER the node pointed to by current */
-/* and returns a pointer to the top of the modified list */
-MC_MathQuestion* insert_node(MC_MathQuestion* first, MC_MathQuestion* current, MC_MathQuestion* new_node)
-{
- /* return pointer to list unchanged if new_node doesn't exist*/
- if (!new_node)
- return first;
- /* if current doesn't exist, new_node is first */
- if (!current)
- {
- new_node->previous = 0;
- new_node->next =0;
- first = new_node;
- return first;
- }
-
- if (current->next) /* avoid error if at end of list */
- current->next->previous = new_node;
- new_node->next = current->next;
- current->next = new_node;
- new_node->previous = current;
- return first;
-}
-
-
-
-/* adds the new node to the end of the list */
-MC_MathQuestion* append_node(MC_MathQuestion* list, MC_MathQuestion* new_node)
-{
- MC_MathQuestion* ptr;
- /* return pointer to list unchanged if new_node doesn't exist*/
- if (!new_node)
- {
- return list;
- }
-
- /* if list does not exist, new_node is the first (and only) node */
- if (!list)
- {
- return new_node;
- }
- /* otherwise, go to end of list */
- ptr = list;
- while (ptr->next)
- {
- ptr = ptr->next;
- }
-
- ptr->next = new_node;
- new_node->previous = ptr;
- new_node->next = 0;
- return list;
-}
-
-
-
-/* this takes the node out of the list but does not delete it */
-/* and returns a pointer to the top of the modified list */
-MC_MathQuestion* remove_node(MC_MathQuestion* first, MC_MathQuestion* n)
-{
- if (!n || !first)
- return first;
- /* special case if first node being removed */
- if (n == first)
- first = first->next;
-
- if (n->previous)
- n->previous->next = n->next;
- if (n->next)
- n->next->previous = n->previous;
- n->previous = 0;
- n->next = 0;
- return first;
-}
-
-
-
-/* frees memory for entire list and returns null pointer */
-MC_MathQuestion* delete_list(MC_MathQuestion* list)
-{
- MC_MathQuestion* tmp_ptr;
- while (list)
- {
- tmp_ptr = list->next;
- free (list);
- list = tmp_ptr;
- }
- return list;
-}
-
-
-
-void print_list(FILE* fp, MC_MathQuestion* list)
-{
- if (!list)
- {
- fprintf(fp, "\nprint_list(): list empty or pointer invalid\n");
- return;
- }
-
- {
- MC_MathQuestion* ptr = list;
- while (ptr)
+ mcdprintf("Adding typing...\n");
+ for (i = MC_GetOpt(MIN_TYPING_NUM); i < MC_GetOpt(MAX_TYPING_NUM); ++i)
{
- print_node(fp, ptr);
- ptr = ptr->next;
- }
+ mcdprintf("(%d)\n", i);
+ tnode = allocate_node();
+ snprintf(tnode->card.formula_string, max_formula_size, "%d", i);
+ snprintf(tnode->card.answer_string, max_formula_size, "%d", i);
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ }
+ }
+ else if (MC_PT_ARITHMETIC)
+ {
+ mcdprintf("Adding arithmetic...\n");
+ for (k = MC_OPER_ADD; k < MC_NUM_OPERS; ++k)
+ {
+ if (!MC_GetOpt(k + ADDITION_ALLOWED) )
+ continue;
+ mcdprintf("\n*%d*\n", k);
+ for (i = MC_GetOpt(MIN_AUGEND + 4 * k); i < MC_GetOpt(MAX_AUGEND + 4 * k); ++i)
+ {
+ mcdprintf("\n%d:\n", i);
+ for (j = MC_GetOpt(MIN_ADDEND + 4 * k); j < MC_GetOpt(MAX_ADDEND + 4 * k); ++j)
+ {
+ //mcdprintf("%d,", j);
+ if (k == MC_OPER_ADD)
+ ans = i + j;
+ else if (k == MC_OPER_SUB)
+ {
+ ans = i - j;
+ if (ans < 0 && !MC_GetOpt(ALLOW_NEGATIVES) )
+ continue;
+ }
+ else if (k == MC_OPER_MULT)
+ ans = i * j;
+ else if (k == MC_OPER_DIV)
+ {
+ mcdprintf("%d %d %d\n", ans, i, j);
+ tmp = i;
+ i *= j;
+ ans = j;
+ j = tmp;
+ mcdprintf("%d %d %d\n", ans, i, j);
+ }
+
+ mcdprintf("Generating: %d %c %d = %d\n", i, operchars[k], j, ans);
+ //add each format, provided it's allowed in general and for this op
+ if (MC_GetOpt(FORMAT_ANSWER_LAST) && MC_GetOpt(FORMAT_ADD_ANSWER_LAST + k * 3) )
+ {
+ tnode = allocate_node();
+ snprintf(tnode->card.answer_string, max_formula_size, "%d", ans);
+ snprintf(tnode->card.formula_string, max_formula_size,
+ "%d %c %d = ?", i, operchars[k], j);
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ }
+ if (MC_GetOpt(FORMAT_ANSWER_FIRST) && MC_GetOpt(FORMAT_ADD_ANSWER_FIRST + k * 3) )
+ {
+ tnode = allocate_node();
+ snprintf(tnode->card.answer_string, max_formula_size, "%d", i);
+ snprintf(tnode->card.formula_string, max_formula_size,
+ "? %c %d = %d", operchars[k], j, ans);
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ }
+ if (MC_GetOpt(FORMAT_ANSWER_MIDDLE) && MC_GetOpt(FORMAT_ADD_ANSWER_MIDDLE + k * 3) )
+ {
+ tnode = allocate_node();
+ snprintf(tnode->card.answer_string, max_formula_size, "%d", j);
+ snprintf(tnode->card.formula_string, max_formula_size,
+ "%d %c ? = %d", i, operchars[k], ans);
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ }
+ //reset j to keep loop from exploding
+ if (k == MC_OPER_DIV)
+ mcdprintf("resetting to %d %d\n", j = ans, i = tmp);
+ }
+ }
+ }
+ }
+ else if (pt == MC_PT_COMPARISON)
+ {
+ for (i = MC_GetOpt(MIN_COMPARATOR); i < MC_GetOpt(MAX_COMPARATOR); ++i)
+ {
+ for (j = MC_GetOpt(MIN_COMPARISAND); j < MC_GetOpt(MAX_COMPARISAND); ++j)
+ {
+ tnode = allocate_node();
+ snprintf(tnode->card.formula_string, max_formula_size, "%d ? %d", i,j);
+ list = insert_node(list, end_of_list, tnode);
+ end_of_list = tnode;
+ }
+ }
}
-}
+ mcdprintf("Exiting add_all_valid()\n");
+ return list;
+}
-void print_vect_list(FILE* fp, MC_MathQuestion** vect, int length)
+MC_MathQuestion* find_node(const MC_MathQuestion* list, int num)
{
- if (!vect)
- {
- fprintf(fp, "\nprint_vect_list(): list empty or pointer invalid\n");
- return;
- }
-
- {
- int i = 0;
- for(i = 0; i < length; i++)
- print_node(fp, vect[i]);
- }
- fprintf(stderr, "Leaving print_vect_list()\n");
-}
-
-/* Don't need this much now that formula_string part of card struct: */
-void print_node(FILE* fp, MC_MathQuestion* ptr)
-{
- if (!ptr || !fp)
- {
- return;
- }
-
- fprintf(fp, "%s\n", ptr->card.formula_string);
- /*fprintf(fp, "randomizer = %d\n", ptr->randomizer);*/
-}
-
-
-#ifdef MC_DEBUG
-void print_card(MC_FlashCard card)
-{
- printf("\nprint_card():");
- printf("\n%d, %d \tOper %d \tAnswer %d \t Format %d\n",
- card.num1,
- card.num2,
- card.operation,
- card.num3,
- card.format);
-}
-#endif
-
-
-#ifdef MC_DEBUG
-/* This sends the values of all "global" counters and the */
-/* lengths of the question lists to stdout - for debugging */
-void print_counters(void)
-{
- printf("\nquest_list_length = \t%d", quest_list_length);
- printf("\nlist_length(question_list) = \t%d", list_length(question_list));
- printf("\nstarting_length = \t%d", starting_length);
- printf("\nunanswered = \t%d", unanswered);
- printf("\nanswered_correctly = \t%d", answered_correctly);
- printf("\nanswered_wrong = \t%d", answered_wrong);
- printf("\nlist_length(wrong_quests) = \t%d", list_length(wrong_quests));
- printf("\nquestions_pending = \t%d", questions_pending);
-}
-#endif
-
-int list_length(MC_MathQuestion* list)
-{
- int length = 0;
- while (list)
- {
- length++;
+ while (--num > 0 && list)
list = list->next;
- }
- return length;
-}
-
-
-
-
-
-
-/* This is a new implementation written in an attempt to avoid */
-/* the O(n^2) performance problems seen with the old randomization */
-/* function. The list is created as a vector, but is for now still */
-/* made a linked list to minimize changes needed elsewhere. */
-/* The argument is a pointer to the top of the old list. This extra */
-/* level of indirection allows the list to be shuffled "in-place". */
-/* The function returns 1 if successful, 0 on errors. */
-
-static int randomize_list(MC_MathQuestion** old_list)
-{
- MC_MathQuestion* old_tmp = *old_list;
- MC_MathQuestion** tmp_vect = NULL;
-
- int i = 0;
- if (!old_list || !*old_list) //invalid/empty list
- return 0;
-
- int old_length = list_length(old_tmp);
-
- /* set random seed: */
- srand(time(0));
-
-
- /* Allocate vector and set ptrs to nodes in old list: */
-
- /* Allocate a list of pointers, not space for the nodes themselves: */
- tmp_vect = (MC_MathQuestion**)malloc(sizeof(MC_MathQuestion*) * old_length);
- /* Set each pointer in the vector to the corresponding node: */
- for (i = 0; i < old_length; i++)
- {
- tmp_vect[i] = old_tmp;
- tmp_vect[i]->randomizer = rand();
- old_tmp = old_tmp->next;
- }
-
- /* Now simply sort on 'tmp_vect[i]->randomizer' to shuffle list: */
- qsort(tmp_vect, old_length,
- sizeof(MC_MathQuestion*),
- comp_randomizer);
-
- /* Re-create pointers to provide linked-list functionality: */
- /* (stop at 'old_length-1' because we dereference tmp_vect[i+1]) */
- for(i = 0; i < old_length - 1; i++)
- {
- if (!tmp_vect[i])
- {
- fprintf(stderr, "Invalid pointer!\n");
- return 0;
- }
- tmp_vect[i]->next = tmp_vect[i+1];
- tmp_vect[i+1]->previous = tmp_vect[i];
- }
- /* Handle end cases: */
- tmp_vect[0]->previous = NULL;
- tmp_vect[old_length-1]->next = NULL;
-
- /* Now arrange for arg pointer to indirectly point to first element! */
- *old_list = tmp_vect[0];
- free(tmp_vect);
- return 1;
-}
-
-
-
-/* This is needed for qsort(): */
-int comp_randomizer (const void* a, const void* b)
-{
-
- int int1 = (*(const struct MC_MathQuestion **) a)->randomizer;
- int int2 = (*(const struct MC_MathQuestion **) b)->randomizer;
-
- if (int1 > int2)
- return 1;
- else if (int1 == int2)
- return 0;
- else
- return -1;
-}
-
-MC_MathQuestion* pick_random(int length, MC_MathQuestion* list)
-{
- int i;
- int rand_node;
-
- /* set random seed DSB */
- srand(time(0));
-
- /* if length is zero, get out to avoid divide-by-zero error */
- if (0 == length)
- {
- return list;
- }
-
- rand_node = rand() % length;
-
- for (i=1; i < rand_node; i++)
- {
- if (list)
- list = list->next;
- }
-
return list;
}
-
-/* compares fields other than pointers */
-int compare_node(MC_MathQuestion* first, MC_MathQuestion* other)
+void reformat_arithmetic(MC_FlashCard* card, MC_Format f)
{
- if (!first || !other)
- return 0;
- if (first->card.num1 == other->card.num1
- && first->card.num2 == other->card.num2
- && first->card.operation == other->card.operation
- && first->card.format == other->card.format)
- return 1;
- else
- return 0;
-}
-
-/* check to see if list already contains an identical node */
-int already_in_list(MC_MathQuestion* list, MC_MathQuestion* ptr)
-{
- if (!list || !ptr)
- return 0;
-
- while (list)
- {
- if (compare_node(list, ptr))
- return 1;
- list = list->next;
- }
- return 0;
-}
-
-/* to prevent option settings in math_opts from getting set to */
-/* values other than 0 or 1 */
-int int_to_bool(int i)
-{
- if (i)
- return 1;
- else
- return 0;
-}
-
-/* prevent values from getting into math_opts that are outside */
-/* the range that can be handled by the program (i.e. more */
-/* than three digits; also disallow negatives if that has been */
-/* selected. */
-int sane_value(int i)
-{
- if (i > MC_GLOBAL_MAX)
- i = MC_GLOBAL_MAX;
- else if (i < -MC_GLOBAL_MAX)
- i = -MC_GLOBAL_MAX;
+ int i, j;
+ char* beg = 0;
+ char* end = 0;
+ char nans[max_answer_size];
+ char nformula[max_formula_size + max_answer_size]; //gets a bit larger than usual in the meantime
- if (i < 0
- && math_opts
- && !math_opts->allow_negatives)
{
- i = 0;
- }
+ snprintf(nans, max_answer_size, "%s", card->answer_string);
+
+ //insert old answer where question mark was
+ for (i = 0, j = 0; card->formula_string[j] != '?'; ++i, ++j)
+ nformula[i] = card->formula_string[j];
+ i += snprintf(nformula + i, max_answer_size-1, "%s", card->answer_string);
+ snprintf(nformula + i, max_formula_size - i, "%s", card->formula_string + j + 1);
- return i;
+ //replace the new answer with a question mark
+ if (f == MC_FORMAT_ANS_LAST)
+ beg = strrchr(nformula, ' ') + 1;
+ if (f == MC_FORMAT_ANS_FIRST)
+ beg = nformula;
+ if (f == MC_FORMAT_ANS_MIDDLE)
+ beg = strchr(nformula, ' ') + 3;
+ end = strchr(beg + 1, ' ');
+ if (!end)
+ end = "";
+ //we now have beg = first digit of number to replace, end = the char after
+ sscanf(beg, "%s", nans);
+ *beg = 0; //sequester the first half of the string
+ snprintf(card->formula_string, max_formula_size, "%s?%s", nformula, end);
+ snprintf(card->answer_string, max_answer_size, nans);
+ card->answer = atoi(card->answer_string);
+ }
}
-
-int abs_value(int i)
-{
- if (i > 0)
- return i;
- else
- return -i;
-}
-
-
-/* Returns true at probability set by math_opts->fraction_to_keep */
-int randomly_keep(void)
-{
- int random;
-
- if (!math_opts)
- return 0;
-
- /* Skip random number generation if keeping all (default) */
- if (1 == math_opts->fraction_to_keep)
- return 1;
-
- random = rand() % 1000;
-
- if (random < (math_opts->fraction_to_keep * 1000))
- return 1;
- else
- return 0;
-}
-
-/* Compares two floats (needed for sorting in MC_MedianTimePerQuestion) */
-int floatCompare(const void *v1,const void *v2)
-{
- float f1,f2;
-
- f1 = *((float *) v1);
- f2 = *((float *) v2);
-
- if (f1 < f2)
- return -1;
- else if (f1 > f2)
- return 1;
- else
- return 0;
-}
Modified: tuxmath/trunk/src/mathcards.h
===================================================================
--- tuxmath/trunk/src/mathcards.h 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/mathcards.h 2008-08-06 02:55:05 UTC (rev 589)
@@ -1,166 +1,154 @@
/*
- mathcards.h
-
- Description: contains headers for a flashcard-type math game.
+ mathcards.h
+
+ Description: contains headers for a flashcard-type math game.
This is a sort of interface-independent backend that could be used with a different
user interface. Developed as an enhancement to Bill Kendrick's "Tux of Math Command"
(aka tuxmath). If tuxmath were a C++ program, this would be a C++ class.
-
- Author: David Bruce <dbruce at tampabay.rr.com>, (C) 2006
-
- Copyright: See COPYING file that comes with this distribution (briefly, GNU GPL version 2 or later)
+ Author: David Bruce <dbruce at tampabay.rr.com>, (C) 2006
+
+ Copyright: See COPYING file that comes with this distribution (briefly, GNU GPL version 2 or later)
+
*/
#ifndef MATHCARDS_H
#define MATHCARDS_H
-//#define MC_DEBUG
-#define MC_FORMULA_LEN 16
-#define MC_ANSWER_LEN 5
+#define MC_DEBUG
+#ifdef MC_DEBUG
+#define mcdprintf(...) printf(__VA_ARGS__)
+#else
+#define mcdprintf(...) 0
+#endif
+#define MC_USE_NEWARC
+typedef enum _MC_ProblemType {
+ MC_PT_TYPING,
+ MC_PT_ARITHMETIC,
+ MC_PT_COMPARISON,
+ MC_NUM_PTYPES
+} MC_ProblemType;
-/* type of math operation used in a given question */
-enum {
+/* type of math operation used in an arithmetic question */
+typedef enum _MC_Operation {
MC_OPER_ADD,
MC_OPER_SUB,
MC_OPER_MULT,
MC_OPER_DIV,
- MC_OPER_TYPING_PRACTICE,
MC_NUM_OPERS
-};
+} MC_Operation;
/* math question formats: */
-enum {
+typedef enum _MC_Format {
MC_FORMAT_ANS_LAST, /* a + b = ? */
MC_FORMAT_ANS_FIRST, /* ? + b = c */
- MC_FORMAT_ANS_MIDDLE /* a + ? = c */
-};
+ MC_FORMAT_ANS_MIDDLE, /* a + ? = c */
+ MC_NUM_FORMATS
+} MC_Format;
-/* This struct contains all options that determine what */
-/* math questions are asked during a game */
-typedef struct MC_Options {
- /* general math options */
- int play_through_list;
- int repeat_wrongs;
- int copies_repeated_wrongs;
- int allow_negatives;
- int max_answer;
- int max_questions;
- int question_copies; /* how many times each question is put in list */
- int randomize; /* whether to shuffle cards */
- float fraction_to_keep; /* Can use to have list contain a random subset */
- /* of the questions meeting selection criteria. */
- /* math question formats: NOTE - list can contain more than one format*/
- /* operation-specific question formats: */
- int format_add_answer_last; /* a + b = ? */
- int format_add_answer_first; /* ? + b = c */
- int format_add_answer_middle; /* a + ? = c */
- int format_sub_answer_last; /* a - b = ? */
- int format_sub_answer_first; /* ? - b = c */
- int format_sub_answer_middle; /* a - ? = c */
- int format_mult_answer_last; /* a * b = ? */
- int format_mult_answer_first; /* ? * b = c */
- int format_mult_answer_middle; /* a * ? = c */
- int format_div_answer_last; /* a / b = ? */
- int format_div_answer_first; /* ? / b = c */
- int format_div_answer_middle; /* a / ? = c */
+/*
+Indices for the various integer options. These are NOT the actual values!
+Actual values are accessed as such: options.iopts[PLAY_THROUGH_LIST] = val;
+Creating additional [integral] options is now centralized--it should only
+be necessary to add to this list, the list of text, and the list of
+defaults. (Besides actually using the new options!)
+*/
+enum {
+ NOT_VALID_OPTION = -1 ,
+ PLAY_THROUGH_LIST = 0 , /* play until all questions answered correctly */
+ QUESTION_COPIES , /* # times each question is put in list */
+ REPEAT_WRONGS , /* reuse incorrectly answered questions or not */
+ COPIES_REPEATED_WRONGS , /* how many copies of an incorrectly answered question to re-insert*/
+ ALLOW_NEGATIVES ,
+ MAX_ANSWER ,
+ MAX_QUESTIONS ,
+ MAX_FORMULA_NUMS ,
+ MIN_FORMULA_NUMS ,
- /* addition options */
- int addition_allowed;
- int min_augend; /* the "augend" is the first addend i.e. "a" in "a + b = c" */
- int max_augend;
- int min_addend; /* options for the other addend */
- int max_addend;
- /* subtraction options */
- int subtraction_allowed;
- int min_minuend; /* minuend - subtrahend = difference */
- int max_minuend;
- int min_subtrahend;
- int max_subtrahend;
- /* multiplication options */
- int multiplication_allowed;
- int min_multiplier; /* multiplier * multiplicand = product */
- int max_multiplier;
- int min_multiplicand;
- int max_multiplicand;
- /* division options */
- int division_allowed;
- int min_divisor; /* dividend/divisor = quotient */
- int max_divisor;
- int min_quotient;
- int max_quotient;
- /* typing practice options */
- int typing_practice_allowed;
- int min_typing_num;
- int max_typing_num;
+ FORMAT_ANSWER_LAST , /* question format is: a + b = ? */
+ FORMAT_ANSWER_FIRST , /* question format is: ? + b = c */
+ FORMAT_ANSWER_MIDDLE , /* question format is: a + ? = c */
+ FORMAT_ADD_ANSWER_LAST , /* a + b = ? */
+ FORMAT_ADD_ANSWER_FIRST , /* ? + b = c */
+ FORMAT_ADD_ANSWER_MIDDLE , /* a + ? = c */
+ FORMAT_SUB_ANSWER_LAST , /* a - b = ? */
+ FORMAT_SUB_ANSWER_FIRST , /* ? - b = c */
+ FORMAT_SUB_ANSWER_MIDDLE , /* a - ? = c */
+ FORMAT_MULT_ANSWER_LAST , /* a * b = ? */
+ FORMAT_MULT_ANSWER_FIRST , /* ? * b = c */
+ FORMAT_MULT_ANSWER_MIDDLE , /* a * ? = c */
+ FORMAT_DIV_ANSWER_LAST , /* a / b = ? */
+ FORMAT_DIV_ANSWER_FIRST , /* ? / b = c */
+ FORMAT_DIV_ANSWER_MIDDLE , /* a / ? = c */
-} MC_Options;
+ ADDITION_ALLOWED ,
+ SUBTRACTION_ALLOWED ,
+ MULTIPLICATION_ALLOWED ,
+ DIVISION_ALLOWED ,
+ TYPING_PRACTICE_ALLOWED ,
+ ARITHMETIC_ALLOWED ,
+ COMPARISON_ALLOWED ,
-/* default values for math_options */
-#define MC_GLOBAL_MAX 999 /* this is the largest absolute value that */
- /* can be entered for math question values. */
-#define MC_MATH_OPTS_INVALID -9999 /* return value for accessor functions */
- /* if math_opts not valid */
+ MIN_AUGEND , /* augend + addend = sum */
+ MAX_AUGEND ,
+ MIN_ADDEND ,
+ MAX_ADDEND ,
-#define DEFAULT_PLAY_THROUGH_LIST 1 /* play until all questions in list answered */ /* correctly */
-#define DEFAULT_REPEAT_WRONGS 1 /* reuse incorrectly answered questions or not */
-#define DEFAULT_COPIES_REPEATED_WRONGS 1 /* how many copies of an incorrectly answered */ /* question to re-insert*/
-#define DEFAULT_ALLOW_NEGATIVES 0
-#define DEFAULT_MAX_ANSWER 999
-#define DEFAULT_MAX_QUESTIONS 5000
-#define DEFAULT_QUESTION_COPIES 1 /* how many times each question is put in list */
-#define DEFAULT_RANDOMIZE 1 /* whether to shuffle cards */
-#define DEFAULT_FRACTION_TO_KEEP 1
+ MIN_MINUEND , /* minuend - subtrahend = difference */
+ MAX_MINUEND ,
+ MIN_SUBTRAHEND ,
+ MAX_SUBTRAHEND ,
-#define DEFAULT_FORMAT_ANSWER_LAST 1 /* question format is: a + b = ? */
-#define DEFAULT_FORMAT_ANSWER_FIRST 0 /* question format is: ? + b = c */
-#define DEFAULT_FORMAT_ANSWER_MIDDLE 0 /* question format is: a + ? = c */
-#define DEFAULT_FORMAT_ADD_ANSWER_LAST 1 /* addition-specific default formats: */
-#define DEFAULT_FORMAT_ADD_ANSWER_FIRST 0
-#define DEFAULT_FORMAT_ADD_ANSWER_MIDDLE 0
-#define DEFAULT_FORMAT_SUB_ANSWER_LAST 1 /* subtraction-specific default formats: */
-#define DEFAULT_FORMAT_SUB_ANSWER_FIRST 0
-#define DEFAULT_FORMAT_SUB_ANSWER_MIDDLE 0
-#define DEFAULT_FORMAT_MULT_ANSWER_LAST 1 /* multiplication-specific default formats: */
-#define DEFAULT_FORMAT_MULT_ANSWER_FIRST 0
-#define DEFAULT_FORMAT_MULT_ANSWER_MIDDLE 0
-#define DEFAULT_FORMAT_DIV_ANSWER_LAST 1 /* division-specific default formats: */
-#define DEFAULT_FORMAT_DIV_ANSWER_FIRST 0
-#define DEFAULT_FORMAT_DIV_ANSWER_MIDDLE 0
+ MIN_MULTIPLIER , /* multiplier * multiplicand = product */
+ MAX_MULTIPLIER ,
+ MIN_MULTIPLICAND ,
+ MAX_MULTIPLICAND ,
-#define DEFAULT_ADDITION_ALLOWED 1
-#define DEFAULT_SUBTRACTION_ALLOWED 1
-#define DEFAULT_MULTIPLICATION_ALLOWED 1
-#define DEFAULT_DIVISION_ALLOWED 1
-#define DEFAULT_TYPING_PRACTICE_ALLOWED 0
+ MIN_DIVISOR , /* dividend/divisor = quotient */
+ MAX_DIVISOR , /* note - generate_list() will prevent */
+ MIN_QUOTIENT , /* questions with division by zero. */
+ MAX_QUOTIENT ,
-#define DEFAULT_MIN_AUGEND 0 /* augend + addend = sum */
-#define DEFAULT_MAX_AUGEND 12
-#define DEFAULT_MIN_ADDEND 0
-#define DEFAULT_MAX_ADDEND 12
+ MIN_TYPING_NUM , /* range for "typing tutor" mode, for */
+ MAX_TYPING_NUM , /* kids just learning to use keyboard. */
+
+ MIN_COMPARATOR , /* left comparison operand */
+ MAX_COMPARATOR ,
+ MIN_COMPARISAND , /* right comparison operannd */
+ MAX_COMPARISAND ,
-#define DEFAULT_MIN_MINUEND 0 /* minuend - subtrahend = difference */
-#define DEFAULT_MAX_MINUEND 12
-#define DEFAULT_MIN_SUBTRAHEND 0
-#define DEFAULT_MAX_SUBTRAHEND 12
+ RANDOMIZE , /* whether to shuffle cards */
+
+ COMPREHENSIVE , /* whether to generate all questions 'in order' */
+ AVG_LIST_LENGTH ,
+ VARY_LIST_LENGTH ,
-#define DEFAULT_MIN_MULTIPLIER 0 /* multiplier * multiplicand = product */
-#define DEFAULT_MAX_MULTIPLIER 12
-#define DEFAULT_MIN_MULTIPLICAND 0
-#define DEFAULT_MAX_MULTIPLICAND 12
+ NOPTS
+};
-#define DEFAULT_MIN_DIVISOR 0 /* dividend/divisor = quotient */
-#define DEFAULT_MAX_DIVISOR 12 /* note - generate_list() will prevent */
-#define DEFAULT_MIN_QUOTIENT 0 /* questions with division by zero. */
-#define DEFAULT_MAX_QUOTIENT 12
+extern const char* const MC_OPTION_TEXT[];
+extern const int MC_DEFAULTS[];
+extern const char operchars[MC_NUM_OPERS];
-#define DEFAULT_MIN_TYPING_NUM 0 /* range for "typing tutor" mode, for kids */
-#define DEFAULT_MAX_TYPING_NUM 12 /* just learning to use keyboard. */
+/* default values for math_options */
+#define MC_MAX_DIGITS 3
+#define MC_GLOBAL_MAX 999 /* This is the largest absolute value that */
+ /* can be entered for math question values.*/
+#define MC_MATH_OPTS_INVALID -9999 /* Return value for accessor functions */
+ /* if math_opts not valid */
+//#define DEFAULT_FRACTION_TO_KEEP 1
+typedef struct _MC_Options
+{
+ int iopts[NOPTS];
+ //float fraction_to_keep; //being a float, we can't keep this in the same array
+} MC_Options; //it'll stay a special case, unless more float options
+
+#ifndef MC_USE_NEWARC
/* struct for individual "flashcard" */
typedef struct MC_FlashCard {
int num1;
@@ -171,6 +159,15 @@
char formula_string[MC_FORMULA_LEN];
char answer_string[MC_ANSWER_LEN];
} MC_FlashCard;
+#else
+/* experimental struct for a more generalized flashcard */
+typedef struct _MC_FlashCard {
+ char* formula_string;
+ char* answer_string;
+ int answer;
+ int difficulty;
+} MC_FlashCard;
+#endif
/* struct for node in math "flashcard" list */
typedef struct MC_MathQuestion {
@@ -180,16 +177,16 @@
int randomizer;
} MC_MathQuestion;
+
/* "public" function prototypes: these functions are how */
/* a user interface communicates with MathCards: */
/* TODO provide comments thoroughly explaining these functions */
-
/* MC_Initialize() sets up the struct containing all of */
/* settings regarding math questions. It should be */
/* called before any other function. Many of the other */
/* functions will not work properly if MC_Initialize() */
-/* has not been called. It only needs to be called once, */
+/* has not been called. It only needs to be called once, */
/* i.e when the program is starting, not at the beginning*/
/* of each math game for the player. Returns 1 if */
/* successful, 0 otherwise. */
@@ -274,144 +271,23 @@
int MC_NumNotAnsweredCorrectly(void);
float MC_MedianTimePerQuestion(void);
-/* Simple "Set/Get" type functions for option parameters: */
-
-/* Simple functions to set option parameters: */
-
-/* Set general math options: */
-void MC_SetPlayThroughList(int opt);
-void MC_SetRepeatWrongs(int opt);
-void MC_SetQuestionCopies(int copies); /* how many times each question is put in list */
-void MC_SetCopiesRepeatedWrongs(int copies);
-void MC_SetMaxAnswer(int max);
-void MC_SetMaxQuestions(int max);
-void MC_SetAllowNegatives(int opt);
-void MC_SetRandomize(int opt);
-void MC_SetFractionToKeep(float fract);
-
-/* Set question formats for all operations: */
-/* NOTE - list can contain more than one format */
-/* Use these to set format the same for all four operations: */
-void MC_SetFormatAnswerLast(int opt); /* a + b = ?, a - b = ?, a * b = ?, a / b = ? */
-void MC_SetFormatAnswerFirst(int opt); /* ? + b = c, etc */
-void MC_SetFormatAnswerMiddle(int opt); /* a + ? = c, etc */
-/* Uset these to set operation-specific question formats: */
-void MC_SetFormatAddAnswerLast(int opt); /* a + b = ? */
-void MC_SetFormatAddAnswerFirst(int opt); /* ? + b = c */
-void MC_SetFormatAddAnswerMiddle(int opt); /* a + ? = c */
-void MC_SetFormatSubAnswerLast(int opt); /* a - b = ? */
-void MC_SetFormatSubAnswerFirst(int opt); /* ? - b = c */
-void MC_SetFormatSubAnswerMiddle(int opt); /* a - ? = c */
-void MC_SetFormatMultAnswerLast(int opt); /* a * b = ? */
-void MC_SetFormatMultAnswerFirst(int opt); /* ? * b = c */
-void MC_SetFormatMultAnswerMiddle(int opt); /* a * ? = c */
-void MC_SetFormatDivAnswerLast(int opt); /* a / b = ? */
-void MC_SetFormatDivAnswerFirst(int opt); /* ? / b = c */
-void MC_SetFormatDivAnswerMiddle(int opt); /* a / ? = c */
-
-/* Set the allowed math operations: */
-void MC_SetAddAllowed(int opt);
-void MC_SetSubAllowed(int opt);
-void MC_SetMultAllowed(int opt);
-void MC_SetDivAllowed(int opt);
-void MC_SetTypingAllowed(int opt);
-
-/* Set min and max for addition: */
-void MC_SetAddMin(int opt); /* augend + addend = sum */
-void MC_SetAddMinAugend(int opt); /* the "augend" is the first addend i.e. "a" in "a + b = c" */
-void MC_SetAddMinAddend(int opt); /* options for the other addend */
-void MC_SetAddMax(int opt);
-void MC_SetAddMaxAugend(int opt);
-void MC_SetAddMaxAddend(int opt);
-
-/* Set min and max for subtraction: */
-void MC_SetSubMin(int opt);
-void MC_SetSubMinMinuend(int opt); /* minuend - subtrahend = difference */
-void MC_SetSubMinSubtrahend(int opt);
-void MC_SetSubMax(int opt);
-void MC_SetSubMaxMinuend(int opt);
-void MC_SetSubMaxSubtrahend(int opt);
-
-/* Set min and max for multiplication: */
-void MC_SetMultMin(int opt);
-void MC_SetMultMinMultiplier(int opt); /* multiplier * multiplicand = product */
-void MC_SetMultMinMultiplicand(int opt);
-void MC_SetMultMax(int opt);
-void MC_SetMultMaxMultiplier(int opt);
-void MC_SetMultMaxMultiplicand(int opt);
-
-/* Set min and max for division: */
-void MC_SetDivMin(int opt);
-void MC_SetDivMinDivisor(int opt); /* dividend/divisor = quotient */
-void MC_SetDivMinQuotient(int opt);
-void MC_SetDivMax(int opt);
-void MC_SetDivMaxDivisor(int opt);
-void MC_SetDivMaxQuotient(int opt);
-
-/* Set min and max for typing practice: */
-void MC_SetTypeMin(int opt);
-void MC_SetTypeMax(int opt);
-
-/* "Get" type functions to query option parameters: */
-
-/* Query general math options: */
-int MC_PlayThroughList(void);
-int MC_RepeatWrongs(void);
-int MC_CopiesRepeatedWrongs(void);
-int MC_MaxAnswer(void);
-int MC_MaxQuestions(void);
-int MC_AllowNegatives(void);
-int MC_QuestionCopies(void); /* how many times each question is put in list */
-int MC_Randomize(void);
-float MC_FractionToKeep(void);
-
-int MC_FormatAddAnswerLast(void); /* a + b = ? */
-int MC_FormatAddAnswerFirst(void); /* ? + b = c */
-int MC_FormatAddAnswerMiddle(void); /* a + ? = c */
-int MC_FormatSubAnswerLast(void); /* a - b = ? */
-int MC_FormatSubAnswerFirst(void); /* ? - b = c */
-int MC_FormatSubAnswerMiddle(void); /* a - ? = c */
-int MC_FormatMultAnswerLast(void); /* a * b = ? */
-int MC_FormatMultAnswerFirst(void); /* ? * b = c */
-int MC_FormatMultAnswerMiddle(void); /* a * ? = c */
-int MC_FormatDivAnswerLast(void); /* a / b = ? */
-int MC_FormatDivAnswerFirst(void); /* ? / b = c */
-int MC_FormatDivAnswerMiddle(void); /* a / ? = c */
-
-
-/* Query the allowed math operations: */
-int MC_AddAllowed(void);
-int MC_SubAllowed(void);
-int MC_MultAllowed(void);
-int MC_DivAllowed(void);
-int MC_TypingAllowed(void);
-
-/* Query min and max for addition: */
-int MC_AddMinAugend(void); /* the "augend" is the first addend i.e. "a" in "a + b = c" */
-int MC_AddMinAddend(void); /* options for the other addend */
-int MC_AddMaxAugend(void);
-int MC_AddMaxAddend(void);
-
-/* Query min and max for subtraction: */
-int MC_SubMinMinuend(void); /* minuend - subtrahend = difference */
-int MC_SubMinSubtrahend(void);
-int MC_SubMaxMinuend(void);
-int MC_SubMaxSubtrahend(void);
-
-/* Query min and max for multiplication: */
-int MC_MultMinMultiplier(void); /* multiplier * multiplicand = product */
-int MC_MultMinMultiplicand(void);
-int MC_MultMaxMultiplier(void);
-int MC_MultMaxMultiplicand(void);
-
-/* Query min and max for division: */
-int MC_DivMinDivisor(void); /* dividend/divisor = quotient */
-int MC_DivMinQuotient(void);
-int MC_DivMaxDivisor(void);
-int MC_DivMaxQuotient(void);
-
-/* Query min and max for typing practice: */
-int MC_TypeMin(void);
-int MC_TypeMax(void);
-
+/********************************************
+Public functions for new mathcards architecture
+*********************************************/
+/* Return the array index of the given text, e.g. randomize->47 */
+unsigned int MC_MapTextToIndex(const char* text);
+void MC_SetOpt(unsigned int index, int val); //access directly,for internal use
+int MC_GetOpt(unsigned int index);
+void MC_SetOp(const char* param, int val); //access by text, for config reading
+int MC_GetOp(const char* param);
+void MC_SetFractionToKeep(float val);
+float MC_GetFractionToKeep(void);
+int MC_VerifyOptionListSane(void);
+int MC_MaxFormulaSize(void);
+int MC_MaxAnswerSize(void);
+MC_FlashCard MC_AllocateFlashcard();
+void MC_FreeFlashcard(MC_FlashCard* fc);
+void MC_ResetFlashCard(MC_FlashCard* fc);
+int MC_FlashCardGood(const MC_FlashCard* fc); //verifies a flashcard is valid
+void reformat_arithmetic(MC_FlashCard* card, MC_Format f);
#endif
Modified: tuxmath/trunk/src/options.c
===================================================================
--- tuxmath/trunk/src/options.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/options.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -981,42 +981,42 @@
fprintf(fp, "use_feedback = %d\n", game_options->use_feedback);
- if(verbose)
- {
- fprintf (fp, "\n# (Feedback) Set the desired danger level.\n"
- "# 0 = too safe, comets typically exploded right at the very top\n"
- "# 1 = too dangerous, comets typically exploded at the moment they hit cities\n"
- "# Set it somewhere between these extremes. As a guideline, early\n"
- "# elementary kids might feel comfortable around 0.2-0.3, older kids\n"
- "# at around 0.4-0.6. Default 0.35.\n");
- }
- fprintf(fp, "danger_level = %f\n", game_options->danger_level);
+ if(verbose)
+ {
+ fprintf (fp, "\n# (Feedback) Set the desired danger level.\n"
+ "# 0 = too safe, comets typically exploded right at the very top\n"
+ "# 1 = too dangerous, comets typically exploded at the moment they hit cities\n"
+ "# Set it somewhere between these extremes. As a guideline, early\n"
+ "# elementary kids might feel comfortable around 0.2-0.3, older kids\n"
+ "# at around 0.4-0.6. Default 0.35.\n");
+ }
+ fprintf(fp, "danger_level = %f\n", game_options->danger_level);
- if(verbose)
- {
- fprintf (fp, "\n# (Feedback) Set danger level speedup.\n"
- "# The margin of safety will decrease by this factor each wave.\n"
- "# Default 1.1. Note 1 = no increase in danger level.\n");
- }
- fprintf(fp, "danger_level_speedup = %f\n", game_options->danger_level_speedup);
+ if(verbose)
+ {
+ fprintf (fp, "\n# (Feedback) Set danger level speedup.\n"
+ "# The margin of safety will decrease by this factor each wave.\n"
+ "# Default 1.1. Note 1 = no increase in danger level.\n");
+ }
+ fprintf(fp, "danger_level_speedup = %f\n", game_options->danger_level_speedup);
- if(verbose)
- {
- fprintf (fp, "\n# (Feedback) Set the maximum danger level.\n"
- "# Default 0.9.\n");
- }
- fprintf(fp, "danger_level_max = %f\n", game_options->danger_level_max);
+ if(verbose)
+ {
+ fprintf (fp, "\n# (Feedback) Set the maximum danger level.\n"
+ "# Default 0.9.\n");
+ }
+ fprintf(fp, "danger_level_max = %f\n", game_options->danger_level_max);
- if (verbose)
- {
- fprintf (fp, "\n# (Feedback) Set the handicap for hitting cities.\n"
- "# When bigger than 0, this causes the game to slow down\n"
- "# by an extra amount after a wave in which one or more\n"
- "# cities get hit. Note that this is similar to slow_after_wrong,\n"
- "# but allows for more gradual changes.\n"
- "# Default 0 (no extra handicap).\n");
- }
- fprintf(fp, "city_explode_handicap = %f\n", game_options->city_expl_handicap);
+ if (verbose)
+ {
+ fprintf (fp, "\n# (Feedback) Set the handicap for hitting cities.\n"
+ "# When bigger than 0, this causes the game to slow down\n"
+ "# by an extra amount after a wave in which one or more\n"
+ "# cities get hit. Note that this is similar to slow_after_wrong,\n"
+ "# but allows for more gradual changes.\n"
+ "# Default 0 (no extra handicap).\n");
+ }
+ fprintf(fp, "city_explode_handicap = %f\n", game_options->city_expl_handicap);
/*
fprintf(fp, "num_cities = %d\n", game_options->num_cities);
Modified: tuxmath/trunk/src/pixels.c
===================================================================
--- tuxmath/trunk/src/pixels.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/pixels.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -42,9 +42,9 @@
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- x); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ x); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
@@ -65,9 +65,9 @@
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 2)); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 2)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
@@ -88,9 +88,9 @@
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 3)); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 3)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
@@ -123,15 +123,15 @@
&& likely((unsigned) y < (unsigned) surface->h)))
{
// Set a pointer to the exact location in memory of the pixel
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 4)); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start: beginning of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 4)); /* Go in X pixels */
/* Set the (correctly-sized) piece of data in the surface's RAM
* to the pixel value sent in: */
- *(Uint32 *) p = pixel; // 32-bit display
+ *(Uint32 *) p = pixel; // 32-bit display
}
}
@@ -149,9 +149,9 @@
/* Set a pointer to the exact location in memory of the pixel
in question: */
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- x); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ x); /* Go in X pixels */
/* Return the correctly-sized piece of data containing the
@@ -175,9 +175,9 @@
/* Set a pointer to the exact location in memory of the pixel
in question: */
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 2)); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 2)); /* Go in X pixels */
/* Return the correctly-sized piece of data containing the
@@ -202,9 +202,9 @@
/* Set a pointer to the exact location in memory of the pixel
in question: */
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 3)); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 3)); /* Go in X pixels */
/* Return the correctly-sized piece of data containing the
@@ -235,16 +235,16 @@
/* Set a pointer to the exact location in memory of the pixel
in question: */
- p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
- (y * surface->pitch) + /* Go down Y lines */
- (x * 4)); /* Go in X pixels */
+ p = (Uint8 *) (((Uint8 *) surface->pixels) + /* Start at top of RAM */
+ (y * surface->pitch) + /* Go down Y lines */
+ (x * 4)); /* Go in X pixels */
/* Return the correctly-sized piece of data containing the
* pixel's value (an 8-bit palette value, or a 16-, 24- or 32-bit
* RGB value) */
- return *(Uint32 *) p; // 32-bit display
+ return *(Uint32 *) p; // 32-bit display
}
void (*putpixels[]) (SDL_Surface *, int, int, Uint32) =
Modified: tuxmath/trunk/src/scandir.c
===================================================================
--- tuxmath/trunk/src/scandir.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/scandir.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -35,8 +35,8 @@
#undef DIRSIZ
#define DIRSIZ(dp) \
- ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
- (((dp)->d_reclen + 1 + 3) &~ 3))
+ ((sizeof(struct dirent) - sizeof(dp)->d_name) + \
+ (((dp)->d_reclen + 1 + 3) &~ 3))
#if defined(__sun) && defined(__SVR4)
# define dirfd(d) ((d)->dd_fd)
@@ -51,7 +51,7 @@
*/
int alphasort(const void *d1, const void *d2)
{
- return strcmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
+ return strcmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
}
@@ -61,78 +61,78 @@
*/
int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
{
- struct dirent *d, *p, **names;
- struct stat stb;
- size_t nitems;
- size_t arraysz;
- DIR *dirp;
+ struct dirent *d, *p, **names;
+ struct stat stb;
+ size_t nitems;
+ size_t arraysz;
+ DIR *dirp;
- if ((dirp = opendir(dirname)) == NULL)
- return(-1);
+ if ((dirp = opendir(dirname)) == NULL)
+ return(-1);
- if (fstat(dirfd(dirp), &stb) < 0)
- return(-1);
+ if (fstat(dirfd(dirp), &stb) < 0)
+ return(-1);
- /*
- * estimate the array size by taking the size of the directory file
- * and dividing it by a multiple of the minimum size entry.
- */
- arraysz = (stb.st_size / 24);
+ /*
+ * estimate the array size by taking the size of the directory file
+ * and dividing it by a multiple of the minimum size entry.
+ */
+ arraysz = (stb.st_size / 24);
- names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
- if (names == NULL)
- return(-1);
+ names = (struct dirent **)malloc(arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
- nitems = 0;
+ nitems = 0;
- while ((d = readdir(dirp)) != NULL)
- {
+ while ((d = readdir(dirp)) != NULL)
+ {
- if (sdfilter != NULL && !(*sdfilter)(d))
- continue; /* just selected names */
+ if (sdfilter != NULL && !(*sdfilter)(d))
+ continue; /* just selected names */
- /*
- * Make a minimum size copy of the data
- */
+ /*
+ * Make a minimum size copy of the data
+ */
- p = (struct dirent *)malloc(DIRSIZ(d));
- if (p == NULL)
- return(-1);
+ p = (struct dirent *)malloc(DIRSIZ(d));
+ if (p == NULL)
+ return(-1);
- p->d_ino = d->d_ino;
- p->d_reclen = d->d_reclen;
- /*p->d_namlen = d->d_namlen;*/
- memcpy(p->d_name, d->d_name, p->d_reclen + 1);
+ p->d_ino = d->d_ino;
+ p->d_reclen = d->d_reclen;
+ /*p->d_namlen = d->d_namlen;*/
+ memcpy(p->d_name, d->d_name, p->d_reclen + 1);
- /*
- * Check to make sure the array has space left and
- * realloc the maximum size.
- */
+ /*
+ * Check to make sure the array has space left and
+ * realloc the maximum size.
+ */
- if (++nitems >= arraysz)
- {
+ if (++nitems >= arraysz)
+ {
- if (fstat(dirfd(dirp), &stb) < 0)
- return(-1); /* just might have grown */
+ if (fstat(dirfd(dirp), &stb) < 0)
+ return(-1); /* just might have grown */
- arraysz = stb.st_size / 12;
+ arraysz = stb.st_size / 12;
- names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
- if (names == NULL)
- return(-1);
- }
+ names = (struct dirent **)realloc((char *)names, arraysz * sizeof(struct dirent *));
+ if (names == NULL)
+ return(-1);
+ }
- names[nitems-1] = p;
- }
+ names[nitems-1] = p;
+ }
- closedir(dirp);
+ closedir(dirp);
- if (nitems && dcomp != NULL)
- qsort(names, nitems, sizeof(struct dirent *), dcomp);
+ if (nitems && dcomp != NULL)
+ qsort(names, nitems, sizeof(struct dirent *), dcomp);
- *namelist = names;
+ *namelist = names;
- return nitems;
+ return nitems;
}
@@ -140,8 +140,8 @@
/*-----------------------------------------------------------------------
- * Here come alphasort and scandir for Windows
- *-----------------------------------------------------------------------*/
+* Here come alphasort and scandir for Windows
+*-----------------------------------------------------------------------*/
#if defined(WIN32)
#undef DATADIR // stupid windows.h defines DATADIR, too
@@ -149,111 +149,111 @@
/*-----------------------------------------------------------------------*/
/**
- * Alphabetic order comparison routine.
- */
+* Alphabetic order comparison routine.
+*/
int alphasort(const void *d1, const void *d2)
{
- return stricmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
+ return stricmp((*(struct dirent * const *)d1)->d_name, (*(struct dirent * const *)d2)->d_name);
}
/*-----------------------------------------------------------------------*/
/**
- * Scan a directory for all its entries
- */
+* Scan a directory for all its entries
+*/
int scandir(const char *dirname, struct dirent ***namelist, int (*sdfilter)(struct dirent *), int (*dcomp)(const void *, const void *))
{
- int len;
- char *findIn, *d;
- WIN32_FIND_DATA find;
- HANDLE h;
- int nDir = 0, NDir = 0;
- struct dirent **dir = 0, *selectDir;
- unsigned long ret;
+ int len;
+ char *findIn, *d;
+ WIN32_FIND_DATA find;
+ HANDLE h;
+ int nDir = 0, NDir = 0;
+ struct dirent **dir = 0, *selectDir;
+ unsigned long ret;
- len = strlen(dirname);
- findIn = (char *)malloc(len+5);
- strcpy(findIn, dirname);
- printf("scandir : findIn orign=%s\n", findIn);
- for (d = findIn; *d; d++)
- if (*d=='/')
- *d='\\';
- if ((len==0))
- {
- strcpy(findIn, ".\\*");
- }
- if ((len==1)&& (d[-1]=='.'))
- {
- strcpy(findIn, ".\\*");
- }
- if ((len>0) && (d[-1]=='\\'))
- {
- *d++ = '*';
- *d = 0;
- }
- if ((len>1) && (d[-1]=='.') && (d[-2]=='\\'))
- {
- d[-1] = '*';
- }
- if ((len>1) && (d[-2]!='\\') && (d[-1]!='*'))
- {
- *d++ = '\\';
- *d++ = '*';
- *d = 0;
- }
+ len = strlen(dirname);
+ findIn = (char *)malloc(len+5);
+ strcpy(findIn, dirname);
+ printf("scandir : findIn orign=%s\n", findIn);
+ for (d = findIn; *d; d++)
+ if (*d=='/')
+ *d='\\';
+ if ((len==0))
+ {
+ strcpy(findIn, ".\\*");
+ }
+ if ((len==1)&& (d[-1]=='.'))
+ {
+ strcpy(findIn, ".\\*");
+ }
+ if ((len>0) && (d[-1]=='\\'))
+ {
+ *d++ = '*';
+ *d = 0;
+ }
+ if ((len>1) && (d[-1]=='.') && (d[-2]=='\\'))
+ {
+ d[-1] = '*';
+ }
+ if ((len>1) && (d[-2]!='\\') && (d[-1]!='*'))
+ {
+ *d++ = '\\';
+ *d++ = '*';
+ *d = 0;
+ }
- printf("scandir : findIn processed=%s\n", findIn);
- if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE)
- {
- printf("scandir : FindFirstFile error\n");
- ret = GetLastError();
- if (ret != ERROR_NO_MORE_FILES)
- {
- // TODO: return some error code
- }
- *namelist = dir;
- return nDir;
- }
- do
- {
- printf("scandir : findFile=%s\n", find.cFileName);
- selectDir=(struct dirent*)malloc(sizeof(struct dirent)+strlen(find.cFileName));
- strcpy(selectDir->d_name, find.cFileName);
- if (!sdfilter || (*sdfilter)(selectDir))
- {
- if (nDir==NDir)
- {
- struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33);
- if (NDir)
- memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
- if (dir)
- free(dir);
- dir = tempDir;
- NDir += 32;
- }
- dir[nDir] = selectDir;
- nDir++;
- dir[nDir] = 0;
- }
- else
- {
- free(selectDir);
- }
- }
- while (FindNextFile(h, &find));
- ret = GetLastError();
- if (ret != ERROR_NO_MORE_FILES)
- {
- // TODO: return some error code
- }
- FindClose(h);
+ printf("scandir : findIn processed=%s\n", findIn);
+ if ((h=FindFirstFile(findIn, &find))==INVALID_HANDLE_VALUE)
+ {
+ printf("scandir : FindFirstFile error\n");
+ ret = GetLastError();
+ if (ret != ERROR_NO_MORE_FILES)
+ {
+ // TODO: return some error code
+ }
+ *namelist = dir;
+ return nDir;
+ }
+ do
+ {
+ printf("scandir : findFile=%s\n", find.cFileName);
+ selectDir=(struct dirent*)malloc(sizeof(struct dirent)+strlen(find.cFileName));
+ strcpy(selectDir->d_name, find.cFileName);
+ if (!sdfilter || (*sdfilter)(selectDir))
+ {
+ if (nDir==NDir)
+ {
+ struct dirent **tempDir = (struct dirent **)calloc(sizeof(struct dirent*), NDir+33);
+ if (NDir)
+ memcpy(tempDir, dir, sizeof(struct dirent*)*NDir);
+ if (dir)
+ free(dir);
+ dir = tempDir;
+ NDir += 32;
+ }
+ dir[nDir] = selectDir;
+ nDir++;
+ dir[nDir] = 0;
+ }
+ else
+ {
+ free(selectDir);
+ }
+ }
+ while (FindNextFile(h, &find));
+ ret = GetLastError();
+ if (ret != ERROR_NO_MORE_FILES)
+ {
+ // TODO: return some error code
+ }
+ FindClose(h);
- free (findIn);
+ free (findIn);
- if (dcomp)
- qsort (dir, nDir, sizeof(*dir),dcomp);
+ if (dcomp)
+ qsort (dir, nDir, sizeof(*dir),dcomp);
- *namelist = dir;
- return nDir;
+ *namelist = dir;
+ return nDir;
}
#endif /* WIN32 */
Modified: tuxmath/trunk/src/setup.c
===================================================================
--- tuxmath/trunk/src/setup.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/setup.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -214,7 +214,7 @@
"If you don't answer a comet's math equation before it hits\n"
"one of your cities, the city's shields will be destroyed.\n"
"If that city is hit by another comet, it is destroyed completely.\n"
- "When you lose all of your cities, the game ends.\n\n");
+ "When you lose all of your cities, the game ends.\n\n");
printf("Note: all settings are now stored in a config file named 'options' in\n"
"a hidden directory named './tuxmath' within the user's home directory.\n"
@@ -225,12 +225,12 @@
"to configure the behavior of Tuxmath.\n\n");
printf("Run the game with:\n"
- "--homedir dirname - seek for user home director(ies) in the specified\n"
- " location, rather than the user's actual home\n"
- " directory. You can set up a user directory tree in\n"
- " this location (see README). This option is\n"
- " especially useful for schools where all students log\n"
- " in with a single user name.\n"
+ "--homedir dirname - seek for user home director(ies) in the specified\n"
+ " location, rather than the user's actual home\n"
+ " directory. You can set up a user directory tree in\n"
+ " this location (see README). This option is\n"
+ " especially useful for schools where all students log\n"
+ " in with a single user name.\n"
"--optionfile filename - read config settings from named file. The locations\n"
" searched for a file with a matching name are the\n"
" current working directory, the absolute path of the\n"
@@ -244,15 +244,15 @@
"--answersmiddle - to ask questions in format: num1 + ? = num3\n"
" instead of default format: num1 + num2 = ?\n"
"--nosound - to disable sound/music\n"
- "--nobackground - to disable background photos (for slower systems)\n"
- "--fullscreen - to run in fullscreen, if possible (vs. windowed)\n"
+ "--nobackground - to disable background photos (for slower systems)\n"
+ "--fullscreen - to run in fullscreen, if possible (vs. windowed)\n"
"--windowed - to run in a window rather than fullscreen\n"
"--keypad - to enable the on-sceen numeric keypad\n"
- "--demo - to run the program as a cycling demonstration\n"
- "--speed S - set initial speed of the game\n"
- " (S may be fractional, default is 1.0)\n"
+ "--demo - to run the program as a cycling demonstration\n"
+ "--speed S - set initial speed of the game\n"
+ " (S may be fractional, default is 1.0)\n"
"--allownegatives - to allow answers to be less than zero\n"
- );
+ );
printf("\n");
@@ -260,24 +260,24 @@
exit(0);
}
else if (strcmp(argv[i], "--copyright") == 0 ||
- strcmp(argv[i], "-c") == 0)
+ strcmp(argv[i], "-c") == 0)
{
printf(
- "\n\"Tux, of Math Command\" version " VERSION ", Copyright (C) 2001 Bill Kendrick\n"
+ "\n\"Tux, of Math Command\" version " VERSION ", Copyright (C) 2001 Bill Kendrick\n"
"This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public License\n"
"as published by the Free Software Foundation. See COPYING.txt\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
- "\n");
+ "\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+ "\n");
cleanup_on_error();
exit(0);
}
else if (strcmp(argv[i], "--usage") == 0 ||
- strcmp(argv[i], "-u") == 0)
+ strcmp(argv[i], "-u") == 0)
{
/* Display (happy) usage: */
@@ -288,26 +288,26 @@
// Parse the user choice of a non-default home directory
if (i >= argc -1)
{
- fprintf(stderr, "%s option requires an argument (dirname)\n", argv[i]);
- usage(1, argv[0]);
+ fprintf(stderr, "%s option requires an argument (dirname)\n", argv[i]);
+ usage(1, argv[0]);
}
else // see whether the specified name is a directory
{
- if ((dirp = opendir(argv[i+1])) == NULL)
- fprintf(stderr,"homedir: %s is not a directory, or it could not be read\n", argv[i+1]);
- else {
- set_user_data_dir(argv[i+1]); // copy the homedir setting
- closedir(dirp);
- }
- i++; // to pass over the next argument, so remaining options parsed
+ if ((dirp = opendir(argv[i+1])) == NULL)
+ fprintf(stderr,"homedir: %s is not a directory, or it could not be read\n", argv[i+1]);
+ else {
+ set_user_data_dir(argv[i+1]); // copy the homedir setting
+ closedir(dirp);
+ }
+ i++; // to pass over the next argument, so remaining options parsed
}
}
else if (0 == strcmp(argv[i], "--optionfile"))
{
if (i >= argc - 1)
{
- fprintf(stderr, "%s option requires an argument (filename)\n", argv[i]);
- usage(1, argv[0]);
+ fprintf(stderr, "%s option requires an argument (filename)\n", argv[i]);
+ usage(1, argv[0]);
}
else /* try to read file named in following arg: */
{
@@ -319,27 +319,27 @@
i++; /* so program doesn't barf on next arg (the filename) */
}
else if (strcmp(argv[i], "--fullscreen") == 0 ||
- strcmp(argv[i], "-f") == 0)
+ strcmp(argv[i], "-f") == 0)
{
Opts_SetFullscreen(1);
}
else if (strcmp(argv[i], "--windowed") == 0 ||
- strcmp(argv[i], "-w") == 0)
+ strcmp(argv[i], "-w") == 0)
{
Opts_SetFullscreen(0);
}
else if (strcmp(argv[i], "--nosound") == 0 ||
- strcmp(argv[i], "-s") == 0 ||
- strcmp(argv[i], "--quiet") == 0 ||
- strcmp(argv[i], "-q") == 0)
+ strcmp(argv[i], "-s") == 0 ||
+ strcmp(argv[i], "--quiet") == 0 ||
+ strcmp(argv[i], "-q") == 0)
{
Opts_SetUseSound(-1); // prevent options files from overwriting
}
else if (strcmp(argv[i], "--version") == 0 ||
- strcmp(argv[i], "-v") == 0)
+ strcmp(argv[i], "-v") == 0)
{
printf("Tux, of Math Command (\"tuxmath\")\n"
- "Version " VERSION "\n");
+ "Version " VERSION "\n");
cleanup_on_error();
exit(0);
}
@@ -349,7 +349,7 @@
Opts_SetUseBkgd(0);
}
else if (strcmp(argv[i], "--demo") == 0 ||
- strcmp(argv[i], "-d") == 0)
+ strcmp(argv[i], "-d") == 0)
{
Opts_SetDemoMode(1);
}
@@ -361,32 +361,32 @@
else if (strcmp(argv[i], "--allownegatives") == 0 ||
strcmp(argv[i], "-n") == 0)
{
- MC_SetAllowNegatives(1);
+ MC_SetOpt(ALLOW_NEGATIVES, 1);
}
else if (strcmp(argv[i], "--playthroughlist") == 0 ||
strcmp(argv[i], "-l") == 0)
{
- MC_SetPlayThroughList(1);
+ MC_SetOpt(PLAY_THROUGH_LIST, 1);
}
else if (strcmp(argv[i], "--answersfirst") == 0)
{
- MC_SetFormatAnswerLast(0);
- MC_SetFormatAnswerFirst(1);
- MC_SetFormatAnswerMiddle(0);
+ MC_SetOpt(FORMAT_ANSWER_LAST, 0);
+ MC_SetOpt(FORMAT_ANSWER_FIRST, 1);
+ MC_SetOpt(FORMAT_ANSWER_MIDDLE, 0);
}
else if (strcmp(argv[i], "--answersmiddle") == 0)
{
- MC_SetFormatAnswerLast(0);
- MC_SetFormatAnswerFirst(0);
- MC_SetFormatAnswerMiddle(1);
+ MC_SetOpt(FORMAT_ANSWER_LAST, 0);
+ MC_SetOpt(FORMAT_ANSWER_FIRST, 0);
+ MC_SetOpt(FORMAT_ANSWER_MIDDLE, 1);
}
else if (strcmp(argv[i], "--speed") == 0 ||
- strcmp(argv[i], "-s") == 0)
+ strcmp(argv[i], "-s") == 0)
{
if (i >= argc - 1)
{
- fprintf(stderr, "%s option requires an argument\n", argv[i]);
- usage(1, argv[0]);
+ fprintf(stderr, "%s option requires an argument\n", argv[i]);
+ usage(1, argv[0]);
}
Opts_SetSpeed(strtod(argv[i + 1], (char **) NULL));
@@ -427,8 +427,8 @@
{
fprintf(stderr,
"\nError: I could not initialize video!\n"
- "The Simple DirectMedia error that occured was:\n"
- "%s\n\n", SDL_GetError());
+ "The Simple DirectMedia error that occured was:\n"
+ "%s\n\n", SDL_GetError());
cleanup_on_error();
exit(1);
}
@@ -474,11 +474,11 @@
//if (Mix_OpenAudio(44100, AUDIO_S16SYS, 2, 2048) < 0)
if (Mix_OpenAudio(MIX_DEFAULT_FREQUENCY, AUDIO_S16SYS, 2, 2048) < 0)
{
- fprintf(stderr,
- "\nWarning: I could not set up audio for 44100 Hz "
- "16-bit stereo.\n"
- "The Simple DirectMedia error that occured was:\n"
- "%s\n\n", SDL_GetError());
+ fprintf(stderr,
+ "\nWarning: I could not set up audio for 44100 Hz "
+ "16-bit stereo.\n"
+ "The Simple DirectMedia error that occured was:\n"
+ "%s\n\n", SDL_GetError());
}
}
@@ -523,8 +523,8 @@
{
fprintf(stderr,
"\nWarning: I could not open the display in fullscreen mode.\n"
- "The Simple DirectMedia error that occured was:\n"
- "%s\n\n", SDL_GetError());
+ "The Simple DirectMedia error that occured was:\n"
+ "%s\n\n", SDL_GetError());
Opts_SetFullscreen(0);
}
}
@@ -538,8 +538,8 @@
{
fprintf(stderr,
"\nError: I could not open the display.\n"
- "The Simple DirectMedia error that occured was:\n"
- "%s\n\n", SDL_GetError());
+ "The Simple DirectMedia error that occured was:\n"
+ "%s\n\n", SDL_GetError());
cleanup_on_error();
exit(1);
}
Modified: tuxmath/trunk/src/titlescreen.c
===================================================================
--- tuxmath/trunk/src/titlescreen.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/titlescreen.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -115,14 +115,14 @@
/* --- locations we need --- */
SDL_Rect dest,
- Tuxdest,
- Titledest,
+ Tuxdest,
+ Titledest,
stopRect,
Backrect,
Tuxback,
Titleback,
- cursor,
- beak;
+ cursor,
+ beak;
/* The background image scaled to windowed 648x480 */
SDL_Surface* bkg = NULL;
@@ -432,8 +432,12 @@
int i;
for (i = 0; i < N_SPRITES; i++)
+ {
+ tmdprintf("Freeing image #%d: ", i);
FreeSprite(sprite_list[i]);
+ }
free(sprite_list);
+ tmdprintf("Images freed\n");
sprite_list = NULL;
}
@@ -441,9 +445,11 @@
void TitleScreen_unload_media(void)
{
+ tmdprintf("Unloading media\n");
FreeSprite(Tux);
Tux = NULL;
TitleScreen_unload_menu();
+
SDL_FreeSurface(egg);
SDL_FreeSurface(bkg);
SDL_FreeSurface(scaled_bkg);
@@ -661,40 +667,41 @@
while (choice >= 0) {
switch (choice) {
case 0: {
- // Training academy lessons
- ret = run_lessons_menu();
- break;
+ // Training academy lessons
+ ret = run_lessons_menu();
+ break;
}
case 1: {
- // Arcade games
- ret = run_arcade_menu();
- break;
+ // Arcade games
+ ret = run_arcade_menu();
+ break;
}
case 2: {
- // Custom game
- ret = run_custom_menu();
- break;
+ // Custom game
+ ret = run_custom_menu();
+ break;
}
case 3: {
- // Help
- Opts_SetHelpMode(1);
- Opts_SetDemoMode(0);
- if (Opts_MenuMusic()) //Turn menu music off for game
- {audioMusicUnload();}
- game();
- RecalcTitlePositions();
- if (Opts_MenuMusic()) //Turn menu music back on
- {audioMusicLoad( "tuxi.ogg", -1 );}
- Opts_SetHelpMode(0);
- break;
+ // Help
+ Opts_SetHelpMode(1);
+ Opts_SetDemoMode(0);
+ if (Opts_MenuMusic()) //Turn menu music off for game
+ {audioMusicUnload();}
+ game();
+ RecalcTitlePositions();
+ if (Opts_MenuMusic()) //Turn menu music back on
+ {audioMusicLoad( "tuxi.ogg", -1 );}
+ Opts_SetHelpMode(0);
+ break;
}
case 4: {
- // More options
- ret = run_options_menu();
+ // More options
+ ret = run_options_menu();
break;
}
case 5: {
- // Quit
+ // Quit
+ tmdprintf("Exiting main menu\n");
return 0;
}
}
@@ -706,19 +713,24 @@
int run_arcade_menu(void)
{
- const unsigned char* menu_text[6] =
+ const unsigned char* menu_text[7] =
{(const unsigned char*)N_("Space Cadet"),
(const unsigned char*)N_("Scout"),
(const unsigned char*)N_("Ranger"),
(const unsigned char*)N_("Ace"),
+ (const unsigned char*)N_("Commando"),
(const unsigned char*)N_("Hall Of Fame"),
(const unsigned char*)N_("Main menu")};
- const char* arcade_config_files[4] =
- {"arcade/space_cadet", "arcade/scout", "arcade/ranger", "arcade/ace"};
- const int arcade_high_score_tables[4] =
- {CADET_HIGH_SCORE,SCOUT_HIGH_SCORE,RANGER_HIGH_SCORE,ACE_HIGH_SCORE};
- sprite* sprites[6] =
- {NULL, NULL, NULL, NULL, NULL, NULL};
+ const char* arcade_config_files[5] =
+ {"arcade/space_cadet", "arcade/scout", "arcade/ranger", "arcade/ace",
+ "arcade/commando"
+ };
+ const int arcade_high_score_tables[5] =
+ {CADET_HIGH_SCORE,SCOUT_HIGH_SCORE,RANGER_HIGH_SCORE,ACE_HIGH_SCORE,
+ COMMANDO_HIGH_SCORE
+ };
+ sprite* sprites[7] =
+ {NULL, NULL, NULL, NULL, NULL, NULL, NULL};
menu_options menu_opts;
int choice,hs_table;
@@ -727,54 +739,55 @@
sprites[1] = sprite_list[SPRITE_SCOUT];
sprites[2] = sprite_list[SPRITE_RANGER];
sprites[3] = sprite_list[SPRITE_ACE];
- sprites[4] = sprite_list[SPRITE_TROPHY];
- sprites[5] = sprite_list[SPRITE_MAIN];
+ //TODO commando sprite
+ sprites[5] = sprite_list[SPRITE_TROPHY];
+ sprites[6] = sprite_list[SPRITE_MAIN];
// set_default_menu_options(&menu_opts);
// menu_opts.ytop = 100;
//This function takes care of all the drawing and receives
//user input:
- choice = choose_menu_item(menu_text,sprites,6,NULL,NULL);
+ choice = choose_menu_item(menu_text,sprites,7,NULL,NULL);
while (choice >= 0) {
- if (choice < 4) {
+ if (choice < NUM_HIGH_SCORE_LEVELS) {
// Play arcade game
if (read_named_config_file(arcade_config_files[choice]))
{
- audioMusicUnload();
- game();
- RecalcTitlePositions();
- if (Opts_MenuMusic()) {
- audioMusicLoad( "tuxi.ogg", -1 );
- }
- /* See if player made high score list! */
- read_high_scores(); /* Update, in case other users have added to it */
- hs_table = arcade_high_score_tables[choice];
- if (check_score_place(hs_table, Opts_LastScore()) < HIGH_SCORES_SAVED){
+ audioMusicUnload();
+ game();
+ RecalcTitlePositions();
+ if (Opts_MenuMusic()) {
+ audioMusicLoad( "tuxi.ogg", -1 );
+ }
+ /* See if player made high score list! */
+ read_high_scores(); /* Update, in case other users have added to it */
+ hs_table = arcade_high_score_tables[choice];
+ if (check_score_place(hs_table, Opts_LastScore()) < HIGH_SCORES_SAVED){
- unsigned char player_name[HIGH_SCORE_NAME_LENGTH * 3];
+ unsigned char player_name[HIGH_SCORE_NAME_LENGTH * 3];
- /* Get name from player: */
- HighScoreNameEntry(&player_name[0]);
- insert_score(player_name, hs_table, Opts_LastScore());
- /* Show the high scores. Note the user will see his/her */
- /* achievement even if (in the meantime) another player */
- /* has in fact already bumped this score off the table. */
- DisplayHighScores(hs_table);
- /* save to disk: */
- /* See "On File Locking" in fileops.c */
- append_high_score(choice,Opts_LastScore(),&player_name[0]);
+ /* Get name from player: */
+ HighScoreNameEntry(&player_name[0]);
+ insert_score(player_name, hs_table, Opts_LastScore());
+ /* Show the high scores. Note the user will see his/her */
+ /* achievement even if (in the meantime) another player */
+ /* has in fact already bumped this score off the table. */
+ DisplayHighScores(hs_table);
+ /* save to disk: */
+ /* See "On File Locking" in fileops.c */
+ append_high_score(choice,Opts_LastScore(),&player_name[0]);
#ifdef TUXMATH_DEBUG
- print_high_scores(stderr);
+ print_high_scores(stderr);
#endif
- }
+ }
} else {
- fprintf(stderr, "\nCould not find %s config file\n",arcade_config_files[choice]);
+ fprintf(stderr, "\nCould not find %s config file\n",arcade_config_files[choice]);
}
- } else if (choice == 4) {
+ } else if (choice == NUM_HIGH_SCORE_LEVELS) {
// Display the Hall of Fame
DisplayHighScores(CADET_HIGH_SCORE);
}
@@ -864,14 +877,14 @@
// Demo
if (read_named_config_file("demo"))
{
- audioMusicUnload();
- game();
- RecalcTitlePositions();
- if (Opts_MenuMusic()) {
- audioMusicLoad( "tuxi.ogg", -1 );
- }
+ audioMusicUnload();
+ game();
+ RecalcTitlePositions();
+ if (Opts_MenuMusic()) {
+ audioMusicLoad( "tuxi.ogg", -1 );
+ }
} else {
- fprintf(stderr, "\nCould not find demo config file\n");
+ fprintf(stderr, "\nCould not find demo config file\n");
}
break;
@@ -880,9 +893,9 @@
// Project Info
//NotImplemented();
ShowMessage(_("TuxMath is free and open-source!"),
- _("You can help make it better by reporting problems,"),
- _("suggesting improvements, or adding code."),
- _("Discuss the future at tuxmath-devel at lists.sourceforge.net"));
+ _("You can help make it better by reporting problems,"),
+ _("suggesting improvements, or adding code."),
+ _("Discuss the future at tuxmath-devel at lists.sourceforge.net"));
break;
}
case 2: {
@@ -1042,21 +1055,21 @@
// User pressed escape or selected Quit/Back, handle by quitting
// or going up a level
if (level == 0) {
- // We are going to quit without logging in.
- // Clean up memory (prob. not necessary, but prevents Valgrind errors!)
- for (i = 0; i < n_login_questions; i++)
- free(user_login_questions[i]);
- free(user_login_questions);
- for (i = 0; i < n_users; i++)
- free(user_names[i]);
- free(user_names);
- return -1;
+ // We are going to quit without logging in.
+ // Clean up memory (prob. not necessary, but prevents Valgrind errors!)
+ for (i = 0; i < n_login_questions; i++)
+ free(user_login_questions[i]);
+ free(user_login_questions);
+ for (i = 0; i < n_users; i++)
+ free(user_names[i]);
+ free(user_names);
+ return -1;
}
else {
- // Go back up one level of the directory tree
- user_data_dirname_up();
- level--;
- menu_opts.starting_entry = -1;
+ // Go back up one level of the directory tree
+ user_data_dirname_up();
+ level--;
+ menu_opts.starting_entry = -1;
}
}
else {
@@ -1105,7 +1118,7 @@
/* (the function returns the index for the selected menu item) */
/* -1 indicates that the user pressed escape */
/****************************************************************/
-int choose_menu_item(const unsigned char **menu_text, sprite **menu_sprites, int n_menu_entries, menu_options* custom_mo, void (*set_custom_menu_opts)(menu_options*) )
+int choose_menu_item(const char **menu_text, sprite **menu_sprites, int n_menu_entries, menu_options* custom_mo, void (*set_custom_menu_opts)(menu_options*) )
{
// Pixel renderings of menu text choices
SDL_Surface **menu_item_unselected = NULL;
@@ -1206,7 +1219,7 @@
buttonheight = 0;
for (i = 0; i < n_menu_entries; i++)
if (buttonheight < menu_item_unselected[i]->h)
- buttonheight = menu_item_unselected[i]->h;
+ buttonheight = menu_item_unselected[i]->h;
buttonheight += 10;
} else
buttonheight = menu_opts.buttonheight;
@@ -1360,7 +1373,7 @@
case SDL_MOUSEMOTION:
{
- loc = -1; // By default, don't be in any entry
+ loc = -1; // By default, don't be in any entry
for (i = 0; (i < n_entries_per_screen) && (loc_screen_start + i < n_menu_entries); i++)
{
if (inRect(menu_button_rect[i], event.motion.x, event.motion.y))
@@ -1423,8 +1436,8 @@
}
loc = loc_screen_start + i;
- stop = 1;
- break;
+ stop = 1;
+ break;
}
}
@@ -1434,8 +1447,8 @@
if (loc_screen_start - n_entries_per_screen >= 0)
{
//loc = loc_screen_start - n_entries_per_screen;
- loc_screen_start -= n_entries_per_screen;
- loc = -1; // nothing selected
+ loc_screen_start -= n_entries_per_screen;
+ loc = -1; // nothing selected
if (Opts_MenuSound())
{
playsound(SND_TOCK);
@@ -1450,8 +1463,8 @@
if (loc_screen_start + n_entries_per_screen < n_menu_entries)
{
//loc = loc_screen_start + n_entries_per_screen;
- loc_screen_start += n_entries_per_screen;
- loc = -1; // nothing selected
+ loc_screen_start += n_entries_per_screen;
+ loc = -1; // nothing selected
if (Opts_MenuSound())
{
playsound(SND_TOCK);
@@ -1487,7 +1500,7 @@
{
if (Opts_MenuSound())
playsound(SND_POP);
- stop = 1;
+ stop = 1;
break;
}
@@ -1499,9 +1512,9 @@
if (Opts_MenuSound())
playsound(SND_TOCK);
if (loc_screen_start - n_entries_per_screen >= 0) {
- loc_screen_start -= n_entries_per_screen;
- loc = -1;
- }
+ loc_screen_start -= n_entries_per_screen;
+ loc = -1;
+ }
// {loc = loc_screen_start - n_entries_per_screen;}
break;
}
@@ -1514,9 +1527,9 @@
if (Opts_MenuSound())
playsound(SND_TOCK);
if (loc_screen_start + n_entries_per_screen < n_menu_entries) {
- loc_screen_start += n_entries_per_screen;
- loc = -1;
- }
+ loc_screen_start += n_entries_per_screen;
+ loc = -1;
+ }
// {loc = (loc_screen_start + n_entries_per_screen);}
break;
}
@@ -1528,15 +1541,15 @@
playsound(SND_TOCK);
if (loc > title_offset)
{loc--;}
- else if (n_menu_entries <= n_entries_per_screen) {
- loc = n_menu_entries-1; // wrap around if only 1 screen
- }
- else if (loc == -1 && loc_screen_start > 0) {
- loc = loc_screen_start-1;
- loc_screen_start -= n_entries_per_screen;
- }
- if (loc != old_loc)
- warp_mouse = 1;
+ else if (n_menu_entries <= n_entries_per_screen) {
+ loc = n_menu_entries-1; // wrap around if only 1 screen
+ }
+ else if (loc == -1 && loc_screen_start > 0) {
+ loc = loc_screen_start-1;
+ loc_screen_start -= n_entries_per_screen;
+ }
+ if (loc != old_loc)
+ warp_mouse = 1;
break;
}
@@ -1548,12 +1561,12 @@
playsound(SND_TOCK);
if (loc >= 0 && loc + 1 < n_menu_entries)
{loc++;}
- else if (n_menu_entries <= n_entries_per_screen)
- loc = title_offset; // wrap around if only 1 screen
- else if (loc == -1)
- loc = loc_screen_start;
- if (loc != old_loc)
- warp_mouse = 1;
+ else if (n_menu_entries <= n_entries_per_screen)
+ loc = title_offset; // wrap around if only 1 screen
+ else if (loc == -1)
+ loc = loc_screen_start;
+ if (loc != old_loc)
+ warp_mouse = 1;
break;
}
@@ -1595,11 +1608,11 @@
audioMusicLoad("tuxi.ogg", -1);
}
break;
- }
-#ifdef TESTING_CAMPAIGN
- case SDLK_c:
- {
- start_campaign();
+ }
+#ifdef TESTING_CAMPAIGN
+ case SDLK_c:
+ {
+ start_campaign();
RecalcTitlePositions();
RecalcMenuPositions(&n_entries_per_screen,
n_menu_entries,
@@ -1613,8 +1626,9 @@
&back_text_rect,
&left_arrow_rect,
&right_arrow_rect);
- redraw = 1;
+ redraw = 1;
}
+
#endif
default:
{
@@ -1656,57 +1670,57 @@
if (images[IMG_STOP])
SDL_BlitSurface(images[IMG_STOP], NULL, screen, &stopRect);
if (Tux->frame[0])
- SDL_BlitSurface(Tux->frame[0], NULL, screen, &Tuxdest);
+ SDL_BlitSurface(Tux->frame[0], NULL, screen, &Tuxdest);
/* Redraw the menu entries */
for (imod = 0; imod < n_entries_per_screen; imod++)
- menu_button_rect[imod].w = 0; // so undrawn buttons don't affect width
+ menu_button_rect[imod].w = 0; // so undrawn buttons don't affect width
for (i = loc_screen_start, imod = 0; i < loc_screen_start+n_entries_per_screen && i < n_menu_entries; i++, imod++) {
- menu_text_rect[imod].w = menu_item_unselected[i]->w;
- if (i >= title_offset) {
- menu_button_rect[imod].w = menu_text_rect[imod].w + 30;
- if (menu_sprites != NULL)
- menu_button_rect[imod].w += 60;
- }
+ menu_text_rect[imod].w = menu_item_unselected[i]->w;
+ if (i >= title_offset) {
+ menu_button_rect[imod].w = menu_text_rect[imod].w + 30;
+ if (menu_sprites != NULL)
+ menu_button_rect[imod].w += 60;
+ }
}
if (menu_opts.button_same_width)
- set_buttons_max_width(menu_button_rect,back_button_rect,n_entries_per_screen);
+ set_buttons_max_width(menu_button_rect,back_button_rect,n_entries_per_screen);
// Make sure the menu title mouse button didn't get turned on
if (loc_screen_start == 0 && title_offset)
- menu_button_rect[0].w = 0;
+ menu_button_rect[0].w = 0;
for (i = loc_screen_start, imod = 0; i < loc_screen_start+n_entries_per_screen && i < n_menu_entries; i++, imod++) {
- if (i == loc) { //Draw text in yellow
- DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
- SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
- }
- else { //Draw text in white
- if (menu_button_rect[imod].w > 0)
- DrawButton(&menu_button_rect[imod], 10, REG_RGBA);
- SDL_BlitSurface(menu_item_unselected[i], NULL, screen, &menu_text_rect[imod]);
- }
- if (menu_sprites != NULL && (i >= title_offset) && menu_sprites[i-title_offset] != NULL)
- SDL_BlitSurface(menu_sprites[i-title_offset]->default_img, NULL, screen, &menu_sprite_rect[imod]);
+ if (i == loc) { //Draw text in yellow
+ DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
+ SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
+ }
+ else { //Draw text in white
+ if (menu_button_rect[imod].w > 0)
+ DrawButton(&menu_button_rect[imod], 10, REG_RGBA);
+ SDL_BlitSurface(menu_item_unselected[i], NULL, screen, &menu_text_rect[imod]);
+ }
+ if (menu_sprites != NULL && (i >= title_offset) && menu_sprites[i-title_offset] != NULL)
+ SDL_BlitSurface(menu_sprites[i-title_offset]->default_img, NULL, screen, &menu_sprite_rect[imod]);
}
/* --- draw 'left' and 'right' buttons --- */
if (n_menu_entries > n_entries_per_screen) {
- if (loc_screen_start > 0) // i.e. not on first page
- {
- SDL_BlitSurface(images[IMG_LEFT], NULL, screen, &left_arrow_rect);
- }
- else /* Draw grayed-out left button: */
+ if (loc_screen_start > 0) // i.e. not on first page
{
- SDL_BlitSurface(images[IMG_LEFT_GRAY], NULL, screen, &left_arrow_rect);
- }
+ SDL_BlitSurface(images[IMG_LEFT], NULL, screen, &left_arrow_rect);
+ }
+ else /* Draw grayed-out left button: */
+ {
+ SDL_BlitSurface(images[IMG_LEFT_GRAY], NULL, screen, &left_arrow_rect);
+ }
- if (loc_screen_start + n_entries_per_screen < n_menu_entries) // not on last page
+ if (loc_screen_start + n_entries_per_screen < n_menu_entries) // not on last page
{
- SDL_BlitSurface(images[IMG_RIGHT], NULL, screen, &right_arrow_rect);
- }
- else /* Draw grayed-out right button: */
- {
- SDL_BlitSurface(images[IMG_RIGHT_GRAY], NULL, screen, &right_arrow_rect);
- }
+ SDL_BlitSurface(images[IMG_RIGHT], NULL, screen, &right_arrow_rect);
+ }
+ else /* Draw grayed-out right button: */
+ {
+ SDL_BlitSurface(images[IMG_RIGHT_GRAY], NULL, screen, &right_arrow_rect);
+ }
}
SDL_Flip(screen);//SDL_UpdateRect(screen, 0, 0, 0 ,0);
@@ -1714,68 +1728,68 @@
// This is not a full redraw, but the selected entry did change.
// By just redrawing the old and new selections, we avoid flickering.
if (old_loc >= 0) {
- imod = old_loc-loc_screen_start;
- use_sprite = (menu_sprites != NULL && old_loc >= title_offset && menu_sprites[old_loc-title_offset] != NULL);
+ imod = old_loc-loc_screen_start;
+ use_sprite = (menu_sprites != NULL && old_loc >= title_offset && menu_sprites[old_loc-title_offset] != NULL);
temp_rect = menu_button_rect[imod];
SDL_FillRect(screen, &temp_rect, 0);
- SDL_BlitSurface(current_bkg(), &back_button_rect[imod], screen, &temp_rect); // redraw background
- if (use_sprite) {
- // Some of the sprites extend beyond the menu button, so we
- // have to make sure we redraw in the sprite rects, too
- SDL_BlitSurface(current_bkg(), &back_sprite_rect[imod], screen, &temp_rect);
- }
- DrawButton(&menu_button_rect[imod], 10, REG_RGBA); // draw button
- //temp_rect = menu_text_rect[imod];
- SDL_BlitSurface(menu_item_unselected[old_loc], NULL, screen, &menu_text_rect[imod]); // draw text
- if (use_sprite) {
- temp_rect = menu_sprite_rect[imod];
- tmdprintf("Sprite %d at (%d %d)\n", imod, temp_rect.x, temp_rect.y);
- SDL_BlitSurface(menu_sprites[old_loc-title_offset]->default_img, NULL, screen, &temp_rect);
- // Also update the sprite rect (in some cases the sprite
- // extends beyond the menu button)
- SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
- }
- SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
+ SDL_BlitSurface(current_bkg(), &back_button_rect[imod], screen, &temp_rect); // redraw background
+ if (use_sprite) {
+ // Some of the sprites extend beyond the menu button, so we
+ // have to make sure we redraw in the sprite rects, too
+ SDL_BlitSurface(current_bkg(), &back_sprite_rect[imod], screen, &temp_rect);
+ }
+ DrawButton(&menu_button_rect[imod], 10, REG_RGBA); // draw button
+ //temp_rect = menu_text_rect[imod];
+ SDL_BlitSurface(menu_item_unselected[old_loc], NULL, screen, &menu_text_rect[imod]); // draw text
+ if (use_sprite) {
+ temp_rect = menu_sprite_rect[imod];
+ tmdprintf("Sprite %d at (%d %d)\n", imod, temp_rect.x, temp_rect.y);
+ SDL_BlitSurface(menu_sprites[old_loc-title_offset]->default_img, NULL, screen, &temp_rect);
+ // Also update the sprite rect (in some cases the sprite
+ // extends beyond the menu button)
+ SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
+ }
+ SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
}
if (loc >= 0) {
- imod = loc-loc_screen_start;
- use_sprite = (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc] != NULL);
- temp_rect = menu_button_rect[imod];
- SDL_BlitSurface(current_bkg, &back_button_rect[imod], screen, &temp_rect);
- if (use_sprite)
- {
- temp_rect = menu_sprite_rect[imod];
- SDL_BlitSurface(current_bkg, &back_sprite_rect[imod], screen, &temp_rect);
- }
- DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
- SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
- if (use_sprite) {
- menu_sprites[loc-title_offset]->cur = 0; // start at beginning of animation sequence
- SDL_BlitSurface(menu_sprites[loc-title_offset]->frame[menu_sprites[loc-title_offset]->cur], NULL, screen, &menu_sprite_rect[imod]);
- SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
- next_frame(menu_sprites[loc-title_offset]);
- }
- SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
- tmdprintf("Updating rect: %d %d %d %d\n", menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
+ imod = loc-loc_screen_start;
+ use_sprite = (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc] != NULL);
+ temp_rect = menu_button_rect[imod];
+ SDL_BlitSurface(current_bkg(), &(back_button_rect[imod]), screen, &temp_rect);
+ if (use_sprite)
+ {
+ temp_rect = menu_sprite_rect[imod];
+ SDL_BlitSurface(current_bkg(), &(back_sprite_rect[imod]), screen, &temp_rect);
+ }
+ DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
+ SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
+ if (use_sprite) {
+ menu_sprites[loc-title_offset]->cur = 0; // start at beginning of animation sequence
+ SDL_BlitSurface(menu_sprites[loc-title_offset]->frame[menu_sprites[loc-title_offset]->cur], NULL, screen, &menu_sprite_rect[imod]);
+ SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
+ next_frame(menu_sprites[loc-title_offset]);
+ }
+ SDL_UpdateRect(screen, menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
+ tmdprintf("Updating rect: %d %d %d %d\n", menu_button_rect[imod].x, menu_button_rect[imod].y, menu_button_rect[imod].w, menu_button_rect[imod].h);
}
} else if (frame_counter % 5 == 0 && loc >= 0) {
// No user input changed anything, but check to see if we need to
// animate the sprite
if (menu_sprites != NULL && loc >= title_offset && menu_sprites[loc-title_offset] != NULL) {
- imod = loc-loc_screen_start;
- //SDL_BlitSurface(current_bkg, &menu_button_rect[imod], screen, &menu_button_rect[imod]);
- temp_rect = menu_sprite_rect[imod];
- SDL_BlitSurface(current_bkg(), &back_sprite_rect[imod], screen, &temp_rect);
- DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
- //SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
- // Note: even though the whole button was redrawn, we don't
- // have to redraw the text & background as long as we don't
- // update that rect. If something else changes and we go to
- // full-screen updates, then remove the "commenting-out" on
- // the two lines above
- SDL_BlitSurface(menu_sprites[loc-title_offset]->frame[menu_sprites[loc-title_offset]->cur], NULL, screen, &menu_sprite_rect[imod]);
- SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
- next_frame(menu_sprites[loc-title_offset]);
+ imod = loc-loc_screen_start;
+ //SDL_BlitSurface(current_bkg, &menu_button_rect[imod], screen, &menu_button_rect[imod]);
+ temp_rect = menu_sprite_rect[imod];
+ SDL_BlitSurface(current_bkg(), &back_sprite_rect[imod], screen, &temp_rect);
+ DrawButton(&menu_button_rect[imod], 10, SEL_RGBA);
+ //SDL_BlitSurface(menu_item_selected[loc], NULL, screen, &menu_text_rect[imod]);
+ // Note: even though the whole button was redrawn, we don't
+ // have to redraw the text & background as long as we don't
+ // update that rect. If something else changes and we go to
+ // full-screen updates, then remove the "commenting-out" on
+ // the two lines above
+ SDL_BlitSurface(menu_sprites[loc-title_offset]->frame[menu_sprites[loc-title_offset]->cur], NULL, screen, &menu_sprite_rect[imod]);
+ SDL_UpdateRect(screen, menu_sprite_rect[imod].x, menu_sprite_rect[imod].y, menu_sprite_rect[imod].w, menu_sprite_rect[imod].h);
+ next_frame(menu_sprites[loc-title_offset]);
}
}
@@ -1817,7 +1831,8 @@
}
if (egg_active) { //if we need to, draw the egg cursor
- SDL_GetMouseState(&cursor.x, &cursor.y);
+ //who knows why GetMouseState() doesn't take Sint16's...
+ SDL_GetMouseState((int*)&cursor.x, (int*)&cursor.y);
cursor.x -= egg->w / 2; //center vertically
SDL_BlitSurface(egg, NULL, screen, &cursor);
SDL_UpdateRect(screen, cursor.x, cursor.y, cursor.w, cursor.h);
@@ -2071,28 +2086,28 @@
UpdateScreen : Update the screen and increment the frame num
***************************/
void UpdateScreen(int *frame) {
- int i;
+ int i;
- /* -- First erase everything we need to -- */
- for (i = 0; i < numupdates; i++)
- if (blits[i].type == 'E')
- SDL_LowerBlit(blits[i].src, blits[i].srcrect, screen, blits[i].dstrect);
-// SNOW_erase();
+ /* -- First erase everything we need to -- */
+ for (i = 0; i < numupdates; i++)
+ if (blits[i].type == 'E')
+ SDL_LowerBlit(blits[i].src, blits[i].srcrect, screen, blits[i].dstrect);
+// SNOW_erase();
- /* -- then draw -- */
- for (i = 0; i < numupdates; i++)
- if (blits[i].type == 'D')
- SDL_BlitSurface(blits[i].src, blits[i].srcrect, screen, blits[i].dstrect);
-// SNOW_draw();
+ /* -- then draw -- */
+ for (i = 0; i < numupdates; i++)
+ if (blits[i].type == 'D')
+ SDL_BlitSurface(blits[i].src, blits[i].srcrect, screen, blits[i].dstrect);
+// SNOW_draw();
- /* -- update the screen only where we need to! -- */
-// if (SNOW_on)
-// SDL_UpdateRects(screen, SNOW_add( (SDL_Rect*)&dstupdate, numupdates ), SNOW_rects);
-// else
- SDL_UpdateRects(screen, numupdates, dstupdate);
+/* -- update the screen only where we need to! -- */
+// if (SNOW_on)
+// SDL_UpdateRects(screen, SNOW_add( (SDL_Rect*)&dstupdate, numupdates ), SNOW_rects);
+// else
+ SDL_UpdateRects(screen, numupdates, dstupdate);
- numupdates = 0;
- *frame = *frame + 1;
+ numupdates = 0;
+ *frame = *frame + 1;
}
Modified: tuxmath/trunk/src/titlescreen.h
===================================================================
--- tuxmath/trunk/src/titlescreen.h 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/titlescreen.h 2008-08-06 02:55:05 UTC (rev 589)
@@ -26,7 +26,7 @@
#define to_upper(c) (((c) >= 'a' && (c) <= 'z') ? (c) -32 : (c))
#define COL2RGB( col ) SDL_MapRGB( screen->format, col->r, col->g, col->b )
-//#define FNLEN 200
+//#define FNLEN 200
#define MAX_SPRITE_FRAMES 30
@@ -44,7 +44,7 @@
#include "SDL_ttf.h"
#ifndef MACOSX
-#include "config.h"
+//#include "config.h"
#endif
#include "tuxmath.h"
@@ -53,10 +53,10 @@
typedef struct {
- SDL_Surface *frame[MAX_SPRITE_FRAMES];
- SDL_Surface *default_img;
- int num_frames;
- int cur;
+ SDL_Surface *frame[MAX_SPRITE_FRAMES];
+ SDL_Surface *default_img;
+ int num_frames;
+ int cur;
} sprite;
// Options that affect how menus are presented
@@ -74,10 +74,10 @@
#define menu_font "AndikaDesRevA.ttf" /* "GenAI102.ttf" */
-#define menu_font_size 18
+#define menu_font_size 18
#define ttf_font "AndikaDesRevA.ttf" /* "GenAI102.ttf" */
-#define ttf_font_size 18
+#define ttf_font_size 18
#define MAX_LESSONS 100
#define MAX_NUM_WORDS 500
@@ -87,15 +87,15 @@
#define MAX_UPDATES 180
-#define WAIT_MS 2500
-#define FRAMES_PER_SEC 50
-#define FULL_CIRCLE 140
+#define WAIT_MS 2500
+#define FRAMES_PER_SEC 50
+#define FULL_CIRCLE 140
/* Title sequence constants */
-#define PRE_ANIM_FRAMES 10
-#define PRE_FRAME_MULT 3
-#define MENU_SEP 20
+#define PRE_ANIM_FRAMES 10
+#define PRE_FRAME_MULT 3
+#define MENU_SEP 20
/* paths */
@@ -115,7 +115,7 @@
SDL_Surface* current_bkg(); //appropriate background for current video mode
-#define MUSIC_FADE_OUT_MS 80
+#define MUSIC_FADE_OUT_MS 80
enum {
WIPE_BLINDS_VERT,
@@ -134,9 +134,9 @@
#define TITLE_MENU_DEPTH 4
#define OPTIONS_SUBMENU 4
-#define GAME_OPTIONS_SUBMENU 3
-#define ARCADE_SUBMENU 2
-#define ROOTMENU 1
+#define GAME_OPTIONS_SUBMENU 3
+#define ARCADE_SUBMENU 2
+#define ROOTMENU 1
/* --- timings for tux blinking --- */
@@ -157,7 +157,11 @@
/*In titlescreen.c */
void TitleScreen(void);
int ChooseMission(void); //FIXME really should be in fileops.c
-int choose_menu_item(const unsigned char**, sprite**, int, menu_options*, void (*)(menu_options*) );
+int choose_menu_item(const char **menu_text,
+ sprite **menu_sprites,
+ int n_menu_entries,
+ menu_options* custom_mo,
+ void (*set_custom_menu_opts)(menu_options*) );
void set_default_menu_options(menu_options *);
@@ -167,7 +171,9 @@
Mix_Chunk *LoadSound( char* datafile );
SDL_Surface *LoadImage( char* datafile, int mode );
SDL_Surface* LoadBkgd(char* datafile);
-int LoadBothBkgds(char* datafile, SDL_Surface** fs_bkgd, SDL_Surface** win_bkgd);
+int LoadBothBkgds(char* datafile,
+ SDL_Surface** fs_bkgd,
+ SDL_Surface** win_bkgd);
sprite *LoadSprite( char* name, int MODE );
sprite *FlipSprite( sprite* in, int X, int Y );
void FreeSprite( sprite* gfx );
Modified: tuxmath/trunk/src/tuxmath.h
===================================================================
--- tuxmath/trunk/src/tuxmath.h 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/tuxmath.h 2008-08-06 02:55:05 UTC (rev 589)
@@ -22,7 +22,9 @@
#ifndef TUXMATH_H
#define TUXMATH_H
-#include "config.h"
+//To build with CMake, comment out this line so we don't include "config.h"
+//To build with Autotools, uncomment it as we must have "config.h"
+//#include "config.h"
// Translation stuff (now works for Mac and Win too!):
#include "gettext.h"
@@ -81,7 +83,7 @@
#define DEFAULT_STARTING_COMETS 2
#define DEFAULT_EXTRA_COMETS_PER_WAVE 2
#define DEFAULT_MAX_COMETS 10
-#define DEFAULT_SAVE_SUMMARY 1
+#define DEFAULT_SAVE_SUMMARY 1
#define DEFAULT_SOUND_HW_AVAILABLE 1
#define DEFAULT_USE_IGLOOS 1
#define DEFAULT_USE_FEEDBACK 0
@@ -98,7 +100,7 @@
#define MINIMUM_SPEED 0.8
#define MAX_MAX_SPEED 20.0
-#define MIN_SPEEDUP_FACTOR 1
+#define MIN_SPEEDUP_FACTOR 1.0
#define MAX_SPEEDUP_FACTOR 2.0
#define MAX_BONUS_SPEED_RATIO 3.0
#define MIN_COMETS 1
@@ -115,15 +117,16 @@
#define REG_RGBA 16,16,96,96
#define SEL_RGBA 16,16,128,128
-#define RES_X 640
-#define RES_Y 480
-#define PIXEL_BITS 32
+#define RES_X 640
+#define RES_Y 480
+#define PIXEL_BITS 32
enum {
CADET_HIGH_SCORE,
SCOUT_HIGH_SCORE,
RANGER_HIGH_SCORE,
ACE_HIGH_SCORE,
+ COMMANDO_HIGH_SCORE,
NUM_HIGH_SCORE_LEVELS
};
Modified: tuxmath/trunk/src/tuxmathadmin.c
===================================================================
--- tuxmath/trunk/src/tuxmathadmin.c 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/tuxmathadmin.c 2008-08-06 02:55:05 UTC (rev 589)
@@ -114,66 +114,66 @@
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[i], "--copyright") == 0 ||
- strcmp(argv[i], "-c") == 0)
+ strcmp(argv[i], "-c") == 0)
{
printf(
- "\ntuxmathadmin version " ADMINVERSION ", Copyright (C) 2007 Tim Holy\n"
+ "\ntuxmathadmin version " ADMINVERSION ", Copyright (C) 2007 Tim Holy\n"
"This program is free software; you can redistribute it and/or\n"
"modify it under the terms of the GNU General Public License\n"
"as published by the Free Software Foundation. See COPYING.txt\n"
- "\n"
- "This program is distributed in the hope that it will be useful,\n"
- "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
- "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
- "\n");
+ "\n"
+ "This program is distributed in the hope that it will be useful,\n"
+ "but WITHOUT ANY WARRANTY; without even the implied warranty of\n"
+ "MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"
+ "\n");
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[i], "--usage") == 0 ||
- strcmp(argv[i], "-u") == 0) {
+ strcmp(argv[i], "-u") == 0) {
usage(0, argv[0]);
exit(EXIT_SUCCESS);
}
else if (strcmp(argv[i], "--path") == 0) {
if (i+1 > argc) {
- fprintf(stderr, "%s option requires an argument (a directory name)\n", argv[i]);
- usage(EXIT_FAILURE, argv[0]);
+ fprintf(stderr, "%s option requires an argument (a directory name)\n", argv[i]);
+ usage(EXIT_FAILURE, argv[0]);
}
else {
- path = argv[i+1];
- dir = opendir(path); // determine whether directory exists
- if (dir == NULL)
- error(EXIT_FAILURE,errno,"path:\n %s",path);
- closedir(dir);
- i++; // increment so further processing skips over the argument
+ path = argv[i+1];
+ dir = opendir(path); // determine whether directory exists
+ if (dir == NULL)
+ error(EXIT_FAILURE,errno,"path:\n %s",path);
+ closedir(dir);
+ i++; // increment so further processing skips over the argument
}
}
else if (strcmp(argv[i], "--level") == 0) {
if (i+1 > argc) {
- fprintf(stderr, "%s option requires an argument (a level number)\n", argv[i]);
- usage(EXIT_FAILURE, argv[0]);
+ fprintf(stderr, "%s option requires an argument (a level number)\n", argv[i]);
+ usage(EXIT_FAILURE, argv[0]);
}
else {
- success = sscanf(argv[i+1],"%d",&level);
- if (!success) {
- fprintf(stderr,"level: %s is not a number\n",argv[i+1]);
- exit(EXIT_FAILURE);
- }
- i++; // increment so further processing skips over the argument
+ success = sscanf(argv[i+1],"%d",&level);
+ if (!success) {
+ fprintf(stderr,"level: %s is not a number\n",argv[i+1]);
+ exit(EXIT_FAILURE);
+ }
+ i++; // increment so further processing skips over the argument
}
}
else if (strcmp(argv[i], "--createhomedirs") == 0) {
is_creatinghomedirs = 1;
if (i+1 > argc) {
- fprintf(stderr, "%s option requires an argument (a file name)\n", argv[i]);
- usage(EXIT_FAILURE, argv[0]);
+ fprintf(stderr, "%s option requires an argument (a file name)\n", argv[i]);
+ usage(EXIT_FAILURE, argv[0]);
}
else {
- file = argv[i+1];
- fp = fopen(file,"r"); // determine whether the file exists
- if (fp == NULL)
- error(EXIT_FAILURE,errno,"createhomedirs using:\n %s",file);
- fclose(fp); // don't read it yet, do that elsewhere
- i++; // increment so further processing skips over the argument
+ file = argv[i+1];
+ fp = fopen(file,"r"); // determine whether the file exists
+ if (fp == NULL)
+ error(EXIT_FAILURE,errno,"createhomedirs using:\n %s",file);
+ fclose(fp); // don't read it yet, do that elsewhere
+ i++; // increment so further processing skips over the argument
}
}
else if (strcmp(argv[i], "--confighighscores") == 0) {
@@ -277,42 +277,42 @@
void display_help(void)
{
printf("\ntuxmathadmin\n"
- "This program facilitates administering tuxmath, and is particularly\n"
- "useful for schools and the like that may have many users.\n\n"
- "Examples:\n"
- " tuxmathadmin --path /servervolume/tuxmath_users --createhomedirs users.csv\n"
- " tuxmathadmin --createhomedirs users.csv\n"
- " Creates a user directory tree in location /servervolume/tuxmath_users,\n"
- " according to the structure specified in users.csv. See configure.pdf\n"
- " for details. The second syntax is applicable if you've defined the\n"
- " homedir path in the global configuration file.\n\n"
- " tuxmathadmin --confighighscores --level 3\n"
- " Sets up sharing of high scores at level 3 of the hierarchy (top is\n"
- " level 1). If students logging in are presented with a choice of grade,\n"
- " then classroom, and then user, then level 1 is the school, level 2 is the\n"
- " grade, level 3 is the classroom, and level 4 is the individual student.\n"
- " So level 3 would set it up so that all kids in the same classroom would\n"
- " compete for high scores.\n\n"
- " tuxmathadmin --unconfighighscores\n"
- " Removes any existing highscores configuration.\n\n"
- " tuxmathadmin --clearhighscores\n"
- " Clears high scores for all users in the location specified by the homedir\n"
- " setting in the global configuration file.\n\n"
- " tuxmathadmin --path /servervolume/tuxmath_users/2ndgrade --clearhighscores\n"
- " Clears the high scores for all users inside the 2ndgrade hierarchy.\n\n"
- " tuxmathadmin --cleargoldstars\n"
- " Clears the gold stars for all users.\n\n"
- " tuxmathadmin --path /servervolume/tuxmath_users/1st\\ grade/Mrs.\\ Smith --cleargoldstars\n"
- " Clears the gold stars for all users in Mrs. Smith's first grade class.\n\n"
- " tuxmathadmin --consolidatelogs\n"
- " Creates consolidated_log.csv files at one level above the lowest level\n"
- " of the directory hierarchy. These files can be opened with a spreadsheet\n"
- " program. This may be useful for tracking student progress.\n"
- " Note also that each student has a personal log.csv file in his/her own\n"
- " directory.\n\n"
- " tuxmathadmin --clearlogs\n"
- " Deletes all log.csv files in the directory hierarchy.\n\n"
- );
+ "This program facilitates administering tuxmath, and is particularly\n"
+ "useful for schools and the like that may have many users.\n\n"
+ "Examples:\n"
+ " tuxmathadmin --path /servervolume/tuxmath_users --createhomedirs users.csv\n"
+ " tuxmathadmin --createhomedirs users.csv\n"
+ " Creates a user directory tree in location /servervolume/tuxmath_users,\n"
+ " according to the structure specified in users.csv. See configure.pdf\n"
+ " for details. The second syntax is applicable if you've defined the\n"
+ " homedir path in the global configuration file.\n\n"
+ " tuxmathadmin --confighighscores --level 3\n"
+ " Sets up sharing of high scores at level 3 of the hierarchy (top is\n"
+ " level 1). If students logging in are presented with a choice of grade,\n"
+ " then classroom, and then user, then level 1 is the school, level 2 is the\n"
+ " grade, level 3 is the classroom, and level 4 is the individual student.\n"
+ " So level 3 would set it up so that all kids in the same classroom would\n"
+ " compete for high scores.\n\n"
+ " tuxmathadmin --unconfighighscores\n"
+ " Removes any existing highscores configuration.\n\n"
+ " tuxmathadmin --clearhighscores\n"
+ " Clears high scores for all users in the location specified by the homedir\n"
+ " setting in the global configuration file.\n\n"
+ " tuxmathadmin --path /servervolume/tuxmath_users/2ndgrade --clearhighscores\n"
+ " Clears the high scores for all users inside the 2ndgrade hierarchy.\n\n"
+ " tuxmathadmin --cleargoldstars\n"
+ " Clears the gold stars for all users.\n\n"
+ " tuxmathadmin --path /servervolume/tuxmath_users/1st\\ grade/Mrs.\\ Smith --cleargoldstars\n"
+ " Clears the gold stars for all users in Mrs. Smith's first grade class.\n\n"
+ " tuxmathadmin --consolidatelogs\n"
+ " Creates consolidated_log.csv files at one level above the lowest level\n"
+ " of the directory hierarchy. These files can be opened with a spreadsheet\n"
+ " program. This may be useful for tracking student progress.\n"
+ " Note also that each student has a personal log.csv file in his/her own\n"
+ " directory.\n\n"
+ " tuxmathadmin --clearlogs\n"
+ " Deletes all log.csv files in the directory hierarchy.\n\n"
+ );
}
// This function does the work of creating the user directory tree,
@@ -359,7 +359,7 @@
line_cur = line_begin;
while (!(*line_cur == '\r' || *line_cur == '\n')) {
if (*line_cur == ',')
- this_line_total_depth++;
+ this_line_total_depth++;
line_cur++;
}
@@ -368,23 +368,23 @@
max_depth = this_line_total_depth;
current_dirtree = (char **) malloc(max_depth * sizeof(char*));
if (current_dirtree == NULL) {
- fprintf(stderr,"Error: couldn't allocate memory for directory tree.\n");
- exit(EXIT_FAILURE);
+ fprintf(stderr,"Error: couldn't allocate memory for directory tree.\n");
+ exit(EXIT_FAILURE);
}
for (i = 0; i < max_depth; i++) {
- current_dirtree[i] = (char *) malloc(PATH_MAX * sizeof(char));
- if (current_dirtree[i] == NULL){
- fprintf(stderr,"Error: couldn't allocate memory for directory tree.\n");
- exit(EXIT_FAILURE);
- } else
- *(current_dirtree[i]) = '\0'; // initialize with blank string
+ current_dirtree[i] = (char *) malloc(PATH_MAX * sizeof(char));
+ if (current_dirtree[i] == NULL){
+ fprintf(stderr,"Error: couldn't allocate memory for directory tree.\n");
+ exit(EXIT_FAILURE);
+ } else
+ *(current_dirtree[i]) = '\0'; // initialize with blank string
}
}
else {
// Check that this line doesn't change the size of the directory hierarchy
if (this_line_total_depth != max_depth) {
- fprintf(stderr,"Error: line\n '%s'\ncontains a different number of depths to the hierarchy than the previous setting (%d).\n",buf,max_depth);
- exit(EXIT_FAILURE);
+ fprintf(stderr,"Error: line\n '%s'\ncontains a different number of depths to the hierarchy than the previous setting (%d).\n",buf,max_depth);
+ exit(EXIT_FAILURE);
}
}
@@ -403,29 +403,29 @@
// the string, so don't be bothered that line_cur could get to be
// one less than line_begin.
while (line_cur >= line_begin && *line_cur != ',')
- line_cur--;
+ line_cur--;
// Determine whether we have a new directory name
if (line_cur+1 < line_cur_end) {
- // We do, copy it over including the terminal \0
- copy_start = line_cur+1;
- if (*copy_start == '\"')
- copy_start++;
- if (line_cur_end[-1] == '\"') {
- line_cur_end--;
- *line_cur_end = '\0';
- }
- memcpy(current_dirtree[current_depth],copy_start,line_cur_end-copy_start+1);
- stop_blanking = 1; // don't clear blank fields in the future
+ // We do, copy it over including the terminal \0
+ copy_start = line_cur+1;
+ if (*copy_start == '\"')
+ copy_start++;
+ if (line_cur_end[-1] == '\"') {
+ line_cur_end--;
+ *line_cur_end = '\0';
+ }
+ memcpy(current_dirtree[current_depth],copy_start,line_cur_end-copy_start+1);
+ stop_blanking = 1; // don't clear blank fields in the future
}
else {
- // Blank this particular field, because we don't want old
- // subdirectories hanging around
- if (!stop_blanking)
- *(current_dirtree[current_depth]) = '\0';
+ // Blank this particular field, because we don't want old
+ // subdirectories hanging around
+ if (!stop_blanking)
+ *(current_dirtree[current_depth]) = '\0';
}
current_depth--;
if (line_cur >= line_begin)
- *line_cur = '\0'; // end the processing at the comma
+ *line_cur = '\0'; // end the processing at the comma
line_cur_end = line_cur;
}
@@ -441,73 +441,73 @@
strncpy(fullpath+len,current_dirtree[i],PATH_MAX-len);
len = strlen(fullpath);
if (fullpath[len-1] != '/' && len+1 < PATH_MAX) {
- fullpath[len] = '/'; // append a slash, if need be
- fullpath[len+1] = '\0';
+ fullpath[len] = '/'; // append a slash, if need be
+ fullpath[len+1] = '\0';
}
}
// Create the directory
if (strlen(fullpath) < PATH_MAX) {
if (mkdir(fullpath,mask) < 0) {
- // There was some kind of error, figure out what happened.
- // Be a little more verbose than the standard library errors.
- if (errno == EEXIST) {
- fprintf(stderr,"Warning: %s already exists, continuing.\n",fullpath);
- }
- else if (errno == ENAMETOOLONG) {
- fprintf(stderr,"Error: the directory name:\n %s\nwas too long.\n",fullpath);
- exit(EXIT_FAILURE);
- }
- else if (errno == ENOENT) {
- fprintf(stderr,"Error: One of the upper-level directories in:\n %s\ndoesn't exist. Check the syntax of your configuration file.\n",fullpath);
- exit(EXIT_FAILURE);
- }
- else if (errno == ENOSPC) {
- fprintf(stderr,"Error: the device has no room available.\n");
- exit(EXIT_FAILURE);
- }
- else {
- // Fall back on the standard library for the remaining error
- // handling
- fprintf(stderr,"Error: couldn't make directory %s:\nDo you have write permission for this location?\nDo you need to be root/administrator?\n",fullpath);
- error(EXIT_FAILURE,errno,"error");
- }
+ // There was some kind of error, figure out what happened.
+ // Be a little more verbose than the standard library errors.
+ if (errno == EEXIST) {
+ fprintf(stderr,"Warning: %s already exists, continuing.\n",fullpath);
+ }
+ else if (errno == ENAMETOOLONG) {
+ fprintf(stderr,"Error: the directory name:\n %s\nwas too long.\n",fullpath);
+ exit(EXIT_FAILURE);
+ }
+ else if (errno == ENOENT) {
+ fprintf(stderr,"Error: One of the upper-level directories in:\n %s\ndoesn't exist. Check the syntax of your configuration file.\n",fullpath);
+ exit(EXIT_FAILURE);
+ }
+ else if (errno == ENOSPC) {
+ fprintf(stderr,"Error: the device has no room available.\n");
+ exit(EXIT_FAILURE);
+ }
+ else {
+ // Fall back on the standard library for the remaining error
+ // handling
+ fprintf(stderr,"Error: couldn't make directory %s:\nDo you have write permission for this location?\nDo you need to be root/administrator?\n",fullpath);
+ error(EXIT_FAILURE,errno,"error");
+ }
}
else {
- fsync(fileno(stderr));
- fprintf(stdout,"Creating %s\n",fullpath);
- fsync(fileno(stdout));
+ fsync(fileno(stderr));
+ fprintf(stdout,"Creating %s\n",fullpath);
+ fsync(fileno(stdout));
- // Append the name to the user_menu_entries file
- // First we split off the last item in fullpath
- line_begin = fullpath;
- len = strlen(line_begin);
- line_begin[len-1] = '\0'; // replace terminal '/' with \0
- line_cur = line_begin + len-1;
- while (line_cur > line_begin && *line_cur != '/')
- line_cur--;
- if (line_cur > line_begin) { // as long as not making in the root directory...a bad idea anyway!
- *line_cur = '\0'; // Split into two strings
- }
- else {
- line_begin = "/";
- }
- line_cur++; // line_cur now points to beginning of newest directory
- strncpy(buf,line_begin,PATH_MAX); // we don't need buf anymore
- buf[strlen(buf)] = '/'; // append directory separator
- len = strlen(buf);
- strncpy(buf+len,USER_MENU_ENTRIES_FILENAME,PATH_MAX-len-strlen(USER_MENU_ENTRIES_FILENAME));
- // Now do the appending
- fpue = fopen(buf,"a");
- if (!fpue) {
- fprintf(stderr,"Error: can't open file %s for writing.\n",buf);
- exit(EXIT_FAILURE);
- }
- len = fprintf(fpue,"%s\n",line_cur);
- if (len != strlen(line_cur)+1) {
- error(EXIT_FAILURE,errno,"Error writing %s to file %s.\n",line_cur,buf);
- }
- fclose(fpue);
+ // Append the name to the user_menu_entries file
+ // First we split off the last item in fullpath
+ line_begin = fullpath;
+ len = strlen(line_begin);
+ line_begin[len-1] = '\0'; // replace terminal '/' with \0
+ line_cur = line_begin + len-1;
+ while (line_cur > line_begin && *line_cur != '/')
+ line_cur--;
+ if (line_cur > line_begin) { // as long as not making in the root directory...a bad idea anyway!
+ *line_cur = '\0'; // Split into two strings
+ }
+ else {
+ line_begin = "/";
+ }
+ line_cur++; // line_cur now points to beginning of newest directory
+ strncpy(buf,line_begin,PATH_MAX); // we don't need buf anymore
+ buf[strlen(buf)] = '/'; // append directory separator
+ len = strlen(buf);
+ strncpy(buf+len,USER_MENU_ENTRIES_FILENAME,PATH_MAX-len-strlen(USER_MENU_ENTRIES_FILENAME));
+ // Now do the appending
+ fpue = fopen(buf,"a");
+ if (!fpue) {
+ fprintf(stderr,"Error: can't open file %s for writing.\n",buf);
+ exit(EXIT_FAILURE);
+ }
+ len = fprintf(fpue,"%s\n",line_cur);
+ if (len != strlen(line_cur)+1) {
+ error(EXIT_FAILURE,errno,"Error writing %s to file %s.\n",line_cur,buf);
+ }
+ fclose(fpue);
}
}
else {
@@ -538,19 +538,19 @@
n_dirs = directory_crawl(path);
success = 0; // This will change to 1 if we find a directory of the
- // right level
+ // right level
for (i = 0; i < n_dirs; i++) {
if (directory_level[i] == level) {
// Create a blank highscores file in this directory
strncpy(buf,directory[i],PATH_MAX);
strncat(buf,HIGHSCORE_FILENAME,PATH_MAX-strlen(buf)-1);
if (strlen(buf) >= PATH_MAX-1) {
- fprintf(stderr,"confighighscores: pathname %s truncated, exiting.\n",buf);
- exit(EXIT_FAILURE);
+ fprintf(stderr,"confighighscores: pathname %s truncated, exiting.\n",buf);
+ exit(EXIT_FAILURE);
}
fp = fopen(buf,"w");
if (!fp)
- error(EXIT_FAILURE,errno,"confighighscores: file:\n %s",buf);
+ error(EXIT_FAILURE,errno,"confighighscores: file:\n %s",buf);
// That creates a blank file, which is all we have to do
fclose(fp);
success = 1;
@@ -597,7 +597,7 @@
fclose(fp);
fp = fopen(buf,"w");
if (!fp)
- error(EXIT_FAILURE,errno,"clearhighscores: file:\n %s",buf);
+ error(EXIT_FAILURE,errno,"clearhighscores: file:\n %s",buf);
// That creates a blank file, which is all we have to do
fclose(fp);
}
@@ -664,30 +664,30 @@
// Skip over white space, and especially blank lines
line_begin = eatwhite(buf);
if (strlen(line_begin) == 0)
- continue;
+ continue;
// Create the full path & filename of the user's log.csv file
strncpy(buf2,directory[i],PATH_MAX);
strncat(buf2,line_begin,PATH_MAX-strlen(buf2)-1);
strncat(buf2,"/log.csv",PATH_MAX-strlen(buf2)-1);
fplogread = fopen(buf2,"r");
if (fplogread) {
- // Copy the relevant lines from the user's log.csv file to the
- // consolidated log file. Make sure only one copy of the
- // column names is written.
- while(fgets(buf3, PATH_MAX, fplogread)) {
- line_begin = eatwhite(buf3);
- if (strlen(line_begin) == 0)
- continue;
- if (strncmp(line_begin,"\"User",5) == 0) {
- if (!column_names_written) {
- fprintf(fplogwrite,"%s\n",line_begin);
- column_names_written = 1;
- }
- } else {
- fprintf(fplogwrite,"%s\n",line_begin);
- }
- }
- fclose(fplogread);
+ // Copy the relevant lines from the user's log.csv file to the
+ // consolidated log file. Make sure only one copy of the
+ // column names is written.
+ while(fgets(buf3, PATH_MAX, fplogread)) {
+ line_begin = eatwhite(buf3);
+ if (strlen(line_begin) == 0)
+ continue;
+ if (strncmp(line_begin,"\"User",5) == 0) {
+ if (!column_names_written) {
+ fprintf(fplogwrite,"%s\n",line_begin);
+ column_names_written = 1;
+ }
+ } else {
+ fprintf(fplogwrite,"%s\n",line_begin);
+ }
+ }
+ fclose(fplogread);
}
}
fclose(fpusersread);
@@ -725,7 +725,7 @@
// We found such a file, delete it
fclose(fp);
if (remove(buf) < 0)
- error(EXIT_FAILURE,errno,"%s: file:\n %s",invoke_name,buf);
+ error(EXIT_FAILURE,errno,"%s: file:\n %s",invoke_name,buf);
}
}
@@ -758,22 +758,22 @@
// Find the "=" sign
tmpvalue = strchr(param_begin+strlen(varname), '=');
if (tmpvalue == NULL)
- continue;
+ continue;
// Skip over the "=" sign
tmpvalue++;
// Skip whitespace
while (isspace(*tmpvalue))
- tmpvalue++;
+ tmpvalue++;
// Eliminate any whitespace at end
param_begin = tmpvalue;
tmpvalue = param_begin + strlen(param_begin) - 1;
while (tmpvalue > param_begin && isspace(*tmpvalue)) {
- *tmpvalue = '\0';
- tmpvalue--;
+ *tmpvalue = '\0';
+ tmpvalue--;
}
// Abort if empty
if (strlen(param_begin) == 0)
- continue;
+ continue;
// Successful, copy the result
*value = strdup(param_begin);
return 1;
@@ -829,45 +829,45 @@
// Just parse directories of the most recently-added level
// (we've already done the work for previous levels)
if (directory_level[i] == current_level) {
- // Read the user_menu_entries file, if it exists
- // Note that previous items already have "/" appended, no need
- // to worry about that here.
- strncpy(fullpath,directory[i],PATH_MAX);
- strncat(fullpath,USER_MENU_ENTRIES_FILENAME,PATH_MAX-strlen(fullpath)-1);
- fp = fopen(fullpath,"r");
- if (fp != NULL) {
- // We found the user_menu_entries file, read it and add directories
- while (fgets (buf, PATH_MAX, fp)) {
- if (current_length >= MAX_USERS) {
- fprintf(stderr,"Error: maximum number of users exceeded.");
- exit(EXIT_FAILURE);
- }
- // Skip over leading & trailing white space, and
- // especially blank lines
- line_begin = eatwhite(buf);
- if (strlen(line_begin) == 0)
- continue;
+ // Read the user_menu_entries file, if it exists
+ // Note that previous items already have "/" appended, no need
+ // to worry about that here.
+ strncpy(fullpath,directory[i],PATH_MAX);
+ strncat(fullpath,USER_MENU_ENTRIES_FILENAME,PATH_MAX-strlen(fullpath)-1);
+ fp = fopen(fullpath,"r");
+ if (fp != NULL) {
+ // We found the user_menu_entries file, read it and add directories
+ while (fgets (buf, PATH_MAX, fp)) {
+ if (current_length >= MAX_USERS) {
+ fprintf(stderr,"Error: maximum number of users exceeded.");
+ exit(EXIT_FAILURE);
+ }
+ // Skip over leading & trailing white space, and
+ // especially blank lines
+ line_begin = eatwhite(buf);
+ if (strlen(line_begin) == 0)
+ continue;
- directory[current_length] = (char *) malloc((strlen(directory[i])+strlen(line_begin)+2)*sizeof(char));
- if (directory[current_length] == NULL) {
- fprintf(stderr,"Memory allocation error in directory_crawl.\n");
- exit(EXIT_FAILURE);
- }
- // Append each new directory to the list
- strcpy(directory[current_length],directory[i]);
- strcat(directory[current_length],line_begin);
- strcat(directory[current_length],"/");
- directory_level[current_length] = current_level+1;
- // Check to make sure it's valid
- dir = opendir(directory[current_length]);
- if (dir == NULL)
- error(EXIT_FAILURE,errno,"directory:\n %s",directory[current_length]);
- closedir(dir);
- current_length++;
- }
- isdone = 0; // We know we need to check the subdirectories
- fclose(fp);
- } // end of: if (fp != NULL)
+ directory[current_length] = (char *) malloc((strlen(directory[i])+strlen(line_begin)+2)*sizeof(char));
+ if (directory[current_length] == NULL) {
+ fprintf(stderr,"Memory allocation error in directory_crawl.\n");
+ exit(EXIT_FAILURE);
+ }
+ // Append each new directory to the list
+ strcpy(directory[current_length],directory[i]);
+ strcat(directory[current_length],line_begin);
+ strcat(directory[current_length],"/");
+ directory_level[current_length] = current_level+1;
+ // Check to make sure it's valid
+ dir = opendir(directory[current_length]);
+ if (dir == NULL)
+ error(EXIT_FAILURE,errno,"directory:\n %s",directory[current_length]);
+ closedir(dir);
+ current_length++;
+ }
+ isdone = 0; // We know we need to check the subdirectories
+ fclose(fp);
+ } // end of: if (fp != NULL)
} // end of: if (directory_level[i] == current_level)
} // end of: loop over previous directories
current_level++; // We're all done parsing this level, move on
Modified: tuxmath/trunk/src/tuxmathrc.rc
===================================================================
--- tuxmath/trunk/src/tuxmathrc.rc 2008-08-05 20:35:28 UTC (rev 588)
+++ tuxmath/trunk/src/tuxmathrc.rc 2008-08-06 02:55:05 UTC (rev 589)
@@ -1,2 +1,2 @@
#define TUXMATH_ICON 104
-TUXMATH_ICON ICON "../data/images/tuxmath.ico"
+TUXMATH_ICON ICON "../data/images/tuxmath.ico"
More information about the Tux4kids-commits
mailing list