Piet - Interpreter

Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Neue Antwort erstellen

 

FWeinb

ehemals "ich"

Betreff: Piet - Interpreter

BeitragSa, Jul 18, 2009 21:03
Antworten mit Zitat
Benutzer-Profile anzeigen
Guten Abend,

Ich bin durch die BCC auf Piet aufmerksam geworden und fand das Prinzip dahinter so gut das ich einen Interpreter für BlitzMax geschrieben habe.

Wer sich für die Funktionsweise Interessiert kann sich hier die Dokumentation anschauen:
http://www.dangermouse.net/esoteric/piet.html

Und hier ist ein Beispiel "Programm" welches erklärt wurde:
http://www.retas.de/thomas/com...plain.html


Die Funktionen under der Type:
BlitzMax: [AUSKLAPPEN]

SuperStrict

Global Hex2hue:String[][] = [["FFC0C0", "FFFFC0", "C0FFC0", "C0FFFF", "C0C0FF", "FFC0FF",..
"FF0000", "FFFF00", "00FF00", "00FFFF", "0000FF", "FF00FF",..
"C00000", "C0C000", "00C000", "00C0C0", "0000C0", "C000C0",..
"FFFFFF", "000000"],["0","1","2","3","4","5","0","1","2","3","4","5","0","1","2","3","4","5","-1","-1"]]
Global Light:Int[] = [0,0,0,0,0,0,1,1,1,1,1,1,2,2,2,2,2,2,-1,-1]
Global Color:Int[] = [0,1,2,3,4,5,6,7,8,9,10,11,12,13,14,15,16,17,18,19]

Global n_hue:Int = 6
Global n_light:Int = 3
Global c_mark_index:Int = 255

Type TStackItem
Field value:Int

Function pushItem:TStackItem(Initial:Int)
Local StackItem:TStackItem = New TStackItem
StackItem.value = Initial
Return StackItem
End Function
End Type

Type TStack
Field List:TList
Field Output:String
Field Cells:TBank
Field DP:Int = 0
Field CC:Int = 1
Field p_xpos:Int = 0
Field p_ypos:Int = 0
Field pre_xpos:Int = 0
Field pre_ypos:Int = 0
Field exec_step:Int = 0
Field Height:Int
Field Width:Int
Field CodelSize:Int

Function Create:TStack()
Local Stack:TStack = New TStack
Stack.List = New TList
Return Stack
End Function


Method Piet_Init()
Self.CC = 1
Self.DP = 0
Self.p_xpos = 0
Self.p_ypos = 0
End Method

Method push(V:Int = 1)
Self.List.AddLast TStackItem.pushItem(V)
End Method

Method Load(Path:String,CodelSize:Int)
'Local Tmp:TImage= LoadImage(Path)
'Local dat:TStream = OpenFile(Path)
Local Image:TPixmap = LoadPixmapPNG(Path)
DrawPixmap Image,0,0
Local col_idx:Int,col:Int
Self.CodelSize = CodelSize

Self.alloc_cells(PixmapWidth(Image),PixmapHeight(Image))

For Local j:Int = 0 To Self.Height - 1
For Local i:Int = 0 To Self.Width - 1
Local rgb:Int
col = Image.ReadPixel(i,j)
col_idx = get_color_idx(col)
If col_idx<0 Then
col_idx = 19
EndIf
Self.Set_cell(i,j,col_idx)
Next
Next


Self.cleanup_input()
Self.DrawBank()

'End
End Method

Method dump_cells()
Local row:String
For Local j:Int = 0 To Self.Height - 1
For Local i:Int = 0 To Self.Width - 1
row:+" "+Self.Get_cell(j,i)
Next
row = ""
Next
End Method

Method Piet_action:Int(c_col:Int,a_col:Int, num_cells:Int)
Local hue_change:Int,Light_change:Int

hue_change = ((get_hue (a_col) - get_hue (c_col)) + n_hue) Mod n_hue
light_change = ((get_light (a_col) - get_light (c_col)) + n_light) Mod n_light

Self.GetStack()

Flip
Select Light_Change
Case 0
Select Hue_Change
Case 1
Self.add()
Case 2
Self.div()
Case 3
Self.gre()
Case 4
Self.dup()
Case 5
Self.inC()
End Select
Case 1
Select Hue_Change
Case 0
Self.push(num_cells)
Case 1
Self.sub()
Case 2
Self.sMod()
Case 3
Self.poi()
Case 4
Self.rol()
Case 5
Self.OutN()
End Select
Case 2
Select Hue_Change
Case 0
Self.pop()
Case 1
Self.mul()
Case 2
Self.sNot()
Case 3
Self.swi()
Case 4
Self.inN()
Case 5
Self.OutC()
End Select
End Select
Return 0
End Method

Method Piet_Step:Int()

'WaitKey()
Local rc:Int, tries:Int, n_x:Int, n_y:Int, a_x:Int, a_y:Int, pre_dp:Int, pre_cc:Int
'Local pre_xpos:Int, pre_ypos:Int
Local c_col:Int, a_col:Int, num_cells:Int
Local white_crossed:Int = 0
Local p_toggle:Int = 0

c_col = Self.get_cell(Self.p_xpos,Self.p_ypos)

SetColor 0,0,0
DrawLine Self.pre_xpos*Self.CodelSize+(Self.CodelSize/2),Self.pre_ypos*Self.CodelSize+(Self.CodelSize/2),Self.p_xpos*Self.CodelSize+(Self.CodelSize/2),Self.p_ypos*Self.CodelSize+(Self.CodelSize/2)


Self.pre_xpos = Self.p_xpos
Self.pre_ypos = Self.p_ypos



If (c_col = 19) Then '19 = Black
Print "In einem Schwarzen Punkt gestartet"
Return -1
EndIf


For tries = 0 To 7
n_x = Self.p_xpos
n_y = Self.p_ypos
If (c_col = 18) Then '18 = Whith
If (tries = 0 ) Then
Print "In einem Weißen Feld gestartet"
EndIf
num_cells = 1
Else
Self.piet_walk_border(n_x,n_y,num_cells)
EndIf
a_x = n_x + dp_dx (Self.DP)
a_y = n_y + dp_dy (Self.DP)
a_col = Self.get_cell(a_x,a_y)

If (c_col = 18 Or a_col = 18) Then
Print a_col
Self.piet_walk_border(a_x,a_y,num_cells)
'While (a_col = 18)
' a_x:+dp_dx(Self.DP)
' a_y:+dp_dy(Self.DP)
' a_col = Self.get_cell(a_x,a_y)
'Wend
a_col = Self.get_cell(a_x,a_y)
If (a_col >= 0) Then
white_crossed = 1
EndIf
EndIf

If (a_col < 0 Or a_col = 19) Then
If p_toggle Mod 2 = 0 Then
Self.toggle_cc()
Else
Self.ClockWise()
EndIf
p_toggle:+1
Else
Self.exec_step:+1
If (white_crossed) Then
rc = 0
Else
rc = Self.piet_action(c_col,a_col,num_cells)
EndIf

If (rc<0) Then
Print "Fehleddr"
Return -1
EndIf
Self.p_xpos = a_x
Self.p_ypos = a_y
Return 0
EndIf
Next



Return -1
End Method
Method GetStack()
Print "___----Start----___"
For Local Item:TStackItem = EachIn Self.List
Print Item.Value
Next
Print "----____End____----"
End Method
Method Piet_Run:Int()
'If (Self.Width<=0 Or Self.Height<=0) Then
' Print "nichts zum Ausführen"
' End
'EndIf
Print "START"
While True
If Self.Piet_step()<0 Then
Print Self.Output
Exit
EndIf

Wend
Return 0
End Method


Method add()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())

Item.value:+Item1.value

Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()

Self.List.AddLast Item
EndIf
End Method

Method sub()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())

Item.value:-Item1.value

Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()
Self.List.AddLast Item
EndIf
End Method

Method mul()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())

Item.value:*Item1.value

Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()
Self.List.AddLast Item
EndIf
End Method
Method div()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())

Item.value = Int(Item.value/Item1.value)

Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()
Self.List.AddLast Item
EndIf
End Method

Method sMod()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())

Item.value = Item.value Mod Item1.value

Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()
Self.List.AddLast Item
EndIf
End Method

Method dup()
If Self.List.Count() > 0 Then
Local Item:TStackItem = TStackItem.pushItem(TStackItem(Self.List.Last()).value)
Self.List.AddLast Item
EndIf
End Method

Method gre()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())
Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()
If Item.Value > Item1.value Then
Self.List.AddLast TStackItem.pushItem(1)
Else
Self.List.AddLast TStackItem.pushItem(0)
EndIf
EndIf
End Method

Method sNot()
If Self.List.Count() > 0 Then
Local Item:TStackItem = TStackItem(Self.List.Last())
Self.List.RemoveLast()
If Item.Value = 0 Then
Self.List.AddLast TStackItem.pushItem(1)
Else
Self.List.AddLast TStackItem.pushItem(0)
EndIf
EndIf
End Method

Method rol()
If Self.List.Count() > 1 Then
Local Item:TStackItem = TStackItem(Self.List.LastLink().PrevLink().Value())
Local Item1:TStackItem = TStackItem(Self.List.Last())

Local CopyLink:TLink = Self.List.LastLink(), Copy:TStackItem,Past:TStackItem,PastLink:TLink
If Item.Value < Self.List.Count() Then

For Local i:Int = 0 To Item.Value
CopyLink = CopyLink.PrevLink()
Next
Copy = TStackItem(CopyLink.Value())
If Item.Value <> 0 Then
If Item1.Value <> 0 Then
If Item1.Value > 0 Then
PastLink = CopyLink.NextLink()
CopyLink.Remove
For Local i:Int = 1 To Item1.Value - 1
PastLink = PastLink.NextLink()
Next
Else
PastLink = CopyLink.PrevLink()
CopyLink.Remove
For Local i:Int = 1 To Abs(Item1.Value) - 1
PastLink = PastLink.NextLink()
Next
EndIf
Self.List.InsertAfterLink(Copy,PastLink)
EndIf
EndIf
Self.List.LastLink().PrevLink().Remove()
Self.List.RemoveLast()
EndIf
EndIf
End Method

Method poi()
If Self.List.Count() <> 0 Then
Local Tim:Int = TStackItem(Self.List.LastLink().Value()).Value

If Tim>0 Then
For Local i:Int=1 To Tim
Self.ClockWise()
Next
Else
For Local i:Int=1 To Tim
Self.AntiClockWise()
Next
EndIf
Self.List.RemoveLast()
EndIf
End Method

Method swi()
If Self.List.Count() <> 0 Then
For Local i:Int=1 To TStackItem(Self.List.LastLink().Value()).Value
Self.toggle_cc()
Next
Self.List.RemoveLast()
EndIf
End Method

Method pop()
If Self.List.Count() > 0 Then
Self.List.RemoveLast()
EndIf
End Method

Method inN()
Local erg:String = Input("Number to Stack:")
Local StackItem:TStackItem = TStackItem.pushItem(Int(erg))
Self.List.AddLast StackItem
End Method

Method inC()
Local erg:String = Input("Char to Stack:")
Local StackItem:TStackItem = TStackItem.pushItem(Asc(erg))
Self.List.AddLast StackItem
End Method

Method outC()
If Self.List.Count() > 0 Then
Local Item:TStackItem = TStackItem(Self.List.Last())
Self.Output:+Chr(Item.Value)
Print Chr(Item.Value)
Self.List.RemoveLast
EndIf
End Method

Method outN()
If Self.List.Count() > 0 Then
Local Item:TStackItem = TStackItem(Self.List.Last())
Self.Output:+Item.Value
Print Item.Value
Self.List.RemoveLast
EndIf
End Method

Method alloc_cells(n_width:Int,n_Height:Int)
Local i:Int,j:Int,b:Int
Local n_cells:TBank = CreateBank(n_width*n_Height*SizeOf(b))

For i = 0 To n_Height - 1
For j = 0 To n_Width - 1
n_cells.PokeByte(j*n_width+i,19)
Next
Next

If Not n_cells Then
Print "Not cells"
End
EndIf

If Self.Cells Then
For i = 0 To n_Height - 1
For j = 0 To n_Width - 1
n_cells.PokeByte(j*n_width+i,Self.Cells.PeekByte(j*n_width+i))
Next
Next
Self.Cells = Null
EndIf

Self.Cells = CreateBank(n_cells.capacity())
CopyBank(n_cells,0,Self.Cells,0,n_cells.Capacity())

Self.Width = n_width
Self.Height = n_Height
n_cells = Null
End Method

Method DrawBank()
Local Tmp:TPixmap = CreatePixmap(Self.Width,Self.Height, 4)
'Tmp.ClearPixels(0)
For Local j:Int = 0 To Self.Height - 1
For Local i:Int = 0 To Self.Width - 1
'Print Self.Cells.PeekByte(cell_idx(i,j))
Tmp.WritePixel (i,j, HexToDez(hex2hue[0][Self.Cells.PeekByte(cell_idx(i,j))]))

Next
Next
'DrawPixmap tmp,150,0
'SavePixmapPNG(Tmp,"Test.png")
'DrawText "Test",0,0
Flip
WaitKey
End Method

Method cleanup_input()
Local i:Int, j:Int, last_c:Int
Local o_cells:TBank

If ( 0 <> (Self.Width) Mod Self.CodelSize) Then
Print "CodelSize stimmt nicht"
End
EndIf
If ( 0 <> (Self.Height) Mod Self.CodelSize) Then
Print "CodelSize Stimmt nicht"
End
EndIf

o_cells = CreateBank(Self.Cells.Capacity())
CopyBank(Self.Cells,0,o_cells,0,Self.Cells.Capacity())

Self.Alloc_cells(Self.Width / Self.CodelSize , Self.Height / Self.CodelSize)


For j = 0 To Self.Height - 1
For i = 0 To Self.Width - 1
Self.Set_cell(i,j,o_cells.PeekByte((j*(Self.CodelSize)) * (Self.Width * (Self.CodelSize)) + (i*(Self.CodelSize))))
Next
Next
o_cells = Null
End Method


Method piet_walk_border_do:Int(n_x:Int Var, n_y:Int Var,num_cells:Int Var)
Local rc:Int, c_idx:Int

c_idx = Get_Cell(Self.p_xpos, Self.p_ypos)

num_cells = 0

rc = Self.check_connected_cell(Self.p_xpos, Self.p_ypos, c_idx, c_mark_index, n_x, n_y, num_cells)

If (rc >= 0) Then
reset_check_connected_cell (Self.p_xpos, Self.p_ypos, c_idx, c_mark_index)
EndIf
Return rc
End Method

Method piet_walk_border:Int(n_x:Int Var, n_y:Int Var,num_cells:Int Var)
Local rc:Int

rc = piet_walk_border_do (n_x, n_y, num_cells);
If (rc < 0) Then
Print("Fehler !")
End
EndIf
Return 0;
End Method

Method reset_check_connected_cell:Int(x1:Int,y1:Int,c_idx:Int, c_mark:Int)
Local c:Int

c = Get_Cell(x1,y1)

If (c < 0 Or c <> c_mark Or c = c_idx) Then
Return -1
EndIf

Self.Set_cell(x1, y1,c_idx)

reset_check_connected_cell (x1 + 1, y1 + 0, c_idx, c_mark)
reset_check_connected_cell (x1 + 0, y1 + 1, c_idx, c_mark)
reset_check_connected_cell (x1 - 1, y1 + 0, c_idx, c_mark)
reset_check_connected_cell (x1 + 0, y1 - 1, c_idx, c_mark)

Return 0
End Method


Method check_connected_cell:Int(X1:Int,Y1:Int,c_idx:Int,c_mark:Int,n_x:Int Var,n_y:Int Var, num_cells:Int Var)
Local found:Int,c:Int

c = Self.Get_Cell(x1,y1)

If ( c < 0 Or c<>c_idx Or c=c_mark ) Then
Return -1
EndIf

found = 0

If (Self.DP = 2 And x1<= n_x) Then
If x1<n_x Or ( Self.CC = 1 And y1 > n_y) Or (Self.CC = 0 And y1<n_y) Then 'Left
found = 1
EndIf
ElseIf (Self.DP = 0 And x1>= n_x)
If x1>n_x Or ( Self.CC = 1 And y1 < n_y) Or (Self.CC = 0 And y1 > n_y) Then 'Right
found = 1
EndIf
ElseIf (Self.DP = 3 And y1<= n_y)
If y1 < n_y Or ( Self.CC = 1 And x1 < n_x) Or (Self.CC = 0 And x1 > n_x) Then 'Up
found = 1
EndIf
ElseIf (Self.DP = 1 And y1 >= n_y)
If y1 > n_y Or ( Self.CC = 1 And x1 > n_x) Or (Self.CC = 0 And x1< n_x) Then 'Down
found = 1
EndIf
EndIf

If (found) Then
n_x = x1
n_y = y1
EndIf

Self.Set_cell(x1,y1,c_mark)

num_cells:+1

check_connected_cell (x1 + 1, y1 + 0, c_idx, c_mark, n_x, n_y, num_cells)
check_connected_cell (x1 + 0, y1 + 1, c_idx, c_mark, n_x, n_y, num_cells)
check_connected_cell (x1 - 1, y1 + 0, c_idx, c_mark, n_x, n_y, num_cells)
check_connected_cell (x1 + 0, y1 - 1, c_idx, c_mark, n_x, n_y, num_cells)

Return 0
End Method

Method Set_cell(x1:Int,y1:Int,val:Int)
Local c_idx:Int
c_idx = Self.Cell_idx(x1,y1)
If (c_idx = Get_Cell(x1,y1) < 0 ) Then
Print "c_idx = Get"
End
EndIf
Self.Cells.PokeByte(c_idx,Val)
End Method

Method Get_Cell:Int(x1:Int,y1:Int)
Local c_idx:Int = cell_idx(x1,y1)
If c_idx<0 Then
Return -1
EndIf
Return Self.cells.PeekByte(c_idx)
End Method
Method get_color_idx:Int(col:Int)
Local i:Int
For i = 0 To 19
If (GetHex(col) = Hex2Hue[0][i]) Then
Return Color[i]
EndIf
Next
Return -1
End Method


Method cell_idx:Int(x1:Int,y1:Int)
If x1<0 Or x1>Self.Width - 1 Or y1<0 Or y1>Self.Height - 1 Then
Return -1
EndIf
Return y1 * Self.Width + x1
End Method

Method ClockWise()
Select Self.DP
Case 0
Self.DP = 1
Case 1
Self.DP = 2
Case 2
Self.DP = 3
Case 3
Self.DP = 0
End Select
End Method

Method AntiClockWise()
Select Self.DP
Case 0
Self.DP = 3
Case 1
Self.DP = 0
Case 2
Self.DP = 1
Case 3
Self.DP = 2
End Select
End Method

Method toggle_cc()
If Self.CC = 0 Then
Self.CC = 1
Else
Self.CC = 0
EndIf
End Method
End Type

Function HexToDez:Int(hexa:String)
Local Bytes:Int,hexwert:String,zeichen:String
hexa:String = Upper(hexa:String)
For Local i:Int =1 To Len(hexa)
If Asc(Mid(hexa,i))<=57 Then hexwert=Mid(hexa,i, 1) Else hexwert=Asc(Mid(hexa,i, 1))-55
zeichen = Len(hexa$)-i
Bytes = Bytes + Int(Int(hexwert)*(16^Double(zeichen)))
Next

Return Bytes
End Function

Function GetHex:String(pixelValue:Int)
Return Right(Hex(pixelValue),6)
EndFunction

Function get_hue:Int(val:Int)
If (val < 18) Then
Return val Mod 6
EndIf
If (val = 19 Or val = 18) Then
Return val
EndIf
Print "Error no such Color:"+val
End
End Function

Function get_Light:Int(val:Int)
If (val < 19) Then
Return val / 6
EndIf
Print "Error no such color:"+val
End
End Function

Function dp_dx:Int(dp:Int)
Local r:Int = 0
If dp = 2 Then r = -1
If dp = 0 Then r = 1
Return r
End Function

Function dp_dy:Int(dp:Int)
Local r:Int = 0
If dp = 3 Then r = -1
If dp = 1 Then r = 1
Return r
End Function


Und hier die Verwändung
BlitzMax: [AUSKLAPPEN]

Graphics 400,400,0,60
Local Stack:TStack = TStack.Create()

Stack.Load("HelloWorld.png",11) ' Die Zahl nach dem Pfad gibt die Coddelsize an

Stack.Piet_Init()
Stack.Piet_Run()


Zu guter Letzt noch ein Paket indem der Code und ein paar Beispiele liegen.

Piet Interpreter

mfg

ich
"Wenn die Menschen nur über das sprächen, was sie begreifen, dann würde es sehr still auf der Welt sein." Albert Einstein (1879-1955)
"If you live each day as if it was your last, someday you'll most certainly be right." Steve Jobs

Neue Antwort erstellen


Übersicht BlitzMax, BlitzMax NG Codearchiv & Module

Gehe zu:

Powered by phpBB © 2001 - 2006, phpBB Group