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] [EINKLAPPEN] 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 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 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()
Local rc:Int, tries:Int, n_x:Int, n_y:Int, a_x:Int, a_y:Int, pre_dp:Int, pre_cc: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 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 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) 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() 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) For Local j:Int = 0 To Self.Height - 1 For Local i:Int = 0 To Self.Width - 1 Tmp.WritePixel (i,j, HexToDez(hex2hue[0][Self.Cells.PeekByte(cell_idx(i,j))]))
Next Next 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 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 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 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 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] [EINKLAPPEN] Graphics 400,400,0,60 Local Stack:TStack = TStack.Create()
Stack.Load("HelloWorld.png",11)
Stack.Piet_Init() Stack.Piet_Run()
Zu guter Letzt noch ein Paket indem der Code und ein paar Beispiele liegen.
Piet Interpreter
mfg
ich
|