Intro to Darwin
genetic-algorithms 20-07-2024
Recently I stumbled across a new concept in the vast world of computer science — namely, genetic algorithms. Genetic algorithms operate on the basis of simulating what we now call “evolution,” the driving factor of which is natural selection often due to random mutation.
Genetic algorithms simulate this process in order to optimize a function. Base candidate functions are laid out, and generations after generations of further functions are tested and weeded out through mutation after mutation. In a system using genetic algorithms, there usually exists a genetic representation of what we are trying to optimize, as well as a fitness function that tells us how “good” our function is.
Thus, we use this fitness function to repeatedly evaluate and mutate the best genetic representations of our target function.
Intrigued, the idea for darwin
was born — named after the scientist, and not to be confused
with Apple’s OS. I thought it would be fun to apply an implementation of genetic algorithms
to a “hunger games”-esque system.
SDL
The first question would be what graphics library I would use. In the past, I’ve tried raylib
in implementing a music visualizer with FFT: krotos. This
time around, I wanted to try something new — so SDL2 it was.
More specifically, the Rust bindings for SDL2. The reputation of these bindings have been better than those for raylib, so I was pretty confident heading into the project that I could iron out any issues later on down the road.
After dispatching some silly mistakes, I created a function for drawing a grid on the canvas (something that I envision using for the game, in order to represent individual cells):
/// Draw a grid on the canvas
fn draw_grid(canvas: &mut sdl2::render::Canvas<sdl2::video::Window>, width: u32, height: u32, cols: u32, rows: u32) {
let cell_width = width / cols;
let cell_height = height / rows;
canvas.set_draw_color(theme::FOREGROUND);
for i in 0..rows {
canvas.draw_line((0, (i * cell_height) as i32), (width as i32, (i * cell_height) as i32)).unwrap();
}
for i in 0..cols {
canvas.draw_line(((i * cell_width) as i32, 0), ((i * cell_width) as i32, height as i32)).unwrap();
}
}
As well as initializing all the proper SDL2 contexts and creating an event loop:
// initialize SDL2
let sdl_context = sdl2::init().unwrap();
let video_subsystem = sdl_context.video().unwrap();
let window = video_subsystem.window("darwin", 1440, 900)
.position_centered()
.build()
.unwrap();
let mut canvas = window.into_canvas().build().unwrap();
// create event loop
canvas.set_draw_color(theme::BACKGROUND);
canvas.clear();
draw_grid(&mut canvas, 1440, 900, 16, 10);
canvas.present();
let mut event_pump = sdl_context.event_pump().unwrap();
'running: loop {
for event in event_pump.poll_iter() {
match event {
Event::Quit {..} => {
break 'running
},
_ => {}
}
}
}