/// Find the point closest to p0 between p0 and p1 that is solid, /// and set result to it. Return false if there was not such point. bool find_hit(game::Map &map, Point p0, Point p1, Point &result) { if (p0 == p1) return false; /// @TODO HACK!!! Check to see if p0 and p1 are Really far away /// and if they are say no collision. This lets us do wrapping easier. //cerr << "find_hit" << p0.x << "x" << p0.y << " " //<< p1.x << "x" << p1.y << endl; if (hypot(p0.x - p1.x, p0.y - p1.y) > map.width/2) return false; int x0 = p0.x, x1 = p1.x, y0 = p0.y, y1 = p1.y; vector <Point> hits; bool steep = abs(y1 - y0) > abs(x1 - x0); { int temp; if (steep) { temp = x0; x0 = y0; y0 = temp; temp = x1; x1 = y1; y1 = temp; } if (x0 > x1) { temp = x0; x0 = x1; x1 = temp; temp = y0; y0 = y1; y1 = temp; }} int deltax = x1 - x0; int deltay = abs(y1 - y0); double error = 0; double deltaerr = ((double)deltay)/((double)deltax); int ystep; int y = y0; ystep = (y0 < y1) ? 1 : -1; for (int x = x0; x <= x1; x++) { Point current = steep ? Point(y, x) : Point(x, y); //cerr << " checking: " << current.x << "x" << current.y << endl; if (on_map(map,current) && map.is_solid(current.x, current.y)) hits.push_back(current); error += deltaerr; if (error >= 0.5) { y += ystep; error = error - 1.0; }} // Calculate the closest hit and return it. Return false if there // was no hit if (!hits.size()) return false; double lowest_distance = INFINITY; FOREACH (vector <Point>, hit, hits) { double distance = hypotf(p0.x - hit->x, p0.y - hit->y); //cerr << " hit w/distance=" << distance << " @" //<< hit->x << "x" << hit->y << endl; // Check for wrapping if (distance > map.width/2) distance = map.width - distance; if (distance < lowest_distance) { result = *hit; lowest_distance = distance; }}
void summon_demons(player_info_t * player, level_t * level) { int how_many; int y; int x; how_many = 2 + rand() % 4; while (how_many--) { y = player->mob->position.y - 2 + rand() % 5; x = player->mob->position.x - 2 + rand() % 5; if (on_map(level, y, x) && get_mob(level, y, x) == -1 && !(level->map[y * level->width + x].flags & tile_unpassable)) { try_make_mob(level, mob_demon, y, x); } } return; }
void draw_map(input_type_t input_type, level_t * level) { int y; int x; int i; int offset_y = 1; int offset_x = 1; int draw_y = offset_y; draw_map_border(input_type, level); for (y = level->view.ul_position.y; y < level->view.ul_position.y + level->view.height; y += 1) { move(++draw_y, offset_x); for (x = level->view.ul_position.x; x < level->view.ul_position.x + level->view.width; x += 1) { if(!on_map(level, y, x)) continue; if (level->map[y * level->width + x].is_explored == 0) { addch(' '); continue; } attrset(A_NORMAL); if (level->map[y * level->width + x].item) { addch('/'); continue; } if (level->map[y * level->width + x].is_lit || level->map[y * level->width + x].is_periphery) { attrset(A_BOLD); } switch (level->map[y * level->width + x].type) { case tile_void: addch(' '); break; case tile_floor: attron(COLOR_PAIR(color_green)); addch('.'); break; case tile_doorway: attron(COLOR_PAIR(color_green)); addch(ACS_BLOCK); break; case tile_corridor: addch('#'); break; case tile_wall_r: case tile_wall_l: attron(COLOR_PAIR(color_yellow)); addch(ACS_VLINE); break; case tile_wall_t: case tile_wall_b: attron(COLOR_PAIR(color_yellow)); addch(ACS_HLINE); break; case tile_wall_ll: attron(COLOR_PAIR(color_yellow)); addch(ACS_LLCORNER); break; case tile_wall_lr: attron(COLOR_PAIR(color_yellow)); addch(ACS_LRCORNER); break; case tile_wall_ul: attron(COLOR_PAIR(color_yellow)); addch(ACS_ULCORNER); break; case tile_wall_ur: attron(COLOR_PAIR(color_yellow)); addch(ACS_URCORNER); break; case tile_wall_plus: attron(COLOR_PAIR(color_yellow)); addch(ACS_PLUS); break; case tile_wall_ttee: attron(COLOR_PAIR(color_yellow)); addch(ACS_TTEE); break; case tile_wall_btee: attron(COLOR_PAIR(color_yellow)); addch(ACS_BTEE); break; case tile_wall_ltee: attron(COLOR_PAIR(color_yellow)); addch(ACS_LTEE); break; case tile_wall_rtee: attron(COLOR_PAIR(color_yellow)); addch(ACS_RTEE); break; case tile_stair: attron(A_NORMAL); addch('>'); break; default: attron(COLOR_PAIR(color_red)); addch('?'); break; } } } attrset(A_NORMAL); for (i = 0; i < MAX_MOBS_PER_LEVEL; i++) { if (level->mobs[i].type && level->map[level->mobs[i].position.y * level->width + level->mobs[i].position.x].is_lit) { int left = level->view.ul_position.x; int top = level->view.ul_position.y; int right = level->view.ul_position.x + level->view.width; int bottom = level->view.ul_position.y + level->view.height; int mob_x = level->mobs[i].position.x; int mob_y = level->mobs[i].position.y; if(mob_x > left && mob_x < right && mob_y > top && mob_y < bottom) { move(level->mobs[i].position.y - top + offset_y + 1, level->mobs[i].position.x - left + offset_x); addch(level->mobs[i].type); } } } attrset(A_NORMAL); refresh(); return; }
/* Lights up the area near a mob, marks it as explored. */ void explore(level_t * level, mob_t * mob) { int p_y; int p_x; int y; int x; int top; int bottom; int left; int right; top = level->view.ul_position.y; bottom = level->view.ul_position.y + level->view.height; left = level->view.ul_position.x; right = level->view.ul_position.x + level->view.width; p_y = mob->position.y; p_x = mob->position.x; for (y = top; y < bottom; y += 1) for (x = left; x < right; x += 1) level->map[y * level->width + x].is_lit = 0; for (y = p_y - 1; y <= p_y + 1; y++) { for (x = p_x - 1; x <= p_x + 1; x++) { if (on_map(level, y, x)) { level->map[y * level->width + x].is_explored = true; level->map[y * level->width + x].is_lit = true; level->map[y * level->width + x].is_periphery = true; } } } /* Floodfill open permalit rooms */ if (level->map[p_y * level->width + p_x].flags & tile_permalit) { bool change; do { change = false; for (y = top; y < bottom; y += 1) { if(y < 1) continue; if(y > level->height - 1) break; for (x = left; x < right; x += 1) { if(x < 1) continue; if(x > level->width - 1) break; if (level->map[y * level->width + x].flags & tile_noflood) continue; if (level->map[y * level->width + x].is_lit == 0 && (level->map[y * level->width + x].flags & tile_permalit || level->map[(y - 1) * level->width + (x - 1)].flags & tile_permalit || level->map[(y - 1) * level->width + (x + 1)].flags & tile_permalit || level->map[(y + 1) * level->width + (x - 1)].flags & tile_permalit || level->map[(y + 1) * level->width + (x + 1)].flags & tile_permalit || level->map[(y - 1) * level->width + x].flags & tile_permalit || level->map[y * level->width + (x - 1)].flags & tile_permalit || level->map[(y + 1) * level->width + x].flags & tile_permalit || level->map[y * level->width + (x + 1)].flags & tile_permalit )) { if (level->map[(y - 1) * level->width + x].is_lit || level->map[y * level->width + (x - 1)].is_lit || level->map[(y + 1) * level->width + x].is_lit || level->map[y * level->width + (x + 1)].is_lit) { level->map[y * level->width + x].is_lit = 1; level->map[y * level->width + x].is_explored = 1; change = true; } } } } } while (change); } bool match; for (y = top; y < bottom; y += 1) { for (x = left; x < right; x += 1) { match = false; if ((level->map[y * level->width + x].flags & tile_noflood) == 0) continue; if (y >= 1 && level->map[(y - 1) * level->width + x].is_lit) match = true; if (x >= 1 && level->map[y * level->width + (x - 1)].is_lit) match = true; if (y < level->height - 1 && level->map[(y + 1) * level->width + x].is_lit) match = true; if (x < level->width + 1 && level->map[y * level->width + (x + 1)].is_lit) match = true; if (y >= 1 && x >= 1 && level->map[(y - 1) * level->width + (x - 1)].is_lit) match = true; if (y >= 1 && x <= level->width && level->map[(y - 1) * level->width + (x + 1)].is_lit) match = true; if (y <= level->height && x >= 1 && level->map[(y + 1) * level->width + (x - 1)].is_lit) match = true; if (y <= level->height && x <= level->width && level->map[(y + 1) * level->width + (x + 1)].is_lit) match = true; if (match) { level->map[y * level->width + x].is_periphery = true; level->map[y * level->width + x].is_explored = true; } } } return; }
const terrain_builder::tile& terrain_builder::tilemap::operator[] (const map_location &loc) const { assert(on_map(loc)); return tiles_[(loc.x + 2) + (loc.y + 2) * (x_ + 4)]; }