diff -uNr moodle.orig/lib/questionlib.php moodle/lib/questionlib.php
--- moodle.orig/lib/questionlib.php	2006-11-16 02:14:05.000000000 +0000
+++ moodle/lib/questionlib.php	2007-03-01 14:21:46.000000000 +0000
@@ -1059,7 +1059,14 @@
     }
 
     // Ensure that the grade does not go down
-    $state->grade = max($state->grade, $state->last_graded->grade);
+    //
+    // This is specific to penalties/timelimit/closing time, so it should not run always!
+    if ($cmoptions->penaltyscheme or $cmoptions->timelimit or $cmoptions->timeclose) {
+       // The structures are initialized to zero, so on the first time it will reset any negative value to zero.
+       if ($state->last_graded->seq_number != 0) {
+          $state->grade = max($state->grade, $state->last_graded->grade);
+       }
+    }
 }
 
 /**
diff -uNr moodle.orig/mod/quiz/attempt.php moodle/mod/quiz/attempt.php
--- moodle.orig/mod/quiz/attempt.php	2006-11-27 02:15:23.000000000 +0000
+++ moodle/mod/quiz/attempt.php	2007-03-01 13:53:32.000000000 +0000
@@ -333,6 +333,8 @@
             // ... and save the new states
             save_question_session($questions[$i], $states[$i]);
         }
+        // make sure sumgrades are non-negative
+        $attempt->sumgrades = max($attempt->sumgrades, 0.0); 
     }
 
 
@@ -371,6 +373,8 @@
             question_process_responses($questions[$i], $states[$i], $actions[$i], $quiz, $attempt);
             save_question_session($questions[$i], $states[$i]);
         }
+        // make sure sumgrades are non-negative
+        $attempt->sumgrades = max($attempt->sumgrades, 0.0); 
 
         $attempt->timemodified = $timestamp;
 
@@ -417,6 +421,8 @@
                 question_process_responses($question, $closestates[$key], $action, $quiz, $attempt);
                             save_question_session($question, $closestates[$key]);
             }
+            // make sure sumgrades are non-negative
+            $attempt->sumgrades = max($attempt->sumgrades, 0.0); 
         }
         add_to_log($course->id, 'quiz', 'close attempt',
                            "review.php?attempt=$attempt->id",
diff -uNr moodle.orig/question/type/multianswer/questiontype.php moodle/question/type/multianswer/questiontype.php
--- moodle.orig/question/type/multianswer/questiontype.php	2006-11-27 02:15:24.000000000 +0000
+++ moodle/question/type/multianswer/questiontype.php	2007-02-22 04:57:57.000000000 +0000
@@ -343,7 +343,7 @@
             $state->raw_grade += $teststate->raw_grade;
         }
         $state->raw_grade /= $question->defaultgrade;
-        $state->raw_grade = min(max((float) $state->raw_grade, 0.0), 1.0)
+        $state->raw_grade = min(max((float) $state->raw_grade, -1.0), 1.0)
          * $question->maxgrade;
 
         if (empty($state->raw_grade)) {
diff -uNr moodle.orig/question/type/multichoice/questiontype.php moodle/question/type/multichoice/questiontype.php
--- moodle.orig/question/type/multichoice/questiontype.php	2006-06-13 03:08:55.000000000 +0100
+++ moodle/question/type/multichoice/questiontype.php	2007-02-22 04:58:38.000000000 +0000
@@ -347,7 +347,7 @@
 
         // Make sure we don't assign negative or too high marks
         $state->raw_grade = min(max((float) $state->raw_grade,
-                            0.0), 1.0) * $question->maxgrade;
+                            -1.0), 1.0) * $question->maxgrade;
         // Apply the penalty for this attempt
         $state->penalty = $question->penalty * $question->maxgrade;
 
