void LightCaster::compute_light_mesh(Mesh* result, Walls* walls, const Vector_& light) { long nwalls = walls->nwalls(); angle = restrict_angle(angle); WallPoint* wall_points = (WallPoint*)GIGGLE->renderer->alloc(sizeof(WallPoint) * nwalls * 2); Wall** open_set = (Wall**)GIGGLE->renderer->alloc(sizeof(Wall*) * nwalls); long nopen_set = 0; for(long ii = 0; ii < nwalls; ++ii) { Wall* wall = &walls->walls[ii]; float angle_start = atan2f(wall->start.y - light.y, wall->start.x - light.x); float angle_end = atan2f(wall->end.y - light.y, wall->end.x - light.x); float dangle = restrict_angle(angle_end - angle_start); long idx1 = 2*ii; long idx2 = idx1 + 1; wall_points[idx1].point = &wall->start; wall_points[idx1].wall = wall; wall_points[idx1].angle = angle_start; wall_points[idx1].begin = dangle > 0; wall_points[idx2].point = &wall->end; wall_points[idx2].wall = wall; wall_points[idx2].angle = angle_end; wall_points[idx2].begin = !wall_points[idx1].begin; } std::sort(wall_points, wall_points + (nwalls*2), WallPointCompare()); float beginAngle = 0; for(int kk = 0; kk < 2; ++kk) { for(long ii = 0; ii < nwalls * 2; ++ii) { WallPoint* wp = &wall_points[ii]; Wall* last_closest = (nopen_set == 0) ? NULL : open_set[0]; if(wp->begin) { add_wall(open_set, &nopen_set, wp->wall, &light); } else { remove_wall(open_set, &nopen_set, wp->wall); } Wall* next_closest = (nopen_set == 0) ? NULL : open_set[0]; if(last_closest != next_closest) { float nextAngle = wp->angle; if(last_closest) { if(kk == 1) { add_triangle(result, light, last_closest, beginAngle, nextAngle); } beginAngle = nextAngle; } } } } }
DesignView::DesignView(ViewStack* vs, MapView* mapv, City* c) : vstk(vs), mv(mapv), city(c), fdv(new FurnitureDesignView(this)), rdv(new RoomsDesignView(this)) { nav.register_key(KEY_Escape, "[Esc] Back", [this]() { vstk->pop(); }); nav.register_key(KEY_space, "[Spc] Pause", [this]() { paused = !paused; }); nav.register_key(KEY_Return, "[Ent] Build Wall", [this]() { build_wall(); }); nav.register_key(KEY_Delete, "[Del] Remove Wall", [this]() { remove_wall(); }); nav.register_key(KEY_r, "[r] Construct Room", [this]() { vstk->push(rdv.get()); }); nav.register_key(KEY_f, "[f] Place Furniture", [this]() { vstk->push(fdv.get()); }); }
/* * showexpl: * Show the explosions as they currently are */ void showexpl(int y, int x, char type) { PLAYER *pp; EXPL *ep; if (y < 0 || y >= HEIGHT) return; if (x < 0 || x >= WIDTH) return; ep = malloc(sizeof(*ep)); ep->e_y = y; ep->e_x = x; ep->e_char = type; ep->e_next = NULL; if (Last_expl == NULL) Expl[0] = ep; else Last_expl->e_next = ep; Last_expl = ep; for (pp = Player; pp < End_player; pp++) { if (pp->p_maze[y][x] == type) continue; pp->p_maze[y][x] = type; cgoto(pp, y, x); outch(pp, type); } #ifdef MONITOR for (pp = Monitor; pp < End_monitor; pp++) { if (pp->p_maze[y][x] == type) continue; pp->p_maze[y][x] = type; cgoto(pp, y, x); outch(pp, type); } #endif switch (Maze[y][x]) { case WALL1: case WALL2: case WALL3: #ifdef RANDOM case DOOR: #endif #ifdef REFLECT case WALL4: case WALL5: #endif if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND) remove_wall(y, x); break; } }
/* * showexpl: * Show the explosions as they currently are */ void showexpl(int y, int x, char type) { PLAYER *pp; EXPL *ep; if (y < 0 || y >= HEIGHT) return; if (x < 0 || x >= WIDTH) return; ep = (EXPL *) malloc(sizeof (EXPL)); /* NOSTRICT */ if (ep == NULL) { logit(LOG_ERR, "malloc"); return; } ep->e_y = y; ep->e_x = x; ep->e_char = type; ep->e_next = NULL; if (Last_expl == NULL) Expl[0] = ep; else Last_expl->e_next = ep; Last_expl = ep; for (pp = Player; pp < End_player; pp++) { if (pp->p_maze[y][x] == type) continue; pp->p_maze[y][x] = type; cgoto(pp, y, x); outch(pp, type); } for (pp = Monitor; pp < End_monitor; pp++) { if (pp->p_maze[y][x] == type) continue; pp->p_maze[y][x] = type; cgoto(pp, y, x); outch(pp, type); } switch (Maze[y][x]) { case WALL1: case WALL2: case WALL3: case DOOR: case WALL4: case WALL5: if (y >= UBOUND && y < DBOUND && x >= LBOUND && x < RBOUND) remove_wall(y, x); break; } }
/** Build the maze by removing walls according to Prim's algorithm. * * @param maze a maze with all walls present. */ static void build_prim(maze_t* maze) { // MST edges and cells. If (a, b) in mst_edges, then (b, a) not in // mst_edges. (a, b) in mst_edges iff a, b both in mst_cells. list356_t* mst_edges = make_list() ; list356_t* mst_cells = make_list() ; // The frontier. This is the collection of edges between cells in the MST // and cells not in the MST. If (a, b) in frontier, then a in mst_cells // and b not in mst_cells. list356_t* frontier = make_list() ; // Choose two adjacent cells at random to put into the MST, then // populate the frontier accordinately. For simplicitly, choose a // cell in the interior of the maze, then randomly choose a direction // for the other cell. cell_t* start = get_cell(maze, random_limit(1, maze->nrows-1), random_limit(1, maze->ncols-1)); unsigned char direction = 1 << random_limit(0, 4) ; cell_t* next = get_neighbor(maze, start, direction) ; /* debug("Removing (%d, %d) - (%d, %d).\n", start->r, start->c, next->r, next->c) ; */ remove_wall(maze, start, direction) ; edge_t init_edge = (edge_t){start, next} ; lst_add(mst_edges, &init_edge) ; lst_add(mst_cells, start) ; lst_add(mst_cells, next) ; for (int d=0; d<4; ++d) { if (directions[d] != direction && is_cell(maze, start, directions[d])) { cell_t* c = get_neighbor(maze, start, directions[d]) ; edge_t* e = malloc(sizeof(edge_t)) ; e->a = start ; e->b = c ; lst_add(frontier, e) ; } } for (int d=0; d<4; ++d) { if (directions[d] != opposite(direction) && is_cell(maze, next, directions[d])) { cell_t* c = get_neighbor(maze, next, directions[d]) ; edge_t* e = malloc(sizeof(edge_t)) ; e->a = next ; e->b = c ; lst_add(frontier, e) ; } } // As long as we don't have all the cells in the MST, choose an // edge in the frontier at random. Put the edge in the MST // and compute the new edges to add to the frontier. while (lst_size(mst_cells) < (maze->nrows)*(maze->ncols)) { int p = random_limit(0, lst_size(frontier)) ; edge_t* edge = lst_get(frontier, p) ; cell_t* old_cell = edge->a ; cell_t* new_cell = edge->b ; /* debug("Removing (%d, %d) - (%d, %d).\n", old_cell->r, old_cell->c, new_cell->r, new_cell->c) ; */ remove_wall(maze, old_cell, get_direction(old_cell, new_cell)) ; lst_add(mst_edges, edge) ; lst_add(mst_cells, new_cell) ; for (int d=0; d<4; ++d) { unsigned char dir = directions[d] ; if (is_cell(maze, new_cell, dir)) { cell_t* adj_cell = get_neighbor(maze, new_cell, dir) ; edge_t* edge2 = malloc(sizeof(edge_t)) ; edge2->a = new_cell ; edge2->b = adj_cell ; if (lst_contains(mst_cells, adj_cell, cell_cmp)) { lst_remove(frontier, edge2, edge_cmp) ; if (adj_cell != old_cell) free(edge2) ; } else { lst_add(frontier, edge2) ; } } } } }