889 lines
42 KiB
PHP
889 lines
42 KiB
PHP
<?
|
|
|
|
|
|
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);
|
|
}
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
?>
|