• Welcome to RetroCoders Community.
 

News:

Welcome to RetroCoders Community

Main Menu

Recent posts

#1
General Discussion / origami christmas ornaments
Last post by RhetaMap - Jan 06, 2025, 07:29 PM
origami box kusudama origami flower how to simple origami crane instructions pdf origami flower lily video origami crane napkin
#2
General Discussion / Re: origami flower roses
Last post by CharlieJV - Jan 06, 2025, 04:08 PM
It would be good if whatever you are sharing does not require creating an account on the platform where you have placed your content.
#3
General Discussion / origami 3d box
Last post by RhetaMap - Jan 06, 2025, 05:29 AM
origami box questions origami crane meaning peace origami crane youtube video origami 4 you origami mobile origami flower how to
#4
General Discussion / origami flower roses
Last post by RhetaMap - Jan 06, 2025, 12:11 AM
origami rose easy origami flower diagram origami 8 pointed star origami box rectangle bain ultra origami 6032
#5
General Discussion / origami crane information
Last post by RhetaMap - Jan 05, 2025, 09:31 AM
origami flower ebook origami crane 100 origami crane ehow origami box pattern origami crane wiki
#6
C / C++ / terminal (cmd) Conway's game o...
Last post by ron77 - Dec 30, 2024, 05:16 PM
#include <stdio.h>
#include <stdlib.h>
#include <unistd.h>
#include <time.h>

#define WIDTH 40
#define HEIGHT 20
#define CLEAR "clear"  // Use "cls" for Windows

// Function to initialize the grid with random values
void initializeGrid(int grid[HEIGHT][WIDTH]) {
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            grid[i][j] = rand() % 2;
        }
    }
}

// Function to count neighbors of a cell
int countNeighbors(int grid[HEIGHT][WIDTH], int row, int col) {
    int count = 0;
    for (int i = -1; i <= 1; i++) {
        for (int j = -1; j <= 1; j++) {
            if (i == 0 && j == 0) continue;
            
            int newRow = row + i;
            int newCol = col + j;
            
            // Check boundaries with wraparound
            if (newRow < 0) newRow = HEIGHT - 1;
            if (newRow >= HEIGHT) newRow = 0;
            if (newCol < 0) newCol = WIDTH - 1;
            if (newCol >= WIDTH) newCol = 0;
            
            count += grid[newRow][newCol];
        }
    }
    return count;
}

// Function to update the grid based on Conway's rules
void updateGrid(int grid[HEIGHT][WIDTH], int newGrid[HEIGHT][WIDTH]) {
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            int neighbors = countNeighbors(grid, i, j);
            
            // Apply Conway's rules
            if (grid[i][j]) {
                // Live cell
                newGrid[i][j] = (neighbors == 2 || neighbors == 3) ? 1 : 0;
            } else {
                // Dead cell
                newGrid[i][j] = (neighbors == 3) ? 1 : 0;
            }
        }
    }
    
    // Copy new grid to original grid
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            grid[i][j] = newGrid[i][j];
        }
    }
}

// Function to display the grid
void displayGrid(int grid[HEIGHT][WIDTH]) {
    // system(CLEAR);  // Clear screen
    
    for (int i = 0; i < HEIGHT; i++) {
        for (int j = 0; j < WIDTH; j++) {
            printf("%c ", grid[i][j] ? '#' : '.');
        }
        printf("\n");
    }
}

int main() {
    // Seed the random number generator
    srand(time(NULL));
    
    // Initialize grids
    int grid[HEIGHT][WIDTH];
    int newGrid[HEIGHT][WIDTH] = {0};
    
    // Initialize with random values
    initializeGrid(grid);
    
    // Main game loop
    while (1) {
        printf("\x1b[H");
		displayGrid(grid);
        updateGrid(grid, newGrid);
        usleep(100000);  // Delay for visualization (100ms)
    }
    
    return 0;
}
#7
General Discussion / How to Register to this forum ...
Last post by ron77 - Dec 28, 2024, 09:11 AM
Hello, as of now, the new member's registration is Disabled Due to Fake Account registration by SpamBots and Spammers...

So, if you are interested in Registering for this forum, In that case, you must send a request by e-mail with your info, including a Valid E-mail with your Name, Age, and Location, and a Bit about why you wish to join this forum and what are your interests to the following email address:

Registration Requests Email.

Thank you for your Understanding...

#8
C / C++ / Donut.c - have a donut
Last post by ron77 - Dec 27, 2024, 02:08 PM
#include <stdio.h>
#include <string.h>
#include <unistd.h>
#include <math.h>

int main() {
    float A = 0, B = 0;
    float i, j;
    int k;
    float z[1760];
    char b[1760];
    printf("\x1b[2J");
    for(;;) {
        memset(b,32,1760);
        memset(z,0,7040);
        for(j=0; j < 6.28; j += 0.07) {
            for(i=0; i < 6.28; i += 0.02) {
                float c = sin(i);
                float d = cos(j);
                float e = sin(A);
                float f = sin(j);
                float g = cos(A);
                float h = d + 2;
                float D = 1 / (c * h * e + f * g + 5);
                float l = cos(i);
                float m = cos(B);
                float n = sin(B);
                float t = c * h * g - f * e;
                int x = 40 + 30 * D * (l * h * m - t * n);
                int y= 12 + 15 * D * (l * h * n + t * m);
                int o = x + 80 * y;
                int N = 8 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n);
                if(22 > y && y > 0 && x > 0 && 80 > x && D > z[o]) {
                    z[o] = D;
                    b[o] = ".,-~:;=!*#$@"[N > 0 ? N : 0];
                }
            }
        }
        printf("\x1b[H");
        for(k = 0; k < 1761; k++) {
            putchar(k % 80 ? b[k] : 10);
        }
        A += 0.04;
        B += 0.02;
        usleep(30000);
    }
    return 0;
}
#9
Rust / Rust Implementation of termina...
Last post by ron77 - Dec 27, 2024, 01:59 PM
https://retrocoders.phatcode.net/index.php?topic=868.0

the rust implementation:
main.rs:
use std::fs;
use std::io::{self, Write};
use std::thread;
use std::time::Duration;
use std::ffi::CString;
use std::env;
use rand::Rng;
use anyhow::{Result, Context};
use bass_sys::*;

// File paths
const DESC1: &str = "data/des1.txt";
const OPENING_BANNER: &str = "banners/opening1.txt";
const OPENING_POINT: &str = "data/opening1.txt";
const MENU: &str = "data/mainmenu.txt";
const MONEY_MENU: &str = "data/moneyMenu.txt";
const FRIENDS_MENU: &str = "data/friendsmenu.txt";
const OVER: &str = "data/suicide.txt";
const GAME_END: &str = "data/theend.txt";
const FAMILY1: &str = "data/family1.txt";
const SCHOOL1: &str = "data/school1.txt";

// Arrays of file paths
const MONTHS: [&str; 12] = [
    "January", "February", "March", "April", "May", "June",
    "July", "August", "September", "October", "November", "December"
];

const SONGS_RAND: [&str; 12] = [
    "sound/walrus1.ogg", "sound/walrus2.ogg", "sound/walrus3.ogg",
    "sound/walrus4.ogg", "sound/walrus5.ogg", "sound/walrus6.ogg",
    "sound/walrus7.ogg", "sound/walrus8.ogg", "sound/walrus9.ogg",
    "sound/walrus10.ogg", "sound/walrus11.ogg", "sound/walrus12.ogg"
];

const MARY: [&str; 5] = [
    "data/mary1.txt", "data/mary2rehab.txt", "data/mary3pregnant.txt",
    "data/mary4jail.txt", "data/mary5dead.txt"
];

const JOE: [&str; 5] = [
    "data/joe1.txt", "data/joe2rehab.txt", "data/joe3jail.txt",
    "data/joe4.txt", "data/joe5prison.txt"
];

const FELIX: [&str; 5] = [
    "data/felix1.txt", "data/felix2.txt", "data/felix3jail.txt",
    "data/felix4rehab.txt", "data/felix5crazy.txt"
];

struct GameState {
    health: i32,
    money: i32,
    turns: usize,
    year: i32,
    is_over: bool,
    is_mary: bool,
    is_joe: bool,
    is_felix: bool,
    is_suicide: bool,
    stream: u32,
}

impl GameState {
    fn new() -> Self {
        Self {
            health: 100,
            money: 5000,
            turns: 0,
            year: 1991,
            is_over: false,
            is_mary: true,
            is_joe: true,
            is_felix: true,
            is_suicide: false,
            stream: 0,
        }
    }

    fn play_music(&mut self, path: &str) -> Result<()> {
        let mut full_path = env::current_dir()?;
        full_path.push(path);
        let path_str = full_path.to_str().unwrap();
        
        println!("Attempting to play: {}", path_str);

        if self.stream != 0 {
            BASS_StreamFree(self.stream);
            self.stream = 0;
        }

        let path_c = CString::new(path_str)?;
        self.stream = BASS_StreamCreateFile(
            0,
            path_c.as_ptr() as *const _,
            0,
            0,
            BASS_SAMPLE_LOOP
        );

        if self.stream == 0 {
            println!("BASS Error Code: {}", BASS_ErrorGetCode());
            return Ok(());
        }

        if BASS_ChannelPlay(self.stream, 0) == 0 {
            println!("Failed to play: Error code {}", BASS_ErrorGetCode());
            return Ok(());
        }
        
        Ok(())
    }

    fn stop_music(&mut self) {
        if self.stream != 0 {
            BASS_ChannelStop(self.stream);
            BASS_StreamFree(self.stream);
            self.stream = 0;
        }
    }

    fn read_file(&self, path: &str) -> Result<String> {
        let mut full_path = env::current_dir()?;
        full_path.push(path);
        fs::read_to_string(&full_path)
            .with_context(|| format!("Failed to read file: {}", full_path.display()))
    }

    fn clear_screen(&self) {
        print!("\x1B[2J\x1B[1;1H");
        io::stdout().flush().unwrap();
    }

    fn get_input(&self) -> Result<i32> {
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        Ok(input.trim().parse()?)
    }

    fn wait_for_enter(&self) -> Result<()> {
        let mut input = String::new();
        io::stdin().read_line(&mut input)?;
        Ok(())
    }

    fn friends(&mut self) -> Result<()> {
        self.clear_screen();
        println!(
            "date: {}, {} health: {} money: {}\n\n{}",
            MONTHS[self.turns], self.year, self.health, self.money,
            self.read_file(FRIENDS_MENU)?
        );

        match self.get_input()? {
            1 => self.visit_mary()?,
            2 => self.visit_joe()?,
            3 => self.visit_felix()?,
            4 => self.visit_school()?,
            5 => self.visit_family()?,
            _ => {
                println!("INVALID INPUT!");
                thread::sleep(Duration::from_secs(5));
            }
        }
        Ok(())
    }

    fn visit_mary(&mut self) -> Result<()> {
        self.clear_screen();
        if !self.is_mary {
            println!("{}", self.read_file(MARY[4])?);
        } else {
            let mut rng = rand::thread_rng();
            let r = rng.gen_range(0..5);
            if r == 4 {
                self.is_mary = false;
            }
            println!("{}", self.read_file(MARY[r])?);
        }
        self.wait_for_enter()?;
        Ok(())
    }

    fn visit_joe(&mut self) -> Result<()> {
        self.clear_screen();
        if !self.is_joe {
            println!("{}", self.read_file(JOE[4])?);
        } else {
            let mut rng = rand::thread_rng();
            let r = rng.gen_range(0..5);
            if r == 4 {
                self.is_joe = false;
            }
            println!("{}", self.read_file(JOE[r])?);
        }
        self.wait_for_enter()?;
        Ok(())
    }

    fn visit_felix(&mut self) -> Result<()> {
        self.clear_screen();
        if !self.is_felix {
            println!("{}", self.read_file(FELIX[4])?);
        } else {
            let mut rng = rand::thread_rng();
            let r = rng.gen_range(0..5);
            if r == 4 {
                self.is_felix = false;
            }
            println!("{}", self.read_file(FELIX[r])?);
        }
        self.wait_for_enter()?;
        Ok(())
    }

    fn visit_school(&mut self) -> Result<()> {
        self.clear_screen();
        println!("{}", self.read_file(SCHOOL1)?);
        self.wait_for_enter()?;
        Ok(())
    }

    fn visit_family(&mut self) -> Result<()> {
        self.clear_screen();
        println!("{}", self.read_file(FAMILY1)?);
        self.wait_for_enter()?;
        Ok(())
    }

    fn drugs(&mut self) -> Result<()> {
        self.clear_screen();
        let mut rng = rand::thread_rng();
        let index = rng.gen_range(0..5);
        
        println!("{}", self.read_file(&format!("data/drug{}.txt", index + 1))?);
        
        match index {
            0 => self.money -= 170,
            3 => {
                self.health -= 5;
                self.money -= 350;
            }
            4 => {
                self.health -= 5;
                self.money -= 250;
            }
            _ => {}
        }
        
        self.wait_for_enter()?;
        Ok(())
    }

    fn shoplist(&mut self) -> Result<()> {
        self.clear_screen();
        let mut rng = rand::thread_rng();
        let index = rng.gen_range(0..5);
        
        println!("{}", self.read_file(&format!("data/shop{}.txt", index + 1))?);
        
        match index {
            0 => self.money += 200,
            1 => self.money += 150,
            2 => self.health -= 3,
            3 => self.money += 200,
            4 => self.health -= 3,
            _ => {}
        }
        
        self.wait_for_enter()?;
        Ok(())
    }

    fn car(&mut self) -> Result<()> {
        self.clear_screen();
        let mut rng = rand::thread_rng();
        let index = rng.gen_range(0..5);
        
        println!("{}", self.read_file(&format!("data/car{}.txt", index + 1))?);
        
        match index {
            0 => self.money += 1000,
            1 => self.money += 2000,
            2 => self.health -= 5,
            3 => self.money += 1500,
            4 => self.health -= 5,
            _ => {}
        }
        
        self.wait_for_enter()?;
        Ok(())
    }

    fn burglary(&mut self) -> Result<()> {
        self.clear_screen();
        let mut rng = rand::thread_rng();
        let index = rng.gen_range(0..5);
        
        println!("{}", self.read_file(&format!("data/burglur{}.txt", index + 1))?);
        
        match index {
            0 => self.money += 2500,
            1 => self.health -= 7,
            2 => self.health -= 7,
            3 => self.money += 2500,
            4 => self.health -= 7,
            _ => {}
        }
        
        self.wait_for_enter()?;
        Ok(())
    }

    fn get_money(&mut self) -> Result<()> {
        self.clear_screen();
        println!(
            "date: {}, {} health: {} money: {}\n\n{}",
            MONTHS[self.turns], self.year, self.health, self.money,
            self.read_file(MONEY_MENU)?
        );

        match self.get_input()? {
            1 => self.shoplist()?,
            2 => self.car()?,
            3 => self.burglary()?,
            _ => {}
        }
        
        Ok(())
    }

    fn rehab(&mut self) -> Result<()> {
        if self.money < 2800 {
            self.clear_screen();
            println!(
                "\nYOU DON'T HAVE ENOUGH MONEY FOR REHAB...\nIT COSTS 2800 AND YOU ONLY HAVE {}\n",
                self.money
            );
            self.wait_for_enter()?;
            return Ok(());
        }

        self.money -= 2800;

        for i in 0..6 {
            self.clear_screen();
            println!("{}", self.read_file(&format!("data/rehab{}.txt", i + 1))?);
            self.wait_for_enter()?;
        }

        self.health += 65;
        if self.health > 100 {
            self.health = 100;
        }

        Ok(())
    }

    fn mirror(&mut self) -> Result<()> {
        self.clear_screen();
        
        let mirror_index = match self.health {
            h if h >= 90 => 0,
            h if h >= 80 => 1,
            h if h >= 70 => 2,
            h if h >= 60 => 3,
            h if h >= 50 => 4,
            h if h >= 40 => 5,
            h if h >= 30 => 6,
            h if h >= 20 => 7,
            h if h >= 10 => 8,
            _ => 9,
        };

        println!("{}", self.read_file(&format!("data/mirror{}.txt", mirror_index + 1))?);

        if self.health < 35 {
            self.is_suicide = true;
        }

        self.wait_for_enter()?;
        Ok(())
    }

    fn suicide(&mut self) -> Result<()> {
        self.clear_screen();
        println!("{}", self.read_file(OVER)?);
        self.wait_for_enter()?;
        self.is_over = true;
        Ok(())
    }
}

fn main() -> Result<()> {
    // Initialize BASS
    if BASS_Init(-1, 44100, 0, std::ptr::null_mut(), std::ptr::null_mut()) == 0 {
        let error_code = BASS_ErrorGetCode();
        eprintln!("Error initializing BASS library: {}", error_code);
        return Ok(());
    }

    let mut game = GameState::new();
    let mut rng = rand::thread_rng();

    // Show intro
    println!("{}", game.read_file(DESC1)?);
    game.wait_for_enter()?;
    game.clear_screen();

    // Start background music
    let song_index = rng.gen_range(0..12);
    if let Err(e) = game.play_music(SONGS_RAND[song_index]) {
        eprintln!("Failed to play music: {}", e);
    }

    println!("{}", game.read_file(OPENING_BANNER)?);
    game.wait_for_enter()?;
    game.clear_screen();

    println!("{}", game.read_file(OPENING_POINT)?);
    game.wait_for_enter()?;
    game.clear_screen();

    // Main game loop
    while game.health > 0 && !game.is_over {
        game.clear_screen();

        if game.turns > 11 {
            game.turns = 0;
            game.year += 1;
        }

        if game.money < 0 {
            game.money = 0;
        }

        println!(
            "date: {}, {} health: {} money: {}\n\n{}",
            MONTHS[game.turns], game.year, game.health, game.money,
            game.read_file(MENU)?
        );

        if game.is_suicide {
            println!("PRESS 8 TO TRY AND SUICIDE");
        }

        match game.get_input()? {
            1 => {
                game.stop_music();
                let song_index = rng.gen_range(0..12);
                if let Err(e) = game.play_music(SONGS_RAND[song_index]) {
                    eprintln!("Failed to change music: {}", e);
                }
            },
            2 => game.friends()?,
            3 => game.drugs()?,
            4 => game.get_money()?,
            5 => game.rehab()?,
            6 => game.mirror()?,
            7 => game.is_over = true,
            8 if game.is_suicide => game.suicide()?,
            _ => {}
        }

        game.turns += 1;
    }

    // Show ending
    game.clear_screen();
    println!("{}", game.read_file(GAME_END)?);
    game.wait_for_enter()?;

    // Cleanup
    game.stop_music();
    BASS_Free();

    Ok(())
}

Cargo.toml:
[package]
name = "rust_trainspotting_II_game"
version = "0.1.0"
edition = "2021"

[dependencies]
rand = "0.8"
bass-sys = "2.1"
anyhow = "1.0"
#10
Rust / Danny chatbot in Rust
Last post by ron77 - Dec 27, 2024, 01:54 PM
use std::fs::File;
use std::io::{self, BufRead, BufReader, Write};
use std::process::Command;
use std::collections::HashMap;
use rand::prelude::*;
use anyhow::{Result, Context as _};

// const MAX_STRING_LENGTH: usize = 1000;
// const MAX_KEYWORDS: usize = 20;
// const MAX_REPLIES: usize = 50;
const MAX_MEMORY: usize = 15;

#[derive(Default)]
struct ArraySet {
    keywords: Vec<String>,
    replies: Vec<String>,
}

#[derive(Default)]
struct ChatBot {
    key_reply: Vec<ArraySet>,
    default_replies: Vec<String>,
    memory: Vec<String>,
    word_swaps: HashMap<String, String>,
    rng: ThreadRng,
    single_line_mode: bool,
}

impl ChatBot {
    fn new() -> Self {
        Self {
            key_reply: Vec::new(),
            default_replies: Vec::new(),
            memory: Vec::with_capacity(MAX_MEMORY),
            word_swaps: HashMap::new(),
            rng: thread_rng(),
            single_line_mode: true,
        }
    }

    fn load_arrays(&mut self, filename: &str) -> Result<()> {
        let file = File::open(filename)
            .with_context(|| format!("Failed to open file: {}", filename))?;
        let reader = BufReader::new(file);
        let mut current_set: Option<ArraySet> = None;

        for line in reader.lines() {
            let line = line?;
            if line.starts_with("d1:") {
                self.default_replies.push(line[3..].to_string());
            } else if line.starts_with("k:") {
                if current_set.is_some() && !current_set.as_ref().unwrap().replies.is_empty() {
                    if let Some(set) = current_set.take() {
                        self.key_reply.push(set);
                    }
                }
                
                if current_set.is_none() {
                    current_set = Some(ArraySet::default());
                }
                
                if let Some(set) = &mut current_set {
                    set.keywords.push(line[2..].to_string());
                }
            } else if line.starts_with("r:") {
                if let Some(set) = &mut current_set {
                    set.replies.push(line[2..].to_string());
                }
            }
        }

        if let Some(set) = current_set {
            self.key_reply.push(set);
        }

        println!("Number of keywords-replies pair groups: {}", self.key_reply.len());
        Ok(())
    }

    fn load_swap_words(&mut self, filename: &str) -> Result<()> {
        let file = File::open(filename)
            .with_context(|| format!("Failed to open swap words file: {}", filename))?;
        let reader = BufReader::new(file);

        for line in reader.lines() {
            let line = line?;
            if line.starts_with("s:") {
                if let Some(pos) = line[2..].find('>') {
                    let (word_in, word_out) = line[2..].split_at(pos);
                    self.word_swaps.insert(
                        word_in.to_string(),
                        word_out[1..].to_string()
                    );
                }
            }
        }
        Ok(())
    }

    fn swap_words(&self, input: &str) -> String {
        input
            .split_whitespace()
            .map(|word| {
                self.word_swaps
                    .get(word)
                    .map_or(word.to_string(), |w| w.clone())
            })
            .collect::<Vec<_>>()
            .join(" ")
    }

    fn isolate_punctuation(s: &str) -> String {
        s.chars()
            .map(|c| {
                if "?!,.:;<>(){}[]".contains(c) {
                    format!(" {} ", c)
                } else {
                    c.to_string()
                }
            })
            .collect()
    }

    fn process_reply(&mut self, reply: &str, user_input: &str) -> String {
        if !reply.ends_with('*') {
            return reply.to_string();
        }

        let reply = &reply[..reply.len() - 1];
        
        if self.memory.len() < MAX_MEMORY {
            self.memory.push(user_input.to_string());
        }
        
        for set in &self.key_reply {
            for keyword in &set.keywords {
                if user_input.contains(keyword.as_str()) {
                    if let Some(rest) = user_input.split(keyword.as_str()).nth(1) {
                        let swapped = self.swap_words(rest);
                        return format!("{} {}", reply, swapped);
                    }
                }
            }
        }
        
        reply.to_string()
    }

    fn user_question(&mut self, txt: &str) -> String {
        let mut matched_replies = Vec::new();
        let mut found = false;

        for set in &self.key_reply {
            for keyword in &set.keywords {
                if txt.contains(keyword.as_str()) {
                    if let Some(reply) = set.replies.choose(&mut self.rng).cloned() {
                        matched_replies.push(reply);
                        found = true;
                        break;
                    }
                }
            }
        }

        let processed_replies: Vec<String> = matched_replies.into_iter()
            .map(|reply| self.process_reply(&reply, txt))
            .collect();

        if !processed_replies.is_empty() {
            if self.single_line_mode {
                processed_replies.join(" | ")
            } else {
                processed_replies.join("\n")
            }
        } else if !found && !self.default_replies.is_empty() {
            self.default_replies
                .choose(&mut self.rng)
                .cloned()
                .unwrap_or_else(|| "I don't understand. Can you rephrase that?".to_string())
        } else {
            "I don't understand. Can you rephrase that?".to_string()
        }
    }

    fn commands(&mut self, txt: &str) -> String {
        if txt.starts_with("/") {
            match txt {
                "/single" => {
                    self.single_line_mode = true;
                    return "Switched to single-line mode.".to_string();
                }
                "/multi" => {
                    self.single_line_mode = false;
                    return "Switched to multi-line mode.".to_string();
                }
                _ => {}
            }
        }

        let isolated = Self::isolate_punctuation(txt);
        let lowercase = isolated.to_lowercase();
        self.user_question(&lowercase)
    }

    fn speak(&self, text: &str) -> Result<()> {
        Command::new("voice")
            .args(["-r", "-1", "-n", "Microsoft David Desktop", text])
            .spawn()
            .with_context(|| "Failed to start TTS process")?
            .wait()
            .with_context(|| "Failed to wait for TTS process")?;
        Ok(())
    }
}

fn main() -> Result<()> {
    println!("CHATBOT DANNY IN RUST VERSION 1.0.0");
    println!("Commands:");
    println!("  /single - Switch to single-line mode");
    println!("  /multi  - Switch to multi-line mode");
    println!("  quit    - Exit the program");
    
    let mut chatbot = ChatBot::new();
    chatbot.load_arrays("database.txt")?;
    chatbot.load_swap_words("swapwords.txt")?;

    let stdin = io::stdin();
    let mut stdout = io::stdout();
    
    loop {
        print!("> ");
        stdout.flush()?;
        
        let mut input = String::new();
        stdin.lock().read_line(&mut input)?;
        let input = input.trim();
        
        if input == "quit" {
            break;
        }
        
        let response = chatbot.commands(input);
        
        if chatbot.single_line_mode {
            println!("{}", response);
            chatbot.speak(&response)?;
        } else {
            for line in response.lines() {
                println!("{}", line);
                chatbot.speak(line)?;
            }
        }
    }

    Ok(())
}

https://retrocoders.phatcode.net/index.php?topic=840.0