some commenting and a license
This commit is contained in:
@@ -3,18 +3,22 @@ use console::Term; // Allows reading key bind input
|
||||
use std::io::{stdin,stdout,Write};
|
||||
use colored::Colorize;
|
||||
|
||||
// This function is used to Generate the output out a range of levels to the console, it accepts starting and
|
||||
// ending levls to print and then it uses a loop to print out each level in between these, each
|
||||
// level is comprised of numbers, each having a specific meaning for instance 0 is an obstacle and
|
||||
// -2 is a slanted wall "/"
|
||||
// This function is used to Generate and output which will later be outputted, it does this as if
|
||||
// the function printed it as it parsed the map then there would be a flicker on large terminals,
|
||||
// so instead it adds the entire output to a variable once parsed it is all printed at once.
|
||||
// The levels vector is made up of numbers, negative numbers are 'reserved' for the wall and
|
||||
// slanted walls, 0 is an obstacle and anything above 0 is safe space
|
||||
fn generate_output(starting_level: u64, ending_level: u64, character_x_coord: u16, character_icon: char, levels: &Vec<Vec<i8>>, debug_mode: bool, boots_mode: bool) -> String {
|
||||
let mut output: String = "".to_string();
|
||||
// In debug mode the x coordinates are shown above the map
|
||||
if debug_mode {
|
||||
let pattern = "0123456789";
|
||||
let repeat_count = (levels[0].len() + 9) / 10;
|
||||
let pattern = "0123456789"; // Can't have numbers that are multiple digits long so it's
|
||||
// fixed at 0 - 9
|
||||
let repeat_count = (levels[0].len() + 9) / 10; // Repeat the pattern for however wide the
|
||||
// game is
|
||||
let mut repeated = pattern.repeat(repeat_count);
|
||||
repeated += "\n";
|
||||
output += &repeated;
|
||||
output += &repeated; // Add this repeating pattern to the start of the output
|
||||
}
|
||||
for i in starting_level..ending_level {
|
||||
let level = &levels[i as usize]; // Cache the level for quicker access
|
||||
@@ -24,16 +28,17 @@ fn generate_output(starting_level: u64, ending_level: u64, character_x_coord: u1
|
||||
if i == starting_level && j == character_x_coord as usize {
|
||||
output = output + &character_icon.to_string();
|
||||
}
|
||||
else if i == starting_level+2 && j == character_x_coord as usize {
|
||||
else if i == starting_level+2 && j == character_x_coord as usize && boots_mode == true {
|
||||
output = output + &character_icon.to_string();
|
||||
}
|
||||
else {
|
||||
match object {
|
||||
-3 => output.push_str(&"|".to_string()), // Specific case for -3
|
||||
0 => output.push_str(&"|".on_truecolor(255,255,255).strikethrough().to_string()), // Specific case for 0
|
||||
-1 => output.push_str(&"\\".to_string()), // Specific case for -1
|
||||
-2 => output.push_str(&"/".to_string()), // Specific case for -2
|
||||
_ => output+=" " // Default, no print for other cases
|
||||
-3 => output.push_str(&"|".to_string()), // Reserved value (-3)
|
||||
// ouputs a wall
|
||||
0 => output.push_str(&" ".on_truecolor(255,255,255).strikethrough().to_string()), // 0 ouputs white background
|
||||
-1 => output.push_str(&"\\".to_string()), // right slanting wall
|
||||
-2 => output.push_str(&"/".to_string()), // left slanting wall
|
||||
_ => output+=" " // Else, it ouputs a empty space
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -41,80 +46,120 @@ fn generate_output(starting_level: u64, ending_level: u64, character_x_coord: u1
|
||||
output+=&i.to_string();
|
||||
output+="\n";
|
||||
}
|
||||
return output;
|
||||
}
|
||||
return output; // Finally return the output
|
||||
} // generate_output
|
||||
|
||||
// This function generates a new level, modifying the positions of the left and right walls
|
||||
// based on a directional preference (how inclined the tunnel is to move in each direction),
|
||||
// then adding obstacles to the level within those boundaries.
|
||||
fn generate_level(level_to_generate: u64, difficulty: i8, left_wall: &mut i16, right_wall: &mut i16, screen_width: u16, preference: &mut f32, levels: &mut Vec<Vec<i8>>) {
|
||||
// Create a new vector that will represent the current level's layout
|
||||
let mut new_level: Vec<i8> = Vec::new();
|
||||
|
||||
// Determine how much to shift the left and right walls based on the 'preference' value
|
||||
// Randomly generates a value between -1 and 1, then adds the preference to it.
|
||||
let left_wall_change = rand::thread_rng().gen_range(-1..2+(*preference as i16));
|
||||
let right_wall_change = rand::thread_rng().gen_range(-1..2+(*preference as i16));
|
||||
|
||||
// Apply the changes to the left and right walls
|
||||
*left_wall = *left_wall + left_wall_change;
|
||||
*right_wall = *right_wall + right_wall_change;
|
||||
|
||||
// Ensure that the left wall does not go out of bounds (it can't go below 1)
|
||||
if *left_wall <= 0 {
|
||||
*left_wall = 1;
|
||||
}
|
||||
|
||||
// Ensure the right wall does not go beyond the screen width (can't go past screen_width - 1)
|
||||
if *right_wall >= screen_width.try_into().unwrap() {
|
||||
*right_wall = screen_width as i16-1
|
||||
}
|
||||
|
||||
// If the distance between the left and right walls is too narrow (less than 8m),
|
||||
// adjust them by 3 so ther's enough space between them.
|
||||
if (*right_wall-*left_wall).abs() < 8 {
|
||||
*left_wall-=3;
|
||||
*right_wall+=3;
|
||||
}
|
||||
|
||||
// Fill up the new_level vector to the screen width, initially setting all elements to 1 (empty space).
|
||||
while new_level.len() <= screen_width as usize {
|
||||
new_level.push(1)
|
||||
}
|
||||
|
||||
// Add obstacles between the left and right walls, based on the current level and difficulty
|
||||
for i in *left_wall..*right_wall {
|
||||
let mut object: i8 = 1;
|
||||
let mut object: i8 = 1; // By default, the space is empty (1).
|
||||
|
||||
// Also, avoid placing objects too close to the middle of the screen (within ±5 of the center) if
|
||||
// it is one of the first levels so the 5 blocks surrounding the player on game start
|
||||
// should be empty.
|
||||
if level_to_generate >= 5 || (i as f32) < (screen_width as f32 / 2.0)-5.0 || (i as f32) > (screen_width as f32 / 2.0)+5.0 {
|
||||
object = rand::thread_rng().gen_range(0..difficulty);
|
||||
object = rand::thread_rng().gen_range(0..difficulty); // Randomize object placement based on difficulty.
|
||||
}
|
||||
new_level[i as usize] = object;
|
||||
new_level[i as usize] = object; // Set the object in the new level's layout
|
||||
}
|
||||
|
||||
// Add wall modifications (left side)
|
||||
for i in 0..*left_wall {
|
||||
// If the current index is the edge of the left wall and the wall was moved right,
|
||||
// mark it with a specific value (-1) which is a slanted wall "\".
|
||||
if i == *left_wall-1 && left_wall_change > 0 {
|
||||
new_level[i as usize] = -1;
|
||||
}
|
||||
// If the current index is the edge of the left wall and the wall was moved left,
|
||||
// mark it with a different value (-2) which is a slanted wall "/".
|
||||
else if i == *left_wall-1 && left_wall_change < 0 {
|
||||
new_level[i as usize] = -2;
|
||||
}
|
||||
// If it’s not on the left wall, mark the space with another value (-3) which is a straight
|
||||
// wall "|".
|
||||
else {
|
||||
new_level[i as usize] = -3;
|
||||
}
|
||||
}
|
||||
|
||||
// Add wall modifications (right side)
|
||||
for i in *right_wall..screen_width as i16 {
|
||||
// Similar to the left wall logic, check for changes to the right wall
|
||||
if i == *right_wall && right_wall_change > 0 {
|
||||
new_level[i as usize] = -1;
|
||||
new_level[i as usize] = -1; // "\"
|
||||
}
|
||||
else if i == *right_wall && right_wall_change < 0 {
|
||||
new_level[i as usize] = -2;
|
||||
new_level[i as usize] = -2; // "/"
|
||||
}
|
||||
else {
|
||||
new_level[i as usize] = -3;
|
||||
new_level[i as usize] = -3; // "|"
|
||||
}
|
||||
}
|
||||
|
||||
// Ensure the 'levels' vector has enough capacity for the new level and then add the level.
|
||||
while levels.len() <= level_to_generate as usize {
|
||||
levels.push(new_level.clone());
|
||||
}
|
||||
levels[level_to_generate as usize] = new_level;
|
||||
|
||||
// Modification of the directional preference logic
|
||||
// Modify the directional preference slightly to add randomness to the level generation
|
||||
// The preference value affects how much the tunnel is inclined to move left or right.
|
||||
*preference = *preference + rand::thread_rng().gen_range(-0.5..0.5);
|
||||
|
||||
// Ensure the preference stays within a valid range (-3.0 to 3.0).
|
||||
if *preference > 3.0 {
|
||||
*preference = -1.0;
|
||||
*preference = -1.0; // Reset if it goes beyond the upper bound.
|
||||
}
|
||||
else if *preference < -3.0 {
|
||||
*preference = 1.0;
|
||||
*preference = 1.0; // Reset if it goes beyond the lower bound.
|
||||
}
|
||||
|
||||
// If the right wall is close to the screen's right edge, force the preference to move left (-1.0).
|
||||
if *right_wall >= screen_width as i16 - 5 {
|
||||
*preference = -1.0;
|
||||
}
|
||||
// If the left wall is close to the screen's left edge, force the preference to move right (+1.0).
|
||||
else if *left_wall <= 5 {
|
||||
*preference = 1.0;
|
||||
}
|
||||
}
|
||||
} // generate_output
|
||||
|
||||
fn debug_mode_modify_variables(current_level: &mut u64) -> u8 {
|
||||
println!("\n----------------VARIABLE MODIFICATION---------------\n");
|
||||
@@ -135,16 +180,16 @@ fn debug_mode_modify_variables(current_level: &mut u64) -> u8 {
|
||||
}
|
||||
}
|
||||
return 1;
|
||||
}
|
||||
} // debug_mode_mofiy_variables
|
||||
|
||||
fn check_if_alive(levels: &Vec<Vec<i8>>, level: usize, x_coord: usize, boots_mode: bool) -> bool {
|
||||
if levels[level][x_coord] <= 0 || levels[level+2][x_coord] <= 0 {
|
||||
if levels[level][x_coord] <= 0 || (levels[level+2][x_coord] <= 0 && boots_mode == true) {
|
||||
return false;
|
||||
}
|
||||
else {
|
||||
return true;
|
||||
}
|
||||
}
|
||||
} // check_if_alive
|
||||
|
||||
fn input() -> String{
|
||||
let mut s=String::new();
|
||||
@@ -162,7 +207,7 @@ fn input() -> String{
|
||||
fn main() {
|
||||
let debug_mode = false; // Enable or disable debugging mode, it will print some useful stats and
|
||||
// let you modify stats midgame with e
|
||||
let can_die = true; // I can't spell invinsiblitlity but this lets you not die...
|
||||
let can_die = true; // I can't spell invinsiblitlity but this lets you not die... FOR DEBUGGING
|
||||
|
||||
let boots_mode = true; // Boots mode means you're falling after your younger sister and have to
|
||||
// prevent both of you dying •_•
|
||||
@@ -186,9 +231,14 @@ fn main() {
|
||||
let mut x_coord: u16 = (screen_width as f32/ 2.0) as u16; // Distance from left wall
|
||||
let mut left_wall: i16 = rand::thread_rng().gen_range(0..((screen_width as f32/ 2.0)-5.0) as i16) as i16;
|
||||
let mut right_wall: i16 = rand::thread_rng().gen_range(((screen_width as f32 /2.0)+5.0) as i16..screen_width as i16) as i16;
|
||||
let mut preference: f32 = rand::thread_rng().gen_range(-2.0..3.0);
|
||||
let mut preference: f32 = rand::thread_rng().gen_range(-2.0..3.0); // Directional preference
|
||||
// indicates which direction
|
||||
// the tunnel will generally
|
||||
// go in, constantly
|
||||
// randomly changes. Makes
|
||||
// the tunnel smoother :)
|
||||
let mut alive: bool = true;
|
||||
let mut difficulty: i8 = 5;
|
||||
let mut difficulty: i8 = 7;
|
||||
|
||||
|
||||
for i in 0..screen_height {
|
||||
@@ -249,14 +299,15 @@ fn main() {
|
||||
// old stats and see console warnings from rust and stuff
|
||||
print!("{}[2J", 27 as char);
|
||||
}
|
||||
println!("{}","GAME OVER".red());
|
||||
println!("{}","GAME OVER".red()); // Print "GAME OVER" in red text
|
||||
println!("You fell {:?}m before going SPLAT",current_level-1);
|
||||
// Print a cute cockroach that is asking "Where is the Princess?"
|
||||
println!(" -__");
|
||||
println!(" / \\");
|
||||
println!(" | -___");
|
||||
println!(" | / ________________________");
|
||||
println!(" | / | |");
|
||||
println!(" ‾ |‾ / _ | Where is the princess? |");
|
||||
println!(" ‾ |‾ / _ | Where is the Princess? |");
|
||||
println!(" / | \\ / | \\ |________________________|");
|
||||
println!(" / ‾‾‾‾‾‾‾ \\ / /");
|
||||
println!(" __ / / \\• •/ _|");
|
||||
@@ -272,3 +323,7 @@ fn main() {
|
||||
println!(" / / / /");
|
||||
println!(" _| \\ /_ |");
|
||||
}
|
||||
|
||||
// Some of the comments were done by an LLM, but I checked them
|
||||
// All code by me (DeaDvey)
|
||||
// GPL3.0 license
|
||||
|
Reference in New Issue
Block a user