Skip to content

Instantly share code, notes, and snippets.

@lucablackwell
Created November 29, 2022 10:06
Show Gist options
  • Save lucablackwell/d5f37ff3ec3ae1446cf9f59cd1019d1d to your computer and use it in GitHub Desktop.
Save lucablackwell/d5f37ff3ec3ae1446cf9f59cd1019d1d to your computer and use it in GitHub Desktop.
the 'mastermind' function of https://github.com/lucablackwell/heroica, loosely based on the 1972 board game for 2.
<?php
function cyan($text) {
return "\e[1;36m$text\e[0m";
}
function red($text) {
return "\e[1;31m$text\e[0m";
}
function green($text) {
return "\e[1;32m$text\e[0m";
}
function yellow($text) {
return "\e[1;33m$text\e[0m";
}
function mastermind($limit, $attempt_max, $hard) {
echo cyan("You come across a door with an ancient mechanism.\nYou'll need to input the correct combination of 4 numbers to proceed.\n");
sleep(2);
echo cyan("You can only use the numbers from 0-" . $limit . ", including 0 itself.\n");
sleep(2);
echo cyan("Studying the mechanism, you see that you'll have " . $attempt_max . " attempts before the combination resets.\n");
sleep(2);
echo "Enter 4 numbers to input them into the mechanism.\n";
$beaten = false;
while (!$beaten) {
// For the remaining, add a random one to the combo
$combo = [];
$remaining = [];
for ($i = 0; $i <= $limit; $i++) {
$remaining[] = $i;
}
for ($i = 0; $i < 4; $i++) {
$rand = array_rand($remaining);
$combo[] = $rand;
unset($remaining[array_search($rand, $remaining)]);
}
$attempt_total = 0;
$input_arr = [];
$correct = 0;
while (($correct != 4 || implode($input_arr) != implode($combo)) && $attempt_total < $attempt_max) {
$attempt_total += 1;
echo '>';
$input = readline();
$sanitised = false;
while (!$sanitised) {
// If there are more or less than 4 characters
if (strlen($input) != 4) {
echo "The ancient mechanism only has 4 spaces.\n";
$input = readline();
// If there are letters
} elseif (preg_match('/[a-z]/', $input)) {
echo "Only numbers are usable to unlock this mechanism.\n";
$input = readline();
// If there are symbols
} elseif (preg_match('/[^\p{L}\d\s@]/u', $input)) {
echo "Only numbers are usable to unlock this mechanism.\n";
$input = readline();
// If there are only numbers
} elseif (preg_match('/[0-9]/', $input)) {
$low_enough = true;
foreach (str_split($input) as $num) {
if ($num > $limit) {
$low_enough = false;
}
}
// If any of the numbers are too high
if (!$low_enough) {
echo "The given numbers only go up to " . ($limit) . "!\n";
$input = readline();
}
// If there are duplicates
if (strlen(count_chars($input, 3)) != 4) {
echo "You are only given one of each number.\n";
$input = readline();
}
if ($low_enough && strlen(count_chars($input, 3)) == 4) {
$sanitised = true;
}
}
}
$input_arr = str_split($input);
$correct = 0;
$half = 0;
$wrong = 0;
if ($hard) {
for ($i = 0; $i < count($input_arr); $i++) {
// If at least right number in any place
if (in_array($input_arr[$i], $combo)) {
// If right place
if ($input_arr[$i] == $combo[$i]) {
$correct += 1;
} else {
$half += 1;
}
} else {
$wrong += 1;
}
}
echo " " . green($correct) . " " . yellow($half) . " " . red($wrong);
} else {
for ($i = 0; $i < count($input_arr); $i++) {
// If at least right number in any place
if (in_array($input_arr[$i], $combo)) {
// If right place
if ($input_arr[$i] == $combo[$i]) {
$correct += 1;
echo green($input_arr[$i]);
} else {
echo yellow($input_arr[$i]);
}
} else {
echo red($input_arr[$i]);
}
}
}
echo " Attempt $attempt_total";
// If all correct
if ($correct == 4 || implode($input_arr) == implode($combo)) {
echo cyan("\nDust falls as the ancient lock opens.");
sleep(2);
$beaten = true;
}
echo "\n";
}
if ($attempt_total == $attempt_max && ($correct != 4 || implode($input_arr) != implode($combo))) {
echo cyan("You took too many attempts, and the ancient lock reconfigured itself!\nTry again...\n");
}
}
}
// run mastermind with numbers 0-9 inclusive and 6 attempts
mastermind(9, 6, false);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment