short int legalizeEdge(Point * p, Triangle * T){ short int ut, ua; Triangle * A; Point * center; for(ut=0; ut<3 && T->points[ut] != p; ++ut); if(ut==3) return -1; ADJACENT(T, T->points[NEXT(ut)], T->points[PREV(ut)], A); if(!A) return 1; for(ua=0; ua<3 && IN_TRIA(T, A->points[ua]); ua++); center = calcCenter(T); if(!center) return -2; if(DISQR(A->points[ua], center) >= DISQR(center, P0)){ free(center); return 1; } free(center); if((ua=swap(T, A))<0) return -3; if((ua=legalizeEdge(p, T))<0) return -ua; if((ua=legalizeEdge(p, A))<0) return -ua; return 1; }
int analyze_terrain(const unsigned char *types, unsigned int size, unsigned int x, unsigned int y, unsigned char *type, unsigned char *adjacent_same, unsigned char *adjacent_sand) { /** * Macros for one dimensional coordinates for all adjacent tiles. * Start with x coordinate, then add as many "rows" as the value y. **/ #define nw_coord ((x - 1) + (size * (y - 1))) #define n_coord (x + (size * (y - 1))) #define ne_coord ((x + 1) + (size * (y - 1))) #define w_coord ((x - 1) + (size * y)) #define e_coord ((x + 1) + (size * y)) #define sw_coord ((x - 1) + (size * (y + 1))) #define s_coord ((x + (size * (y + 1)))) #define se_coord ((x + 1) + (size * (y + 1))) unsigned int c_type; unsigned int nw_type; unsigned int n_type; unsigned int ne_type; unsigned int w_type; unsigned int e_type; unsigned int sw_type; unsigned int s_type; unsigned int se_type; /* First only retrieve center tile's type */ c_type = types[x + (size * y)]; *type = c_type; /* NOTE: All info needed for SAND retrieved at this point */ /** * Get terrain types for all adjacent tiles, using their * one dimensional coordinates. First perform appropriate ternary * boundary checks for each case. Default to center tile type. **/ nw_type = (y > 0 && x > 0)? types[nw_coord] : c_type; n_type = (y > 0)? types[n_coord] : c_type; ne_type = (x < size - 1 && y > 0)? types[ne_coord] : c_type; w_type = (x > 0)? types[w_coord] : c_type; e_type = (x < size - 1)? types[e_coord] : c_type; sw_type = (x > 0 && y < size - 1)? types[sw_coord] : c_type; s_type = (y < size - 1)? types[s_coord] : c_type; se_type = (y < size - 1 && x < size - 1)? types[se_coord] : c_type; /* NOTE: All info needed for WATER retrieved at this point */ *adjacent_sand = ADJACENT(T_SAND)|ADJACENT(T_WATER)|ADJACENT(T_ROCK); /* NOTE: All info needed for DIRT retrieved at this point */ *adjacent_same = ADJACENT(c_type); /* DEBUG_XY(79, 95); */ return 0; }
static void delete_finish(ptst_t *ptst, node_t *x) { qnode_t g_qn, p_qn, w_qn, x_qn; node_t *g, *p, *w; int done = 0; do { if ( IS_GARBAGE(x) ) return; p = x->p; g = p->p; mcs_lock(&g->lock, &g_qn); if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) || IS_GARBAGE(g) ) goto unlock_g; mcs_lock(&p->lock, &p_qn); /* Removing unbalanced red nodes is okay. */ if ( !ADJACENT(p, x) || (IS_UNBALANCED(p->v) && IS_BLACK(p->v)) ) goto unlock_pg; mcs_lock(&x->lock, &x_qn); if ( IS_UNBALANCED(x->v) ) goto unlock_xpg; if ( GET_VALUE(x->v) != NULL ) { done = 1; goto unlock_xpg; } if ( p->l == x ) w = p->r; else w = p->l; assert(w != x); mcs_lock(&w->lock, &w_qn); if ( IS_UNBALANCED(w->v) ) goto unlock_wxpg; if ( g->l == p ) g->l = w; else g->r = w; MK_GARBAGE(p); gc_free(ptst, p, gc_id); MK_GARBAGE(x); gc_free(ptst, x, gc_id); w->p = g; if ( IS_BLACK(p->v) && IS_BLACK(w->v) ) { w->v = MK_UNBALANCED(w->v); done = 2; } else { w->v = MK_BLACK(w->v); done = 1; } unlock_wxpg: mcs_unlock(&w->lock, &w_qn); unlock_xpg: mcs_unlock(&x->lock, &x_qn); unlock_pg: mcs_unlock(&p->lock, &p_qn); unlock_g: mcs_unlock(&g->lock, &g_qn); } while ( !done ); if ( done == 2 ) fix_unbalance_down(ptst, w); }
static void fix_unbalance_down(ptst_t *ptst, node_t *x) { /* WN == W_NEAR, WF == W_FAR (W_FAR is further, in key space, from X). */ qnode_t x_qn, w_qn, p_qn, g_qn, wn_qn, wf_qn; node_t *w, *p, *g, *wn, *wf; int done = 0; do { if ( !IS_UNBALANCED(x->v) || IS_GARBAGE(x) ) return; p = x->p; g = p->p; mcs_lock(&g->lock, &g_qn); if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) || IS_GARBAGE(g) ) goto unlock_g; mcs_lock(&p->lock, &p_qn); if ( !ADJACENT(p, x) || IS_UNBALANCED(p->v) ) goto unlock_pg; mcs_lock(&x->lock, &x_qn); if ( !IS_BLACK(x->v) || !IS_UNBALANCED(x->v) ) { done = 1; goto unlock_xpg; } if ( IS_ROOT(x) ) { x->v = MK_BALANCED(x->v); done = 1; goto unlock_xpg; } w = (x == p->l) ? p->r : p->l; mcs_lock(&w->lock, &w_qn); if ( IS_UNBALANCED(w->v) ) { if ( IS_BLACK(w->v) ) { /* Funky relaxed rules to the rescue. */ x->v = MK_BALANCED(x->v); w->v = MK_BALANCED(w->v); if ( IS_BLACK(p->v) ) { p->v = MK_UNBALANCED(p->v); done = 2; } else { p->v = MK_BLACK(p->v); done = 1; } } goto unlock_wxpg; } assert(!IS_LEAF(w)); if ( x == p->l ) { wn = w->l; wf = w->r; } else { wn = w->r; wf = w->l; } mcs_lock(&wn->lock, &wn_qn); /* Hanke has an extra relaxed transform here. It's not needed. */ if ( IS_UNBALANCED(wn->v) ) goto unlock_wnwxpg; mcs_lock(&wf->lock, &wf_qn); if ( IS_UNBALANCED(wf->v) ) goto unlock_wfwnwxpg; if ( IS_RED(w->v) ) { /* Case 1. Rotate at parent. */ assert(IS_BLACK(p->v) && IS_BLACK(wn->v) && IS_BLACK(wf->v)); w->v = MK_BLACK(w->v); p->v = MK_RED(p->v); if ( x == p->l ) left_rotate(ptst, p); else right_rotate(ptst, p); goto unlock_wfwnwxpg; } if ( IS_BLACK(wn->v) && IS_BLACK(wf->v) ) { if ( IS_RED(p->v) ) { /* Case 2. Simple recolouring. */ p->v = MK_BLACK(p->v); done = 1; } else { /* Case 5. Simple recolouring. */ p->v = MK_UNBALANCED(p->v); done = 2; } w->v = MK_RED(w->v); x->v = MK_BALANCED(x->v); goto unlock_wfwnwxpg; } if ( x == p->l ) { if ( IS_RED(wf->v) ) { /* Case 3. Single rotation. */ wf->v = MK_BLACK(wf->v); w->v = SET_COLOUR(w->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); left_rotate(ptst, p); } else { /* Case 4. Double rotation. */ assert(IS_RED(wn->v)); wn->v = SET_COLOUR(wn->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); right_rotate(ptst, w); left_rotate(ptst, p); } } else /* SYMMETRIC CASE: X == P->R */ { if ( IS_RED(wf->v) ) { /* Case 3. Single rotation. */ wf->v = MK_BLACK(wf->v); w->v = SET_COLOUR(w->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); right_rotate(ptst, p); } else { /* Case 4. Double rotation. */ assert(IS_RED(wn->v)); wn->v = SET_COLOUR(wn->v, GET_COLOUR(p->v)); p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); left_rotate(ptst, w); right_rotate(ptst, p); } } done = 1; unlock_wfwnwxpg: mcs_unlock(&wf->lock, &wf_qn); unlock_wnwxpg: mcs_unlock(&wn->lock, &wn_qn); unlock_wxpg: mcs_unlock(&w->lock, &w_qn); unlock_xpg: mcs_unlock(&x->lock, &x_qn); unlock_pg: mcs_unlock(&p->lock, &p_qn); unlock_g: mcs_unlock(&g->lock, &g_qn); if ( done == 2 ) { x = p; done = 0; } } while ( !done ); }
static void fix_unbalance_up(ptst_t *ptst, node_t *x) { qnode_t x_qn, g_qn, p_qn, w_qn, gg_qn; node_t *g, *p, *w, *gg; int done = 0; do { assert(IS_UNBALANCED(x->v)); if ( IS_GARBAGE(x) ) return; p = x->p; g = p->p; gg = g->p; mcs_lock(&gg->lock, &gg_qn); if ( !ADJACENT(gg, g) || IS_UNBALANCED(gg->v) || IS_GARBAGE(gg) ) goto unlock_gg; mcs_lock(&g->lock, &g_qn); if ( !ADJACENT(g, p) || IS_UNBALANCED(g->v) ) goto unlock_ggg; mcs_lock(&p->lock, &p_qn); if ( !ADJACENT(p, x) || IS_UNBALANCED(p->v) ) goto unlock_pggg; mcs_lock(&x->lock, &x_qn); assert(IS_RED(x->v)); assert(IS_UNBALANCED(x->v)); if ( IS_BLACK(p->v) ) { /* Case 1. Nothing to do. */ x->v = MK_BALANCED(x->v); done = 1; goto unlock_xpggg; } if ( IS_ROOT(x) ) { /* Case 2. */ x->v = MK_BLACK(MK_BALANCED(x->v)); done = 1; goto unlock_xpggg; } if ( IS_ROOT(p) ) { /* Case 2. */ p->v = MK_BLACK(p->v); x->v = MK_BALANCED(x->v); done = 1; goto unlock_xpggg; } if ( g->l == p ) w = g->r; else w = g->l; mcs_lock(&w->lock, &w_qn); if ( IS_RED(w->v) ) { /* Case 5. */ /* In all other cases, doesn't change colour or subtrees. */ if ( IS_UNBALANCED(w->v) ) goto unlock_wxpggg; g->v = MK_UNBALANCED(MK_RED(g->v)); p->v = MK_BLACK(p->v); w->v = MK_BLACK(w->v); x->v = MK_BALANCED(x->v); done = 2; goto unlock_wxpggg; } /* Cases 3 & 4. Both of these need the great-grandfather locked. */ if ( p == g->l ) { if ( x == p->l ) { /* Case 3. Single rotation. */ x->v = MK_BALANCED(x->v); p->v = MK_BLACK(p->v); g->v = MK_RED(g->v); right_rotate(ptst, g); } else { /* Case 4. Double rotation. */ x->v = MK_BALANCED(MK_BLACK(x->v)); g->v = MK_RED(g->v); left_rotate(ptst, p); right_rotate(ptst, g); } } else /* SYMMETRIC CASE */ { if ( x == p->r ) { /* Case 3. Single rotation. */ x->v = MK_BALANCED(x->v); p->v = MK_BLACK(p->v); g->v = MK_RED(g->v); left_rotate(ptst, g); } else { /* Case 4. Double rotation. */ x->v = MK_BALANCED(MK_BLACK(x->v)); g->v = MK_RED(g->v); right_rotate(ptst, p); left_rotate(ptst, g); } } done = 1; unlock_wxpggg: mcs_unlock(&w->lock, &w_qn); unlock_xpggg: mcs_unlock(&x->lock, &x_qn); unlock_pggg: mcs_unlock(&p->lock, &p_qn); unlock_ggg: mcs_unlock(&g->lock, &g_qn); unlock_gg: mcs_unlock(&gg->lock, &gg_qn); if ( done == 2 ) { x = g; done = 0; } } while ( !done ); }