Mechanic · simulation · real-time strategy
Structure placement
The rules for where a finished structure may be set down on the map.
On this page
Structure placement decides where a new building may stand. In Dune II a footprint must lie on rock, slab, or a destroyed wall, and a player’s structure must touch the player’s own base, corners included; each tile without a concrete slab costs the new structure starting health1.
- Adjacent to the baseDune II (1992). Rock, slab, or destroyed wall, touching the player's base corners included; each tile without a slab costs starting health.1Command & Conquer (1995). Every footprint cell clear land or road, one of them beside the player's own building, wall, or bib, corners included; the computer is exempt.2
Games
| Game | Year | How | Note |
|---|---|---|---|
| Dungeon Keeper | 1997 | rooms go only on ground the Imps have dug out and tiled | |
| RollerCoaster Tycoon | 1999 | a shop serves from one side, which has to face a path; only the Information Kiosk serves from all four | |
| Dune II | 1992 | Adjacent to the base | rock, slab, or destroyed wall, touching the player's base corners included; each tile without a slab costs starting health |
| Command & Conquer | 1995 | Adjacent to the base | every footprint cell clear land or road, one of them beside the player's own building, wall, or bib, corners included; the computer is exempt |
Every claim about this mechanic, by game (5)
References
- ^ abA structure fits where every footprint tile is rock (entirely or mostly), a concrete slab, or a destroyed wall, with no unit or structure on it; slabs and the construction yard can't go on a slab. For the player, one of the tiles ringing the footprint, corners included, must also hold one of the player's structures, or a slab or wall the player owns; the construction yard is exempt, and a computer house's placement skips the check. For every structure but slabs and the construction yard, which never count missing slabs, the footprint tiles without a slab take (maximum hit points ÷ 2) × (tiles without a slab) ÷ (footprint tiles) off the new structure's starting hit points. Computed: such a structure placed with no slab starts at half health.CodeOpenDUNErevised
How we know
766 if (si->o.flags.notOnConcrete) { 767 if (!g_table_landscapeInfo[lst].isValidForStructure2 && g_validateStrictIfZero == 0) { ⋮ 772 if (!g_table_landscapeInfo[lst].isValidForStructure && g_validateStrictIfZero == 0) { ⋮ 776 if (lst != LST_CONCRETE_SLAB) neededSlabs++; ⋮ 780 if (Object_GetByPackedTile(curPos) != NULL) {
src/structure.c lines 748–784 at ebea79a · upstream ↗ 786 if (g_validateStrictIfZero == 0 && isValid && type != STRUCTURE_CONSTRUCTION_YARD && !g_debugScenario) { ⋮ 798 if (s->o.houseID != g_playerHouseID) continue; ⋮ 804 if (lst != LST_CONCRETE_SLAB && lst != LST_WALL) continue; 805 if (g_map[curPos].houseID != g_playerHouseID) continue; ⋮ 814 return -neededSlabs;
src/structure.c lines 786–814 at ebea79a · upstream ↗ 1305const int16 g_table_structure_layoutTilesAround[STRUCTURE_LAYOUT_MAX][16] = {src/table/structureinfo.c lines 1305–1309 at ebea79a · upstream ↗ 57 { /* 4 / LST_ENTIRELY_ROCK */ ⋮ 60 /* isValidForStructure */ true, ⋮ 69 { /* 5 / LST_MOSTLY_ROCK */ ⋮ 72 /* isValidForStructure */ true,
src/table/landscapeinfo.c lines 57–74 at ebea79a · upstream ↗ 129 { /* 10 / LST_CONCRETE_SLAB */ ⋮ 132 /* isValidForStructure */ true, 133 /* isSand */ false, 134 /* isValidForStructure2 */ false,
src/table/landscapeinfo.c lines 129–134 at ebea79a · upstream ↗ 165 { /* 13 / LST_DESTROYED_WALL */src/table/landscapeinfo.c lines 165–170 at ebea79a · upstream ↗ 22 /* notOnConcrete */ true,src/table/structureinfo.c lines 16–22 at ebea79a · upstream ↗ 531 if (validBuildLocation == 0 && s->o.houseID == g_playerHouseID && !g_debugScenario && g_validateStrictIfZero == 0) return false;src/structure.c lines 530–531 at ebea79a · upstream ↗ 549 /* If the return value is negative, there are tiles without slab. This gives a penalty to the hitpoints. */ ⋮ 554 s->o.hitpoints -= (si->o.hitpoints / 2) * tilesWithoutSlab / structureTileCount;
src/structure.c lines 549–554 at ebea79a · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Revised after a check by a second AI model, 2026-10-22.
- ^In the remaster's code, a structure can be placed where every cell of its footprint, its bib included, is clear: no object, no wall, no owned bib, and ground marked buildable (clear land or road; not Tiberium, beach, rock, or water). For a human house, one of the eight cells around some footprint cell, corners included, must also hold one of the house's buildings or be a cell the house owns, which its walls and bibs are; a computer house's placement skips that check. Dune II's rule is also adjacency with corners counted and also skipped for the computer, but on rock, concrete slab, or destroyed wall, with the construction yard exempt.CodeC&C Remastered source · OpenDUNE
How we know
5490 if (Debug_Map || !House->IsHuman) { ⋮ 5499 short const * ptr = Occupy_List(true); ⋮ 5505 for (FacingType facing = FACING_N; facing < FACING_COUNT; facing++) { 5506 CELL newcell = Adjacent_Cell(cell, facing); ⋮ 5511 ** The special cell ownership flag allows building adjacent 5512 ** to friendly walls and bibs even though there is no official ⋮ 5515 if (Map[newcell].Owner == House->Class->House) { ⋮ 5519 if (base && base->House->Class->House == House->Class->House) {
TIBERIANDAWN/BUILDING.CPP lines 5485–5524 at f1f0d42 · upstream ↗ 2926 if (tech->What_Am_I() != RTTI_BUILDING || ((BuildingClass *)tech)->Passes_Proximity_Check(cell)) { 2927 builder->Transmit_Message(RADIO_HELLO, tech); 2928 if (tech->Unlimbo(Cell_Coord(cell))) {
TIBERIANDAWN/HOUSE.CPP lines 2926–2928 at f1f0d42 · upstream ↗ 1196 if (ScenarioInit || Can_Enter_Cell(Coord_Cell(coord), FACING_NONE) == MOVE_OK) {TIBERIANDAWN/OBJECT.CPP line 1196 at f1f0d42 · upstream ↗ 3832 return(Class->Legal_Placement(cell) ? MOVE_OK : MOVE_NO);TIBERIANDAWN/BUILDING.CPP line 3832 at f1f0d42 · upstream ↗ 4415 offset = Occupy_List(true); ⋮ 4419 if (!Map[cell].Is_Generally_Clear()) {
TIBERIANDAWN/BDATA.CPP lines 4415–4420 at f1f0d42 · upstream ↗ 434 if (Flag.Composite || IsFlagged || Cell_Occupier()) { ⋮ 439 if (Smudge != SMUDGE_NONE && SmudgeTypeClass::As_Reference(Smudge).IsBib && Owner != HOUSE_NONE) { ⋮ 442 if (Overlay != OVERLAY_NONE && (Overlay == OVERLAY_FLAG_SPOT || OverlayTypeClass::As_Reference(Overlay).IsWall)) { ⋮ 468 return(::Ground[Land_Type()].Build);
TIBERIANDAWN/CELL.CPP lines 430–468 at f1f0d42 · upstream ↗ }, true}, // LAND_CLEAR … }, true}, // LAND_ROAD … }, false}, // LAND_WATER … }, false}, // LAND_ROCK … }, false}, // LAND_TIBERIUM … }, false}, // LAND_BEACH
TIBERIANDAWN/CONST.CPP#L269-L275 · upstream ↗ 228 if (Class->IsBib) { ⋮ 231 cell->Owner = ToOwn;
TIBERIANDAWN/SMUDGE.CPP lines 228–231 at f1f0d42 · upstream ↗ 241 if (Class->IsWall) { ⋮ 253 cellptr->Owner = ToOwn;
TIBERIANDAWN/OVERLAY.CPP lines 241–253 at f1f0d42 · upstream ↗ 786 if (g_validateStrictIfZero == 0 && isValid && type != STRUCTURE_CONSTRUCTION_YARD && !g_debugScenario) { ⋮ 798 if (s->o.houseID != g_playerHouseID) continue;
src/structure.c lines 786–814 at ebea79a · upstream ↗ 531 if (validBuildLocation == 0 && s->o.houseID == g_playerHouseID && !g_debugScenario && g_validateStrictIfZero == 0) return false;src/structure.c lines 530–531 at ebea79a · upstream ↗ Checked against the evidence by its author, an AI model, 2026-10-22.
Checked by a second AI model, 2026-10-22.
Sources
Code
- OpenDUNE contributors. 2026. “OpenDUNE: a C re-creation of Dune II from its DOS executable (OpenDUNE/OpenDUNE).” Commit ebea79a. OpenDUNE/OpenDUNE @ ebea79a · licence, all uses