ARTIKEL X1 - FLAGS UND BITFELDER

von [Win]Elchtest


BITS & BYTES!

Bei einigen Variablen ist es so, dass einzelne Bits oder Gruppen von einzelnen Bits eine bestimmte Bedeutung haben. So kann man zum Beispiel mit einer 8 Bit Variable, die ja binär aus einer Mischung aus insgesamt 8 Nullen und/oder Einsen besteht, 8 verschiedene Ja / Nein Informationen abspeichern. So eine einzelne bitweise Information nennt man "Flag". Zum Beispiel setzt man zum Aktivieren des God-Modus ein Flag, nämlich FL_GODMODE.

In der Datei g_local.h erfährt man mehr darüber:

// gentity->flags
#define FL_GODMODE 0x00000010

Die Eigenschaft der Unverwundbarkeit wird also durch 0x00000010 bestimmt. Die Schreibweise 0x00000010 sagt dem C Compiler, dass er hier das Hexadezimalsystem verwenden soll. Am einfachsten ist es wohl Konvertierungen von dem für uns gewohnten Zehnersystem in das 16er System zu machen, indem man den Windows Taschenrechner (Ansicht: Wissenschaftlich) aus dem Zubehör benutzt. Hier kann man im "Hex"-Modus die Zahl 10 eingeben (vorne stehende Nuller kann man wie gewohnt weglassen), und sieht nach dem Umschalten in den "Bin"-Modus die Zahl 10000. Das bedeuted, dass für den God Status also das fünfte Bit von rechts gesehen relevant ist.

Möchte man nun ein neues Flag einführen, muß man vorsichtig sein, das man kein bereits vorhandenes überschreibt. Man nimmt sich im "Bin"-Modus eine 1 mit einer bestimmten Anzahl von 0 dazu und wandelt diese in "Hex" um. Ist dieser Wert noch unbenutzt, so können wir ihn für ein neues Flag benutzen, in dem wir noch "0x" voranstellen.

WIE ARBEITE ICH MIT FLAGS?

Irgendwie muß man nun Flags setzen und überprüfen können. Möchte man ein spezielles Flag abfragen, z.B. FL_GODMODE, so ist es das Ziel alle anderen Bits des Attribut-Bytes (das die anderen Flags auch noch speichert) auf 0 zu setzen, damit nur noch der eine Bit-Wert übrigbleibt, und man feststellen kann, ob dieses gesetzt ist oder nicht. Mit einer binären UND-Operation ist das überhaupt kein Problem, weil UND alle Bits ausblendet, die nicht in der sogenannten UND-Maske vorkommen. Eine UND-Verknüpfung kann in C mit Hilfe des &-Operators ausgeführt werden. Der Ausdruck

ent->flags & FL_GODMODE

lässt also nur noch das Bit 5 (von rechts aus) stehen, und liefert deswegen das Ergebnis 16 (0x00000010), wenn dieses Bit gesetzt ist. Anderenfalls lautet das Ergebnis 0.

Innerhalb eines if Befehls lässt sich dieser Ausdruck wie folgt einsetzen:

if( (ent->flags & FL_GODMODE) != 0)

/* god modus ist gesetzt, tue dies und das */

else

/* kein god modus an, spieler soll sterben */

Etwas schwieriger wird es, wenn man mehrere Bits gleichzeitig überprüfen möchte. Dann müssen die Wertigkeiten der verschiedenen Bits miteinander addiert werden. Nehmen wir z.B. an, wir wollen überprüfen, ob sowohl god mode, als auch notarget (Gegner sehen einen nicht) aktiviert ist.

#define FL_NOTARGET 0x00000020

Die korrekte Abfrage ist wie gesagt die Summe beider. Dieses mal reicht es nicht alleine auf ungleich 0 zu testen, da dies auch schon eintritt, wenn nur eines der beiden Bits gesetzt wäre. Daher geht man folgendermaßen vor:

if( (ent->flags & (FL_GODMODE + FL_NOTARGET)) == (FL_GODMODE + FL_NOTARGET) )

/* sowohl god modus als auch notarget aktiviert, tue dies, oder das */

else

/* es sind nicht beide gleichzeitig gesetzt. sage "blubb". */

 

Die andere Geschichte ist es, Flags zu setzen. Möchte man auf jeden Fall ein Flag auf 1 setzen, so nimmt man die bitweise ODER-Operation zur Hand.

ent->flags = ent->flags | FL_GODMODE; // lange Form

ent->flags |= FL_GODMODE; // kürzere identische Form

Möchte man mehrere Flags gleichzeitig setzen, so wird wieder addiert:

ent->flags |= FL_GODMODE + FL_NOTARGET;

Was aber tun, wenn man ein Flag auf 0 setzen möchte? Hier kommt wieder eine UND-Verknüpfung zum Einsatz, die jetzt jedoch etwas anders gestaltet werden muß, weil ja nicht mehr alle anderen, sondern das gewünschte Bit ausgeblendet werden soll. Nach den Gesetzen der binären Logik muß die Wertigkeit jetzt mit Hilfe des NOT-Operators (!) invertiert werden, damit das gewünschte Ergebnis zustande kommt. Um also den God-Modus garantiert abzustellen, lautet der Befehl:

ent->flags &= !FL_GODMODE;

Wie gewohnt wird bei mehreren Flags addiert...

Der letzte Fall ist es, wenn wir z.B. in der Konsole "\god" eingeben, dann wollen wir ja, das automatisch das Gegenteil von dem Modus eingestellt wird, der momentan aktiv ist. Also sind wir schon Gott, so wollen wir sterblich werden, sind wir sterblich, so wollen wir zu den Göttern empor. Dafür benutzt man den XOR-Operator (^).

ent->flags ^= FL_GODMODE;

Das wars auch schon, du solltest jetzt keine Probleme mehr haben deine eigenen Statuseinstellungen zu speichern und zu verwenden!