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
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 */
/* 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 */
/* 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!
|