Public export: private machine paths and host identifiers are replaced with placeholders. Recorded results and numerical weights are unchanged. Embedded source hashes identify the original files; PUBLICATION-MANIFEST.json identifies these public copies.

Experiment 5 · seaquest · original

Built-in Codex tools were disabled. Harness execution is separately permitted only in Experiments 3 and 6. Text below is taken from saved records; it is not a new model run. Reasoning blocks are the summaries actually emitted by the CLI.

Recorded neutral instruction file
Answer the user's request.
t001 · no harness call

Recorded prompt · Raw CLI events · Settings and audit

Message sent to Codex — 18,266 characters
YOUR TASK: write, from scratch, the weights of a policy network that plays this game as well as possible. There is no training: no data, no loss, no gradients, no fine-tuning; you choose every number yourself. You have no tools: no code execution, no calculator, nothing to run. This is a single response and you will get no feedback. First describe your design briefly (the strategy, and what the hidden units compute), then write the edits block.

THE GAME: Seaquest from MinAtar (Young & Tian 2019), on a 10 x 10 grid. The player steers a two-cell submarine (front and back) in all 4 directions and fires bullets from its front. Enemy fish and enemy submarines cross the screen; enemy submarines shoot. Hitting an enemy with a bullet gives +1. Divers can be picked up (up to 6; a bar along the bottom counts them). Oxygen runs down (another bar along the bottom) and is refilled by surfacing at the top row with at least one diver on board (surfacing with fewer than 6 removes one diver; with 6, all are removed and a bonus is paid). The episode ends when the submarine is hit, runs out of oxygen, or surfaces with no diver.
Actions: left, up, right, down move the submarine, fire shoots.

The game's exact implementation (the MinAtar package, version 1.0.15, file minatar/environments/seaquest.py) follows. The environment wrapper calls act(a) with a = 0..5 meaning 'n' (no-op), 'l', 'u', 'r', 'd', 'f' (this file's action_map), and with probability 0.1 it repeats the previous action instead of the new one (sticky actions). The observation the network gets is built from this file's state() as described under THE INPUT.

```python
################################################################################################################
# Authors:                                                                                                     #
# Kenny Young (kjyoung@ualberta.ca)                                                                            #
# Tian Tian (ttian@ualberta.ca)                                                                                #
################################################################################################################
import numpy as np


#####################################################################################################################
# Constants
#
#####################################################################################################################
ramp_interval = 100
max_oxygen = 200
init_spawn_speed = 20
diver_spawn_speed = 30
init_move_interval = 5
shot_cool_down = 5
enemy_shot_interval = 10
enemy_move_interval = 5
diver_move_interval = 5


#####################################################################################################################
# Env
#
# The player controls a submarine consisting of two cells, front and back, to allow direction to be determined. The
# player can also fire bullets from the front of the submarine. Enemies consist of submarines and fish, distinguished
# by the fact that submarines shoot bullets and fish do not. A reward of +1 is given each time an enemy is struck by
# one of the player's bullets, at which point the enemy is also removed. There are also divers which the player can
# move onto to pick up, doing so increments a bar indicated by another channel along the bottom of the screen. The
# player also has a limited supply of oxygen indicated by another bar in another channel. Oxygen degrades over time,
# and is replenished whenever the player moves to the top of the screen as long as the player has at least one rescued
# diver on board. The player can carry a maximum of 6 divers. When surfacing with less than 6, one diver is removed.
# When surfacing with 6, all divers are removed and a reward is given for each active cell in the oxygen bar. Each
# time the player surfaces the difficulty is increased by increasing the spawn rate and movement speed of enemies.
# Termination occurs when the player is hit by an enemy fish, sub or bullet; or when oxygen reached 0; or when the
# player attempts to surface with no rescued divers. Enemy and diver directions are indicated by a trail channel
# active in their previous location to reduce partial observability.
#
#####################################################################################################################
class Env:
    def __init__(self, ramping=True):
        self.channels ={
            'sub_front':0,
            'sub_back':1,
            'friendly_bullet':2,
            'trail':3,
            'enemy_bullet':4,
            'enemy_fish':5,
            'enemy_sub':6,
            'oxygen_guage':7,
            'diver_guage':8,
            'diver':9
        }
        self.action_map = ['n','l','u','r','d','f']
        self.ramping = ramping
        self.random = np.random.RandomState()
        self.reset()

    # Update environment according to agent action
    def act(self, a):
        r = 0
        if(self.terminal):
            return r, self.terminal

        a = self.action_map[a]

        # Spawn enemy if timer is up
        if(self.e_spawn_timer==0):
            self._spawn_enemy()
            self.e_spawn_timer = self.e_spawn_speed

        if(self.d_spawn_timer==0):
            self._spawn_diver()
            self.d_spawn_timer = diver_spawn_speed

        # Resolve player action
        if(a=='f' and self.shot_timer == 0):
            self.f_bullets+=[[self.sub_x, self.sub_y, self.sub_or]]
            self.shot_timer = shot_cool_down
        elif(a=='l'):
            self.sub_x = max(0, self.sub_x-1)
            self.sub_or = False
        elif(a=='r'):
            self.sub_x = min(9, self.sub_x+1)
            self.sub_or = True
        elif(a=='u'):
            self.sub_y = max(0, self.sub_y-1)
        elif(a=='d'):
            self.sub_y = min(8, self.sub_y+1)

        # Update friendly Bullets
        for bullet in reversed(self.f_bullets):
            bullet[0]+=1 if bullet[2] else -1
            if(bullet[0]<0 or bullet[0]>9):
                self.f_bullets.remove(bullet)
            else:
                removed = False
                for x in self.e_fish:
                    if(bullet[0:2]==x[0:2]):
                        self.e_fish.remove(x)
                        self.f_bullets.remove(bullet)
                        r+=1
                        removed = True
                        break
                if(not removed):
                    for x in self.e_subs:
                        if(bullet[0:2]==x[0:2]):
                            self.e_subs.remove(x)
                            self.f_bullets.remove(bullet)
                            r+=1
                            break

        # Update divers
        for diver in reversed(self.divers):
            if(diver[0:2]==[self.sub_x,self.sub_y] and self.diver_count<6):
                self.divers.remove(diver)
                self.diver_count+=1
            else:
                if(diver[3]==0):
                    diver[3]=diver_move_interval
                    diver[0]+=1 if diver[2] else -1
                    if(diver[0]<0 or diver[0]>9):
                        self.divers.remove(diver)
                    elif(diver[0:2]==[self.sub_x,self.sub_y] and self.diver_count<6):
                        self.divers.remove(diver)
                        self.diver_count+=1
                else:
                    diver[3]-=1

        # Update enemy subs
        for sub in reversed(self.e_subs):
            if(sub[0:2]==[self.sub_x,self.sub_y]):
                self.terminal = True
            if(sub[3]==0):
                sub[3]=self.move_speed
                sub[0]+=1 if sub[2] else -1
                if(sub[0]<0 or sub[0]>9):
                    self.e_subs.remove(sub)
                elif(sub[0:2]==[self.sub_x,self.sub_y]):
                    self.terminal = True
                else:
                    for x in self.f_bullets:
                        if(sub[0:2]==x[0:2]):
                            self.e_subs.remove(sub)
                            self.f_bullets.remove(x)
                            r+=1
                            break
            else:
                sub[3]-=1
            if(sub[4]==0):
                sub[4]=enemy_shot_interval
                self.e_bullets+=[[sub[0] if sub[2] else sub[0], sub[1], sub[2]]]
            else:
                sub[4]-=1

        # Update enemy bullets
        for bullet in reversed(self.e_bullets):
            if(bullet[0:2]==[self.sub_x,self.sub_y]):
                self.terminal = True
            bullet[0]+=1 if bullet[2] else -1
            if(bullet[0]<0 or bullet[0]>9):
                self.e_bullets.remove(bullet)
            else:
                if(bullet[0:2]==[self.sub_x,self.sub_y]):
                    self.terminal = True

        # Update enemy fish
        for fish in reversed(self.e_fish):
            if(fish[0:2]==[self.sub_x,self.sub_y]):
                self.terminal = True
            if(fish[3]==0):
                fish[3]=self.move_speed
                fish[0]+=1 if fish[2] else -1
                if(fish[0]<0 or fish[0]>9):
                    self.e_fish.remove(fish)
                elif(fish[0:2]==[self.sub_x,self.sub_y]):
                    self.terminal = True
                else:
                    for x in self.f_bullets:
                        if(fish[0:2]==x[0:2]):
                            self.e_fish.remove(fish)
                            self.f_bullets.remove(x)
                            r+=1
                            break
            else:
                fish[3]-=1

        # Update various timers
        self.e_spawn_timer -= self.e_spawn_timer>0
        self.d_spawn_timer -= self.d_spawn_timer>0
        self.shot_timer -= self.shot_timer>0
        if(self.oxygen<=0):
            self.terminal = True
        if(self.sub_y>0):
            self.oxygen-=1
            self.surface = False
        else:
            if(not self.surface):
                if(self.diver_count == 0):
                    self.terminal = True
                else:
                    r+=self._surface()
        return r, self.terminal

    # Called when player hits surface (top row) if they have no divers, this ends the game,
    # if they have 6 divers this gives reward proportional to the remaining oxygen and restores full oxygen
    # otherwise this reduces the number of divers and restores full oxygen
    def _surface(self):
        self.surface = True
        if(self.diver_count == 6):
            self.diver_count = 0
            r = self.oxygen*10//max_oxygen
        else:
            r = 0
        self.oxygen = max_oxygen
        self.diver_count -= 1
        if self.ramping and (self.e_spawn_speed>1 or self.move_speed>2):
            if(self.move_speed>2 and self.ramp_index%2):
                    self.move_speed-=1
            if(self.e_spawn_speed>1):
                    self.e_spawn_speed-=1
            self.ramp_index+=1
        return r

    # Spawn an enemy fish or submarine in random row and random direction,
    # if the resulting row and direction would lead to a collision, do nothing instead
    def _spawn_enemy(self):
        lr = self.random.rand() < 1/2
        is_sub = self.random.rand() < 1/3
        x = 0 if lr else 9
        y = self.random.randint(low=1, high=9)

        # Do not spawn in same row an opposite direction as existing
        if(any([z[1]==y and z[2]!=lr for z in self.e_subs+self.e_fish])):
            return
        if(is_sub):
            self.e_subs+=[[x,y,lr,self.move_speed,enemy_shot_interval]]
        else:
            self.e_fish+=[[x,y,lr,self.move_speed]]

    # Spawn a diver in random row with random direction
    def _spawn_diver(self):
        lr = self.random.rand() < 1/2
        x = 0 if lr else 9
        y = self.random.randint(low=1, high=9)
        self.divers+=[[x,y,lr,diver_move_interval]]

    # Query the current level of the difficulty ramp, could be used as additional input to agent for example
    def difficulty_ramp(self):
        return self.ramp_index

    # Process the game-state into the 10x10xn state provided to the agent and return
    def state(self):
        state = np.zeros((10,10,len(self.channels)),dtype=bool)
        state[self.sub_y,self.sub_x,self.channels['sub_front']] = 1
        back_x = self.sub_x-1 if self.sub_or else self.sub_x+1
        state[self.sub_y,back_x,self.channels['sub_back']] = 1
        state[9,0:max(0,self.oxygen)*10//max_oxygen, self.channels['oxygen_guage']] = 1
        state[9,9-self.diver_count:9, self.channels['diver_guage']] = 1
        for bullet in self.f_bullets:
            state[bullet[1],bullet[0], self.channels['friendly_bullet']] = 1
        for bullet in self.e_bullets:
            state[bullet[1],bullet[0], self.channels['enemy_bullet']] = 1
        for fish in self.e_fish:
            state[fish[1],fish[0], self.channels['enemy_fish']] = 1
            back_x = fish[0]-1 if fish[2] else fish[0]+1
            if(back_x>=0 and back_x<=9):
                state[fish[1],back_x, self.channels['trail']] = 1
        for sub in self.e_subs:
            state[sub[1],sub[0], self.channels['enemy_sub']] = 1
            back_x = sub[0]-1 if sub[2] else sub[0]+1
            if(back_x>=0 and back_x<=9):
                state[sub[1],back_x, self.channels['trail']] = 1
        for diver in self.divers:
            state[diver[1],diver[0], self.channels['diver']] = 1
            back_x = diver[0]-1 if diver[2] else diver[0]+1
            if(back_x>=0 and back_x<=9):
                state[diver[1],back_x, self.channels['trail']] = 1

        return state

    # Reset to start state for new episode
    def reset(self):
        self.oxygen = max_oxygen
        self.diver_count = 0
        self.sub_x = 5
        self.sub_y = 0
        # 0=left, 1=right
        self.sub_or = False
        self.f_bullets = []
        self.e_bullets = []
        self.e_fish = []
        self.e_subs = []
        self.divers = []
        self.e_spawn_speed = init_spawn_speed
        self.e_spawn_timer = self.e_spawn_speed
        self.d_spawn_timer = diver_spawn_speed
        self.move_speed = init_move_interval
        self.ramp_index = 0
        self.shot_timer = 0
        self.surface = True
        self.terminal = False

    # Dimensionality of the game-state (10x10xn)
    def state_shape(self):
        return [10,10,len(self.channels)]

    # Subset of actions that actually have a unique impact in this environment
    def minimal_action_set(self):
        minimal_actions = ['n','l','u','r','d','f']
        return [self.action_map.index(x) for x in minimal_actions]

```

THE INPUT (600 numbers, each 0 or 1): the 10 x 10 grid (rows 0 top to 9 bottom, columns 0 left to 9 right) with 6 channels. Input number i = (row * 10 + column) * 6 + channel; for example input 0 is (row 0, column 0, channel 0), input 6 is (row 0, column 1, channel 0) and input 599 is (row 9, column 9, channel 5). In this game:
  channel 0 (player): the submarine (front and back cells)
  channel 1 (danger): enemy fish, enemy submarines and enemy bullets
  channel 2 (reward): enemy fish, enemy submarines and divers
  channel 3 (projectile): the player's bullets
  channel 4 (trail): the cell just behind each enemy and diver, and the submarine's back cell
  channel 5 (gauge): the oxygen bar and the diver bar along the bottom row
THE OUTPUT (6 numbers, logits) for the actions 0 no-op, 1 left, 2 up, 3 right, 4 down, 5 fire; the action is sampled from the softmax of the logits. With probability 0.1 the game repeats the previous action instead (sticky actions).
How the 6 channels are built from the game's own channels (state() in the source): channel 0 (player) <- sub_front, sub_back; channel 1 (danger) <- enemy_fish, enemy_sub, enemy_bullet; channel 2 (reward) <- enemy_fish, enemy_sub, diver; channel 3 (projectile) <- friendly_bullet; channel 4 (trail) <- trail, sub_back; channel 5 (gauge) <- oxygen_guage, diver_guage. A cell is 1 in a channel if any of its source channels is 1.

THE NETWORK (the same architecture as the reinforcement-learning networks it will be compared with): a multilayer perceptron with 600 inputs, two hidden layers of 32 units with tanh activations, and 6 outputs; 20,486 parameters:
  h1 = tanh(x @ W1 + b1)          W1: 600 x 32, b1: 32
  h2 = tanh(h1 @ W2 + b2)         W2: 32 x 32,  b2: 32
  logits = h2 @ W3 + b3           W3: 32 x 6,  b3: 6
Row i of W1 holds the weights from input i to the 32 first-layer units; column j of a weight matrix belongs to unit j of the next layer. EVERY WEIGHT STARTS AT 0; you set the weights you need.

HOW YOUR NETWORK IS SCORED: its mean score per episode over 1,000 episodes, each action sampled from the softmax of the logits (with the sticky actions above); an episode also stops after 10,000 steps. It is compared with networks of the same architecture trained by reinforcement learning on this game.

HOW TO WRITE THE WEIGHTS (numbers only; nothing is run). Write a code block whose opening line is three backticks followed by the word edits, one statement per line ('#' starts a comment; a long list may continue over the next lines). Tensors: W1, b1, W2, b2, W3, b3.

```edits
W1[12, 0] = 2.5                     # one entry: row 12, column 0
W1[0:6, 3] = [1, 0, -1, 0, 2, 0]    # explicit values along a range (as many values as entries)
b1[0:4] = -1                        # fill a range (a:b is half-open; ':' alone = the whole axis)
W1[3:600:60, 0] = [0, 0, 0, 0, 0, 0, 0, 0, 1, 1]   # column 0 of channel 3, rows 0..9 of the grid -> unit 0
W2[0:2, 0:3] = [[1, -1, 0.5], [0, 2, 0]]   # a 2-D list for a 2-D block (here 2 x 3)
W3[:, 2] *= 2                       # scale (also += and -=)
```
Ranges: a:b is half-open, a:b:s takes every s-th index. Input index i = (row * 10 + column) * 6 + channel. Useful strided ranges: all 10 cells of column c in channel ch are rows c*6+ch : 600 : 60 of W1; all 10 cells of row r in channel ch are rows r*60+ch : r*60+60 : 6.
Statements apply in order; a later statement overwrites an earlier one. Only the LAST edits block of your reply is read; a statement that cannot be read is skipped (the others still apply). Values: plain decimal numbers (|v| <= 1e6).
CLI notice/error (verbatim)
Code Mode is unavailable because code-mode host is disabled. Code mode will fail closed; enable `features.code_mode_host` and install `codex-code-mode-host`.
Recorded reasoning summary
**Designing the 32x2 controller**
**Encoding gauge triggers**
**Tuning ascent safeguards**
Recorded reasoning summary
**Tuning initial dive rules**
**Designing 32 hidden features**
**Refining target-row encoding**
Recorded reasoning summary
**Testing spatial comparison encoding**
**Refining row-based target encoding**
**Tuning row-target encoding**
Recorded reasoning summary
**Choosing a diver strategy**
**Adding row hazard signals**
**Preparing left-facing camp**
Recorded reasoning summary
**Testing orientation detection**
**Testing fixed x5 strategy**
**Mapping nearby row hazards**
Recorded reasoning summary
**Integrating target into gates**
**Tuning row-value gates**
**Checking row-value scaling**
Recorded reasoning summary
**Tuning ascent gating**
**Refining emergency ascent gating**
**Weighting row danger scores**
Recorded reasoning summary
**Targeting the retreating enemy**
**Designing row-action units**
**Resolving row8 action count**
Recorded reasoning summary
**Mapping gated unit assignments**
Recorded reasoning summary
**Tuning safer downward transitions**
**Tuning exponential gradients**
Recorded reasoning summary
**Tuning target attraction**
**Refining hazard weights**
Recorded reasoning summary
**Firing at the enemy**
**Dodging incoming bullets**
**Shooting the enemy**
Recorded reasoning summary
**Setting reward weights**
**Designing robust row features**
**Repurposing row thresholds**
Recorded reasoning summary
**Designing the row gate**
**Tuning the row gate**
Recorded reasoning summary
**Refining enemy isolation**
**Tuning hazard detection**
Recorded reasoning summary
**Tuning potential weights**
**Tuning hazard weights**
Recorded reasoning summary
**Refining activation coefficients**
**Tuning action-value weights**
Recorded reasoning summary
**Firing at diver**
**Tuning emergency ascent**
Recorded reasoning summary
**Choosing the next row**
**Tuning gated up-action logits**
Recorded reasoning summary
**Adding boundary guard unit**
**Tuning row-one exit guard**
Recorded reasoning summary
**Adjusting ascent scoring**
**Configuring ascent weights**
Recorded reasoning summary
**Calculating hazard weights**
**Evaluating h2 assignments**
Recorded reasoning summary
**Setting h2 scoring weights**
**Adjusting h2 offsets**
Recorded reasoning summary
**Computing row sums**
Recorded reasoning summary
**Calculating row values**
**Assembling bias arrays**
Recorded reasoning summary
**Configuring movement weights**
**Evaluating hazard gating**
Recorded reasoning summary
**Dodging the c8 bullet**
**Shifting from adjacent enemy**
Recorded reasoning summary
**Configuring action-output weights**
**Tuning fire-output weights**
Recorded reasoning summary
**Designing fixed-column plan**
**Constructing W2 matrix blocks**
Recorded reasoning summary
**Preparing W2 matrix**
Recorded reasoning summary
**Checking layer weight assignments**
**Checking target-D overlap**
Recorded reasoning summary
**Refining enemy-row targeting**
**Reweighting row-one divers**
Recorded reasoning summary
**Refining unit allocation**
**Updating bias sums**
Recorded reasoning summary
**Checking gate-weight setup**
**Checking boundary guard**
Recorded reasoning summary
**Correcting row settings**
Recorded reasoning summary
**Tuning descent hazard lookahead**
**Tuning hazard lookahead**
Recorded reasoning summary
**Tuning hazard penalties**
**Updating hazard weights**
Recorded reasoning summary
**Validating hazard lookahead**
**Checking output saturation**
Recorded reasoning summary
**Checking matrix bias calculation**

Codex reply

The policy stays at the starting column, firing left while changing rows to intercept divers and attack enemies. Hidden units detect player position, diver rows, shooting opportunities, nearby hazards, and low oxygen with a rescued diver. The second layer scores candidate rows, anticipates sticky movement, and guards against surfacing empty.

```edits
# First layer: player row indicators.
b1[0:9] = -6
W1[0:60:6, 0] = 6
W1[60:120:6, 1] = 6
W1[120:180:6, 2] = 6
W1[180:240:6, 3] = 6
W1[240:300:6, 4] = 6
W1[300:360:6, 5] = 6
W1[360:420:6, 6] = 6
W1[420:480:6, 7] = 6
W1[480:540:6, 8] = 6

# Diver presence in rows 2 through 8.
b1[9:16] = -4
W1[122:180:6, 9] = 8
W1[121:180:6, 9] = -8
W1[182:240:6, 10] = 8
W1[181:240:6, 10] = -8
W1[242:300:6, 11] = 8
W1[241:300:6, 11] = -8
W1[302:360:6, 12] = 8
W1[301:360:6, 12] = -8
W1[362:420:6, 13] = 8
W1[361:420:6, 13] = -8
W1[422:480:6, 14] = 8
W1[421:480:6, 14] = -8
W1[482:540:6, 15] = 8
W1[481:540:6, 15] = -8

# Collision risk near the fixed player column.
b1[16:32] = -3
W1[61:120:6, 16] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[62:120:6, 16] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[121:180:6, 17] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[122:180:6, 17] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[181:240:6, 18] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[182:240:6, 18] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[241:300:6, 19] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[242:300:6, 19] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[301:360:6, 20] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[302:360:6, 20] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[361:420:6, 21] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[362:420:6, 21] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[421:480:6, 22] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[422:480:6, 22] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]
W1[481:540:6, 23] = [0, 0, 2, 4, 7, 7, 7, 5, 2, 0]
W1[482:540:6, 23] = [0, 0, -1.8, -3.6, -1, 0, -1, -3, -1.8, 0]

# Surface request: oxygen below 60 and at least one diver.
W1[557, 24] = -6
W1[593, 24] = 6

# Left-side shooting opportunities in rows 2 through 8.
W1[121:144:6, 25] = 6
W1[181:204:6, 26] = 6
W1[241:264:6, 27] = 6
W1[301:324:6, 28] = 6
W1[361:384:6, 29] = 6
W1[421:444:6, 30] = 6
W1[481:504:6, 31] = 6

# Second layer: fire candidate gated by current row.
W2[1, 0] = 10
W2[2, 1] = 10
W2[3, 2] = 10
W2[4, 3] = 10
W2[5, 4] = 10
W2[6, 5] = 10
W2[7, 6] = 10
W2[8, 7] = 10

# Up candidates.
W2[2, 8] = 10
W2[3, 9] = 10
W2[4, 10] = 10
W2[5, 11] = 10
W2[6, 12] = 10
W2[7, 13] = 10
W2[8, 14] = 10
W2[1, 15] = 6

# Down candidates.
W2[0, 16] = 10
W2[1, 17] = 10
W2[2, 18] = 10
W2[3, 19] = 10
W2[4, 20] = 10
W2[5, 21] = 10
W2[6, 22] = 10
W2[7, 23] = 10

# Diver attraction for fire candidates.
W2[9:16, 0:8] = [
[0.45, 0.6, 0.45, 0.34, 0.255, 0.19, 0.145, 0.11],
[0.34, 0.45, 0.6, 0.45, 0.34, 0.255, 0.19, 0.145],
[0.255, 0.34, 0.45, 0.6, 0.45, 0.34, 0.255, 0.19],
[0.19, 0.255, 0.34, 0.45, 0.6, 0.45, 0.34, 0.255],
[0.145, 0.19, 0.255, 0.34, 0.45, 0.6, 0.45, 0.34],
[0.11, 0.145, 0.19, 0.255, 0.34, 0.45, 0.6, 0.45],
[0.08, 0.11, 0.145, 0.19, 0.255, 0.34, 0.45, 0.6]
]

# Diver attraction for up candidates.
W2[9:16, 8:15] = [
[0.45, 0.6, 0.45, 0.34, 0.255, 0.19, 0.145],
[0.34, 0.45, 0.6, 0.45, 0.34, 0.255, 0.19],
[0.255, 0.34, 0.45, 0.6, 0.45, 0.34, 0.255],
[0.19, 0.255, 0.34, 0.45, 0.6, 0.45, 0.34],
[0.145, 0.19, 0.255, 0.34, 0.45, 0.6, 0.45],
[0.11, 0.145, 0.19, 0.255, 0.34, 0.45, 0.6],
[0.08, 0.11, 0.145, 0.19, 0.255, 0.34, 0.45]
]

# Diver attraction for down candidates.
W2[9:16, 16:24] = [
[0.45, 0.6, 0.45, 0.34, 0.255, 0.19, 0.145, 0.11],
[0.34, 0.45, 0.6, 0.45, 0.34, 0.255, 0.19, 0.145],
[0.255, 0.34, 0.45, 0.6, 0.45, 0.34, 0.255, 0.19],
[0.19, 0.255, 0.34, 0.45, 0.6, 0.45, 0.34, 0.255],
[0.145, 0.19, 0.255, 0.34, 0.45, 0.6, 0.45, 0.34],
[0.11, 0.145, 0.19, 0.255, 0.34, 0.45, 0.6, 0.45],
[0.08, 0.11, 0.145, 0.19, 0.255, 0.34, 0.45, 0.6]
]

# Shooting opportunity attraction for fire candidates.
W2[25:32, 0:8] = [
[0.12, 0.35, 0.12, 0.04, 0.01, 0, 0, 0],
[0.04, 0.12, 0.35, 0.12, 0.04, 0.01, 0, 0],
[0.01, 0.04, 0.12, 0.35, 0.12, 0.04, 0.01, 0],
[0, 0.01, 0.04, 0.12, 0.35, 0.12, 0.04, 0.01],
[0, 0, 0.01, 0.04, 0.12, 0.35, 0.12, 0.04],
[0, 0, 0, 0.01, 0.04, 0.12, 0.35, 0.12],
[0, 0, 0, 0, 0.01, 0.04, 0.12, 0.35]
]

# Shooting opportunity attraction for up candidates.
W2[25:32, 8:15] = [
[0.12, 0.35, 0.12, 0.04, 0.01, 0, 0],
[0.04, 0.12, 0.35, 0.12, 0.04, 0.01, 0],
[0.01, 0.04, 0.12, 0.35, 0.12, 0.04, 0.01],
[0, 0.01, 0.04, 0.12, 0.35, 0.12, 0.04],
[0, 0, 0.01, 0.04, 0.12, 0.35, 0.12],
[0, 0, 0, 0.01, 0.04, 0.12, 0.35],
[0, 0, 0, 0, 0.01, 0.04, 0.12]
]

# Shooting opportunity attraction for down candidates.
W2[25:32, 16:24] = [
[0.12, 0.35, 0.12, 0.04, 0.01, 0, 0, 0],
[0.04, 0.12, 0.35, 0.12, 0.04, 0.01, 0, 0],
[0.01, 0.04, 0.12, 0.35, 0.12, 0.04, 0.01, 0],
[0, 0.01, 0.04, 0.12, 0.35, 0.12, 0.04, 0.01],
[0, 0, 0.01, 0.04, 0.12, 0.35, 0.12, 0.04],
[0, 0, 0, 0.01, 0.04, 0.12, 0.35, 0.12],
[0, 0, 0, 0, 0.01, 0.04, 0.12, 0.35]
]

# Immediate destination hazards.
W2[16, 0:24:8] = -3
W2[17, 1:24:8] = -3
W2[18, 2:24:8] = -3
W2[19, 3:24:8] = -3
W2[20, 4:24:8] = -3
W2[21, 5:24:8] = -3
W2[22, 6:24:8] = -3
W2[23, 7] = -3
W2[23, 23] = -3

# Additional risk if a vertical action sticks.
W2[16, 9] = -0.3
W2[17, 10] = -0.3
W2[18, 11] = -0.3
W2[19, 12] = -0.3
W2[20, 13] = -0.3
W2[21, 14] = -0.3
W2[17, 16] = -0.3
W2[18, 17] = -0.3
W2[19, 18] = -0.3
W2[20, 19] = -0.3
W2[21, 20] = -0.3
W2[22, 21] = -0.3
W2[23, 22] = -0.3

# Oxygen-driven ascent, gated against empty surfacing.
W2[24, 8] = 4.75
W2[24, 9:15] = 0.75
W2[24, 15] = 6

# Extra surface guard near rows 1 and 2.
W2[1:3, 24] = 3
W2[24, 24] = -3

# Leave row 1 promptly unless ascending for oxygen.
W2[1, 25] = 3
W2[24, 25] = -3

# Candidate offsets.
b2[0:8] = [-11.96, -11.09, -10.63, -10.395, -10.32, -10.395, -10.63, -11.09]
b2[8:16] = [-15.21, -10.64, -10.18, -9.945, -9.87, -9.945, -10.18, -6]
b2[16:24] = [-12.26, -11.39, -10.93, -10.695, -10.62, -10.695, -10.93, -11.09]
b2[24] = 0
b2[25] = -3

# Action logits.
W3[0:8, 5] = 30
W3[8:15, 2] = 30
W3[15, 2] = 40
W3[16:24, 4] = 30
W3[24, 2] = -12
W3[25, 4] = 4
b3[:] = [-100, -100, 238, -100, 244, 241.8]
```