Hallo Besucher, der Thread wurde 3,3k mal aufgerufen und enthält 23 Antworten

letzter Beitrag von BIF am

Z10: Mini-Schatz-Höhle


  • Hallo alle beieinander,
    Hier kommt die nächste Herausforderung für den ambitionierten Basic-Programmierer.
    Hat der Smaragd-Sammler schon ein Vollschirm-Spiel im 2x2-Zufalls-Modus geboten stellt sich natürlich die Frage, ob es möglich ist ein Vollschirm-Spiel in 10 Zeilen zu programmieren, bei dem man statt zufällig alle Elemente vorbestimmt programmieren kann.


    Also viel Spaß beim Knobeln.


    Schönen Gruß.

  • Oder eine simple Komprimiermethode anwenden. Also z.B. eine Zahl=welches Tile (0-9) und ein Buchstabe=Anzahl Wiederholungen (1-26) von links nach rechts.


    Der oben gezeigte Level könnte dann als String so aussehen. Beispiel für erste 26 Tiles:


    "1a2h1a2f1b2h..."


    Aber mal schauen, was sonst noch für Vorschläge kommen. Interessant wird es ja erst, wenn das mit der Aufbauroutine gekoppelt wird. Und das möglichst effizient.

  • Ich habe den obigen Level mal nachgebildet:


    Die erzeugten Daten lassen sich dann mit folgendem Basic-Code anzeigen (Screen Code Schreibweise basiert auf CBM prg Studio terminologie):


    Code
    1. 10 poke53280,0:poke53281,0:print"{clear}";
    2. 11 t$(0)="{down}{right}{right}"
    3. 12 t$(1)="{orange}{reverse on}{sh @}{cm p}{down}{left}{left}{cm p}{sh @}"
    4. 13 t$(2)="{cyan}{reverse on}{sh pound}{green}{reverse off}M{down}{left}{left}M{cyan}{sh pound}"
    5. 14 reada$:m=16:fori=1tolen(a$)
    6. 15 c=asc(mid$(a$,i,1))-35:t=int(c/m):n=c-t*m:forj=1ton:printt$(t)"{up}";:z=z+1:ifz=20thenz=0:print
    7. 16 next:next:wait198,1
    8. 17 data4k4i5k4h4d4i5h6k4g4e4h4d4g5d4g%5g4d5h6&d7g4j$4)5k4d'4d4&f5h6i$d4g4e4h4d4d$e5d4i5g4$5h6g7'

    Der Level-String hier ist 90 Zeichen lang, das liegt aber daran, dass der Beispiel(Zufalls)-Level ziemlich zerhackt ist. Ich denke in einem von Hand gezeichneten Level, wird es viele Zeichen hintereinander geben und der String somit wesentlich kürzer.

  • Hallo BIF

    Im Moment bist du etwa bei 8 Zeilen für den Schirmaufbau. Da ist also noch Luft.

    Nun ja, in Kurzschreibweise und etwas arrangiert, bringt man das schon auf 4 Zeilen (bei PUR-80). Aber klar, das Optimierungspotenzial ist auch so noch nicht ausgeschöpft.


    Hierzu eine Frage...

    alle Elemente vorbestimmt

    Es geht bei dieser Übung nicht darum, deinen Beispiel-Level (siehe Screenshot im ersten post) 1:1 nachzubilden, richtig? Denn dort wiederholt sich der Aufbau nach 6 Zeilen und beinahe auch nach 9 Spalten. Diese Erkenntnis könnte man bei einem Wettbewerb ausnutzen (man erinnere sich an ZeHa's "Draw the Frog"-Contest).


    Es geht hier also schon eher darum, einen beliebigen, von Hand gezeichneten Level-Aufbau möglichst kompakt im Code zu hinterlegen, ohne dass man von einem Muster ausgehen kann, korrekt?


    Wenn man vor allem Platz sparen muss - was bei einem PUR-80 Zehnzeiler schon mal die Grundvoraussetzung ist - dann gestaltet man die Levels doch eher Prozedural (Pseudo-Zufällig/Fibonacci), und kann mit Spiegelung zumindest noch etwas Symmetrie und damit attraktiveren Level-Aufbau hinkriegen.


    Vordefinierte Levels sind dann doch eher etwas für PUR-120 oder PUR-256. Wie siehst du das?


    Und hast du denn selbst schon einen Lösungsansatz, der kompakter ist, als was bisher vorgeschlagen wurde?

  • Wobei es zu berücksichtigen gilt, dass man nicht alle 256-ASCII-Zeichen in einen Data String packen kann. Z.B. würde ein Bitmuster eines Gänsefuss-Zeichens den Datastring terminieren. Mit dieser Einschränkung müsste die Konversions-Routine umgehen können.

  • Ja, stimmt natürlich, es gibt Wiederholungen im Bildaufbau, die man natürlich berücksichtigen kann.


    Bei meinen Algorithmus kann man aber natürlich alle Elemente am Schirm frei wählen.
    Einschließlich der Männchen-Position.


    Die Grundüberlegung, wie man 240 Tiles auf den Schirm bringen kann ist natürlich schon richtig.


    Ansonsten gibt es natürlich Parrallelen zum Smaragd-Sammler, was die Programm-Logik anbettrifft.
    Außer, daß man natürlich noch die Mauern berücksichtigen muß.
    Und natürlich die Status-Leiste mit Runden und Punktzähler, diesmal in Zeile 24.
    Und natürlich hat das Spiel, wie der Smaragd-Sammler auch Ton-Ausgabe und am Levelende einen Flimmer-Effekt im Rahmen.
    Bei der neusten Version habe ich übrigens auch noch den "Sammler" rechtsbündig realisiert, also ohne Bild-Rollen, damit es noch ein bisschen anspruchsvoller ist und um zu zeigen, daß das natürlich auch geht.


    Schönen Gruß.

  • Verstehe ich das richtig, dass der neue BASIC Zehnzeiler...

    • wieder auf PUR-80 basiert
    • EINEN, von Hand gestalteten Level beinhaltet (also nicht mehrere Levels)
    • bei Levelbeginn Smaragde, Mauern und der Mampfer an einer bestimmten Position dargestellt wird (oder kann der Level vor Spielbeginn auch schon leere Tiles beinhalten?)
    • Der Mampfer die Smaragde aufsammeln, aber bei Mauern und Randbereichen nicht durch kann (wohl nur logisch)


    Wäre noch cool, deinen Zehnzeiler als Video zu sehen, damit man sich einen besseren Eindruck machen kann.


    Und gibt es einen Bonuspunkt wenn man noch einen Level-Editor dazuprogrammiert? :D

  • So weit so gut :ChPeace



    Fehlt aber noch etwas die Herausforderung, also im Spiel meine ich. Das Nachbauen selber hat viel Spass gemacht.
    Hier mein Code. Habe sogar noch ein paar Zeichen über. Ich könnte mir noch einen zweiten Level leisten.


  • Hallo BIF


    Vielen Dank für das PRG file. Sehr interessant, unsere teils unterschiedlichen Ansätze für dasselbe Ziel zu vergleichen.


    Die Möglichkeit, mit dem LEFT$( "{up}", POS( 0 ) ), um die Zeilenschaltung nach 20 Tiles zu erreichen, kannte ich noch nicht. Wirklich elegant.


    Auch der POKE242,0 ist witzig, um das Bildschirmscrollen beim Printen des letzten Zeichens von "SAMMLER" zu verhindern. Das Führt aber leider zu ein paar unschönen Nebeneffekten, wenn man das Spiel dann unterbricht und den Code auflisten möchte. Ein <SHIFT><HOME> (löschen des Bildschirms) setzt das aber zum Glück wieder zurück. Ich habe das alternativ auch mit ...TAB(33)"SAMMLR{left}{insert}E"; hingekriegt.


    Den Soundeffekt beim Aufnehmen eines Diamanten finde ich gelungen. Ist halt einfach schade, dass man zur Sounderzeugung auf dem C64 mehrere Pokes benötigt. Bei einem Zehnzeiler ist das schon fast Verschwendung (weil auf mögliche Kosten des Gameplays). Aber ein hörbares Feedback hat schon was. Gefällt mir.


    Deine Level-Daten sind mit insgesamt 48 Zeichen enorm kompakt. Wie ich sehe, stehen die unteren 5 Bits für die Mauer=1 bzw. Diamant=0 Sequenz. Und die oberen 3 Bits wurden wohl jeweils so gesetzt, damit man sie als DATA-String-Zeichen einfach eintippen kann? Statt dem Space könnte also auch ein @ stehen? Das würde mich noch interessieren, wie du den Doppelpunkt (‭00111010‬=58) vermeidest. Nimmst du in jenem Fall das Bitmuster (01011010=90), also das "Z"?


    Mit den neuen Erkenntnissen im Rucksack, versuche ich mal meinen Code weiter zu kürzen. Vielleicht kann ich dann noch etwas mehr Herausforderung in das Spiel packen. Ich erlaube mir die künstlerische Freiheit, den Mampfer in einen Indiana Jones-Verschnitt zu ändern (das Azteken-Thema wird über das Leveldesign angedeutet) und schaue mal, ob ich noch Schlangen ins Spiel bringen kann. Und wenn ich dafür Sorge, dass immer ein äusserer Rahmen von Mauern existiert, spare ich mir einerseits die zusätzliche Abfrage auf die Spieler-Position und zweitens muss der Level dann nur noch 18x10 (also 180 statt 240) Zeichen gross sein. Das spart weitere Zeichen. :thumbsup:


    Beste Grüsse

  • wizball6502:


    Danke für die Würdigung.
    ------------------------------------
    Ist mir noch nicht aufgefallen, daß es bei Break zu Nebeneffekten kommt, weil ich vermutlich den Schirm immer gelöscht habe und auch noch keine Fehlermeldung hatte.
    Alternativ kann man :poke213,40: verwenden, soweit ich mich entsinne.


    Sonst: Richtig, für Space könnte auch @ stehen, und für Kleiner auch das Pfundzeichen.
    Grundsätzlich werden nur die ersten 5 Bit 0-31 für die Leveldecodierung benutzt.
    Ich war da wohl der Meinung, daß es für das Abtippen einfacher ist Leerzeichen und Kleiner-Zeichen zu verwenden.
    Falls man einen Doppelpunkt benutzen möchte, sollte man den String vermutlich besser in Anführungszeichen setzen, also "abcd:::efgh". Probleme gibt es dann vermutlich nur mit dem Anführungszeichen, Code:34.
    5-Bit Kodierung geht also für´s Eingeben noch recht unproblematisch.
    Und ich hab es gewählt, weil man dann glatte 4 Zeichen für eine Tile-Zeile hat.


    Ich hoffe, daß euch das Spiel schon gefallen hat.
    Ich fand es wie immer ziemlch gut.


    Schönen Gruß.

  • Grundsätzlich habe ich mir eben grade überlegt, daß man : und Anführungszeichen doch verwenden kann.
    Und zwar wenn man die Zeichen statt als String direkt mit peek aus dem Programm liest.
    Man bräuchte dann aber die Zeilen-Adresse im Programm-Code.
    Theoretisch könnte man dafür wohl auf den Data-Zeiger zugreifen.
    Also:
    9 :data1,2,3:abcdefghei::"",usw.


    Müßte man mal ausprobieren.


    Schönen Gruß.

  • Grundsätzlich habe ich mir eben grade überlegt, daß man : und Anführungszeichen doch verwenden kann.

    Interessanter Hack die Daten dann mit Peek aus dem Listing-RAM auslesen zu wollen. .

    Dann kannst du dir aber auch das 'data' sparen, also quasi gleich so:


    9 abcdefghei::""

    Die Zeile lässt sich tatsächlich so eingeben. Aber ich würde mit einem führenden Anführungszeichen beginnen. Damit ...def… nicht als Basic-Befehl erkannt und dann als einzelnes Byte (statt deren drei) im Speicher abgelegt wird. Auch kann man ohne führendes Anführungszeichen keine geshifteten Zeichen eingeben. So könnte das also funktionieren:


    9 "abcdefghei::""


    Man darf dann einfach keine nachträglichen Änderungen mehr machen. Sonst verschiebt sich die Startadresse des Strings.

  • Man darf dann einfach keine nachträglichen Änderungen mehr machen. Sonst verschiebt sich die Startadresse des Strings.

    Oder alternativ in der ersten Programmzeile das ganze in einen String packen....


    Sowas hab ich schon mal in einem 128er Programm gemacht. Da wird ein String mit fester Länge gesetzt und später schreibt dann eine ASM-Routine dort Daten rein die das Basic-Programm dann direkt benutzen kann.

  • Jo, wenn man mehr als 5-Bit rausholen will wird die ganze Sache in jedem Falle schon kniffelig.


    6 Bit sind vielleicht noch gut machbar, wenn man die Kombinationen mit Shift oder CBM nutzt.


    Danm käme man bei Zwei-Bit-Kodierung auf 3, also 240/3=80 Zeichen.
    Und da der Tastenpuffer 88 Zeichen verkraftet kann man die sogar noch, mit Griff in die Trickkiste, mit Zeilenverlängerung eingeben.


    Schönen Gruß