Welcome to RetroCoders Community
' 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()
' 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 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()
#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;
}
#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;
}
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(())
}
[package]
name = "rust_trainspotting_II_game"
version = "0.1.0"
edition = "2021"
[dependencies]
rand = "0.8"
bass-sys = "2.1"
anyhow = "1.0"
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(())
}