Collab: Entwicklung eines TSB-Puzznic-Klons

Es gibt 1.089 Antworten in diesem Thema, welches 110.207 mal aufgerufen wurde. Der letzte Beitrag (1. November 2024 um 23:56) ist von Omega.

  • Neuer Denkansatz: Das TSB-Programm manipuliert, ohne Ausgabe auf dem Bildschirm, nur einen Speicherbereich von 12 mal 12 Bytes.

    Das habe ich mir ganz am Anfang auch überlegt. Ob man statt 2x2 Zeichen einfach 1 Zeichen pro Feld darstellt. Aber ich fürchte, damit kann man den eklatanten Geschwindigkeitsmangel nicht ausgleichen.

    MEGA65 sagt mir überhaupt nix.

    Lügner! :P

    Da wird niemand meckern und wenn es einem doch zu lang ist, kann er auch kurz aufs Klo gehen. ;)

    Dann stellt sich nur die Frage, aus welchem Grund man nach jedem Spielzug aufs Klo gehen sollte. Bei "Hollywood Poker Pro" könnte ich mir das ja noch vorstellen. Aber bei Puzznic?

  • Dem Link auf meine VDCBasic-Seite folgen und lesen! =O

    Hast du das auch in einfacher? Was genau muss ich machen, wenn ich ein 1,5KB großes MS-Programm in den Heap laden will?

    Und dann stelle ich mir noch die Frage: Wenn man die Größe des Heaps reduziert. Ist es dann nicht so, dass Mr. Garbage-Collection alle 30 Sekunden zu Besuch kommt? Man muss ja auch bedenken, dass ich trotz der eingebundenen MS-Routinen noch ein normales TSB-Programm ablaufen lassen möchte.

  • Dann stellt sich nur die Frage, aus welchem Grund man nach jedem Spielzug aufs Klo gehen sollte.

    Zitat

    So wird jede Sitzung ein Erfolg: Witze, Klodokus und mehr oder weniger Wissenswertes verkürzen lange Wartezeiten

    Bitte melde dich an, um diesen Anhang zu sehen.

  • Also ich mag ja den llvm-mos-Compiler und hab mal das im Anhang gebastelt. Ist nur ein erster Wurf (230 Zeilen C mit vielen Dopplungen, keine zwei Stunden Bastelei) und noch ohne veränderten Zeichensatz (gibt's den irgendwo? Edit Bitte melde dich an, um diesen Link zu sehen.) oder weitere Level. Das, was man da sieht, ist der Bitte melde dich an, um diesen Link zu sehen..

    Cursortasten zum Auswählen, dann Return, dann mit Cursortaste Richtung wählen. Lässt sich durch Austausch von 50 Zeilen plattformabhängigem Code auch für den PC oder sonstwas kompilieren.

    2.8KBytes insgesamt und die Geschwindigkeit sind doch ganz nett. Kommt ohne Rekursion und ohne Scannen des ganzen Spielfelds aus, sondern benutzt eine Liste der veränderten Felder und schaut nur die an (wobei das glaube ich bei so einem kleinen Spielfeld und kompiliertem Integer-C jetzt nicht so die Rolle spielt ;) ).

    Ich räum den Code noch etwas auf und mach den dann verfügbar.

  • Das habe ich mir ganz am Anfang auch überlegt. Ob man statt 2x2 Zeichen einfach 1 Zeichen pro Feld darstellt. Aber ich fürchte, damit kann man den eklatanten Geschwindigkeitsmangel nicht ausgleichen.

    Nee, das bringt vielleicht was beim Fallenlassen, also der Animation an sich. Für die Logik ist das irrelevant, die würde man ja auch im Bildschirmspeicher nicht in 2*2-Blöcken laufen lassen. Oder anders: Fürs Matching der zusammengehörigen Blöcke muss ich nicht alle 4 Blöcke prüfen. Es reicht einer pro Stein.

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

    2 Mal editiert, zuletzt von EgonOlsen71 (20. Februar 2024 um 07:14)

  • Die einzige andere Methode ohne vollen Scan des gesamten Levels wäre, wie 1570 das gemacht hat. Alle Steine in ein eigenes Array, das man aber auch

    a) nach y-Position sortiert

    und

    b) komplett durcharbeiten

    muss. Insgesamt wahrscheinlich langsamer als alles stur runterzutesten.

    Ich sehe schon, BASIC-Compo mit Puzznic-Klon!

    C64Studio: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- C64Studio WIP: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- Bitte melde dich an, um diesen Link zu sehen.

  • (wobei das glaube ich bei so einem kleinen Spielfeld und kompiliertem Integer-C jetzt nicht so die Rolle spielt ;) )

    Sehe ich auch so! Bei einen kompilierten oder einem direkt in Assembler geschriebenen Programm würde ich mir bei einer 12x12-Spielfläche keine Sekunde Gedanken über irgendwelche Optimierungen machen. Das wäre in diesem Fall wohl eher Zeitverschwendung! ;)

  • Hier habe ich mal beides naiv ausprobiert. Für die naive Implementation in Zeile 70 statt GOSUB 1100 GOSUB 1000 einsetzen.

    1100 ist (derzeit) schneller, weil es nur zwei Teile sind. Das wird natürlich mit zunehmender Zahl der Teile langsamer. Und man muss beim manuellen Verschieben ggf. das Array neu sortieren! (sonst fällt ein höheres Teil plötzlich vor einem tiefer liegenden)

    Dateien

    C64Studio: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- C64Studio WIP: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- Bitte melde dich an, um diesen Link zu sehen.

  • 1570: Bei deiner Variante lösen sich die Teile nicht auf. Es ging hier aber auch nicht um das Erstellen eines Puzznic-Klons auf jede erdenkliche Weise. Sondern in Basic. Oder genauer gesagt mit TSB. Wenn MS verwendet wird, dann darf es nur <1KB sein. (Von $c000-$c3f7). Oder man benutzt den Heap als Ablageort. Das weiß aber nur GoDot wie das geht. Und er verrät es keinem. :P

    Endurion: Ich seh nur, dass zwei Teile runterfallen. Ob da jetzt die komplette Logik für einen Puzznic-Klon drin ist, weiß ich nicht.

  • Ich bastle einfach mal weiter an einer TSB-Lösung, die sich hoffentlich möglichst geschmeidig in den schon vorhandenen Code von Omega einfügt. :syshack::hammer:

    Allerdings wird der Programmcode dann eine FSK 18-Freigabe haben. Vor allem wurden die Prozeduren "holerunter" und "schieberein" beanstandet! :prof:

  • 1570: Bei deiner Variante lösen sich die Teile nicht auf. Es ging hier aber auch nicht um das Erstellen eines Puzznic-Klons auf jede erdenkliche Weise. Sondern in Basic. Oder genauer gesagt mit TSB. Wenn MS verwendet wird, dann darf es nur <1KB sein. (Von $c000-$c3f7). Oder man benutzt den Heap als Ablageort. Das weiß aber nur GoDot wie das geht. Und er verrät es keinem. :P

    Endurion: Ich seh nur, dass zwei Teile runterfallen. Ob da jetzt die komplette Logik für einen Puzznic-Klon drin ist, weiß ich nicht.

    Nee, ich habe erstmal nur das Fallen drin. Das Auflösen bastle ich nochmal hinterher.

    C64Studio: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- C64Studio WIP: Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. --- Bitte melde dich an, um diesen Link zu sehen.

  • Das weiß aber nur GoDot wie das geht. Und er verrät es keinem. :P

    Ich finde die Erklärung. bzw. den Ausschnitt aus dem Screenshot, den du gepostet hast, auch etwas "an der Zielgruppe vorbei" erklärt. Wer BASIC gewohnt ist, kann mit Hexwerten oft nichts anfangen und was ein D!(ouble)Peek macht, muss man auch erstmal kapieren. Genauso, was ein Heap sein soll. Ich versuche es mal einfacher zu machen:

    Du hast in BASIC (auch in TSB) erst das Programm, dann die Variablen, dann die Arrays und dann den Stringspeicher im RAM liegen. Das Ganze endet am Ende des BASIC-Speichers (üblicherweise 40960, exklusiv). Diese Bereiche sind alle fix, bis auf den Stringspeicher bzw. den Teil des Stringspeichers, der für Strings verwendet wird. Der variiert in der Größe und ab und zu wird dieser Speicher von der Garbage Collection aufgeräumt. Der Stringspeicher füllt sich langsam vom Ende des BASIC-Rams runter bis zum Beginn des Stringspeichers (also rückwärts...das ist aber eigentlich wurscht). Die Idee ist jetzt einfach, beim Start des Programms das Ende des BASIC-Rams nach unten zu setzen (Zeropage-Adressen 55/56, oder im Screenshot, wenn es denn unbedingt Hex sein muss, $37/$38). Dadurch wird Speicher für Strings weniger, aber in dem jetzt nicht mehr von BASIC benutzen Bereich kannst du andere Dinge ablegen. Z.B. das MS-Programm.

    Beispiel (für normales BASIC):

    Code
    0 POKE 56,152:POKE 55,0:CLR

    Das setzt das Ende des BASIC-RAMs auf 38912. Du hast also ab da 2048 Bytes bis zum ROM frei für...irgendwas.

    Ich weiß nicht genau, wo das Ende von TSB liegt (32768 / $8000)??, aber das Prinzip ist dasselbe. In TSB-Sprech wäre das dann wohl:

    Code
    0 D!POKE 55,30720:CLR

    Dann hättest du ab 30720 (und bis 32768) Platz für anderen Kram

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

    Einmal editiert, zuletzt von EgonOlsen71 (20. Februar 2024 um 09:18)

  • Die einzige andere Methode ohne vollen Scan des gesamten Levels wäre, wie 1570 das gemacht hat. Alle Steine in ein eigenes Array

    Nee, das mache ich nicht. Die Steine an sich sind nur auf dem Bildschirm, im Array wird eine Liste der Positionen mitgezogen, die sich verändert haben.

    Da sind unmittelbar nach einem Zug des Spielers nur zwei Positionen drin, beim "Fallen" wird die Liste dann entsprechend angepasst und beim "Auflösen" ebenso.

    Das kann man in BASIC ebenso machen und wird dort mit ziemlicher Sicherheit Geschwindigkeit bringen, man schaut sich dann ja nur (in dem Beispiel aus Bitte melde dich an, um diesen Link zu sehen.) 12 Positionen fürs komplette Fallen an statt 12*12*12 Positionen (12x voller Scan des Spielfelds).

    Bei deiner Variante lösen sich die Teile nicht auf.

    Ich hab für Deine schwachen Augen nochmal genau Dein Szenario aus Bitte melde dich an, um diesen Link zu sehen. unten angehängt. Schaust Du genau hin, siehst Du, dass sich die beiden "RSTU"-Ringe obendrauf aufgelöst haben. Die "ABCD"s sind Glasblöcke und lösen sich nicht auf (siehe Bitte melde dich an, um diesen Link zu sehen.).

    Wenn MS verwendet wird, dann darf es nur <1KB sein.

    Der "Resolve"-Teil in dem Programm ist gerade rund 1KB groß (vermutlich als simpler kompletter Scan nur ein paar hundert Bytes). Gilt aus C kompilierte Maschinensprache als Maschinensprache? ;)

  • Ich finde die Erklärung. bzw. den Ausschnitt aus dem Screenshot, den du gepostet hast, auch etwas "an der Zielgruppe vorbei" erklärt. Wer BASIC gewohnt ist, kann mit Hexwerten oft nichts anfangen und was ein D!(ouble)Peek macht, muss man auch erstmal kapieren. Genauso, was ein Heap sein soll.

    Die Zielgruppe ist Omega ...

    Und der kennt sowohl D!POKE als auch die Hexschreibweise. So doof wie er manchmal tut, ist er zum Glück gar nicht... :wink: Ich hab in Dezimalschreibweise einfach keine Vorstellung davon, wo was liegt. Hex ist dagegen sonnenklar: $8000 ist der Anfang von TSB, $CB00 ist der Anfang des MAP-Befehls. Dagegen 32768 (was gerade noch so im Gedächtnis schweben kann) und 51968 (kann ich rein gar nichts mit anfangen) sind eher Ideen-Bremsklötze.

    Der Heap ist der String-Speicher. Der wird von hinten (da, wo das Basic bzw. wo TSB anfängt) nach vorne solange gefüllt, bis das Ende der Arrays erreicht ist. Spätestens an der Stelle gibt's dann eine Garbage Collection. Wenn man den Heap kleiner macht, wirkt sich das bei so kleinen PRGs, um die es hier geht, so gut wie gar nicht aus. 1KB! Pah!:Peace

    Arndt

    GoDot C64 Image Processing
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.
    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Ich finde die Erklärung ...

    Ab hier ist für Omega schon wieder Schluss! Er liest keine Dokus, er schaut sich keine Demos an, er hört einem im Grunde noch nicht mal zu! :D

    Er lebt nach dem Motto:

    Es interessiert niemanden, wie es funktioniert, solange es funktioniert

    Die Welt wird mit Klebeband und Klebstoff zusammengehalten. Es ist leider üblich, dass Entwickler so viele Probleme mit Code lösen müssen, der zwar funktioniert, aber niemand versteht, warum. Das ist einfach eine Tatsache im Leben eines Programmierers. Programmierer schreiben, schreiben um und optimieren ihren Code jahrelang immer wieder. Bugs (Fehler) treten auf, werden behoben und manchmal müssen sich Programmierer auf Trial-and-Error (Versuchen und Irren) verlassen, um die Dinge richtig zum Laufen zu bringen. Jeder Programmierer wird dir sagen, dass Trial-and-Error zu Lösungen führen kann, die einfach auf magische Weise funktionieren.

    Also, gebt ihm das Programm, das zu 105% genau das macht, was er haben will und geht dann unauffällig und still weiter! :whistling:


    Ach, bevor es einer falsch versteht: Ich habe kein Problem mit ihm, ganz im Gegenteil! ;)

  • Zur Garbage-Collection-"Problematik": Selbst bei 100 aktiven Strings braucht die GC nur etwa eine Sekunde. Keine Ahnung, wieso das Thema GC so aufgeblasen wird, solange man nicht gerade eine Datenbank schreibt, hat man ja im Programm nur eine handvoll aktive String-Variablen. Bei Gold Quest 6 läuft die GC ständig und fällt überhaupt nicht auf.

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Zur Garbage-Collection-"Problematik": Selbst bei 100 aktiven Strings braucht die GC nur etwa eine Sekunde. Keine Ahnung, wieso das Thema GC so aufgeblasen wird..

    Hat hier doch niemand gemacht...!? :?:

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

    Bitte melde dich an, um diesen Link zu sehen.

  • Hat hier doch niemand gemacht...!? :?:

    Ja stimmt, auf Godot bezog ich mich auch nicht. Ich hatte den Ton anderer Texte und Konversationen zum Thema im Ohr, z.B. las sich Bitte melde dich an, um diesen Link zu sehen. ganz schön apokalyptisch (habe aber gerade mal ein paar relativierende Sätze eingefügt), und ähnliches war hier an anderer Stelle im Forum auch schon zu lesen.

    Bitte melde dich an, um diesen Link zu sehen. - Bitte melde dich an, um diesen Link zu sehen.

  • Die Zielgruppe ist Omega ... So doof wie er manchmal tut, ist er zum Glück gar nicht...

    Stimmt nicht. Ich bin viel doofer. Juhuuu! Aus dem Weg! :freude

    Ich hab für Deine schwachen Augen nochmal genau Dein Szenario aus #150 unten angehängt. Schaust Du genau hin, siehst Du, dass sich die beiden "RSTU"-Ringe obendrauf aufgelöst haben. Die "ABCD"s sind Glasblöcke und lösen sich nicht auf (siehe Bitte melde dich an, um diesen Link zu sehen.).

    Oh, entschuldige. Du hast recht. Meine neue Brille ist schuld. :emojiSmiley-102:

    Ja stimmt, auf Godot bezog ich mich auch nicht. Ich hatte den Ton anderer Texte und Konversationen zum Thema im Ohr...

    Die Garbage-Collection kommt!!! Flieht alle in den Schutzbunker. Waaaaah! :schreck!:

  • Also ich habe mir den Post von EgonOlsen71 durchgelesen und nochmal eingehend nachgedacht.

    Wenn ich am Anfang von meinem TSB-Programm d!poke 55,30720:clr eingebe, dann stehen mir folgende größere Bereiche für MS zur Verfügung:

    Code
    30720-32768 ($7000-$8000) = 2048 Bytes
    49152-50167 ($c000-$c3f7) = 1015 Bytes

    Und wenn ich den Heap um 2 KB verkleinere, dann macht das nicht viel aus?

    Habe ich das jetzt richtig verstanden?