data/claims/wolf3d.yamlWolfenstein 3D (id Software's source release, id-Software/wolf3d)
Game: Wolfenstein 3D.
id Software's released Wolfenstein 3D source names no version number: John Carmack's RELEASE.TXT calls it "all the source we have relating to the original PC wolfenstein 3D project", built in Borland C++ 3.0, and VERSION.H, which selects the build, leaves SPEAR (the Spear of Destiny build) commented out and defines GOODTIMES. wolf3d/source-version
WOLFSRC/README/RELEASE.TXT#L6-L7This is all the source we have relating to the original
PC wolfenstein 3D project. We haven't looked at thisWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/README/RELEASE.TXT#L10about it. The original project was built in borland c++ 3.0.Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/README/RELEASE.TXT#L51-L52John Carmack
Technical DirectorWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/VERSION.H#L1-L3//#define SPEAR
//#define JAPAN
#define GOODTIMESChecked by claude, 2026-10-22 — read RELEASE.TXT and VERSION.H at the pinned commit, and searched the C and header files for a version string or number (none)Every other claim here reads this source with VERSION.H's settings, the Wolfenstein 3D build. Which shipped executable it matches (a numbered release such as 1.4, or the edition GOODTIMES selects) is not stated in the repo.
Cited by: Wolfenstein 3D
id Software first released the Wolfenstein 3D source under a limited-use license and later relicensed it under the GPL: the repo's LICENSE.DOC is the "LIMITED USE SOFTWARE LICENSE AGREEMENT", and John Carmack wrote in 2009 that he released the source "originally under a not-for-commercial purposes license, then later under the GPL", and in a 2011 mail, quoted in Debian's wolf4sdl copyright file, "Yes, we relicensed it under the gpl years ago." No source here dates the relicensing. wolf3d/gpl-relicensing
README.rst#L89 LIMITED USE SOFTWARE LICENSE AGREEMENTWolfenstein 3D Classic for iPhone: source release notes (wolf3d_iphone_v1.1_src.txt)originally under a not-for-commercial purposes license, then later under the GPLwolf4sdl: Debian copyright file (contrib, stable)Yes, we relicensed it under the gpl years ago.Checked by claude, 2026-10-22 — read README.rst's copy of the license at the pinned commit and both pinned copies of the external statementsCited by: Wolfenstein 3D
John Carmack's notes to the Wolfenstein 3D source release say the game's "ray casting refresh architecture is still reasonably appropriate for the game", and that "a BSP based texture mapper could go faster, but ray casting was a lot simpler to do at the time". wolf3d/release-notes
About: Wolfenstein 3D Raycasting
DeveloperWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/README/RELEASE.TXT#L20-L22The ray casting refresh architecture is still reasonably
appropriate for the game. A BSP based texture mapper could
go faster, but ray casting was a lot simpler to do at the time.Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/README/RELEASE.TXT#L51-L52John Carmack
Technical DirectorChecked by claude, 2026-10-22 — read RELEASE.TXT at the pinned commitCited by: Raycasting
Wolfenstein 3D finds its walls with one ray per column of the view: AsmRefresh steps pixx from 0 up to viewwidth, aiming each ray at the view angle plus pixelangle[pixx], in angles of 3,600 to a turn (FINEANGLES), and CalcProjection sets each column's offset to the arctangent of its whole-pixel distance from the center (scaled by VIEWGLOBAL/viewwidth) over facedist, the focal length plus MINDIST, so the rays cross a flat projection plane at even spacing rather than fanning out at even angles (the last part computed). The two middle columns both get an offset of 0, though the loop's comment says it starts "1/2 pixel over". wolf3d/column-rays
About: Wolfenstein 3D Raycasting
Value: 3600 angles/turn
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_DR_A.ASM#L7FINEANGLES = 3600Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DR_A.ASM#L207-L213pixxloop:
mov ax,SEG finetangent
mov es,ax
mov cx,[midangle] ; center of view area
mov bx,[pixx]
shl bx,1
add cx,[pixelangle+bx] ; delta for this pixelWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DR_A.ASM#L517-L523nextpix:
mov ax,[pixx]
inc ax
mov [pixx],ax
cmp ax,[viewwidth]
jge done
jmp pixxloopWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_MAIN.C#L653-L654 focallength = focal;
facedist = focal+MINDIST;Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_MAIN.C#L674-L681 for (i=0;i<halfview;i++)
{
// start 1/2 pixel over, so viewangle bisects two middle pixels
tang = (long)i*VIEWGLOBAL/viewwidth/facedist;
angle = atan(tang);
intang = angle*radtoint;
pixelangle[halfview-1-i] = intang;
pixelangle[halfview+i] = -intang;Checked by claude, 2026-10-22 — read AsmRefresh's per-pixel setup and its nextpix loop, and CalcProjection's pixelangle table, at the pinned commitCited by: Raycasting, Wolfenstein 3D
Each Wolfenstein 3D ray walks the tile map, 64 by 64 tiles at most (MAPSIZE), one grid line at a time: AsmRefresh alternates between the next vertical and the next horizontal grid line, taking whichever the ray crosses first, and steps by adding a tangent from finetangent (ystep or xstep) to the other coordinate's intercept; at each crossing it tests the tile beyond in tilemap, marking an empty one in spotvis, and the first nonzero tile ends the ray with a call to HitVertWall or HitHorizWall, or the door and pushwall code when the tile's top bit is set. wolf3d/grid-walk
About: Wolfenstein 3D Raycasting
Value: 64 tiles
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_DEF.H#L122#define MAPSIZE 64 // maps are 64*64 maxWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DR_A.ASM#L232-L252entry90:
mov [xtilestep],1 ; xtilestep = 1
mov [ytilestep],-1 ; ytilestep = -1
mov [BYTE cs:horizop],OP_JGE ; patch a jge in
mov [BYTE cs:vertop],OP_JLE ; patch a jle in
mov bx,DEG90-1
sub bx,cx
shl bx,2
mov ax,[es:bx]
mov dx,[es:bx+2]
mov [WORD xstep],ax
mov [WORD xstep+2],dx ; xstep = finetangent[DEG90-1-angle]
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DR_A.ASM#L438-L469vertcheck:
cmp dx,bp
vertop: ; 0x7e = jle (ytilestep==-1)
jle horizentry ; 0x7d = jge (ytilestep==1)
vertentry:
test [BYTE tilemap+si],0ffh ; tilehit = *((byte *)tilemap+xspot);
jnz hitvert
passvert:
mov [BYTE spotvis+si],1 ; *((byte *)spotvis+xspot) = true;
add bx,[xtilestep] ; xtile+=xtilestep
mov ax,[WORD ystep]
add [WORD yintercept],ax ; yintercept += ystep
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DR_A.ASM#L479-L508horizcheck:
cmp cx,bx
horizop: ; 0x7e = jle (xtilestep==-1)
jle vertentry ; 0x7d = jge (xtilestep==1)
horizentry:
test [BYTE tilemap+di],0ffh ; tilehit = *((byte *)tilemap+yspot);
jnz hithoriz
passhoriz:
mov [BYTE spotvis+di],1 ; *((byte *)spotvis+yspot) = true;
add bp,[ytilestep] ; ytile+=ytilestep
mov ax,[WORD xstep]
add [WORD xintercept],ax ; xintercept += xstep
…Checked by claude, 2026-10-22 — read the 0-89 degree setup and the vertcheck and horizcheck loops with their hit branches at the pinned commit; the other three quadrants set the same variables with other signsCited by: Raycasting, Wolfenstein 3D
Wolfenstein 3D sizes each wall column by the hit point's distance along the facing, not along the ray: CalcHeight takes the hit point's offset from the view point, which WallRefresh sets focallength behind the player, projects it onto the view direction with viewcos and viewsin (nx = gxt-gyt), raises it to at least mindist, and divides heightnumerator by nx>>8, which the code's comment calls the "perspective ratio". Measuring along the facing is what keeps a flat wall straight on screen instead of bowed (fisheye), the atlas's reading. wolf3d/wall-height
About: Wolfenstein 3D Raycasting
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_DRAW.C#L366-L382 gx = xintercept-viewx;
gxt = FixedByFrac(gx,viewcos);
gy = yintercept-viewy;
gyt = FixedByFrac(gy,viewsin);
nx = gxt-gyt;
//
// calculate perspective ratio (heightnumerator/(nx>>8))
//
if (nx<mindist)
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DRAW.C#L488 wallheight[pixx] = CalcHeight();Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DRAW.C#L1307-L1308 viewx = player->x - FixedByFrac(focallength,viewcos);
viewy = player->y + FixedByFrac(focallength,viewsin);Checked by claude, 2026-10-22 — read CalcHeight, its call in HitVertWall, and the view-point setup in WallRefresh at the pinned commitCited by: Raycasting, Wolfenstein 3D
A Wolfenstein 3D gun shot (GunAttack) picks a target instead of tracing a bullet's path: it takes the nearest visible shootable actor within shootdelta (a tenth of the view's width) of the screen's center column and hits it if CheckLine returns true, which its header comment describes as "a straight line between the player and ob is unobstructed"; as written, the loop's second pass looks only for actors nearer than that one, so a blocked line is a miss (computed). The damage is a roll of US_RndT (0 to 255) by the larger of the x and y tile distances: under 2 tiles the roll / 4 (0 to 63), under 4 the roll / 6 (0 to 42), and farther a miss when a first roll / 12 is below the distance, otherwise a second roll / 6. wolf3d/gun-attack
About: Wolfenstein 3D Hitscan
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_AGENT.C#L1196-L1242 while (1)
{
oldclosest = closest;
for (check=ob->next ; check ; check=check->next)
if ( (check->flags & FL_SHOOTABLE)
&& (check->flags & FL_VISABLE)
&& abs (check->viewx-centerx) < shootdelta
)
{
if (check->transx < viewdist)
{
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_MAIN.C#L1283 shootdelta = viewwidth/10;Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_STATE.C#L1030-L1032= CheckLine
=
= Returns true if a straight line between the player and ob is unobstructedWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/ID_US_A.ASM#L80-L95; int US_RndT (void)
; Return a random # between 0-255
…
mov al,[es:rndtable+BX]
xor ah,ahChecked by claude, 2026-10-25 — read GunAttack's target loop and damage branches, shootdelta's setting, CheckLine's header, and US_RndT, which returns one table byte with AH cleared, at the pinned commit; worked through the loop's second pass by handCited by: Damage formula, Hitscan, Wolfenstein 3D
An enemy's shot in Wolfenstein 3D (T_Shoot) traces no bullet either: when the shooter's area connects to the player's (areabyplayer) and CheckLine finds a clear line, it hits if a roll of US_RndT is below a chance of 256 less 16 per tile of distance, or less 8 per tile when the shooter isn't visible on the player's screen (FL_VISABLE), starting from 160 instead of 256 when the player's thrust this frame (thrustspeed) reached RUNSPEED (6,000); SS guards and bossobj bosses count two-thirds of the distance. A hit deals the roll >> 2 (0 to 63) under 2 tiles, >> 3 (0 to 31) under 4, and >> 4 (0 to 15) farther. wolf3d/enemy-shot
About: Wolfenstein 3D Hitscan
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_ACT2.C#L3449-L3490 hitchance = 128;
if (!areabyplayer[ob->areanumber])
return;
if (!CheckLine (ob)) // player is behind a wall
return;
dx = abs(ob->tilex - player->tilex);
dy = abs(ob->tiley - player->tiley);
dist = dx>dy ? dx:dy;
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DEF.H#L75#define RUNSPEED 6000Checked by claude, 2026-10-22 — read T_Shoot and the RUNSPEED define at the pinned commitCited by: Damage formula, Hitscan, Wolfenstein 3D
Wolfenstein 3D keeps no velocity for the player: each frame ControlMovement zeroes thrustspeed, and Thrust moves the player straight through ClipMove by the frame's control value times MOVESCALE (150), or BACKMOVESCALE (100) backward. The keyboard sets that value to 35 a tic walking (BASEMOVE) or 70 running (RUNMOVE), times the frame's tics, so a walk moves 5,250 and a run 10,500 units a tic, with 65,536 units to a tile (TILEGLOBAL); Thrust clamps each move to MINDIST*2-1 (45,055), so those rates hold on frames of at most 8 tics walking or 4 running, and longer frames move less a tic. At the 70 tics a second of TickBase's comment a run is about 11.2 tiles a second (computed). wolf3d/move-speed
About: Wolfenstein 3D Running
Value: 10500 units/tic
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_AGENT.C#L18-L19#define MOVESCALE 150l
#define BACKMOVESCALE 100lWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L156 thrustspeed = 0;Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L205-L214 if (controly < 0)
{
Thrust (ob->angle,-controly*MOVESCALE); // move forwards
}
else if (controly > 0)
{
angle = ob->angle + ANGLES/2;
if (angle >= ANGLES)
angle -= ANGLES;
Thrust (angle,controly*BACKMOVESCALE); // move backwardsWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L943-L953 thrustspeed += speed;
//
// moving bounds speed
//
if (speed >= MINDIST*2)
speed = MINDIST*2-1;
xmove = FixedByFrac(speed,costable[angle]);
ymove = -FixedByFrac(speed,sintable[angle]);
ClipMove(player,xmove,ymove);Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DEF.H#L115#define MINDIST (0x5800l)Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_PLAY.C#L246-L247#define BASEMOVE 35
#define RUNMOVE 70Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_PLAY.C#L343-L357 if (buttonstate[bt_run])
{
if (Keyboard[dirscan[di_north]])
controly -= RUNMOVE*tics;
if (Keyboard[dirscan[di_south]])
controly += RUNMOVE*tics;
if (Keyboard[dirscan[di_west]])
controlx -= RUNMOVE*tics;
if (Keyboard[dirscan[di_east]])
controlx += RUNMOVE*tics;
}
else
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DEF.H#L97-L98#define GLOBAL1 (1l<<16)
#define TILEGLOBAL GLOBAL1Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/ID_SD.H#L17#define TickBase 70 // 70Hz per tick - used as a base for timer 0Checked by claude, 2026-10-22 — read ControlMovement, Thrust, PollKeyboardMove, and the defines at the pinned commit; the speeds are worked out from themCited by: Running, Wolfenstein 3D
Because the player's thrust scales with the frame's tics, a Wolfenstein 3D player who only walks straight forward with the keyboard (5,250 units a tic) counts as running for T_Shoot's lower hit chance (thrustspeed at least RUNSPEED, 6,000) on any frame that spans 2 or more tics, and only a 1-tic frame leaves that walk below it; thrustspeed sums every Thrust call, so a walk that also strafes (5,250 + 5,250) passes it even in 1 tic (computed). wolf3d/dodge-by-tics
About: Wolfenstein 3D Hitscan
Value: 2 tics
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_PLAY.C#L354-L357 else
{
if (Keyboard[dirscan[di_north]])
controly -= BASEMOVE*tics;Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L205-L207 if (controly < 0)
{
Thrust (ob->angle,-controly*MOVESCALE); // move forwardsWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L156 thrustspeed = 0;Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L164-L175 if (buttonstate[bt_strafe])
{
//
// strafing
//
//
if (controlx > 0)
{
angle = ob->angle - ANGLES/4;
if (angle < 0)
angle += ANGLES;
Thrust (angle,controlx*MOVESCALE); // move to leftWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L943 thrustspeed += speed;Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_ACT2.C#L3464 if (thrustspeed >= RUNSPEED)Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_DEF.H#L75#define RUNSPEED 6000Checked by claude, 2026-10-22 — worked out from PollKeyboardMove's walk value, the MOVESCALE thrust, and T_Shoot's RUNSPEED test at the pinned commitCited by: Wolfenstein 3D
With the strafe button held, Wolfenstein 3D's side move is a second Thrust at 90° to the facing, and PollControls caps the side and forward control values separately at 100 a tic, so running forward and sideways on the keyboard (70 each) moves √2 ≈ 1.41 times as fast as running forward alone, about 14,849 units a tic (computed). wolf3d/strafe-running
About: Wolfenstein 3D Strafe-running
Value: 1.41 ×
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/WL_AGENT.C#L164-L183 if (buttonstate[bt_strafe])
{
//
// strafing
//
//
if (controlx > 0)
{
angle = ob->angle - ANGLES/4;
if (angle < 0)
angle += ANGLES;
Thrust (angle,controlx*MOVESCALE); // move to left
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_AGENT.C#L205-L207 if (controly < 0)
{
Thrust (ob->angle,-controly*MOVESCALE); // move forwardsWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_PLAY.C#L343-L353 if (buttonstate[bt_run])
{
if (Keyboard[dirscan[di_north]])
controly -= RUNMOVE*tics;
if (Keyboard[dirscan[di_south]])
controly += RUNMOVE*tics;
if (Keyboard[dirscan[di_west]])
controlx -= RUNMOVE*tics;
if (Keyboard[dirscan[di_east]])
controlx += RUNMOVE*tics;
}Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_PLAY.C#L540-L548 max = 100*tics;
min = -max;
if (controlx > max)
controlx = max;
else if (controlx < min)
controlx = min;
if (controly > max)
controly = max;Checked by claude, 2026-10-22 — read the strafe and forward branches of ControlMovement and PollControls' clamp at the pinned commit; the ratio is worked out from themCited by: Strafe-running, Wolfenstein 3D
Wolfenstein 3D's random numbers come from rndtable, a fixed table of 256 bytes: US_RndT adds 1 to one index, wraps it at 256, and returns that entry, and the file's comment calls it "John Carmack's table driven pseudo-random number generator". SetupGameLevel sets the index to 0 for each level of a demo being played or recorded, and otherwise to the low byte of DX from DOS's get-time call (int 21h, function 2Ch), the hundredths of a second, 0 to 99 (the atlas's reading of the DOS call). wolf3d/rng
About: Wolfenstein 3D Random number generator
Value: 256 entries
CodeWolfenstein 3D: the source release (id-Software/wolf3d) ·WOLFSRC/ID_US_A.ASM#L4-L6; Assembly portion of the User Mgr. This is just John Carmack's table
; driven pseudo-random number generator, and we put it in the User Mgr
; because we couldn't figure out where it should goWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/ID_US_A.ASM#L19rndtable db 0, 8, 109, 220, 222, 241, 149, 107, 75, 248, 254, 140, 16, 66Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/ID_US_A.ASM#L60-L73 mov ax,[randomize]
or ax,ax
jne @@timeit ;if randomize is true, really random
mov dx,0 ;set to a definite value
jmp @@setit
@@timeit:
mov ah,2ch
int 21h ;GetSystemTime
and dx,0ffh
…Wolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/ID_US_A.ASM#L85-L96PROC US_RndT
public US_RndT
mov ax,SEG rndtable
mov es,ax
mov bx,[es:rndindex]
inc bx
and bx,0ffh
mov [es:rndindex],bx
mov al,[es:rndtable+BX]
xor ah,ah
retWolfenstein 3D: the source release (id-Software/wolf3d) · WOLFSRC/WL_GAME.C#L641-L644
if (demoplayback || demorecord)
US_InitRndT (false);
elseChecked by claude, 2026-10-22 — read US_InitRndT, US_RndT, the table, and its call in SetupGameLevel at the pinned commitCited by: Wolfenstein 3D