diff --git a/Makefile b/Makefile index 6bd384f..d28716d 100644 --- a/Makefile +++ b/Makefile @@ -1,7 +1,7 @@ DBG = -g CC = gcc WARNFLAGS = -Wall -Wmissing-declarations -Wdeclaration-after-statement -Wcast-align -Winline -Wsign-compare -Wnested-externs -Wpointer-arith -Wformat-security -override CFLAGS += -D_REENTRANT -O2 $(shell sdl-config --cflags) $(DBG) $(WARNFLAGS) +override CFLAGS += -D_REENTRANT $(shell sdl-config --cflags) $(DBG) $(WARNFLAGS) .PHONY: all clean install all: sdlbomber diff --git a/bomber.h b/bomber.h index b526e67..522b8b6 100644 --- a/bomber.h +++ b/bomber.h @@ -59,9 +59,13 @@ typedef struct solid uchar *graphics; } solid; -typedef struct player -{ - struct player *next; +typedef struct listhead listhead; +struct listhead { + listhead *prev, *next; +}; + +typedef struct player { + listhead list; int xpos,ypos; int flags; int abilities; @@ -95,12 +99,8 @@ typedef struct damage { int xsize,ysize; } damage; -typedef struct list { - void *next; -} list; - typedef struct bomb { - struct bomb *next; + listhead list; int type; int xpos,ypos; int px,py; @@ -115,11 +115,12 @@ typedef struct bomb { #define BOMB_NORMAL 1 #define BOMB_CONTROLLED 2 #define BOMBLIFE 60 +#define BOMB_CONTROLLED_LIFE 150 #define FLAMELIFE 15 #define DECAYLIFE 15 typedef struct flame { - struct flame *next; + listhead list; int xpos,ypos; int px,py; int timer; @@ -133,23 +134,21 @@ typedef struct flame { #define FL_RIGHT 4 typedef struct brickdecay { - struct brickdecay *next; + listhead list; int xpos,ypos; int px,py; int timer; } brickdecay; -typedef union listitem listitem; -union listitem { - listitem *next; - bomb b; - flame f; - brickdecay bc; - player p; -}; +typedef struct bonustile { + listhead list; + int xpos,ypos; + int px,py; + int type; +} bonustile; typedef struct generic { - struct generic *next; + listhead list; int xpos,ypos; int px,py; int timer; @@ -159,13 +158,6 @@ typedef struct generic { int data1,data2; } generic; -typedef struct bonustile { - struct bonustile *next; - int xpos,ypos; - int px,py; - int type; -} bonustile; - enum tile_types { TILE_NONE = -1, TILE_DISEASE = 0, @@ -217,7 +209,6 @@ enum tile_types { #define MAXSETS 8 #define MAXSPRITES 256 #define MAXDAMAGES 512 -#define MAXBOMBSDETONATED 32 extern char exitflag; diff --git a/draw.c b/draw.c index c6439e1..a625051 100644 --- a/draw.c +++ b/draw.c @@ -53,7 +53,7 @@ int bigfontxsize,bigfontysize,bigfontyspace; static int textx,texty; -static char *remapstring="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< ="; +static const unsigned char *remapstring = (const unsigned char*) "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZ.:!?\177/\\*-,>< ="; static char asciiremap[256]; /* On screen array variables */ @@ -202,16 +202,16 @@ static void texthome(void) { textx=texty=10; } -// static void drawstring(int xpos,int ypos,char *str) { -// char ch; -// -// while((ch=*str++)) { -// drawfigure(xpos,ypos,font+asciiremap[toupper(ch)]); -// xpos+=fontxsize; -// } -// } +void drawstring(int xpos, int ypos, const char *str) { + char ch; -void drawbigstring(int xpos,int ypos,char *str) { + while((ch=*str++)) { + drawfigure(xpos,ypos,font+asciiremap[toupper(ch)]); + xpos+=fontxsize; + } +} + +void drawbigstring(int xpos, int ypos, const char *str) { char ch; while('\0' != (ch=*str++)) { @@ -220,7 +220,7 @@ void drawbigstring(int xpos,int ypos,char *str) { } } -void centerbig(int y,char *str) { +void centerbig(int y, const char *str) { int w; w=strlen(str)*bigfontxsize; @@ -363,7 +363,7 @@ int arraytoscreeny(int y) { static void loadfonts(void) { int i,j; - char *p; + const unsigned char *p; getsingle(fontname,font,NUMCHARACTERS); getsingle(bigfontname,bigfont,NUMCHARACTERS); @@ -377,7 +377,7 @@ static void loadfonts(void) { memset(asciiremap,j,sizeof(asciiremap)); p=remapstring; i=0; - while(*p && i<40) + while(*p && ixpos=arraytoscreenx(x); pl->ypos=arraytoscreeny(y); pl->color=color; @@ -105,12 +102,22 @@ static void initplayers(void) { } } +static void resetstats(void) { + int i; + + host_deaths = host_kills = 0; + for (i = 0; i < MAXNETNODES; i++) { + netnodes[i].deaths = netnodes[i].kills = 0; + } +} + static void firstzero(void) { mycount = mydatacount = 0; memset(latestactions,0,sizeof(latestactions)); memset(latestcounts,0,sizeof(latestcounts)); memset(actionblock,0,sizeof(actionblock)); actioncount = 0; + resetstats(); } static void initgame() { @@ -124,14 +131,13 @@ static void initgame() { set_game_options(&configopts); gameframe=0; allocthings(); - initheader(&activebombs); - initheader(&activeflames); - initheader(&activedecays); - initheader(&activebonus); - initheader(&activeplayers); - initheader(&activegeneric); - - detonateput=detonatetake=0; + list_init_head(&activebombs); + list_init_head(&detonatebombs); + list_init_head(&activeflames); + list_init_head(&activedecays); + list_init_head(&activebonus); + list_init_head(&activeplayers); + list_init_head(&activegeneric); p=bonuschances; bonustotal=0; @@ -174,7 +180,7 @@ static void initgame() { static void addflame(player *owner,int px,int py) { flame *fl,*fl2; - fl=allocentry(); + fl = allocentry(flame); if(!fl) return; addtail(&activeflames,fl); field[py][px]=FIELD_FLAME; @@ -210,7 +216,7 @@ static void dropbomb(player *pl,int px,int py,int type){ bomb *bmb; if(field[py][px]!=FIELD_EMPTY) return; - bmb=allocentry(); + bmb = allocentry(bomb); if(!bmb) return; playsound(3); addtail(&activebombs,bmb); @@ -227,41 +233,11 @@ static void dropbomb(player *pl,int px,int py,int type){ bmb->owner=pl; } -static void adddetonate(bomb *bmb) { - if(bmb->type==BOMB_OFF) return; - - bmb->type=BOMB_OFF; - field[bmb->py][bmb->px]=FIELD_EXPLODING; - info[bmb->py][bmb->px]=0; - detonated[detonateput++]=bmb; - detonateput%=MAXBOMBSDETONATED; -} - -static void processbombs() { - bomb *bmb; - - bmb=activebombs.next; - while(bmb) { - switch(bmb->type) { - case BOMB_NORMAL: - ++bmb->timer; - if(bmb->timer==BOMBLIFE) - adddetonate(bmb); - ++(bmb->figcount); - break; - case BOMB_CONTROLLED: - ++(bmb->figcount); - break; - } - bmb=bmb->next; - } -} - static void adddecay(int px,int py) { brickdecay *bd; int xpos,ypos; - bd=allocentry(); + bd = allocentry(brickdecay); if(!bd) return; field[py][px]=FIELD_EXPLODING; bd->xpos=arraytoscreenx(px); @@ -279,7 +255,7 @@ static void adddecay(int px,int py) { static void addbonus(int px,int py,int type) { bonustile *bonus; - bonus=allocentry(); + bonus = allocentry(bonustile); if(!bonus) return; addtail(&activebonus,bonus); bonus->px=px; @@ -313,7 +289,40 @@ static void deletebonus(bonustile *bonus) { py=bonus->py; field[py][px]=0; info[py][px]=0; - delink(&activebonus,bonus); + list_del(&bonus->list); + freeentry(bonus); +} + +static void adddetonate(bomb *bmb) { + if (bmb->type==BOMB_OFF) return; + + bmb->type = BOMB_OFF; + field[bmb->py][bmb->px] = FIELD_EXPLODING; + info[bmb->py][bmb->px] = 0; + + removeitem(bmb); + addtail(&detonatebombs, bmb); +} + +static void processbombs() { + bomb *bmb, *next; + + list_for_each_entry_safe(bmb, next, &activebombs, list) { + ++(bmb->figcount); + ++bmb->timer; + switch(bmb->type) { + case BOMB_NORMAL: + if (bmb->timer == BOMBLIFE) + adddetonate(bmb); + break; + case BOMB_CONTROLLED: + if (bmb->timer == BOMB_CONTROLLED_LIFE) { + bmb->timer = 0; + bmb->type = BOMB_NORMAL; + } + break; + } + } } static void flameshaft(player *owner,int px,int py,int dx,int dy,int power) { @@ -361,7 +370,8 @@ static void detonatebomb(bomb *bmb) { py=bmb->py; power=bmb->power; owner=bmb->owner; - delink(&activebombs,bmb); + list_del(&bmb->list); + freeentry(bmb); addflame(owner,px,py); flameshaft(owner,px,py,-1,0,power); flameshaft(owner,px,py,0,-1,power); @@ -370,52 +380,43 @@ static void detonatebomb(bomb *bmb) { } static void dodetonations(void) { - int i=0; + int i = 0; + bomb *bmb; - while(detonatetake!=detonateput) { + while (!list_empty(&detonatebombs)) { + bmb = (bomb*) detonatebombs.next; ++i; - detonatebomb(detonated[detonatetake]); - detonatetake=(detonatetake+1) % MAXBOMBSDETONATED; + detonatebomb(bmb); } if(i) playsound((myrand()&1) ? 0 : 4); } static void processflames(void) { - flame *fl,*fl2; + flame *fl, *next; - fl=activeflames.next; - while(fl) { + list_for_each_entry_safe(fl, next, &activeflames, list) { ++(fl->timer); - fl=fl->next; - } - fl=activeflames.next; - while(fl) { - if(fl->timer==FLAMELIFE) - { + + if(fl->timer==FLAMELIFE) { field[fl->py][fl->px]=FIELD_EMPTY; info[fl->py][fl->px]=0; - fl2=fl; - fl=fl->next; - delink(&activeflames,fl2); - } else - fl=fl->next; + list_del(&fl->list); + freeentry(fl); + } } } static void processdecays() { - brickdecay *bd,*bd2; + brickdecay *bd, *next; - bd=activedecays.next; - while(bd) { + list_for_each_entry_safe(bd, next, &activedecays, list) { ++(bd->timer); - if(bd->timer==DECAYLIFE) { - field[bd->py][bd->px]=FIELD_EMPTY; - trybonus(bd->px,bd->py); - bd2=bd; - bd=bd->next; - delink(&activedecays,bd2); - } else - bd=bd->next; + if(bd->timer == DECAYLIFE) { + field[bd->py][bd->px] = FIELD_EMPTY; + trybonus(bd->px, bd->py); + list_del(&bd->list); + freeentry(bd); + } } } @@ -426,8 +427,7 @@ static void drawbombs(void) { int color; int xpos,ypos; - bmb=activebombs.next; - while(bmb) { + list_for_each_entry(bmb, &activebombs, list) { color=bmb->owner->color; figtab=(bmb->type==BOMB_NORMAL) ? bombs1[color] : bombs2[color]; j=bmb->figcount % (NUMBOMBFRAMES<<1); @@ -436,7 +436,6 @@ static void drawbombs(void) { ypos=tovideoy(bmb->ypos)-3; addsprite(xpos,ypos,figtab+j); - bmb=bmb->next; } } @@ -446,8 +445,7 @@ static void drawflames(void) { int color; int fig; - fl=activeflames.next; - while(fl) { + list_for_each_entry(fl, &activeflames, list) { color=fl->owner->color; xpos=tovideox(fl->xpos); ypos=tovideoy(fl->ypos); @@ -455,29 +453,24 @@ static void drawflames(void) { if(fig>=5) fig=9-fig; fig+=5*fl->lurd; addsprite(xpos,ypos,flamefigs[0/* color */]+fig); - fl=fl->next; } } static void drawdecays() { brickdecay *bd; - bd=activedecays.next; - while(bd) { + list_for_each_entry(bd, &activedecays, list) { addsprite(tovideox(bd->xpos),tovideoy(bd->ypos), blocksx+(bd->timer*9)/DECAYLIFE); - bd=bd->next; } } static void drawbonus() { bonustile *bonus; - bonus=activebonus.next; - while(bonus) { + list_for_each_entry(bonus, &activebonus, list) { addsprite(tovideox(bonus->xpos),tovideoy(bonus->ypos), tiles+bonus->type); - bonus=bonus->next; } } @@ -485,9 +478,7 @@ static void drawplayers() { player *pl; int xpos,ypos; - pl=activeplayers.next; - - while(pl) { + list_for_each_entry(pl, &activeplayers, list) { if(!(pl->flags & FLG_DEAD)) { if(!pl->figure) pl->figure=walking[pl->color]+30; @@ -495,24 +486,23 @@ static void drawplayers() { ypos=tovideoy(pl->ypos)+pl->fixy; addsprite(xpos,ypos,pl->figure); } - pl=pl->next; } } static void detonatecontrolled(player *pl) { - bomb *bmb; + bomb *bmb, *next; - bmb=activebombs.next; - while(bmb) { + list_for_each_entry_safe(bmb, next, &activebombs, list) { if(bmb->owner==pl && bmb->type==BOMB_CONTROLLED) adddetonate(bmb); - bmb=bmb->next; } } static void playonce(generic *gen) { - if(gen->timer==gen->data1) - delink(&activegeneric,gen); + if (gen->timer == gen->data1) { + list_del(&gen->list); + freeentry(gen); + } } static void drawgeneric(generic *gen) { @@ -522,7 +512,7 @@ static void drawgeneric(generic *gen) { static void queuesequence(int xpos,int ypos,figure *fig,int count) { generic *gen; - gen=allocentry(); + gen = allocentry(generic); if(!gen) return; gen->xpos=xpos; gen->ypos=ypos; @@ -542,6 +532,11 @@ static void adddeath(player *pl) { } static void killplayer(player *pl) { + if (pl->controller == -1) { + host_deaths++; + } else { + netnodes[pl->controller].deaths++; + } pl->flags|=FLG_DEAD; playsound(2); adddeath(pl); @@ -549,24 +544,42 @@ static void killplayer(player *pl) { } static void processgenerics(void) { - generic *gen,*gen2; + generic *gen, *next; - gen=activegeneric.next; - while(gen) { - gen2=gen; - gen=gen->next; - ++(gen2->timer); - gen2->process(gen2); + list_for_each_entry_safe(gen, next, &activegeneric, list) { + ++(gen->timer); + gen->process(gen); } } static void drawgenerics(void) { generic *gen; - gen=activegeneric.next; - while(gen) { + list_for_each_entry(gen, &activegeneric, list) { gen->draw(gen); - gen=gen->next; + } +} + +static void drawstats(void) { + int d, k, p = 0, i; + const char *n; + char buf[16]; + + solidcopy(&background, 0, 0, IXSIZE, arraystarty); + for (i = -1; i < MAXNETNODES; i++) { + if (i >= 0) { + if (!netnodes[i].used) continue; + k = netnodes[i].kills; + d = netnodes[i].deaths; + n = netnodes[i].name; + } else { + k = host_kills; + d = host_deaths; + n = playername; + } + snprintf(buf, sizeof(buf), "%-8.8s %2i/%2i", n, k % 100, d % 100); + drawstring(11 + (p/2) * (15 * fontxsize + 7), 11 + (p%2) * (fontysize+2), buf); + p++; } } @@ -795,13 +808,10 @@ static void doplayer(player *pl) { } static void processplayers(void) { - player *pl,*pl2; + player *pl, *next; - pl=activeplayers.next; - while(pl) { - pl2=pl; - pl=pl->next; - doplayer(pl2); + list_for_each_entry_safe(pl, next, &activeplayers, list) { + doplayer(pl); } } @@ -886,13 +896,16 @@ static int iterate(void) { drawdecays(); drawflames(); drawplayers(); + drawstats(); plotsprites(); copyup(); - if(!activegeneric.next) { + if (list_empty(&activegeneric)) { player *pl; + int deadplayers = 0; i = 0; - for (pl = activeplayers.next; pl; pl = pl->next) { + + list_for_each_entry(pl, &activeplayers, list) { if(!(pl->flags & FLG_DEAD)) ++i; else diff --git a/list.c b/list.c index b6658de..85df0e5 100644 --- a/list.c +++ b/list.c @@ -3,16 +3,29 @@ #include "list.h" #include "utils.h" -static listitem *things=0, *free_things; +typedef union genericlistitem genericlistitem; +union genericlistitem { + genericlistitem *next; + bomb b; + flame f; + brickdecay bc; + player p; + bonustile bt; + generic g; +}; + +/* doesn't use prev link */ +static genericlistitem *things=0; +static genericlistitem *free_things; void allocthings(void) { int i; const int num = MAXTHINGS; if (!things) { - things = calloc(sizeof(listitem), num); + things = calloc(sizeof(genericlistitem), num); } else { - memset(things, 0, sizeof(listitem)*num); + memset(things, 0, sizeof(genericlistitem)*num); } if(!things) nomem("Trying to allocate thing memory"); for(i=0;i sizeof(genericlistitem)) return 0; if (free_things) { free_things = free_things->next; - memset(entry, 0, sizeof(*entry)); + memset(entry, 0, sizeof(genericlistitem)); } return entry; } -void freeentry(void *_entry) { - listitem *entry = _entry; - +void freeentry(void *ptr) { + genericlistitem *entry = ptr; entry->next = free_things; free_things = entry; } -void addtail(void *_header,void *_entry) { - listitem *header = _header, *entry = _entry; - - while (header->next) header = header->next; - header->next = entry; - entry->next = 0; +void list_add_tail(listhead *head, listhead *entry) { + entry->next = head; + entry->prev = head->prev; + head->prev->next = entry; + head->prev = entry; } -void delink(void *_header,void *_entry) { - listitem *header = _header, *entry = _entry; - - while (header->next != entry) header = header->next; - header->next = entry->next; - entry->next = 0; - freeentry(entry); +void list_del(listhead *entry) { + entry->next->prev = entry->prev; + entry->prev->next = entry->next; + entry->next = entry->prev = entry; } -void initheader(void *p) { - memset(p,0,sizeof(list)); +void list_init_head(listhead *head) { + head->next = head; + head->prev = head; } - diff --git a/list.h b/list.h index b2a628f..bf11f20 100644 --- a/list.h +++ b/list.h @@ -1,12 +1,60 @@ #ifndef LIST_H #define LIST_H -void allocthings(void); -void *allocentry(void); -void freeentry(void *entry); -void addtail(void *header,void *entry); -void delink(void *header,void *entry); +/* from linux kernel */ -void initheader(void *p); +#define container_of(ptr, type, member) ({ \ + const typeof( ((type *)0)->member ) *__mptr = (ptr); \ + (type *)( (char *)__mptr - offsetof(type,member) );}) + +/** + * list_entry - get the struct for this entry + * @ptr: the &struct list_head pointer. + * @type: the type of the struct this is embedded in. + * @member: the name of the list_struct within the struct. + */ +#define list_entry(ptr, type, member) container_of(ptr, type, member) + +void allocthings(void); +void *_allocentry(size_t size); +#define allocentry(type) (type*) _allocentry(sizeof(type)) +void freeentry(void *ptr); + +void list_add_tail(listhead *header, listhead *entry); +#define addtail(head, entry) list_add_tail(head, &(entry->list)); + +/* remove entry from list */ +void list_del(listhead *entry); +#define removeitem(entry) list_del(&(entry->list)); + +void list_init_head(listhead *head); + + +/** + * list_for_each_entry - iterate over list of given type + * @pos: the type * to use as a loop cursor. + * @head: the head for your list. + * @member: the name of the list_struct within the struct. + */ +#define list_for_each_entry(pos, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member); \ + /* prefetch(pos->member.next), */ \ + &pos->member != (head); \ + pos = list_entry(pos->member.next, typeof(*pos), member)) + +/** + * list_for_each_entry_safe - iterate over list of given type safe against removal of list entry + * @pos:<-->the type * to use as a loop cursor. + * @n:<><-->another type * to use as temporary storage + * @head:<->the head for your list. + * @member:>the name of the list_struct within the struct. + */ +#define list_for_each_entry_safe(pos, n, head, member) \ + for (pos = list_entry((head)->next, typeof(*pos), member), \ + n = list_entry(pos->member.next, typeof(*pos), member); \ + &pos->member != (head); \ + pos = n, n = list_entry(n->member.next, typeof(*n), member)) + +#define list_empty(head) ((head) == (head)->next) #endif diff --git a/network.c b/network.c index 894d4bf..676336f 100644 --- a/network.c +++ b/network.c @@ -10,7 +10,7 @@ #define MAXMSG 4096 int udpsocket; -const unsigned char gameversion[4]={0xda,0x01,0x00,0x06}; +const unsigned char gameversion[4]={0xda,0x01,0x00,0x07}; struct netnode netnodes[MAXNETNODES]; diff --git a/network.h b/network.h index 7ac98dd..e666429 100644 --- a/network.h +++ b/network.h @@ -5,12 +5,16 @@ #include #include -#define MAXNETNODES 8 +enum { + MAXNETNODES = 8 +} maxnetnodesconst; struct netnode { struct sockaddr_in netname; char name[16]; char used; + + int kills, deaths; }; extern struct netnode netnodes[MAXNETNODES];