/* * 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); }
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); } }
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; }
#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;