Rogue

Stellt hier eure Projekte vor.
Internetseiten, Skripte, und alles andere bzgl. Python.
Antworten
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Als Wochenendprojekt habe ich eine C-Version von Rogue, einem, nein dem ersten, Computerrollenspiel in Python portiert.

Hier seht ihr unseren tapferen Helden "@", wie er auf der Suche nach dem Amulet von Yendor unmittelbar davor steht, den ersten Level des Dungeon über die Treppe "%" zu verlassen und den zweiten Level zu betreten:
Bild

Falls jemand an dem Quelltext interessiert ist, packe ich ihn gerne auf Google Code oder so. Ich möchte mich jedoch gleich von der Form distanzieren. Ich habe versucht, den (antiken) C-Code 1:1 in Python zu übertragen, andere Python-Programme würde ich so sicherlich nicht schreiben :) Aus 6282 Zeilen C sind so 4065 Zeilen Python geworden (keine Blockenden zu haben, macht es kürzer). Ich habe bislang ungefähr 15 Stunden für die Portierung gebraucht. Den Quelltext übersetzen war eins - dann aber meine Flüchtigkeitsfehler finden, hat echt Zeit gekostet und da sind bestimmt immer noch welche.

Ich nutze curses, damit funktioniert das wahrscheinlich nur auf dem Mac und unter Linux. Im Prinzip muss man aber nur ein Zeichen an einer bestimmten Bildschirmposition ausgeben können und einzelne Zeichen über die Tastatur einlesen können, ohne dass man etwas sieht oder RETURN drücken muss.

Da man hier ja Python-Code zeigen soll, hier noch die Hauptschleife ;)

Code: Alles auswählen

def main():
    init()
    while True:
        clear_level()
        make_level()
        put_objects()
        put_stairs()
        put_monsters()
        put_player()
        light_up_room()
        print_stats()
        play_level()
        g.level_objects.next_object = None
        g.level_monsters.next_object = None
        clear()
Stefan
Benutzeravatar
Craven
User
Beiträge: 223
Registriert: Dienstag 24. Januar 2006, 13:37

sma hat geschrieben:Falls jemand an dem Quelltext interessiert ist, packe ich ihn gerne auf Google Code oder so.
Hi Stefan,

Ich würds mir gerne mal ansehen, schon alleine weil mich interessiert, wie genau du die level aufbaust.
Die Form ist sicher auch nicht uninteressant. ;)

Gruß, Craven
Zuletzt geändert von Craven am Freitag 16. Januar 2009, 13:51, insgesamt 1-mal geändert.
[code]q = 'q = %s; print q %% repr(q)'; print q % repr(q) [/code]
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Craven hat geschrieben:Ich würds mir gerne mal ansehen, schon alleine weil mich interessiert, wie genau du die level aufbaust.
Der Aufbau der Level ist recht einfach. Nicht ich, sondern ein mir unbekannter Programmierer hat sich das bereits Ende der 70er Jahre ausgedacht:

Der Bildschirm wird in 3x3 Segmente á 26x7 aufgeteilt, in denen sich je ein Raum zufälliger Größe befinden kann. Nummeriert man die Segmente von oben links nach unten rechts, existieren entweder immer 1,4,7 oder 3,4,5. Die restlichen 6 Räume entstehen mit einer Wahrscheinlichkeit von ja 45%. Benachbarte Räume werden jetzt mit zufällig aussehenden Gängen verbunden und mit einigen toten Gängen dekoriert.

Ich würde das vielleicht so programmieren:

Code: Alles auswählen

def create_level():
    must_exist = choose([1, 4, 7], [3, 4, 5])
    for r in range(9):
        if r in must_exist or percent(45):
            create_room(r)
    for r in range(9):
        try_to_connect(r, r + 1, must_exist)
        try_to_connect(r, r + 3, must_exist)
    for r1, r2, r3 in [[0, 1, 2], [0, 3, 6], [2, 5, 8], [6, 7, 8]]:
        if room(r1) and not room(r2) and room(r3) and percent(75):
            create_passage(r1, r3)

def create_room(r):
    height = rnd(4, 6)
    width = rnd(7, 26)
    row = rnd(0, 6 - height) + (r / 3) * 7
    col = rnd(0, 26 - width) + (r % 3) * 27
    rooms[r] = Room(row, col, height, width)
    
def try_to_connect(r1, r2, must_exist):
    if is_adjacent(r1, r2):
        if r1 in must_exist or r2 in must_exist or percent(20):
            create_passage(r1, r2)

def is_adjacent(r1, r2):
    return room(r1) and room(r2) and (
        (abs(r1 % 3 - r2 % 3) == 1 and same_row(r1, r2)) or
        (abs(r1 / 3 - r2 / 3) == 1 and same_col(r1, r2)))

def room(r):
    return rooms[r] if 0 <= r < 9 else None

def create_passage(r1, r2):
    if r2 > r1: r1, r2 = r2, r1
    if same_row(r1, r2):
        start_row = room(r1).random_row
        start_col = room(r1).right_col + 1
        end_row = room(r2).random_row
        end_col = room(r2).left_col - 1
        middle = (start_col + end_col + rnd(0, 1)) / 2
        # horizontal line from start to middle
        # then vertical line if rows differ
        # then horizontal line to end
    elif same_col(r1, r2):
        start_row = room(r1).bottom_row + 1
        start_col = room(r1).random_col
        end_row = room(r2).top_row - 1
        end_col = room(r2).random_col
        middle = (start_row + end_row + rnd(0, 1)) / 2
        # vertical line from start to middle
        # then horizontal line if cols differ
        # then vertical line to end
    else:
        assert False
        
def same_row(r1, r2): return r1 / 3 == r2 / 3
def same_col(r1, r2): return r1 % 3 == r2 % 3
Stefan
Vingdoloras
User
Beiträge: 53
Registriert: Sonntag 2. Dezember 2007, 18:25

http://paste.pocoo.org/

Der wurde mir empfohlen (naja mir wurde nur gesagt, ich solle meinen Code darauf Pasten)

Hab mich mal im Internet umgeschaut... eine Browserversion davon gefunden... das Spiel is witzig... nur leider kapier ich nicht, wie ich ein Level weiterkomme... nach ner Weile bin ich die Gänge einfach nurnoch mit gedrückter Richtungstaste langgelaufen und hab plötzlich gemerkt, wie man angreift, weil ich ein oder zwei Monster quasi überrannt habe :D
Trotzdem... also % soll die Treppe sein? Wie nutz' ich diese Treppe? Ich bin im zweiten Level hängengeblieben (naja "im" ist ja "in dem" aber die Level werden ja zufällig generiert... daher müsste es eigentlich heißen "in einem zweiten Level")... Ich hatte (scheinbar) alle Räume entdeckt, das % hatte ich auch entdeckt, nur konnte ich halt nix damit machen...

Ansonsten is das Spiel interessant, ich würde gerne mal den Code sehn :wink:
EDIT: Wie werden denn die Items eingefügt? Gibt es da einfach eine Liste oder sind das jeweils auch noch keine Codestücke, die dann jeweils in einen Raum eingefügt werden? Es wäre doch sicher mal spannend, ein paar neue Gegenstände einzufügen oder so :)
Leonidas
Python-Forum Veteran
Beiträge: 16025
Registriert: Freitag 20. Juni 2003, 16:30
Kontaktdaten:

Vingdoloras hat geschrieben:http://paste.pocoo.org/

Der wurde mir empfohlen (naja mir wurde nur gesagt, ich solle meinen Code darauf Pasten)
Ja, für Snippets. Ein 4000 Zeilen langes Programm dass ggf. aus mehreren Dateien besteht ist dort eher schlecht aufgehoben. Etwa: nimm Paste #23954 und nenne es ``main.py``, dann nimm Paste #23412 und nenne es ``level.py`` und dann nehme Paste ...
My god, it's full of CARs! | Leonidasvoice vs (former) Modvoice
Benutzeravatar
Craven
User
Beiträge: 223
Registriert: Dienstag 24. Januar 2006, 13:37

Leonidas hat geschrieben:Ja, für Snippets. Ein 4000 Zeilen langes Programm dass ggf. aus mehreren Dateien besteht ist dort eher schlecht aufgehoben. Etwa: nimm Paste #23954 und nenne es ``main.py``, dann nimm Paste #23412 und nenne es ``level.py`` und dann nehme Paste ...
Dafür wäre dann das Projektmanagement gut. Da kann man ausgewählte Dateien in einem Archiv herunterladen, etc.
[code]q = 'q = %s; print q %% repr(q)'; print q % repr(q) [/code]
BlackJack

Bin gerade über diesen Telepolis-Artikel gestolpert: Spielerlebnis für Hartgesottene. Geht um das "rouge-like" Slaves to Armok II: Dwarf Fortress.
sma
User
Beiträge: 3018
Registriert: Montag 19. November 2007, 19:57
Wohnort: Kiel

Da ich mehr erstmal nicht schaffe, gibt's hier den Quelltext.

Zu Darf Fortress kann ich nur sagen: Falsches Betriebssystem. Die Screenshots sehen aber, sagen wir, originell aus... mutiges Konzept im Jahre 2008. Zu "Projektmanagement" kann ich nur sagen: "Arg! Meine Augen" ;)

Absteigen kann man bei Rogue mit ">". Bei (Net)Hack ist das dann auch das Symbol für Treppen. "%" war da glaube ich Nahrung... so lange her.

Zu der Frage nach Gegenständen: Rogue verwaltet einfach eine Liste. Jeder Gegenstand hat einen Typ und eine Position auf dem Bildschirm. Mehr ist da nicht hinter. Pro Level werden jetzt ein paar zufällige Gegenstände erzeugt und zufällig verteilt. Es gibt magische Schriftrollen, Tränke, Zauberstäbe, Waffen, Rüstung und etwas zu essen. Das besondere ist, dass zunächst nicht bekannt ist, was die Dinge tun. Das muss man ausprobieren (oder den Zauberspruch zum Identifizieren eines anderen Gegenstands nutzen). Die besondere Funktion ist über das ganze Spiel verteilt.

Ich denke nicht, dass die Implementierung bei Rogue ein Vorbild sein sollte. Hier schreit alles nach Objektorientierung - insbesondere wenn man so ein Spiel erweitern möchte. Idealerweise könnten Dritte neue Gegenstände oder auch Monster bauen und dann in ein existierendes Spiel einklinken. Für Java hatte ich vor einigen Jahren mal über so etwas nachgedacht, aber einfache statische Vererbung ist nicht mächtig genug. Pythons Dynamik und Metaprogrammierung könnte hier besser geeignet sein.

Stefan
Benutzeravatar
BlackVivi
User
Beiträge: 762
Registriert: Samstag 9. Dezember 2006, 14:29
Kontaktdaten:

sma hat geschrieben:Zu Darf Fortress kann ich nur sagen: Falsches Betriebssystem. Die Screenshots sehen aber, sagen wir, originell aus... mutiges Konzept im Jahre 2008. Zu "Projektmanagement" kann ich nur sagen: "Arg! Meine Augen" ;)
Läuft aber hervorragend unter Wine. Das Spiel hab ich schon damals gespielt als's noch keirner kannte :3
Antworten