/*! \brief Tests a if a given OBJECT was hit at a given set of coordinates * * \par Function Description * Tests a if a given OBJECT was hit at a given set of coordinates. If an * object is not selectable (e.g. it is locked), or it is invisible and * not being rendered, this function will return FALSE. * * \param [in] w_current The GschemToplevel object. * \param [in] object The OBJECT being hit-tested. * \param [in] w_x The X coordinate to test (in world coords). * \param [in] w_y The Y coordinate to test (in world coords). * \param [in] w_slack The slack applied to the hit-test. * * \returns TRUE if the OBJECT was hit, otherwise FALSE. */ static gboolean is_object_hit (GschemToplevel *w_current, OBJECT *object, int w_x, int w_y, int w_slack) { int left, top, right, bottom; if (!object->selectable) return FALSE; /* We can't hit invisible (text) objects unless show_hidden_text is active. */ if (!o_is_visible (object) && !w_current->toplevel->show_hidden_text) return FALSE; /* Do a coarse test first to avoid computing distances for objects ouside * of the hit range. */ if (!world_get_single_object_bounds(w_current->toplevel, object, &left, &top, &right, &bottom) || !inside_region (left - w_slack, top - w_slack, right + w_slack, bottom + w_slack, w_x, w_y)) return FALSE; return (o_shortest_distance (w_current->toplevel, object, w_x, w_y) < w_slack); }
static errval_t do_single_modify_flags(struct pmap_arm *pmap, genvaddr_t vaddr, size_t pages, vregion_flags_t flags) { errval_t err = SYS_ERR_OK; struct vnode *ptable = find_ptable(pmap, vaddr); uint16_t ptentry = ARM_USER_L2_OFFSET(vaddr); if (ptable) { struct vnode *page = find_vnode(ptable, ptentry); if (page) { if (inside_region(ptable, ptentry, pages)) { // we're modifying part of a valid mapped region // arguments to invocation: invoke frame cap, first affected // page (as offset from first page in mapping), #affected // pages, new flags. Invocation should check compatibility of // new set of flags with cap permissions. size_t off = ptentry - page->entry; uintptr_t pmap_flags = vregion_flags_to_kpi_paging_flags(flags); err = invoke_frame_modify_flags(page->u.frame.cap, off, pages, pmap_flags); printf("invoke_frame_modify_flags returned error: %s (%"PRIuERRV")\n", err_getstring(err), err); return err; } else { // overlaps some region border return LIB_ERR_PMAP_EXISTING_MAPPING; } } } return SYS_ERR_OK; }
/* * check whether player enters/leaves one or more regions. */ boolean in_out_region(struct level *lev, xchar x, xchar y) { int i, f_indx; /* First check if we can do the move */ for (i = 0; i < lev->n_regions; i++) { if (inside_region(lev->regions[i], x, y) && !hero_inside(lev->regions[i]) && !lev->regions[i]->attach_2_u) { if ((f_indx = lev->regions[i]->can_enter_f) != NO_CALLBACK) if (!(*callbacks[f_indx]) (lev->regions[i], 0)) return FALSE; } else if (hero_inside(lev->regions[i]) && !inside_region(lev->regions[i], x, y) && !lev->regions[i]->attach_2_u) { if ((f_indx = lev->regions[i]->can_leave_f) != NO_CALLBACK) if (!(*callbacks[f_indx]) (lev->regions[i], 0)) return FALSE; } } /* Callbacks for the regions we do leave */ for (i = 0; i < lev->n_regions; i++) if (hero_inside(lev->regions[i]) && !lev->regions[i]->attach_2_u && !inside_region(lev->regions[i], x, y)) { clear_hero_inside(lev->regions[i]); if (lev->regions[i]->leave_msg != NULL) pline("%s", lev->regions[i]->leave_msg); if ((f_indx = lev->regions[i]->leave_f) != NO_CALLBACK) (void)(*callbacks[f_indx]) (lev->regions[i], 0); } /* Callbacks for the regions we do enter */ for (i = 0; i < lev->n_regions; i++) if (!hero_inside(lev->regions[i]) && !lev->regions[i]->attach_2_u && inside_region(lev->regions[i], x, y)) { set_hero_inside(lev->regions[i]); if (lev->regions[i]->enter_msg != NULL) pline("%s", lev->regions[i]->enter_msg); if ((f_indx = lev->regions[i]->enter_f) != NO_CALLBACK) (void)(*callbacks[f_indx]) (lev->regions[i], 0); } return TRUE; }
/* * check whether a monster enters/leaves one or more region. */ boolean m_in_out_region(struct monst * mon, xchar x, xchar y) { int i, f_indx; /* First check if we can do the move */ for (i = 0; i < mon->dlevel->n_regions; i++) { if (inside_region(mon->dlevel->regions[i], x, y) && !mon_in_region(mon->dlevel->regions[i], mon) && mon->dlevel->regions[i]->attach_2_m != mon->m_id) { if ((f_indx = mon->dlevel->regions[i]->can_enter_f) != NO_CALLBACK) if (!(*callbacks[f_indx]) (mon->dlevel->regions[i], mon)) return FALSE; } else if (mon_in_region(mon->dlevel->regions[i], mon) && !inside_region(mon->dlevel->regions[i], x, y) && mon->dlevel->regions[i]->attach_2_m != mon->m_id) { if ((f_indx = mon->dlevel->regions[i]->can_leave_f) != NO_CALLBACK) if (!(*callbacks[f_indx]) (mon->dlevel->regions[i], mon)) return FALSE; } } /* Callbacks for the regions we do leave */ for (i = 0; i < mon->dlevel->n_regions; i++) if (mon_in_region(mon->dlevel->regions[i], mon) && mon->dlevel->regions[i]->attach_2_m != mon->m_id && !inside_region(mon->dlevel->regions[i], x, y)) { remove_mon_from_reg(mon->dlevel->regions[i], mon); if ((f_indx = mon->dlevel->regions[i]->leave_f) != NO_CALLBACK) (void)(*callbacks[f_indx]) (mon->dlevel->regions[i], mon); } /* Callbacks for the regions we do enter */ for (i = 0; i < mon->dlevel->n_regions; i++) if (!hero_inside(mon->dlevel->regions[i]) && !mon->dlevel->regions[i]->attach_2_u && inside_region(mon->dlevel->regions[i], x, y)) { add_mon_to_reg(mon->dlevel->regions[i], mon); if ((f_indx = mon->dlevel->regions[i]->enter_f) != NO_CALLBACK) (void)(*callbacks[f_indx]) (mon->dlevel->regions[i], mon); } return TRUE; }
/* * Check if a spot is under a visible region (eg: gas cloud). * Returns NULL if not, otherwise returns region. */ struct region * visible_region_at(struct level *lev, xchar x, xchar y) { int i; for (i = 0; i < lev->n_regions; i++) if (inside_region(lev->regions[i], x, y) && lev->regions[i]->visible && lev->regions[i]->ttl != 0) return lev->regions[i]; return NULL; }
/* * Checks player's regions after a teleport for instance. */ void update_player_regions(struct level *lev) { int i; for (i = 0; i < lev->n_regions; i++) if (!lev->regions[i]->attach_2_u && inside_region(lev->regions[i], u.ux, u.uy)) set_hero_inside(lev->regions[i]); else clear_hero_inside(lev->regions[i]); }
/* * Add a region to the list. * This actually activates the region. */ void add_region(struct level *lev, struct region *reg) { struct region **tmp_reg; int i, j; if (lev->max_regions <= lev->n_regions) { tmp_reg = lev->regions; lev->regions = malloc(sizeof (struct region *) * (lev->max_regions + 10)); if (lev->max_regions > 0) { memcpy(lev->regions, tmp_reg, lev->max_regions * sizeof (struct region *)); free(tmp_reg); } lev->max_regions += 10; } reg->lev = lev; lev->regions[lev->n_regions] = reg; lev->n_regions++; /* Check for monsters inside the region */ for (i = reg->bounding_box.lx; i <= reg->bounding_box.hx; i++) for (j = reg->bounding_box.ly; j <= reg->bounding_box.hy; j++) { /* Some lev->regions can cross the level boundaries */ if (!isok(i, j)) continue; if (MON_AT(level, i, j) && inside_region(reg, i, j)) add_mon_to_reg(reg, level->monsters[i][j]); if (reg->visible && cansee(i, j)) newsym(i, j); } /* Check for player now... */ if (inside_region(reg, u.ux, u.uy)) set_hero_inside(reg); else clear_hero_inside(reg); }
/* * Ditto for a specified monster. */ void update_monster_region(struct monst *mon) { int i; for (i = 0; i < mon->dlevel->n_regions; i++) { if (inside_region(mon->dlevel->regions[i], mon->mx, mon->my)) { if (!mon_in_region(mon->dlevel->regions[i], mon)) add_mon_to_reg(mon->dlevel->regions[i], mon); } else { if (mon_in_region(mon->dlevel->regions[i], mon)) remove_mon_from_reg(mon->dlevel->regions[i], mon); } } }
/* * Remove a region from the list & free it. */ void remove_region(struct region *reg) { int i, x, y; struct level *lev = reg->lev; for (i = 0; i < reg->lev->n_regions; i++) if (reg->lev->regions[i] == reg) break; if (i == reg->lev->n_regions) return; /* Update screen if necessary */ if (reg->visible && level == lev) for (x = reg->bounding_box.lx; x <= reg->bounding_box.hx; x++) for (y = reg->bounding_box.ly; y <= reg->bounding_box.hy; y++) if (isok(x, y) && inside_region(reg, x, y) && cansee(x, y)) newsym(x, y); free_region(reg); lev->regions[i] = lev->regions[lev->n_regions - 1]; lev->regions[lev->n_regions - 1] = NULL; lev->n_regions--; }