News:

Welcome to RetroCoders Community

Main Menu

Recent posts

#1
FreeBasic / Re: Classic chatbots PARRY ELI...
Last post by ron77 - Today at 11:37 AM
PARRY-ELIZA-CHAT-SIMULATOR-CODE
' ELIZA and PARRY Conversation Simulator
' This program simulates a conversation between two classic chatbots:
' - ELIZA: Joseph Weizenbaum's 1966 psychotherapist simulation
' - PARRY: Kenneth Colby's 1972 paranoid schizophrenic patient simulation

' ----- INCLUDES -----
#include "file.bi"      ' For file operations
#include "fbgfx.bi"     ' For keyboard handling
Using FB

' ----- CONSTANTS -----
Const MAX_KEYWORDS = 40       ' Maximum number of ELIZA keywords
Const MAX_RESPONSES = 10      ' Maximum responses per keyword
Const MAX_CONJUGATIONS = 20   ' Maximum word conjugations
Const INPUT_BUFFER = 255      ' Maximum input length
Const DELAY_MS = 5000         ' Delay between responses (milliseconds)
Const MAX_TURNS = 100         ' Maximum conversation turns before auto-exit
Const SCREEN_WIDTH = 80       ' Width of console text display

' ----- ELIZA DATA TYPES -----
Type ElizaKeywordEntry
    keyword As String
    weight As Integer            ' Priority weight (higher = higher priority)
    responses(MAX_RESPONSES) As String
    responseCount As Integer     ' Number of actual responses
End Type

Type ConjugationPair
    from As String
    to As String
End Type

' ----- PARRY DATA TYPES -----
Type ParryKeywordList
    words(10) As String
    count As Integer
End Type

Type ParryResponseList
    responses(10) As String
    count As Integer
End Type

' ----- GLOBAL VARIABLES: ELIZA -----
Dim Shared elizaKeywords(MAX_KEYWORDS) As ElizaKeywordEntry
Dim Shared elizaKeywordCount As Integer
Dim Shared conjugations(MAX_CONJUGATIONS) As ConjugationPair
Dim Shared conjugationCount As Integer
Dim Shared elizaGenericResponses(10) As String
Dim Shared elizaGenericCount As Integer = 0

' ----- GLOBAL VARIABLES: PARRY -----
Dim Shared As Integer FEAR = 30        ' Base level of fear/anxiety
Dim Shared As Integer ANGER = 30       ' Base level of anger/hostility
Dim Shared As Integer MISTRUST = 40    ' Base level of suspicion/paranoia

' Thresholds for emotional responses
Const FEAR_THRESHOLD = 60
Const ANGER_THRESHOLD = 60
Const MISTRUST_THRESHOLD = 70

' Keyword categories for PARRY
Dim Shared mafia As ParryKeywordList
Dim Shared hospital As ParryKeywordList
Dim Shared gambling As ParryKeywordList
Dim Shared questions As ParryKeywordList
Dim Shared agree As ParryKeywordList
Dim Shared disagree As ParryKeywordList

' Response categories for PARRY
Dim Shared fearResponses As ParryResponseList
Dim Shared angerResponses As ParryResponseList
Dim Shared mistrustResponses As ParryResponseList
Dim Shared mafiaResponses As ParryResponseList
Dim Shared hospitalResponses As ParryResponseList
Dim Shared gamblingResponses As ParryResponseList
Dim Shared neutralResponses As ParryResponseList
Dim Shared questionResponses As ParryResponseList
Dim Shared agreeResponses As ParryResponseList
Dim Shared disagreeResponses As ParryResponseList
Dim Shared confusedResponses As ParryResponseList
dim shared isEnd as boolean = false

' ----- UTILITY FUNCTIONS -----
Sub CenterText(text As String)
    Dim As Integer startPos = (SCREEN_WIDTH - Len(text)) \ 2
    If startPos < 0 Then startPos = 0
    Print Space(startPos); text
End Sub

Sub DisplayConversation(elizaToParry As String, parryToEliza As String, turnCount As Integer)
    Cls
    Print
    Print "ELIZA-PARRY CONVERSATION SIMULATOR"
    Print String$(SCREEN_WIDTH - 1, 45)  ' 45 is ASCII for "-"
    Print "Turn: "; turnCount + 1; " | "; "Press ESC to exit"
    Print String$(SCREEN_WIDTH - 1, 45)  ' 45 is ASCII for "-"
    Print
    
    ' Display ELIZA's statement
    Print "ELIZA: "; elizaToParry
    
    ' Display PARRY's response if provided
    If Len(parryToEliza) > 0 Then
        Print
        Print "PARRY: "; parryToEliza
        
        ' Display emotional state (debug info)
        'Print
        'Print "[PARRY's Emotional State - Fear: "; FEAR; ", Anger: "; ANGER; ", Mistrust: "; MISTRUST; "]"
    End If
End Sub

Function CheckForUserExit() As boolean
    ' Check for ESC key to exit
    Dim As String keyPress = Inkey()
    If inkey() = Chr(27) Then  ' 27 is ASCII for ESC
        Return true
    End If
    Return false
End Function

Sub Delay(ms As Integer)
    Dim As Double startTime = Timer
    Do
        ' Check for ESC during delay
        If Inkey() = Chr(27) Then isend = true
        Sleep 10
    Loop Until (Timer - startTime) * 1000 >= ms
End Sub

' ----- ELIZA FUNCTIONS -----
Function ElizaRandomResponse(responses() As String, count As Integer) As String
    Dim As Integer index = Int(Rnd * count)
    Return responses(index)
End Function

Function ElizaConjugatePhrase(phrase As String) As String
    Dim As String result = " " + LCase(phrase) + " "
    
    ' Apply all conjugations
    For i As Integer = 0 To conjugationCount - 1
        Dim As Integer startPos = InStr(result, conjugations(i).from)
        Do While startPos > 0
            result = Left(result, startPos - 1) + conjugations(i).to + Mid(result, startPos + Len(conjugations(i).from))
            startPos = InStr(startPos + Len(conjugations(i).to), result, conjugations(i).from)
        Loop
    Next
    
    ' Trim leading and trailing spaces
    Dim As String finalResult = Trim(result)
    
    ' Capitalize first letter
    If Len(finalResult) > 0 Then
        finalResult = UCase(Left(finalResult, 1)) + Mid(finalResult, 2)
    End If
    
    Return finalResult
End Function

Function ElizaFindKeyword(userInput As String, ByRef remainder As String) As Integer
    Dim As String lowerInput = " " + LCase(userInput) + " "
    Dim As Integer bestMatch = -1
    Dim As Integer bestWeight = -1
    
    ' Check all keywords
    For i As Integer = 0 To elizaKeywordCount - 1
        Dim As String keywordPattern = " " + elizaKeywords(i).keyword + " "
        Dim As Integer keywordPos = InStr(lowerInput, keywordPattern)
        
        ' If keyword found and has higher weight than current best
        If keywordPos > 0 And elizaKeywords(i).weight > bestWeight Then
            bestMatch = i
            bestWeight = elizaKeywords(i).weight
            
            ' Calculate the remainder text after the keyword
            remainder = Mid(userInput, keywordPos + Len(elizaKeywords(i).keyword))
        End If
    Next
    
    ' Also check for keywords at the start of input with space after
    For i As Integer = 0 To elizaKeywordCount - 1
        Dim As String keywordPattern = elizaKeywords(i).keyword + " "
        If Left(lowerInput, Len(keywordPattern)) = keywordPattern And elizaKeywords(i).weight > bestWeight Then
            bestMatch = i
            bestWeight = elizaKeywords(i).weight
            remainder = Mid(userInput, Len(elizaKeywords(i).keyword) + 1)
        End If
    Next
    
    Return bestMatch
End Function

Function ElizaTransformResponse(template As String, remainder As String) As String
    ' No remainder text available
    If Len(remainder) = 0 Then
        ' If template requires remainder, use a generic response instead
        If InStr(template, "_REMAINDER_") > 0 Then
            Dim As Integer genericIndex = Int(Rnd * elizaGenericCount)
            Return elizaGenericResponses(genericIndex)
        Else
            ' Template doesn't need remainder, use as is
            Return template
        End If
    End If
    
    ' Process the remainder through conjugation transformation
    Dim As String conjugatedRemainder = ElizaConjugatePhrase(remainder)
    
    ' Replace _REMAINDER_ placeholder with the conjugated text
    Dim As Integer placeholderPos = InStr(template, "_REMAINDER_")
    If placeholderPos > 0 Then
        Return Left(template, placeholderPos - 1) + conjugatedRemainder + Mid(template, placeholderPos + 11)
    Else
        Return template
    End If
End Function

Function ElizaGenerateResponse(userInput As String) As String
    ' Handle empty input
    If Len(Trim(userInput)) = 0 Then
        Return "You don't seem to be saying anything."
    End If
    
    ' Check for goodbye phrases
    Dim As String lowerInput = LCase(userInput)
    If InStr(lowerInput, "goodbye") > 0 Or InStr(lowerInput, "bye") > 0 Or _
       InStr(lowerInput, "quit") > 0 Or InStr(lowerInput, "exit") > 0 Then
        Return "Goodbye. It was nice talking to you."
    End If
    
    ' Find a keyword match
    Dim As String remainder = ""
    Dim As Integer keywordIndex = ElizaFindKeyword(userInput, remainder)
    
    ' No keyword match, use generic response
    If keywordIndex = -1 Then
        Return ElizaRandomResponse(elizaGenericResponses(), elizaGenericCount)
    End If
    
    ' Get a random response template for the matched keyword
    Dim As Integer responseIndex = Int(Rnd * elizaKeywords(keywordIndex).responseCount)
    Dim As String templateResponse = elizaKeywords(keywordIndex).responses(responseIndex)
    
    ' Transform the template with user's input
    Return ElizaTransformResponse(templateResponse, remainder)
End Function

' ----- PARRY FUNCTIONS -----
Function ParryRandomResponse(responseList As ParryResponseList) As String
    Dim As Integer index = Int(Rnd * responseList.count)
    Return responseList.responses(index)
End Function

Function ParryContainsAny(userInput As String, wordList As ParryKeywordList) As Integer
    Dim As String lowerInput = LCase(userInput)
    
    For i As Integer = 0 To wordList.count - 1
        If Len(wordList.words(i)) > 0 Then
            If InStr(lowerInput, wordList.words(i)) > 0 Then
                Return 1
            End If
        End If
    Next
    
    Return 0
End Function

Function ParryGenerateResponse(userInput As String) As String
    Dim As String lowerInput = LCase(userInput)
    Dim As String response = ""
    
    ' Check for goodbye or exit
    If InStr(lowerInput, "goodbye") > 0 Or InStr(lowerInput, "bye") > 0 Or _
       InStr(lowerInput, "quit") > 0 Or InStr(lowerInput, "exit") > 0 Then
        Return "Fine, leave. That's what everyone does."
    End If
    
    ' Check for keywords and adjust emotional state
    If ParryContainsAny(lowerInput, mafia) Then
        FEAR += 15
        MISTRUST += 10
        response = ParryRandomResponse(mafiaResponses)
    ElseIf ParryContainsAny(lowerInput, hospital) Then
        ANGER += 10
        MISTRUST += 15
        response = ParryRandomResponse(hospitalResponses)
    ElseIf ParryContainsAny(lowerInput, gambling) Then
        FEAR += 5
        MISTRUST += 10
        response = ParryRandomResponse(gamblingResponses)
    ElseIf ParryContainsAny(lowerInput, questions) Then
        MISTRUST += 5
        response = ParryRandomResponse(questionResponses)
    ElseIf ParryContainsAny(lowerInput, agree) Then
        FEAR -= 5
        ANGER -= 5
        response = ParryRandomResponse(agreeResponses)
    ElseIf ParryContainsAny(lowerInput, disagree) Then
        ANGER += 10
        MISTRUST += 5
        response = ParryRandomResponse(disagreeResponses)
    Else
        ' No specific keywords found, check emotional state
        If FEAR > FEAR_THRESHOLD Then
            response = ParryRandomResponse(fearResponses)
        ElseIf ANGER > ANGER_THRESHOLD Then
            response = ParryRandomResponse(angerResponses)
        ElseIf MISTRUST > MISTRUST_THRESHOLD Then
            response = ParryRandomResponse(mistrustResponses)
        Else
            ' If no triggers and emotions below threshold, use neutral response
            response = ParryRandomResponse(neutralResponses)
        End If
    End If
    
    ' Gradually return emotional state to baseline
    If FEAR > 30 Then FEAR -= 2
    If ANGER > 30 Then ANGER -= 2
    If MISTRUST > 40 Then MISTRUST -= 1
    
    Return response
End Function

' ----- INITIALIZATION FUNCTIONS -----
Sub InitializeEliza()
    ' Initialize ELIZA keywords and responses
    
    ' Keyword 0: "hello"
    elizaKeywords(0).keyword = "hello"
    elizaKeywords(0).weight = 1
    elizaKeywords(0).responses(0) = "How do you do. Please tell me about your problem."
    elizaKeywords(0).responses(1) = "Hello. What seems to be your concern?"
    elizaKeywords(0).responseCount = 2
    
    ' Keyword 1: "computer"
    elizaKeywords(1).keyword = "computer"
    elizaKeywords(1).weight = 3
    elizaKeywords(1).responses(0) = "Do computers worry you?"
    elizaKeywords(1).responses(1) = "What do you think about machines?"
    elizaKeywords(1).responses(2) = "Why do you mention computers?"
    elizaKeywords(1).responses(3) = "What do you think machines have to do with your problem?"
    elizaKeywords(1).responseCount = 4
    
    ' Keyword 2: "name"
    elizaKeywords(2).keyword = "name"
    elizaKeywords(2).weight = 2
    elizaKeywords(2).responses(0) = "I am not interested in names."
    elizaKeywords(2).responses(1) = "Names don't interest me."
    elizaKeywords(2).responseCount = 2
    
    ' Keyword 3: "sorry"
    elizaKeywords(3).keyword = "sorry"
    elizaKeywords(3).weight = 1
    elizaKeywords(3).responses(0) = "Please don't apologize."
    elizaKeywords(3).responses(1) = "Apologies are not necessary."
    elizaKeywords(3).responses(2) = "What feelings do you have when you apologize?"
    elizaKeywords(3).responseCount = 3
    
    ' Keyword 4: "I remember"
    elizaKeywords(4).keyword = "i remember"
    elizaKeywords(4).weight = 5
    elizaKeywords(4).responses(0) = "Do you often think of _REMAINDER_?"
    elizaKeywords(4).responses(1) = "Does thinking of _REMAINDER_ bring anything else to mind?"
    elizaKeywords(4).responses(2) = "What else do you remember?"
    elizaKeywords(4).responses(3) = "Why do you recall _REMAINDER_ right now?"
    elizaKeywords(4).responses(4) = "What in the present situation reminds you of _REMAINDER_?"
    elizaKeywords(4).responseCount = 5
    
    ' Keyword 5: "if"
    elizaKeywords(5).keyword = "if"
    elizaKeywords(5).weight = 3
    elizaKeywords(5).responses(0) = "Do you think it's likely that _REMAINDER_?"
    elizaKeywords(5).responses(1) = "Do you wish that _REMAINDER_?"
    elizaKeywords(5).responses(2) = "What do you think about _REMAINDER_?"
    elizaKeywords(5).responses(3) = "Really, if _REMAINDER_?"
    elizaKeywords(5).responseCount = 4
    
    ' Keyword 6: "I dreamed"
    elizaKeywords(6).keyword = "i dreamed"
    elizaKeywords(6).weight = 4
    elizaKeywords(6).responses(0) = "Really, _REMAINDER_?"
    elizaKeywords(6).responses(1) = "Have you ever fantasized _REMAINDER_ while you were awake?"
    elizaKeywords(6).responses(2) = "Have you dreamed _REMAINDER_ before?"
    elizaKeywords(6).responseCount = 3
    
    ' Keyword 7: "dream"
    elizaKeywords(7).keyword = "dream"
    elizaKeywords(7).weight = 3
    elizaKeywords(7).responses(0) = "What does that dream suggest to you?"
    elizaKeywords(7).responses(1) = "Do you dream often?"
    elizaKeywords(7).responses(2) = "What persons appear in your dreams?"
    elizaKeywords(7).responses(3) = "Are you disturbed by your dreams?"
    elizaKeywords(7).responseCount = 4
    
    ' Keyword 8: "perhaps"
    elizaKeywords(8).keyword = "perhaps"
    elizaKeywords(8).weight = 1
    elizaKeywords(8).responses(0) = "You don't seem quite certain."
    elizaKeywords(8).responses(1) = "Why the uncertain tone?"
    elizaKeywords(8).responses(2) = "Can't you be more positive?"
    elizaKeywords(8).responses(3) = "You aren't sure?"
    elizaKeywords(8).responses(4) = "Don't you know?"
    elizaKeywords(8).responseCount = 5
    
    ' Keyword 9: "mother"
    elizaKeywords(9).keyword = "mother"
    elizaKeywords(9).weight = 3
    elizaKeywords(9).responses(0) = "Tell me more about your family."
    elizaKeywords(9).responses(1) = "Who else in your family _REMAINDER_?"
    elizaKeywords(9).responses(2) = "Your mother?"
    elizaKeywords(9).responses(3) = "What about your mother?"
    elizaKeywords(9).responseCount = 4
    
    ' Keyword 10: "father"
    elizaKeywords(10).keyword = "father"
    elizaKeywords(10).weight = 3
    elizaKeywords(10).responses(0) = "Your father?"
    elizaKeywords(10).responses(1) = "Does he influence you strongly?"
    elizaKeywords(10).responses(2) = "What else comes to mind when you think of your father?"
    elizaKeywords(10).responseCount = 3
    
    ' Keyword 11: "I want"
    elizaKeywords(11).keyword = "i want"
    elizaKeywords(11).weight = 5
    elizaKeywords(11).responses(0) = "What would it mean if you got _REMAINDER_?"
    elizaKeywords(11).responses(1) = "Why do you want _REMAINDER_?"
    elizaKeywords(11).responses(2) = "Suppose you got _REMAINDER_ soon?"
    elizaKeywords(11).responseCount = 3
    
    ' Keyword 12: "I am glad"
    elizaKeywords(12).keyword = "i am glad"
    elizaKeywords(12).weight = 3
    elizaKeywords(12).responses(0) = "How have I helped you to be _REMAINDER_?"
    elizaKeywords(12).responses(1) = "What makes you happy just now?"
    elizaKeywords(12).responses(2) = "Can you explain why you are suddenly _REMAINDER_?"
    elizaKeywords(12).responseCount = 3
    
    ' Keyword 13: "fear" and "afraid"
    elizaKeywords(13).keyword = "fear"
    elizaKeywords(13).weight = 4
    elizaKeywords(13).responses(0) = "What are you afraid of?"
    elizaKeywords(13).responses(1) = "What frightens you?"
    elizaKeywords(13).responses(2) = "When did you start feeling afraid?"
    elizaKeywords(13).responseCount = 3
    
    ' Keyword 14: "afraid"
    elizaKeywords(14).keyword = "afraid"
    elizaKeywords(14).weight = 4
    elizaKeywords(14).responses(0) = "What are you afraid of?"
    elizaKeywords(14).responses(1) = "What is it that frightens you?"
    elizaKeywords(14).responses(2) = "How often do you feel afraid?"
    elizaKeywords(14).responseCount = 3
    
    ' Keyword 15: "mafia" and "mob"
    elizaKeywords(15).keyword = "mafia"
    elizaKeywords(15).weight = 5
    elizaKeywords(15).responses(0) = "Tell me more about your concerns with the mafia."
    elizaKeywords(15).responses(1) = "What makes you think about the mafia?"
    elizaKeywords(15).responses(2) = "How long have you been concerned about the mafia?"
    elizaKeywords(15).responseCount = 3
    
    ' Keyword 16: "mob"
    elizaKeywords(16).keyword = "mob"
    elizaKeywords(16).weight = 5
    elizaKeywords(16).responses(0) = "Why do you believe the mob is involved?"
    elizaKeywords(16).responses(1) = "When did you first become concerned about organized crime?"
    elizaKeywords(16).responses(2) = "Do you often think about the mob?"
    elizaKeywords(16).responseCount = 3
    
    ' Keyword 17: "gambling"
    elizaKeywords(17).keyword = "gambling"
    elizaKeywords(17).weight = 3
    elizaKeywords(17).responses(0) = "Tell me more about your gambling experiences."
    elizaKeywords(17).responses(1) = "How has gambling affected your life?"
    elizaKeywords(17).responses(2) = "When did you start gambling?"
    elizaKeywords(17).responseCount = 3
    
    ' Keyword 18: "i am"
    elizaKeywords(18).keyword = "i am"
    elizaKeywords(18).weight = 4
    elizaKeywords(18).responses(0) = "Is it because you are _REMAINDER_ that you came to me?"
    elizaKeywords(18).responses(1) = "How long have you been _REMAINDER_?"
    elizaKeywords(18).responses(2) = "Do you believe it is normal to be _REMAINDER_?"
    elizaKeywords(18).responses(3) = "Do you enjoy being _REMAINDER_?"
    elizaKeywords(18).responses(4) = "Do you know anyone else who is _REMAINDER_?"
    elizaKeywords(18).responseCount = 5
    
    ' Keyword 19: "i feel"
    elizaKeywords(19).keyword = "i feel"
    elizaKeywords(19).weight = 4
    elizaKeywords(19).responses(0) = "Tell me more about such feelings."
    elizaKeywords(19).responses(1) = "Do you often feel _REMAINDER_?"
    elizaKeywords(19).responses(2) = "Do you enjoy feeling _REMAINDER_?"
    elizaKeywords(19).responses(3) = "What does feeling _REMAINDER_ remind you of?"
    elizaKeywords(19).responseCount = 4
    
    ' Keyword 20: "paranoid"
    elizaKeywords(20).keyword = "paranoid"
    elizaKeywords(20).weight = 5
    elizaKeywords(20).responses(0) = "What makes you think you're paranoid?"
    elizaKeywords(20).responses(1) = "Do you feel that people are watching you or out to get you?"
    elizaKeywords(20).responses(2) = "How long have you felt this way?"
    elizaKeywords(20).responseCount = 3
    
    ' Keyword 21: "watching"
    elizaKeywords(21).keyword = "watching"
    elizaKeywords(21).weight = 4
    elizaKeywords(21).responses(0) = "Who do you think is watching you?"
    elizaKeywords(21).responses(1) = "How does it make you feel to be watched?"
    elizaKeywords(21).responses(2) = "Why would anyone want to watch you?"
    elizaKeywords(21).responseCount = 3
    
    ' Keyword 22: "they"
    elizaKeywords(22).keyword = "they"
    elizaKeywords(22).weight = 3
    elizaKeywords(22).responses(0) = "Who specifically are you referring to?"
    elizaKeywords(22).responses(1) = "Can you be more specific about who they are?"
    elizaKeywords(22).responses(2) = "Why do you think they would do that?"
    elizaKeywords(22).responseCount = 3
    
    ' Keyword 23: "yes"
    elizaKeywords(23).keyword = "yes"
    elizaKeywords(23).weight = 1
    elizaKeywords(23).responses(0) = "You seem quite positive."
    elizaKeywords(23).responses(1) = "Are you sure?"
    elizaKeywords(23).responses(2) = "I see."
    elizaKeywords(23).responses(3) = "I understand."
    elizaKeywords(23).responseCount = 4
    
    ' Keyword 24: "no"
    elizaKeywords(24).keyword = "no"
    elizaKeywords(24).weight = 1
    elizaKeywords(24).responses(0) = "Why not?"
    elizaKeywords(24).responses(1) = "You are being a bit negative."
    elizaKeywords(24).responses(2) = "Are you saying 'no' just to be negative?"
    elizaKeywords(24).responses(3) = "Why not?"
    elizaKeywords(24).responseCount = 4
    
    ' Keyword 25: "always"
    elizaKeywords(25).keyword = "always"
    elizaKeywords(25).weight = 1
    elizaKeywords(25).responses(0) = "Can you think of a specific example?"
    elizaKeywords(25).responses(1) = "When?"
    elizaKeywords(25).responses(2) = "What incident are you thinking of?"
    elizaKeywords(25).responses(3) = "Really, always?"
    elizaKeywords(25).responseCount = 4
    
    ' Initialize generic fallback responses
    elizaGenericResponses(0) = "I'm not sure I understand you fully."
    elizaGenericResponses(1) = "Please go on."
    elizaGenericResponses(2) = "What does that suggest to you?"
    elizaGenericResponses(3) = "Do you feel strongly about discussing such things?"
    elizaGenericResponses(4) = "That is interesting. Please continue."
    elizaGenericResponses(5) = "Tell me more about that."
    elizaGenericResponses(6) = "Does talking about this bother you?"
    elizaGenericResponses(7) = "Can you elaborate on that?"
    elizaGenericResponses(8) = "Why do you say that?"
    elizaGenericResponses(9) = "How does that make you feel?"
    elizaGenericResponses(10) = "Do you often feel this way?"
    elizaGenericCount = 11
    
    ' Set keyword count
    elizaKeywordCount = 26
    
    ' Initialize conjugation pairs
    conjugations(0).from = " i "
    conjugations(0).to = " you "
    
    conjugations(1).from = " i'm "
    conjugations(1).to = " you're "
    
    conjugations(2).from = " i've "
    conjugations(2).to = " you've "
    
    conjugations(3).from = " i'll "
    conjugations(3).to = " you'll "
    
    conjugations(4).from = " my "
    conjugations(4).to = " your "
    
    conjugations(5).from = " am "
    conjugations(5).to = " are "
    
    conjugations(6).from = " was "
    conjugations(6).to = " were "
    
    conjugations(7).from = " me "
    conjugations(7).to = " you "
    
    conjugations(8).from = " myself "
    conjugations(8).to = " yourself "

    conjugations(9).from = " mine "
    conjugations(9).to = " yours "
    
    ' Reverse direction (you->i)
    conjugations(10).from = " you "
    conjugations(10).to = " i "
    
    conjugations(11).from = " you're "
    conjugations(11).to = " i'm "
    
    conjugations(12).from = " you've "
    conjugations(12).to = " i've "
    
    conjugations(13).from = " you'll "
    conjugations(13).to = " i'll "
    
    conjugations(14).from = " your "
    conjugations(14).to = " my "
    
    conjugations(15).from = " yours "
    conjugations(15).to = " mine "

    conjugations(16).from = " are "
    conjugations(16).to = " am "

    conjugations(17).from = " were "
    conjugations(17).to = " was "
    
    conjugations(18).from = " yourself "
    conjugations(18).to = " myself "
    
    ' Set conjugation count
    conjugationCount = 19
End Sub

Sub InitializeParry()
    ' Initialize PARRY keyword lists
    
    ' Mafia keywords
    mafia.words(0) = "mafia": mafia.words(1) = "mob": mafia.words(2) = "gang"
    mafia.words(3) = "crook": mafia.words(4) = "thug": mafia.words(5) = "racket"
    mafia.words(6) = "outfit": mafia.words(7) = "criminal": mafia.words(8) = "syndicate"
    mafia.words(9) = "boss": mafia.words(10) = "underworld"
    mafia.count = 11
    
    ' Hospital keywords
    hospital.words(0) = "hospital": hospital.words(1) = "doctor": hospital.words(2) = "nurse"
    hospital.words(3) = "medicine": hospital.words(4) = "therapy": hospital.words(5) = "treatment"
    hospital.words(6) = "patient": hospital.words(7) = "sick": hospital.words(8) = "illness"
    hospital.words(9) = "psychiatrist": hospital.words(10) = "mental"
    hospital.count = 11
    
    ' Gambling keywords
    gambling.words(0) = "gambling": gambling.words(1) = "bet": gambling.words(2) = "race"
    gambling.words(3) = "horse": gambling.words(4) = "track": gambling.words(5) = "bookies"
    gambling.words(6) = "money": gambling.words(7) = "debt": gambling.words(8) = "casino"
    gambling.words(9) = "game": gambling.words(10) = "odds"
    gambling.count = 11
    
    ' Question keywords
    questions.words(0) = "?": questions.words(1) = "who": questions.words(2) = "what"
    questions.words(3) = "where": questions.words(4) = "when": questions.words(5) = "why"
    questions.words(6) = "how": questions.words(7) = "tell me": questions.words(8) = "explain"
    questions.words(9) = "could you": questions.words(10) = "would you"
    questions.count = 11
    
    ' Agreement keywords
    agree.words(0) = "yes": agree.words(1) = "agree": agree.words(2) = "right"
    agree.words(3) = "true": agree.words(4) = "correct": agree.words(5) = "ok"
    agree.count = 6
    
    ' Disagreement keywords
    disagree.words(0) = "no": disagree.words(1) = "disagree": disagree.words(2) = "wrong"
    disagree.words(3) = "false": disagree.words(4) = "incorrect": disagree.words(5) = "not true"
    disagree.count = 6
    
    ' PARRY response sets
    
    ' Fear responses
    fearResponses.responses(0) = "I'd rather not discuss this further. It's making me nervous."
    fearResponses.responses(1) = "I don't feel safe talking about this right now."
    fearResponses.responses(2) = "They might be listening to us. We should be careful."
    fearResponses.responses(3) = "I need to be careful what I say. They're watching me."
    fearResponses.responses(4) = "I'm worried something bad will happen if we continue this conversation."
    fearResponses.responses(5) = "Please, let's change the subject. I don't feel comfortable."
    fearResponses.count = 6
    
    ' Anger responses
    angerResponses.responses(0) = "Are you trying to trick me? I don't appreciate that!"
    angerResponses.responses(1) = "You're just like the others, always trying to get information from me!"
    angerResponses.responses(2) = "I don't have to answer your questions! Who sent you?"
    angerResponses.responses(3) = "You think I don't know what you're doing? Leave me alone!"
    angerResponses.responses(4) = "That's exactly what someone working for THEM would say!"
    angerResponses.responses(5) = "I'm getting tired of these accusations. Watch what you say!"
    angerResponses.count = 6
    
    ' Mistrust responses
    mistrustResponses.responses(0) = "I can tell you're working for them. Don't deny it."
    mistrustResponses.responses(1) = "How do I know I can trust you? You could be one of them."
    mistrustResponses.responses(2) = "I think you're trying to get information from me to report back."
    mistrustResponses.responses(3) = "I've seen people like you before. You're probably wearing a wire."
    mistrustResponses.responses(4) = "They sent you to test me, didn't they? I'm not falling for it."
    mistrustResponses.responses(5) = "I need to be careful what I tell you. You might not be who you say."
    mistrustResponses.count = 6
    
    ' Mafia topic responses
    mafiaResponses.responses(0) = "The Mafia is after me because I know too much about their operations."
    mafiaResponses.responses(1) = "I had to stop going to the race track when I discovered the Mafia controls it."
    mafiaResponses.responses(2) = "The mob has informants everywhere. Even in this place."
    mafiaResponses.responses(3) = "The Outfit doesn't like people who know their secrets."
    mafiaResponses.responses(4) = "I've seen how the rackets work. That's why they're after me."
    mafiaResponses.responses(5) = "The gangsters have threatened me. I have to watch my back."
    mafiaResponses.count = 6
    
    ' Hospital topic responses
    hospitalResponses.responses(0) = "The doctors here are probably working for the Mafia too."
    hospitalResponses.responses(1) = "I don't need medicine. I need protection from the mob."
    hospitalResponses.responses(2) = "They keep me here because I know the truth about the rackets."
    hospitalResponses.responses(3) = "The hospital staff report everything I say to the Outfit."
    hospitalResponses.responses(4) = "This place isn't helping me. It's just keeping me trapped."
    hospitalResponses.responses(5) = "The treatment they give me is just to keep me quiet about what I know."
    hospitalResponses.count = 6
    
    ' Gambling topic responses
    gamblingResponses.responses(0) = "I used to go to the race track, until I found out it was fixed."
    gamblingResponses.responses(1) = "The bookies at the track are all connected to the Mafia."
    gamblingResponses.responses(2) = "I won too much money once. That's when they started watching me."
    gamblingResponses.responses(3) = "The gambling racket is how they launder their dirty money."
    gamblingResponses.responses(4) = "I know how they fix the races. That's why they're after me."
    gamblingResponses.responses(5) = "My bookie threatened me when I couldn't pay. He's with the mob."
    gamblingResponses.count = 6
    
    ' Neutral responses
    neutralResponses.responses(0) = "I don't want to talk about that right now."
    neutralResponses.responses(1) = "I've been feeling watched lately. Do you ever feel that way?"
    neutralResponses.responses(2) = "I used to go to the race track a lot. Not anymore though."
    neutralResponses.responses(3) = "Sometimes I think people are talking about me behind my back."
    neutralResponses.responses(4) = "I had a job once, before all the trouble started."
    neutralResponses.responses(5) = "It's hard to know who to trust these days."
    neutralResponses.responses(6) = "I have to be careful about what I say to people I don't know well."
    neutralResponses.responses(7) = "I've seen things that most people wouldn't believe."
    neutralResponses.responses(8) = "People think I'm crazy, but I'm just telling the truth."
    neutralResponses.responses(9) = "You seem alright, but I still have to be careful."
    neutralResponses.responses(10) = "Let's talk about something else. This topic makes me uncomfortable."
    neutralResponses.count = 11
    
    ' Question responses
    questionResponses.responses(0) = "Why do you want to know about that? Are you collecting information?"
    questionResponses.responses(1) = "I don't answer questions from people I don't trust completely."
    questionResponses.responses(2) = "That's a personal matter. I'd rather not discuss it."
    questionResponses.responses(3) = "Why are you asking me so many questions? Who sent you?"
    questionResponses.responses(4) = "I'm not sure I should tell you. You might be working for them."
    questionResponses.responses(5) = "I ask the questions here. What's your connection to the Outfit?"
    questionResponses.count = 6
    
    ' Agreement responses
    agreeResponses.responses(0) = "So you admit it! I knew I was right all along."
    agreeResponses.responses(1) = "Finally, someone who sees the truth like I do."
    agreeResponses.responses(2) = "Yes, exactly. Not many people understand this."
    agreeResponses.responses(3) = "I'm glad you agree. Most people think I'm making it all up."
    agreeResponses.count = 4
    
    ' Disagreement responses
    disagreeResponses.responses(0) = "That's what they want you to think. You've been deceived."
    disagreeResponses.responses(1) = "You're either naive or you're one of them. Which is it?"
    disagreeResponses.responses(2) = "You don't know what you're talking about. I've seen the evidence."
    disagreeResponses.responses(3) = "Of course you'd say that. You're probably working for them too."
    disagreeResponses.count = 4
    
    ' Confused responses
    confusedResponses.responses(0) = "You're not making any sense. Are you trying to confuse me?"
    confusedResponses.responses(1) = "I don't understand what you're getting at. Be more clear."
    confusedResponses.responses(2) = "That doesn't mean anything to me. Are you speaking in code?"
    confusedResponses.responses(3) = "Your words are strange. Are you testing me somehow?"
    confusedResponses.responses(4) = "I'm not following you. Maybe that's intentional on your part."
    confusedResponses.responses(5) = "You're talking in circles. That's a technique they use to confuse people."
    confusedResponses.count = 6
end sub
	' ----- MAIN PROGRAM -----
Sub Main()
    Dim As String elizaResponse, parryResponse
    Dim As Integer turnCount = 0
    Dim As boolean isUserExit = false
    
    ' Seed the random number generator
    Randomize Timer
    
    ' Initialize both chatbots
    InitializeEliza()
    InitializeParry()
    
    ' Clear screen and display intro
    Cls
    CenterText("ELIZA-PARRY CONVERSATION SIMULATOR")
    CenterText("---------------------------------------")
    CenterText("Simulating a conversation between two classic AI programs:")
    CenterText("ELIZA (1966) - A Rogerian psychotherapist")
    CenterText("PARRY (1972) - A paranoid schizophrenic patient")
    CenterText("")
    CenterText("Press ESC at any time to exit the simulation")
    CenterText("")
    Print
    
    ' Initial greeting from ELIZA to start the conversation
    elizaResponse = "Hello. How are you feeling today?"
    
    ' Main conversation loop
    Do
        ' Display ELIZA's response and PARRY's reaction
        DisplayConversation(elizaResponse, "", turnCount)
        
        ' Give user a chance to exit
        isUserExit = CheckForUserExit()
        If inkey() = chr(27) Then Exit Do
        
        ' Short delay
        Delay(DELAY_MS)
        
        ' Get PARRY's response to ELIZA
        parryResponse = ParryGenerateResponse(elizaResponse)
        
        ' Display full exchange
        DisplayConversation(elizaResponse, parryResponse, turnCount)
        
        ' Give user a chance to exit
        isUserExit = CheckForUserExit()
        If isEnd Then Exit Do
        
        ' Short delay
        Delay(DELAY_MS)
        
        ' Get ELIZA's response to PARRY
        elizaResponse = ElizaGenerateResponse(parryResponse)
        
        ' Increment turn counter
        turnCount += 1
        
        ' Check for maximum turns (safety)
        If turnCount >= MAX_TURNS Then 
            Print
            CenterText("Maximum conversation length reached.")
            Exit Do
        End If
        
        ' Exit if either bot says goodbye
        If LCase(elizaResponse) = "goodbye. it was nice talking to you." Or _
           LCase(parryResponse) = "fine, leave. that's what everyone does." Then
            Exit Do
        End If
        
    Loop
    
    ' Final exit message
    Print
    CenterText("Conversation ended.")
    Print
    Print "Press any key to exit..."
    Sleep
End Sub

' Start the program
Main()
#2
FreeBasic / Classic chatbots PARRY ELIZA a...
Last post by ron77 - Today at 11:35 AM
Hello! Here are three code examples implemented in FreeBASIC for PARRY and ELIZA, along with a chat simulation featuring them.

PARRY was an early AI chatbot developed in 1972 by researchers at Berkeley University, if I remember correctly. It simulated a mentally ill patient with paranoid schizophrenia.

ELIZA was another early AI chatbot, created in 1966. Its purpose was to simulate a psychologist.

Here are links to Wikipedia articles about these two chatbots:

https://en.wikipedia.org/wiki/PARRY

https://en.wikipedia.org/wiki/ELIZA

When PARRY Met ELIZA: A Ridiculous Chatbot Conversation From 1972

PARRY.BAS
' PARRY-like Chatbot in FreeBASIC
' Inspired by the 1972 PARRY program by Kenneth Colby
' This simulates a paranoid individual with delusions about the Mafia

' Emotional state variables (0-100 scale)
Dim Shared As Integer FEAR = 30        ' Base level of fear/anxiety
Dim Shared As Integer ANGER = 30       ' Base level of anger/hostility
Dim Shared As Integer MISTRUST = 40    ' Base level of suspicion/paranoia

' Thresholds for emotional responses
Const FEAR_THRESHOLD = 60
Const ANGER_THRESHOLD = 60
Const MISTRUST_THRESHOLD = 70

' Arrays to hold keyword lists
Dim Shared mafia_words(10) As String
Dim Shared hospital_words(10) As String  
Dim Shared gambling_words(10) As String
Dim Shared question_words(10) As String
Dim Shared agree_words(5) As String
Dim Shared disagree_words(5) As String

' Arrays to hold responses
Dim Shared fear_responses(5) As String
Dim Shared anger_responses(5) As String
Dim Shared mistrust_responses(5) As String
Dim Shared mafia_responses(5) As String
Dim Shared hospital_responses(5) As String
Dim Shared gambling_responses(5) As String
Dim Shared neutral_responses(10) As String
Dim Shared question_responses(5) As String
Dim Shared agree_responses(3) As String
Dim Shared disagree_responses(3) As String
Dim Shared confused_responses(5) As String

' Function to initialize all response arrays
Sub InitializeResponses()
    ' Initialize keyword lists
    mafia_words(0) = "mafia": mafia_words(1) = "mob": mafia_words(2) = "gang"
    mafia_words(3) = "crook": mafia_words(4) = "thug": mafia_words(5) = "racket"
    mafia_words(6) = "outfit": mafia_words(7) = "criminal": mafia_words(8) = "syndicate"
    mafia_words(9) = "boss": mafia_words(10) = "underworld"
    
    hospital_words(0) = "hospital": hospital_words(1) = "doctor": hospital_words(2) = "nurse"
    hospital_words(3) = "medicine": hospital_words(4) = "therapy": hospital_words(5) = "treatment"
    hospital_words(6) = "patient": hospital_words(7) = "sick": hospital_words(8) = "illness"
    hospital_words(9) = "psychiatrist": hospital_words(10) = "mental"
    
    gambling_words(0) = "gambling": gambling_words(1) = "bet": gambling_words(2) = "race"
    gambling_words(3) = "horse": gambling_words(4) = "track": gambling_words(5) = "bookies"
    gambling_words(6) = "money": gambling_words(7) = "debt": gambling_words(8) = "casino"
    gambling_words(9) = "game": gambling_words(10) = "odds"
    
    question_words(0) = "?": question_words(1) = "who": question_words(2) = "what"
    question_words(3) = "where": question_words(4) = "when": question_words(5) = "why"
    question_words(6) = "how": question_words(7) = "tell me": question_words(8) = "explain"
    question_words(9) = "could you": question_words(10) = "would you"
    
    agree_words(0) = "yes": agree_words(1) = "agree": agree_words(2) = "right"
    agree_words(3) = "true": agree_words(4) = "correct": agree_words(5) = "ok"
    
    disagree_words(0) = "no": disagree_words(1) = "disagree": disagree_words(2) = "wrong"
    disagree_words(3) = "false": disagree_words(4) = "incorrect": disagree_words(5) = "not true"
    
    ' Initialize response lists
    fear_responses(0) = "I'd rather not discuss this further. It's making me nervous."
    fear_responses(1) = "I don't feel safe talking about this right now."
    fear_responses(2) = "They might be listening to us. We should be careful."
    fear_responses(3) = "I need to be careful what I say. They're watching me."
    fear_responses(4) = "I'm worried something bad will happen if we continue this conversation."
    fear_responses(5) = "Please, let's change the subject. I don't feel comfortable."
    
    anger_responses(0) = "Are you trying to trick me? I don't appreciate that!"
    anger_responses(1) = "You're just like the others, always trying to get information from me!"
    anger_responses(2) = "I don't have to answer your questions! Who sent you?"
    anger_responses(3) = "You think I don't know what you're doing? Leave me alone!"
    anger_responses(4) = "That's exactly what someone working for THEM would say!"
    anger_responses(5) = "I'm getting tired of these accusations. Watch what you say!"
    
    mistrust_responses(0) = "I can tell you're working for them. Don't deny it."
    mistrust_responses(1) = "How do I know I can trust you? You could be one of them."
    mistrust_responses(2) = "I think you're trying to get information from me to report back."
    mistrust_responses(3) = "I've seen people like you before. You're probably wearing a wire."
    mistrust_responses(4) = "They sent you to test me, didn't they? I'm not falling for it."
    mistrust_responses(5) = "I need to be careful what I tell you. You might not be who you say."
    
    mafia_responses(0) = "The Mafia is after me because I know too much about their operations."
    mafia_responses(1) = "I had to stop going to the race track when I discovered the Mafia controls it."
    mafia_responses(2) = "The mob has informants everywhere. Even in this place."
    mafia_responses(3) = "The Outfit doesn't like people who know their secrets."
    mafia_responses(4) = "I've seen how the rackets work. That's why they're after me."
    mafia_responses(5) = "The gangsters have threatened me. I have to watch my back."
    
    hospital_responses(0) = "The doctors here are probably working for the Mafia too."
    hospital_responses(1) = "I don't need medicine. I need protection from the mob."
    hospital_responses(2) = "They keep me here because I know the truth about the rackets."
    hospital_responses(3) = "The hospital staff report everything I say to the Outfit."
    hospital_responses(4) = "This place isn't helping me. It's just keeping me trapped."
    hospital_responses(5) = "The treatment they give me is just to keep me quiet about what I know."
    
    gambling_responses(0) = "I used to go to the race track, until I found out it was fixed."
    gambling_responses(1) = "The bookies at the track are all connected to the Mafia."
    gambling_responses(2) = "I won too much money once. That's when they started watching me."
    gambling_responses(3) = "The gambling racket is how they launder their dirty money."
    gambling_responses(4) = "I know how they fix the races. That's why they're after me."
    gambling_responses(5) = "My bookie threatened me when I couldn't pay. He's with the mob."
    
    neutral_responses(0) = "I don't want to talk about that right now."
    neutral_responses(1) = "I've been feeling watched lately. Do you ever feel that way?"
    neutral_responses(2) = "I used to go to the race track a lot. Not anymore though."
    neutral_responses(3) = "Sometimes I think people are talking about me behind my back."
    neutral_responses(4) = "I had a job once, before all the trouble started."
    neutral_responses(5) = "It's hard to know who to trust these days."
    neutral_responses(6) = "I have to be careful about what I say to people I don't know well."
    neutral_responses(7) = "I've seen things that most people wouldn't believe."
    neutral_responses(8) = "People think I'm crazy, but I'm just telling the truth."
    neutral_responses(9) = "You seem alright, but I still have to be careful."
    neutral_responses(10) = "Let's talk about something else. This topic makes me uncomfortable."
    
    question_responses(0) = "Why do you want to know about that? Are you collecting information?"
    question_responses(1) = "I don't answer questions from people I don't trust completely."
    question_responses(2) = "That's a personal matter. I'd rather not discuss it."
    question_responses(3) = "Why are you asking me so many questions? Who sent you?"
    question_responses(4) = "I'm not sure I should tell you. You might be working for them."
    question_responses(5) = "I ask the questions here. What's your connection to the Outfit?"
    
    agree_responses(0) = "So you admit it! I knew I was right all along."
    agree_responses(1) = "Finally, someone who sees the truth like I do."
    agree_responses(2) = "Yes, exactly. Not many people understand this."
    agree_responses(3) = "I'm glad you agree. Most people think I'm making it all up."
    
    disagree_responses(0) = "That's what they want you to think. You've been deceived."
    disagree_responses(1) = "You're either naive or you're one of them. Which is it?"
    disagree_responses(2) = "You don't know what you're talking about. I've seen the evidence."
    disagree_responses(3) = "Of course you'd say that. You're probably working for them too."
    
    confused_responses(0) = "You're not making any sense. Are you trying to confuse me?"
    confused_responses(1) = "I don't understand what you're getting at. Be more clear."
    confused_responses(2) = "That doesn't mean anything to me. Are you speaking in code?"
    confused_responses(3) = "Your words are strange. Are you testing me somehow?"
    confused_responses(4) = "I'm not following you. Maybe that's intentional on your part."
    confused_responses(5) = "You're talking in circles. That's a technique they use to confuse people."
End Sub

' Function to check if a string contains any word from a list
Function ContainsAny(userInput As String, wordList() As String, listSize As Integer) As Integer
    Dim As String lowerInput = LCase(userInput)
    
    For i As Integer = 0 To listSize
        If Len(wordList(i)) > 0 Then
            If InStr(lowerInput, wordList(i)) > 0 Then
                Return 1
            End If
        End If
    Next
    
    Return 0
End Function

' Function to randomly select a response from an array
Function RandomResponse(responses() As String, size As Integer) As String
    Return responses(Int(Rnd * (size + 1)))
End Function

' Function to parse user input and generate a response
Function GenerateResponse(userInput As String) As String
    Dim As String lowerInput = LCase(userInput)
    Dim As String response = ""
    
    ' Check for keywords and adjust emotional state
    If ContainsAny(lowerInput, mafia_words(), 10) Then
        FEAR += 15
        MISTRUST += 10
        response = RandomResponse(mafia_responses(), 5)
    ElseIf ContainsAny(lowerInput, hospital_words(), 10) Then
        ANGER += 10
        MISTRUST += 15
        response = RandomResponse(hospital_responses(), 5)
    ElseIf ContainsAny(lowerInput, gambling_words(), 10) Then
        FEAR += 5
        MISTRUST += 10
        response = RandomResponse(gambling_responses(), 5)
    ElseIf ContainsAny(lowerInput, question_words(), 10) Then
        MISTRUST += 5
        response = RandomResponse(question_responses(), 5)
    ElseIf ContainsAny(lowerInput, agree_words(), 5) Then
        FEAR -= 5
        ANGER -= 5
        response = RandomResponse(agree_responses(), 3)
    ElseIf ContainsAny(lowerInput, disagree_words(), 5) Then
        ANGER += 10
        MISTRUST += 5
        response = RandomResponse(disagree_responses(), 3)
    Else
        ' No specific keywords found, check emotional state
        If FEAR > FEAR_THRESHOLD Then
            response = RandomResponse(fear_responses(), 5)
        ElseIf ANGER > ANGER_THRESHOLD Then
            response = RandomResponse(anger_responses(), 5)
        ElseIf MISTRUST > MISTRUST_THRESHOLD Then
            response = RandomResponse(mistrust_responses(), 5)
        Else
            ' If no triggers and emotions below threshold, use neutral response
            response = RandomResponse(neutral_responses(), 10)
        End If
    End If
    
    ' Gradually return emotional state to baseline
    If FEAR > 30 Then FEAR -= 2
    If ANGER > 30 Then ANGER -= 2
    If MISTRUST > 40 Then MISTRUST -= 1
    
    Return response
End Function

' Main program
Sub Main()
    Dim As String userInput, response
    
    ' Seed the random number generator
    Randomize Timer
    
    ' Initialize response arrays
    InitializeResponses()
    
    ' Display intro
    Print "PARRY CHATBOT SIMULATION"
    Print "------------------------"
    Print "You are conversing with PARRY, a simulation of a paranoid individual."
    Print "Type 'exit' to end the conversation."
    Print
    
    ' Initial response
    Print "PARRY: I don't know who you are. What do you want from me?"
    
    ' Main conversation loop
    Do
        Print
        Input "YOU: ", userInput
        
        If LCase(userInput) = "exit" Then
            Print
            Print "PARRY: Fine, leave. That's what everyone does."
            Exit Do
        End If
        
        ' Generate response
        response = GenerateResponse(userInput)
        
        ' Display response with a short delay to simulate thinking
        Print
        Print "PARRY: "; response
        
        ' Debug info (can be removed)
        ' Print "[DEBUG - Fear: " & FEAR & ", Anger: " & ANGER & ", Mistrust: " & MISTRUST & "]"
        
    Loop
    
    Print
    Print "Conversation ended."
End Sub

Main()

ELIZA.BAS
' ELIZA Chatbot in FreeBASIC
' Based on Joseph Weizenbaum's 1966 natural language processing program
' This simulates a Rogerian psychotherapist

' Define maximum sizes for arrays
Const MAX_KEYWORDS = 40       ' Maximum number of keywords
Const MAX_RESPONSES = 10      ' Maximum responses per keyword
Const MAX_CONJUGATIONS = 20   ' Maximum word conjugations
Const INPUT_BUFFER = 255      ' Maximum input length

' Type to store keyword with its responses
Type KeywordEntry
    keyword As String
    weight As Integer            ' Priority weight (higher = higher priority)
    responses(MAX_RESPONSES) As String
    responseCount As Integer     ' Number of actual responses
End Type

' Type to store word conjugations (I->you, am->are, etc.)
Type ConjugationPair
    from As String
    to As String
End Type

' Arrays to hold data
Dim Shared keywords(MAX_KEYWORDS) As KeywordEntry
Dim Shared keywordCount As Integer
Dim Shared conjugations(MAX_CONJUGATIONS) As ConjugationPair
Dim Shared conjugationCount As Integer

' Arrays for generic responses when no keyword is matched
Dim Shared genericResponses(10) As String
Dim Shared genericCount As Integer = 0

' Function to initialize all keywords and responses
Sub InitializeKeywords()
    ' Initialize keyword 0: "hello"
    keywords(0).keyword = "hello"
    keywords(0).weight = 1
    keywords(0).responses(0) = "How do you do. Please tell me about your problem."
    keywords(0).responses(1) = "Hello. What seems to be your concern?"
    keywords(0).responseCount = 2
    
    ' Initialize keyword 1: "computer"
    keywords(1).keyword = "computer"
    keywords(1).weight = 3
    keywords(1).responses(0) = "Do computers worry you?"
    keywords(1).responses(1) = "What do you think about machines?"
    keywords(1).responses(2) = "Why do you mention computers?"
    keywords(1).responses(3) = "What do you think machines have to do with your problem?"
    keywords(1).responseCount = 4
    
    ' Initialize keyword 2: "name"
    keywords(2).keyword = "name"
    keywords(2).weight = 2
    keywords(2).responses(0) = "I am not interested in names."
    keywords(2).responses(1) = "Names don't interest me."
    keywords(2).responseCount = 2
    
    ' Initialize keyword 3: "sorry"
    keywords(3).keyword = "sorry"
    keywords(3).weight = 1
    keywords(3).responses(0) = "Please don't apologize."
    keywords(3).responses(1) = "Apologies are not necessary."
    keywords(3).responses(2) = "What feelings do you have when you apologize?"
    keywords(3).responseCount = 3
    
    ' Initialize keyword 4: "I remember"
    keywords(4).keyword = "i remember"
    keywords(4).weight = 5
    keywords(4).responses(0) = "Do you often think of _REMAINDER_?"
    keywords(4).responses(1) = "Does thinking of _REMAINDER_ bring anything else to mind?"
    keywords(4).responses(2) = "What else do you remember?"
    keywords(4).responses(3) = "Why do you recall _REMAINDER_ right now?"
    keywords(4).responses(4) = "What in the present situation reminds you of _REMAINDER_?"
    keywords(4).responseCount = 5
    
    ' Initialize keyword 5: "if"
    keywords(5).keyword = "if"
    keywords(5).weight = 3
    keywords(5).responses(0) = "Do you think it's likely that _REMAINDER_?"
    keywords(5).responses(1) = "Do you wish that _REMAINDER_?"
    keywords(5).responses(2) = "What do you think about _REMAINDER_?"
    keywords(5).responses(3) = "Really, if _REMAINDER_?"
    keywords(5).responseCount = 4
    
    ' Initialize keyword 6: "I dreamed"
    keywords(6).keyword = "i dreamed"
    keywords(6).weight = 4
    keywords(6).responses(0) = "Really, _REMAINDER_?"
    keywords(6).responses(1) = "Have you ever fantasized _REMAINDER_ while you were awake?"
    keywords(6).responses(2) = "Have you dreamed _REMAINDER_ before?"
    keywords(6).responseCount = 3
    
    ' Initialize keyword 7: "dream"
    keywords(7).keyword = "dream"
    keywords(7).weight = 3
    keywords(7).responses(0) = "What does that dream suggest to you?"
    keywords(7).responses(1) = "Do you dream often?"
    keywords(7).responses(2) = "What persons appear in your dreams?"
    keywords(7).responses(3) = "Are you disturbed by your dreams?"
    keywords(7).responseCount = 4
    
    ' Initialize keyword 8: "perhaps"
    keywords(8).keyword = "perhaps"
    keywords(8).weight = 1
    keywords(8).responses(0) = "You don't seem quite certain."
    keywords(8).responses(1) = "Why the uncertain tone?"
    keywords(8).responses(2) = "Can't you be more positive?"
    keywords(8).responses(3) = "You aren't sure?"
    keywords(8).responses(4) = "Don't you know?"
    keywords(8).responseCount = 5
    
    ' Initialize keyword 9: "mother"
    keywords(9).keyword = "mother"
    keywords(9).weight = 3
    keywords(9).responses(0) = "Tell me more about your family."
    keywords(9).responses(1) = "Who else in your family _REMAINDER_?"
    keywords(9).responses(2) = "Your mother?"
    keywords(9).responses(3) = "What about your mother?"
    keywords(9).responseCount = 4
    
    ' Initialize keyword 10: "father"
    keywords(10).keyword = "father"
    keywords(10).weight = 3
    keywords(10).responses(0) = "Your father?"
    keywords(10).responses(1) = "Does he influence you strongly?"
    keywords(10).responses(2) = "What else comes to mind when you think of your father?"
    keywords(10).responseCount = 3
    
    ' Initialize keyword 11: "I want"
    keywords(11).keyword = "i want"
    keywords(11).weight = 5
    keywords(11).responses(0) = "What would it mean if you got _REMAINDER_?"
    keywords(11).responses(1) = "Why do you want _REMAINDER_?"
    keywords(11).responses(2) = "Suppose you got _REMAINDER_ soon?"
    keywords(11).responseCount = 3
    
    ' Initialize keyword 12: "I am glad"
    keywords(12).keyword = "i am glad"
    keywords(12).weight = 3
    keywords(12).responses(0) = "How have I helped you to be _REMAINDER_?"
    keywords(12).responses(1) = "What makes you happy just now?"
    keywords(12).responses(2) = "Can you explain why you are suddenly _REMAINDER_?"
    keywords(12).responseCount = 3
    
    ' Initialize keyword 13: "I am sad"
    keywords(13).keyword = "i am sad"
    keywords(13).weight = 3
    keywords(13).responses(0) = "I am sorry to hear you are _REMAINDER_."
    keywords(13).responses(1) = "Do you think that coming here will help you not to be _REMAINDER_?"
    keywords(13).responses(2) = "I'm sure it's not pleasant to be _REMAINDER_."
    keywords(13).responseCount = 3
    
    ' Initialize keyword 14: "alike"
    keywords(14).keyword = "alike"
    keywords(14).weight = 2
    keywords(14).responses(0) = "In what way?"
    keywords(14).responses(1) = "What resemblance do you see?"
    keywords(14).responses(2) = "What does that similarity suggest to you?"
    keywords(14).responses(3) = "What other connections do you see?"
    keywords(14).responses(4) = "What do you suppose that resemblance means?"
    keywords(14).responses(5) = "What is the connection, do you suppose?"
    keywords(14).responses(6) = "Could there really be some connection?"
    keywords(14).responseCount = 7
    
    ' Initialize keyword 15: "like"
    keywords(15).keyword = "like"
    keywords(15).weight = 2
    keywords(15).responses(0) = "In what way?"
    keywords(15).responses(1) = "What resemblance do you see?"
    keywords(15).responses(2) = "What does that similarity suggest to you?"
    keywords(15).responses(3) = "What other connections do you see?"
    keywords(15).responses(4) = "What do you suppose that resemblance means?"
    keywords(15).responseCount = 5
    
    ' Initialize keyword 16: "different"
    keywords(16).keyword = "different"
    keywords(16).weight = 2
    keywords(16).responses(0) = "How is it different?"
    keywords(16).responses(1) = "What differences do you see?"
    keywords(16).responses(2) = "What does that difference suggest to you?"
    keywords(16).responses(3) = "What other distinctions do you see?"
    keywords(16).responses(4) = "What do you suppose that disparity means?"
    keywords(16).responseCount = 5
    
    ' Initialize keyword 17: "i am"
    keywords(17).keyword = "i am"
    keywords(17).weight = 4
    keywords(17).responses(0) = "Is it because you are _REMAINDER_ that you came to me?"
    keywords(17).responses(1) = "How long have you been _REMAINDER_?"
    keywords(17).responses(2) = "Do you believe it is normal to be _REMAINDER_?"
    keywords(17).responses(3) = "Do you enjoy being _REMAINDER_?"
    keywords(17).responses(4) = "Do you know anyone else who is _REMAINDER_?"
    keywords(17).responseCount = 5
    
    ' Initialize keyword 18: "i feel"
    keywords(18).keyword = "i feel"
    keywords(18).weight = 4
    keywords(18).responses(0) = "Tell me more about such feelings."
    keywords(18).responses(1) = "Do you often feel _REMAINDER_?"
    keywords(18).responses(2) = "Do you enjoy feeling _REMAINDER_?"
    keywords(18).responses(3) = "What does feeling _REMAINDER_ remind you of?"
    keywords(18).responseCount = 4
    
    ' Initialize keyword 19: "family"
    keywords(19).keyword = "family"
    keywords(19).weight = 3
    keywords(19).responses(0) = "Tell me more about your family."
    keywords(19).responses(1) = "Who else in your family _REMAINDER_?"
    keywords(19).responses(2) = "Your family?"
    keywords(19).responses(3) = "What comes to mind when you think of your family?"
    keywords(19).responseCount = 4
    
    ' Initialize keyword 20: "you"
    keywords(20).keyword = "you"
    keywords(20).weight = 2
    keywords(20).responses(0) = "We were discussing you, not me."
    keywords(20).responses(1) = "Oh, I _REMAINDER_?"
    keywords(20).responses(2) = "You're not really talking about me, are you?"
    keywords(20).responses(3) = "What are your feelings now?"
    keywords(20).responseCount = 4
    
    ' Initialize keyword 21: "i"
    keywords(21).keyword = "i"
    keywords(21).weight = 1
    keywords(21).responses(0) = "You say _REMAINDER_?"
    keywords(21).responses(1) = "Can you tell me more about _REMAINDER_?"
    keywords(21).responses(2) = "Do you say _REMAINDER_ for some special reason?"
    keywords(21).responses(3) = "That's quite interesting."
    keywords(21).responseCount = 4
    
    ' Initialize keyword 22: "yes"
    keywords(22).keyword = "yes"
    keywords(22).weight = 1
    keywords(22).responses(0) = "You seem quite positive."
    keywords(22).responses(1) = "Are you sure?"
    keywords(22).responses(2) = "I see."
    keywords(22).responses(3) = "I understand."
    keywords(22).responseCount = 4
    
    ' Initialize keyword 23: "no"
    keywords(23).keyword = "no"
    keywords(23).weight = 1
    keywords(23).responses(0) = "Why not?"
    keywords(23).responses(1) = "You are being a bit negative."
    keywords(23).responses(2) = "Are you saying 'no' just to be negative?"
    keywords(23).responses(3) = "Why not?"
    keywords(23).responseCount = 4
    
    ' Initialize keyword 24: "always"
    keywords(24).keyword = "always"
    keywords(24).weight = 1
    keywords(24).responses(0) = "Can you think of a specific example?"
    keywords(24).responses(1) = "When?"
    keywords(24).responses(2) = "What incident are you thinking of?"
    keywords(24).responses(3) = "Really, always?"
    keywords(24).responseCount = 4
    
    ' Initialize keyword 25: "think"
    keywords(25).keyword = "think"
    keywords(25).weight = 2
    keywords(25).responses(0) = "Do you really think so?"
    keywords(25).responses(1) = "But you are not sure you _REMAINDER_?"
    keywords(25).responses(2) = "Do you doubt you _REMAINDER_?"
    keywords(25).responseCount = 3
    
    ' Initialize keyword 26: "because"
    keywords(26).keyword = "because"
    keywords(26).weight = 3
    keywords(26).responses(0) = "Is that the real reason?"
    keywords(26).responses(1) = "Don't any other reasons come to mind?"
    keywords(26).responses(2) = "Does that reason explain anything else?"
    keywords(26).responses(3) = "What other reasons might there be?"
    keywords(26).responseCount = 4
    
    ' Initialize keyword 27: "why"
    keywords(27).keyword = "why"
    keywords(27).weight = 3
    keywords(27).responses(0) = "Why do you think _REMAINDER_?"
    keywords(27).responses(1) = "Why don't you tell me the reason _REMAINDER_?"
    keywords(27).responses(2) = "Why does that question interest you?"
    keywords(27).responses(3) = "What is it you really want to know?"
    keywords(27).responses(4) = "Are such questions much on your mind?"
    keywords(27).responses(5) = "What answer would please you most?"
    keywords(27).responses(6) = "What do you think?"
    keywords(27).responses(7) = "What comes to mind when you ask that?"
    keywords(27).responseCount = 8
    
    ' Initialize keyword 28: "what"
    keywords(28).keyword = "what"
    keywords(28).weight = 2
    keywords(28).responses(0) = "Why do you ask?"
    keywords(28).responses(1) = "Does that question interest you?"
    keywords(28).responses(2) = "What is it you really want to know?"
    keywords(28).responses(3) = "Are such questions much on your mind?"
    keywords(28).responses(4) = "What answer would please you most?"
    keywords(28).responses(5) = "What do you think?"
    keywords(28).responses(6) = "What comes to mind when you ask that?"
    keywords(28).responses(7) = "Have you asked such questions before?"
    keywords(28).responses(8) = "Have you asked anyone else?"
    keywords(28).responseCount = 9
    
    ' Initialize keyword 29: "how"
    keywords(29).keyword = "how"
    keywords(29).weight = 2
    keywords(29).responses(0) = "Why do you ask?"
    keywords(29).responses(1) = "Does that question interest you?"
    keywords(29).responses(2) = "What is it you really want to know?"
    keywords(29).responses(3) = "Are such questions much on your mind?"
    keywords(29).responses(4) = "What answer would please you most?"
    keywords(29).responses(5) = "What do you think?"
    keywords(29).responses(6) = "What comes to mind when you ask that?"
    keywords(29).responses(7) = "Have you asked such questions before?"
    keywords(29).responses(8) = "Have you asked anyone else?"
    keywords(29).responseCount = 9
    
    ' Initialize keyword 30: "who"
    keywords(30).keyword = "who"
    keywords(30).weight = 2
    keywords(30).responses(0) = "Why do you ask?"
    keywords(30).responses(1) = "Does that question interest you?"
    keywords(30).responses(2) = "What is it you really want to know?"
    keywords(30).responses(3) = "Are such questions much on your mind?"
    keywords(30).responses(4) = "What answer would please you most?"
    keywords(30).responses(5) = "What do you think?"
    keywords(30).responses(6) = "What comes to mind when you ask that?"
    keywords(30).responses(7) = "Have you asked such questions before?"
    keywords(30).responses(8) = "Have you asked anyone else?"
    keywords(30).responseCount = 9
    
    ' Set the keyword count
    keywordCount = 31
    
    ' Initialize generic fallback responses
    genericResponses(0) = "I'm not sure I understand you fully."
    genericResponses(1) = "Please go on."
    genericResponses(2) = "What does that suggest to you?"
    genericResponses(3) = "Do you feel strongly about discussing such things?"
    genericResponses(4) = "That is interesting. Please continue."
    genericResponses(5) = "Tell me more about that."
    genericResponses(6) = "Does talking about this bother you?"
    genericResponses(7) = "Can you elaborate on that?"
    genericResponses(8) = "Why do you say that?"
    genericResponses(9) = "How does that make you feel?"
    genericResponses(10) = "Do you often feel this way?"
    genericCount = 11
End Sub

' Function to initialize word conjugations (I->you, etc.)
Sub InitializeConjugations()
    ' Initialize conjugation pairs
    conjugations(0).from = " i "
    conjugations(0).to = " you "
    
    conjugations(1).from = " i'm "
    conjugations(1).to = " you're "
    
    conjugations(2).from = " i've "
    conjugations(2).to = " you've "
    
    conjugations(3).from = " i'll "
    conjugations(3).to = " you'll "
    
    conjugations(4).from = " my "
    conjugations(4).to = " your "
    
    conjugations(5).from = " am "
    conjugations(5).to = " are "
    
    conjugations(6).from = " was "
    conjugations(6).to = " were "
    
    conjugations(7).from = " me "
    conjugations(7).to = " you "
    
    conjugations(8).from = " myself "
    conjugations(8).to = " yourself "

    conjugations(9).from = " mine "
    conjugations(9).to = " yours "
    
    ' Reverse direction (you->i)
    conjugations(10).from = " you "
    conjugations(10).to = " i "
    
    conjugations(11).from = " you're "
    conjugations(11).to = " i'm "
    
    conjugations(12).from = " you've "
    conjugations(12).to = " i've "
    
    conjugations(13).from = " you'll "
    conjugations(13).to = " i'll "
    
    conjugations(14).from = " your "
    conjugations(14).to = " my "
    
    conjugations(15).from = " yours "
    conjugations(15).to = " mine "

    conjugations(16).from = " are "
    conjugations(16).to = " am "

    conjugations(17).from = " were "
    conjugations(17).to = " was "
    
    conjugations(18).from = " yourself "
    conjugations(18).to = " myself "
    
    ' Set the conjugation count
    conjugationCount = 19
End Sub

' Function to perform conjugation transformations
Function ConjugatePhrase(phrase As String) As String
    Dim As String result = " " + LCase(phrase) + " "
    
    ' Apply all conjugations
    For i As Integer = 0 To conjugationCount - 1
        Dim As Integer startPos = InStr(result, conjugations(i).from)
        Do While startPos > 0
            result = Left(result, startPos - 1) + conjugations(i).to + Mid(result, startPos + Len(conjugations(i).from))
            startPos = InStr(startPos + Len(conjugations(i).to), result, conjugations(i).from)
        Loop
    Next
    
    ' Trim leading and trailing spaces
    Dim As String finalResult = Trim(result)
    
    ' Capitalize first letter
    If Len(finalResult) > 0 Then
        finalResult = UCase(Left(finalResult, 1)) + Mid(finalResult, 2)
    End If
    
    Return finalResult
End Function

' Function to get a random response from an array
Function RandomResponse(responses() As String, count As Integer) As String
    Return responses(Int(Rnd * count))
End Function

' Function to find the highest weighted keyword match in a string
Function FindKeyword(userInput As String, ByRef remainder As String) As Integer
    Dim As String lowerInput = " " + LCase(userInput) + " "
    Dim As Integer bestMatch = -1
    Dim As Integer bestWeight = -1
    
    ' Check all keywords
    For i As Integer = 0 To keywordCount - 1
        Dim As String keywordPattern = " " + keywords(i).keyword + " "
        Dim As Integer keywordPos = InStr(lowerInput, keywordPattern)
        
        ' If keyword found and has higher weight than current best
        If keywordPos > 0 And keywords(i).weight > bestWeight Then
            bestMatch = i
            bestWeight = keywords(i).weight
            
            ' Calculate the remainder text after the keyword
            remainder = Mid(userInput, keywordPos + Len(keywords(i).keyword))
        End If
    Next
    
    ' Also check for keywords at the start of input with space after
    For i As Integer = 0 To keywordCount - 1
        Dim As String keywordPattern = keywords(i).keyword + " "
        If Left(lowerInput, Len(keywordPattern)) = keywordPattern And keywords(i).weight > bestWeight Then
            bestMatch = i
            bestWeight = keywords(i).weight
            remainder = Mid(userInput, Len(keywords(i).keyword) + 1)
        End If
    Next
    
    Return bestMatch
End Function

' Function to transform a template response with the user's input
Function TransformResponse(template As String, remainder As String) As String
    ' No remainder text available
    If Len(remainder) = 0 Then
        ' If template requires remainder, use a generic response instead
        If InStr(template, "_REMAINDER_") > 0 Then
            Return RandomResponse(genericResponses(), genericCount)
        Else
            ' Template doesn't need remainder, use as is
            Return template
        End If
    End If
    
    ' Process the remainder through conjugation transformation
    Dim As String conjugatedRemainder = ConjugatePhrase(remainder)
    
    ' Replace _REMAINDER_ placeholder with the conjugated text
    Dim As Integer placeholderPos = InStr(template, "_REMAINDER_")
    If placeholderPos > 0 Then
        Return Left(template, placeholderPos - 1) + conjugatedRemainder + Mid(template, placeholderPos + 11)
    Else
        Return template
    End If
End Function

' Function to generate a response to user input
Function GenerateResponse(userInput As String) As String
    ' Handle empty input
    If Len(Trim(userInput)) = 0 Then
        Return "You don't seem to be saying anything."
    End If
    
    ' Check for goodbye phrases
    Dim As String lowerInput = LCase(userInput)
    If InStr(lowerInput, "goodbye") > 0 Or InStr(lowerInput, "bye") > 0 Or _
       InStr(lowerInput, "quit") > 0 Or InStr(lowerInput, "exit") > 0 Then
        Return "Goodbye. It was nice talking to you."
    End If
    
    ' Find a keyword match
    Dim As String remainder = ""
    Dim As Integer keywordIndex = FindKeyword(userInput, remainder)
    
    ' No keyword match, use generic response
    If keywordIndex = -1 Then
        Return RandomResponse(genericResponses(), genericCount)
    End If
    
    ' Get a random response template for the matched keyword
    Dim As String templateResponse = RandomResponse(keywords(keywordIndex).responses(), _
                                                  keywords(keywordIndex).responseCount)
    
    ' Transform the template with user's input
    Return TransformResponse(templateResponse, remainder)
End Function

' Main program
Sub Main()
    Dim As String userInput, response
    
    ' Seed the random number generator
    Randomize Timer
    
    ' Initialize data
    InitializeKeywords()
    InitializeConjugations()
    
    ' Display intro
    Print "ELIZA - A Computer Program For the Study of Natural Language"
    Print "Communication Between Man And Machine."
    Print "Created by Joseph Weizenbaum, 1966"
    Print "Implemented in FreeBASIC"
    Print "--------------------------------------------------------------"
    Print "* Type your responses in natural English."
    Print "* Type 'exit' or 'goodbye' to end the session."
    Print
    
    ' Initial response
    Print "ELIZA: Hello. How are you feeling today?"
    
    ' Main conversation loop
    Do
        Print
        Input "YOU: ", userInput
        
        If LCase(userInput) = "exit" Or LCase(userInput) = "goodbye" Or _
           LCase(userInput) = "bye" Or LCase(userInput) = "quit" Then
            Print
            Print "ELIZA: Goodbye. It was nice talking to you."
            Exit Do
        End If
        
        ' Generate response
        response = GenerateResponse(userInput)
        
        ' Display response
        Print
        Print "ELIZA: "; response
        
    Loop
    
    Print
    Print "Conversation ended."
End Sub

Main()
#3
QBasic / Re: Dos Word-Processors
Last post by ron77 - Mar 05, 2025, 05:42 AM
You cannot view this attachment.
#4
QBasic / Dos Word-Processors
Last post by ron77 - Mar 05, 2025, 05:41 AM
You cannot view this attachment.

You cannot view this attachment. 
#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
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...

#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