Hallo Besucher, der Thread wurde 2,6k mal aufgerufen und enthält 18 Antworten

letzter Beitrag von faddie am

Definierte Zahlenreihe durcheinander bringen

  • Moin,


    ich hab gerade ein algorithmisches Problem, was ich irgendwie effizient lösen möchte.

    Ich habe folgende Zahlenreihe von 2 bis max. 8 und die Zahlen möchte ich möglichst durcheinander an eine andere Stelle kopiert haben. Dabei dürfen es wieder nur genau die Ausgangszahlen sein, also keine Doppelten oder.


    Hintergrund: Es geht darum bis zu 8 Mitspieler nacheinander in zufälliger Reihenfolge auszuwählen.


    Gibt es da irgendein BubbleRandom :) ?

  • Konkret könnte den Rauschgenerator des SIDs für die Zufallszahlen nutzen (vorher stumm schalten...)...also so ähnlich wie das hier vielleicht (in BASIC, weil...schneller zu tippen...):


  • Das hier funktioniert jetzt beinahe.. allerdings ist eine Zahl immer Doppelt drin :S


    Zahlenreihen, die dabei rauskommen sehen so aus:

    21075630

    53641274

    23647005

    52316701

    54120746

    62413053

    47106735


    Einer ist immer doppelt ;(


    Edit: Hab den Code entsprechend gefixt, geht jetzt. :D

  • Das ist streng genommen immer noch nicht ganz korrekt, weil ja erst das DEY und dann der Check auf 0 kommt. D.h.

    für y=0 wird die Schleife nie durchlaufen. Im Grunde macht das aber nicht viel, weil ja bei den ersten 7 Vertauschungen durchaus mal die 0 als Tauschpartner kommen kann.

  • Wieder mal ein Optimierungsvorschlag, weil's mir grad wieder ins Auge gesprungen ist. Da DEY bereits das Zero-Flag entsprechend setzt, kann man sich ein CPY #00 eigentlich sparen.


    dey

    cpy #$00

    bne !loop-


    Und wenn man den Durchlauf bei Wert 0 haben möchte, dann kann man bei Y-Werten bis 127 mit dem Negative-Flag arbeiten:


    dey

    bpl !loop-


    Er springt nicht mehr wenn y FF (= -1) geworden ist.


    Wenn man den vollen Register Umfang braucht, dann kann man sich mit dem Trick behelfen, indem man die Basisadresse bei den indiizierten Adressierungen um 1 verschiebt:

    mov rndPerm8_result-1, x : ZeroPageTemp // Zahl an der Stelle Zufallszahl temp. speichern

    mov rndPerm8_result-1, y : rndPerm8_result, x // Zahl an Stelle y nach y kopieren

    mov ZeroPageTemp : rndPerm8_result-1, y // temp Wert (x) zurückholen und an y speichern


    Man muss dann nur dafür sorgen, das der jeweilige Index dann von 1 bis "Max" geht (und im Array-Bereich bleibt).

  • Ja, kann man. Aber dann optimiert man die nicht ganz richtige Fassung, weil die Schleife eigentlich für 0 auch nochmal laufen sollte.


    Edit: Ja, mit BPL geht das natürlich. Ich würde es an dieser Stelle und für diesen Zweck, besonders zum Lernen, aber nicht machen. Diese Routine wird einmal beim Spielstart aufgerufen und kommt so einmal im Code vor, wenn ich das richtig verstanden habe. Da sind 2 Takte bzw. Bytes zusätzlich für den CPY völlig irrelevant und der Code bleibt besser lesbar, weil er einen sprechenden Vergleich enthält.

  • Stimmt, das ist doof. Bei 3 Spielern kommt da immer 1,2,0 oder 2,0,1 raus und keine andere Verteilung.

    Naja, bei 3 Personen gibt es ja auch nur 2 Reihenfolgen.

    Wenn es nicht unbedingt auf den Startplatz ankommt kann man das so lassen.

    So, wie ich das verstehe, hilft ein weiterer Schleifendurchlauf mit Y=0 nicht.

    Der Tauscht dann nur Platz 0 mit 0.


    Wie genau macht es denn getRandomRange und wie ist das Limit gedacht?
    Ist bei 3 Personen das Limit 2? Liefert getRandomRange dann auch Zufallszahlen von 0 bis 2, oder nur bis 1 weniger?

  • Der ganze Zermon meiner Unsinnigkeiten liegt übrigens hier:

    https://github.com/dkrey/mafia_asm


    getRandom8 sieht so aus (steht in libRandom.asm)

    Also bei 3 Personen ist die Range 0,1 und 2. Klar, im Spiel ist es eigentlich Wurst. Aber es wäre schon schick, wenn die Routine alle Verschwurbelungen ausrechnen könnte.



    EgonOlsen71

    Die Routine kommt häufiger vor. Es geht darum, dass sich der Spieler eine "ehrliche Arbeit" bei den Mitspielen suchen kann, allerdings nur ab einem bestimmten Einkommen. Damit alle Mitspieler - aber immer irgendwer anders- als Arbeitgeber herangezogen werden kömmem, dafür ist die Routine da.

  • getRandom8 sieht so aus (steht in libRandom.asm)

    ...

    Also bei 3 Personen ist die Range 0,1 und 2.

    getRandom8 sieht etwas gefährlich aus.

    Mit 0/0 aufgerufen sehe ich eine Endlos-Schleife, 0/1 wird ein bisschen trödeln und dann immer 0 zurückgeben. Mit 0 las Untergrenze gilt also Zufallszahl bis Obergrenze-1.


    rndPerm8_limit aus deinem oberen Quelltext müsste also bei 3 Spielern zunächst 3 enthalten, um dann das Ergebnis mit Platz 2 zu tauschen. Dann nochmal mit 2 aufgerufen, um Platz 1 zu tauschen. Und dann ist Ende.

  • Die Routine kommt häufiger vor. Es geht darum, dass sich der Spieler eine "ehrliche Arbeit" bei den Mitspielen suchen kann, allerdings nur ab einem bestimmten Einkommen. Damit alle Mitspieler - aber immer irgendwer anders- als Arbeitgeber herangezogen werden kömmem, dafür ist die Routine da.

    Ja, ok. Aber nicht so, dass 2 Takte irgendwas ausmachen würden...

  • Ja, kann man. Aber dann optimiert man die nicht ganz richtige Fassung, weil die Schleife eigentlich für 0 auch nochmal laufen sollte.


    Edit: Ja, mit BPL geht das natürlich. Ich würde es an dieser Stelle und für diesen Zweck, besonders zum Lernen, aber nicht machen. Diese Routine wird einmal beim Spielstart aufgerufen und kommt so einmal im Code vor, wenn ich das richtig verstanden habe. Da sind 2 Takte bzw. Bytes zusätzlich für den CPY völlig irrelevant und der Code bleibt besser lesbar, weil er einen sprechenden Vergleich enthält.

    Das halte ich für überbewertet, dass in einem Assemblercode BPL oder BNE einen Unterschied in der Lesbarkeit macht. Das hinge sehr von den Skills des jeweiligen Code-Lesers ab. Z.B. macht es für mich überhaupt keinen Unterschied. Blutige Anfänger werden mit beiden Problemen haben, weil sie die Auswirkungen der Flags nicht im Hinterkopf haben.

    Daher:

    Wenn der Code ordentlich dokumentiert ist (ja, das ist hier sicher schon zig mal diskutiert worden), nämlich warum und wozu etwas gemacht wird bzw. in welcher Verbindung ein Statement zur Umgebung steht (nicht nur beschrieben wird, was ein Assembler-Befehl macht), dann ist es faktisch für jeden "verständlich". Eine "umständliche" Codierung kann niemals eine richtige Kommentierung ersetzen. Daran zu glauben, könnte man fast verwegen halten. Ich halte es für eine (nicht wegzubringende) Mär, dass im Source-Code Lernübungen unter dem Deckmantel der Lesbarkeit etwas bringt. Das zeigt für sich alleine nur, wie man es nicht machen soll (genau das sollte man eben nicht lernen).


    Wenn man wirklich für Anschauungszwecke und Lehrbücher thematisch zu einer Lösung hinführt, dann mag eine umständlichere Codierung durchaus Sinn ergeben. Nur im Falle von faddies Lernfortschritt, wenn schon die "üblichere" Variante, die eigentlich jeder ernsthafte 6502-Programmierer verwendet, bringt es nicht viel, irgendeinen unüblichen Lernzwischenschritt im Sourcecode zu verewigen. Für wen? Für sich selbst? Nein, er weiß es jetzt schon besser. Für andere? Die sollten sich mit ordentlichen Kommentaren leicht zurecht finden und gleich das richtige Kochrezept, das man üblicherweise einsetzt sehen und lernen.


    Richtig, in diesem Fall bringt die Optimierung in der Initialisierung nicht viel. Aber darum ging es auch nicht. Wenn man es gleich richtig machen kann, dann sollte man dies auch gleich im üblichen 6502-Style machen. :D
    Aber ich will niemanden bekehren oder überreden und von der Überzeugung eines besonderen Lerncodes abbringen, ich gebe lediglich meine Sicht in begründeter Weise wieder.

  • Versteht mich nicht falsch. Ich bin, gerade auf den ollen 8-Bittern, immer ein Freund von Optimierungen. Ich denke nur, a) man sollte damit warten, bis der Algorithmus überhaupt das macht, was er soll und b) ist ein explizit hingeschriebener Compare immer deutlicher, als ein impliziter durch die Flags. Und damit sollten wir das Thema ruhen lassen...Diskussionen über Codestile sind so sinnvoll wie über Frauen oder Autos und führen meistens zu nicht viel. Schreibt man nur für sich selber, ist es eh völlig hupe. Müssen andere das lesen können, dann...ist es mir auch hupe...:D

  • Hoogo : Du bist gut! Der Fehler in getRandom8 mit der 0 war der Grund, warum randomPerm8 nicht mehr funktioniert hat, sobald ich mit bpl "gebranched" habe.


    JeeK Besten Dank für die Optimierungsvorschläge. Ich find's eigentlich ziemlich gut, den cpy wegzulassen. Selbst, wenn ich nach einem Monat Pause wieder alles vergessen habe, ist es ein guter Denkanstoß zu sehen, dass bne trotzdem funzt. Hab allerdings jetzt deinen bpl Tipp umgesetzt.


    EgonOlsen71 Von Optimierungen und Takten bin ich tatsächlich meilenweit entfernt. Es ist ja auch nur ein reines Textspiel.