From 4c516766ba1b1397f6789f34da08f1db6d979972 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 11 Aug 2009 17:19:43 +0200 Subject: [PATCH 1/7] List rewrite --- Makefile | 2 +- bomber.h | 52 ++++++++++++----------- game.c | 127 ++++++++++++++++++++++++------------------------------- list.c | 50 ++++++++++++---------- list.h | 20 +++++++-- 5 files changed, 126 insertions(+), 125 deletions(-) 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..c76234c 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; @@ -119,7 +119,7 @@ typedef struct bomb { #define DECAYLIFE 15 typedef struct flame { - struct flame *next; + listhead list; int xpos,ypos; int px,py; int timer; @@ -133,23 +133,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,12 +157,16 @@ typedef struct generic { int data1,data2; } generic; -typedef struct bonustile { - struct bonustile *next; - int xpos,ypos; - int px,py; - int type; -} bonustile; +typedef union genericlistitem genericlistitem; +union genericlistitem { + listhead h; + bomb b; + flame f; + brickdecay bc; + player p; + bonustile bt; + generic g; +}; enum tile_types { TILE_NONE = -1, diff --git a/game.c b/game.c index 0a28b5a..e00757f 100644 --- a/game.c +++ b/game.c @@ -11,20 +11,20 @@ static int gameframe; -static list activebombs; -static list activedecays; -static list activebonus; -static list activegeneric; +static listhead activebombs; +static listhead activedecays; +static listhead activebonus; +static listhead activegeneric; static bomb *detonated[MAXBOMBSDETONATED]; static int detonateput=0; static int detonatetake=0; -static list activeflames; -static list activeplayers; +static listhead activeflames; +static listhead activeplayers; figure walking[MAXSETS][NUMWALKFRAMES]; -solid background,backgroundoriginal; +solid background, backgroundoriginal; /* The playfield array, contains FIELD_* equates */ unsigned char field[32][32]; @@ -68,7 +68,6 @@ static void initplayer(int color,int x,int y,int controller) { if(!pl) nomem("Couldn't get player structure (allocentry())"); addtail(&activeplayers,pl); - memset(pl,0,sizeof(player)); pl->xpos=arraytoscreenx(x); pl->ypos=arraytoscreeny(y); pl->color=color; @@ -239,9 +238,9 @@ static void adddetonate(bomb *bmb) { static void processbombs() { bomb *bmb; + listhead *iter; - bmb=activebombs.next; - while(bmb) { + foreach_list_entry(&activebombs, iter, bmb) { switch(bmb->type) { case BOMB_NORMAL: ++bmb->timer; @@ -253,7 +252,6 @@ static void processbombs() { ++(bmb->figcount); break; } - bmb=bmb->next; } } @@ -313,7 +311,7 @@ static void deletebonus(bonustile *bonus) { py=bonus->py; field[py][px]=0; info[py][px]=0; - delink(&activebonus,bonus); + delink(bonus); } static void flameshaft(player *owner,int px,int py,int dx,int dy,int power) { @@ -361,7 +359,7 @@ static void detonatebomb(bomb *bmb) { py=bmb->py; power=bmb->power; owner=bmb->owner; - delink(&activebombs,bmb); + delink(bmb); addflame(owner,px,py); flameshaft(owner,px,py,-1,0,power); flameshaft(owner,px,py,0,-1,power); @@ -381,53 +379,43 @@ static void dodetonations(void) { } static void processflames(void) { - flame *fl,*fl2; + flame *fl; + listhead *iter; - fl=activeflames.next; - while(fl) { + foreach_list_entry(&activeflames, iter, fl) { ++(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; + iter = delinkhead(iter); + } } } static void processdecays() { - brickdecay *bd,*bd2; + brickdecay *bd; + listhead *iter; - bd=activedecays.next; - while(bd) { + foreach_list_entry(&activedecays, iter, bd) { ++(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); + iter = delinkhead(iter); + } } } static void drawbombs(void) { int j; bomb *bmb; + listhead *iter; struct figure *figtab; int color; int xpos,ypos; - bmb=activebombs.next; - while(bmb) { + foreach_list_entry(&activebombs, iter, bmb) { color=bmb->owner->color; figtab=(bmb->type==BOMB_NORMAL) ? bombs1[color] : bombs2[color]; j=bmb->figcount % (NUMBOMBFRAMES<<1); @@ -436,18 +424,17 @@ static void drawbombs(void) { ypos=tovideoy(bmb->ypos)-3; addsprite(xpos,ypos,figtab+j); - bmb=bmb->next; } } static void drawflames(void) { flame *fl; + listhead *iter; int xpos,ypos; int color; int fig; - fl=activeflames.next; - while(fl) { + foreach_list_entry(&activeflames, iter, fl) { color=fl->owner->color; xpos=tovideox(fl->xpos); ypos=tovideoy(fl->ypos); @@ -455,39 +442,35 @@ 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() { + listhead *iter; brickdecay *bd; - bd=activedecays.next; - while(bd) { + foreach_list_entry(&activedecays, iter, bd) { addsprite(tovideox(bd->xpos),tovideoy(bd->ypos), blocksx+(bd->timer*9)/DECAYLIFE); - bd=bd->next; } } static void drawbonus() { bonustile *bonus; + listhead *iter; - bonus=activebonus.next; - while(bonus) { + foreach_list_entry(&activebonus, iter, bonus) { addsprite(tovideox(bonus->xpos),tovideoy(bonus->ypos), tiles+bonus->type); - bonus=bonus->next; } } static void drawplayers() { player *pl; int xpos,ypos; + listhead *iter; - pl=activeplayers.next; - - while(pl) { + foreach_list_entry(&activeplayers, iter, pl) { if(!(pl->flags & FLG_DEAD)) { if(!pl->figure) pl->figure=walking[pl->color]+30; @@ -495,24 +478,22 @@ static void drawplayers() { ypos=tovideoy(pl->ypos)+pl->fixy; addsprite(xpos,ypos,pl->figure); } - pl=pl->next; } } static void detonatecontrolled(player *pl) { bomb *bmb; + listhead *iter; - bmb=activebombs.next; - while(bmb) { + foreach_list_entry(&activebombs, iter, bmb) { 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); + delink(gen); } static void drawgeneric(generic *gen) { @@ -551,10 +532,10 @@ static void killplayer(player *pl) { static void processgenerics(void) { generic *gen,*gen2; - gen=activegeneric.next; - while(gen) { - gen2=gen; - gen=gen->next; + gen = (generic*) activegeneric.next; + while ((listhead*) gen != &activegeneric) { + gen2 = gen; + gen = (generic*) gen->list.next; ++(gen2->timer); gen2->process(gen2); } @@ -562,11 +543,10 @@ static void processgenerics(void) { static void drawgenerics(void) { generic *gen; + listhead *iter; - gen=activegeneric.next; - while(gen) { + foreach_list_entry(&activegeneric, iter, gen) { gen->draw(gen); - gen=gen->next; } } @@ -795,12 +775,12 @@ static void doplayer(player *pl) { } static void processplayers(void) { - player *pl,*pl2; + player *pl, *pl2; - pl=activeplayers.next; - while(pl) { - pl2=pl; - pl=pl->next; + pl = (player*) activeplayers.next; + while ((listhead*) pl != &activeplayers) { + pl2 = pl; + pl = (player*) pl->list.next; doplayer(pl2); } } @@ -888,11 +868,14 @@ static int iterate(void) { drawplayers(); plotsprites(); copyup(); - if(!activegeneric.next) { + if (activegeneric.next == &activegeneric) { player *pl; + listhead *iter; + int deadplayers = 0; i = 0; - for (pl = activeplayers.next; pl; pl = pl->next) { + + foreach_list_entry(&activeplayers, iter, pl) { if(!(pl->flags & FLG_DEAD)) ++i; else diff --git a/list.c b/list.c index b6658de..f10b0fb 100644 --- a/list.c +++ b/list.c @@ -3,60 +3,64 @@ #include "list.h" #include "utils.h" -static listitem *things=0, *free_things; +/* doesn't use prev link */ +static genericlistitem *things=0; +static listhead *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;inext; - memset(entry, 0, sizeof(*entry)); + memset(entry, 0, sizeof(genericlistitem)); } return entry; } -void freeentry(void *_entry) { - listitem *entry = _entry; +static void freeentry(void *_entry) { + listhead *entry = _entry; entry->next = free_things; + entry->prev = NULL; 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 _addtail(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; +listhead* delinkhead(listhead *entry) { + listhead *result = entry->prev; + + entry->next->prev = entry->prev; + entry->prev->next = entry->next; - while (header->next != entry) header = header->next; - header->next = entry->next; - entry->next = 0; freeentry(entry); + return result; } -void initheader(void *p) { - memset(p,0,sizeof(list)); +void initheader(listhead *head) { + head->next = head; + head->prev = head; } diff --git a/list.h b/list.h index b2a628f..3dd7e68 100644 --- a/list.h +++ b/list.h @@ -3,10 +3,22 @@ void allocthings(void); void *allocentry(void); -void freeentry(void *entry); -void addtail(void *header,void *entry); -void delink(void *header,void *entry); -void initheader(void *p); +void _addtail(listhead *header, listhead *entry); +#define addtail(head, entry) _addtail(head, &(entry->list)); + +/* returns previous entry, use as + * iter = delinkhead(iter); + * in foreach_list_entry loops + */ +listhead* delinkhead(listhead *entry); +#define delink(entry) delinkhead(&(entry->list)); + + +void initheader(listhead *head); + +/* listhead *head, listhead *iter, XXX *item */ +#define foreach_list_entry(head, iter, item) \ + for (iter = (head)->next, item = (void*) iter; iter != (head); iter = iter->next, item = (void*) iter) #endif From de5183b81888324ed7bfe514c81546602d4d7735 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 11 Aug 2009 17:46:32 +0200 Subject: [PATCH 2/7] Improve foreach_list* macros --- game.c | 41 +++++++++++++++-------------------------- list.h | 16 +++++++++------- 2 files changed, 24 insertions(+), 33 deletions(-) diff --git a/game.c b/game.c index e00757f..aec0a36 100644 --- a/game.c +++ b/game.c @@ -238,9 +238,8 @@ static void adddetonate(bomb *bmb) { static void processbombs() { bomb *bmb; - listhead *iter; - foreach_list_entry(&activebombs, iter, bmb) { + foreach_list_fast(&activebombs, bmb) { switch(bmb->type) { case BOMB_NORMAL: ++bmb->timer; @@ -379,30 +378,28 @@ static void dodetonations(void) { } static void processflames(void) { - flame *fl; - listhead *iter; + flame *fl, *next; - foreach_list_entry(&activeflames, iter, fl) { + foreach_list_safe(&activeflames, fl, next) { ++(fl->timer); if(fl->timer==FLAMELIFE) { field[fl->py][fl->px]=FIELD_EMPTY; info[fl->py][fl->px]=0; - iter = delinkhead(iter); + delink(fl); } } } static void processdecays() { - brickdecay *bd; - listhead *iter; + brickdecay *bd, *next; - foreach_list_entry(&activedecays, iter, bd) { + foreach_list_safe(&activedecays, bd, next) { ++(bd->timer); if(bd->timer == DECAYLIFE) { field[bd->py][bd->px] = FIELD_EMPTY; trybonus(bd->px, bd->py); - iter = delinkhead(iter); + delink(bd); } } } @@ -410,12 +407,11 @@ static void processdecays() { static void drawbombs(void) { int j; bomb *bmb; - listhead *iter; struct figure *figtab; int color; int xpos,ypos; - foreach_list_entry(&activebombs, iter, bmb) { + foreach_list_fast(&activebombs, bmb) { color=bmb->owner->color; figtab=(bmb->type==BOMB_NORMAL) ? bombs1[color] : bombs2[color]; j=bmb->figcount % (NUMBOMBFRAMES<<1); @@ -429,12 +425,11 @@ static void drawbombs(void) { static void drawflames(void) { flame *fl; - listhead *iter; int xpos,ypos; int color; int fig; - foreach_list_entry(&activeflames, iter, fl) { + foreach_list_fast(&activeflames, fl) { color=fl->owner->color; xpos=tovideox(fl->xpos); ypos=tovideoy(fl->ypos); @@ -446,10 +441,9 @@ static void drawflames(void) { } static void drawdecays() { - listhead *iter; brickdecay *bd; - foreach_list_entry(&activedecays, iter, bd) { + foreach_list_fast(&activedecays, bd) { addsprite(tovideox(bd->xpos),tovideoy(bd->ypos), blocksx+(bd->timer*9)/DECAYLIFE); } @@ -457,9 +451,8 @@ static void drawdecays() { static void drawbonus() { bonustile *bonus; - listhead *iter; - foreach_list_entry(&activebonus, iter, bonus) { + foreach_list_fast(&activebonus, bonus) { addsprite(tovideox(bonus->xpos),tovideoy(bonus->ypos), tiles+bonus->type); } @@ -468,9 +461,8 @@ static void drawbonus() { static void drawplayers() { player *pl; int xpos,ypos; - listhead *iter; - foreach_list_entry(&activeplayers, iter, pl) { + foreach_list_fast(&activeplayers, pl) { if(!(pl->flags & FLG_DEAD)) { if(!pl->figure) pl->figure=walking[pl->color]+30; @@ -483,9 +475,8 @@ static void drawplayers() { static void detonatecontrolled(player *pl) { bomb *bmb; - listhead *iter; - foreach_list_entry(&activebombs, iter, bmb) { + foreach_list_fast(&activebombs, bmb) { if(bmb->owner==pl && bmb->type==BOMB_CONTROLLED) adddetonate(bmb); } @@ -543,9 +534,8 @@ static void processgenerics(void) { static void drawgenerics(void) { generic *gen; - listhead *iter; - foreach_list_entry(&activegeneric, iter, gen) { + foreach_list_fast(&activegeneric, gen) { gen->draw(gen); } } @@ -870,12 +860,11 @@ static int iterate(void) { copyup(); if (activegeneric.next == &activegeneric) { player *pl; - listhead *iter; int deadplayers = 0; i = 0; - foreach_list_entry(&activeplayers, iter, pl) { + foreach_list_fast(&activeplayers, pl) { if(!(pl->flags & FLG_DEAD)) ++i; else diff --git a/list.h b/list.h index 3dd7e68..dc1336e 100644 --- a/list.h +++ b/list.h @@ -7,18 +7,20 @@ void *allocentry(void); void _addtail(listhead *header, listhead *entry); #define addtail(head, entry) _addtail(head, &(entry->list)); -/* returns previous entry, use as - * iter = delinkhead(iter); - * in foreach_list_entry loops - */ +/* returns previous entry */ listhead* delinkhead(listhead *entry); #define delink(entry) delinkhead(&(entry->list)); void initheader(listhead *head); -/* listhead *head, listhead *iter, XXX *item */ -#define foreach_list_entry(head, iter, item) \ - for (iter = (head)->next, item = (void*) iter; iter != (head); iter = iter->next, item = (void*) iter) +/* listhead *head, XXX *item */ +#define foreach_list_fast(head, item) \ + for (item = (void*) (head)->next; (listhead*) item != (head); item = (void*) ((listhead*)item)->next) + +/* listhead *head, XXX *item, XXX *next : you are allowed to delink(item) */ +#define foreach_list_safe(head, item, next) \ + for (item = (void*) (head)->next, next = (void*) ((listhead*)item)->next; (listhead*) item != (head); item = next, next = (void*) ((listhead*)item)->next) + #endif From e280118e3d30e5e1090eab9b50c604584e67fabe Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 11 Aug 2009 18:20:48 +0200 Subject: [PATCH 3/7] Limit lifetime of controlled bombs --- bomber.h | 1 + game.c | 15 +++++++++------ 2 files changed, 10 insertions(+), 6 deletions(-) diff --git a/bomber.h b/bomber.h index c76234c..b14bfe7 100644 --- a/bomber.h +++ b/bomber.h @@ -115,6 +115,7 @@ 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 diff --git a/game.c b/game.c index aec0a36..45617f6 100644 --- a/game.c +++ b/game.c @@ -237,18 +237,21 @@ static void adddetonate(bomb *bmb) { } static void processbombs() { - bomb *bmb; + bomb *bmb, *next; - foreach_list_fast(&activebombs, bmb) { + foreach_list_safe(&activebombs, bmb, next) { + ++(bmb->figcount); + ++bmb->timer; switch(bmb->type) { case BOMB_NORMAL: - ++bmb->timer; - if(bmb->timer==BOMBLIFE) + if (bmb->timer == BOMBLIFE) adddetonate(bmb); - ++(bmb->figcount); break; case BOMB_CONTROLLED: - ++(bmb->figcount); + if (bmb->timer == BOMB_CONTROLLED_LIFE) { + bmb->timer = 0; + bmb->type = BOMB_NORMAL; + } break; } } From 8a8afdf56e8c6bad4a4601bad78289050d272e2a Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 11 Aug 2009 19:09:59 +0200 Subject: [PATCH 4/7] remove limit of detonating bombs --- bomber.h | 1 - game.c | 85 +++++++++++++++++++++++++++----------------------------- list.c | 15 +++++----- list.h | 9 +++++- 4 files changed, 57 insertions(+), 53 deletions(-) diff --git a/bomber.h b/bomber.h index b14bfe7..265c1a3 100644 --- a/bomber.h +++ b/bomber.h @@ -220,7 +220,6 @@ enum tile_types { #define MAXSETS 8 #define MAXSPRITES 256 #define MAXDAMAGES 512 -#define MAXBOMBSDETONATED 32 extern char exitflag; diff --git a/game.c b/game.c index 45617f6..8558d70 100644 --- a/game.c +++ b/game.c @@ -15,11 +15,7 @@ static listhead activebombs; static listhead activedecays; static listhead activebonus; static listhead activegeneric; - -static bomb *detonated[MAXBOMBSDETONATED]; -static int detonateput=0; -static int detonatetake=0; - +static listhead detonatebombs; static listhead activeflames; static listhead activeplayers; @@ -124,14 +120,13 @@ static void initgame() { gameframe=0; allocthings(); initheader(&activebombs); + initheader(&detonatebombs); initheader(&activeflames); initheader(&activedecays); initheader(&activebonus); initheader(&activeplayers); initheader(&activegeneric); - detonateput=detonatetake=0; - p=bonuschances; bonustotal=0; for(;;) { @@ -226,37 +221,6 @@ 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, *next; - - foreach_list_safe(&activebombs, bmb, next) { - ++(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 adddecay(int px,int py) { brickdecay *bd; int xpos,ypos; @@ -316,6 +280,38 @@ static void deletebonus(bonustile *bonus) { delink(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; + + foreach_list_safe(&activebombs, bmb, next) { + ++(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) { int there; bomb *bmb; @@ -370,12 +366,13 @@ 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); } @@ -477,9 +474,9 @@ static void drawplayers() { } static void detonatecontrolled(player *pl) { - bomb *bmb; + bomb *bmb, *next; - foreach_list_fast(&activebombs, bmb) { + foreach_list_safe(&activebombs, bmb, next) { if(bmb->owner==pl && bmb->type==BOMB_CONTROLLED) adddetonate(bmb); } diff --git a/list.c b/list.c index f10b0fb..186ef3d 100644 --- a/list.c +++ b/list.c @@ -34,9 +34,7 @@ void *allocentry(void) { return entry; } -static void freeentry(void *_entry) { - listhead *entry = _entry; - +void _freeentry(listhead *entry) { entry->next = free_things; entry->prev = NULL; free_things = entry; @@ -49,13 +47,16 @@ void _addtail(listhead *head, listhead *entry) { head->prev = entry; } +void _removeitem(listhead *entry) { + entry->next->prev = entry->prev; + entry->prev->next = entry->next; +} + listhead* delinkhead(listhead *entry) { listhead *result = entry->prev; - entry->next->prev = entry->prev; - entry->prev->next = entry->next; - - freeentry(entry); + _removeitem(entry); + _freeentry(entry); return result; } diff --git a/list.h b/list.h index dc1336e..f6ad7ea 100644 --- a/list.h +++ b/list.h @@ -3,11 +3,17 @@ void allocthings(void); void *allocentry(void); +void _freeentry(listhead *entry); +#define freeentry(entry) _freeentry(&(entry->list)); void _addtail(listhead *header, listhead *entry); #define addtail(head, entry) _addtail(head, &(entry->list)); -/* returns previous entry */ +/* remove entry from list */ +void _removeitem(listhead *entry); +#define removeitem(entry) _removeitem(&(entry->list)); + +/* returns previous entry, deletes entry */ listhead* delinkhead(listhead *entry); #define delink(entry) delinkhead(&(entry->list)); @@ -22,5 +28,6 @@ void initheader(listhead *head); #define foreach_list_safe(head, item, next) \ for (item = (void*) (head)->next, next = (void*) ((listhead*)item)->next; (listhead*) item != (head); item = next, next = (void*) ((listhead*)item)->next) +#define list_empty(head) ((head) == (head)->next) #endif From 5e908b99368c75819d030a6b643448e1505d35fc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 11 Aug 2009 19:13:18 +0200 Subject: [PATCH 5/7] Redo some list foreach loops --- game.c | 22 ++++++++-------------- 1 file changed, 8 insertions(+), 14 deletions(-) diff --git a/game.c b/game.c index 8558d70..90f3f69 100644 --- a/game.c +++ b/game.c @@ -521,14 +521,11 @@ static void killplayer(player *pl) { } static void processgenerics(void) { - generic *gen,*gen2; + generic *gen, *next; - gen = (generic*) activegeneric.next; - while ((listhead*) gen != &activegeneric) { - gen2 = gen; - gen = (generic*) gen->list.next; - ++(gen2->timer); - gen2->process(gen2); + foreach_list_safe(&activegeneric, gen, next) { + ++(gen->timer); + gen->process(gen); } } @@ -765,13 +762,10 @@ static void doplayer(player *pl) { } static void processplayers(void) { - player *pl, *pl2; + player *pl, *next; - pl = (player*) activeplayers.next; - while ((listhead*) pl != &activeplayers) { - pl2 = pl; - pl = (player*) pl->list.next; - doplayer(pl2); + foreach_list_safe(&activeplayers, pl, next) { + doplayer(pl); } } @@ -858,7 +852,7 @@ static int iterate(void) { drawplayers(); plotsprites(); copyup(); - if (activegeneric.next == &activegeneric) { + if (list_empty(&activegeneric)) { player *pl; int deadplayers = 0; From 3f6d769ebe3d11f6fdb77112905bafb6dd76dd9d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 18 Aug 2009 14:05:12 +0200 Subject: [PATCH 6/7] New double-linked list implementation, add death stats (kills always 0) --- bomber.h | 11 ------ draw.c | 26 ++++++------- draw.h | 6 ++- game.c | 111 ++++++++++++++++++++++++++++++++++++++---------------- list.c | 45 ++++++++++++---------- list.h | 65 ++++++++++++++++++++++---------- network.h | 6 ++- 7 files changed, 172 insertions(+), 98 deletions(-) diff --git a/bomber.h b/bomber.h index 265c1a3..522b8b6 100644 --- a/bomber.h +++ b/bomber.h @@ -158,17 +158,6 @@ typedef struct generic { int data1,data2; } generic; -typedef union genericlistitem genericlistitem; -union genericlistitem { - listhead h; - bomb b; - flame f; - brickdecay bc; - player p; - bonustile bt; - generic g; -}; - enum tile_types { TILE_NONE = -1, TILE_DISEASE = 0, 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(px); @@ -243,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; @@ -277,7 +289,8 @@ static void deletebonus(bonustile *bonus) { py=bonus->py; field[py][px]=0; info[py][px]=0; - delink(bonus); + list_del(&bonus->list); + freeentry(bonus); } static void adddetonate(bomb *bmb) { @@ -294,7 +307,7 @@ static void adddetonate(bomb *bmb) { static void processbombs() { bomb *bmb, *next; - foreach_list_safe(&activebombs, bmb, next) { + list_for_each_entry_safe(bmb, next, &activebombs, list) { ++(bmb->figcount); ++bmb->timer; switch(bmb->type) { @@ -357,7 +370,8 @@ static void detonatebomb(bomb *bmb) { py=bmb->py; power=bmb->power; owner=bmb->owner; - delink(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); @@ -380,13 +394,14 @@ static void dodetonations(void) { static void processflames(void) { flame *fl, *next; - foreach_list_safe(&activeflames, fl, next) { + list_for_each_entry_safe(fl, next, &activeflames, list) { ++(fl->timer); if(fl->timer==FLAMELIFE) { field[fl->py][fl->px]=FIELD_EMPTY; info[fl->py][fl->px]=0; - delink(fl); + list_del(&fl->list); + freeentry(fl); } } } @@ -394,12 +409,13 @@ static void processflames(void) { static void processdecays() { brickdecay *bd, *next; - foreach_list_safe(&activedecays, bd, next) { + 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); - delink(bd); + list_del(&bd->list); + freeentry(bd); } } } @@ -411,7 +427,7 @@ static void drawbombs(void) { int color; int xpos,ypos; - foreach_list_fast(&activebombs, 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); @@ -429,7 +445,7 @@ static void drawflames(void) { int color; int fig; - foreach_list_fast(&activeflames, fl) { + list_for_each_entry(fl, &activeflames, list) { color=fl->owner->color; xpos=tovideox(fl->xpos); ypos=tovideoy(fl->ypos); @@ -443,7 +459,7 @@ static void drawflames(void) { static void drawdecays() { brickdecay *bd; - foreach_list_fast(&activedecays, bd) { + list_for_each_entry(bd, &activedecays, list) { addsprite(tovideox(bd->xpos),tovideoy(bd->ypos), blocksx+(bd->timer*9)/DECAYLIFE); } @@ -452,7 +468,7 @@ static void drawdecays() { static void drawbonus() { bonustile *bonus; - foreach_list_fast(&activebonus, bonus) { + list_for_each_entry(bonus, &activebonus, list) { addsprite(tovideox(bonus->xpos),tovideoy(bonus->ypos), tiles+bonus->type); } @@ -462,7 +478,7 @@ static void drawplayers() { player *pl; int xpos,ypos; - foreach_list_fast(&activeplayers, pl) { + list_for_each_entry(pl, &activeplayers, list) { if(!(pl->flags & FLG_DEAD)) { if(!pl->figure) pl->figure=walking[pl->color]+30; @@ -476,15 +492,17 @@ static void drawplayers() { static void detonatecontrolled(player *pl) { bomb *bmb, *next; - foreach_list_safe(&activebombs, bmb, next) { + list_for_each_entry_safe(bmb, next, &activebombs, list) { if(bmb->owner==pl && bmb->type==BOMB_CONTROLLED) adddetonate(bmb); } } static void playonce(generic *gen) { - if(gen->timer==gen->data1) - delink(gen); + if (gen->timer == gen->data1) { + list_del(&gen->list); + freeentry(gen); + } } static void drawgeneric(generic *gen) { @@ -494,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; @@ -514,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); @@ -523,7 +546,7 @@ static void killplayer(player *pl) { static void processgenerics(void) { generic *gen, *next; - foreach_list_safe(&activegeneric, gen, next) { + list_for_each_entry_safe(gen, next, &activegeneric, list) { ++(gen->timer); gen->process(gen); } @@ -532,11 +555,34 @@ static void processgenerics(void) { static void drawgenerics(void) { generic *gen; - foreach_list_fast(&activegeneric, gen) { + list_for_each_entry(gen, &activegeneric, list) { gen->draw(gen); } } +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++; + } +} + static int centerxchange(player *pl) { int speed; int val; @@ -764,7 +810,7 @@ static void doplayer(player *pl) { static void processplayers(void) { player *pl, *next; - foreach_list_safe(&activeplayers, pl, next) { + list_for_each_entry_safe(pl, next, &activeplayers, list) { doplayer(pl); } } @@ -850,6 +896,7 @@ static int iterate(void) { drawdecays(); drawflames(); drawplayers(); + drawstats(); plotsprites(); copyup(); if (list_empty(&activegeneric)) { @@ -858,7 +905,7 @@ static int iterate(void) { int deadplayers = 0; i = 0; - foreach_list_fast(&activeplayers, pl) { + list_for_each_entry(pl, &activeplayers, list) { if(!(pl->flags & FLG_DEAD)) ++i; else diff --git a/list.c b/list.c index 186ef3d..85df0e5 100644 --- a/list.c +++ b/list.c @@ -3,9 +3,20 @@ #include "list.h" #include "utils.h" +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 listhead *free_things; +static genericlistitem *free_things; void allocthings(void) { int i; @@ -18,14 +29,16 @@ void allocthings(void) { } if(!things) nomem("Trying to allocate thing memory"); for(i=0;i sizeof(genericlistitem)) return 0; if (free_things) { free_things = free_things->next; @@ -34,34 +47,26 @@ void *allocentry(void) { return entry; } -void _freeentry(listhead *entry) { +void freeentry(void *ptr) { + genericlistitem *entry = ptr; entry->next = free_things; - entry->prev = NULL; free_things = entry; } -void _addtail(listhead *head, listhead *entry) { +void list_add_tail(listhead *head, listhead *entry) { entry->next = head; entry->prev = head->prev; head->prev->next = entry; head->prev = entry; } -void _removeitem(listhead *entry) { +void list_del(listhead *entry) { entry->next->prev = entry->prev; entry->prev->next = entry->next; + entry->next = entry->prev = entry; } -listhead* delinkhead(listhead *entry) { - listhead *result = entry->prev; - - _removeitem(entry); - _freeentry(entry); - return result; -} - -void initheader(listhead *head) { +void list_init_head(listhead *head) { head->next = head; head->prev = head; } - diff --git a/list.h b/list.h index f6ad7ea..bf11f20 100644 --- a/list.h +++ b/list.h @@ -1,32 +1,59 @@ #ifndef LIST_H #define LIST_H -void allocthings(void); -void *allocentry(void); -void _freeentry(listhead *entry); -#define freeentry(entry) _freeentry(&(entry->list)); +/* from linux kernel */ -void _addtail(listhead *header, listhead *entry); -#define addtail(head, entry) _addtail(head, &(entry->list)); +#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 _removeitem(listhead *entry); -#define removeitem(entry) _removeitem(&(entry->list)); +void list_del(listhead *entry); +#define removeitem(entry) list_del(&(entry->list)); -/* returns previous entry, deletes entry */ -listhead* delinkhead(listhead *entry); -#define delink(entry) delinkhead(&(entry->list)); +void list_init_head(listhead *head); -void initheader(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)) -/* listhead *head, XXX *item */ -#define foreach_list_fast(head, item) \ - for (item = (void*) (head)->next; (listhead*) item != (head); item = (void*) ((listhead*)item)->next) - -/* listhead *head, XXX *item, XXX *next : you are allowed to delink(item) */ -#define foreach_list_safe(head, item, next) \ - for (item = (void*) (head)->next, next = (void*) ((listhead*)item)->next; (listhead*) item != (head); item = next, next = (void*) ((listhead*)item)->next) +/** + * 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) 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]; From 3da47935a463085900a2257dc60b8a7f549f6226 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Stefan=20B=C3=BChler?= Date: Tue, 18 Aug 2009 14:06:26 +0200 Subject: [PATCH 7/7] Network version 1.0.7 --- network.c | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) 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];