News:

Welcome to RetroCoders Community

Main Menu

chatbot Danny in C

Started by ron77, Sep 04, 2024, 09:40 AM

Previous topic - Next topic

ron77

ok just a basic version of fb_chatbot_danny converted to C...

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stdbool.h>
#include <unistd.h>

#define MAX_STRING_LENGTH 1000
#define MAX_ARRAY_SIZE 1000
#define MAX_KEYWORDS 20
#define MAX_REPLIES 50
#define MAX_MATCHES 5
#define MAX_SWAP_WORDS 100
#define MAX_MEMORY 10

char wordIn[MAX_SWAP_WORDS][MAX_STRING_LENGTH];
char wordOut[MAX_SWAP_WORDS][MAX_STRING_LENGTH];
int wCnt = 0;

char memory[MAX_MEMORY][MAX_STRING_LENGTH];
int memoryCount = 0;

typedef struct {
    char keywords[MAX_KEYWORDS][MAX_STRING_LENGTH];
    char replies[MAX_REPLIES][MAX_STRING_LENGTH];
    int keywordCount;
    int replyCount;
} ArraySet;

ArraySet g_Key_Reply[MAX_ARRAY_SIZE];
int g_Key_ReplyCount = 0;

char default_replies[MAX_ARRAY_SIZE][MAX_STRING_LENGTH];
int default_reply_count = 0;

char* safe_strdup(const char* s) {
    if (!s) return NULL;
    char* result = strdup(s);
    if (!result) {
        fprintf(stderr, "Memory allocation failed in safe_strdup\n");
        exit(1);
    }
    return result;
}

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

void loadArrays(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        printf("Error opening file: %s\n", filename);
        return;
    }

    char line[MAX_STRING_LENGTH];
    int currentSet = -1;
    
    while (fgets(line, sizeof(line), file)) {
        line[strcspn(line, "\n")] = 0;  // Remove newline

        if (strncmp(line, "d1:", 3) == 0) {
            strcpy(default_replies[default_reply_count++], line + 3);
        }
    
        if (line[0] == 'k' && line[1] == ':') {
            if (currentSet == -1 || g_Key_Reply[currentSet].replyCount > 0) {
                currentSet++;
            }
            strcpy(g_Key_Reply[currentSet].keywords[g_Key_Reply[currentSet].keywordCount], line + 2);
            g_Key_Reply[currentSet].keywordCount++;
            g_Key_ReplyCount = currentSet + 1;
        } else if (line[0] == 'r' && line[1] == ':') {
            strcpy(g_Key_Reply[currentSet].replies[g_Key_Reply[currentSet].replyCount], line + 2);
            g_Key_Reply[currentSet].replyCount++;
        }
    }

    fclose(file);
}

void loadSwapWords(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        printf("Error opening swap words file: %s\n", filename);
        return;
    }

    char line[MAX_STRING_LENGTH];
    while (fgets(line, sizeof(line), file) && wCnt < MAX_SWAP_WORDS) {
        line[strcspn(line, "\n")] = 0;  // Remove newline
        if (line[0] == 's' && line[1] == ':') {
            char* delimiter = strchr(line + 2, '>');
            if (delimiter) {
                *delimiter = '\0';
                strcpy(wordIn[wCnt], line + 2);
                strcpy(wordOut[wCnt], delimiter + 1);
                wCnt++;
            }
        }
    }

    fclose(file);
}

char* swapWords(const char* input) {
    if (!input) return NULL;
    char* result = safe_strdup(input);
    char* temp = malloc(strlen(input) * 2 + 1); // Allocate more space for worst-case scenario
    if (!temp) {
        free(result);
        return NULL;
    }

    char* word = strtok(result, " ");
    temp[0] = '\0';

    while (word != NULL) {
        bool swapped = false;
        for (int i = 0; i < wCnt; i++) {
            if (strcmp(word, wordIn[i]) == 0) {
                strcat(temp, wordOut[i]);
                strcat(temp, " ");
                swapped = true;
                break;
            }
        }
        if (!swapped) {
            strcat(temp, word);
            strcat(temp, " ");
        }
        word = strtok(NULL, " ");
    }

    // Remove trailing space
    int len = strlen(temp);
    if (len > 0 && temp[len - 1] == ' ') {
        temp[len - 1] = '\0';
    }

    free(result);
    return temp;
}

char* processReply(const char* reply, const char* userInput) {
    if (!reply || !userInput) return NULL;
    char* processedReply = safe_strdup(reply);
    int len = strlen(processedReply);
    
    if (len > 0 && processedReply[len - 1] == '*') {
        processedReply[len - 1] = '\0';  // Remove the asterisk
        
        // Save the user's input to memory
        if (memoryCount < MAX_MEMORY) {
            strncpy(memory[memoryCount], userInput, MAX_STRING_LENGTH - 1);
            memory[memoryCount][MAX_STRING_LENGTH - 1] = '\0';
            memoryCount++;
        }
        
        // Find the keyword in the user's input
        char* keyword = NULL;
        for (int i = 0; i < g_Key_ReplyCount; i++) {
            for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
                if (strstr(userInput, g_Key_Reply[i].keywords[j])) {
                    keyword = g_Key_Reply[i].keywords[j];
                    break;
                }
            }
            if (keyword) break;
        }
        
        if (keyword) {
            char* rest = strstr(userInput, keyword);
            if (rest) {
                rest += strlen(keyword);
                char* swapped = swapWords(rest);
                if (swapped) {
                    // Concatenate the swapped input to the reply
                    char* temp = malloc(strlen(processedReply) + strlen(swapped) + 2);
                    if (temp) {
                        sprintf(temp, "%s %s", processedReply, swapped);
                        free(processedReply);
                        processedReply = temp;
                    }
                    free(swapped);
                }
            }
        }
    }
    
    return processedReply;
}

char* userQuestion(const char* txt) {
    if (!txt) return NULL;
    char* matchedReplies[MAX_MATCHES] = {NULL};
    int matchCount = 0;
    bool found = false;
    char* combinedReply = NULL;

    for (int i = 0; i < g_Key_ReplyCount && matchCount < MAX_MATCHES; i++) {
        for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
            if (strstr(txt, g_Key_Reply[i].keywords[j])) {
                int replyIndex = rand() % g_Key_Reply[i].replyCount;
                matchedReplies[matchCount] = safe_strdup(g_Key_Reply[i].replies[replyIndex]);
                matchCount++;
                found = true;
                break;
            }
        }
    }

    if (matchCount > 0) {
        size_t totalLength = 1;  // Start with 1 for the null terminator
        for (int i = 0; i < matchCount; i++) {
            char* processedReply = processReply(matchedReplies[i], txt);
            if (processedReply) {
                totalLength += strlen(processedReply) + 1;  // +1 for newline
                free(matchedReplies[i]);
                matchedReplies[i] = processedReply;
            }
        }

        combinedReply = malloc(totalLength);
        if (combinedReply) {
            combinedReply[0] = '\0';
            for (int i = 0; i < matchCount; i++) {
                if (matchedReplies[i]) {
                    strcat(combinedReply, matchedReplies[i]);
                    strcat(combinedReply, "\n");
                    free(matchedReplies[i]);
                }
            }
        }
    } else if (!found) {
        if (default_reply_count > 0) {
            int defaultIndex = rand() % default_reply_count;
            combinedReply = safe_strdup(default_replies[defaultIndex]);
        }
    }
    
    return combinedReply ? combinedReply : safe_strdup("I don't understand. Can you rephrase that?");
}

char* commands(char* txt) {
    char* isolated = isolatePunctuation(txt);
    for (int i = 0; isolated[i]; i++) {
        isolated[i] = tolower(isolated[i]);
    }
    
    char* response = userQuestion(isolated);
    
    free(isolated);
    return response;
}

void speak(const char* text) {
    char command[MAX_STRING_LENGTH * 2];
    snprintf(command, sizeof(command), "voice -r -1 -n \"Microsoft David Desktop\" \"%s\"", text);
    system(command);
}

int main() {
    srand(time(NULL));
    
    loadArrays("database.txt");
    loadSwapWords("swapwords.txt");
    
    char input[MAX_STRING_LENGTH];
    char* response;
    
    while (1) {
        printf("> ");
        if (fgets(input, sizeof(input), stdin) == NULL) {
            break;
        }
        input[strcspn(input, "\n")] = 0;  // Remove newline
        
        if (strcmp(input, "quit") == 0) break;
        
        response = commands(input);
        
        if (response) {
            // Split the response into separate lines and speak each one
            char* line = strtok(response, "\n");
            while (line != NULL) {
                printf("%s\n", line);
                speak(line);
                line = strtok(NULL, "\n");
            }
            
            free(response);
        } else {
            printf("An error occurred while processing your input.\n");
        }
    }
    
    return 0;
}

databases files:

You cannot view this attachment.

You cannot view this attachment.

this chatbot uses voice.exe TTS cli engine 

ron77

Okay, I made some final adjustments to the chatbot. First, let me clear that this chatbot is not politically correct. It is an offensive chatbot that is not suitable for minors under 18 years old, and also, I do not take on any responsibility for your usage of it. So here are the final elements of almost the final diversion of the chatbot in C programming Language.

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <ctype.h>
#include <time.h>
#include <stdbool.h>
#include <unistd.h>

#define MAX_STRING_LENGTH 1000
#define MAX_ARRAY_SIZE 1000
#define MAX_KEYWORDS 20
#define MAX_REPLIES 50
#define MAX_MATCHES 10
#define MAX_SWAP_WORDS 100
#define MAX_MEMORY 15

char wordIn[MAX_SWAP_WORDS][MAX_STRING_LENGTH];
char wordOut[MAX_SWAP_WORDS][MAX_STRING_LENGTH];
int wCnt = 0;

char memory[MAX_MEMORY][MAX_STRING_LENGTH];
int memoryCount = 0;

typedef struct {
    char keywords[MAX_KEYWORDS][MAX_STRING_LENGTH];
    char replies[MAX_REPLIES][MAX_STRING_LENGTH];
    int keywordCount;
    int replyCount;
} ArraySet;

ArraySet g_Key_Reply[MAX_ARRAY_SIZE];
int g_Key_ReplyCount = 0;

char default_replies[MAX_ARRAY_SIZE][MAX_STRING_LENGTH];
int default_reply_count = 0;

char* safe_strdup(const char* s) {
    if (!s) return NULL;
    char* result = strdup(s);
    if (!result) {
        fprintf(stderr, "Memory allocation failed in safe_strdup\n");
        exit(1);
    }
    return result;
}

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

void loadArrays(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        printf("Error opening file: %s\n", filename);
        return;
    }

    char line[MAX_STRING_LENGTH];
    int currentSet = -1;
    
    while (fgets(line, sizeof(line), file)) {
        line[strcspn(line, "\n")] = 0;  // Remove newline

        if (strncmp(line, "d1:", 3) == 0) {
            strcpy(default_replies[default_reply_count++], line + 3);
        }
    
        if (line[0] == 'k' && line[1] == ':') {
            if (currentSet == -1 || g_Key_Reply[currentSet].replyCount > 0) {
                currentSet++;
            }
            strcpy(g_Key_Reply[currentSet].keywords[g_Key_Reply[currentSet].keywordCount], line + 2);
            g_Key_Reply[currentSet].keywordCount++;
            g_Key_ReplyCount = currentSet + 1;
        } else if (line[0] == 'r' && line[1] == ':') {
            strcpy(g_Key_Reply[currentSet].replies[g_Key_Reply[currentSet].replyCount], line + 2);
            g_Key_Reply[currentSet].replyCount++;
        }
    }

    fclose(file);
	printf("number of keywords-replies pair groups %d\n", currentSet);
}

void loadSwapWords(const char* filename) {
    FILE* file = fopen(filename, "r");
    if (!file) {
        printf("Error opening swap words file: %s\n", filename);
        return;
    }

    char line[MAX_STRING_LENGTH];
    while (fgets(line, sizeof(line), file) && wCnt < MAX_SWAP_WORDS) {
        line[strcspn(line, "\n")] = 0;  // Remove newline
        if (line[0] == 's' && line[1] == ':') {
            char* delimiter = strchr(line + 2, '>');
            if (delimiter) {
                *delimiter = '\0';
                strcpy(wordIn[wCnt], line + 2);
                strcpy(wordOut[wCnt], delimiter + 1);
                wCnt++;
            }
        }
    }

    fclose(file);
}

char* swapWords(const char* input) {
    if (!input) return NULL;
    char* result = safe_strdup(input);
    char* temp = malloc(strlen(input) * 2 + 1); // Allocate more space for worst-case scenario
    if (!temp) {
        free(result);
        return NULL;
    }

    char* word = strtok(result, " ");
    temp[0] = '\0';

    while (word != NULL) {
        bool swapped = false;
        for (int i = 0; i < wCnt; i++) {
            if (strcmp(word, wordIn[i]) == 0) {
                strcat(temp, wordOut[i]);
                strcat(temp, " ");
                swapped = true;
                break;
            }
        }
        if (!swapped) {
            strcat(temp, word);
            strcat(temp, " ");
        }
        word = strtok(NULL, " ");
    }

    // Remove trailing space
    int len = strlen(temp);
    if (len > 0 && temp[len - 1] == ' ') {
        temp[len - 1] = '\0';
    }

    free(result);
    return temp;
}

char* processReply(const char* reply, const char* userInput) {
    if (!reply || !userInput) return NULL;
    char* processedReply = safe_strdup(reply);
    int len = strlen(processedReply);
    
    if (len > 0 && processedReply[len - 1] == '*') {
        processedReply[len - 1] = '\0';  // Remove the asterisk
        
        // Save the user's input to memory
        if (memoryCount < MAX_MEMORY) {
            strncpy(memory[memoryCount], userInput, MAX_STRING_LENGTH - 1);
            memory[memoryCount][MAX_STRING_LENGTH - 1] = '\0';
            memoryCount++;
        }
        
        // Find the keyword in the user's input
        char* keyword = NULL;
        for (int i = 0; i < g_Key_ReplyCount; i++) {
            for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
                if (strstr(userInput, g_Key_Reply[i].keywords[j])) {
                    keyword = g_Key_Reply[i].keywords[j];
                    break;
                }
            }
            if (keyword) break;
        }
        
        if (keyword) {
            char* rest = strstr(userInput, keyword);
            if (rest) {
                rest += strlen(keyword);
                char* swapped = swapWords(rest);
                if (swapped) {
                    // Concatenate the swapped input to the reply
                    char* temp = malloc(strlen(processedReply) + strlen(swapped) + 2);
                    if (temp) {
                        sprintf(temp, "%s %s", processedReply, swapped);
                        free(processedReply);
                        processedReply = temp;
                    }
                    free(swapped);
                }
            }
        }
    }
    
    return processedReply;
}

char* userQuestion(const char* txt) {
    if (!txt) return NULL;
    char* matchedReplies[MAX_MATCHES] = {NULL};
    int matchCount = 0;
    bool found = false;
    char* combinedReply = NULL;

    for (int i = 0; i < g_Key_ReplyCount && matchCount < MAX_MATCHES; i++) {
        for (int j = 0; j < g_Key_Reply[i].keywordCount; j++) {
            if (strstr(txt, g_Key_Reply[i].keywords[j])) {
                int replyIndex = rand() % g_Key_Reply[i].replyCount;
                matchedReplies[matchCount] = safe_strdup(g_Key_Reply[i].replies[replyIndex]);
                matchCount++;
                found = true;
                break;
            }
        }
    }

    if (matchCount > 0) {
        size_t totalLength = 1;  // Start with 1 for the null terminator
        for (int i = 0; i < matchCount; i++) {
            char* processedReply = processReply(matchedReplies[i], txt);
            if (processedReply) {
                totalLength += strlen(processedReply) + 1;  // +1 for newline
                free(matchedReplies[i]);
                matchedReplies[i] = processedReply;
            }
        }

        combinedReply = malloc(totalLength);
        if (combinedReply) {
            combinedReply[0] = '\0';
            for (int i = 0; i < matchCount; i++) {
                if (matchedReplies[i]) {
                    strcat(combinedReply, matchedReplies[i]);
                    strcat(combinedReply, "\n");
                    free(matchedReplies[i]);
                }
            }
        }
    } else if (!found) {
        if (default_reply_count > 0) {
            int defaultIndex = rand() % default_reply_count;
            combinedReply = safe_strdup(default_replies[defaultIndex]);
        }
    }
    
    return combinedReply ? combinedReply : safe_strdup("I don't understand. Can you rephrase that?");
}

char* commands(char* txt) {
    char* isolated = isolatePunctuation(txt);
    for (int i = 0; isolated[i]; i++) {
        isolated[i] = tolower(isolated[i]);
    }
    
    char* response = userQuestion(isolated);
    
    free(isolated);
    return response;
}

void speak(const char* text) {
    char command[MAX_STRING_LENGTH * 2];
    snprintf(command, sizeof(command), "voice -r -1 -n \"Microsoft David Desktop\" \"%s\"", text);
    system(command);
}

int main() {
    srand(time(NULL));
    
    loadArrays("database.txt");
    loadSwapWords("swapwords.txt");
    
	printf("CHATBOT DANNY IN C PROGRAMMING LANGUAGE VERSION 1.1.6.5 (C) RON77\n");
	
    char input[MAX_STRING_LENGTH];
    char* response;
    
    while (1) {
        printf("> ");
        if (fgets(input, sizeof(input), stdin) == NULL) {
            break;
        }
        input[strcspn(input, "\n")] = 0;  // Remove newline
        
        if (strcmp(input, "quit") == 0) break;
        
        response = commands(input);
        
        if (response) {
            // Split the response into separate lines and speak each one
            char* line = strtok(response, "\n");
            while (line != NULL) {
                printf("%s\n", line);
                speak(line);
                line = strtok(NULL, "\n");
            }
            
            free(response);
        } else {
            printf("An error occurred while processing your input.\n");
        }
    }
    
    return 0;
}

You cannot view this attachment.

You cannot view this attachment.

this chatbot used 'voice.exe' TTS cli engine wrapper on windows...

https://elifulkerson.com/projects/commandline-text-to-speech.php