Example #1
0
/*
 * Sorting hook srt squares by "distance to player"
 *
 * We use pythagoreans theorum to calculate the distance
 */
static bool coords_sort_distance(coord c1, coord c2)
{
    int py = p_ptr->py;
    int px = p_ptr->px;

    int dist1 = GET_SQUARE(py - c1.y) + GET_SQUARE(px - c1.x);
    int dist2 = GET_SQUARE(py - c2.y) + GET_SQUARE(px - c2.x);

    /* Compare the distances */
    return (dist1 <= dist2);
}
Example #2
0
static void game_redraw(drawing *dr, game_drawstate *ds,
                        const game_state *oldstate, const game_state *state,
                        int dir, const game_ui *ui,
                        float animtime, float flashtime)
{
    int i, j;
    struct bbox bb = find_bbox(&state->params);
    struct solid *poly;
    const int *pkey, *gkey;
    float t[3];
    float angle;
    int square;

    draw_rect(dr, 0, 0, XSIZE(GRID_SCALE, bb, state->solid),
	      YSIZE(GRID_SCALE, bb, state->solid), COL_BACKGROUND);

    if (dir < 0) {
        const game_state *t;

        /*
         * This is an Undo. So reverse the order of the states, and
         * run the roll timer backwards.
         */
	assert(oldstate);

        t = oldstate;
        oldstate = state;
        state = t;

        animtime = ROLLTIME - animtime;
    }

    if (!oldstate) {
        oldstate = state;
        angle = 0.0;
        square = state->current;
        pkey = state->dpkey;
        gkey = state->dgkey;
    } else {
        angle = state->angle * animtime / ROLLTIME;
        square = state->previous;
        pkey = state->spkey;
        gkey = state->sgkey;
    }
    state = oldstate;

    for (i = 0; i < state->grid->nsquares; i++) {
        int coords[8];

        for (j = 0; j < state->grid->squares[i].npoints; j++) {
            coords[2*j] = ((int)(state->grid->squares[i].points[2*j] * GRID_SCALE)
			   + ds->ox);
            coords[2*j+1] = ((int)(state->grid->squares[i].points[2*j+1]*GRID_SCALE)
			     + ds->oy);
        }

        draw_polygon(dr, coords, state->grid->squares[i].npoints,
                     GET_SQUARE(state, i) ? COL_BLUE : COL_BACKGROUND,
		     COL_BORDER);
    }

    /*
     * Now compute and draw the polyhedron.
     */
    poly = transform_poly(state->solid, state->grid->squares[square].flip,
                          pkey[0], pkey[1], angle);

    /*
     * Compute the translation required to align the two key points
     * on the polyhedron with the same key points on the current
     * face.
     */
    for (i = 0; i < 3; i++) {
        float tc = 0.0;

        for (j = 0; j < 2; j++) {
            float grid_coord;

            if (i < 2) {
                grid_coord =
                    state->grid->squares[square].points[gkey[j]*2+i];
            } else {
                grid_coord = 0.0;
            }

            tc += (grid_coord - poly->vertices[pkey[j]*3+i]);
        }

        t[i] = tc / 2;
    }
    for (i = 0; i < poly->nvertices; i++)
        for (j = 0; j < 3; j++)
            poly->vertices[i*3+j] += t[j];

    /*
     * Now actually draw each face.
     */
    for (i = 0; i < poly->nfaces; i++) {
        float points[8];
        int coords[8];

        for (j = 0; j < poly->order; j++) {
            int f = poly->faces[i*poly->order + j];
            points[j*2] = (poly->vertices[f*3+0] -
                           poly->vertices[f*3+2] * poly->shear);
            points[j*2+1] = (poly->vertices[f*3+1] -
                             poly->vertices[f*3+2] * poly->shear);
        }

        for (j = 0; j < poly->order; j++) {
            coords[j*2] = (int)floor(points[j*2] * GRID_SCALE) + ds->ox;
            coords[j*2+1] = (int)floor(points[j*2+1] * GRID_SCALE) + ds->oy;
        }

        /*
         * Find out whether these points are in a clockwise or
         * anticlockwise arrangement. If the latter, discard the
         * face because it's facing away from the viewer.
         *
         * This would involve fiddly winding-number stuff for a
         * general polygon, but for the simple parallelograms we'll
         * be seeing here, all we have to do is check whether the
         * corners turn right or left. So we'll take the vector
         * from point 0 to point 1, turn it right 90 degrees,
         * and check the sign of the dot product with that and the
         * next vector (point 1 to point 2).
         */
        {
            float v1x = points[2]-points[0];
            float v1y = points[3]-points[1];
            float v2x = points[4]-points[2];
            float v2y = points[5]-points[3];
            float dp = v1x * v2y - v1y * v2x;

            if (dp <= 0)
                continue;
        }

        draw_polygon(dr, coords, poly->order,
                     state->facecolours[i] ? COL_BLUE : COL_BACKGROUND,
		     COL_BORDER);
    }
    sfree(poly);

    draw_update(dr, 0, 0, XSIZE(GRID_SCALE, bb, state->solid),
		YSIZE(GRID_SCALE, bb, state->solid));

    /*
     * Update the status bar.
     */
    {
	char statusbuf[256];

	if (state->completed) {
		strcpy(statusbuf, _("COMPLETED!"));
		strcpy(statusbuf+strlen(statusbuf), " ");
	} else statusbuf[0] = '\0';
	sprintf(statusbuf+strlen(statusbuf), _("Moves: %d"),
		(state->completed ? state->completed : state->movecount));

	status_bar(dr, statusbuf);
    }
}
Example #3
0
static game_state *execute_move(const game_state *from, const char *move)
{
    game_state *ret;
    float angle;
    struct solid *poly;
    int pkey[2];
    int skey[2], dkey[2];
    int i, j, dest;
    int direction;

    switch (*move) {
      case 'L': direction = LEFT; break;
      case 'R': direction = RIGHT; break;
      case 'U': direction = UP; break;
      case 'D': direction = DOWN; break;
      default: return NULL;
    }

    dest = find_move_dest(from, direction, skey, dkey);
    if (dest < 0)
        return NULL;

    ret = dup_game(from);
    ret->current = dest;

    /*
     * So we know what grid square we're aiming for, and we also
     * know the two key points (as indices in both the source and
     * destination grid squares) which are invariant between source
     * and destination.
     * 
     * Next we must roll the polyhedron on to that square. So we
     * find the indices of the key points within the polyhedron's
     * vertex array, then use those in a call to transform_poly,
     * and align the result on the new grid square.
     */
    {
        int all_pkey[4];
        align_poly(from->solid, &from->grid->squares[from->current], all_pkey);
        pkey[0] = all_pkey[skey[0]];
        pkey[1] = all_pkey[skey[1]];
        /*
         * Now pkey[0] corresponds to skey[0] and dkey[0], and
         * likewise [1].
         */
    }

    /*
     * Now find the angle through which to rotate the polyhedron.
     * Do this by finding the two faces that share the two vertices
     * we've found, and taking the dot product of their normals.
     */
    {
        int f[2], nf = 0;
        float dp;

        for (i = 0; i < from->solid->nfaces; i++) {
            int match = 0;
            for (j = 0; j < from->solid->order; j++)
                if (from->solid->faces[i*from->solid->order + j] == pkey[0] ||
                    from->solid->faces[i*from->solid->order + j] == pkey[1])
                    match++;
            if (match == 2) {
                assert(nf < 2);
                f[nf++] = i;
            }
        }

        assert(nf == 2);

        dp = 0;
        for (i = 0; i < 3; i++)
            dp += (from->solid->normals[f[0]*3+i] *
                   from->solid->normals[f[1]*3+i]);
        angle = (float)acos(dp);
    }

    /*
     * Now transform the polyhedron. We aren't entirely sure
     * whether we need to rotate through angle or -angle, and the
     * simplest way round this is to try both and see which one
     * aligns successfully!
     * 
     * Unfortunately, _both_ will align successfully if this is a
     * cube, which won't tell us anything much. So for that
     * particular case, I resort to gross hackery: I simply negate
     * the angle before trying the alignment, depending on the
     * direction. Which directions work which way is determined by
     * pure trial and error. I said it was gross :-/
     */
    {
        int all_pkey[4];
        int success;

        if (from->solid->order == 4 && direction == UP)
            angle = -angle;            /* HACK */

        poly = transform_poly(from->solid,
                              from->grid->squares[from->current].flip,
                              pkey[0], pkey[1], angle);
        flip_poly(poly, from->grid->squares[ret->current].flip);
        success = align_poly(poly, &from->grid->squares[ret->current], all_pkey);

        if (!success) {
            sfree(poly);
            angle = -angle;
            poly = transform_poly(from->solid,
                                  from->grid->squares[from->current].flip,
                                  pkey[0], pkey[1], angle);
            flip_poly(poly, from->grid->squares[ret->current].flip);
            success = align_poly(poly, &from->grid->squares[ret->current], all_pkey);
        }

        assert(success);
    }

    /*
     * Now we have our rotated polyhedron, which we expect to be
     * exactly congruent to the one we started with - but with the
     * faces permuted. So we map that congruence and thereby figure
     * out how to permute the faces as a result of the polyhedron
     * having rolled.
     */
    {
        int *newcolours = snewn(from->solid->nfaces, int);

        for (i = 0; i < from->solid->nfaces; i++)
            newcolours[i] = -1;

        for (i = 0; i < from->solid->nfaces; i++) {
            int nmatch = 0;

            /*
             * Now go through the transformed polyhedron's faces
             * and figure out which one's normal is approximately
             * equal to this one.
             */
            for (j = 0; j < poly->nfaces; j++) {
                float dist;
                int k;

                dist = 0;

                for (k = 0; k < 3; k++)
                    dist += SQ(poly->normals[j*3+k] -
                               from->solid->normals[i*3+k]);

                if (APPROXEQ(dist, 0)) {
                    nmatch++;
                    newcolours[i] = ret->facecolours[j];
                }
            }

            assert(nmatch == 1);
        }

        for (i = 0; i < from->solid->nfaces; i++)
            assert(newcolours[i] != -1);

        sfree(ret->facecolours);
        ret->facecolours = newcolours;
    }

    ret->movecount++;

    /*
     * And finally, swap the colour between the bottom face of the
     * polyhedron and the face we've just landed on.
     * 
     * We don't do this if the game is already complete, since we
     * allow the user to roll the fully blue polyhedron around the
     * grid as a feeble reward.
     */
    if (!ret->completed) {
        i = lowest_face(from->solid);
        j = ret->facecolours[i];
        ret->facecolours[i] = GET_SQUARE(ret, ret->current);
        SET_SQUARE(ret, ret->current, j);

        /*
         * Detect game completion.
         */
        j = 0;
        for (i = 0; i < ret->solid->nfaces; i++)
            if (ret->facecolours[i])
                j++;
        if (j == ret->solid->nfaces) {
            ret->completed = ret->movecount;
        }

    }

    sfree(poly);

    /*
     * Align the normal polyhedron with its grid square, to get key
     * points for non-animated display.
     */
    {
        int pkey[4];
        int success;

        success = align_poly(ret->solid, &ret->grid->squares[ret->current], pkey);
        assert(success);

        ret->dpkey[0] = pkey[0];
        ret->dpkey[1] = pkey[1];
        ret->dgkey[0] = 0;
        ret->dgkey[1] = 1;
    }


    ret->spkey[0] = pkey[0];
    ret->spkey[1] = pkey[1];
    ret->sgkey[0] = skey[0];
    ret->sgkey[1] = skey[1];
    ret->previous = from->current;
    ret->angle = angle;

    return ret;
}
Example #4
0
#define _GNU_SOURCE
#include <stdlib.h>
#include <stdarg.h>
#include <stdio.h>
#include <string.h>

#include "monitor.h"
#include "serveur.h"

void	avertCase(serveur* this, clients* monitor, char* k) {
  position p;
  char*		r;

  sscanf(k, "bct %d %d\n", &(p.x), &(p.y));
  r = GET_SQUARE(this, p.x, p.y);
  avertThisMonitor(monitor,
		   mCaseMap(p.x, p.y,
			    r[nourriture], r[linemate], r[deraumere],
			    r[sibur], r[mendiane], r[phiras],
			    r[thystame]
			    ));
}

void	avertMap(serveur* this, clients* monitor) {
  position	p;
  char* r;

  p.x = 0;
  while (p.x < this->size.x)
    {
      p.y = 0;