Example #1
0
/*
 * Sift a node down from its current position to satisfy the heap
 * property.
 */
static void
sift_down(binaryheap *heap, int node_off)
{
	while (true)
	{
		int			left_off = left_offset(node_off);
		int			right_off = right_offset(node_off);
		int			swap_off = 0;

		/* Is the left child larger than the parent? */
		if (left_off < heap->bh_size &&
			heap->bh_compare(heap->bh_nodes[node_off],
							 heap->bh_nodes[left_off],
							 heap->bh_arg) < 0)
			swap_off = left_off;

		/* Is the right child larger than the parent? */
		if (right_off < heap->bh_size &&
			heap->bh_compare(heap->bh_nodes[node_off],
							 heap->bh_nodes[right_off],
							 heap->bh_arg) < 0)
		{
			/* swap with the larger child */
			if (!swap_off ||
				heap->bh_compare(heap->bh_nodes[left_off],
								 heap->bh_nodes[right_off],
								 heap->bh_arg) < 0)
				swap_off = right_off;
		}

		/*
		 * If we didn't find anything to swap, the heap condition is
		 * satisfied, and we're done.
		 */
		if (!swap_off)
			break;

		/*
		 * Otherwise, swap the node with the child that violates the heap
		 * property; then go on to check its children.
		 */
		swap_nodes(heap, swap_off, node_off);
		node_off = swap_off;
	}
}
// --------------------------------------------------------------------------
// t_combat_object_model_base class
// --------------------------------------------------------------------------
t_compound_object_model::t_compound_object_model( t_combat_object_model_24 const& source,
												  double scale )
{
	t_bitmap_group bitmaps;

	m_type = source.get_type();
	if (scale == 1.0)
	{
		bitmaps = t_bitmap_group( source.get_frames() );
	}
	else
	{
		t_bitmap_group_24 frames = source.get_frames();

		frames.offset( source.get_offset() );
		scale_group( frames, bitmaps, scale );
		bitmaps.offset( -source.get_offset() );
	}

	int segment_size;

	m_footprint_size = source.get_footprint_size();
	// determine size of subchunks.  1 for passable objects, as large as possible for
	// others
	if (source.blocks_movement() || source.is_underlay() 
		|| source.get_type() == k_obstacle_special || source.get_type() == k_obstacle_castle_tower)
		segment_size = greatest_common_divisor( m_footprint_size.row,
											    m_footprint_size.column );
	else
		segment_size = 1;

	// handle case where this isn't really compound
	if ((segment_size == m_footprint_size.row && segment_size == m_footprint_size.column)
		|| m_footprint_size.row == 0 || m_footprint_size.column == 0 )
	{
		t_object_segment* segment;

		segment = new t_object_segment( source, segment_size, t_map_point_2d(0,0), source,
			                            bitmaps );
		m_segments.push_back( segment );
		return;
	}

	t_map_point_3d		cell_offset(0,0,0);
	t_screen_rect		image_rect = bitmaps.get_rect();
	t_screen_point      shape_origin;
	t_screen_point		base_point;
	t_screen_point		left_tile_base;
	t_screen_point		right_tile_base;
	t_screen_point      bottom_tile_base;
	t_bitmap_line		line;
	t_bitmap_line_array lines;
	int					i;
	int					center;
	int					width;
	int					image_width = image_rect.width();
	int					half_segment_height;
	int					segment_height;
	t_map_point_2d      left_offset( segment_size, 0 );
	t_map_point_2d      right_offset( 0, segment_size );
	t_map_point_2d      down_offset( segment_size, segment_size );

	// chop image up into segment_size x segment_size chunks
	cell_offset.height = source.get_height();
	for (cell_offset.row = 0; cell_offset.row < m_footprint_size.row;
	     cell_offset.row += segment_size)
	{
		for (cell_offset.column = 0; cell_offset.column < m_footprint_size.column;
		     cell_offset.column += segment_size)
		{
			// find screen coordinate of top of tile
			base_point = get_base_point( cell_offset, scale ) - source.get_offset();
			left_tile_base = get_base_point( cell_offset + left_offset, scale )
				             - source.get_offset();
			right_tile_base = get_base_point( cell_offset + right_offset, scale )
				              - source.get_offset();
			bottom_tile_base = get_base_point( cell_offset + down_offset, scale )
				               - source.get_offset();
			lines.clear();
			shape_origin.x = image_rect.left;
			center = base_point.x - shape_origin.x;
			left_tile_base.x -= image_rect.left;
			right_tile_base.x -= image_rect.left;
			if (cell_offset.row == 0 && cell_offset.column == 0)
			{   // for the topmost tile only, include all the lines above half the height
				shape_origin.y = image_rect.top;
				line.left = 0;
				line.right = image_width;
				for (i = shape_origin.y; i < base_point.y; i++)
					lines.push_back( line );
			}
			else
			{
				shape_origin.y = base_point.y;
			}

			// create top half of mask
			half_segment_height = left_tile_base.y - base_point.y;
			for (i = 0; i < half_segment_height; i++)
			{
				width = 2 * (i + 1) * scale;
				if (cell_offset.column == 0)
					line.left = 0;
				else
					line.left = center - width;
				if (cell_offset.row == 0)
					line.right = image_width;
				else
					line.right = center + width;
				lines.push_back( line );
			}
			// create bottom half of mask
			segment_height = bottom_tile_base.y - base_point.y - half_segment_height;
			for (i = 0; i < segment_height; i++)
			{
				width = 2 * (i + 1) * scale;

				if (cell_offset.row + segment_size != m_footprint_size.row)
					line.left = left_tile_base.x + width;
				else if (cell_offset.column == 0)
					line.left = 0;
				else
					line.left = left_tile_base.x;

				if (cell_offset.column + segment_size != m_footprint_size.column)
					line.right = right_tile_base.x - width;
				else if (cell_offset.row == 0)
					line.right = image_width;
				else
					line.right = right_tile_base.x;

				lines.push_back( line );
			}
			if (cell_offset.row + segment_size == m_footprint_size.row
				|| cell_offset.column + segment_size == m_footprint_size.column)
			{
				if (cell_offset.row + segment_size != m_footprint_size.row)
					line.left = center;
				else if (cell_offset.column == 0)
					line.left = 0;
				else
					line.left = left_tile_base.x;

				if (cell_offset.column + segment_size != m_footprint_size.column)
					line.right = center;
				else if (cell_offset.row == 0)
					line.right = image_width;
				else
					line.right = right_tile_base.x;

				for (i = base_point.y + segment_height + half_segment_height; 
				     i < image_rect.bottom; i++)
					lines.push_back( line );
			}

			t_bitmap_group    segment_bitmaps;
			t_object_segment* segment;

			copy_bitmaps( bitmaps, segment_bitmaps, shape_origin, lines );
			if (segment_bitmaps.get_rect().width() == 0)
				continue;

			segment = new t_object_segment( source, segment_size,
				                            cell_offset << k_battlefield_subcell_shift,
											source, segment_bitmaps );
			base_point.y += cell_offset.height * scale;
			segment->set_offset( -base_point );
			m_segments.push_back( segment );
		}
	}
}