コード例 #1
0
ファイル: map_classic.c プロジェクト: ChunHungLiu/cdogs-sdl
static int FindWallRun(
	const Map *map, const Vec2i mid, const Vec2i d, const int len)
{
	int run = 0;
	int next = 0;
	bool plus = false;
	// Find the wall run by starting from a midpoint and expanding outwards in
	// both directions, in a series 0, 1, -1, 2, -2...
	for (int i = 0; i < len; i++, run++)
	{
		// Check if this is a wall so we can add a door here
		// Also check if the two tiles aside are not walls

		// Note: we must look for runs

		if (plus)
		{
			next += i;
		}
		else
		{
			next -= i;
		}
		const Vec2i v = Vec2iAdd(mid, Vec2iScale(d, next));
		plus = !plus;

		if (IMapGet(map, v) != MAP_WALL ||
			IMapGet(map, Vec2iNew(v.x + d.y, v.y + d.x)) == MAP_WALL ||
			IMapGet(map, Vec2iNew(v.x - d.y, v.y - d.x)) == MAP_WALL)
		{
			break;
		}
	}
	return run;
}
コード例 #2
0
void MissionConvertToType(Mission *m, Map *map, MapType type)
{
	memset(&m->u, 0, sizeof m->u);
	switch (type)
	{
	case MAPTYPE_CLASSIC:
		// Setup default parameters
		m->u.Classic.Walls = 10;
		m->u.Classic.WallLength = 5;
		m->u.Classic.CorridorWidth = 2;
		m->u.Classic.Rooms.Count = 10;
		m->u.Classic.Rooms.Min = 5;
		m->u.Classic.Rooms.Max = 8;;
		m->u.Classic.Rooms.Edge = true;
		m->u.Classic.Rooms.Overlap = true;
		m->u.Classic.Rooms.Walls = 1;
		m->u.Classic.Rooms.WallLength = 1;
		m->u.Classic.Rooms.WallPad = 1;
		m->u.Classic.Squares = 1;
		m->u.Classic.Doors.Enabled = true;
		m->u.Classic.Doors.Min = 1;
		m->u.Classic.Doors.Max = 2;
		m->u.Classic.Pillars.Count = 1;
		m->u.Classic.Pillars.Min = 2;
		m->u.Classic.Pillars.Max = 3;
		break;
	case MAPTYPE_STATIC:
		{
			Vec2i v;
			// Take all the tiles from the current map
			// and save them in the static map
			CArrayInit(&m->u.Static.Tiles, sizeof(unsigned short));
			for (v.y = 0; v.y < m->Size.y; v.y++)
			{
				for (v.x = 0; v.x < m->Size.x; v.x++)
				{
					unsigned short tile = IMapGet(map, v);
					CArrayPushBack(&m->u.Static.Tiles, &tile);
				}
			}
			CArrayInit(&m->u.Static.Items, sizeof(MapObjectPositions));
			CArrayInit(&m->u.Static.Characters, sizeof(CharacterPositions));
			CArrayInit(&m->u.Static.Objectives, sizeof(ObjectivePositions));
			CArrayInit(&m->u.Static.Keys, sizeof(KeyPositions));
		}
		break;
	case MAPTYPE_CAVE:
		// Setup default parameters
		m->u.Cave.FillPercent = 40;
		m->u.Cave.Repeat = 4;
		m->u.Cave.R1 = 5;
		m->u.Cave.R2 = 2;
		m->u.Cave.CorridorWidth = 2;
		break;
	default:
		CASSERT(false, "unknown map type");
		break;
	}
	m->Type = type;
}
コード例 #3
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
int MapIsAreaClearOrRoom(Map *map, Vec2i pos, Vec2i size)
{
	Vec2i v;

	if (pos.x < 0 || pos.y < 0 ||
		pos.x + size.x >= map->Size.x || pos.y + size.y >= map->Size.y)
	{
		return 0;
	}

	for (v.y = pos.y; v.y < pos.y + size.y; v.y++)
	{
		for (v.x = pos.x; v.x < pos.x + size.x; v.x++)
		{
			unsigned short tile = IMapGet(map, v) & MAP_MASKACCESS;
			switch (tile)
			{
			case MAP_FLOOR:	// fallthrough
			case MAP_ROOM:
				break;
			case MAP_WALL:
				// Check if this wall is part of a room
				if (!MapTileIsPartOfRoom(map, v))
				{
					return 0;
				}
				break;
			default:
				return 0;
			}
		}
	}

	return 1;
}
コード例 #4
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
int MapIsAreaClearOrWall(Map *map, Vec2i pos, Vec2i size)
{
	Vec2i v;

	if (pos.x < 0 || pos.y < 0 ||
		pos.x + size.x >= map->Size.x || pos.y + size.y >= map->Size.y)
	{
		return 0;
	}

	for (v.y = pos.y; v.y < pos.y + size.y; v.y++)
	{
		for (v.x = pos.x; v.x < pos.x + size.x; v.x++)
		{
			switch (IMapGet(map, v) & MAP_MASKACCESS)
			{
			case MAP_FLOOR:
				break;
			case MAP_WALL:
				// need to check if this is not a room wall
				if (MapTileIsPartOfRoom(map, v))
				{
					return 0;
				}
				break;
			default:
				return 0;
			}
		}
	}

	return 1;
}
コード例 #5
0
ファイル: map_classic.c プロジェクト: kodephys/cdogs-sdl
static int MapFindWallRun(Map *map, Vec2i start, Vec2i d, int len)
{
	int wallRun = 0;
	Vec2i v;
	int i;
	for (i = 0, v = start; i < len; i++, v = Vec2iAdd(v, d))
	{
		// Check if this is a wall so we can add a door here
		// Also check if the two tiles aside are not walls
		if (IMapGet(map, v) == MAP_WALL &&
			IMapGet(map, Vec2iNew(v.x + d.y, v.y + d.x)) != MAP_WALL &&
			IMapGet(map, Vec2iNew(v.x - d.y, v.y - d.x)) != MAP_WALL)
		{
			wallRun++;
		}
	}
	return wallRun;
}
コード例 #6
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
void MapMakeRoom(Map *map, int xOrigin, int yOrigin, int width, int height)
{
	int x, y;
	// Set the perimeter walls and interior
	// If the tile is a room interior already, do not turn it into a wall
	// This is due to overlapping rooms
	for (y = yOrigin; y < yOrigin + height; y++)
	{
		for (x = xOrigin; x < xOrigin + width; x++)
		{
			if (y == yOrigin || y == yOrigin + height - 1 ||
				x == xOrigin || x == xOrigin + width - 1)
			{
				if (IMapGet(map, Vec2iNew(x, y)) == MAP_FLOOR)
				{
					IMapSet(map, Vec2iNew(x, y), MAP_WALL);
				}
			}
			else
			{
				IMapSet(map, Vec2iNew(x, y), MAP_ROOM);
			}
		}
	}
	// Check perimeter again; if there are walls where both sides contain
	// rooms, remove the wall as the rooms have merged
	for (y = yOrigin; y < yOrigin + height; y++)
	{
		for (x = xOrigin; x < xOrigin + width; x++)
		{
			if (y == yOrigin || y == yOrigin + height - 1 ||
				x == xOrigin || x == xOrigin + width - 1)
			{
				if (((IMapGet(map, Vec2iNew(x + 1, y)) & MAP_MASKACCESS) == MAP_ROOM &&
					(IMapGet(map, Vec2iNew(x - 1, y)) & MAP_MASKACCESS) == MAP_ROOM) ||
					((IMapGet(map, Vec2iNew(x, y + 1)) & MAP_MASKACCESS) == MAP_ROOM &&
					(IMapGet(map, Vec2iNew(x, y - 1)) & MAP_MASKACCESS) == MAP_ROOM))
				{
					IMapSet(map, Vec2iNew(x, y), MAP_ROOM);
				}
			}
		}
	}
}
コード例 #7
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
// Set tile properties for a map tile, such as picture to use
static void MapSetupTile(Map *map, const Vec2i pos, const Mission *m)
{
	const int floor = m->FloorStyle % FLOOR_STYLE_COUNT;
	const int wall = m->WallStyle % WALL_STYLE_COUNT;
	const int room = m->RoomStyle % ROOM_STYLE_COUNT;
	Tile *tAbove = MapGetTile(map, Vec2iNew(pos.x, pos.y - 1));
	bool canSeeTileAbove = !(tAbove != NULL && !TileCanSee(tAbove));
	Tile *t = MapGetTile(map, pos);
	if (!t)
	{
		return;
	}
	switch (IMapGet(map, pos) & MAP_MASKACCESS)
	{
	case MAP_FLOOR:
	case MAP_SQUARE:
		t->pic = PicManagerGetMaskedStylePic(
			&gPicManager, "floor", floor,
			canSeeTileAbove ? FLOOR_NORMAL : FLOOR_SHADOW,
			m->FloorMask, m->AltMask);
		if (canSeeTileAbove)
		{
			// Normal floor tiles can be replaced randomly with
			// special floor tiles such as drainage
			t->flags |= MAPTILE_IS_NORMAL_FLOOR;
		}
		break;

	case MAP_ROOM:
	case MAP_DOOR:
		t->pic = PicManagerGetMaskedStylePic(
			&gPicManager, "room", room,
			canSeeTileAbove ? ROOMFLOOR_NORMAL : ROOMFLOOR_SHADOW,
			m->RoomMask, m->AltMask);
		break;

	case MAP_WALL:
		t->pic = PicManagerGetMaskedStylePic(
			&gPicManager, "wall", wall, MapGetWallPic(map, pos),
			m->WallMask, m->AltMask);
		t->flags =
			MAPTILE_NO_WALK | MAPTILE_NO_SHOOT |
			MAPTILE_NO_SEE | MAPTILE_IS_WALL;
		break;

	case MAP_NOTHING:
		t->pic = NULL;
		t->flags =
			MAPTILE_NO_WALK | MAPTILE_IS_NOTHING;
		break;
	}
}
コード例 #8
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
static int MapTileIsPartOfRoom(Map *map, Vec2i pos)
{
	Vec2i v2;
	int isRoom = 0;
	int isFloor = 0;
	// Find whether a wall tile is part of a room perimeter
	// The surrounding tiles must have normal floor and room tiles
	// to be a perimeter
	for (v2.y = pos.y - 1; v2.y <= pos.y + 1; v2.y++)
	{
		for (v2.x = pos.x - 1; v2.x <= pos.x + 1; v2.x++)
		{
			if ((IMapGet(map, v2) & MAP_MASKACCESS) == MAP_ROOM)
			{
				isRoom = 1;
			}
			else if ((IMapGet(map, v2) & MAP_MASKACCESS) == MAP_FLOOR)
			{
				isFloor = 1;
			}
		}
	}
	return isRoom && isFloor;
}
コード例 #9
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
int MapIsValidStartForWall(
	Map *map, int x, int y, unsigned short tileType, int pad)
{
	Vec2i d;
	if (x == 0 || y == 0 || x == map->Size.x - 1 || y == map->Size.y - 1)
	{
		return 0;
	}
	for (d.x = x - pad; d.x <= x + pad; d.x++)
	{
		for (d.y = y - pad; d.y <= y + pad; d.y++)
		{
			if (IMapGet(map, d) != tileType)
			{
				return 0;
			}
		}
	}
	return 1;
}
コード例 #10
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
int MapIsAreaClear(Map *map, Vec2i pos, Vec2i size)
{
	Vec2i v;

	if (pos.x < 0 || pos.y < 0 ||
		pos.x + size.x >= map->Size.x || pos.y + size.y >= map->Size.y)
	{
		return 0;
	}

	for (v.y = pos.y; v.y < pos.y + size.y; v.y++)
	{
		for (v.x = pos.x; v.x < pos.x + size.x; v.x++)
		{
			if (IMapGet(map, v) != MAP_FLOOR)
			{
				return 0;
			}
		}
	}

	return 1;
}
コード例 #11
0
ファイル: editor_brush.c プロジェクト: ChunHungLiu/cdogs-sdl
// Paint all the edge tiles as a wall, unless they are room tiles already;
// then paint the interior as room tiles
static void EditorBrushPaintRoom(EditorBrush *b, Mission *m)
{
	Vec2i v;
	for (v.y = 0; v.y < b->BrushSize; v.y++)
	{
		for (v.x = 0; v.x < b->BrushSize; v.x++)
		{
			unsigned short tile = MAP_ROOM;
			if (v.x == 0 || v.x == b->BrushSize - 1 ||
				v.y == 0 || v.y == b->BrushSize - 1)
			{
				tile = MAP_WALL;
			}
			const Vec2i pos = Vec2iAdd(b->Pos, v);
			const unsigned short tileExisting = IMapGet(&gMap, pos);
			if (tileExisting != MAP_ROOM)
			{
				SetTile(m, pos, tile);
			}
		}
	}
	b->IsPainting = true;
	b->LastPos = b->Pos;
}
コード例 #12
0
ファイル: map_classic.c プロジェクト: ChunHungLiu/cdogs-sdl
static void MapGrowWall(
	Map *map, int x, int y,
	unsigned short tileType, int pad, int d, int length)
{
	int l;
	Vec2i v;

	if (length <= 0)
		return;

	switch (d) {
	case 0:
		if (y < 2 + pad)
		{
			return;
		}
		// Check tiles above
		// xxxxx
		//  xxx
		//   o
		for (v.y = y - 2; v.y > y - 2 - pad; v.y--)
		{
			int level = v.y - (y - 2);
			for (v.x = x - 1 - level; v.x <= x + 1 + level; v.x++)
			{
				if (IMapGet(map, v) != tileType)
				{
					return;
				}
			}
		}
		y--;
		break;
	case 1:
		// Check tiles to the right
		//   x
		//  xx
		// oxx
		//  xx
		//   x
		for (v.x = x + 2; v.x < x + 2 + pad; v.x++)
		{
			int level = v.x - (x + 2);
			for (v.y = y - 1 - level; v.y <= y + 1 + level; v.y++)
			{
				if (IMapGet(map, v) != tileType)
				{
					return;
				}
			}
		}
		x++;
		break;
	case 2:
		// Check tiles below
		//   o
		//  xxx
		// xxxxx
		for (v.y = y + 2; v.y < y + 2 + pad; v.y++)
		{
			int level = v.y - (y + 2);
			for (v.x = x - 1 - level; v.x <= x + 1 + level; v.x++)
			{
				if (IMapGet(map, v) != tileType)
				{
					return;
				}
			}
		}
		y++;
		break;
	case 4:
		if (x < 2 + pad)
		{
			return;
		}
		// Check tiles to the left
		// x
		// xx
		// xxo
		// xx
		// x
		for (v.x = x - 2; v.x > x - 2 - pad; v.x--)
		{
			int level = v.x - (x - 2);
			for (v.y = y - 1 - level; v.y <= y + 1 + level; v.y++)
			{
				if (IMapGet(map, v) != tileType)
				{
					return;
				}
			}
		}
		x--;
		break;
	}
	MapMakeWall(map, Vec2iNew(x, y));
	length--;
	if (length > 0 && (rand() & 3) == 0)
	{
		// Randomly try to grow the wall in a different direction
		l = rand() % length;
		MapGrowWall(map, x, y, tileType, pad, rand() & 3, l);
		length -= l;
	}
	// Keep growing wall in same direction
	MapGrowWall(map, x, y, tileType, pad, d, length);
}
コード例 #13
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
// Check that this area does not overlap two or more "walls"
int MapIsLessThanTwoWallOverlaps(Map *map, Vec2i pos, Vec2i size)
{
	Vec2i v;
	int numOverlaps = 0;
	Vec2i overlapMin = Vec2iZero();
	Vec2i overlapMax = Vec2iZero();

	if (pos.x < 0 || pos.y < 0 ||
		pos.x + size.x >= map->Size.x || pos.y + size.y >= map->Size.y)
	{
		return 0;
	}

	for (v.y = pos.y; v.y < pos.y + size.y; v.y++)
	{
		for (v.x = pos.x; v.x < pos.x + size.x; v.x++)
		{
			// only check perimeter
			if (v.x != pos.x && v.x != pos.x + size.x - 1 &&
				v.y != pos.y && v.y != pos.y + size.y - 1)
			{
				continue;
			}
			switch (IMapGet(map, v))
			{
			case MAP_WALL:
				// Check if this wall is part of a room
				if (!MapTileIsPartOfRoom(map, v))
				{
					if (numOverlaps == 0)
					{
						overlapMin = overlapMax = v;
					}
					else
					{
						overlapMin = Vec2iMin(overlapMin, v);
						overlapMax = Vec2iMax(overlapMax, v);
					}
					numOverlaps++;
				}
				break;
			default:
				break;
			}
		}
	}
	if (numOverlaps < 2)
	{
		return 1;
	}

	// Now check that all tiles between the first and last tiles are
	// pillar tiles
	for (v.y = overlapMin.y; v.y <= overlapMax.y; v.y++)
	{
		for (v.x = overlapMin.x; v.x <= overlapMax.x; v.x++)
		{
			switch (IMapGet(map, v) & MAP_MASKACCESS)
			{
			case MAP_WALL:
				// Check if this wall is not part of a room
				if (MapTileIsPartOfRoom(map, v))
				{
					return 0;
				}
				break;
			default:
				// invalid tile type
				return 0;
			}
		}
	}

	return 1;
}
コード例 #14
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
// Find the size of the passage created by the overlap of two rooms
// To find whether an overlap is valid,
// collect the perimeter walls that overlap
// Two possible cases where there is a valid overlap:
// - if there are exactly two overlapping perimeter walls
//   i.e.
//          X
// room 2 XXXXXX
//        X X     <-- all tiles between either belong to room 1 or room 2
//     XXXXXX
//        X    room 1
//
// - if the collection of overlapping tiles are contiguous
//   i.e.
//        X room 1 X
//     XXXXXXXXXXXXXXX
//     X     room 2  X
//
// In both cases, the overlap is valid if all tiles in between are room or
// perimeter tiles. The size of the passage is given by the largest difference
// in the x or y coordinates between the first and last intersection tiles,
// minus 1
int MapGetRoomOverlapSize(
	Map *map, Vec2i pos, Vec2i size, unsigned short *overlapAccess)
{
	Vec2i v;
	int numOverlaps = 0;
	Vec2i overlapMin = Vec2iZero();
	Vec2i overlapMax = Vec2iZero();

	if (pos.x < 0 || pos.y < 0 ||
		pos.x + size.x >= map->Size.x || pos.y + size.y >= map->Size.y)
	{
		return 0;
	}

	// Find perimeter tiles that overlap
	for (v.y = pos.y; v.y < pos.y + size.y; v.y++)
	{
		for (v.x = pos.x; v.x < pos.x + size.x; v.x++)
		{
			// only check perimeter
			if (v.x != pos.x && v.x != pos.x + size.x - 1 &&
				v.y != pos.y && v.y != pos.y + size.y - 1)
			{
				continue;
			}
			switch (IMapGet(map, v))
			{
			case MAP_WALL:
				// Check if this wall is part of a room
				if (MapTileIsPartOfRoom(map, v))
				{
					// Get the access level of the room
					Vec2i v2;
					for (v2.y = v.y - 1; v2.y <= v.y + 1; v2.y++)
					{
						for (v2.x = v.x - 1; v2.x <= v.x + 1; v2.x++)
						{
							if ((IMapGet(map, v2) & MAP_MASKACCESS) == MAP_ROOM)
							{
								*overlapAccess |=
									IMapGet(map, v2) & MAP_ACCESSBITS;
							}
						}
					}
					if (numOverlaps == 0)
					{
						overlapMin = overlapMax = v;
					}
					else
					{
						overlapMin = Vec2iMin(overlapMin, v);
						overlapMax = Vec2iMax(overlapMax, v);
					}
					numOverlaps++;
				}
				break;
			default:
				break;
			}
		}
	}
	if (numOverlaps < 2)
	{
		return 0;
	}

	// Now check that all tiles between the first and last tiles are room or
	// perimeter tiles
	for (v.y = overlapMin.y; v.y <= overlapMax.y; v.y++)
	{
		for (v.x = overlapMin.x; v.x <= overlapMax.x; v.x++)
		{
			switch (IMapGet(map, v) & MAP_MASKACCESS)
			{
			case MAP_ROOM:
				break;
			case MAP_WALL:
				// Check if this wall is part of a room
				if (!MapTileIsPartOfRoom(map, v))
				{
					return 0;
				}
				break;
			default:
				// invalid tile type
				return 0;
			}
		}
	}

	return MAX(overlapMax.x - overlapMin.x, overlapMax.y - overlapMin.y) - 1;
}
コード例 #15
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
void MapPlaceDoors(
	Map *map, Vec2i pos, Vec2i size,
	int hasDoors, int doors[4], int doorMin, int doorMax,
	unsigned short accessMask)
{
	int x, y;
	int i;
	unsigned short doorTile = hasDoors ? MAP_DOOR : MAP_ROOM;
	Vec2i v;

	// Set access mask
	for (y = pos.y + 1; y < pos.y + size.y - 1; y++)
	{
		for (x = pos.x + 1; x < pos.x + size.x - 1; x++)
		{
			if ((IMapGet(map, Vec2iNew(x, y)) & MAP_MASKACCESS) == MAP_ROOM)
			{
				IMapSet(map, Vec2iNew(x, y), MAP_ROOM | accessMask);
			}
		}
	}

	// Set the doors
	if (doors[0])
	{
		int doorSize = MIN(
			(doorMax > doorMin ? (rand() % (doorMax - doorMin + 1)) : 0) + doorMin,
			size.y - 4);
		for (i = -doorSize / 2; i < (doorSize + 1) / 2; i++)
		{
			v = Vec2iNew(pos.x, pos.y + size.y / 2 + i);
			if (IMapGet(map, Vec2iNew(v.x + 1, v.y)) != MAP_WALL &&
				IMapGet(map, Vec2iNew(v.x - 1, v.y)) != MAP_WALL)
			{
				IMapSet(map, v, doorTile);
			}
		}
	}
	if (doors[1])
	{
		int doorSize = MIN(
			(doorMax > doorMin ? (rand() % (doorMax - doorMin + 1)) : 0) + doorMin,
			size.y - 4);
		for (i = -doorSize / 2; i < (doorSize + 1) / 2; i++)
		{
			v = Vec2iNew(pos.x + size.x - 1, pos.y + size.y / 2 + i);
			if (IMapGet(map, Vec2iNew(v.x + 1, v.y)) != MAP_WALL &&
				IMapGet(map, Vec2iNew(v.x - 1, v.y)) != MAP_WALL)
			{
				IMapSet(map, v, doorTile);
			}
		}
	}
	if (doors[2])
	{
		int doorSize = MIN(
			(doorMax > doorMin ? (rand() % (doorMax - doorMin + 1)) : 0) + doorMin,
			size.x - 4);
		for (i = -doorSize / 2; i < (doorSize + 1) / 2; i++)
		{
			v = Vec2iNew(pos.x + size.x / 2 + i, pos.y);
			if (IMapGet(map, Vec2iNew(v.x, v.y + 1)) != MAP_WALL &&
				IMapGet(map, Vec2iNew(v.x, v.y - 1)) != MAP_WALL)
			{
				IMapSet(map, v, doorTile);
			}
		}
	}
	if (doors[3])
	{
		int doorSize = MIN(
			(doorMax > doorMin ? (rand() % (doorMax - doorMin + 1)) : 0) + doorMin,
			size.x - 4);
		for (i = -doorSize / 2; i < (doorSize + 1) / 2; i++)
		{
			v = Vec2iNew(pos.x + size.x / 2 + i, pos.y + size.y - 1);
			if (IMapGet(map, Vec2iNew(v.x, v.y + 1)) != MAP_WALL &&
				IMapGet(map, Vec2iNew(v.x, v.y - 1)) != MAP_WALL)
			{
				IMapSet(map, v, doorTile);
			}
		}
	}
}
コード例 #16
0
ファイル: map_build.c プロジェクト: depoorterp/cdogs-sdl
static int W(Map *map, int x, int y)
{
	return IMapGet(map, Vec2iNew(x, y)) == MAP_WALL;
}