コード例 #1
0
ファイル: penrose.c プロジェクト: Bluerise/bitrig-xenocara
/*-
 * Update the status of this vertex on the forced vertex queue.  If
 * the vertex has become untileable set tp->done.  This is supposed
 * to detect dislocations -- never call this routine with a completely
 * tiled vertex.
 *
 * Check for untileable vertices in check_vertex and stop tiling as
 * soon as one finds one.  I don't know if it is possible to run out
 * of forced vertices while untileable vertices exist (or will
 * cavities inevitably appear).  If this can happen, add_random_tile
 * might get called with an untileable vertex, causing ( n <= 1).
 * (This is what the tp->done checks for).
 *
 * A delayLoop celebrates the dislocation.
 */
static void
check_vertex(ModeInfo * mi, fringe_node_c * vertex, tiling_c * tp)
{
	rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
	int         n_hits = match_rules(vertex, hits, False);
	unsigned    forced_sides = 0;

	if (vertex->rule_mask == 0) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Dislocation occurred!\n");
		}
		tp->busyLoop = CELEBRATE;	/* Should be able to recover */
	}
	if (1 == find_completions(vertex, hits, n_hits, S_LEFT, 0 /*, False */ ))
		forced_sides |= S_LEFT;
	if (1 == find_completions(vertex, hits, n_hits, S_RIGHT, 0 /*, False */ ))
		forced_sides |= S_RIGHT;
	if (forced_sides == 0) {
		if (vertex->list_ptr != 0) {
			forced_node_c *node = *vertex->list_ptr;

			*vertex->list_ptr = node->next;
			if (node->next != 0)
				node->next->vertex->list_ptr = vertex->list_ptr;
			free(node);
			tp->forced.n_nodes--;
			if (!vertex->off_screen)
				tp->forced.n_visible--;
			vertex->list_ptr = 0;
		}
	} else {
		forced_node_c *node;

		if (vertex->list_ptr == 0) {
			if ((node = ALLOC_NODE(forced_node_c)) == NULL)
				return;
			node->vertex = vertex;
			node->next = tp->forced.first;
			if (tp->forced.first != 0)
				tp->forced.first->vertex->list_ptr = &(node->next);
			tp->forced.first = node;
			vertex->list_ptr = &(tp->forced.first);
			tp->forced.n_nodes++;
			if (!vertex->off_screen)
				tp->forced.n_visible++;
		} else
			node = *vertex->list_ptr;
		node->forced_sides = forced_sides;
	}
}
コード例 #2
0
ファイル: penrose.c プロジェクト: Bluerise/bitrig-xenocara
/*-
 * Whether the addition of a tile of vtype on the given side of vertex
 * would conform to the rules.  The efficient way to do this would be
 * to add the new tile and then use the same type of search as in
 * match_rules.  However, this function is not a performance
 * bottleneck (only needed for random tile additions, which are
 * relatively infrequent), so I will settle for a simpler implementation.
 */
static int
legal_move(fringe_node_c * vertex, unsigned side, vertex_type_c vtype)
{
	rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
	vertex_type_c legal_vt[MAX_COMPL];
	int         n_hits, n_legal, i;

	n_hits = match_rules(vertex, hits, False);
	n_legal = find_completions(vertex, hits, n_hits, side, legal_vt /*, False */ );
	for (i = 0; i < n_legal; i++)
		if (legal_vt[i] == vtype)
			return True;
	return False;
}
コード例 #3
0
ファイル: filter.c プロジェクト: Ethylix/child
int filter_check (char *line, int direction)
{
    if (rule_list.enabled == 0)
        return -1;

    struct ruleset *rule, *last = NULL, packet;
    memset(&packet, 0, sizeof(packet));

    char *from, *action, *to, *data;
    char temp[1024];
    strncpy(temp, line, 1023);

    from = temp;
    action = SeperateWord(from);
    to = SeperateWord(action);
    data = SeperateWord(to);

    if (strempty(from))
        return -1;

    if (*from == ':')
        from++;

    packet.direction = direction;
    strncpy(packet.from, from, NICKLEN);
    if (action)
        strncpy(packet.action, action, 128);
    if (to)
        strncpy(packet.to, to, NICKLEN);
    if (data) {
        if (*data == ':')
            data++;
        strncpy(packet.data, data, 1023);
    }

    for (rule = rule_list.ltail; rule; rule = rule->lprev) {
        packet.rule = rule->rule;
        if ((match_rules(rule, &packet)) == 1) {
            last = rule;
            if (rule->quick == 1)
                return rule->rule;
        }
    }

    if (last)
        return last->rule;

    return -1;
}
コード例 #4
0
ファイル: penrose.c プロジェクト: Bluerise/bitrig-xenocara
/*-
 * Add a forced tile to a given forced vertex.  Basically an easy job,
 * since we know what to add.  But it might fail if adding the tile
 * would cause some untiled area to become enclosed.  There is also another
 * more exotic culprit: we might have a dislocation.  Fortunately, they
 * are very rare (the PRL article reported that perfect tilings of over
 * 2^50 tiles had been generated).  There is a version of the algorithm
 * that doesn't produce dislocations, but it's a lot hairier than the
 * simpler version I used.
 */
static int
add_forced_tile(ModeInfo * mi, forced_node_c * node)
{
	tiling_c   *tp = &tilings[MI_SCREEN(mi)];
	unsigned    side;
	vertex_type_c vtype;
	rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
	int         n;

	if (node->forced_sides == (S_LEFT | S_RIGHT))
		side = NRAND(2) ? S_LEFT : S_RIGHT;
	else
		side = node->forced_sides;
	n = match_rules(node->vertex, hits, True);
	n = find_completions(node->vertex, hits, n, side, &vtype /*, True */ );
	if (n <= 0) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_forced_tile()\n");
			(void) fprintf(stderr, "n = %d\n", n);
		}
	}
	return add_tile(mi, node->vertex, side, vtype);
}
コード例 #5
0
ファイル: penrose.c プロジェクト: Bluerise/bitrig-xenocara
/*-
 * Add a randomly chosen tile to a given vertex.  This requires more checking
 * as we must make sure the new tile conforms to the vertex rules at every
 * vertex it touches. */
static void
add_random_tile(fringe_node_c * vertex, ModeInfo * mi)
{
	fringe_node_c *right, *left, *far;
	int         i, j, n, n_hits, n_good;
	unsigned    side, fc, no_good, s;
	vertex_type_c vtypes[MAX_COMPL];
	rule_match_c hits[MAX_TILES_PER_VERTEX * N_VERTEX_RULES];
	tiling_c   *tp = &tilings[MI_SCREEN(mi)];

	if (MI_NPIXELS(mi) > 2) {
		tp->thick_color = NRAND(MI_NPIXELS(mi));
		/* Insure good contrast */
		tp->thin_color = (NRAND(2 * MI_NPIXELS(mi) / 3) + tp->thick_color +
				  MI_NPIXELS(mi) / 6) % MI_NPIXELS(mi);
	} else {
		unsigned long temp = tp->thick_color;

		tp->thick_color = tp->thin_color;
		tp->thin_color = temp;
	}
	n_hits = match_rules(vertex, hits, False);
	side = NRAND(2) ? S_LEFT : S_RIGHT;
	n = find_completions(vertex, hits, n_hits, side, vtypes /*, False */ );
	/* One answer would mean a forced tile. */
	if (n <= 0) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
			(void) fprintf(stderr, "n = %d\n", n);
		}
	}
	no_good = 0;
	n_good = n;
	for (i = 0; i < n; i++) {
		fc = fringe_changes(mi, vertex, side, vtypes[i], &right, &far, &left);
		if (fc & FC_BAG) {
			tp->done = True;
			if (MI_IS_VERBOSE(mi)) {
				(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
				(void) fprintf(stderr, "fc = %d, FC_BAG = %d\n", fc, FC_BAG);
			}
		}
		if (right) {
			s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_LEFT)) ? S_RIGHT : S_LEFT);
			if (!legal_move(right, s, VT_RIGHT(vtypes[i]))) {
				no_good |= (1 << i);
				n_good--;
				continue;
			}
		}
		if (left) {
			s = (((fc & FC_CUT_FAR) && (fc & FC_CUT_RIGHT)) ? S_LEFT : S_RIGHT);
			if (!legal_move(left, s, VT_LEFT(vtypes[i]))) {
				no_good |= (1 << i);
				n_good--;
				continue;
			}
		}
		if (far) {
			s = ((fc & FC_CUT_LEFT) ? S_RIGHT : S_LEFT);
			if (!legal_move(far, s, VT_FAR(vtypes[i]))) {
				no_good |= (1 << i);
				n_good--;
			}
		}
	}
	if (n_good <= 0) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
			(void) fprintf(stderr, "n_good = %d\n", n_good);
		}
	}
	n = NRAND(n_good);
	for (i = j = 0; i <= n; i++, j++)
		while (no_good & (1 << j))
			j++;

	if (!add_tile(mi, vertex, side, vtypes[j - 1])) {
		tp->done = True;
		if (MI_IS_VERBOSE(mi)) {
			(void) fprintf(stderr, "Weirdness in add_random_tile()\n");
		}
		free_penrose(tp);
	}
}