Tips & Tricks für Programmierer

Ein tapferer Krieger

Alle, die sich mit Krieg der Kerne (siehe auch [1]) beschäftigen, sollten einmal unser Programm »Cat Can« (Listing 2) ausprobieren. Denn trotz seines einfachen Prinzips ist es fast nicht zu besiegen. Cat Can stoppt gegnerische Programme, indem es deren Rechenzeit für sinnlose Aktionen verschwendet. Split-Befehle reduzieren die Rechenzeit der noch intakten gegnerischen Programme drastisch und legen sie im Idealfall völlig lahm. Sobald der Feind auf diese Weise gestoppt ist, zerstört Cat Can die letzten Gegner mit Datenbomben.

Beachten Sie beim Austesten, daß die Größe des Speicherrings durch acht teilbar sein muß. Wir verwendeten beispielsweise 2048 Speicherzellen. An dieser Stelle sei auch auf einen Fehler in dem Programm »Corewars« hingewiesen: Der letzte »JMN«-Befehl dient dazu, Cat Can sich nicht selbst umbringen zu lassen. Da jedoch Corewars die indirekte Adressierung mit pre-dekrement falsch bearbeitet, funktioniert diese Methode nicht. Denn sobald ein Überlauf stattfindet, setzt Corewars die Adresse nicht auf Null zurück, sondern erniedrigt sie weiter. Derselbe Fehler findet sich auch bei der »DJN«-Anweisung. Damit ist Cat Can unter »Corewars« nur bedingt lauffähig. Mit »Krieg der Kerne« funktioniert es dagegen problemlos.

(Alexander Kirchner/ba)

[1] »Duell im Computer«, ST-Magazin 1/90, Seite 58 f.

Pop-Up-Menüs in GFA-Basic

Die Menüleiste des GEM ist sehr komfortabel. Denn statt die Befehle mühselig einzutippen oder über schwer nachzuvollziehbare Tastaturkürzel aufzurufen, fahren Sie einfach mit der Maus in die Menüleiste und wählen den gewünschten Menüpunkt aus. Diese Art Menüs heißt Pull-Down-Menüs (zu deutsch etwa »Klappmenüs«). Eine weitere, noch komfortablere Art stellt das Pop-Up-Menü dar. Dieses erscheint auf Mausknopfdruck auf dem Bildschirm nahe beim Cursor. Der Vorteil liegt auf der Hand: Das lästige Anfahren des Menüs entfällt, da das Pop-Up-Menü beim Mauscursor erscheint. Leider unterstützt das AES keine Pop-Up-Menüs. Dazu bedarf es einer kleinen Routine, die Sie in Listing 1 Finden. Wir haben sie der besseren Verständlichkeit wegen in GFA-Basic 3.0 formuliert.

In den Programmzeilen 1 bis 9 demonstrieren wir den Aufruf der Pop-Up-Prozedur »menu«, die Sie ab Zeile 12 finden, »menu« benötigt vier Parameter: Einen Zeiger auf die Rückgabevariable (*num), in der »menu« am Ende die Nummer des ausgewählten Menüpunkts bzw. den Wert -1 (kein ausgewählter Menüpunkt) speichert. Als zweiten Parameter benötigt »menu« ein Stringarray, in dem die Menüpunkte bezeichnet sind (siehe Programmzeilen drei bis acht). Die letzten beiden Parameter geben die X- und Y-Koordinate der linken oberen Ecke des Pop-Up-Menüs an. Es liegt also an Ihnen, wo das Menü erscheint. Sinnvoll sind z. B. die X- und Y-Koordinate der Maus als Bezugspunkt. (Christoph Falk/ba)

.n4
DIM a$(100)
a$(1)="Menu"
a$(2)="Menu"
a$(3)="Menu"
a$(4)="Menu"
a$(5)=MMenu"
a$(6)="Menu"
menu(*num,*a$(),10,50)
'
'
PROCEDURE menu(nura,lp,x,y)
    LOCAL lang,a,b,n,ly,lx.bild$ 
    DIM menu$(100)
    SWAP *lp,menu$() 
    n=1
    REPEAT 
        INC n 
    UNTIL menu$(n)=""
    DEC n
    GRAPHMODE 1
    b=-1
    lang=0
    ly=n*16
    FOR i=1 TO n
        IF LEN(menu$(i))>lang THEN 
            lang=LEN(menuS(i))
        ENDIF 
    NEXT i
    lx=(lang+2)*8
    IF (x+lx)<635 AND (y+ly)<395 and x>5 AND y>5 
        fy=INT(ly/n)
        DEFFILL 0,1,1
        GET x-4.y-9,x+lx+3,y+ly+4,bild$
        PBOX x-4,y-9,x+lx+3,y+ly+2 
        BOX x-4,y-5,x+lx+3,y+y+2 
        BOX x-1,y-2,x+lx,y+ly-1 
        PBOX x-4,y-9,x+lx+3,y-2 
        BOX x-4,y-9,x+lx+3,y-2 
        BOX x-2,y-6,x+lx+2,y-5 
        FOR s=1 TO n 
            TEXT x+6,y+s*16-4,menu$(s)
        NEXT s
        '
        GRAPHMODE 3 
        DEFFILL 1,1,1 
        REPEAT
            IF FN in(x,y+9,lx,ly-l4)=1 
                yk=MOUSEY
                a=INT((yk-y)/fy)*fy 
                IF b<>a
                    IF b>=0 AND b<n*16 
                        DEFFILL 0,1,1
                        PBOX x-3,b+y-1,x+lx+2,y+b+16 
                    ENDIF
                    DEFFILL 1,1,1
                    PBOX x-3,a+y-1,x+lx+2,y+a+l6 
                    b=a 
                ENDIF 
            ENDIF 
        UNTIL MOUSEK=1 
        IF FN in(x,y,lx,ly)=l 
            *num=a/l6+1 
        ELSE 
            *num=-1 
        ENDIF
        '
        PUT x-4,y-9,bild$
    ELSE
        *num=-1
    ENDIF
    SWAP *lp,menu$()
    ERASE menu$()
    DEFFN in{x,y,lx,ly)=ABS(MOUSEX>x AND MOUSEY>y AND MOUSEX<(x+lx) AND MOUSEY<(y+ly))
RETURN
'
'                     Pop-Up Menü 
'
'          Geschrieben von FALK CHRISTOPH 
'
'                     15.11.1989
'

Listing 1. Stellen auch Sie komfortable Pop-Up-Menüs unter GFA-Basic 3.0 dar

Joystickabfrage in C

Turbo-C ist sicherlich eine der mächtigsten Programmiersprachen für den ST. Die Bibliotheken sind schnell und lassen im Funktionsumfang fast keine Wünsche mehr offen. Besonders die Spieleprogrammierer vermissen aber eine Routine zur unkomplizierten Joystickabfrage. Mittlerweile gibt es zwar eine Vielzahl von Vorschlägen zur Abfrage des Joysticks, aber entweder sind diese Routinen zu lang oder zu unhandlich. Um diesen Mißstand zu beseitigen, stellen wir eine kurze, universelle Joystickabfrage in Turbo-C und Assembler vor.

Der Kern, die Assembler-Routine (Listing 4), speichern Sie unter dem Namen JOYSTICK.S. Die Headerdatei (Listing 2) sollten Sie JOYSTICK.H benennen. Das C-Programm im Listing 3 demonstriert den Einsatz der Joystickroutinen. In Listing 4 finden Sie eine vorgefertigte Projektdatei, die ein ablauffertiges Programm erzeugt.

Beachten Sie, daß wir darin das Assembler-Programm mit ».S« aufgenommen haben. Damit geben wir Turbo-C an, JOYSTICK.S mit dem MAS.TTP zu assemblieren. Besitzer eines anderen Assemblers sollten die Assembler-Routine separat assemblieren und eine DRI-Objektdatei erzeugen. Um diese in die Projektdatei einzubinden, ersetzen Sie einfach das ».S« durch ».O«.

Die Joystick-Abfrage schalten Sie mit »j_on()« ein. Von nun an werden Sie von den beiden globalen Variablen »joyst1« und »joyst2« über den Status der Joysticks in Port 1 und 2 informiert. Jede Bewegung verändert den Wert der Variablen. Ein erneuter Aufruf von »j_on()« ist nicht nötig. Um die Joystick-Abfrage wieder abzuschalten, rufen Sie »j_off()« auf.

Die Werte, die die Variablen »joyst1« und »joyst2« annehmen können, finden Sie in der Textbox.

(Ulrich Eckartz/ba)

Listings 1-4

Diese Werte nehmen die beiden Variablen »joyst1« und »joyst2« an. Kombinationen sind möglich:

oben
5 1 9
links 4 0 8 rechts
6 2 10
unten
Fire + 128

Bildverwaltung in ST-Basic

Bilder sagen oft mehr als tausend Worte. Und Programme, die sich der Bildersprache bedienen, sind doppelt so attraktiv. Doch dabei stellt sich vielen Programmierern ein Problem in den Weg: Wie erzeugt, lädt, verwaltet und zeigt man Bilder? In Listing 3 finden Sie drei Prozeduren für Omikron-Basic, die Ihnen diese Last abnehmen.

Die Prozedur »Bild_Speichern« (Programmzeile 49 ff.) erlaubt Ihnen, einen beliebigen Bildschirmausschnitt zu speichern. Dazu übergeben Sie fünf Parameter: den Bildnamen, die X- und die Y-Koordinate des linken oberen Ecks sowie die Breite und Höhe des Ausschnitts. Um den kompletten Bildschirm im monochromen Modus zu speichern, geben Sie beispielsweise die Parameter »"HIRES ",0,0,640,400« an. In diesem Beispiel sind die beiden Koordinaten x und y Null, die Breite des Ausschnitts beträgt 640 und die Höhe 400 Pixel.

Um ein Bild zu laden, rufen Sie die Prozedur »Bild_Laden« auf, die Sie ab Programmzeile 57 finden. Sie verlangt zwei Parameter: den Bildnamen und die Bildnummer. Die Bildnummer ist eine Art ID, mit dessen Hilfe Sie später erneut auf das Bild zurückgreifen können.

Ein geladenes Bild zeigen Sie mit der letzten Prozedur »Bild_Zeigen« an. Hierzu übergeben Sie die X- und Y-Koordinate der oberen linken Ecke, den Zeichenmodus (siehe Handbuch) und die Bildnummer. Er eignet sich besonders gut, da er aus einem Bildschirmausschnitt einen zusammenhängenden Block mit einem Header (Breite und Höhe) macht.

Die Prozeduren bedienen sich des »BITBLT«-Befehls, um Bildausschnitte für das Speichern vorzubereiten und darzustellen.

Mit den Befehlen »BSAVE« und »BLOAD« speichern und laden die Prozeduren den BITBLT-Block. Ein Anwendungsbeispiel der drei Prozeduren finden Sie in den Zeilen 0 bis 43.

(Peter Kraiczy/ba)

; CAT CAN
;
; Written by A. Kirchner with help from J. Tenzer 
; and W. Rohmann
;
start   MOV grab, @dest 
        MOV prog, <dest 
        SUB #7, dest 
        JMN start, dest 
        SUB #4, dest 
kill    MOV dest, <dest
        JMN kill, dest 
prog    SPL 0
grab    JMP -1
deat    DAT -16

Listing 2. Ein fast unbesiegbares Kampfprogramm nach den Regeln von »Krieg der Kerne

0   PRINT CHR$(27)+"f"
1   CLIP 0,0,639,399
2   REPEAT
3       MODE = 1
4       CLS
5       FOR A= 1 TO 30
6           X= RND(640)
7           Y= RND(400)
8           Radius= RND(50)*20
9           Stil= RND(1)*2
10          Index= RND(22)
11          FILL STYLE= Stil, Index
12          PCIRCLE X,Y,Radius
13      NEXT A
14      TEXT 200,200,"Bitte Ausschnitt wählen..."
15      MODE= 3
16      MOUSEON
17      REPEAT
18          Maus_X= MOUSEX
19          Maus_Y= MOUSEY
20      UNTIL MOUSEBUT= 1
21      MOUSEOFF
22      REPEAT
23          Hoehe= ABS(Maus_Y-MOUSEY)
24          Breite= ABS(Maus_X-MOUSEX)
25          BOX Maus_X,Maus_Y,Breite.Hoehe
26          BOX Maus_X,Maus_Y,Breite,Hoehe
27      UNTIL MOUSE8UT= 0
28      MODE= 1
29      MOUSEON
30      FORM_ALERT(2,"[3][ Bitte Diskette elnlegen. | Ich speichere den Ausschnitt | Jetzt ab. ][ OK | ABBRUCH ]",Button)
31      MOUSEOFF
32      IF Button= 2 THEN
33          EXIT TO Ende
34      ENDIF
35      Bild_Speichern("Bild",Maus_X,Maus_Y,Breite,Hoehe)
36      CLS
37      PRINT @(11,3);"Ich lade Jetzt den abgespeicherten Ausschnitt auf die Position (0.0)"
38      WAIT 4
39      CLS
40      Bild_Laden("Bild",1)
41      Bild_Zeigen(0,0,3,1)
42      REPEAT UNTIL MOUSEBUT
43  UNTIL 0
44  '
45  -Ende
46  CLS
47  END
48  '
49  DEF PROC Bild_Speichern(File_Name$,X,Y,Breite,Hoehe)
50      LOCAL Adresse,Speicher
51      Speicher= (Breite*15)/16*Hoehe*2+6
52      Adresse= MEMORY(Speicher)
53      BITBLT X,Y,Breite,Hoehe TO Adresse
54      BSAVE File_Name$+".BLD",Adresse,Speicher
55  RETURN
56  '
57  DEF PROC Bild_Laden(File_Name$,Bild_Nummer)
58      LOCAL Bild_Laden_Flag
59      IF Bild_Laden_Flag= 0 THEN
60          DIM Adresse(10)
61          Bild_Laden_Flag= 1
62      ENDIF
63      File_Name$= File_Name$+".BLD"
64      GEMDOS(Dta_Buffer,$2f)
65      File_Name= LPEEK(SEGPTR+28)+LPEEK(VARPTR(File_Name$))
66      GEMDOS(.$4e,HIGH(File_Name),LOW(File_Name),$3f)
67      Datei_Laenge= LPEHC(DtaBuffer-26)
68      Adresse(Bild_Nummer)= MEMORY(Datei_Laenge)
69      BLOAD File_Name$,Adresse(Bild_Nummer)
70  RETURN
71  '
72  DEF PROC Bild_Zeigen(X,Y,Modus,Bild_Nummer)
73      Breite= WPEEK(Adresse(Bild_Nummer)+2)
74      Hoehe= WPEEK(Adresse(Bild_Nummer)+4)
75      BITBLT Adresse(Bild_Nummer) TO X,Y,Breite,Hoehe,Modus
76  RETURN

Listing 3. Drei Prozeduren und ein Anwendungsbeispiel zur komfortablen Blldschlrmverwaltung unter Omikron-Basic

    xdef myjoy
    xref joyst1,joyst2
    text            ; Für DEVPAC 2.0: section text
myjoy:  movem.l a0-a1,-(a7)
    addq.l  #1,a0
    move.b  (a0)+,joyst1
    move.b  (a0),joyst2
    movea.l (a7)+,a0-a1
    rts

Listing 4. Der Kern der Joystickabfrage Ist Assembler. Nennen Sie diese Datei JOYSTICKS.

/* Variablendef. */
long oldjoy ;
char code = 0x14 ;
char mausan[] = { 0x15. 0x8 );
unsigned char joyst1, joyst2;
KBDVBASE *kvb;

/* Prototypen */ 
extern void myjoy(void); 
void j_on(void); 
void j_off(void);

/* Joystick an */ 
void j_on(void)
(
    kvb = Kbdvbase() ;
    oldjoy = (long)kvb->kb_joyvec: /* Alte Routine sichern */ 
    kvb->kb_joyvec = myjoy;                 /* Neue setzen */
    Ikbdws(0, &code);/* An Tastaturprozessor: Joysticks an */
}

/* Joystick aus */ 
void jo_ff(void)
{
    Ikbdws(1, mausan);              /* Joysticks aus und Maus an */
    kvb->kb_joyvec = (void *)oldjoy;    /* Alte Routine zurück */
}

Listing 5. Um In den Genuß unserer komfortablen Joystickabfrage zu kommen, binden Sie diese Headerdatei In Ihren C-Quelltext ein

#include <stdio.h> 
#include <tos.h> 
#include <joystick.h>

void main(void)
{
    j_on(); /* Joystickroutine elnschalten */

    while (!Bconstat(2)) /* ...bis Taste gedrückt wird */ 
        printf("%d %d\n",joyst1, joyst2) ;

    j_off(); /* Joystickroutine auaachalten */
}

Listing 6. Ein Anwendungsbelsplel für die Joystickabfrage In Turbo-C

; PRJ-Datei JOYSTICK.PRJ:
*; name of executable program is topmost window

= ; list of modules follows...

TCSTART.O ; startup code
JOYSTICK.S

* ; compile topmost window

TCFLTLIB.LIB 
TCSTDLIB.LIB 
TCEXTLIB.LIB 
TCTOSLIB.LIB

Listing 7. Mit dieser Projektdatel erzeugen Sie ein ablauftertiges Programm aus den Listings 4 bis 6



Links

Copyright-Bestimmungen: siehe Über diese Seite