Probability is what controls all of the 'random' events in Keen. This page details how probability and probability patches work in Keen games. It should be noted from the outset that the Keen games are only 'pseudorandom'; they are ultimately predictable if everything is known about the game and can be repeated flawlessly if the same setup is used.
Events controlled by probability
In general any event that appears to happen occasionally or unpredictably is controlled by probability. This is mostly enemy behaviors, such as when a given enemy will attack. Each enemy sprite is tracked separately from all others, so they will not all attack (or do other things) at the same time.
Code mechanism
In code a 'random' decision is made by requesting a (pseudo)random number from the game and comparing it to a fixed value in the code. There are varying setups but usually if the returned value is larger then something will be done, otherwise nothing will. The possible values the game can return range from 0-255 (All the values a single byte can take.) Given that the following table gives rough probabilities for given comparison values:
Value Probability if action
$00 0%
$12 1%
$28 5%
$39 10%
$40 12.5%
$51 20%
$5B 25%
$63 30%
$68 33%
$72 40%
$80 50%
$8C 60%
$93 66%
$97 70%
$9D 75%
$A2 80%
$A9 87.5%
$AC 90%
$B0 95%
$B4 99%
$FF 100%
Probability patches
A typical probability patch is listed below, it gives the probability of a Keen 4 Blue Bird landing when it is next to the ground Keen is standing on:
Patch: Keen 4 |
%patch $10489 $0080W $73 |
The variable checked against here is the value in blue ($0080W). As can be seen from the previous section, this represents a possibility of 50% each time the code is run. Depending on how often this is, the behavior can be a simple choice, an increasing chance over time or near-instant action. If the value is set to zero, the bird never lands. If it is set to $FF then it always lands as soon as possible. Most check values are $80, though there are some exceptions.
The lookup table
Rather than creating numbers on the fly the game uses a static table 256 bytes long containing numbers between 0 and 255 in a fixed, scrambled order. There is an index to this table which starts at zero. Each call to the function P_Random advances the index by one, wrapping around to zero after 255, and returns the table entry at that index. This means that nothing in the game is truly random and if a single enemy is watched for long enough it will act in a repeated and predictable manner.
Although the table is 256 bytes long, it does not contain all of the numbers between 0 and 255 inclusive. For example, 0 appears twice and 1 does not appear at all; 145 appears five times, more than any other number. Thus the values are not uniformly distributed, but in fact they are nearly so. The mean value is 128.852, whereas it would be 127.500 if all values were equally likely. All of this suggests that the table was generated using a conventional pseudorandom number generator of reasonable quality.
Apparent randomness in gameplay is due to the interactions of the player; unless a precisely identical path is taken in each game they will quickly desynchronize. Differing behaviors at differing times will result in differing decisions by the player, further altering a game session.
Resetting the table index
Whenever a new game or demo is started the game 'resets' its table index back to zero. This is so that each time a demo plays it will play identically. It will be noticed by experienced players that when recording demos the game is far more predictable, as this reset happens when recording a demo also, to ensure recording and playback are synchronized.
The table in games
The same table is used in all Keen games, as well as in other Id Software games such as Hovertank and Doom. The table has a location in code, in Keen Vorticons this is a location in the data segment, in Keen Galaxy and Dreams it has its own segment and is located two bytes in.
Altering the values found in the table will alter the global (pseudo)randomness in the game.
Patch: Keen 1 |
%patch $C0DD $5159W
%patch $181A9 $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |
Patch: Keen 2 |
%patch $B7F5 $5135W
%patch $1C8B5 $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |
Patch: Keen 3 |
%patch $CB53 $5385W
%patch $1EBA5 $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |
Patch: Keen 4 |
%patch $1D04B $1ED3RW
%patch $1ED32 $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |
Patch: Keen 5 |
%patch $1DFE7 $1FCDRW
%patch $1FCD2 $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |
Patch: Keen 6 |
%patch $1CF65 $1EC4RW
%patch $1EC42 $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |
Patch: Keen Dreams |
%patch $16C75 $5C8CW
%patch $296FC $00 $08 $6D $DC $DE $F1 $95 $6B $4B $F8 $FE $8C $10 $42 $4A $15
$D3 $2F $50 $F2 $9A $1B $CD $80 $A1 $59 $4D $24 $5F $6E $55 $30
$D4 $8C $D3 $F9 $16 $4F $C8 $32 $1C $BC $34 $8C $CA $78 $44 $91
$3E $46 $B8 $BE $5B $C5 $98 $E0 $95 $68 $19 $B2 $FC $B6 $CA $B6
$8D $C5 $04 $51 $B5 $F2 $91 $2A $27 $E3 $9C $C6 $E1 $C1 $DB $5D
$7A $AF $F9 $00 $AF $8F $46 $EF $2E $F6 $A3 $35 $A3 $6D $A8 $87
$02 $EB $19 $5C $14 $91 $8A $4D $45 $A6 $4E $B0 $AD $D4 $A6 $71
$5E $A1 $29 $32 $EF $31 $6F $A4 $46 $3C $02 $25 $AB $4B $88 $9C
$0B $38 $2A $92 $8A $E5 $49 $92 $4D $3D $62 $C4 $87 $6A $3F $C5
$C3 $56 $60 $CB $71 $65 $AA $F7 $B5 $71 $50 $FA $6C $07 $FF $ED
$81 $E2 $4F $6B $70 $A6 $67 $F1 $18 $DF $EF $78 $C6 $3A $3C $52
$80 $03 $B8 $42 $8F $E0 $91 $E0 $51 $CE $A3 $2D $3F $5A $A8 $72
$3B $21 $9F $5F $1C $8B $7B $62 $7D $C4 $0F $46 $C2 $FD $36 $0E
$6D $E2 $47 $11 $A1 $5D $BA $57 $F4 $8A $14 $34 $7B $FB $1A $24
$11 $2E $34 $E7 $E8 $4C $1F $DD $54 $25 $D8 $A5 $D4 $6A $C5 $F2
$62 $2B $27 $AF $FE $91 $BE $54 $76 $DE $BB $88 $78 $A3 $EC $F9 |