changeset 155:6749f6639924

Fix bug for STAILQ that fail to remove a node. The previous one should be re-linked to next of removed one. But, it is linked to the removed one. Fix it!
author Thinker K.F. Li <thinker@branda.to>
date Wed, 01 Oct 2008 14:46:08 +0800
parents 6ce68c1f7405
children 2aad042b30a4
files examples/tank/Makefile examples/tank/tank_main.c src/animate.c src/mb_timer.h src/timer.c src/tools.h
diffstat 6 files changed, 62 insertions(+), 6 deletions(-) [+]
line wrap: on
line diff
--- a/examples/tank/Makefile	Tue Sep 30 02:44:06 2008 +0800
+++ b/examples/tank/Makefile	Wed Oct 01 14:46:08 2008 +0800
@@ -1,5 +1,5 @@
 SVGS =	brick.svg bullet.svg bush.svg mud.svg rock.svg \
-	tank1.svg tank2.svg tank_en.svg
+	tank1.svg tank2.svg tank_en.svg bang.svg
 SVGHS =	$(SVGS:C/\.svg/.h/)
 SVGCS =	$(SVGS:C/\.svg/.c/)
 SVGOS = $(SVGS:C/\.svg/.o/)
--- a/examples/tank/tank_main.c	Tue Sep 30 02:44:06 2008 +0800
+++ b/examples/tank/tank_main.c	Wed Oct 01 14:46:08 2008 +0800
@@ -1,3 +1,4 @@
+#include <math.h>
 #include <sys/time.h>
 #include <string.h>
 #include <mb/mb.h>
@@ -50,6 +51,8 @@
     mb_progm_t *progm;
     mb_timeval_t start_time;
     observer_t *ob_redraw;
+    mb_timer_t *hit_tmr;
+    mb_tman_t *tman;
 };
 typedef struct _tank_bullet tank_bullet_t;
 enum { BU_UP = 0, BU_RIGHT, BU_DOWN, BU_LEFT };
@@ -336,10 +339,14 @@
     redraw_man_t *rdman;
     subject_t *redraw;
     ob_factory_t *factory;
+
+    bullet = tank->bullet;
+    rdman = bullet->rdman;
+
+    if(bullet->hit_tmr != NULL)
+	mb_tman_remove(bullet->tman, bullet->hit_tmr);
     
     /*! \todo Simplify the procdure of using observer pattern. */
-    bullet = tank->bullet;
-    rdman = bullet->rdman;
     factory = rdman_get_ob_factory(rdman);
     redraw = rdman_get_redraw_subject(rdman);
     bullet->ob_redraw =
@@ -347,6 +354,45 @@
 			     bullet_go_out_map_and_redraw, tank);
 }
 
+static void bullet_bang(tank_bullet_t *bullet, int map_x, int map_y) {
+}
+
+static void bullet_hit_chk(const mb_timeval_t *tmo,
+			   const mb_timeval_t *now,
+			   void *arg) {
+    tank_t *tank = (tank_t *)arg;
+    tank_bullet_t *bullet;
+    mb_timeval_t diff, next;
+    mb_timeval_t unit_tm;
+    float move_units_f;
+    int move_units;
+    int x, y;
+    int dir;
+    static int move_adj[][2] = {{0, -1}, {1, 0}, {0, 1}, {-1, 0}};
+
+    bullet = tank->bullet;
+    MB_TIMEVAL_CP(&diff, now);
+    MB_TIMEVAL_DIFF(&diff, &bullet->start_time);
+    MB_TIMEVAL_SET(&unit_tm, 0, 250000);
+    move_units_f = MB_TIMEVAL_DIV(&diff, &unit_tm);
+    move_units = floorl(move_units_f);
+    dir = bullet->direction;
+    x = bullet->start_map_x + move_adj[dir][0] * move_units;
+    y = bullet->start_map_y + move_adj[dir][1] * move_units;
+
+    if(map[y][x] != MUD) {
+	bullet->hit_tmr = NULL;
+	mb_progm_abort(bullet->progm);
+	bullet_go_out_map(NULL, arg);
+	bullet_bang(bullet, x, y);
+    } else {
+	MB_TIMEVAL_SET(&next, 0, 100000);
+	MB_TIMEVAL_ADD(&next, now);
+	bullet->hit_tmr = mb_tman_timeout(bullet->tman, &next,
+					  bullet_hit_chk, arg);
+    }
+}
+
 static void tank_fire_bullet(tank_rt_t *tank_rt, tank_t *tank) {
     X_MB_runtime_t *xmb_rt;
     redraw_man_t *rdman;
@@ -359,7 +405,7 @@
     mb_word_t *word;
     mb_action_t *act;
     mb_timeval_t start, playing;
-    mb_timeval_t now;
+    mb_timeval_t now, next;
     ob_factory_t *factory;
     mb_tman_t *tman;
     subject_t *subject;
@@ -377,6 +423,7 @@
     map_y = tank->map_y + map_xy_adj[dir][1];
     tank->bullet = tank_bullet_new(rdman, map_x, map_y, dir);
     bullet = tank->bullet;
+    bullet->tman = tman;
 
     switch(dir) {
     case TD_UP:
@@ -415,6 +462,10 @@
     get_now(&now);
     MB_TIMEVAL_CP(&bullet->start_time, &now);
     mb_progm_start(progm, tman, &now);
+
+    MB_TIMEVAL_SET(&next, 0, 100000);
+    MB_TIMEVAL_ADD(&next, &now);
+    bullet->hit_tmr = mb_tman_timeout(tman, &next, bullet_hit_chk, tank);
 }
 
 #define CHANGE_POS(g, x, y) do {			\
--- a/src/animate.c	Tue Sep 30 02:44:06 2008 +0800
+++ b/src/animate.c	Wed Oct 01 14:46:08 2008 +0800
@@ -290,6 +290,7 @@
 	    MB_TIMEVAL_CP(&next_tmo, &word->abs_start);
 	timer = mb_tman_timeout(progm->tman, &next_tmo,
 				mb_progm_step, progm);	
+	progm->cur_timer = timer;
     } else {
 	/* Make program to complete. */
 #ifndef UNITTEST
--- a/src/mb_timer.h	Tue Sep 30 02:44:06 2008 +0800
+++ b/src/mb_timer.h	Wed Oct 01 14:46:08 2008 +0800
@@ -67,6 +67,9 @@
 	    (a)->tv_usec -= 1000000;		\
 	}					\
     } while(0)
+#define MB_TIMEVAL_DIV(a, b)			\
+    (((a)->tv_sec * 1000000.0 + (a)->tv_usec) /	\
+     ((b)->tv_sec * 1000000.0 + (b)->tv_usec))
 
 
 extern void get_now(mb_timeval_t *tmo);
--- a/src/timer.c	Tue Sep 30 02:44:06 2008 +0800
+++ b/src/timer.c	Wed Oct 01 14:46:08 2008 +0800
@@ -61,7 +61,8 @@
     for(visit = STAILQ_HEAD(tman->timers);
 	visit != NULL;
 	visit = STAILQ_NEXT(mb_timer_t, next, visit)) {
-	if(MB_TIMEVAL_LATER(&visit->tmo, tmo))
+	if(MB_TIMEVAL_LATER(&visit->tmo, tmo) ||
+	   MB_TIMEVAL_EQ(&visit->tmo, tmo))
 	    break;
 	last = visit;
     }
--- a/src/tools.h	Tue Sep 30 02:44:06 2008 +0800
+++ b/src/tools.h	Wed Oct 01 14:46:08 2008 +0800
@@ -55,7 +55,7 @@
 		  _stailq_cur->field != (elm))		\
 		_stailq_cur = _stailq_cur->field;	\
 	    if(_stailq_cur != NULL) {			\
-		_stailq_cur->field = elm;		\
+		_stailq_cur->field = (elm)->field;	\
 		if((q).tail == (elm))			\
 		    (q).tail = _stailq_cur;		\
 	    }						\