Пример #1
0
// --------------------------------------------------------------------------------------
// Select next segment.
//	If there is a connection on the current side, then choose that segment.
// If there is no connecting segment on the current side, try any segment.
__attribute_warn_unused_result
static std::pair<vsegptridx_t, uint_fast32_t> get_next_segment_side(const vsegptridx_t curseg_num, uint_fast32_t curside)
{
    const auto side_child = curseg_num->children[curside];
    if (IS_CHILD(side_child))
    {
        const auto &&newseg_num = curseg_num.absolute_sibling(side_child);
        // Find out what side we came in through and favor side opposite that
        const auto newside = Side_opposite[find_connect_side(curseg_num, newseg_num)];
        // If there is nothing attached on the side opposite to what we came in (*newside), pick any other side
        if (!IS_CHILD(newseg_num->children[newside]))
            for (uint_fast32_t s = 0; s != MAX_SIDES_PER_SEGMENT; ++s)
            {
                const auto cseg = newseg_num->children[s];
                if (cseg != curseg_num && IS_CHILD(cseg))
                    return {newseg_num, s};
            }
        return {newseg_num, newside};
    }
    else
    {
        return {curseg_num, curside};
    }

}
Пример #2
0
// ---------------------------------------------------------------------------------------------------
// Do chase mode.
//	View current segment (Cursegp) from the previous segment.
void set_chase_matrix(segment *sp)
{
	int			v;
	vms_vector	forvec = ZERO_VECTOR, upvec;
	vms_vector	tv = ZERO_VECTOR;
	segment		*psp;

	// move back two segments, if possible, else move back one, if possible, else use current
	if (IS_CHILD(sp->children[WFRONT])) {
		psp = &Segments[sp->children[WFRONT]];
		if (IS_CHILD(psp->children[WFRONT]))
			psp = &Segments[psp->children[WFRONT]];
	} else
		psp = sp;

	for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++)
		vm_vec_add2(&forvec,&Vertices[sp->verts[v]]);
	vm_vec_scale(&forvec,F1_0/MAX_VERTICES_PER_SEGMENT);

	for (v=0; v<MAX_VERTICES_PER_SEGMENT; v++)
		vm_vec_add2(&tv,&Vertices[psp->verts[v]]);
	vm_vec_scale(&tv,F1_0/MAX_VERTICES_PER_SEGMENT);

	Ed_view_target = forvec;

	vm_vec_sub2(&forvec,&tv);

	extract_up_vector_from_segment(psp,&upvec);

	if (!((forvec.x == 0) && (forvec.y == 0) && (forvec.z == 0)))
		vm_vector_2_matrix(&LargeView.ev_matrix,&forvec,&upvec,NULL);
}
Пример #3
0
//---------------------------------------------------------------------
// Add a wall (removable 2 sided)
int add_wall(segment *seg, short side)
{
	int Connectside;
	segment *csegp;

	if (Num_walls < MAX_WALLS-2)
  	if (IS_CHILD(seg->children[side])) {
		if (seg->sides[side].wall_num == -1) {
 			seg->sides[side].wall_num = Num_walls;
			Num_walls++;
			}
				 
		csegp = &Segments[seg->children[side]];
		Connectside = find_connect_side(seg, csegp);

		if (csegp->sides[Connectside].wall_num == -1) {
			csegp->sides[Connectside].wall_num = Num_walls;
			Num_walls++;
			}
		
		create_removable_wall( seg, side, CurrentTexture );
		create_removable_wall( csegp, Connectside, CurrentTexture );

		return 1;
		}

	return 0;
}
Пример #4
0
//  -------------- Create all sloppy joints within CurrentGroup ------------------
int CreateSloppyAdjacentJointsGroup()
{
	int		adj_side;
	int		done_been_a_change = 0;
	range_for(const auto &gs, GroupList[current_group].segments)
	{
		auto segp = vsegptridx(gs);

		for (int sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
			if (!IS_CHILD(segp->children[sidenum]))
			{
				segptridx_t adj_sp = segment_none;
				if (med_find_closest_threshold_segment_side(segp, sidenum, adj_sp, &adj_side, 5*F1_0)) {
					if (adj_sp->group == segp->group) {
						if (segp->children[sidenum] != adj_sp)
							if (!med_form_joint(segp, sidenum, adj_sp,adj_side))
								done_been_a_change = 1;
					}
				}
			}
	}

	if (done_been_a_change) {
		Update_flags |= UF_WORLD_CHANGED;
		mine_changed = 1;
		autosave_mine(mine_filename);
		diagnostic_message("Sloppy Joint segment formed.");
		undo_status[Autosave_count] = "Sloppy Joint segment undone.";
		warn_if_concave_segments();
	}

	return 1;
}
Пример #5
0
// ----------------------------------------------------------------------------------------------------------------
// Recursively parse mine structure, drawing segments.
void draw_mine_sub(int segnum,int depth)
{
	segment *mine_ptr;

	if (Been_visited[segnum]) return;		// If segment already drawn, return.

	Been_visited[segnum] = 1;		// Say that this segment has been drawn.

	mine_ptr = &Segments[segnum];

	// If this segment is active, process it, else skip it.

	if (mine_ptr->segnum != -1) {
		int	side;

		if (Search_mode) check_segment(mine_ptr);
		else add_edges(mine_ptr);	//add this segments edges to list

		if (depth != 0) {
			for (side=0; side<MAX_SIDES_PER_SEGMENT; side++) {
				if (IS_CHILD(mine_ptr->children[side])) {
					if (mine_ptr->sides[side].wall_num != -1)
						draw_special_wall(mine_ptr, side);
					draw_mine_sub(mine_ptr->children[side],depth-1);
				}
			}
		}
	}
}
Пример #6
0
//-----------------------------------------------------------------
// Adds a specific trigger flag to Markedsegp/Markedside if it is possible.
// Automatically adds flag to Connectside if possible unless it is a control trigger.
// Returns 1 if trigger flag added.
// Returns 0 if trigger flag cannot be added.
int trigger_flag_Markedside(short flag, int value)
{
	int trigger_num; //, ctrigger_num;
	int wall_num;
	
	if (!Markedsegp) {
		editor_status("No Markedside.");
		return 0;
	}

	// If no child on Markedside return
	if (!IS_CHILD(Markedsegp->children[Markedside])) return 0;

	// If no wall just return
	wall_num = Markedsegp->sides[Markedside].wall_num;
	if (!value && wall_num == -1) return 0;
	trigger_num = value ? add_trigger(Markedsegp, Markedside) : Walls[wall_num].trigger;

	if (trigger_num == -1) {
		editor_status(value ? "Cannot add trigger at Markedside." : "No trigger at Markedside.");
		return 0;
	}

 	if (value)
		Triggers[trigger_num].flags |= flag;
	else
		Triggers[trigger_num].flags &= ~flag;

	return 1;
}
Пример #7
0
int trigger_remove_flag_from_Markedside(short flag) {
	int trigger_num; //, ctrigger_num;
	int wall_num;
	
	if (!Markedsegp) {
		editor_status("No Markedside.");
		return 0;
	}

	// If no child on Markedside return
	if (!IS_CHILD(Markedsegp->children[Markedside])) return 0;

	// If no wall just return
	wall_num = Markedsegp->sides[Markedside].wall_num;
	if (wall_num == -1) return 0;

	trigger_num = Walls[wall_num].trigger;

	// If flag is already cleared, then don't change anything.
	if ( trigger_num == -1 ) {
		editor_status("No trigger at Markedside.");
		return 0;
	}

	if (!Triggers[trigger_num].flags & flag)
		return 1;

 	Triggers[trigger_num].flags &= ~flag;

	return 1;
}
Пример #8
0
//  -------------- Create all sloppy joints within CurrentGroup ------------------
int CreateSloppyAdjacentJointsGroup()
{
    int		adj_side;
    segment	*adj_sp;
    int		num_segs = GroupList[current_group].num_segments;
    short		*segs = GroupList[current_group].segments;
    segment	*segp;
    int		done_been_a_change = 0;
    int		segind, sidenum;

    for (segind=0; segind<num_segs; segind++) {
        segp = &Segments[segs[segind]];

        for (sidenum=0; sidenum < MAX_SIDES_PER_SEGMENT; sidenum++)
            if (!IS_CHILD(segp->children[sidenum]))
                if (med_find_closest_threshold_segment_side(segp, sidenum, &adj_sp, &adj_side, 5*F1_0)) {
                    if (adj_sp->group == segp->group) {
                        if (segp->children[sidenum] != adj_sp-Segments)
                            if (!med_form_joint(segp, sidenum, adj_sp,adj_side))
                                done_been_a_change = 1;
                    }
                }
    }

    if (done_been_a_change) {
        Update_flags |= UF_WORLD_CHANGED;
        mine_changed = 1;
        autosave_mine(mine_filename);
        diagnostic_message("Sloppy Joint segment formed.");
        strcpy(undo_status[Autosave_count], "Sloppy Joint segment undone.");
        warn_if_concave_segments();
    }

    return 1;
}
Пример #9
0
__attribute_warn_unused_result
static vsegptridx_t get_previous_segment(const vsegptridx_t curseg_num, const uint_fast32_t curside)
{
    const auto side_child = curseg_num->children[Side_opposite[curside]];
    if (IS_CHILD(side_child))
        return curseg_num.absolute_sibling(side_child);
    // no segment on opposite face, connect to anything
    return get_any_attached_segment(curseg_num, curside);
}
Пример #10
0
// -----------------------------------------------------------------------------
//	Increase the size of Cursegp in dimension dimension by amount
int segsize_common(int dimension, fix amount)
{
    int	i;
    int	propagated[MAX_SIDES_PER_SEGMENT];
    vms_vector	uvec, rvec, fvec, scalevec;

    Degenerate_segment_found = 0;

    med_scale_segment_new(Cursegp, dimension, amount);

    med_extract_up_vector_from_segment_side(Cursegp, Curside, &uvec);
    med_extract_right_vector_from_segment_side(Cursegp, Curside, &rvec);
    extract_forward_vector_from_segment(Cursegp, &fvec);

    scalevec.x = vm_vec_mag(&rvec);
    scalevec.y = vm_vec_mag(&uvec);
    scalevec.z = vm_vec_mag(&fvec);

    if (Degenerate_segment_found) {
        Degenerate_segment_found = 0;
        // mprintf(0, "Applying scale would create degenerate segments.  Aborting scale.\n");
        editor_status("Applying scale would create degenerate segments.  Aborting scale.");
        med_scale_segment_new(Cursegp, dimension, -amount);
        return 1;
    }

    med_create_new_segment(&scalevec);

    //	For all segments to which Cursegp is connected, propagate tmap (uv coordinates) from the connected
    //	segment back to Cursegp.  This will meaningfully propagate uv coordinates to all sides which havve
    //	an incident edge.  It will also do some sides more than once.  And it is probably just not what you want.
    for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
        propagated[i] = 0;

    for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
        if (IS_CHILD(Cursegp->children[i])) {
            int	s;
            for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
                propagated[s]++;
            propagated[Side_opposite[i]]--;
            med_propagate_tmaps_to_segments(&Segments[Cursegp->children[i]],Cursegp,1);
        }

    //	Now, for all sides that were not adjacent to another side, and therefore did not get tmaps
    //	propagated to them, treat as a back side.
    for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
        if (!propagated[i]) {
            med_propagate_tmaps_to_back_side(Cursegp, i, 1);
        }

    //	New stuff, assign default texture to all affected sides.

    Update_flags |= UF_WORLD_CHANGED;
    mine_changed = 1;
    return 1;
}
Пример #11
0
// ---------------------------------------------------------------------------------------
// Select previous segment.
//	If there is a connection on the side opposite to the current side, then choose that segment.
// If there is no connecting segment on the opposite face, try any segment.
void get_previous_segment(int curseg_num, int curside,int *newseg_num, int *newside)
{
	int     s;

	*newseg_num = curseg_num;

        if (IS_CHILD(Segments[curseg_num].children[(int)Side_opposite[curside]]))
                *newseg_num = Segments[curseg_num].children[(int)Side_opposite[curside]];
	else        // no segment on opposite face, connect to anything
		for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
			if ((s != curside) && IS_CHILD(Segments[curseg_num].children[s]))
				*newseg_num = Segments[curseg_num].children[s];

	// Now make Curside point at the segment we just left (unless we couldn't leave it).
	if (*newseg_num != curseg_num)
		*newside = find_connect_side(&Segments[curseg_num],&Segments[*newseg_num]);
	else
		*newside = curside;
}
Пример #12
0
//	-----------------------------------------------------------------------------
//	Return true if ok for buddy to talk, else return false.
//	Buddy is allowed to talk if the segment he is in does not contain a blastable wall that has not been blasted
//	AND he has never yet, since being initialized for level, been allowed to talk.
int BuddyMayTalk(void)
{
	int		i;
	segment	*segp;

	if (gameData.objs.objects[gameData.escort.nObjNum].type != OBJ_ROBOT) {
		gameData.escort.bMayTalk = 0;
		return 0;
	}

	if (gameData.escort.bMayTalk)
		return 1;

	if ((gameData.objs.objects[gameData.escort.nObjNum].type == OBJ_ROBOT) && 
		(gameData.escort.nObjNum <= gameData.objs.nLastObject) && 
		!gameData.bots.pInfo[gameData.objs.objects[gameData.escort.nObjNum].id].companion) {
		for (i=0; i<=gameData.objs.nLastObject; i++)
			if (gameData.bots.pInfo[gameData.objs.objects[i].id].companion)
				break;
		if (i > gameData.objs.nLastObject)
			return 0;
		else
			gameData.escort.nObjNum = i;
	}

	segp = gameData.segs.segments + gameData.objs.objects[gameData.escort.nObjNum].segnum;

	for (i=0; i<MAX_SIDES_PER_SEGMENT; i++) {
		short	wall_num = WallNumP (segp, (short) i);

		if (IS_WALL (wall_num)) {
			if ((gameData.walls.walls[wall_num].type == WALL_BLASTABLE) && 
				!(gameData.walls.walls[wall_num].flags & WALL_BLASTED))
				return 0;
		}

		//	Check one level deeper.
		if (IS_CHILD(segp->children[i])) {
			int		j;
			segment	*csegp = &gameData.segs.segments[segp->children[i]];

			for (j=0; j<MAX_SIDES_PER_SEGMENT; j++) {
				short	wall2 = WallNumP (csegp, (short) j);

				if (IS_WALL (wall2)) {
					if ((gameData.walls.walls[wall2].type == WALL_BLASTABLE) && !(gameData.walls.walls[wall2].flags & WALL_BLASTED))
						return 0;
				}
			}
		}
	}

	gameData.escort.bMayTalk = 1;
	return 1;
}
Пример #13
0
__attribute_warn_unused_result
static vsegptridx_t get_any_attached_segment(const vsegptridx_t curseg_num, const uint_fast32_t skipside)
{
    for (uint_fast32_t s = 0; s != MAX_SIDES_PER_SEGMENT; ++s)
    {
        if (unlikely(s == skipside))
            continue;
        const auto child = curseg_num->children[s];
        if (IS_CHILD(child))
            return curseg_num.absolute_sibling(child);
    }
    return curseg_num;
}
Пример #14
0
// --------------------------------------------------------------------------------------
// Select next segment.
//	If there is a connection on the current side, then choose that segment.
// If there is no connecting segment on the current side, try any segment.
void get_next_segment(int curseg_num, int curside, int *newseg_num, int *newside)
{
	int	s;

	if (IS_CHILD(Segments[curseg_num].children[curside])) {

		*newseg_num = Segments[curseg_num].children[Curside];

		// Find out what side we came in through and favor side opposite that
		*newside = Side_opposite[find_connect_side(&Segments[curseg_num],&Segments[*newseg_num])];

		// If there is nothing attached on the side opposite to what we came in (*newside), pick any other side
		if (!IS_CHILD(Segments[*newseg_num].children[*newside]))
			for (s=0; s<MAX_SIDES_PER_SEGMENT; s++)
				if ((Segments[*newseg_num].children[s] != curseg_num) && IS_CHILD(Segments[*newseg_num].children[s]))
					*newside = s;
	} else {
		*newseg_num = curseg_num;
		*newside = curside;
	}

}
Пример #15
0
int wall_add_external_wall()
{
	if (Cursegp->children[Curside] == -2) {
		editor_status( "Wall is already external!" );
		return 1;
	}

	if (IS_CHILD(Cursegp->children[Curside])) {
		editor_status( "Cannot add external wall here - seg has children" );
		return 0;
	}

	Cursegp->children[Curside] = -2;

	return 1;
}
Пример #16
0
int GenerateCurve()
{
    if ( (Markedsegp != 0) && !IS_CHILD(Markedsegp->children[Markedside])) {
		r1scale = r4scale = F1_0*20;
      autosave_mine( mine_filename );
      diagnostic_message("Curve Generated.");
		Update_flags |= UF_WORLD_CHANGED;
      curve = generate_curve(r1scale, r4scale);
		mine_changed = 1;
        if (curve == 1) {
            strcpy(undo_status[Autosave_count], "Curve Generation UNDONE.\n");
        }
        if (curve == 0) diagnostic_message("Cannot generate curve -- check Current segment.");
    }
    else diagnostic_message("Cannot generate curve -- check Marked segment.");
	warn_if_concave_segments();

	return 1;
}
Пример #17
0
//	-----------------------------------------------------------------------------
//	Create a breadth-first list of segments reachable from current segment.
//	max_segs is maximum number of segments to search.  Use MAX_SEGMENTS to search all.
//	On exit, *length <= max_segs.
//	Input:
//		start_seg
//	Output:
//		bfs_list:	array of shorts, each reachable segment.  Includes start segment.
//		length:		number of elements in bfs_list
void CreateBfsList(int start_seg, short bfs_list[], int *length, int max_segs)
{
	int		head, tail;
	sbyte		bVisited[MAX_SEGMENTS];

#if 1
	memset (bVisited, 0, MAX_SEGMENTS * sizeof (sbyte));
#else
	for (i=0; i<MAX_SEGMENTS; i++)
		bVisited[i] = 0;
#endif
	head = 0;
	tail = 0;

	bfs_list[head++] = start_seg;
	bVisited[start_seg] = 1;

while ((head != tail) && (head < max_segs)) {
	int		i;
	short		curseg;
	segment	*cursegp;

	curseg = bfs_list[tail++];
	cursegp = gameData.segs.segments + curseg;

	for (i=0; i<MAX_SIDES_PER_SEGMENT; i++) {
		int	connected_seg = cursegp->children[i];
		if (!IS_CHILD (connected_seg))
			continue;
		if (bVisited[connected_seg])
			continue;
		if (!SegmentIsReachable(curseg, (short) i))
			continue;
		bfs_list[head++] = connected_seg;
		if (head >= max_segs)
			break;
		bVisited[connected_seg] = 1;
		Assert(head < MAX_SEGMENTS);
		}
	}
*length = head;
}
Пример #18
0
void run_test() {
  int n;
  pid_t pid;

  n = NUM_PROC;
  while(n-- > 0) {
    pid = x_fork();
    
    if(IS_CHILD(pid)) {
      // do something;
      test_routine();

      exit(0);
    }
  }

  n = NUM_PROC;
  while(n-- > 0) {
    pid = x_wait(NULL);
    //printf("Done: %d\n", pid);
  }
}
Пример #19
0
//-----------------------------------------------------------------
// Adds a specific trigger flag to Markedsegp/Markedside if it is possible.
// Automatically adds flag to Connectside if possible unless it is a control trigger.
// Returns 1 if trigger flag added.
// Returns 0 if trigger flag cannot be added.
int trigger_add_to_Markedside(short flag) {
	int trigger_num; //, ctrigger_num;

	if (!Markedsegp) {
		editor_status("No Markedside.");
		return 0;
	}

	// If no child on Markedside return
	if (!IS_CHILD(Markedsegp->children[Markedside])) return 0;

	trigger_num = add_trigger(Markedsegp, Markedside);

	if (trigger_num == -1) {
		editor_status("Cannot add trigger at Markedside.");
		return 0;
	}

 	Triggers[trigger_num].flags |= flag;

	return 1;
}
Пример #20
0
int trigger_dialog_handler(UI_DIALOG *dlg, d_event *event, trigger_dialog *t)
{
	int i;
	short Markedwall, trigger_num;
	int keypress = 0;
	int rval = 0;

	Assert(MainWindow != NULL);
	if (!Markedsegp) {
		close_trigger_window();
		return 0;
	}

	//------------------------------------------------------------
	// Call the ui code..
	//------------------------------------------------------------
	ui_button_any_drawn = 0;
	
	if (event->type == EVENT_KEY_COMMAND)
		keypress = event_key_get(event);
	
	//------------------------------------------------------------
	// If we change walls, we need to reset the ui code for all
	// of the checkboxes that control the wall flags.  
	//------------------------------------------------------------
	Markedwall = Markedsegp->sides[Markedside].wall_num;
	if (Markedwall != -1)
		trigger_num = Walls[Markedwall].trigger;
	else trigger_num = -1;

	if (t->old_trigger_num != trigger_num)
	{
		if (trigger_num != -1)
		{
			trigger *trig = &Triggers[trigger_num];

  			ui_checkbox_check(t->triggerFlag[0], trig->flags & TRIGGER_CONTROL_DOORS);
 			ui_checkbox_check(t->triggerFlag[1], trig->flags & TRIGGER_SHIELD_DAMAGE);
 			ui_checkbox_check(t->triggerFlag[2], trig->flags & TRIGGER_ENERGY_DRAIN);
 			ui_checkbox_check(t->triggerFlag[3], trig->flags & TRIGGER_EXIT);
 			ui_checkbox_check(t->triggerFlag[4], trig->flags & TRIGGER_ONE_SHOT);
 			ui_checkbox_check(t->triggerFlag[5], trig->flags & TRIGGER_ILLUSION_ON);
 			ui_checkbox_check(t->triggerFlag[6], trig->flags & TRIGGER_ILLUSION_OFF);
 			ui_checkbox_check(t->triggerFlag[7], trig->flags & TRIGGER_ON);
 			ui_checkbox_check(t->triggerFlag[8], trig->flags & TRIGGER_MATCEN);
 			ui_checkbox_check(t->triggerFlag[9], trig->flags & TRIGGER_SECRET_EXIT);
		}
	}
	
	//------------------------------------------------------------
	// If any of the checkboxes that control the wallflags are set, then
	// update the cooresponding wall flag.
	//------------------------------------------------------------
	if (IS_CHILD(Markedsegp->children[Markedside]))
	{
		rval = 1;
		
		if (GADGET_PRESSED(t->triggerFlag[0])) 
			trigger_flag_Markedside(TRIGGER_CONTROL_DOORS, t->triggerFlag[0]->flag); 
		else if (GADGET_PRESSED(t->triggerFlag[1]))
			trigger_flag_Markedside(TRIGGER_SHIELD_DAMAGE, t->triggerFlag[1]->flag); 
		else if (GADGET_PRESSED(t->triggerFlag[2]))
			trigger_flag_Markedside(TRIGGER_ENERGY_DRAIN, t->triggerFlag[2]->flag); 
		else if (GADGET_PRESSED(t->triggerFlag[3]))
			trigger_flag_Markedside(TRIGGER_EXIT, t->triggerFlag[3]->flag); 
		else if (GADGET_PRESSED(t->triggerFlag[4]))
			trigger_flag_Markedside(TRIGGER_ONE_SHOT, t->triggerFlag[4]->flag); 
		else if (GADGET_PRESSED(t->triggerFlag[5]))
			trigger_flag_Markedside(TRIGGER_ILLUSION_ON, t->triggerFlag[5]->flag); 
		else if (GADGET_PRESSED(t->triggerFlag[6]))
			trigger_flag_Markedside(TRIGGER_ILLUSION_OFF, t->triggerFlag[6]->flag);
		else if (GADGET_PRESSED(t->triggerFlag[7]))
			trigger_flag_Markedside(TRIGGER_ON, t->triggerFlag[7]->flag);
		else if (GADGET_PRESSED(t->triggerFlag[8])) 
			trigger_flag_Markedside(TRIGGER_MATCEN, t->triggerFlag[8]->flag);
		else if (GADGET_PRESSED(t->triggerFlag[9])) 
			trigger_flag_Markedside(TRIGGER_SECRET_EXIT, t->triggerFlag[9]->flag);
		else
			rval = 0;

	} else
		for (i = 0; i < NUM_TRIGGER_FLAGS; i++ )
			ui_checkbox_check(t->triggerFlag[i], 0);

	//------------------------------------------------------------
	// Draw the wall in the little 64x64 box
	//------------------------------------------------------------
	if (event->type == EVENT_UI_DIALOG_DRAW)
	{
		gr_set_current_canvas( t->wallViewBox->canvas );

		if ((Markedsegp->sides[Markedside].wall_num == -1) || (Walls[Markedsegp->sides[Markedside].wall_num].trigger) == -1)
			gr_clear_canvas( CBLACK );
		else {
			if (Markedsegp->sides[Markedside].tmap_num2 > 0)  {
				gr_ubitmap(0,0, texmerge_get_cached_bitmap( Markedsegp->sides[Markedside].tmap_num, Markedsegp->sides[Markedside].tmap_num2));
			} else {
				if (Markedsegp->sides[Markedside].tmap_num > 0)	{
					PIGGY_PAGE_IN(Textures[Markedsegp->sides[Markedside].tmap_num]);
					gr_ubitmap(0,0, &GameBitmaps[Textures[Markedsegp->sides[Markedside].tmap_num].index]);
				} else
					gr_clear_canvas( CGREY );
			}
		}
	}

	//------------------------------------------------------------
	// If anything changes in the ui system, redraw all the text that
	// identifies this robot.
	//------------------------------------------------------------
	if (event->type == EVENT_UI_DIALOG_DRAW)
	{
		if ( Markedsegp->sides[Markedside].wall_num > -1 )	{
			ui_dprintf_at( MainWindow, 12, 6, "Trigger: %d    ", trigger_num);
		}	else {
			ui_dprintf_at( MainWindow, 12, 6, "Trigger: none ");
		}
	}
	
	if (ui_button_any_drawn || (t->old_trigger_num != trigger_num) )
		Update_flags |= UF_WORLD_CHANGED;
		
	if (event->type == EVENT_WINDOW_CLOSE)
	{
		d_free(t);
		MainWindow = NULL;
		return 0;
	}

	if ( GADGET_PRESSED(t->quitButton) || (keypress==KEY_ESC))
	{
		close_trigger_window();
		return 1;
	}		

	t->old_trigger_num = trigger_num;
	
	return rval;
}
Пример #21
0
void do_trigger_window()
{
	int i;
	short Markedwall, trigger_num;

	if ( MainWindow == NULL ) return;
	if (!Markedsegp) {
		close_trigger_window();
		return;
	}

	//------------------------------------------------------------
	// Call the ui code..
	//------------------------------------------------------------
	ui_button_any_drawn = 0;
	ui_window_do_gadgets(MainWindow);
	
	//------------------------------------------------------------
	// If we change walls, we need to reset the ui code for all
	// of the checkboxes that control the wall flags.  
	//------------------------------------------------------------
	Markedwall = Markedsegp->sides[Markedside].wall_num;
	if (Markedwall != -1)
		trigger_num = Walls[Markedwall].trigger;
	else trigger_num = -1;

	if (old_trigger_num != trigger_num ) {
		for (	i=0; i < NUM_TRIGGER_FLAGS; i++ )	{
			TriggerFlag[i]->flag = 0;				// Tells ui that this button isn't checked
			TriggerFlag[i]->status = 1;				// Tells ui to redraw button
		}

		if (trigger_num != -1) {
  			if (Triggers[trigger_num].flags & TRIGGER_CONTROL_DOORS)
				TriggerFlag[0]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_SHIELD_DAMAGE)
				TriggerFlag[1]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_ENERGY_DRAIN)
				TriggerFlag[2]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_EXIT)
				TriggerFlag[3]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_ONE_SHOT)
				TriggerFlag[4]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_ILLUSION_ON)
				TriggerFlag[5]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_ILLUSION_OFF)
				TriggerFlag[6]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_ON)
				TriggerFlag[7]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_MATCEN)
				TriggerFlag[8]->flag = 1;
 			if (Triggers[trigger_num].flags & TRIGGER_SECRET_EXIT)
				TriggerFlag[9]->flag = 1;
		}
	}
	
	//------------------------------------------------------------
	// If any of the checkboxes that control the wallflags are set, then
	// update the cooresponding wall flag.
	//------------------------------------------------------------
	if (IS_CHILD(Markedsegp->children[Markedside])) {
		if (TriggerFlag[0]->flag == 1) 
			trigger_add_to_Markedside(TRIGGER_CONTROL_DOORS); 
		else
			trigger_remove_flag_from_Markedside(TRIGGER_CONTROL_DOORS);
		if (TriggerFlag[1]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_SHIELD_DAMAGE); 
		else
			trigger_remove_flag_from_Markedside(TRIGGER_SHIELD_DAMAGE);
		if (TriggerFlag[2]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_ENERGY_DRAIN); 
		else
			trigger_remove_flag_from_Markedside(TRIGGER_ENERGY_DRAIN);
		if (TriggerFlag[3]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_EXIT); 
		else
			trigger_remove_flag_from_Markedside(TRIGGER_EXIT);
		if (TriggerFlag[4]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_ONE_SHOT); 
		else
			trigger_remove_flag_from_Markedside(TRIGGER_ONE_SHOT);
		if (TriggerFlag[5]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_ILLUSION_ON); 
		else
			trigger_remove_flag_from_Markedside(TRIGGER_ILLUSION_ON);
		if (TriggerFlag[6]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_ILLUSION_OFF);
		else
			trigger_remove_flag_from_Markedside(TRIGGER_ILLUSION_OFF);
		if (TriggerFlag[7]->flag == 1)
			trigger_add_to_Markedside(TRIGGER_ON);
		else
			trigger_remove_flag_from_Markedside(TRIGGER_ON);

		if (TriggerFlag[8]->flag == 1) 
			trigger_add_to_Markedside(TRIGGER_MATCEN);
		else
			trigger_remove_flag_from_Markedside(TRIGGER_MATCEN);

		if (TriggerFlag[9]->flag == 1) 
			trigger_add_to_Markedside(TRIGGER_SECRET_EXIT);
		else
			trigger_remove_flag_from_Markedside(TRIGGER_SECRET_EXIT);

	} else
		for (	i=0; i < NUM_TRIGGER_FLAGS; i++ )
			if (TriggerFlag[i]->flag == 1) { 
				TriggerFlag[i]->flag = 0;					// Tells ui that this button isn't checked
				TriggerFlag[i]->status = 1;				// Tells ui to redraw button
			}
	
	//------------------------------------------------------------
	// Draw the wall in the little 64x64 box
	//------------------------------------------------------------
  	gr_set_current_canvas( WallViewBox->canvas );

	if ((Markedsegp->sides[Markedside].wall_num == -1) || (Walls[Markedsegp->sides[Markedside].wall_num].trigger) == -1)
		gr_clear_canvas( CBLACK );
	else {
		if (Markedsegp->sides[Markedside].tmap_num2 > 0)  {
			gr_ubitmap(0,0, texmerge_get_cached_bitmap( Markedsegp->sides[Markedside].tmap_num, Markedsegp->sides[Markedside].tmap_num2));
		} else {
			if (Markedsegp->sides[Markedside].tmap_num > 0)	{
				PIGGY_PAGE_IN(Textures[Markedsegp->sides[Markedside].tmap_num]);
				gr_ubitmap(0,0, &GameBitmaps[Textures[Markedsegp->sides[Markedside].tmap_num].index]);
			} else
				gr_clear_canvas( CGREY );
		}
 	}

	//------------------------------------------------------------
	// If anything changes in the ui system, redraw all the text that
	// identifies this robot.
	//------------------------------------------------------------
	if (ui_button_any_drawn || (old_trigger_num != trigger_num) ) {
		if ( Markedsegp->sides[Markedside].wall_num > -1 )	{
			ui_wprintf_at( MainWindow, 12, 6, "Trigger: %d    ", trigger_num);
		}	else {
			ui_wprintf_at( MainWindow, 12, 6, "Trigger: none ");
		}
		Update_flags |= UF_WORLD_CHANGED;
	}

	if ( QuitButton->pressed || (last_keypress==KEY_ESC))	{
		close_trigger_window();
		return;
	}		

	old_trigger_num = trigger_num;
}
Пример #22
0
int main(void) {
  int in[2];
  int out[2];
  pid_t pid;

  printf("type 'quit' for exit\n\n");

  x_pipe(in);
  x_pipe(out);
  
  pid = x_fork();
  
  if(IS_CHILD(pid)) {
    x_dup2(in[READ], STDIN_FD);
    x_dup2(out[WRITE], STDOUT_FD);
    
    x_close(in[READ]);
    x_close(in[WRITE]);
    x_close(out[READ]);
    x_close(out[WRITE]);
    
    execl("/usr/bin/bc", "runbc", NULL);

    perror("execl");
    exit(1);
  } else if(IS_PARENT(pid)) {
    char buf[BUFSIZE + 1];
    fd_set rfds;
    int count;
    int flag = 1;

    x_close(in[READ]);
    x_close(out[WRITE]);
    
    while(13) {
      FD_ZERO(&rfds);
      FD_SET(STDIN_FD, &rfds);
      FD_SET(out[READ], &rfds);
      
      count = 0;

      x_select(out[READ] + 1, &rfds, NULL, NULL, NULL);

      if(FD_ISSET(out[READ], &rfds)) {
        // read messages from BC
        count = x_read(out[READ], buf, BUFSIZE);
        if(count) {
          x_write(STDOUT_FD, buf, count);
        } else {
          break;
        }
      }

      if(FD_ISSET(STDIN_FD, &rfds) && flag) {
        // send commands to BC
        count = x_read(STDIN_FD, buf, BUFSIZE);
        if(count) {
          x_write(in[WRITE], buf, count);
        } else {
          x_write(in[WRITE], "quit\n", 6);
          flag = 0;
        }
      }
    }

    x_waitpid(pid, NULL, 0);

    x_close(in[WRITE]);
    x_close(out[READ]);
  }

  return 0;
}
Пример #23
0
//---------------------------------------------------------------------
//	Remove a specific side.
int wall_remove_side(segment *seg, short side)
{
	int Connectside;
	segment *csegp;
	int lower_wallnum;
	int w, s, t, l, t1;

	if (IS_CHILD(seg->children[side]) && IS_CHILD(seg->sides[side].wall_num)) {
		csegp = &Segments[seg->children[side]];
		Connectside = find_connect_side(seg, csegp);

		remove_trigger(seg, side);
		remove_trigger(csegp, Connectside);

		// Remove walls 'wall_num' and connecting side 'wall_num'
		//  from Walls array.  
	 	lower_wallnum = seg->sides[side].wall_num;
		if (csegp->sides[Connectside].wall_num < lower_wallnum)
			 lower_wallnum = csegp->sides[Connectside].wall_num;

		if (Walls[lower_wallnum].linked_wall != -1)
			Walls[Walls[lower_wallnum].linked_wall].linked_wall = -1;
		if (Walls[lower_wallnum+1].linked_wall != -1)
			Walls[Walls[lower_wallnum+1].linked_wall].linked_wall = -1;

		for (w=lower_wallnum;w<Num_walls-2;w++)
			Walls[w] = Walls[w+2];

		Num_walls -= 2;

		for (s=0;s<=Highest_segment_index;s++)
			if (Segments[s].segnum != -1)
			for (w=0;w<MAX_SIDES_PER_SEGMENT;w++)
				if	(Segments[s].sides[w].wall_num > lower_wallnum+1)
					Segments[s].sides[w].wall_num -= 2;

		// Destroy any links to the deleted wall.
		for (t=0;t<Num_triggers;t++)
			for (l=0;l<Triggers[t].num_links;l++)
				if ((Triggers[t].seg[l] == seg-Segments) && (Triggers[t].side[l] == side)) {
					for (t1=0;t1<Triggers[t].num_links-1;t1++) {
						Triggers[t].seg[t1] = Triggers[t].seg[t1+1];
						Triggers[t].side[t1] = Triggers[t].side[t1+1];
					}
					Triggers[t].num_links--;	
				}

		// Destroy control center links as well.
		for (l=0;l<ControlCenterTriggers.num_links;l++)
			if ((ControlCenterTriggers.seg[l] == seg-Segments) && (ControlCenterTriggers.side[l] == side)) {
				for (t1=0;t1<ControlCenterTriggers.num_links-1;t1++) {
					ControlCenterTriggers.seg[t1] = ControlCenterTriggers.seg[t1+1];
					ControlCenterTriggers.side[t1] = ControlCenterTriggers.side[t1+1];
				}
				ControlCenterTriggers.num_links--;	
			}

		seg->sides[side].wall_num = -1;
		csegp->sides[Connectside].wall_num = -1;

		Update_flags |= UF_WORLD_CHANGED;
		return 1;
	}

	editor_status( "Can't remove wall.  No wall present.");
	return 0;
}
Пример #24
0
//	-----------------------------------------------------------------------------
//do whatever this thing does in a frame
void DoReactorFrame (object *objP)
{
    int	nBestGun;

    //	If a boss level, then gameData.reactor.bPresent will be 0.
    if (!gameData.reactor.bPresent)
        return;

#ifndef NDEBUG
    if (!gameStates.app.cheats.bRobotsFiring || (gameStates.app.bGameSuspended & SUSP_ROBOTS))
        return;
#else
    if (!gameStates.app.cheats.bRobotsFiring)
        return;
#endif

    if (!(gameData.reactor.bHit || gameData.reactor.bSeenPlayer)) {
        if (!(gameData.app.nFrameCount % 8)) {		//	Do every so often...
            vms_vector	vec_to_player;
            fix			dist_to_player;
            int			i;
            segment		*segp = &gameData.segs.segments[objP->segnum];

            // This is a hack.  Since the control center is not processed by
            // ai_do_frame, it doesn't know to deal with cloaked dudes.  It
            // seems to work in single-player mode because it is actually using
            // the value of Believed_player_position that was set by the last
            // person to go through ai_do_frame.  But since a no-robots game
            // never goes through ai_do_frame, I'm making it so the control
            // center can spot cloaked dudes.

            if (gameData.app.nGameMode & GM_MULTI)
                gameData.ai.vBelievedPlayerPos = gameData.objs.objects[gameData.multi.players[gameData.multi.nLocalPlayer].objnum].pos;

            //	Hack for special control centers which are isolated and not reachable because the
            //	real control center is inside the boss.
            for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
                if (IS_CHILD (segp->children[i]))
                    break;
            if (i == MAX_SIDES_PER_SEGMENT)
                return;

            VmVecSub (&vec_to_player, &gameData.objs.console->pos, &objP->pos);
            dist_to_player = VmVecNormalizeQuick (&vec_to_player);
            if (dist_to_player < F1_0*200) {
                gameData.reactor.bSeenPlayer = ObjectCanSeePlayer (objP, &objP->pos, 0, &vec_to_player);
                gameData.reactor.nNextFireTime = 0;
            }
        }
        return;
    }

//	Periodically, make the reactor fall asleep if player not visible.
    if (gameData.reactor.bHit || gameData.reactor.bSeenPlayer) {
        if ((Last_time_cc_vis_check + F1_0*5 < gameData.time.xGame) || (Last_time_cc_vis_check > gameData.time.xGame)) {
            vms_vector	vec_to_player;
            fix			dist_to_player;

            VmVecSub (&vec_to_player, &gameData.objs.console->pos, &objP->pos);
            dist_to_player = VmVecNormalizeQuick (&vec_to_player);
            Last_time_cc_vis_check = gameData.time.xGame;
            if (dist_to_player < F1_0*120) {
                gameData.reactor.bSeenPlayer = ObjectCanSeePlayer (objP, &objP->pos, 0, &vec_to_player);
                if (!gameData.reactor.bSeenPlayer)
                    gameData.reactor.bHit = 0;
            }
        }
    }

    if ((gameData.reactor.nNextFireTime < 0) && !(gameStates.app.bPlayerIsDead && (gameData.time.xGame > gameStates.app.nPlayerTimeOfDeath+F1_0*2))) {
        if (gameData.multi.players[gameData.multi.nLocalPlayer].flags & PLAYER_FLAGS_CLOAKED)
            nBestGun = CalcBestReactorGun (N_controlcen_guns, Gun_pos, Gun_dir, &gameData.ai.vBelievedPlayerPos);
        else
            nBestGun = CalcBestReactorGun (N_controlcen_guns, Gun_pos, Gun_dir, &gameData.objs.console->pos);

        if (nBestGun != -1) {
            int			rand_prob, count;
            vms_vector	vec_to_goal;
            fix			dist_to_player;
            fix			delta_fire_time;

            if (gameData.multi.players[gameData.multi.nLocalPlayer].flags & PLAYER_FLAGS_CLOAKED) {
                VmVecSub (&vec_to_goal, &gameData.ai.vBelievedPlayerPos, &Gun_pos[nBestGun]);
                dist_to_player = VmVecNormalizeQuick (&vec_to_goal);
            }
            else {
                VmVecSub (&vec_to_goal, &gameData.objs.console->pos, &Gun_pos[nBestGun]);
                dist_to_player = VmVecNormalizeQuick (&vec_to_goal);
            }
            if (dist_to_player > F1_0*300) {
                gameData.reactor.bHit = 0;
                gameData.reactor.bSeenPlayer = 0;
                return;
            }
#ifdef NETWORK
            if (gameData.app.nGameMode & GM_MULTI)
                MultiSendCtrlcenFire (&vec_to_goal, nBestGun, OBJ_IDX (objP));
#endif
            CreateNewLaserEasy (&vec_to_goal, &Gun_pos[nBestGun], OBJ_IDX (objP), CONTROLCEN_WEAPON_NUM, 1);
            //	some of time, based on level, fire another thing, not directly at player, so it might hit him if he's constantly moving.
            rand_prob = F1_0/ (abs (gameData.missions.nCurrentLevel)/4+2);
            count = 0;
            while ((d_rand () > rand_prob) && (count < 4)) {
                vms_vector	randvec;

                MakeRandomVector (&randvec);
                VmVecScaleInc (&vec_to_goal, &randvec, F1_0/6);
                VmVecNormalizeQuick (&vec_to_goal);
#ifdef NETWORK
                if (gameData.app.nGameMode & GM_MULTI)
                    MultiSendCtrlcenFire (&vec_to_goal, nBestGun, OBJ_IDX (objP));
#endif
                CreateNewLaserEasy (&vec_to_goal, &Gun_pos[nBestGun], OBJ_IDX (objP), CONTROLCEN_WEAPON_NUM, 0);
                count++;
            }

            delta_fire_time = (NDL - gameStates.app.nDifficultyLevel) * F1_0/4;
            if (gameStates.app.nDifficultyLevel == 0)
                delta_fire_time += F1_0/2;
            if (gameData.app.nGameMode & GM_MULTI) // slow down rate of fire in multi player
                delta_fire_time *= 2;
            gameData.reactor.nNextFireTime = delta_fire_time;
        }
    }
    else
        gameData.reactor.nNextFireTime -= gameData.time.xFrame;
}
Пример #25
0
//	-----------------------------------------------------------------------------------------------------------
//	Create a path from objP->info.position.vPos to the center of nEndSeg.
//	Return a list of (segment_num, point_locations) at pointSegP
//	Return number of points in *numPoints.
//	if nMaxDepth == -1, then there is no maximum depth.
//	If unable to create path, return -1, else return 0.
//	If randomFlag !0, then introduce randomness into path by looking at sides in random order.  This means
//	that a path between two segments won't always be the same, unless it is unique.p.
//	If bSafeMode is set, then additional points are added to "make sure" that points are reachable.p.  I would
//	like to say that it ensures that the CObject can move between the points, but that would require knowing what
//	the CObject is (which isn't passed, right?) and making fvi calls (slow, right?).  So, consider it the more_or_less_safeFlag.
//	If nEndSeg == -2, then end seg will never be found and this routine will drop out due to depth (xProbably called by CreateNSegmentPath).
int CreatePathPoints (CObject *objP, int nStartSeg, int nEndSeg, tPointSeg *pointSegP, short *numPoints,
							 int nMaxDepth, int bRandom, int bSafeMode, int nAvoidSeg)
{
	short				nCurSeg;
	short				nSide, hSide;
	int				qTail = 0, qHead = 0;
	int				h, i, j;
	sbyte				bVisited [MAX_SEGMENTS_D2X];
	segQueueEntry	segmentQ [MAX_SEGMENTS_D2X];
	short				depth [MAX_SEGMENTS_D2X];
	int				nCurDepth;
	sbyte				randomXlate [MAX_SIDES_PER_SEGMENT];
	tPointSeg		*origPointSegs = pointSegP;
	int				lNumPoints;
	CSegment			*segP;
	CFixVector		vCenter;
	int				nParentSeg, nDestSeg;
	tFVIQuery		fq;
	tFVIData			hitData;
	int				hitType;
	int				bAvoidPlayer;

#if PATH_VALIDATION
ValidateAllPaths ();
#endif

if ((objP->info.nType == OBJ_ROBOT) && (objP->cType.aiInfo.behavior == AIB_RUN_FROM) && (nAvoidSeg != -32767)) {
	bRandom = 1;
	nAvoidSeg = gameData.objs.consoleP->info.nSegment;
	}
bAvoidPlayer = gameData.objs.consoleP->info.nSegment == nAvoidSeg;
if (nMaxDepth == -1)
	nMaxDepth = MAX_PATH_LENGTH;
lNumPoints = 0;
memset (bVisited, 0, sizeof (bVisited [0]) * gameData.segs.nSegments);
memset (depth, 0, sizeof (depth [0]) * gameData.segs.nSegments);
//	If there is a CSegment we're not allowed to visit, mark it.
if (nAvoidSeg != -1) {
	Assert (nAvoidSeg <= gameData.segs.nLastSegment);
	if ((nStartSeg != nAvoidSeg) && (nEndSeg != nAvoidSeg)) {
		bVisited [nAvoidSeg] = 1;
		depth [nAvoidSeg] = 0;
		}
	}

nCurSeg = nStartSeg;
bVisited [nCurSeg] = 1;
nCurDepth = 0;

#if DBG
if (objP->Index () == nDbgObj)
	nDbgObj = nDbgObj;
#endif
if (bRandom)
	CreateRandomXlate (randomXlate);
nCurSeg = nStartSeg;
bVisited [nCurSeg] = 1;
while (nCurSeg != nEndSeg) {
	segP = SEGMENTS + nCurSeg;
	if (bRandom && (d_rand () < 8192))	//create a different xlate at random time intervals
		CreateRandomXlate (randomXlate);

	for (nSide = 0; nSide < MAX_SIDES_PER_SEGMENT; nSide++) {
		hSide = bRandom ? randomXlate [nSide] : nSide;
		if (!IS_CHILD (segP->m_children [hSide]))
			continue;
		if (!((segP->IsDoorWay (hSide, NULL) & WID_FLY_FLAG) ||
			  (AIDoorIsOpenable (objP, segP, hSide))))
			continue;
		nDestSeg = segP->m_children [hSide];
		if (bVisited [nDestSeg])
			continue;
		if (bAvoidPlayer && ((nCurSeg == nAvoidSeg) || (nDestSeg == nAvoidSeg))) {
			vCenter = segP->SideCenter (hSide);
			fq.p0					= &objP->info.position.vPos;
			fq.startSeg			= objP->info.nSegment;
			fq.p1					= &vCenter;
			fq.radP0				=
			fq.radP1				= objP->info.xSize;
			fq.thisObjNum		= objP->Index ();
			fq.ignoreObjList	= NULL;
			fq.flags				= 0;
			fq.bCheckVisibility = false;
			hitType = FindVectorIntersection (&fq, &hitData);
			if (hitType != HIT_NONE)
				continue;
			}
		if (nDestSeg < 0)
			continue;
		if (nCurSeg < 0)
			continue;
		segmentQ [qTail].start = nCurSeg;
		segmentQ [qTail].end = nDestSeg;
		segmentQ [qTail].nConnSide = (ubyte) hSide;
		bVisited [nDestSeg] = 1;
		depth [qTail++] = nCurDepth + 1;
		if (depth [qTail-1] == nMaxDepth) {
			nEndSeg = segmentQ [qTail-1].end;
			goto pathTooLong;
			}	// end if (depth [...
		}	//	for (nSide.p...

	if (qHead >= qTail) {
		//	Couldn't get to goal, return a path as far as we got, which is probably acceptable to the unparticular caller.
		nEndSeg = segmentQ [qTail-1].end;
		break;
		}
	nCurSeg = segmentQ [qHead].end;
	nCurDepth = depth [qHead];
	qHead++;

pathTooLong: ;
	}	//	while (nCurSeg ...
//	Set qTail to the CSegment which ends at the goal.
while (segmentQ [--qTail].end != nEndSeg)
	if (qTail < 0) {
		*numPoints = lNumPoints;
		return -1;
		}
for (i = qTail; i >= 0; ) {
	nParentSeg = segmentQ [i].start;
	lNumPoints++;
	if (nParentSeg == nStartSeg)
		break;
	while (segmentQ [--i].end != nParentSeg)
		Assert (i >= 0);
	}

if (bSafeMode && ((pointSegP - gameData.ai.routeSegs) + 2 * lNumPoints + 1 >= LEVEL_POINT_SEGS)) {
	//	Ouch! Cannot insert center points in path.  So return unsafe path.
#if TRACE
	console.printf (CON_DBG, "Resetting all paths because of bSafeMode.p.\n");
#endif
	AIResetAllPaths ();
	*numPoints = lNumPoints;
	return -1;
	}
pointSegP->nSegment = nStartSeg;
pointSegP->point = SEGMENTS [nStartSeg].Center ();
if (bSafeMode)
	lNumPoints *= 2;
j = lNumPoints++;
h = bSafeMode + 1;
for (i = qTail; i >= 0; j -= h) {
	nDestSeg = segmentQ [i].end;
	nParentSeg = segmentQ [i].start;
	pointSegP [j].nSegment = nDestSeg;
	pointSegP [j].point = SEGMENTS [nDestSeg].Center ();
	pointSegP [j].nConnSide = segmentQ [i].nConnSide;
	if (nParentSeg == nStartSeg)
		break;
	while (segmentQ [--i].end != nParentSeg)
		Assert (qTail >= 0);
	}
if (bSafeMode) {
	for (i = 0; i < lNumPoints - 1; i = j) {
		j = i + 2;
		InsertTransitPoint (pointSegP + i + 1, pointSegP + i, pointSegP + j, pointSegP [j].nConnSide);
		}
	lNumPoints = OptimizePath (pointSegP, lNumPoints);
	}
pointSegP += lNumPoints;

#if PATH_VALIDATION
ValidatePath (2, origPointSegs, lNumPoints);
#endif

#if PATH_VALIDATION
ValidatePath (3, origPointSegs, lNumPoints);
#endif

// -- MK, 10/30/95 -- This code causes apparent discontinuities in the path, moving a point
//	into a new CSegment.  It is not necessarily bad, but it makes it hard to track down actual
//	discontinuity xProblems.
if ((objP->info.nType == OBJ_ROBOT) && ROBOTINFO (objP->info.nId).companion)
	MoveTowardsOutside (origPointSegs, &lNumPoints, objP, 0);

#if PATH_VALIDATION
ValidatePath (4, origPointSegs, lNumPoints);
#endif

*numPoints = lNumPoints;
return 0;
}
Пример #26
0
//	-----------------------------------------------------------------------------
//do whatever this thing does in a frame
void do_controlcen_frame(object *obj)
{
	int			best_gun_num;

	//	If a boss level, then Control_center_present will be 0.
	if (!Control_center_present)
		return;

#ifndef NDEBUG
	if (!Robot_firing_enabled || (Game_suspended & SUSP_ROBOTS))
		return;
#else
	if (!Robot_firing_enabled)
		return;
#endif

	if (!(Control_center_been_hit || Control_center_player_been_seen)) {
		if (!(FrameCount % 8)) {		//	Do every so often...
			vms_vector	vec_to_player;
			fix			dist_to_player;
			int			i;
			segment		*segp = &Segments[obj->segnum];

			// This is a hack.  Since the control center is not processed by
			// ai_do_frame, it doesn't know to deal with cloaked dudes.  It
			// seems to work in single-player mode because it is actually using
			// the value of Believed_player_position that was set by the last
			// person to go through ai_do_frame.  But since a no-robots game
			// never goes through ai_do_frame, I'm making it so the control
			// center can spot cloaked dudes.  

			if (Game_mode & GM_MULTI)
				Believed_player_pos = Objects[Players[Player_num].objnum].pos;

			//	Hack for special control centers which are isolated and not reachable because the
			//	real control center is inside the boss.
			for (i=0; i<MAX_SIDES_PER_SEGMENT; i++)
				if (IS_CHILD(segp->children[i]))
					break;
			if (i == MAX_SIDES_PER_SEGMENT)
				return;

			vm_vec_sub(&vec_to_player, &ConsoleObject->pos, &obj->pos);
			dist_to_player = vm_vec_normalize_quick(&vec_to_player);
			if (dist_to_player < F1_0*200) {
				Control_center_player_been_seen = player_is_visible_from_object(obj, &obj->pos, 0, &vec_to_player);
				Control_center_next_fire_time = 0;
			}
		}			

		return;
	}

	//	Periodically, make the reactor fall asleep if player not visible.
	if (Control_center_been_hit || Control_center_player_been_seen) {
		if ((Last_time_cc_vis_check + F1_0*5 < GameTime) || (Last_time_cc_vis_check > GameTime)) {
			vms_vector	vec_to_player;
			fix			dist_to_player;

			vm_vec_sub(&vec_to_player, &ConsoleObject->pos, &obj->pos);
			dist_to_player = vm_vec_normalize_quick(&vec_to_player);
			Last_time_cc_vis_check = GameTime;
			if (dist_to_player < F1_0*120) {
				Control_center_player_been_seen = player_is_visible_from_object(obj, &obj->pos, 0, &vec_to_player);
				if (!Control_center_player_been_seen)
					Control_center_been_hit = 0;
			}
		}

	}

	if ((Control_center_next_fire_time < 0) && !(Player_is_dead && (GameTime > Player_time_of_death+F1_0*2))) {
		if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED)
			best_gun_num = calc_best_gun(N_controlcen_guns, Gun_pos, Gun_dir, &Believed_player_pos);
		else
			best_gun_num = calc_best_gun(N_controlcen_guns, Gun_pos, Gun_dir, &ConsoleObject->pos);

		if (best_gun_num != -1) {
			int			rand_prob, count;
			vms_vector	vec_to_goal;
			fix			dist_to_player;
			fix			delta_fire_time;

			if (Players[Player_num].flags & PLAYER_FLAGS_CLOAKED) {
				vm_vec_sub(&vec_to_goal, &Believed_player_pos, &Gun_pos[best_gun_num]);
				dist_to_player = vm_vec_normalize_quick(&vec_to_goal);
			} else {
				vm_vec_sub(&vec_to_goal, &ConsoleObject->pos, &Gun_pos[best_gun_num]);
				dist_to_player = vm_vec_normalize_quick(&vec_to_goal);
			}

			if (dist_to_player > F1_0*300)
			{
				Control_center_been_hit = 0;
				Control_center_player_been_seen = 0;
				return;
			}
	
			#ifdef NETWORK
			if (Game_mode & GM_MULTI)
				multi_send_controlcen_fire(&vec_to_goal, best_gun_num, obj-Objects);	
			#endif
			Laser_create_new_easy( &vec_to_goal, &Gun_pos[best_gun_num], obj-Objects, CONTROLCEN_WEAPON_NUM, 1);

			//	some of time, based on level, fire another thing, not directly at player, so it might hit him if he's constantly moving.
			rand_prob = F1_0/(abs(Current_level_num)/4+2);
			count = 0;
			while ((rand() > rand_prob) && (count < 4)) {
				vms_vector	randvec;

				make_random_vector(&randvec);
				vm_vec_scale_add2(&vec_to_goal, &randvec, F1_0/6);
				vm_vec_normalize_quick(&vec_to_goal);
				#ifdef NETWORK
				if (Game_mode & GM_MULTI)
					multi_send_controlcen_fire(&vec_to_goal, best_gun_num, obj-Objects);
				#endif
				Laser_create_new_easy( &vec_to_goal, &Gun_pos[best_gun_num], obj-Objects, CONTROLCEN_WEAPON_NUM, 0);
				count++;
			}

			delta_fire_time = (NDL - Difficulty_level) * F1_0/4;
			if (Difficulty_level == 0)
				delta_fire_time += F1_0/2;

			if (Game_mode & GM_MULTI) // slow down rate of fire in multi player
				delta_fire_time *= 2;

			Control_center_next_fire_time = delta_fire_time;

		}
	} else
		Control_center_next_fire_time -= FrameTime;

}
Пример #27
0
//	-----------------------------------------------------------------------------
//do whatever this thing does in a frame
void DoReactorFrame (CObject *objP)
{
	int				nBestGun, i;
	tReactorStates	*rStatP;

	//	If a boss level, then gameData.reactor.bPresent will be 0.
if (!gameData.reactor.bPresent)
	return;
i = FindReactor (objP);
if (i < 0)
	return;
rStatP = gameData.reactor.states + i;
#if DBG
if (!gameStates.app.cheats.bRobotsFiring || (gameStates.app.bGameSuspended & SUSP_ROBOTS))
	return;
#else
if (!gameStates.app.cheats.bRobotsFiring)
	return;
#endif

if (!(rStatP->bHit || rStatP->bSeenPlayer)) {
	if (gameStates.app.tick40fps.bTick) {		//	Do ever so often...
		CFixVector	vecToPlayer;
		fix			xDistToPlayer;
		int			i;
		CSegment		*segP = SEGMENTS + objP->info.nSegment;

		// This is a hack.  Since the control center is not processed by
		// ai_do_frame, it doesn't know how to deal with cloaked dudes.  It
		// seems to work in single-CPlayerData mode because it is actually using
		// the value of Believed_player_position that was set by the last
		// person to go through ai_do_frame.  But since a no-robots game
		// never goes through ai_do_frame, I'm making it so the control
		// center can spot cloaked dudes.

		if (IsMultiGame)
			gameData.ai.target.vBelievedPos = OBJPOS (OBJECTS + LOCALPLAYER.nObject)->vPos;

		//	Hack for special control centers which are isolated and not reachable because the
		//	real control center is inside the boss.
		for (i = 0; i < MAX_SIDES_PER_SEGMENT; i++)
			if (IS_CHILD (segP->m_children [i]))
				break;
		if (i == MAX_SIDES_PER_SEGMENT)
			return;

		vecToPlayer = OBJPOS (gameData.objs.consoleP)->vPos - objP->info.position.vPos;
		xDistToPlayer = CFixVector::Normalize (vecToPlayer);
		if (xDistToPlayer < I2X (200)) {
			rStatP->bSeenPlayer = AICanSeeTarget (objP, &objP->info.position.vPos, 0, &vecToPlayer);
			rStatP->nNextFireTime = 0;
			}
		}		
	return;
	}

//	Periodically, make the reactor fall asleep if CPlayerData not visible.
if (rStatP->bHit || rStatP->bSeenPlayer) {
	if ((rStatP->xLastVisCheckTime + I2X (5) < gameData.time.xGame) || 
		 (rStatP->xLastVisCheckTime > gameData.time.xGame)) {
		CFixVector	vecToPlayer;
		fix			xDistToPlayer;

		vecToPlayer = gameData.objs.consoleP->info.position.vPos - objP->info.position.vPos;
		xDistToPlayer = CFixVector::Normalize (vecToPlayer);
		rStatP->xLastVisCheckTime = gameData.time.xGame;
		if (xDistToPlayer < I2X (120)) {
			rStatP->bSeenPlayer = AICanSeeTarget (objP, &objP->info.position.vPos, 0, &vecToPlayer);
			if (!rStatP->bSeenPlayer)
				rStatP->bHit = 0;
			}
		}
	}

if ((rStatP->nNextFireTime < 0) && 
	 !(gameStates.app.bPlayerIsDead && (gameData.time.xGame > gameStates.app.nPlayerTimeOfDeath + I2X (2)))) {
	nBestGun = CalcBestReactorGun (gameData.reactor.props [objP->info.nId].nGuns, rStatP->vGunPos, rStatP->vGunDir, 
											 (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED) ? &gameData.ai.target.vBelievedPos : &gameData.objs.consoleP->info.position.vPos);
	if (nBestGun != -1) {
		int			nRandProb, count;
		CFixVector	vecToGoal;
		fix			xDistToPlayer;
		fix			xDeltaFireTime;

		if (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED) {
			vecToGoal = gameData.ai.target.vBelievedPos - rStatP->vGunPos[nBestGun];
			xDistToPlayer = CFixVector::Normalize (vecToGoal);
			} 
		else {
			vecToGoal = gameData.objs.consoleP->info.position.vPos - rStatP->vGunPos [nBestGun];
			xDistToPlayer = CFixVector::Normalize (vecToGoal);
			}
		if (xDistToPlayer > I2X (300)) {
			rStatP->bHit = 0;
			rStatP->bSeenPlayer = 0;
			return;
			}
		if (gameData.app.nGameMode & GM_MULTI)
			MultiSendCtrlcenFire (&vecToGoal, nBestGun, objP->Index ());
		CreateNewLaserEasy (&vecToGoal, &rStatP->vGunPos [nBestGun], objP->Index (), CONTROLCEN_WEAPON_NUM, 1);
		//	some of time, based on level, fire another thing, not directly at CPlayerData, so it might hit him if he's constantly moving.
		nRandProb = I2X (1) / (abs (gameData.missions.nCurrentLevel) / 4 + 2);
		count = 0;
		while ((d_rand () > nRandProb) && (count < 4)) {
			CFixVector	vRand;

			vRand = CFixVector::Random();
			vecToGoal += vRand * (I2X (1)/6);
			CFixVector::Normalize (vecToGoal);
			if (IsMultiGame)
				MultiSendCtrlcenFire (&vecToGoal, nBestGun, objP->Index ());
			CreateNewLaserEasy (&vecToGoal, &rStatP->vGunPos [nBestGun], objP->Index (), CONTROLCEN_WEAPON_NUM, 0);
			count++;
			}
		xDeltaFireTime = I2X (NDL - gameStates.app.nDifficultyLevel) / 4;
		if (gameStates.app.nDifficultyLevel == 0)
			xDeltaFireTime += (fix) (I2X (1) / 2 * gameStates.gameplay.slowmo [0].fSpeed);
		if (IsMultiGame) // slow down rate of fire in multi player
			xDeltaFireTime *= 2;
		rStatP->nNextFireTime = xDeltaFireTime;
		}
	} 
else
	rStatP->nNextFireTime -= gameData.physics.xTime;
}
Пример #28
0
//	-----------------------------------------------------------------------------
//do whatever this thing does in a frame
void DoReactorFrame (tObject *objP)
{
	int				nBestGun, i;
	tReactorStates	*rStatP;

	//	If a boss level, then gameData.reactor.bPresent will be 0.
if (!gameData.reactor.bPresent)
	return;
i = FindReactor (objP);
if (i < 0)
	return;
rStatP = gameData.reactor.states + i;
#ifdef _DEBUG
if (!gameStates.app.cheats.bRobotsFiring || (gameStates.app.bGameSuspended & SUSP_ROBOTS))
	return;
#else
if (!gameStates.app.cheats.bRobotsFiring)
	return;
#endif

if (!(rStatP->bHit || rStatP->bSeenPlayer)) {
	if (gameStates.app.tick40fps.bTick) {		//	Do ever so often...
		vmsVector	vecToPlayer;
		fix			xDistToPlayer;
		int			i;
		tSegment		*segP = gameData.segs.segments + objP->nSegment;

		// This is a hack.  Since the control center is not processed by
		// ai_do_frame, it doesn't know how to deal with cloaked dudes.  It
		// seems to work in single-tPlayer mode because it is actually using
		// the value of Believed_player_position that was set by the last
		// person to go through ai_do_frame.  But since a no-robots game
		// never goes through ai_do_frame, I'm making it so the control
		// center can spot cloaked dudes.

		if (IsMultiGame)
			gameData.ai.vBelievedPlayerPos = gameData.objs.objects [LOCALPLAYER.nObject].position.vPos;

		//	Hack for special control centers which are isolated and not reachable because the
		//	real control center is inside the boss.
		for (i = 0; i < MAX_SIDES_PER_SEGMENT; i++)
			if (IS_CHILD (segP->children [i]))
				break;
		if (i == MAX_SIDES_PER_SEGMENT)
			return;

		VmVecSub (&vecToPlayer, &gameData.objs.console->position.vPos, &objP->position.vPos);
		xDistToPlayer = VmVecNormalizeQuick (&vecToPlayer);
		if (xDistToPlayer < F1_0 * 200) {
			rStatP->bSeenPlayer = ObjectCanSeePlayer (objP, &objP->position.vPos, 0, &vecToPlayer);
			rStatP->nNextFireTime = 0;
			}
		}			
	return;
	}

//	Periodically, make the reactor fall asleep if tPlayer not visible.
if (rStatP->bHit || rStatP->bSeenPlayer) {
	if ((rStatP->xLastVisCheckTime + F1_0 * 5 < gameData.time.xGame) || 
		 (rStatP->xLastVisCheckTime > gameData.time.xGame)) {
		vmsVector	vecToPlayer;
		fix			xDistToPlayer;

		VmVecSub (&vecToPlayer, &gameData.objs.console->position.vPos, &objP->position.vPos);
		xDistToPlayer = VmVecNormalizeQuick (&vecToPlayer);
		rStatP->xLastVisCheckTime = gameData.time.xGame;
		if (xDistToPlayer < F1_0 * 120) {
			rStatP->bSeenPlayer = ObjectCanSeePlayer (objP, &objP->position.vPos, 0, &vecToPlayer);
			if (!rStatP->bSeenPlayer)
				rStatP->bHit = 0;
			}
		}
	}

if ((rStatP->nNextFireTime < 0) && 
	 !(gameStates.app.bPlayerIsDead && (gameData.time.xGame > gameStates.app.nPlayerTimeOfDeath + F1_0 * 2))) {
	if (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED)
		nBestGun = CalcBestReactorGun (gameData.reactor.props [objP->id].nGuns, rStatP->vGunPos, rStatP->vGunDir, &gameData.ai.vBelievedPlayerPos);
	else
		nBestGun = CalcBestReactorGun (gameData.reactor.props [objP->id].nGuns, rStatP->vGunPos, rStatP->vGunDir, &gameData.objs.console->position.vPos);

	if (nBestGun != -1) {
		int			nRandProb, count;
		vmsVector	vecToGoal;
		fix			xDistToPlayer;
		fix			xDeltaFireTime;

		if (LOCALPLAYER.flags & PLAYER_FLAGS_CLOAKED) {
			VmVecSub (&vecToGoal, &gameData.ai.vBelievedPlayerPos, &rStatP->vGunPos [nBestGun]);
			xDistToPlayer = VmVecNormalizeQuick (&vecToGoal);
			} 
		else {
			VmVecSub (&vecToGoal, &gameData.objs.console->position.vPos, &rStatP->vGunPos [nBestGun]);
			xDistToPlayer = VmVecNormalizeQuick (&vecToGoal);
			}
		if (xDistToPlayer > F1_0 * 300) {
			rStatP->bHit = 0;
			rStatP->bSeenPlayer = 0;
			return;
			}
		if (gameData.app.nGameMode & GM_MULTI)
			MultiSendCtrlcenFire (&vecToGoal, nBestGun, OBJ_IDX (objP));	
		CreateNewLaserEasy (&vecToGoal, &rStatP->vGunPos[nBestGun], OBJ_IDX (objP), CONTROLCEN_WEAPON_NUM, 1);
		//	some of time, based on level, fire another thing, not directly at tPlayer, so it might hit him if he's constantly moving.
		nRandProb = F1_0 / (abs (gameData.missions.nCurrentLevel) / 4 + 2);
		count = 0;
		while ((d_rand () > nRandProb) && (count < 4)) {
			vmsVector	vRand;

			MakeRandomVector (&vRand);
			VmVecScaleInc (&vecToGoal, &vRand, F1_0/6);
			VmVecNormalizeQuick (&vecToGoal);
			if (IsMultiGame)
				MultiSendCtrlcenFire (&vecToGoal, nBestGun, OBJ_IDX (objP));
			CreateNewLaserEasy (&vecToGoal, &rStatP->vGunPos[nBestGun], OBJ_IDX (objP), CONTROLCEN_WEAPON_NUM, 0);
			count++;
			}
		xDeltaFireTime = (NDL - gameStates.app.nDifficultyLevel) * F1_0/4;
		if (gameStates.app.nDifficultyLevel == 0)
			xDeltaFireTime += (fix) (F1_0 / 2 * gameStates.gameplay.slowmo [0].fSpeed);
		if (IsMultiGame) // slow down rate of fire in multi player
			xDeltaFireTime *= 2;
		rStatP->nNextFireTime = xDeltaFireTime;
		}
	} 
else
	rStatP->nNextFireTime -= gameData.physics.xTime;
}
Пример #29
0
//	-----------------------------------------------------------------------------------------------------------
//	Return true if door can be flown through by a suitable nType robot.
//	Brains, avoid robots, companions can open doors.
//	objP == NULL means treat as buddy.
int AIDoorIsOpenable (CObject *objP, CSegment *segP, short nSide)
{
	CWall	*wallP;

if (!IS_CHILD (segP->m_children [nSide]))
	return 0;		//trap -2 (exit CSide)
if (!(wallP = segP->Wall (nSide)))
	return 1;				//d:\temp\dm_testthen say it can't be opened
	//	The mighty console CObject can open all doors (for purposes of determining paths).
if (objP == gameData.objs.consoleP) {
	if (wallP->nType == WALL_DOOR)
		return 1;
	}
if ((objP == NULL) || (ROBOTINFO (objP->info.nId).companion == 1)) {
	int	ailp_mode;

	if (wallP->flags & WALL_BUDDY_PROOF) {
		if ((wallP->nType == WALL_DOOR) && (wallP->state == WALL_DOOR_CLOSED))
			return 0;
		else if (wallP->nType == WALL_CLOSED)
			return 0;
		else if ((wallP->nType == WALL_ILLUSION) && !(wallP->flags & WALL_ILLUSION_OFF))
			return 0;
		}

	if (wallP->keys != KEY_NONE) {
		if (wallP->keys == KEY_BLUE)
			return (LOCALPLAYER.flags & PLAYER_FLAGS_BLUE_KEY);
		else if (wallP->keys == KEY_GOLD)
			return (LOCALPLAYER.flags & PLAYER_FLAGS_GOLD_KEY);
		else if (wallP->keys == KEY_RED)
			return (LOCALPLAYER.flags & PLAYER_FLAGS_RED_KEY);
		}

	if (wallP->nType == WALL_CLOSED)
		return 0;
	if (wallP->nType != WALL_DOOR) /*&& (wallP->nType != WALL_CLOSED))*/
		return 1;

	//	If Buddy is returning to CPlayerData, don't let him think he can get through triggered doors.
	//	It's only valid to think that if the CPlayerData is going to get him through.  But if he's
	//	going to the CPlayerData, the CPlayerData is probably on the opposite CSide.
	if (objP)
		ailp_mode = gameData.ai.localInfo [objP->Index ()].mode;
	else if (gameData.escort.nObjNum >= 0)
		ailp_mode = gameData.ai.localInfo [gameData.escort.nObjNum].mode;
	else
		ailp_mode = 0;

	// -- if (Buddy_got_stuck) {
	if (ailp_mode == AIM_GOTO_PLAYER) {
		if ((wallP->nType == WALL_BLASTABLE) && (wallP->state != WALL_BLASTED))
			return 0;
		if (wallP->nType == WALL_CLOSED)
			return 0;
		if (wallP->nType == WALL_DOOR) {
			if ((wallP->flags & WALL_DOOR_LOCKED) && (wallP->state == WALL_DOOR_CLOSED))
				return 0;
			}
		}
		// -- }

	if ((ailp_mode != AIM_GOTO_PLAYER) && (wallP->controllingTrigger != -1)) {
		int	nClip = wallP->nClip;

		if (nClip == -1)
			return 1;
		else if (gameData.walls.animP [nClip].flags & WCF_HIDDEN) {
			if (wallP->state == WALL_DOOR_CLOSED)
				return 0;
			else
				return 1;
			}
		else
			return 1;
		}

	if (wallP->nType == WALL_DOOR)  {
		if (wallP->nType == WALL_BLASTABLE)
			return 1;
		else {
			int	nClip = wallP->nClip;

			if (nClip == -1)
				return 1;
			//	Buddy allowed to go through secret doors to get to player.
			else if ((ailp_mode != AIM_GOTO_PLAYER) && (gameData.walls.animP [nClip].flags & WCF_HIDDEN)) {
				if (wallP->state == WALL_DOOR_CLOSED)
					return 0;
				else
					return 1;
				}
			else
				return 1;
			}
		}
	}
else if ((objP->info.nId == ROBOT_BRAIN) || (objP->cType.aiInfo.behavior == AIB_RUN_FROM) || (objP->cType.aiInfo.behavior == AIB_SNIPE)) {
	if (wallP) {
		if ((wallP->nType == WALL_DOOR) && (wallP->keys == KEY_NONE) && !(wallP->flags & WALL_DOOR_LOCKED))
			return 1;
		else if (wallP->keys != KEY_NONE) {	//	Allow bots to open doors to which CPlayerData has keys.
			if (wallP->keys & LOCALPLAYER.flags)
				return 1;
			}
		}
	}
return 0;
}