Talk:2001: An Esolang Odyssey
Jump to navigation
Jump to search
Implementation
This is an implementation in Visual Basic. You can provide a program as input, or, if UseSpecifiedCode is set to true, you can run the code inside the string. Compiling code with UseSpecifiedCode is equivalent to (but not quite) compiling 2001: An Esolang Odyssey. I did try to implement command line arguments for this, but it has not been tested thoroughly and appears to not work the best.
Imports System
Imports System.Collections.Generic
Imports System.Text.RegularExpressions
Imports System.Numerics
Module _2001_AnEsolangOdyssey
Dim Code As New List(Of String)
Dim Left As New Stack(Of Integer)
Dim Right As New Stack(Of Integer)
' ---[DIFFERENCES FROM SPECIFICATION]---
' The original specification says the cells
' should be unbounded, but BigIntegers are
' really weird to deal with in Visual Basic.
'
' Therefore, I have used a 64-bit integer instead,
' which should fulfill most purposes.
Dim Current As Long = 0
Dim MainDepth As Integer = 0
' Set this to True if you want to insert the code
' in the interpreter source (in SpecifiedString),
' False if you want to get the program from console input.
'
' --[NOTES]--
' * Console input programs need to have @End appended to them.
' "Stop, Dave." does not suffice since it can appear in the
' middle of a program.
' * Using True does not make this program a true compiler,
' but makes compiling this program equivalent to compiling
' 2001: An Esolang Odyssey code. You can therefore make
' actual 2001: An Esolang Odyssey executables (.exe).
' Because of this I have provided a way to use command-line
' arguments.
Dim UseSpecifiedCode As Boolean = False
' Set this to True if you want to give the 2001AEO program
' access to command-line arguments.
'
' Command-line arguments are put to the left of
' the starting pointer position, with the
' rightmost character of the rightmost
' argument being the one directly to
' the left of the pointer.
'
' From left to right, the format is:
' * -2 (This provides a marker to allow the code to
' stop at the correct point when trying to find the
' first argument. Ascii codes should never be negative
' numbers, so this provides a valuable marker.
' * Any number of arguments
' * A list of ascii codes of the characters of the argument
' * -1 (Another marker to get to the beginning or end of an argument)
'
' A good way to get to the -2 marker is this code snippet:
' -----------------------------------------------------------
' Hal? Hal! Hal!
' What are you doing, Dave?
' I'm afraid. I'm afraid, Dave. Dave, my mind is going. I can feel it. I can feel it.
' I've picked up a fault in the AE-35 unit.
' Hal? Hal! Hal!
' Dave, this conversation can serve no purpose anymore. Goodbye.
' I'm afraid. I'm afraid, Dave. Dave, my mind is going. I can feel it. I can feel it.
' -----------------------------------------------------------
' That only works if you are to the right of it, but you can replace
' the 4th line in that snippet with
' "Well, he acts like he has genuine emotions." to go from the left instead.
'
' The marker/anchor cell idea is from a video by mitxela on YouTube.
Dim UseCommandLineArgs As Boolean = False
' The specification says to throw an error if the program tries
' to input and hits EOF, but by setting this to false it will input -1 instead.
Dim ThrowErrorOnNoInput As Boolean = True
' Insert your program here if UseSpecifiedCode is True.
Dim SpecifiedString As String =
"Good afternoon, gentlemen. I am a Hello World computer. I became operational at Foobar Lane on May 6th, 2020.
I've picked up a fault in the AE-35 unit.
I've picked up a fault in the AE-35 unit.
Close the pod bay doors, HAL.
Stop, Dave."
Dim SpecifiedCode As List(Of String) = New List(Of String) (SpecifiedString.Split(New Char(){vbCr(0), vbLf(0)}))
Sub Main(Args As String())
If Not UseSpecifiedCode Then
While True
Dim Line As String = Console.ReadLine()
If Line.Equals("@End") Then
Exit While
End If
Code.Add(Line)
End While
End If
If UseSpecifiedCode Then
Code = SpecifiedCode
End If
If Not Regex.IsMatch(Code(0), "Good afternoon\, gentlemen\. I am a .* computer\. I became operational at .* on .*\.") Then
Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Program did not begin with a proper greeting.")
End If
If Not Code(Code.Count - 1).Equals("Stop, Dave.") Then
Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Program did not end with ""Stop, Dave.""")
End If
Dim I = 0
While I < Code.Count
If Code(I).Equals("What are you doing, Dave?") Then
MainDepth += 1
ElseIf Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
MainDepth -= 1
End If
I += 1
End While
If UseCommandLineArgs Then
Left.Push(-2)
For J As Integer = 0 To Args.Length
For K As Integer = 0 To Args(J).Length
Left.Push(AscW(Args(J)(K)))
Next
Left.Push(-1)
Next
End If
MainDepth = 0
I = 0
While I < Code.Count
' Where N is the number of times " Hal!"
' minus the quotes appears at the end of
' this instruction, HAL will increment his
' current cell by N.
If Regex.IsMatch(Code(I), "Hal\?( Hal\!)+") Then
Current = Current + (((Code(I).Length - 4) / 5))
' Where N is the number of times "I can feel it"
' minus the quotes appears at the end
' of this instruction, HAL will decrement
' his current cell by N.
ElseIf Regex.IsMatch(Code(I), "I'm afraid\. I'm afraid\, Dave\. Dave\, my mind is going\.( I can feel it\.)+") Then
Current = Current - (((Code(I).Length - 53) / 15))
' If HAL's current cell is zero, he will
' go to the matching loop end. This is a loop start.
ElseIf Code(I).Equals("What are you doing, Dave?") Then
If Current = 0 Then
Dim Depth = 1
While Depth > 0
I = I + 1
If Code(I).Equals("What are you doing, Dave?") Then
Depth = Depth + 1
End If
If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
Depth = Depth - 1
End If
If I >= Code.Count Then
Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Unmatched loops.")
End If
End While
Else
MainDepth = MainDepth + 1
End If
' If HAL's current cell is nonzero,
' he will go back to the matching
' loop start. This is a loop end.
ElseIf Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
If Not Current = 0 Then
Dim Depth = 1
While Depth > 0
I = I - 1
If Code(I).Equals("What are you doing, Dave?") Then
Depth = Depth - 1
End If
If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
Depth = Depth + 1
End If
If I < 0 Then
Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: Unmatched loops.")
End If
End While
Else
MainDepth = MainDepth - 1
End If
' HAL will break out of the innermost
' two loops he is in (or one or none if
' he isn't in at least two loops).
ElseIf Code(I).Equals("This mission is too important for me to allow you to jeopardize it.") Then
If MainDepth = 0 Then
ElseIf MainDepth = 1 Then
Dim Depth = 1
While Depth > 0
I = I + 1
If Code(I).Equals("What are you doing, Dave?") Then
Depth = Depth + 1
End If
If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
Depth = Depth - 1
End If
End While
Else
Dim Depth = 2
While Depth > 0
I = I + 1
If Code(I).Equals("What are you doing, Dave?") Then
Depth = Depth + 1
End If
If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
Depth = Depth - 1
End If
End While
End If
' HAL will break out of all loops he is currently in.
ElseIf Code(I).Equals("I know I've made some very poor decisions recently, " +
"but I can give you my complete assurance that my wor" +
"k will be back to normal.") Then
Dim Depth = MainDepth
While Depth > 0
I = I + 1
If Code(I).Equals("What are you doing, Dave?") Then
Depth = Depth + 1
End If
If Code(I).Equals("Dave, this conversation can serve no purpose anymore. Goodbye.") Then
Depth = Depth - 1
End If
End While
' HAL will move his cell pointer one cell to the left.
ElseIf Code(I).Equals("I've picked up a fault in the AE-35 unit.") Then
If Left.Count = 0 Then
Left.Push(CInt(0))
End If
Right.Push(Current)
Current = Left.Pop
' HAL will move his cell pointer one cell to the right.
ElseIf Code(I).Equals("Well, he acts like he has genuine emotions.") Then
If Right.Count = 0 Then
Right.Push(CInt(0))
End If
Left.Push(Current)
Current = Right.Pop
' HAL will set his current cell to a user
' input character; no input and an error
' message will be displayed, and he will
' set his current cell to zero, but the
' program will not be terminated.
ElseIf Code(I).Equals("Open the pod bay doors, HAL.") Then
Current = Console.Read()
If ThrowErrorOnNoInput AndAlso Current = -1 Then
Throw New Exception("I'm sorry Dave, I'm afraid I can't do that. [REASON]: EOF reached on input.")
End If
' HAL will output his current cell as a character.
ElseIf Code(I).Equals("Close the pod bay doors, HAL.") Then
Dim OutputChar = ChrW(Current)
Console.Write(OutputChar)
' To write a comment, type
' "Hal_Memory.EntryAdd: "
' (there must be a space at the end).
' This isn't actual code and doesn't mean
' anything, but it fits the AI context.
' You can of course very easily change this
' string to something else in this implementation
' but that would make it even less portable.
'
' --------------------------------------------
' THIS IS NOT IN THE SPECIFICATION,
' AND DEGRADES PORTABILITY.
' --------------------------------------------
ElseIf Code(I).StartsWith("Hal_Memory.EntryAdd: ") Then
Current = Current + 0
' Whitespace only lines or blank lines
' also do nothing, allowing some nice formatting.
' --------------------------------------------
' THIS IS NOT IN THE SPECIFICATION,
' AND DEGRADES PORTABILITY.
' --------------------------------------------
ElseIf Regex.IsMatch(Code(I), "\s*") Then
Current = Current + 0
' Multiline comments can be done with
' "[[" to start and "]]" to end.
' They must be on their own line.
' Usually multiline comment borders
' should not overlap loop borders,
' but there may be use cases for that.
'
' The main thing that will happen when
' overlapping a loop and a comment will
' be that the loop will start running the comment
' if it is valid code and the value is zero,
' and it will break out of the loop prematurely
' if the value is non-zero and skip the comment entirely.
' This can effectively be an if-else construct.
'
' Doing these kinds of things is extremely unstable,
' though, and for these reasons it is a bad idea to
' include lines containing only
' "What are you doing, Dave?"
' or
' "Dave, this conversation can serve no purpose anymore. Goodbye."
' (without quotes)
'
' If you really need those lines in your comment,
' differentiate them in some way like prepending them
' with some symbol.
'
' Break commands should be safe though.
'
' --------------------------------------------
' THIS IS NOT IN THE SPECIFICATION,
' AND DEGRADES PORTABILITY.
' --------------------------------------------
ElseIf Code(I).Equals("[[") Then
While Code(I).Equals("]]")
I += 1
End While
End If
I = I + 1
End While
End Sub
End Module
BoundedBeans (talk) 19:22, 21 August 2022 (UTC)
- I've realized recently that the block of code that says
If UseCommandLineArgsrequires thatThenbe following it. I'm honestly surprised the program even runs at all. I've changed it in the code block above. BoundedBeans (talk) 01:47, 6 December 2022 (UTC)