On this page
  1. Related
  2. Mechanics
  3. References
  4. Sources

Dune II came out in 19921. The atlas reads it through OpenDUNE, a translation of the DOS executable into C that runs on the data files of version 1.072. OpenDUNE fixes bugs of the original behind a switch that is on by default2, so a claim resting on a fixed line names the fix.

A harvester fills on spice and a refinery turns its load into credits3,4. Every build pays its cost a tick at a time and stops when the money does5. A player’s new structure must touch the base, and each tile without a concrete slab lowers its starting health6. In the original game every structure built during play then decays toward half health, slabs or not7.

A shot deals its unit’s table damage with no roll and no armor8. The damage lands at the explosion and falls off with distance from it, so a shell fired at a moving unit can miss9, and rocket launchers’ missiles aim off target at random10. The computer’s construction yard builds only what the house has lost11. In the original game its retaliation routine does nothing beyond setting a flag, because it looks only for carryalls12.

Mechanics

MechanicKindHow
Resource harvestingCarried loadsa harvester's load grows by a random 0 or 1 per call up to 100, and a refinery pays the player 7 credits a unit
ConstructionPay as builta builder pays cost ÷ build time each structure tick and waits when the money runs out; the computer builds slower early and only rebuilds what it lost
Structure placementAdjacent to the baserock, slab, or destroyed wall, touching the player's base corners included; each tile without a slab costs starting health
Tech treeOwned structureseach structure lists the structures a house must own and a first mission, which code moves for some houses
Structure decayAll structuresfrom the third mission every structure built in play loses 1–3 hit points by house each interval down to half; OpenDUNE's default spares structures wholly on slabs
Damage formulaFixed tableeach unit's table damage, no roll and no armor, halved per quarter tile from the explosion
Hit chanceAim scatterthe rocket launcher's and the Deviator's missiles fly to a random point near the target; turrets' missiles don't scatter
Every claim about this game, by concept (17)
generalDune II came out in 1992.Wikidata
OpenDUNE runs on the data files of Dune II 1.07, dune2.exe included, and keeps the original behavior behind a switch: with dune2_enhanced at 0 the "game acts like the original Dune II, including bugs", and at 1, the default, it applies the fixes that enhancement.txt lists.Code
The first time a computer house's structure is hit, Structure_HouseUnderAttack sets the house's full-scale-attack flag and, in OpenDUNE's enhanced mode (the default), sends its armed units on area guard to hunt. In the original mode the routine returns after setting the flag: OpenDUNE's comment says Dune II searched only for carryalls (unit type 0), so the rest did nothing, and enhancement.txt adds that the bug "makes the game much easier in its original form".Code
ConstructionA factory or construction yard counts a build down from 256 × the item's build time. On each structure tick, every 30 game-timer ticks at normal game speed, a builder at full health takes 256 off the count (less for a computer house; dune2/ai-build-speed) and pays the build cost ÷ build time, carrying fractions of a credit in 1/256ths; a damaged builder takes off and pays only its share of full health (hit points × 256 ÷ maximum) each tick. When its owner can't pay a tick's share, the build waits, and a player's build goes on hold with a message. Computed: at full health an item takes its build time in structure ticks and costs about its build cost, which OpenDUNE's 60 Hz game timer makes half a second per unit of build time at normal speed.Code
A computer house builds at no more than (20 × mission index + 95)/256 of full speed, where the first mission is index 0, and pays per tick in the same proportion. Computed: 95/256, about 37%, in the first mission, rising to 255/256 in the ninth.Code
A computer house's construction yard builds only structures the house has lost. Removing a structure records its type and position in the first free of five slots per house; while the house's AI is active and it has credits, an idle yard builds the first recorded type it can build, places the finished structure at once at the recorded position, and clears the slot. If no slot matches or placement fails at every match, the house gets the cost back and the structure is dropped.Code
Damage formulaThe executable's unit table sets hit points, speed (out of 256), range in tiles, fire delay, and damage per shot: the Trike 100, 45, 3, 50, and 5; the Quad 130, 40, 3, 50, and 7; the combat tank 200, 25, 4, 80, and 25; the siege tank 300, 20, 5, 90, and 30; the rocket launcher 100, 30, 9, 120, and 75; the Devastator 400, 10, 5, 100, and 40; and the sonic tank 110, 30, 8, 80, and 60. PROFILE.INI, read from the game data at start, can replace any of these.Code
A shot carries its unit's table damage, with no roll; only troopers and trooper squads firing beyond 2 tiles switch to a missile at damage − damage/4. The whole damage applies only at the point of impact, where a unit, or a structure on the impact tile, loses it from its hit points, down to 0, with no armor or defense stat; units farther from the point take less (dune2/splash). Units flagged to fire twice (among them the Trike, Quad, rocket launcher, siege tank, and Devastator) follow a shot with a second after a delay of 5 rather than twice their fire delay (at normal game speed), but only while above half health; every fire delay gets 0 or 1 added at random.Code
A shell or missile damages where it explodes, not the unit it was fired at: the explosion damages every unit within one tile of the point (two for the Death Hand explosion), its own side's included, by the damage halved once per quarter tile of distance, so full within a quarter tile, half to a half, a quarter to three quarters, and an eighth to one tile; the frigate and bullets in flight take none. A structure on the impact tile takes the full damage. A shell flies to the target's position at the moment of firing and explodes there, or earlier on a wall, structure, or mountain tile in its path; a turret's shell passes over its own side's walls and structures.Code
Hit chanceThe rocket launcher's and the Deviator's missiles aim at a random point near the target. 15 times in 16 the miss distance is a random byte halved until it is at most 8 + the distance to the target in whole tiles, and 1 time in 16 at most 8 + a second random byte, in sixteenths of a tile, in a random direction. The rocket turret's missiles carry no such flag and fly to the target point.Code
Resource harvestingEach time a harvester's script calls Script_Unit_Harvest while the harvester stands on spice or thick spice with a load below 100, the load grows by 0 or 1 at random, capped at 100, and in 1 call out of 32 the tile loses a level: thick spice becomes spice, and spice becomes sand. The status line reports the load as a percentage full.Code
A refinery empties a docked harvester a step at a time: each call to Script_Structure_RefineSpice moves up to 3 load units at full health, 2 once damaged, and 1 below 171/256 of full health (computed from hp × 256 / max × 3 / 256, at least 1), and pays 7 credits per unit to the player, or 6 to 9 at random per call to a computer house; the next call waits 6 script ticks. Computed: a full harvester (100) is worth 700 credits to the player.Code
Each refinery stores 1,005 credits and each spice silo 1,000 (the structure table's defaults). On each house tick, credits above a house's storage are lost, except that the player keeps the mission's starting credits as a floor until storage passes them. OpenDUNE moved this check: its comment says the original ran it outside the per-house loop, and enhancement.txt says 1.07 thereby updated only the house that owns the latest structure. In the original mode, a structure still being built also counts toward storage.Code
Structure decayFrom the third mission on, every 10,800 game-timer ticks at normal game speed, each structure marked as degrading loses hit points while it stands above half its table maximum: 3 for the Harkonnen, 2 for the Ordos, and 1 for every other house. Placement marks a structure when any footprint tile lacks a concrete slab, except a construction yard, which never counts missing slabs; in the original mode it marks every structure placed, slabs or not, and OpenDUNE's enhanced mode (the default) leaves a construction yard and a structure built wholly on slabs unmarked. Structures a scenario places start unmarked, and slabs and walls never decay. Computed: OpenDUNE's 60 Hz timer makes the interval 3 minutes, and a structure placed with no slab, which starts at half health, doesn't decay until repaired above it.Code
Structure placementA 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.Code
Tech treeThe executable's structure table sets, among others, a concrete slab at 5 credits, 16 build-time units, and 20 hit points; a windtrap at 300, 48, and 200; a refinery at 400, 80, and 450; a spice silo at 150, 48, and 150; an outpost at 400, 80, and 500; a light factory at 400, 96, and 350; a heavy factory at 600, 144, and 200; and a palace at 999, 130, and 1,000. Each row also names the structures a house must own first and the first mission it can be built in; code moves the light factory's first mission from 3 to 2 for every house but the Harkonnen. PROFILE.INI, read from the game data at start, can replace a row's cost, time, hit points, and first mission, along with its fog radius and its build, target, and sort priorities.Code
The player's construction yard offers a structure once the house owns every structure in its row's requirement set, the mission number has reached the row's first mission, the house may build it, and the yard's upgrade level is high enough. Two exceptions are coded: for the Harkonnen, the WOR, which trains troopers, needs no barracks and opens from the second mission; for other houses, the light factory opens from the second mission. A computer house's yard skips the requirement set and the upgrade level.Code

References

  1. ^Dune II came out in 1992.WikidataWikidata
    How we know
    +1992-01-01T00:00:00Z
    Q596631, publication date (P577) · archived copy ↗

    The quote matches our archived copy.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  2. ^ abOpenDUNE runs on the data files of Dune II 1.07, dune2.exe included, and keeps the original behavior behind a switch: with dune2_enhanced at 0 the "game acts like the original Dune II, including bugs", and at 1, the default, it applies the fixes that enhancement.txt lists.CodeOpenDUNE
    How we know
    64Copy the original Dune2 1.07 data files (including dune2.exe) to data/.
    
    README.txt line 64 at ebea79a · upstream ↗
    96- dune2_enhanced : 0 = game acts like the original Dune II, including bugs
    97                   1(default) = enable OpenDUNE enhancements
    
    README.txt lines 95–97 at ebea79a · upstream ↗
    81bool g_dune2_enhanced = true; /*!< If false, the game acts exactly like the original Dune2, including bugs. */
    
    src/opendune.c line 81 at ebea79a · upstream ↗
    3When OpenDUNE is started in enhanced mode (default), a lot of bugs and
    4 problems which are in the original Dune2 version, are fixed.
    
    enhancement.txt lines 3–4 at ebea79a · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  3. ^Each time a harvester's script calls Script_Unit_Harvest while the harvester stands on spice or thick spice with a load below 100, the load grows by 0 or 1 at random, capped at 100, and in 1 call out of 32 the tile loses a level: thick spice becomes spice, and spice becomes sand. The status line reports the load as a percentage full.CodeOpenDUNE
    How we know
    1651	if (u->amount >= 100) return 0;
    ⋮
    1656	if (type != LST_SPICE && type != LST_THICK_SPICE) return 0;
    ⋮
    1658	u->amount += Tools_Random_256() & 1;
    ⋮
    1663	if (u->amount > 100) u->amount = 100;
    ⋮
    1665	if ((Tools_Random_256() & 0x1F) != 0) return 1;
    ⋮
    1667	Map_ChangeSpiceAmount(packed, -1);
    ⋮
    1669	return 0;
    
    src/script/unit.c lines 1650–1669 at ebea79a · upstream ↗
    787		type = (type == LST_THICK_SPICE) ? LST_SPICE : LST_NORMAL_SAND;
    
    src/map.c lines 784–788 at ebea79a · upstream ↗
    2064		stringID = STR_IS_D_PERCENT_FULL;
    
    src/unit.c lines 2061–2069 at ebea79a · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  4. ^A refinery empties a docked harvester a step at a time: each call to Script_Structure_RefineSpice moves up to 3 load units at full health, 2 once damaged, and 1 below 171/256 of full health (computed from hp × 256 / max × 3 / 256, at least 1), and pays 7 credits per unit to the player, or 6 to 9 at random per call to a computer house; the next call waits 6 script ticks. Computed: a full harvester (100) is worth 700 credits to the player.CodeOpenDUNE
    How we know
    125	harvesterStep = (s->o.hitpoints * 256 / si->o.hitpoints) * 3 / 256;
    ⋮
    128	if (u->amount != 0 && harvesterStep < 1) harvesterStep = 1;
    ⋮
    131	creditsStep = 7;
    132	if (u->o.houseID != g_playerHouseID) {
    133		creditsStep += (Tools_Random_256() % 4) - 1;
    ⋮
    136	creditsStep *= harvesterStep;
    
    src/script/structure.c lines 125–136 at ebea79a · upstream ↗
    147	h->credits += creditsStep;
    148	u->amount -= harvesterStep;
    ⋮
    151	s->o.script.delay = 6;
    
    src/script/structure.c lines 146–151 at ebea79a · upstream ↗

    Checked against the evidence by its author, an AI model, 2026-10-21.

    Checked by a second AI model, 2026-10-22.

    In the claim ledger

  5. ^A factory or construction yard counts a build down from 256 × the item's build time. On each structure tick, every 30 game-timer ticks at normal game speed, a builder at full health takes 256 off the count (less for a computer house; dune2/ai-build-speed) and pays the build cost ÷ build time, carrying fractions of a credit in 1/256ths; a damaged builder takes off and pays only its share of full health (hit points × 256 ÷ maximum) each tick. When its owner can't pay a tick's share, the build waits, and a player's build goes on hold with a message. Computed: at full health an item takes its build time in structure ticks and costs about its build cost, which OpenDUNE's 60 Hz game timer makes half a second per unit of build time at normal speed.CodeOpenDUNE
    How we know
    1665		s->countDown = oi->buildTime << 8;
    
    src/structure.c line 1665 at ebea79a · upstream ↗
    68		s_tickStructureStructure = g_timerGame + Tools_AdjustToGameSpeed(30, 15, 60, true);
    
    src/structure.c lines 66–69 at ebea79a · upstream ↗
    175				if (!s->o.flags.s.onHold && s->countDown != 0 && s->o.linkedID != 0xFF && s->state == STRUCTURE_STATE_BUSY && si->o.flags.factory) {
    
    src/structure.c line 175 at ebea79a · upstream ↗
    188					buildSpeed = 256;
    189					if (s->o.hitpoints < si->o.hitpoints) {
    190						buildSpeed = s->o.hitpoints * 256 / si->o.hitpoints;
    ⋮
    198					buildCost = oi->buildCredits * 256 / oi->buildTime;
    ⋮
    201						buildCost = buildSpeed * buildCost / 256;
    ⋮
    208					buildCost += s->buildCostRemainder;
    ⋮
    210					if (buildCost / 256 <= h->credits) {
    211						s->buildCostRemainder = buildCost & 0xFF;
    212						h->credits -= buildCost / 256;
    ⋮
    215							s->countDown -= buildSpeed;
    
    src/structure.c lines 188–215 at ebea79a · upstream ↗
    265						/* Out of money means the building gets put on hold */
    266						if (s->o.houseID == g_playerHouseID) {
    267							s->o.flags.s.onHold = true;
    
    src/structure.c lines 264–269 at ebea79a · upstream ↗
    1168	Timer_Add(Timer_Tick, 1000000 / 60, false);
    
    src/opendune.c line 1168 at ebea79a · upstream ↗
    364	if ((s_timersActive & TIMER_GAME) != 0) g_timerGame++;
    
    src/timer.c line 364 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.

    In the claim ledger

  6. ^A 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 claim ledger

  7. ^From the third mission on, every 10,800 game-timer ticks at normal game speed, each structure marked as degrading loses hit points while it stands above half its table maximum: 3 for the Harkonnen, 2 for the Ordos, and 1 for every other house. Placement marks a structure when any footprint tile lacks a concrete slab, except a construction yard, which never counts missing slabs; in the original mode it marks every structure placed, slabs or not, and OpenDUNE's enhanced mode (the default) leaves a construction yard and a structure built wholly on slabs unmarked. Structures a scenario places start unmarked, and slabs and walls never decay. Computed: OpenDUNE's 60 Hz timer makes the interval 3 minutes, and a structure placed with no slab, which starts at half health, doesn't decay until repaired above it.CodeOpenDUNErevised
    How we know
    61	if (s_tickStructureDegrade <= g_timerGame && g_campaignID > 1) {
    62		tickDegrade = true;
    63		s_tickStructureDegrade = g_timerGame + Tools_AdjustToGameSpeed(10800, 5400, 21600, true);
    
    src/structure.c lines 61–63 at ebea79a · upstream ↗
    95		if (s->o.type == STRUCTURE_SLAB_1x1 || s->o.type == STRUCTURE_SLAB_2x2 || s->o.type == STRUCTURE_WALL) continue;
    
    src/structure.c line 95 at ebea79a · upstream ↗
    121		if (tickDegrade && s->o.flags.s.degrades && s->o.hitpoints > si->o.hitpoints / 2) {
    122			Structure_Damage(s, hi->degradingAmount, 0);
    
    src/structure.c lines 121–122 at ebea79a · upstream ↗
    9		/* name                 */ "Harkonnen",
    ⋮
    12		/* degradingAmount      */ 3,
    
    src/table/houseinfo.c lines 9–12 at ebea79a · upstream ↗
    41		/* name                 */ "Ordos",
    ⋮
    44		/* degradingAmount      */ 2,
    
    src/table/houseinfo.c lines 41–44 at ebea79a · upstream ↗
    28		/* degradingAmount      */ 1,
    ⋮
    60		/* degradingAmount      */ 1,
    ⋮
    76		/* degradingAmount      */ 1,
    ⋮
    92		/* degradingAmount      */ 1,
    
    src/table/houseinfo.c lines 25–92 at ebea79a · upstream ↗
    550	if (validBuildLocation < 0) {
    ⋮
    556		s->o.flags.s.degrades = true;
    557	} else {
    558		/* ENHANCEMENT -- When you build a structure completely on slabs, it should not degrade */
    559		if (!g_dune2_enhanced) {
    560			s->o.flags.s.degrades = true;
    
    src/structure.c lines 550–561 at ebea79a · upstream ↗
    766			if (si->o.flags.notOnConcrete) {
    ⋮
    776				if (lst != LST_CONCRETE_SLAB) neededSlabs++;
    
    src/structure.c lines 766–777 at ebea79a · upstream ↗
    542		/* notOnConcrete        */ true,
    
    src/table/structureinfo.c lines 536–542 at ebea79a · upstream ↗
    285		s->o.flags.s.degrades = false;
    
    src/scenario.c lines 284–285 at ebea79a · upstream ↗
    1168	Timer_Add(Timer_Tick, 1000000 / 60, false);
    
    src/opendune.c line 1168 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 claim ledger

  8. ^A shot carries its unit's table damage, with no roll; only troopers and trooper squads firing beyond 2 tiles switch to a missile at damage − damage/4. The whole damage applies only at the point of impact, where a unit, or a structure on the impact tile, loses it from its hit points, down to 0, with no armor or defense stat; units farther from the point take less (dune2/splash). Units flagged to fire twice (among them the Trike, Quad, rocket launcher, siege tank, and Devastator) follow a shot with a second after a delay of 5 rather than twice their fire delay (at normal game speed), but only while above half health; every fire delay gets 0 or 1 added at random.CodeOpenDUNErevised
    How we know
    623	damage = ui->damage;
    ⋮
    626	fireTwice = ui->flags.firesTwice && u->o.hitpoints > ui->o.hitpoints / 2;
    ⋮
    628	if ((u->o.type == UNIT_TROOPERS || u->o.type == UNIT_TROOPER) && (int16)distance > 512) typeID = UNIT_MISSILE_TROOPER;
    
    src/script/unit.c lines 623–628 at ebea79a · upstream ↗
    659			damage -= damage / 4;
    
    src/script/unit.c lines 658–659 at ebea79a · upstream ↗
    683	u->fireDelay = Tools_AdjustToGameSpeed(ui->fireDelay * 2, 1, 0xFFFF, true);
    ⋮
    687		if (u->o.flags.s.fireTwiceFlip) u->fireDelay = Tools_AdjustToGameSpeed(5, 1, 10, true);
    ⋮
    692	u->fireDelay += Tools_Random_256() & 1;
    
    src/script/unit.c lines 683–692 at ebea79a · upstream ↗
    431				Unit_Damage(u, hitpoints >> (distance >> 2), 0);
    
    src/map.c lines 427–431 at ebea79a · upstream ↗
    1544	if (unit->o.hitpoints >= damage) {
    1545		unit->o.hitpoints -= damage;
    
    src/unit.c lines 1544–1548 at ebea79a · upstream ↗
    1049	if (s->o.hitpoints >= damage) {
    1050		s->o.hitpoints -= damage;
    
    src/structure.c lines 1049–1053 at ebea79a · upstream ↗
    1012		/* firesTwice           */ true,
    
    src/table/unitinfo.c line 1012 at ebea79a · upstream ↗
    1158		/* firesTwice           */ true,
    
    src/table/unitinfo.c line 1158 at ebea79a · upstream ↗
    574		/* firesTwice           */ true,
    
    src/table/unitinfo.c line 574 at ebea79a · upstream ↗
    793		/* firesTwice           */ true,
    
    src/table/unitinfo.c line 793 at ebea79a · upstream ↗
    866		/* firesTwice           */ true,
    
    src/table/unitinfo.c line 866 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 claim ledger

  9. ^A shell or missile damages where it explodes, not the unit it was fired at: the explosion damages every unit within one tile of the point (two for the Death Hand explosion), its own side's included, by the damage halved once per quarter tile of distance, so full within a quarter tile, half to a half, a quarter to three quarters, and an eighth to one tile; the frigate and bullets in flight take none. A structure on the impact tile takes the full damage. A shell flies to the target's position at the moment of firing and explodes there, or earlier on a wall, structure, or mountain tile in its path; a turret's shell passes over its own side's walls and structures.CodeOpenDUNE
    How we know
    405	uint16 reactionDistance = (type == EXPLOSION_DEATH_HAND) ? 32 : 16;
    ⋮
    427			distance = Tile_GetDistance(position, u->o.position) >> 4;
    428			if (distance >= reactionDistance) continue;
    ⋮
    430			if (!(u->o.type == UNIT_SANDWORM && type == EXPLOSION_SANDWORM_SWALLOW) && u->o.type != UNIT_FRIGATE) {
    431				Unit_Damage(u, hitpoints >> (distance >> 2), 0);
    
    src/map.c lines 405–431 at ebea79a · upstream ↗
    489		Structure *s = Structure_Get_ByPackedTile(positionPacked);
    ⋮
    501			Structure_Damage(s, hitpoints, 0);
    
    src/map.c lines 488–501 at ebea79a · upstream ↗
    1540	if (!ui->flags.isNormalUnit && unit->o.type != UNIT_SANDWORM) return false;
    
    src/unit.c line 1540 at ebea79a · upstream ↗
    1981			bullet->targetAttack = target;
    1982			bullet->o.hitpoints = damage;
    1983			bullet->currentDestination = tile;
    
    src/unit.c lines 1981–1983 at ebea79a · upstream ↗
    2020			bullet->currentDestination = tile;
    
    src/unit.c lines 2020–2021 at ebea79a · upstream ↗
    1444							Map_MakeExplosion((ui->explosionType + unit->o.hitpoints / 20) & 3, newPosition, unit->o.hitpoints, unit->originEncoded);
    
    src/unit.c lines 1438–1444 at ebea79a · upstream ↗
    1399		if (unit->o.type == UNIT_BULLET) {
    ⋮
    1403					if (g_map[Tile_PackTile(newPosition)].houseID == unit->o.houseID) {
    ⋮
    1409			if (type == LST_WALL || type == LST_STRUCTURE || type == LST_ENTIRELY_MOUNTAIN) {
    
    src/unit.c lines 1399–1412 at ebea79a · upstream ↗
    44	if (distance_x > distance_y) return distance_x + (distance_y / 2);
    
    src/tile.c lines 39–45 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.

    In the claim ledger

  10. ^The rocket launcher's and the Deviator's missiles aim at a random point near the target. 15 times in 16 the miss distance is a random byte halved until it is at most 8 + the distance to the target in whole tiles, and 1 time in 16 at most 8 + a second random byte, in sixteenths of a tile, in a random direction. The rocket turret's missiles carry no such flag and fly to the target point.CodeOpenDUNE
    How we know
    1985			if (ui->flags.notAccurate) {
    1986				bullet->currentDestination = Tile_MoveByRandom(tile, (Tools_Random_256() & 0xF) != 0 ? Tile_GetDistance(position, tile) / 256 + 8 : Tools_Random_256() + 8, false);
    
    src/unit.c lines 1985–1987 at ebea79a · upstream ↗
    319	newDistance = Tools_Random_256();
    320	while (newDistance > distance) newDistance /= 2;
    ⋮
    323	orientation = Tools_Random_256();
    324	x += ((_stepX[orientation] * distance) / 128) * 16;
    
    src/tile.c lines 319–325 at ebea79a · upstream ↗
    1405		/* name                 */ "Rocket",
    ⋮
    1454		/* notAccurate          */ true,
    
    src/table/unitinfo.c lines 1405–1454 at ebea79a · upstream ↗
    1551		/* name                 */ "GRocket",
    ⋮
    1600		/* notAccurate          */ true,
    
    src/table/unitinfo.c lines 1551–1600 at ebea79a · upstream ↗
    1478		/* name                 */ "ARocket",
    ⋮
    1527		/* notAccurate          */ false,
    
    src/table/unitinfo.c lines 1478–1527 at ebea79a · upstream ↗
    31	UNIT_MISSILE_ROCKET   = 19,
    32	UNIT_MISSILE_TURRET   = 20,
    33	UNIT_MISSILE_DEVIATOR = 21,
    
    src/unit.h lines 31–33 at ebea79a · upstream ↗
    595		/* bulletType           */ UNIT_MISSILE_ROCKET,
    
    src/table/unitinfo.c line 595 at ebea79a · upstream ↗
    668		/* bulletType           */ UNIT_MISSILE_DEVIATOR,
    
    src/table/unitinfo.c line 668 at ebea79a · upstream ↗
    529		type      = UNIT_MISSILE_TURRET;
    
    src/script/structure.c line 529 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.

    In the claim ledger

  11. ^A computer house's construction yard builds only structures the house has lost. Removing a structure records its type and position in the first free of five slots per house; while the house's AI is active and it has credits, an idle yard builds the first recorded type it can build, places the finished structure at once at the recorded position, and clears the slot. If no slot matches or placement fails at every match, the house gets the cost back and the structure is dropped.CodeOpenDUNE
    How we know
    1338	for (i = 0; i < 5; i++) {
    1339		if (h->ai_structureRebuild[i][0] != 0) continue;
    1340		h->ai_structureRebuild[i][0] = s->o.type;
    1341		h->ai_structureRebuild[i][1] = packed;
    
    src/structure.c lines 1338–1342 at ebea79a · upstream ↗
    1993	if (s->o.type == STRUCTURE_CONSTRUCTION_YARD) {
    1994		for (i = 0; i < 5; i++) {
    1995			type = h->ai_structureRebuild[i][0];
    
    src/structure.c lines 1993–2003 at ebea79a · upstream ↗
    308				/* AI maintenance on structures */
    309				if (h->flags.isAIActive && s->o.flags.s.allocated && s->o.houseID != g_playerHouseID && h->credits != 0) {
    ⋮
    316					if (si->o.flags.factory && s->countDown == 0 && s->o.linkedID == 0xFF) {
    317						uint16 type = Structure_AI_PickNextToBuild(s);
    
    src/structure.c lines 308–319 at ebea79a · upstream ↗
    240								/* The AI places structures which are operational immediately */
    ⋮
    247									if (!Structure_Place(ns, h->ai_structureRebuild[i][1])) continue;
    ⋮
    254								/* If the AI no longer had in memory where to store the structure, free it and forget about it */
    ⋮
    258									h->credits += nsi->o.buildCredits;
    
    src/structure.c lines 240–261 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.

    In the claim ledger

  12. ^The first time a computer house's structure is hit, Structure_HouseUnderAttack sets the house's full-scale-attack flag and, in OpenDUNE's enhanced mode (the default), sends its armed units on area guard to hunt. In the original mode the routine returns after setting the flag: OpenDUNE's comment says Dune II searched only for carryalls (unit type 0), so the rest did nothing, and enhancement.txt adds that the bug "makes the game much easier in its original form".CodeOpenDUNE
    How we know
    1940	if (houseID != g_playerHouseID && h->flags.doneFullScaleAttack) return;
    1941	h->flags.doneFullScaleAttack = true;
    ⋮
    1949		return;
    ⋮
    1952	/* ENHANCEMENT -- Dune2 originally only searches for units with type 0 (Carry-all). In result, the rest of this function does nothing. */
    1953	if (!g_dune2_enhanced) return;
    ⋮
    1968		if (ui->bulletType == UNIT_INVALID) continue;
    ⋮
    1971		if ((u->actionID == ACTION_GUARD && u->actionID == ACTION_AMBUSH) || u->actionID == ACTION_AREA_GUARD) Unit_SetAction(u, ACTION_HUNT);
    
    src/structure.c lines 1940–1971 at ebea79a · upstream ↗
    500			Structure_HouseUnderAttack(s->o.houseID);
    
    src/map.c line 500 at ebea79a · upstream ↗
    39- When you attack the structure of the AI, the idea is that they massively
    40    start to attack you (payback and stuff). To do this, Dune2 searches all
    41    Units with type 0 (Carry-alls), instead of type 0xFFFF (all units).
    42    WARNING: this glitch makes the game much easier in its original form.
    
    enhancement.txt lines 39–42 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.

    In the claim ledger

Sources

Code

Secondary