GC7R0TA-Rechenzentrum/hrm/functions.php

889 lines
42 KiB
PHP
Raw Permalink Normal View History

2024-05-04 07:40:23 +00:00
<?
define("PROGRAM_IS_CORRECT", "PROGRAM_IS_CORRECT");
define("PROGRAM_TAKES_TOO_MANY_EFFECTIVE_STEPS", "PROGRAM_TAKES_TOO_MANY_EFFECTIVE_STEPS");
define("PROGRAM_IS_WRONG", "PROGRAM_IS_WRONG");
define("SUCCESS", "SUCCESS");
define("FAIL", "FAIL");
error_reporting(E_ERROR | E_PARSE);
/* Initialize the program
* Count the effective program lines (without empty/labels)
*/
function init_program($arr_asm, $level, $passcode){
$back_to_editor = "<br><br>Gehe wieder zum Editor-Fenster <a href=editor.php?level=$level&passcode=$passcode>zurück</a>, um deinen Programm-Code zu verbessern. Viel Glück!";
$program = array();
// $inbox = array_reverse($inbox);
// echo("<h3>Parse Program</h3>");
// echo("<div class=frame>");
$instruction_counter = 0;
$program_line_counter = 0;
$comments_counter = 0;
$labels_counter = 0;
foreach($arr_asm as $line){
$line = trim($line);
$line = preg_replace('!\s+!', ' ', $line); // Replacing multiple spaces with a single space
@list($cmd, $param) = explode(" ", $line);
// echo($program_line_counter + 1 . ": cmd = \"$cmd\", param = \"$param\"<br>\n");
$program_line_counter = $program_line_counter + 1;
switch($cmd){
case "inbox":
case "outbox":
case "jump":
case "jumpz":
case "jumpn":
case "copyto":
case "copyfrom":
case "add":
case "sub":
case "bumpup":
case "bumpdn":
array_push($program, ['cmd' => $cmd, 'param' => $param, 'instruction' => $instruction_counter]);
$instruction_counter = $instruction_counter + 1;
break;
default:
if(substr($cmd, 0, 2) == "--"){ //comment
$comments_counter = $comments_counter + 1;
array_push($program, ['cmd' => "comment", 'comment' => $line]);
}
else if(strlen($cmd) == 0){ //empty line
//nothing to do
}
else if(substr($cmd, -1, 1) == ":"){ //label, cutting off appending character (":")
$label = substr(trim("$cmd"), 0, -1);
// echo "Label: $label<br>";
if(!preg_match("/^[a-zA-Z]+$/", $label)){ //found invalid character in label
// echo("Parse error on line $program_line_counter: $line!\n");
$program_summary = "<font color=darkred>Fehler in Programm-Code, Zeile $program_line_counter: $line! $back_to_editor</font><br>";
array_push($program, ['cmd' => $cmd, 'param' => $param, 'instruction' => $instruction_counter]);
return array(0, $program, $program_summary, $instruction_counter, $labels_counter, ($comments_counter - 1));
}
$labels_counter = $labels_counter + 1;
array_push($program, ['cmd' => "label", 'label' => "$label"]);
}
else{ //error
// echo("Parse error on line $program_line_counter: $line!\n");
$program_summary = "<font color=darkred>Fehler in Programm-Code, Zeile $program_line_counter: $line! $back_to_editor</font><br>";
array_push($program, ['cmd' => $cmd, 'param' => $param, 'instruction' => $instruction_counter]);
return array(0, $program, $program_summary, $instruction_counter, $labels_counter, ($comments_counter - 1));
}
break;
}
}
$program_summary = "Total $program_line_counter Zeile(n) mit $instruction_counter Instruktion(en), $labels_counter Ziel(en) und $comments_counter Kommentar(en).";
return array(true, $program, $program_summary, $instruction_counter, $labels_counter, ($comments_counter - 1));
}
/* Tests the given program
*
*/
function test_program($program, $inbox, $expected_outbox, $hand, $data_registers, $max_allowed_steps){
// echo("$max_allowed_steps");
$outbox = array();
// $step_boxes = array();
$instructions_line_counter = 0;
$used_steps = 0;
$hand = "";
// print_r($program);
// echo("max_allowed_steps: $max_allowed_steps");
while($instructions_line_counter < count($program)){
// echo("($instructions_line_counter < ".count($program).") and (".count($outbox)." < ".count($inbox).")<br>");
$used_steps++;
/* Check if output is still correct
* todo: only run after a OUTPUT command
*/
// echo("Current Inbox: [");
// foreach($inbox as $element){ echo("$element, "); }; echo("]<br>");
// echo("Hand: $hand, Data registers: [");
// foreach($data_registers as $element){ echo("$element, "); }
// echo("]<br>");
// echo("Current Outbox: [");
// foreach($outbox as $element){ echo("$element, "); } echo("] , Expected Outbox: [");
// foreach($expected_outbox as $element){ echo("$element, "); }; echo("]<br>");
for($i = count($outbox) - 1; $i >= 0; $i--){
// echo($outbox[$i] . " <=> " . $expected_outbox[count($expected_outbox) - count($outbox) + $i] . " | ");
if($outbox[$i] != ($expected_outbox[count($expected_outbox)- count($outbox) + $i])){ //mismatch, outbox is wrong
// echo("<pre>Program is incorrect</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
}
// echo("<br><hr>");
if(count($outbox) == count($expected_outbox)){ //outbox is full, program completed successfully
// echo("Program is correct<br>");
return [PROGRAM_IS_CORRECT, $used_steps - 1];
}
// array_push($step_boxes, $instructions_line_counter);
if($used_steps > $max_allowed_steps){
// echo("<pre>Maximum steps reached (" . ($used_steps -1 ) . "/$max_allowed_steps)</pre>");
return [PROGRAM_TAKES_TOO_MANY_EFFECTIVE_STEPS, $used_steps - 1];
}
$line = $program[$instructions_line_counter];
$cmd = $line['cmd'];
$param = $line['param'];
$label = $line['label'];
$comment = $line['comment'];
// echo("$used_steps: $cmd $param$label$comment<br>");
//--------------------------------------------------------------------------
switch($cmd){
case "inbox":
if(count($inbox) > 0){ //Check: Inbox is not empty
$hand = array_pop($inbox);
}
else{
// echo("<pre>inbox: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "outbox":
if($hand !== ""){ //Check: Hand is not empty
array_unshift($outbox, $hand);
$hand = "";
}
else{
// echo("<pre>outbox: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "jump":
$lable_is_on_line = "";
//find matching lable
foreach($program as $line_no => $line2){
if($line2['label'] == $param){
$lable_is_on_line = $line_no;
}
}
if($lable_is_on_line !== ""){ //Check: lable got found
$instructions_line_counter = $lable_is_on_line - 1; //set program counter to line containing the LABEL
}
else{
// echo("<pre>: jumpcommand is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "jumpz":
if($hand !== ""){ //Check: Hand is not empty;
$lable_is_on_line = "";
//find matching lable
foreach($program as $line_no => $line2){
if($line2['label'] == $param){
$lable_is_on_line = $line_no;
}
}
if($lable_is_on_line !== ""){ //Check: lable got found
if($hand == 0){ //hand is 0
$instructions_line_counter = $lable_is_on_line - 1; //set program counter to line containing the LABEL
}
else{ //continue on next line
//nothing to do
}
}
else{
// echo("<pre>jumpz: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
}
else{
// echo("<pre>jumpz: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "jumpn":
if($hand !== ""){ //Check: Hand is not empty;
$lable_is_on_line = "";
//find matching lable
foreach($program as $line_no => $line2){
if($line2['label'] == $param){
$lable_is_on_line = $line_no;
}
}
if($lable_is_on_line !== ""){ //Check: lable got found
if($hand < 0){ //hand is < 0
$instructions_line_counter = $lable_is_on_line - 1; //set program counter to line containing the LABEL
}
else{ //continue on next line
//nothing to do
}
}
else{
// echo("<pre>jumpn: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
}
else{
// echo("<pre>command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "copyto":
if(($hand !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Hand is not empty;
$data_registers[$param] = $hand;
}
else{
// echo("<pre>copyto: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "copyfrom":
if(($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Register is not empty
$hand = $data_registers[$param];
}
else{
// echo("<pre>copyfrom: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "add":
if(($hand !== "") and ($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Hand and data register are not empty
$hand = $hand + $data_registers[$param];
}
else{
// echo("<pre>add: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "sub":
if(($hand !== "") and ($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Hand and data register are not empty
$hand = $hand - $data_registers[$param];
}
else{
// echo("<pre>: subcommand is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "bumpup":
if(($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Register is not empty
$data_registers[$param] = $data_registers[$param] + 1;
$hand = $data_registers[$param];
}
else{
// echo("<pre>bumpup: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "bumpdn":
if(($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Register is not empty
$data_registers[$param] = $data_registers[$param] - 1;
$hand = $data_registers[$param];
}
else{
// echo("<pre>bumpdn: command is NOT valid with current registers/boxes</pre>");
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
break;
//--------------------------------------------------------------------------
case "label": //label
$used_steps--; //A label doesn't count as a step real step, so decrement it again
break;
case "comment": //comment
$used_steps--; //A comment doesn't count as a step real step, so decrement it again
break;
//--------------------------------------------------------------------------
default: //unknown command
return [PROGRAM_IS_WRONG, $used_steps - 1];
}
$instructions_line_counter++;
}
}
function test_program_with_iterations($program, $level_configuration){
$average_used_steps = 0;
$max_used_steps = 0;
$test_iteration = 0;
while($test_iteration < $level_configuration['test_runs']){ // run many iterations of the users program to check if it works under all conditions
$test_iteration++;
$inbox = $level_configuration["inbox_preparation_function"]($level_configuration);
$expected_outbox = $level_configuration["reference_program"]($inbox, $level_configuration);
list($program_quality, $used_steps, $step_prints) = test_program(
$program,
$inbox,
$expected_outbox,
$level_configuration['hand'],
$level_configuration['data_registers'],
$level_configuration['max_allowed_steps']
);
// echo("<pre>$used_steps</pre>");
$average_used_steps = $average_used_steps + $used_steps;
If($used_steps > $max_used_steps) {
$max_used_steps = $used_steps;
}
if($program_quality != PROGRAM_IS_CORRECT){
return [FAIL, $inbox, $expected_outbox, round($average_used_steps / $test_iteration), $max_used_steps, $program_quality];
}
}
return [SUCCESS, $inbox, $expected_outbox, round($average_used_steps / $test_iteration), $max_used_steps];
}
function outbox_contains_no_errors($inbox, $expected_outbox, $outbox, $hand, $data_registers,$used_steps, $inbox_size, $outbox_size, $level, $passcode){
$back_to_editor = "<br><br>Gehe wieder zum Editor-Fenster <a href=editor.php?level=$level&passcode=$passcode>zurück</a>, um deinen Programm-Code zu verbessern. Viel Glück!";
for($i = count($outbox) - 1; $i >= 0; $i--){
// echo($outbox[$i] . " != " . $expected_outbox[count($expected_outbox)- count($outbox) + $i] . "<br>");
if($outbox[$i] != $expected_outbox[count($expected_outbox)- count($outbox) + $i]){ //mismatch, outbox is wrong
print_step($hand, $data_registers, $inbox, $outbox, "Fehler nach Schritt ". ($used_steps - 1) .": Die Outbox enthält ein falsches Element
(Erwartet: ". box($expected_outbox[count($expected_outbox) - count($outbox)]) . ", Erhalten: ". box($outbox[0]) . ")! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
// echo("Die Outbox enthält ein falsches Element<br>");
return false;
}
}
return true;
}
function generate_program_steps($program, $inbox, $expected_outbox, $hand, $data_registers, $max_allowed_steps, $average_effective_steps, $maximum_allowed_instruction, $instruction_counter, $inbox_size, $outbox_size, $reward, $show_outbox_as_coordinate, $level, $passcode){
$back_to_editor = "<br>Gehe wieder zum Editor-Fenster <a href=editor.php?level=$level&passcode=$passcode>zurück</a>, um deinen Programm-Code zu verbessern. Viel Glück!";
$outbox = array();
$step_boxes = array();
$instructions_line_counter = 0;
$visual_step = 0; //includes lables (since the target is also shown as a step point). It gets automatically incremented in print_step()
$used_steps = 0; //exclusive target since this is no real step
$hand = "";
while($instructions_line_counter < count($program)){
// echo("Visual Step: $visual_step: ($instructions_line_counter < ".count($program).") and (".count($outbox)." < ".count($inbox).")<br>");
$used_steps++;
if(outbox_contains_no_errors($inbox, $expected_outbox, $outbox, $hand, $data_registers, $used_steps, $inbox_size, $outbox_size, $level, $passcode) != true){
array_push($step_boxes, -4);
return $step_boxes;
}
if(count($outbox) == count($expected_outbox)){ //outbox is full, program completed successfully
goto PROGRAM_END;
}
// echo($instructions_line_counter);
array_push($step_boxes, $instructions_line_counter);
if($used_steps > $max_allowed_steps){
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: Fehler: Maximale Anzahl Schritte ($max_allowed_steps) erreicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
$line = $program[$instructions_line_counter];
$cmd = $line['cmd'];
$param = $line['param'];
$label = $line['label'];
$comment = $line['comment'];
//--------------------------------------------------------------------------
switch($cmd){
case "inbox":
if(count($inbox) > 0){ //Check: Inbox is not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$hand = array_pop($inbox);
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span><br>
Fehler: Inbox ist leer! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "outbox":
if($hand !== ""){ //Check: Hand is not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
array_unshift($outbox, $hand);
$hand = "";
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span><br>
Fehler: Hand ist leer! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "jump":
$lable_is_on_line = "";
//find matching lable
foreach($program as $line_no => $line2){
if($line2['label'] == $param){
$lable_is_on_line = $line_no;
}
}
if($lable_is_on_line !== ""){ //Check: lable got found
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$instructions_line_counter = $lable_is_on_line - 1; //set program counter to line containing the LABEL
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Ziel existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "jumpz":
if($hand !== ""){ //Check: Hand is not empty;
$lable_is_on_line = "";
//find matching lable
foreach($program as $line_no => $line2){
if($line2['label'] == $param){
$lable_is_on_line = $line_no;
}
}
if($lable_is_on_line !== ""){ //Check: lable got found
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
//
if($hand == 0){ //hand is 0
$instructions_line_counter = $lable_is_on_line - 1; //set program counter to line containing the LABEL
}
else{ //continue on next line
//nothing to do
}
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Ziel existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span><br>
Fehler: Hand ist leer! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "jumpn":
if($hand !== ""){ //Check: Hand is not empty;
$lable_is_on_line = "";
//find matching lable
foreach($program as $line_no => $line2){
if($line2['label'] == $param){
$lable_is_on_line = $line_no;
}
}
if($lable_is_on_line !== ""){ //Check: lable got found
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
//
if($hand < 0){ //hand is < 0
$instructions_line_counter = $lable_is_on_line - 1; //set program counter to line containing the LABEL
}
else{ //continue on next line
//nothing to do
}
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Ziel existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span><br>
Fehler: Hand ist leer! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "copyto":
if(($hand !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Hand is not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$data_registers[$param] = $hand;
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Hand ist leer oder das Daten-Register existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "copyfrom":
if(($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Register is not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$hand = $data_registers[$param];
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Data Register ist leer oder existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "add":
if(($hand !== "") and ($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Hand and data register are not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$hand = $hand + $data_registers[$param];
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Hand oder Data Register ist leer oder das Daten-Register existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "sub":
if(($hand !== "") and ($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Hand and data register are not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$hand = $hand - $data_registers[$param];
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Hand oder Data Register ist leer oder das Daten-Register existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "bumpup":
if(($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Register is not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$data_registers[$param] = $data_registers[$param] + 1;
$hand = $data_registers[$param];
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Data Register ist leer oder existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "bumpdn":
if(($data_registers[$param] !== "") and (is_numeric($param)) and ($param >= 0) and ($param < count($data_registers))){ //Check: Register is not empty
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$data_registers[$param] = $data_registers[$param] - 1;
$hand = $data_registers[$param];
}
else{ //command is NOT valid with current registers/boxes
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Data Register ist leer oder existiert nicht! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
break;
//--------------------------------------------------------------------------
case "label": //label
print_step($hand, $data_registers, $inbox, $outbox, "Ziel <span class=\"jumpdst cmd\">$label</span>", "black", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
$used_steps--; //A label doesn't count as a step real step, so decrement it again
break;
case "comment": //comment
array_pop($step_boxes); //remove step again from steps array, a comment is no instruction
$used_steps--; //A comment doesn't count as a step real step, so decrement it again
break;
//--------------------------------------------------------------------------
default: //unknown command
print_step($hand, $data_registers, $inbox, $outbox, "Schritt $used_steps: <span class=\"$cmd cmd\">$cmd</span> <span class=\"$cmd cmd\">$param</span><br>
Fehler: Unbekannter Befehl auf Zeile $instructions_line_counter: \"$cmd $param$label$comment\"! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
break;
}
$instructions_line_counter++;
}
/* Reached last line of program.
* Is the outbox as expected?
*/
if(count($outbox) != count($expected_outbox)){
array_push($step_boxes, -2);
print_step($hand, $data_registers, $inbox, $outbox, "Letzte Zeile des Programms erreicht, aber die Outbox ist nicht korrekt! $back_to_editor", "DarkRed", $inbox_size, $outbox_size, $show_outbox_as_coordinate);
// echo("End of program reached! but outbox incomplete<br>");
return $step_boxes;
}
PROGRAM_END:
if(($average_effective_steps <= $max_allowed_steps) and ($instruction_counter <= $maximum_allowed_instruction)){ //ok, meet one of both requirements
$text = "Programm erfolgreich abgearbeitet (Du hast " . ($used_steps - 1) . " Schritte benötigt).<br><br>$reward";
$color = "green";
}
else if($instruction_counter > $maximum_allowed_instruction){ //fail, used too many instructions
$text = "Programm erfolgreich abgearbeitet, aber Du hast zu viele Instruktionen ($instruction_counter) verwendet. Programm-Speicher ist sehr kostbar, daher muss die Programm-Grösse auf dem Minimum gehalten werden! Versuche mit $maximum_allowed_instruction Instruktionen auszukommen! $back_to_editor";
$color = "OrangeRed";
}
else{//fail, used too many steps
$text = "Programm erfolgreich abgearbeitet, aber Du hast im Durchschnitt zu viele Schritte ($average_effective_steps) benötigt. Je mehr Programm-Schritte ein Auftrag benötigt, desto mehr Zeit braucht das Programm. Und Zeit ist bekanntlich Geld. Versuche mit $max_allowed_steps Schritten auszukommen! $back_to_editor";
$color = "OrangeRed";
}
array_push($step_boxes, -3);
print_step($hand, $data_registers, $inbox, $outbox, $text, $color, $inbox_size, $outbox_size, $show_outbox_as_coordinate);
return $step_boxes;
}
/* This command is run before the execution of the instruction.
* It shows the situation the instruction is applied to!
*/
function print_step($hand, $data_registers, $inbox, $outbox, $text, $color, $inbox_size, $outbox_size, $show_outbox_as_coordinate){
global $visual_step;
$visual_step++;
?>
<!-- <? echo("$visual_step"); ?> -->
<div style="margin-bottom: 10px;"></div>
<div class=step_boxes id="step_<? echo($visual_step); ?>_box">
<div class=hrmcode style="margin-left: 20px; margin-top: 15px; z-index:10;"><font color="<? echo($color); ?>"><? echo("$text"); ?></font></div>
<hr>
<?
print_inbox($inbox, $inbox_size);
echo("<hr>\n");
print_registers($hand, $data_registers);
echo("<hr>\n");
print_outbox($outbox, $outbox_size, $show_outbox_as_coordinate);
echo("\n");
?>
</div>
<?
}
function box($value){
return "<span class=\"inbox\">$value</span> ";
}
function print_box($value){
if($value !== ""){
echo("<div class=\"hrmcode box_float_left\">" . box($value) . "</div>");
}
else{
echo("<div class=\"empty_box\"></div>");
}
}
function print_registers($hand, $data_registers){
?>
<div style="margin-top: 20px; margin-left: 20px; height: 40px">
<div class="box_float_left">
<div class="box_float_left" style="margin-top: 0px">
<img src="images/hand.png" height=28px>
</div>
<?
print_box($hand);
?>
</div>
<div class="box_float_left">
<h3 style="margin-left: 30px; margin-top: 10px">Daten-Register:</h3>
</div>
<div class="box_float_left">
<?
$i = 0;
foreach($data_registers as $item){
?>
<div class="DataRegister">
<? print_box($item); ?><br>
<p><? echo($i);?></p>
</div>
<?
$i++;
}
?>
</div>
</div>
<div style="clear: both; margin-bottom: 30px;"></div>
<?
}
function print_inbox($inbox, $inbox_size){
$inbox_size = 8; //limit
?>
<div style="margin-top: 20px; margin-left: 20px; height: 70px">
<h3>Inbox =></h3>
<div style="clear: both;">
<?
if(count($inbox) <= $inbox_size){
for($i = 0; $i < ($inbox_size - count($inbox)); $i++){ //less boxes than space, show as empty
print_box("");
}
foreach($inbox as $item){
print_box($item);
}
}
else{ //too many elements in the inbox, only print first ones
echo("<div class=\"hrmcode box_float_left\">...</div>");
for($i = $inbox_size; $i > 0; $i--){
print_box($inbox[count($inbox) - $i]);
}
}
?>
</div>
<div style="clear: both; margin-bottom: 30px;"></div>
</div>
<?
}
function print_outbox($outbox, $outbox_size, $show_outbox_as_coordinate){
// $outbox_size = 8; //limit
?>
<div style="margin-left: 20px; height: 50px">
<h3>=> Outbox</h3>
<?
if($show_outbox_as_coordinate != true){ //normal
foreach($outbox as $item){
print_box($item);
}
for($i = 0; $i < ($outbox_size - count($outbox)); $i++){ //less boxes than space, show as empty
print_box("");
}
}
else{ //coordinate
$position = 0;
echo("<div class=\"hrmcode box_float_left\">N</div>");
foreach($outbox as $item){
print_box($item);
coordinate_formating($position);
$position++;
}
for($i = 0; $i < ($outbox_size - count($outbox)); $i++){ //less boxes than space, show as empty
print_box("");
coordinate_formating($position);
$position++;
}
}
?>
</div>
<div style="clear: both; margin-bottom: 25px;"></div>
<?
}
function coordinate_formating($position){
if(($position == 6)){ echo("<div style=\"clear: both;\"></div><div class=\"hrmcode box_float_left\">E</div>");}
elseif(($position == 1) or ($position == 9)){ echo("<div class=\"hrmcode box_float_left\">°</div>");}
else if(($position == 3) or ($position == 11)){ echo("<div class=\"hrmcode box_float_left\">,</div>");}
}
function cleanup_asm_array(&$value)
{
$value = trim($value);
if(substr($value, 0, 2) == "--"){ //comment
//nothing to do
}
else{ //all other commands/lables, change to upper case
$value = strtolower($value);
}
}
?>