News:

Welcome to RetroCoders Community

Main Menu

Recent posts

#2
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;
}
#3
General Discussion / How to Register to this forum ...
Last post by ron77 - Dec 28, 2024, 09:11 AM
As of now, the new member's registration has to be approved due to Fake Account registration by SpamBots and Spammers...

So, if you are interested in registering for this forum, register. Still, after that, you must send a request by e-mail with your info, including a valid e-mail, and tell us a bit about yourself, why you wish to join this forum, and what your interests are to the following email address. Don't forget to mention the nickname that you registered with. If you are approved, we'll send you the email you contacted us, stating that you are now approved. You can log in to the forum with the password, and members nick you registered with - if you try to register but do not email us, you WILL NOT be approved, and your registration will be deleted in 60 days:

Registration Requests Email Address

Thank you for your Understanding...

#4
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;
}
#5
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"
#6
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
#7
Rust / Rust Donut
Last post by ron77 - Dec 27, 2024, 01:52 PM
use std::{thread, time::Duration};

fn main() {
    let mut a = 0.0f32;
    let mut b = 0.0f32;
    let mut z = vec![0.0f32; 1760];
    let mut buffer = vec![' '; 1760];
    
    // Clear screen
    print!("\x1b[2J");
    
    loop {
        // Reset buffers
        buffer.fill(' ');
        z.fill(0.0);
        
        let mut j = 0.0f32;
        while j < 6.28 {
            let mut i = 0.0f32;
            while i < 6.28 {
                let c = i.sin();
                let d = j.cos();
                let e = a.sin();
                let f = j.sin();
                let g = a.cos();
                let h = d + 2.0;
                let d = 1.0 / (c * h * e + f * g + 5.0);
                let l = i.cos();
                let m = b.cos();
                let n = b.sin();
                let t = c * h * g - f * e;
                let x = (40.0 + 30.0 * d * (l * h * m - t * n)) as i32;
                let y = (12.0 + 15.0 * d * (l * h * n + t * m)) as i32;
                let o = (x + 80 * y) as usize;
                let luminance = (8.0 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n)) as i32;
                
                if y > 0 && y < 22 && x > 0 && x < 80 && d > z[o] {
                    z[o] = d;
                    buffer[o] = ".,-~:;=!*#$@".chars().nth((luminance.max(0) as usize).min(11)).unwrap();
                }
                
                i += 0.02;
            }
            j += 0.07;
        }
        
        // Move cursor to home position
        print!("\x1b[H");
        
        // Print the frame
        for k in 0..1760 {
            if k % 80 == 0 {
                println!();
            } else {
                print!("{}", buffer[k]);
            }
        }
        
        a += 0.04;
        b += 0.02;
        thread::sleep(Duration::from_micros(30000));
    }

}
#8
General Discussion / Merry Christmas and Happy New ...
Last post by CharlieJV - Dec 24, 2024, 02:22 PM
Best wishes for the holidays and for 2025.

Rock'n roll !
#9
C3 / Have a Donut in C3 - donut.c3
Last post by ron77 - Dec 24, 2024, 07:41 AM
donut.c3:

module example;

import std::math;
import std::io;
import std::thread;
import libc;

fn void main()
{
    float a1 = 0;
    float b1 = 0;
    float i;
    float j;
    int k;
    float[1760] z;
    char[1760] b;
    
    io::printf("\x1b[2J");
    
    while (true)
    {
        // Initialize arrays
        for (k = 0; k < 1760; k++)
        {
            b[k] = ' ';
            z[k] = 0;
        }
        
        for (j = 0; j < 6.28; j += 0.07)
        {
            for (i = 0; i < 6.28; i += 0.02)
            {
                float c = math::sin(i);
                float d = math::cos(j);
                float e = math::sin(a1);
                float f = math::sin(j);
                float g = math::cos(a1);
                float h = d + 2;
                float d2 = 1 / (c * h * e + f * g + 5);
                float l = math::cos(i);
                float m = math::cos(b1);
                float n = math::sin(b1);
                float t = c * h * g - f * e;
                
                int x = 40 + (int)(30 * d2 * (l * h * m - t * n));
                int y = 12 + (int)(15 * d2 * (l * h * n + t * m));
                int o = x + 80 * y;
                
                int n2 = (int)(8 * ((f * e - c * d * g) * m - c * d * e - f * g - l * d * n));
                
                if (y > 0 && y < 22 && x > 0 && x < 80 && d2 > z[o])
                {
                    z[o] = d2;
                    b[o] = n2 > 0 ? ".,-~:;=!*#$@"[n2] : ".,-~:;=!*#$@"[0];
                }
            }
        }
        
        io::printf("\x1b[H");
        for (k = 0; k < 1761; k++)
        {
            libc::putchar(k % 80 ? b[k] : 10);
        }
        
        a1 += 0.04;
        b1 += 0.02;
        thread::sleep_ms(30); // Replace usleep with thread::sleep_ms
    }
}
#10
C3 / C3 chatbot Danny
Last post by ron77 - Dec 24, 2024, 05:26 AM
hi all, well i converted my chatbot from C to C3 here is the code:

module c3_danny_std;

import std;
import libc;
import std::math::random;

extern fn char* strdup(char* s);

const int MAX_STRING_LENGTH = 1000;
const int MAX_ARRAY_SIZE = 1000;
const int MAX_KEYWORDS = 50;
const int MAX_REPLIES = 50;
const int MAX_MATCHES = 10;
const int MAX_SWAP_WORDS = 100;
const int MAX_MEMORY = 15;

/*
s:are>am
s:am>are
s:were>was
s:was>were
s:you>i
s:i>you
s:your>my
s:my>your
s:i've>you've
s:you've>i've
s:i'm>you're
s:you're>i'm
s:me>you
s:i'll>you'll
s:you'll>i'll
*/




String[] word_in = {
    "are",
    "am",
    "were",
    "was",
    "you",
    "i",
    "your",
    "my",
    "i've",
    "you've",
    "i'm",
    "you're",
    "me",
    "i'll",
    "you'll",

};
String[] word_out = {
    "am",
    "are",
    "was",
    "were",
    "i",
    "you",
    "my",
    "your",
    "you've",
    "i've",
    "you're",
    "i'm",
    "you",
    "you'll",
    "i'll",

};



String[MAX_SWAP_WORDS] wordIn;
String[MAX_SWAP_WORDS] wordOut;
int wCnt = 0;

String[MAX_MEMORY] memory;
int memoryCount = 0;

struct ArraySet {
    String[MAX_KEYWORDS] keywords;
    String[MAX_REPLIES] replies;
    int keywordCount;
    int replyCount;
} 

ArraySet[MAX_ARRAY_SIZE] g_Key_Reply;
int g_Key_ReplyCount = 0;

String[MAX_ARRAY_SIZE] default_replies;
int default_reply_count = 0;

fn char* safe_strdup(char* s) {
    if (!s) return null;
    char* result = strdup(s);
    if (!result) {
        io::printfn("%s Memory allocation failed in safe_strdup\n", &std::io::stderr);
        return null;
    }
    return result;
}

fn char* isolatePunctuation(char* s) {
    char* b = malloc(libc::strlen((ZString)s) * 3 + 1);
    if (!b) return null;
    
    int j = 0;
    for (int i = 0; s[i]; i++) {
        if (libc::strchr("?!,.:;<>(){}[]", s[i])) {
            b[j++] = ' ';
            b[j++] = s[i];
            b[j++] = ' ';
        } else {
            b[j++] = s[i];
        }
    }
    b[j] = '\0';
    return b;
}

fn void loadArrays(String filename) {
    File! f = io::file::open(filename, "r");
    if (catch error = f) {
        io::printfn("Error opening file: %s: %s\n", filename, error);
        return;
    }

    defer (void)f.close();

    // String line; no needs for this
    int currentSet = -1;
    
    while (try line = io::treadline(&f)) { // line is created here automatically
        if (line.len < 3) {
            // Skip lines that aren't long enough
            continue;
        }
        if (f.eof()) break;

        if (line[0..2] == "d1:") { //(strncmp(line, "d1:", 3) == 0) {
            default_replies[default_reply_count++] = line[3..]; //strcpy(default_replies[default_reply_count++], line + 3);
        }
    
        if (line[0..1] == "k:") { //(line[0] == 'k' && line[1] == ':') {
            if (currentSet == -1 || g_Key_Reply[currentSet].replyCount > 0) {
                currentSet++;
            }
            if (currentSet >= MAX_ARRAY_SIZE) {
                io::printfn("Error: too many keyword-reply pairs\n");
                break;
            }
            if (g_Key_Reply[currentSet].keywordCount < 50) {
                String keyword = string::tformat(" %s ", line[2..]);
            g_Key_Reply[currentSet].keywords[g_Key_Reply[currentSet].keywordCount] = keyword; //line[2..];//strcpy(g_Key_Reply[currentSet].keywords[g_Key_Reply[currentSet].keywordCount], line + 2);
            g_Key_Reply[currentSet].keywordCount++;
            g_Key_ReplyCount = currentSet + 1;
            // g_Key_Reply[currentSet].replyCount = 0;
            } else {
                io::printfn("Error: too many keywords for keyword-reply pair %d\n", currentSet);
            }
        } else if (line[0..1] == "r:") { //(line[0] == 'r' && line[1] == ':') {
            if (g_Key_Reply[currentSet].replyCount < 50) {
            g_Key_Reply[currentSet].replies[g_Key_Reply[currentSet].replyCount] = line[2..];//strcpy(g_Key_Reply[currentSet].replies[g_Key_Reply[currentSet].replyCount], line + 2);
            g_Key_Reply[currentSet].replyCount++;
            // g_Key_Reply[currentSet].keywordCount = 0;
            } else {
                io::printfn("Error: too many replies for keyword %s\n", g_Key_Reply[currentSet].keywords[g_Key_Reply[currentSet].keywordCount - 1]);
            }
        }
        
    }

     //fclose(file);
    io::printfn("number of keywords-replies pair groups %d\n", currentSet);

}

fn void loadSwapWords(String filename) {
    File! f = io::file::open(filename, "r");
    if (catch error = f) {
        io::printfn("Error opening file: %s: %s\n", filename, error);
        return;
    }

    defer (void)f.close();
    String line;
    while ((line = io::treadline(&f)!!) && wCnt < MAX_SWAP_WORDS) {
        if (line.len < 3) {
            // Skip lines that aren't long enough
                continue;
        }

        if (f.eof()) break;

        //line[strcspn(line, "\n")] = 0;  // Remove newline
        if (line[0..1] == "s:") { //(line[0] == 's' && line[1] == ':') {
            int indexOfdelimiter = (int)line.index_of(">")!!;
            // if (indexOfdelimiter != null) {
                wordIn[wCnt] = line[2..indexOfdelimiter];//strcpy(wordIn[wCnt], line + 2);
                wordOut[wCnt] = line[indexOfdelimiter + 1..line.len-1];//strcpy(wordOut[wCnt], delimiter + 1);
                wCnt++;
            // }
            // char* delimiter = strchr(line + 2, '>');
            // if (delimiter) {
            //     *delimiter = '\0';
            //     strcpy(wordIn[wCnt], line + 2);
            //     strcpy(wordOut[wCnt], delimiter + 1);
            //     wCnt++;
            // }
        }
    }

     //fclose(file);
}


fn String swapWords(String input) {
    if (input == "") return "";


    // DString output;
    String output;
    // output.temp_init();
    String[] words = input.tsplit(" ");
    String temp = "";
 

    foreach (j, word: words) {
        String result = word;
        bool swapped = false;

        foreach (i, swap_word: word_in) {
            if (word == word_in[i]) {
                result = word_out[i];
                break;
            }
        }

        output = String.tconcat(output, result);
        // if (j < words.len - 1) output.append(" ");
        if (j < words.len - 1) output = String.tconcat(output, " ");
    }


    // return output.str_view();
    return output;
}



fn String processReply(String reply, String userInput) {
    if (reply == "" || userInput == "") return reply;
    
    
    if (reply[reply.len - 1] == '*') {
        // If the reply doesn't end with an asterisk, don't swap words
        // return reply;
    // } else {
        reply = reply[0:reply.len-1];  // Remove the asterisk
        // reply = reply[0..reply.len-2];
    }  
    String keyword = "";
    for (int i = 0; i < g_Key_ReplyCount; i++) {
        for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
            if (userInput.contains(g_Key_Reply[i].keywords[j])) {
                keyword = g_Key_Reply[i].keywords[j];
                break;
            }
        }
        if (keyword != "") break;
    }

    if (keyword != "") {
        int keywordIndex = (int)userInput.index_of(keyword)!!;
        String tail = userInput[keywordIndex + keyword.len..];
        String swappedTail = swapWords(tail);

        if (swappedTail != "") {
            reply = String.tconcat(reply, " ");
            reply = String.tconcat(reply, swappedTail);
        }
    }
    // }

    return reply;
}


// fn String userQuestion(String txt) {
//     String[MAX_MATCHES] matchedReplies;
//     int matchCount = 0;
//     bool isMatch = false;   
//     String finalReply = "";

//     // Find matching replies
//     for (int i = 0; i < g_Key_ReplyCount && matchCount < MAX_MATCHES; i++) {
//         bool foundInGroup = false;
//         for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
//             if (txt.contains(g_Key_Reply[i].keywords[j])) {
//                 if (!foundInGroup) {
//                     int replyIndex = random::rand(g_Key_Reply[i].replyCount);
//                     matchedReplies[matchCount++] = g_Key_Reply[i].replies[replyIndex];
//                     foundInGroup = true;
//                     isMatch = true;
//                 }
//             }
//         }
//     }

//     // Process replies
//     if (matchCount > 0 && isMatch && matchCount <= MAX_MATCHES) {
//         foreach (reply : matchedReplies[0..matchCount]) {
//             String processed = processReply(reply, txt);
//             if (processed != "") {
//                 if (finalReply != "") {
//                     finalReply = String.tconcat(finalReply, " ");
//                 }
//                 finalReply = String.tconcat(finalReply, processed);
//             }
//         }
//         return finalReply.trim();
//     }

//     // Default reply
//     return default_replies[random::rand(default_reply_count)];
// }


fn String userQuestion(String txt) {
    String response = "I don't understand. Can you rephrase that?";
    String[MAX_MATCHES] matchedReplies;
    int matchCount = 0;
    bool isMatch = false;   
    String combinedReply = "";

    for (int i = 0; i < g_Key_ReplyCount && matchCount < MAX_MATCHES; i++) {
        for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
            if (txt.contains(g_Key_Reply[i].keywords[j])) {
                int replyIndex = random::rand(g_Key_Reply[i].replyCount);
                matchedReplies[matchCount++] = g_Key_Reply[i].replies[replyIndex];
                isMatch = true;
                break;
            }
        }
    }

    if (matchCount > 0 && isMatch && matchCount <= MAX_MATCHES) {
        
        for (int i = 0 ; i < matchCount ; i++) {
            String reply = matchedReplies[i];
             if (reply[reply.len-1] == '*') {
            combinedReply = String.tconcat(combinedReply, processReply(reply, txt));
            } else {
                combinedReply = String.tconcat(combinedReply, reply);
            }
            combinedReply = String.tconcat(combinedReply, " ");
            
        }
    response = combinedReply;
    } else if (!isMatch) {
        int defaultIndex = random::rand(default_reply_count);
        response = default_replies[defaultIndex];
    }

    return response;
}





fn String commands(String txt) {
    // String isolated = isolatePunctuation(txt);
    // for (int i = 0; isolated[i]; i++) {
    //     isolated[i] = tolower(isolated[i]);
    // }
    String text = string::tformat(" %s ", txt);
    String response = userQuestion(text);
    
    // free(isolated);
    return response;
}

fn void speak(String text) {
    String command;
    command = "voice -r -1 -n \"Microsoft David Desktop\" ";
    String text2 = string::tformat("\"%s\"",text);
    // command = string::tformat("%s \"%s\"", command, text2);
    command = String.tconcat(command, text2);
    // command = String.tconcat(text2, "\"");
    // String.tconcat(command, text2);
    libc::system((ZString)command);
}

fn int main() {
    libc::srand((uint)libc::time(null));
    
    loadArrays("./database.txt");
    // loadSwapWords("./swapwords.txt");

    // for (int i = 0; i < wCnt; i++) {
    //     io::printfn("wordIn[%d] = %s, wordOut[%d] = %s\n", i, wordIn[i], i, wordOut[i]);
    // }
    
    io::printfn("CHATBOT DANNY IN C3 PROGRAMMING LANGUAGE VERSION 1.1.6.5 (C) RON77\n");
    
    String input;
    String response;
    
    while (true) {
        io::printf("> ");
        //if (fgets(input, sizeof(input), stdin) == NULL) {
        input = io::treadline()!!; 
            
        
        // input[strcspn(input, "\n")] = 0;  // Remove newline
        
        if (input == "quit") break;
        
        response = commands(input);
        
        if (response != "") {
            // Split the response into separate lines and speak each one
            String line = response;
            while (line != "") {
                io::printn(line);
                io::printn("\n");
                speak(line);
                line = "";
            }
            
            // free(response);
        } else {
            io::printfn("An error occurred while processing your input.\n");
        }
    }
    
    return 0;
}

The database.txt can be found here, as well as the 'voice.exe' TTS cli engine for Windows...
https://retrocoders.phatcode.net/index.php?topic=840.0