{
 "chunk": "game_mapGenerator6F00_6F00",
 "unit": "game/mapGenerator6F00",
 "unitLabels": {
  "game/mapGenerator6F00": {
   "6F1A": "storeMapStyleFlags",
   "6F2A": "storeMapSymmetryFlag",
   "6F89": "joinRiverClearCentre",
   "6F8E": "mapGeneratorDone",
   "6F9D": "linkServiceNotNeeded",
   "6FC4": "limitHillsForQbSneak",
   "6FCB": "storeHillSiteCount",
   "6FD2": "noHillSitesAtAll",
   "6FD5": "setRowCandidateLimit",
   "6FDE": "hillBlobSizeLoop",
   "6FF5": "hillRowCandidateLoop",
   "7010": "mirrorHillRowCandidates",
   "7027": "startSitePlacement",
   "702B": "tryRowCandidate",
   "702F": "tryJitteredLaneColumn",
   "7036": "jitterLaneColumn",
   "7061": "rowCandidateWrapTest",
   "706B": "hillSiteAccepted",
   "7072": "advanceToNextHillSite",
   "7085": "placeNextHillSite",
   "7088": "storeHillSitesPlaced",
   "708D": "hillSitesDone",
   "7096": "laneIndexDone",
   "709F": "rowCandidateDone",
   "70A5": "laneIdentityLoop",
   "70AC": "laneSwapLoop",
   "70CC": "laneColumnFillLoop",
   "70EA": "summitBlobLoop",
   "7109": "summitsDone",
   "7112": "lowerHillScanInit",
   "7122": "lowerHillRowStart",
   "7126": "lowerHillCellScan",
   "7135": "lowerHillCellOccupied",
   "7141": "lowerHillNorthClassTest",
   "714C": "lowerHillTestWest",
   "7161": "lowerHillTestEast",
   "7163": "lowerHillReadEast",
   "7176": "lowerHillTestSouth",
   "718B": "growLowerHillHere",
   "7194": "lowerHillNextColumn",
   "719F": "lowerHillNextRow",
   "71AA": "lowerHillScanDone",
   "71DC": "blobPopStack",
   "71E3": "blobResumeCell",
   "721C": "blobGrowWest",
   "721F": "blobTryWest",
   "7204": "blobMarkNorthTried",
   "7221": "blobStepWest",
   "7243": "blobTryEast",
   "725D": "blobTestEastBlank",
   "7269": "blobTrySouth",
   "7271": "blobSouthAlreadyTried",
   "728A": "blobTestSouthChance",
   "728F": "blobCellExhausted",
   "7292": "blobPaintCell",
   "72A1": "blobWriteTile",
   "72B1": "blobPushCell",
   "72B3": "blobSaveParentFlags",
   "72D3": "blobStoreColumnBias",
   "72D5": "blobRowBias",
   "72E1": "blobMergeRowBias",
   "72E5": "blobStoreChildFlags",
   "72F2": "blobExpandChild",
   "72F5": "blobFinished",
   "7300": "forestBlockTestNw",
   "730D": "forestBlockTestNe",
   "7310": "forestBlockClassNe",
   "7311": "forestBlockLookupNe",
   "7316": "forestBlockCompareNe",
   "731A": "forestBlockTestSw",
   "731E": "forestBlockClassSw",
   "7328": "forestBlockTestSe",
   "7335": "forestBlockAccept",
   "733D": "forestBlockAcceptRts",
   "733E": "forestBlockReject",
   "734C": "storeForestTile",
   "7362": "limitForestForDefender",
   "7369": "storeForestClusterCount",
   "736B": "forestClusterLoop",
   "736E": "forestCentreFromRandom",
   "7387": "forestSeedRowRetry",
   "7394": "forestSeedColumnRetry",
   "7396": "jitterForestSeedColumn",
   "73AC": "forestClustersDone",
   "73B0": "forestSeedStepEast",
   "73B7": "forestSeedPaintSouthEast",
   "73BC": "forestSeedPaintSouth",
   "73E4": "growForestSeedBlob",
   "73ED": "forestSeedOffMap",
   "7403": "contourScanCell",
   "7412": "contourReadCell",
   "741A": "contourCompareRingClass",
   "741C": "contourCellIsOldRing",
   "7426": "contourEraseOldRing",
   "742A": "contourApplyRule",
   "742F": "contourNextColumn",
   "744A": "contourNeighbourLoop",
   "7460": "contourNextNeighbour",
   "746F": "contourClipRightEdge",
   "7475": "contourClipTopEdge",
   "747B": "contourClipBottomEdge",
   "7481": "contourLookupRule",
   "749E": "contourTakeRandomBit",
   "74BD": "contourMaybeFillCell",
   "74C3": "contourFillWithInterior",
   "74C9": "contourBackUpScan",
   "74D2": "contourStoreScanCol",
   "74D6": "contourBackUpRow",
   "74DD": "contourStoreScanRow",
   "74E0": "contourRescanReturn",
   "74E1": "contourRingTileFromRule",
   "74E5": "contourWriteTile",
   "74EC": "contourLeaveCell"
  }
 },
 "notes": {
  "6F00": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "laneColumnTable - the four vertical 'lanes' of the battlefield along which hill summits are",
    "placed: columns 6, 15, 25 and 34 of the 40-column map.  shuffleLaneColumns copies them into",
    "$0329-$032C in a random order so successive summits land in different parts of the map.",
    "(The label is only marked sub_6F00 because the comcen-screens overlay has code at this address.)"
   ],
   "line": "lane columns 6, 15, 25, 34 (indexed 0-3 by the shuffled permutation)"
  },
  "6F04": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "generateBattlefieldMap - entry point of the procedural battlefield generator.  Derives the",
    "map-style flags for the chosen game type, decides whether the map is point-symmetric, puts",
    "'WORKING...' on the status line, blanks all 1600 map cells to $40 and re-seeds the scenario RNG",
    "from the 24-bit map seed, then falls into runMapGeneratorPasses.  The battlefield is never loaded",
    "from disk: seed + game type completely determine the terrain, which is why both machines produce",
    "the identical map and why a map can be named by its seed.",
    "In:  gameTypeOptions $0BA3 bits 0-2 = game type 0-6, mapSeed $0B95-$0B97; needs the contour rule",
    "     table at $0200 (track 18 s15) and the $EC00 comm-tail helpers resident",
    "Out: $032E map style, $032D symmetry flags, map $F000-$F63F built, scenario RNG $5A-$5C advanced,",
    "     map name text $0BA9-$0BAD, generator scratch $0300-$032C, $0400-$04EF and $9025-$9028 clobbered",
    "Called from: manualLookupCheck ($09E0) to show the map the manual asks about, and from the setup",
    "     screens of this overlay ($76AD map editor, $76FF, $7A02 game start, $7D23 film playback)"
   ],
   "block": [
    "Choose the map style from the game type: QB SNEAK and DEFENDER get special terrain."
   ],
   "line": "gameTypeOptions from the settings block"
  },
  "6F07": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-2 = game type (0 SCRIMAGE .. 6 DEFENDER)"
  },
  "6F09": {
   "unit": "game/mapGenerator6F00",
   "line": "keep the type in Y for the two comparisons below"
  },
  "6F0A": {
   "unit": "game/mapGenerator6F00",
   "line": "type 0 (SCRIMAGE): A is already 0 = ordinary random map"
  },
  "6F0C": {
   "unit": "game/mapGenerator6F00",
   "line": "style $40 = DEFENDER map (river always, exactly 4 hills, 1-4 forest clusters)"
  },
  "6F0E": {
   "unit": "game/mapGenerator6F00",
   "line": "game type 6 = DEFENDER?"
  },
  "6F10": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - keep style $40"
  },
  "6F12": {
   "unit": "game/mapGenerator6F00",
   "line": "style $80 = QB SNEAK map (no river, at most 1 hill, 10 forest clusters)"
  },
  "6F14": {
   "unit": "game/mapGenerator6F00",
   "line": "game type 1 = QB SNEAK?"
  },
  "6F16": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - keep style $80"
  },
  "6F18": {
   "unit": "game/mapGenerator6F00",
   "line": "every other game type: no special style"
  },
  "6F1A": {
   "unit": "game/mapGenerator6F00",
   "line": "$032E mapGenGameFlags: bit 7 = QB SNEAK style, bit 6 = DEFENDER style"
  },
  "6F1D": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "A map whose name ends in '=' (seed bits 0-4 all set) is built point-symmetric."
   ],
   "line": "assume an asymmetric map"
  },
  "6F1F": {
   "unit": "game/mapGenerator6F00",
   "line": "low byte of the 24-bit map seed"
  },
  "6F22": {
   "unit": "game/mapGenerator6F00",
   "line": "bits 0-4 are the last character of the 5-letter map name"
  },
  "6F24": {
   "unit": "game/mapGenerator6F00",
   "line": "$1F = the alphabet's last symbol '='"
  },
  "6F26": {
   "unit": "game/mapGenerator6F00",
   "line": "not a symmetric map code - leave the flag clear"
  },
  "6F28": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 = build a point-symmetric battlefield"
  },
  "6F2A": {
   "unit": "game/mapGenerator6F00",
   "line": "$032D mapSymmetryFlags (bit 6 is set later if the river crosses the centre)"
  },
  "6F2D": {
   "unit": "game/mapGenerator6F00",
   "line": "show message 1 'WORKING...' - generating the map takes several seconds"
  },
  "6F30": {
   "unit": "game/mapGenerator6F00",
   "line": "fill the whole 40x40 map $F000-$F63F with blank terrain $40"
  },
  "6F33": {
   "unit": "game/mapGenerator6F00",
   "line": "scenario RNG $5A-$5C := mapSeed; returns the three seed bytes in A/Y/X"
  },
  "6F36": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "runMapGeneratorPasses - the eight terrain passes, entered by fall-through from",
    "generateBattlefieldMap.  Order: map name from the seed; river with its keep-clear markers; hill",
    "summit sites; summit blobs; erase the $80 markers; upper contour ring; lower hill bodies; erase",
    "the $81 markers; lower contour ring; forest clusters.  A symmetric map is finished by copying the",
    "top half onto the bottom half rotated 180 degrees, with a three-cell patch that joins the two",
    "halves of the river at the centre.  The opponent link is serviced between passes.",
    "In:  A/Y/X = the three map seed bytes, $032D symmetry flags, $032E map style, RNG $5A-$5C",
    "Out: the finished map at $F000-$F63F, map name text $0BA9-$0BAD, generator scratch $0300-$032C;",
    "     ends with JMP resetMessageQueue, which clears 'WORKING...' and returns to the caller",
    "Called from: nothing in this overlay (fall-through only); the JSR $7125 the XREF lists belongs to",
    "     the comcen-screens overlay that shares this address range"
   ],
   "block": [
    "Pass 1-2: name the map, then carve the river."
   ],
   "line": "write the seed as the 5-character map name at $0BA9 (A/Y/X still hold it)"
  },
  "6F39": {
   "unit": "game/mapGenerator6F00",
   "line": "carve the river ($55-$5C) and reserve its banks with the $80/$81 markers"
  },
  "6F3C": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Pass 3-5: hill summits, then the upper slope ring around them."
   ],
   "line": "choose how many summits to place in the top half and on which lanes"
  },
  "6F3F": {
   "unit": "game/mapGenerator6F00",
   "line": "give the modem/trainer link a turn - generation must not stall the exchange"
  },
  "6F42": {
   "unit": "game/mapGenerator6F00",
   "line": "paint each summit as a blob of tile $65/$66"
  },
  "6F45": {
   "unit": "game/mapGenerator6F00",
   "line": "$80 = the outer (wide) river keep-clear marker"
  },
  "6F47": {
   "unit": "game/mapGenerator6F00",
   "line": "turn those markers back into blank $40 before the contour pass reads them"
  },
  "6F4A": {
   "unit": "game/mapGenerator6F00",
   "line": "service the link again"
  },
  "6F4D": {
   "unit": "game/mapGenerator6F00",
   "line": "contour offset 0: rule-table tiles are used unchanged ($41-$54)"
  },
  "6F4F": {
   "unit": "game/mapGenerator6F00",
   "line": "$0324 = amount subtracted from every rule-table tile code"
  },
  "6F52": {
   "unit": "game/mapGenerator6F00",
   "line": "$65 = summit tile, terrain class 6"
  },
  "6F54": {
   "unit": "game/mapGenerator6F00",
   "line": "draw the upper slope contour $41-$54 around everything of class >= 6"
  },
  "6F57": {
   "unit": "game/mapGenerator6F00",
   "line": "service the link"
  },
  "6F5A": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Pass 6-7: widen the hills into bodies and draw their lower contour ring."
   ],
   "line": "grow lower-hill bodies ($61-$64) beside the upper slopes"
  },
  "6F5D": {
   "unit": "game/mapGenerator6F00",
   "line": "$81 = the inner river keep-clear marker"
  },
  "6F5F": {
   "unit": "game/mapGenerator6F00",
   "line": "erase those markers too - the banks are now safe from the lower ring"
  },
  "6F62": {
   "unit": "game/mapGenerator6F00",
   "line": "contour offset $20: rule tiles $41-$54 become the lower ring $21-$34"
  },
  "6F64": {
   "unit": "game/mapGenerator6F00",
   "line": "$0324"
  },
  "6F67": {
   "unit": "game/mapGenerator6F00",
   "line": "$61 = lower hill tile, terrain class 4"
  },
  "6F69": {
   "unit": "game/mapGenerator6F00",
   "line": "draw the lower contour around everything of class >= 4"
  },
  "6F6C": {
   "unit": "game/mapGenerator6F00",
   "line": "service the link"
  },
  "6F6F": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Pass 8: forest, then the optional 180-degree mirror for symmetric maps."
   ],
   "line": "scatter the forest clusters ($5D-$60)"
  },
  "6F72": {
   "unit": "game/mapGenerator6F00",
   "line": "mapSymmetryFlags"
  },
  "6F75": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 clear - asymmetric map, nothing more to do"
  },
  "6F77": {
   "unit": "game/mapGenerator6F00",
   "line": "overwrite the bottom half with the 180-degree rotation of the top half"
  },
  "6F7A": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 = the river jogged up to row 19 at column 20 (set by chooseNextRiverSegment)"
  },
  "6F7D": {
   "unit": "game/mapGenerator6F00",
   "line": "the river does not meet itself at the centre - done"
  },
  "6F7F": {
   "unit": "game/mapGenerator6F00",
   "line": "$58 = river bend left/up"
  },
  "6F81": {
   "unit": "game/mapGenerator6F00",
   "line": "cell (19,20) = $F000 + 20*40 + 19"
  },
  "6F84": {
   "unit": "game/mapGenerator6F00",
   "line": "$55 = river bend down/right"
  },
  "6F86": {
   "unit": "game/mapGenerator6F00",
   "line": "cell (19,19) = $F000 + 19*40 + 19"
  },
  "6F89": {
   "unit": "game/mapGenerator6F00",
   "line": "$40 = blank terrain"
  },
  "6F8B": {
   "unit": "game/mapGenerator6F00",
   "line": "cell (20,20): erase the mirrored stub so the two river halves join cleanly"
  },
  "6F8E": {
   "unit": "game/mapGenerator6F00",
   "line": "clear the 'WORKING...' message and return to generateBattlefieldMap's caller"
  },
  "6F91": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "serviceLinkWhileGenerating - lets the opponent link breathe during the long map build.  Does",
    "nothing while a game film is being replayed (no opponent) or while the battle loop is running",
    "(the frame handler already services the link there); otherwise runs one command-exchange step.",
    "In:  filmPlaybackMode $0B9B bit 7, gamePhase zp_B1 bit 7",
    "Out: whatever serviceCommandExchange ($4DA9) does - packets sent/received, messages updated",
    "Called from: runMapGeneratorPasses ($6F3F, $6F4A, $6F57, $6F6C) and the map-name screen ($773A)"
   ],
   "line": "filmPlaybackMode: bit 7 = watching a recorded game"
  },
  "6F94": {
   "unit": "game/mapGenerator6F00",
   "line": "film playback - there is nobody on the other end"
  },
  "6F96": {
   "unit": "game/mapGenerator6F00",
   "line": "gamePhase: bit 7 set in the setup/menu phases"
  },
  "6F98": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 clear = the battle loop is running and already services the link"
  },
  "6F9A": {
   "unit": "game/mapGenerator6F00",
   "line": "exchange one round of commands with the opponent (tail call)"
  },
  "6F9D": {
   "unit": "game/mapGenerator6F00",
   "line": "nothing to do"
  },
  "6F9E": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "pickHillSummitSites - decides how many hill summits the map gets and finds a blank cell for each.",
    "The count is rolled as (rnd AND 3) + (rnd AND 1), re-rolled to 1-4 if it came out exactly 1;",
    "DEFENDER always gets 4 and QB SNEAK at most 1.  Each site gets a blob size of 2-5 cells, and four",
    "candidate rows in the range 7-14 are rolled.  findBlankSitesOnLanes then places the top-half",
    "sites; afterwards the count is doubled, the candidate rows are mirrored to 39-row and the same",
    "routine runs again by fall-through, so every summit gets a point-mirrored twin in the bottom half.",
    "In:  $032E map style bits 6/7, scenario RNG",
    "Out: $0300 = total number of sites placed, $0307[0..7] blob sizes, $0314[i]/$031C[i] site",
    "     column/row, $0325[0..3] candidate rows, $0329-$032C lane columns; zp_18, zp_28-zp_2B",
    "Called from: runMapGeneratorPasses ($6F3C)"
   ],
   "block": [
    "Roll the number of summits for the top half of the map."
   ],
   "line": "start the top-half pass at site 0"
  },
  "6FA0": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2A = index of the site being placed; the first pass starts at site 0"
  },
  "6FA2": {
   "unit": "game/mapGenerator6F00",
   "line": "DEFENDER gets exactly 4 summits"
  },
  "6FA4": {
   "unit": "game/mapGenerator6F00",
   "line": "mapGenGameFlags"
  },
  "6FA7": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 (DEFENDER style) - keep the fixed count of 4"
  },
  "6FA9": {
   "unit": "game/mapGenerator6F00",
   "line": "first roll"
  },
  "6FAC": {
   "unit": "game/mapGenerator6F00",
   "line": "0-3"
  },
  "6FAE": {
   "unit": "game/mapGenerator6F00",
   "line": "remember it"
  },
  "6FB0": {
   "unit": "game/mapGenerator6F00",
   "line": "second roll"
  },
  "6FB3": {
   "unit": "game/mapGenerator6F00",
   "line": "0-1"
  },
  "6FB5": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "6FB6": {
   "unit": "game/mapGenerator6F00",
   "line": "count = (rnd AND 3) + (rnd AND 1) = 0-4, biased towards 1-3"
  },
  "6FB8": {
   "unit": "game/mapGenerator6F00",
   "line": "did it come out as a single lone summit?"
  },
  "6FBA": {
   "unit": "game/mapGenerator6F00",
   "line": "no - keep the count"
  },
  "6FBC": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - re-roll rather than build a one-hill map"
  },
  "6FBF": {
   "unit": "game/mapGenerator6F00",
   "line": "0-3"
  },
  "6FC1": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "6FC2": {
   "unit": "game/mapGenerator6F00",
   "line": "1-4 summits instead"
  },
  "6FC4": {
   "unit": "game/mapGenerator6F00",
   "line": "mapGenGameFlags"
  },
  "6FC7": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 clear - not QB SNEAK, keep the count"
  },
  "6FC9": {
   "unit": "game/mapGenerator6F00",
   "line": "QB SNEAK: 0 or 1 summit only, the field has to stay open"
  },
  "6FCB": {
   "unit": "game/mapGenerator6F00",
   "line": "$0300 = summit count (the generator uses the $0200-$03FF setup block as scratch RAM)"
  },
  "6FCE": {
   "unit": "game/mapGenerator6F00",
   "line": "redundant: every path above already set Z from A"
  },
  "6FD0": {
   "unit": "game/mapGenerator6F00",
   "line": "at least one summit"
  },
  "6FD2": {
   "unit": "game/mapGenerator6F00",
   "line": "no hills at all - store 0 through the common exit and return"
  },
  "6FD5": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Roll one blob size per site (mirrored to the twin) and four candidate rows 7-14."
   ],
   "line": "zp_28 = highest index of the candidate-row list..."
  },
  "6FD7": {
   "unit": "game/mapGenerator6F00",
   "line": "...= count-1, so 0-3 (there are four candidate rows)"
  },
  "6FD9": {
   "unit": "game/mapGenerator6F00",
   "line": "Y walks the top-half sites 0..count-1"
  },
  "6FDB": {
   "unit": "game/mapGenerator6F00",
   "line": "X walks their bottom-half twins, which start at index count"
  },
  "6FDE": {
   "unit": "game/mapGenerator6F00",
   "line": "roll the size of this summit blob"
  },
  "6FE1": {
   "unit": "game/mapGenerator6F00",
   "line": "0-3"
  },
  "6FE3": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "6FE4": {
   "unit": "game/mapGenerator6F00",
   "line": "blob size 2-5 cells"
  },
  "6FE6": {
   "unit": "game/mapGenerator6F00",
   "line": "$0307[y] = size of top-half site y"
  },
  "6FE9": {
   "unit": "game/mapGenerator6F00",
   "line": "$0307[count+y] = the mirrored twin gets the same size"
  },
  "6FEC": {
   "unit": "game/mapGenerator6F00",
   "line": "next top-half site"
  },
  "6FED": {
   "unit": "game/mapGenerator6F00",
   "line": "next bottom-half twin"
  },
  "6FEE": {
   "unit": "game/mapGenerator6F00",
   "line": "all sites given a size?"
  },
  "6FF1": {
   "unit": "game/mapGenerator6F00",
   "line": "one size per site"
  },
  "6FF3": {
   "unit": "game/mapGenerator6F00",
   "line": "four candidate rows, filled backwards 3..0"
  },
  "6FF5": {
   "unit": "game/mapGenerator6F00",
   "line": "roll one candidate row"
  },
  "6FF8": {
   "unit": "game/mapGenerator6F00",
   "line": "0-7"
  },
  "6FFA": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "6FFB": {
   "unit": "game/mapGenerator6F00",
   "line": "row 7-14: summits stay clear of the top edge and of the centre line"
  },
  "6FFD": {
   "unit": "game/mapGenerator6F00",
   "line": "$0325[y] = candidate row list used by findBlankSitesOnLanes"
  },
  "7000": {
   "unit": "game/mapGenerator6F00",
   "line": "preload $031C[y] as well so an unplaced site still holds a sane row"
  },
  "7003": {
   "unit": "game/mapGenerator6F00",
   "line": "next candidate-row slot"
  },
  "7004": {
   "unit": "game/mapGenerator6F00",
   "line": "four candidate rows in all"
  },
  "7006": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Place the top half, then mirror everything into the bottom half."
   ],
   "line": "resolve the top-half sites onto the four lanes"
  },
  "7009": {
   "unit": "game/mapGenerator6F00",
   "line": "double the placed count - each site also gets a point-mirrored twin"
  },
  "700C": {
   "unit": "game/mapGenerator6F00",
   "line": "nothing could be placed - store 0 and return"
  },
  "700E": {
   "unit": "game/mapGenerator6F00",
   "line": "mirror the four candidate rows"
  },
  "7010": {
   "unit": "game/mapGenerator6F00",
   "line": "row of site y (the accepted row, or the preloaded candidate)"
  },
  "7013": {
   "unit": "game/mapGenerator6F00",
   "line": "39 - row: the same distance from the bottom edge"
  },
  "7016": {
   "unit": "game/mapGenerator6F00",
   "line": "candidate rows 25-32 for the bottom half"
  },
  "7019": {
   "unit": "game/mapGenerator6F00",
   "line": "next of the four candidate rows"
  },
  "701A": {
   "unit": "game/mapGenerator6F00",
   "line": "falls into findBlankSitesOnLanes for sites count..2*count-1"
  },
  "701C": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "findBlankSitesOnLanes - gives every summit site from zp_2A to $0300-1 a column and a row.  The",
    "four lane columns are reshuffled first; each site then takes the next lane and the next candidate",
    "row and tries up to 21 jittered columns (+/-6 around the lane) until it finds a blank ($40) cell.",
    "If a whole row fails it moves on to the next candidate row, and if every row fails the site is",
    "dropped ($0300 and zp_2A are decremented).  Entered by JSR for the top half and by fall-through",
    "for the mirrored bottom half, which is why zp_2A is not reset here.",
    "In:  zp_2A = first site index, $0300 = requested count, zp_28 = highest candidate-row index,",
    "     $0325[] candidate rows, map at $F000",
    "Out: $0314[i] site column, $031C[i] site row, $0300 = sites actually placed, $0329-$032C lanes;",
    "     zp_1D/zp_1E/zp_1F/zp_29/zp_2B scratch",
    "Called from: pickHillSummitSites ($7006, and by fall-through from $701A)"
   ],
   "line": "randomise the order of the four lane columns 6/15/25/34"
  },
  "701F": {
   "unit": "game/mapGenerator6F00",
   "line": "lane index 3 = the last entry of the shuffled lane list"
  },
  "7021": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2B = lane index; advanceLaneIndex counts down 3,2,1,0,3,..."
  },
  "7023": {
   "unit": "game/mapGenerator6F00",
   "line": "highest valid candidate-row index (= count-1)"
  },
  "7025": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_29 = start at the top of the candidate-row list"
  },
  "7027": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Per site: try candidate rows in turn until a blank cell is found."
   ],
   "line": "current candidate-row index"
  },
  "7029": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_1F remembers which candidate row this site started with"
  },
  "702B": {
   "unit": "game/mapGenerator6F00",
   "line": "21 column attempts per candidate row (counter $14 down through 0)"
  },
  "702D": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_1E = attempts left"
  },
  "702F": {
   "unit": "game/mapGenerator6F00",
   "line": "current lane"
  },
  "7031": {
   "unit": "game/mapGenerator6F00",
   "line": "its column: 6, 15, 25 or 34"
  },
  "7034": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 3 jitter steps, i.e. an offset of 0, +/-2, +/-4 or +/-6 columns"
  },
  "7036": {
   "unit": "game/mapGenerator6F00",
   "line": "scatter the site sideways around its lane column"
  },
  "7039": {
   "unit": "game/mapGenerator6F00",
   "line": "still inside the 40-column map?"
  },
  "703B": {
   "unit": "game/mapGenerator6F00",
   "line": "off the map - roll again (a rejected roll does not use up an attempt)"
  },
  "703D": {
   "unit": "game/mapGenerator6F00",
   "line": "index of the site being placed"
  },
  "703F": {
   "unit": "game/mapGenerator6F00",
   "line": "$0314[i] = provisional column"
  },
  "7042": {
   "unit": "game/mapGenerator6F00",
   "line": "X = column for readMapCell"
  },
  "7043": {
   "unit": "game/mapGenerator6F00",
   "line": "current candidate-row slot"
  },
  "7045": {
   "unit": "game/mapGenerator6F00",
   "line": "the candidate row for this attempt"
  },
  "7048": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_1D keeps it until the cell is known to be free"
  },
  "704A": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = row for readMapCell"
  },
  "704B": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_48/49 -> map cell (column,row)"
  },
  "704E": {
   "unit": "game/mapGenerator6F00",
   "line": "offset 0 = the cell itself"
  },
  "7050": {
   "unit": "game/mapGenerator6F00",
   "line": "what is already there"
  },
  "7052": {
   "unit": "game/mapGenerator6F00",
   "line": "$40 = blank terrain (the river and its markers are not)"
  },
  "7054": {
   "unit": "game/mapGenerator6F00",
   "line": "free - take this site"
  },
  "7056": {
   "unit": "game/mapGenerator6F00",
   "line": "one attempt used up"
  },
  "7058": {
   "unit": "game/mapGenerator6F00",
   "line": "try another column on the same row"
  },
  "705A": {
   "unit": "game/mapGenerator6F00",
   "line": "this row is hopeless - step to the next candidate row"
  },
  "705D": {
   "unit": "game/mapGenerator6F00",
   "line": "the candidate row we have wrapped round to"
  },
  "705F": {
   "unit": "game/mapGenerator6F00",
   "line": "have we cycled back to the row we started on?"
  },
  "7061": {
   "unit": "game/mapGenerator6F00",
   "line": "no - give that row its own 21 attempts"
  },
  "7063": {
   "unit": "game/mapGenerator6F00",
   "line": "every candidate row failed: drop this site from the count"
  },
  "7066": {
   "unit": "game/mapGenerator6F00",
   "line": "and let the next site re-use its index"
  },
  "7068": {
   "unit": "game/mapGenerator6F00",
   "line": "site dropped - skip the accept path"
  },
  "706B": {
   "unit": "game/mapGenerator6F00",
   "line": "index of the site just placed"
  },
  "706D": {
   "unit": "game/mapGenerator6F00",
   "line": "the row that worked"
  },
  "706F": {
   "unit": "game/mapGenerator6F00",
   "line": "$031C[i] = site row"
  },
  "7072": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Advance lane and row candidate so consecutive summits are spread out."
   ],
   "line": "next site uses the next lane column"
  },
  "7075": {
   "unit": "game/mapGenerator6F00",
   "line": "the candidate row this site started from"
  },
  "7077": {
   "unit": "game/mapGenerator6F00",
   "line": "restore the candidate row this site started from..."
  },
  "7079": {
   "unit": "game/mapGenerator6F00",
   "line": "...then step it once, so the next site starts on a different row"
  },
  "707C": {
   "unit": "game/mapGenerator6F00",
   "line": "next site index"
  },
  "707E": {
   "unit": "game/mapGenerator6F00",
   "line": "site index just used"
  },
  "7080": {
   "unit": "game/mapGenerator6F00",
   "line": "all requested sites handled?"
  },
  "7083": {
   "unit": "game/mapGenerator6F00",
   "line": "all sites handled - store the real count"
  },
  "7085": {
   "unit": "game/mapGenerator6F00",
   "line": "place the next site"
  },
  "7088": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2A = number of sites actually placed"
  },
  "708A": {
   "unit": "game/mapGenerator6F00",
   "line": "$0300 corrected, so the painters only walk real sites"
  },
  "708D": {
   "unit": "game/mapGenerator6F00",
   "line": "returns with $0300 = the number of sites that really exist"
  },
  "708E": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "advanceLaneIndex - steps the lane cursor zp_2B down through the four shuffled lane columns in",
    "$0329-$032C, wrapping 0 back to 3.",
    "In:  zp_2B",
    "Out: zp_2B = next lane index 0-3",
    "Called from: findBlankSitesOnLanes ($7072)"
   ],
   "line": "next lane"
  },
  "7090": {
   "unit": "game/mapGenerator6F00",
   "line": "still a valid index"
  },
  "7092": {
   "unit": "game/mapGenerator6F00",
   "line": "lane index 3"
  },
  "7094": {
   "unit": "game/mapGenerator6F00",
   "line": "wrap round to the last of the four lanes"
  },
  "7096": {
   "unit": "game/mapGenerator6F00",
   "line": "return the wrapped lane index"
  },
  "7097": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "advanceRowCandidate - steps the candidate-row cursor zp_29 down through $0325[0..zp_28],",
    "wrapping 0 back to zp_28 (= summit count - 1).",
    "In:  zp_29, zp_28",
    "Out: zp_29 = next candidate-row index",
    "Called from: findBlankSitesOnLanes ($705A, $7079)"
   ],
   "line": "next candidate row"
  },
  "7099": {
   "unit": "game/mapGenerator6F00",
   "line": "still a valid index"
  },
  "709B": {
   "unit": "game/mapGenerator6F00",
   "line": "highest candidate index"
  },
  "709D": {
   "unit": "game/mapGenerator6F00",
   "line": "wrap round to the top of the list"
  },
  "709F": {
   "unit": "game/mapGenerator6F00",
   "line": "return the wrapped candidate-row index"
  },
  "70A0": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "shuffleLaneColumns - builds a random permutation of 0-3 (identity, then four random transpositions)",
    "in the sprite build buffer $9025-$9028, which is free while the map is generated, and writes",
    "laneColumnTable[perm[y]] into $0329-$032C.  Summits are therefore distributed over the four",
    "vertical lanes of the map in a different order for every map.",
    "In:  scenario RNG, laneColumnTable $6F00",
    "Out: $0329-$032C = the four lane columns in random order; $9025-$9028 and zp_18 clobbered",
    "Called from: findBlankSitesOnLanes ($701C)"
   ],
   "line": "load the swap count"
  },
  "70A2": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_18 = swap counter: 3,2,1,0 = four swaps"
  },
  "70A4": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 3"
  },
  "70A5": {
   "unit": "game/mapGenerator6F00",
   "line": "A = Y"
  },
  "70A6": {
   "unit": "game/mapGenerator6F00",
   "line": "$9025[y] = y: start from the identity permutation"
  },
  "70A9": {
   "unit": "game/mapGenerator6F00",
   "line": "next slot"
  },
  "70AA": {
   "unit": "game/mapGenerator6F00",
   "line": "four entries 3..0"
  },
  "70AC": {
   "unit": "game/mapGenerator6F00",
   "line": "pick the first index..."
  },
  "70AF": {
   "unit": "game/mapGenerator6F00",
   "line": "0-3"
  },
  "70B1": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = first slot to swap"
  },
  "70B2": {
   "unit": "game/mapGenerator6F00",
   "line": "...and the second (may be the same, which is a no-op swap)"
  },
  "70B5": {
   "unit": "game/mapGenerator6F00",
   "line": "0-3"
  },
  "70B7": {
   "unit": "game/mapGenerator6F00",
   "line": "X = second slot to swap (may be the same)"
  },
  "70B8": {
   "unit": "game/mapGenerator6F00",
   "line": "perm[y]"
  },
  "70BB": {
   "unit": "game/mapGenerator6F00",
   "line": "save it on the stack"
  },
  "70BC": {
   "unit": "game/mapGenerator6F00",
   "line": "perm[x]"
  },
  "70BF": {
   "unit": "game/mapGenerator6F00",
   "line": "perm[y] = perm[x]"
  },
  "70C2": {
   "unit": "game/mapGenerator6F00",
   "line": "the old perm[y]"
  },
  "70C3": {
   "unit": "game/mapGenerator6F00",
   "line": "exchange perm[y] and perm[x]"
  },
  "70C6": {
   "unit": "game/mapGenerator6F00",
   "line": "one swap done"
  },
  "70C8": {
   "unit": "game/mapGenerator6F00",
   "line": "four swaps in all"
  },
  "70CA": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 3: fill the lane list backwards"
  },
  "70CC": {
   "unit": "game/mapGenerator6F00",
   "line": "permuted index 0-3"
  },
  "70CF": {
   "unit": "game/mapGenerator6F00",
   "line": "lane column 6, 15, 25 or 34"
  },
  "70D2": {
   "unit": "game/mapGenerator6F00",
   "line": "$0329-$032C = shuffled lane columns"
  },
  "70D5": {
   "unit": "game/mapGenerator6F00",
   "line": "next lane slot"
  },
  "70D6": {
   "unit": "game/mapGenerator6F00",
   "line": "four lanes"
  },
  "70D8": {
   "unit": "game/mapGenerator6F00",
   "line": "the four lane columns are ready"
  },
  "70D9": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "paintHillSummits - paints every site chosen by pickHillSummitSites as a blob of summit tiles.",
    "Each blob is 2-5 cells of tile $65 (randomTileVariant may pick $66) grown from the site with a",
    "horizontal spread of 200/256 and a vertical spread of 32/256, so summits are wide and flat rather",
    "than round.  Does nothing when no sites were placed.",
    "In:  $0300 site count, $0307[] blob sizes, $0314[]/$031C[] site coordinates",
    "Out: summit tiles written to the map; $0301 = $65, $0304 = 0, zp_2A, zp_A7/zp_A8",
    "Called from: runMapGeneratorPasses ($6F42)"
   ],
   "line": "number of summit sites"
  },
  "70DC": {
   "unit": "game/mapGenerator6F00",
   "line": "no hills on this map"
  },
  "70DE": {
   "unit": "game/mapGenerator6F00",
   "line": "clear A for the two stores below"
  },
  "70E0": {
   "unit": "game/mapGenerator6F00",
   "line": "$0304 blob flags = 0: no 2x2 block constraint"
  },
  "70E3": {
   "unit": "game/mapGenerator6F00",
   "line": "start at site 0"
  },
  "70E5": {
   "unit": "game/mapGenerator6F00",
   "line": "$65 = summit tile, terrain class 6"
  },
  "70E7": {
   "unit": "game/mapGenerator6F00",
   "line": "$0301 = the tile growTerrainBlob paints"
  },
  "70EA": {
   "unit": "game/mapGenerator6F00",
   "line": "index of the site being painted"
  },
  "70EC": {
   "unit": "game/mapGenerator6F00",
   "line": "site column"
  },
  "70EF": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A7 = blob origin column"
  },
  "70F1": {
   "unit": "game/mapGenerator6F00",
   "line": "site row"
  },
  "70F4": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A8 = blob origin row"
  },
  "70F6": {
   "unit": "game/mapGenerator6F00",
   "line": "A = 2-5 cells to place"
  },
  "70F9": {
   "unit": "game/mapGenerator6F00",
   "line": "X = horizontal spread 200/256 - summits stretch east/west"
  },
  "70FB": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = vertical spread 32/256 - and stay thin north/south"
  },
  "70FD": {
   "unit": "game/mapGenerator6F00",
   "line": "paint this summit"
  },
  "7100": {
   "unit": "game/mapGenerator6F00",
   "line": "next site"
  },
  "7102": {
   "unit": "game/mapGenerator6F00",
   "line": "site index just painted"
  },
  "7104": {
   "unit": "game/mapGenerator6F00",
   "line": "all sites painted?"
  },
  "7107": {
   "unit": "game/mapGenerator6F00",
   "line": "every site, top-half original and mirrored twin alike"
  },
  "7109": {
   "unit": "game/mapGenerator6F00",
   "line": "no more sites"
  },
  "710A": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "growLowerHillsBesideSlopes - second terrain layer.  Scans every interior cell (column and row",
    "1-38) and, when a blank cell touches an upper slope tile (terrain class 5, $41-$54), grows a",
    "5-cell blob of lower-hill tile $61 from it.  The chance is 1 in 4 for the north and south",
    "neighbours and 1 in 2 for west and east, so the hill bodies spread sideways like the summits.",
    "The first matching neighbour wins.  Skipped entirely when the map has no hills.",
    "In:  $0300 summit count, the map, terrainClassTable $077E, scenario RNG",
    "Out: lower-hill tiles written to the map; $0301 = $61, $0304 = 0, zp_A7/zp_A8 = the scan cell",
    "Called from: runMapGeneratorPasses ($6F5A)"
   ],
   "line": "were any summits placed?"
  },
  "710D": {
   "unit": "game/mapGenerator6F00",
   "line": "there are hills to widen"
  },
  "710F": {
   "unit": "game/mapGenerator6F00",
   "line": "no hills - nothing to widen"
  },
  "7112": {
   "unit": "game/mapGenerator6F00",
   "line": "clear A for the two stores below"
  },
  "7114": {
   "unit": "game/mapGenerator6F00",
   "line": "$0304 blob flags = 0: no 2x2 block constraint"
  },
  "7117": {
   "unit": "game/mapGenerator6F00",
   "line": "clears zp_2A as a side effect; nothing in this routine reads it"
  },
  "7119": {
   "unit": "game/mapGenerator6F00",
   "line": "$61 = lower hill tile ($61-$64 variants), terrain class 4"
  },
  "711B": {
   "unit": "game/mapGenerator6F00",
   "line": "$0301 = the tile growTerrainBlob paints"
  },
  "711E": {
   "unit": "game/mapGenerator6F00",
   "line": "row 1"
  },
  "7120": {
   "unit": "game/mapGenerator6F00",
   "line": "scan starts at row 1 (the outermost ring is never used)"
  },
  "7122": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Scan loop over the interior cells.  zp_A7/zp_A8 hold the cell; zp_48/49 is set to the top-left",
    "corner of its 3x3 block so the neighbours are at fixed offsets $01 N, $28 W, $29 self, $2A E,",
    "$51 S."
   ],
   "line": "column 1"
  },
  "7124": {
   "unit": "game/mapGenerator6F00",
   "line": "each row starts at column 1"
  },
  "7126": {
   "unit": "game/mapGenerator6F00",
   "line": "X = column..."
  },
  "7128": {
   "unit": "game/mapGenerator6F00",
   "line": "...minus 1"
  },
  "7129": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = row..."
  },
  "712B": {
   "unit": "game/mapGenerator6F00",
   "line": "...minus 1"
  },
  "712C": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_48/49 -> cell (col-1,row-1), the top-left of the 3x3 block"
  },
  "712F": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $29 = the cell itself"
  },
  "7131": {
   "unit": "game/mapGenerator6F00",
   "line": "the terrain code of the scan cell"
  },
  "7133": {
   "unit": "game/mapGenerator6F00",
   "line": "only blank cells can start a lower hill"
  },
  "7135": {
   "unit": "game/mapGenerator6F00",
   "line": "occupied - move on"
  },
  "7137": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $01 = north neighbour (col,row-1)"
  },
  "7139": {
   "unit": "game/mapGenerator6F00",
   "line": "north neighbour's cell"
  },
  "713B": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 set = a unit or a river keep-clear marker, not terrain"
  },
  "713D": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "713E": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of the north neighbour"
  },
  "7141": {
   "unit": "game/mapGenerator6F00",
   "line": "class 5 = upper slope contour $41-$54"
  },
  "7143": {
   "unit": "game/mapGenerator6F00",
   "line": "not a slope - try the west neighbour"
  },
  "7145": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the north slope"
  },
  "7148": {
   "unit": "game/mapGenerator6F00",
   "line": "1 chance in 4 for a north slope"
  },
  "714A": {
   "unit": "game/mapGenerator6F00",
   "line": "won - grow a hill body here"
  },
  "714C": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $28 = west neighbour (col-1,row)"
  },
  "714E": {
   "unit": "game/mapGenerator6F00",
   "line": "west neighbour's cell"
  },
  "7150": {
   "unit": "game/mapGenerator6F00",
   "line": "unit or marker - skip"
  },
  "7152": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "7153": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of the west neighbour"
  },
  "7156": {
   "unit": "game/mapGenerator6F00",
   "line": "upper slope?"
  },
  "7158": {
   "unit": "game/mapGenerator6F00",
   "line": "no - try the east neighbour"
  },
  "715A": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the west slope"
  },
  "715D": {
   "unit": "game/mapGenerator6F00",
   "line": "1 chance in 2 for a side slope - hills widen east/west"
  },
  "715F": {
   "unit": "game/mapGenerator6F00",
   "line": "won - grow a hill body here"
  },
  "7161": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $2A = east neighbour (col+1,row)"
  },
  "7163": {
   "unit": "game/mapGenerator6F00",
   "line": "east neighbour's cell"
  },
  "7165": {
   "unit": "game/mapGenerator6F00",
   "line": "unit or marker - skip"
  },
  "7167": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "7168": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of the east neighbour"
  },
  "716B": {
   "unit": "game/mapGenerator6F00",
   "line": "upper slope?"
  },
  "716D": {
   "unit": "game/mapGenerator6F00",
   "line": "no - try the south neighbour"
  },
  "716F": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the east slope"
  },
  "7172": {
   "unit": "game/mapGenerator6F00",
   "line": "1 chance in 2"
  },
  "7174": {
   "unit": "game/mapGenerator6F00",
   "line": "won - grow a hill body here"
  },
  "7176": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $51 = south neighbour (col,row+1)"
  },
  "7178": {
   "unit": "game/mapGenerator6F00",
   "line": "south neighbour's cell"
  },
  "717A": {
   "unit": "game/mapGenerator6F00",
   "line": "unit or marker - give up on this cell"
  },
  "717C": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "717D": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of the south neighbour"
  },
  "7180": {
   "unit": "game/mapGenerator6F00",
   "line": "upper slope?"
  },
  "7182": {
   "unit": "game/mapGenerator6F00",
   "line": "no - nothing to do at this cell"
  },
  "7184": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the south slope"
  },
  "7187": {
   "unit": "game/mapGenerator6F00",
   "line": "1 chance in 4 (inverted test: falls through to grow)"
  },
  "7189": {
   "unit": "game/mapGenerator6F00",
   "line": "lost the roll"
  },
  "718B": {
   "unit": "game/mapGenerator6F00",
   "line": "X = horizontal spread 64/256"
  },
  "718D": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = vertical spread 16/256 - the body hugs the slope"
  },
  "718F": {
   "unit": "game/mapGenerator6F00",
   "line": "A = 5 cells"
  },
  "7191": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A7/zp_A8 already hold the scan cell = the blob origin"
  },
  "7194": {
   "unit": "game/mapGenerator6F00",
   "line": "next column"
  },
  "7196": {
   "unit": "game/mapGenerator6F00",
   "line": "the column just finished"
  },
  "7198": {
   "unit": "game/mapGenerator6F00",
   "line": "columns 1-38 only"
  },
  "719A": {
   "unit": "game/mapGenerator6F00",
   "line": "row finished"
  },
  "719C": {
   "unit": "game/mapGenerator6F00",
   "line": "scan the next cell of this row"
  },
  "719F": {
   "unit": "game/mapGenerator6F00",
   "line": "next row"
  },
  "71A1": {
   "unit": "game/mapGenerator6F00",
   "line": "the row just finished"
  },
  "71A3": {
   "unit": "game/mapGenerator6F00",
   "line": "rows 1-38 only"
  },
  "71A5": {
   "unit": "game/mapGenerator6F00",
   "line": "whole map scanned"
  },
  "71A7": {
   "unit": "game/mapGenerator6F00",
   "line": "scan the next row"
  },
  "71AA": {
   "unit": "game/mapGenerator6F00",
   "line": "the whole interior has been scanned"
  },
  "71AB": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "unusedBitTable71AB - $08,$04,$02,$01,$00.  Dead in this overlay: nothing between $6F00 and $87FF",
    "reads it (the $71AC reference in XREF belongs to the comcen-screens overlay).  It looks like a",
    "leftover direction-bit table for growTerrainBlob, which builds the same bits with immediate",
    "operands instead."
   ],
   "line": "unused direction-bit constants"
  },
  "71B0": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "growTerrainBlob - the generic random blob painter used by every terrain pass.  Starting at",
    "(zp_A7,zp_A8) it performs a depth-first walk with an explicit 80-entry stack in page 4 ($0400",
    "columns, $0450 rows, $04A0 tried-direction flags) and paints tile $0301 - passed through",
    "randomTileVariant - on blank ($40) cells until A cells have been placed, the stack empties or the",
    "stack overflows.  From each cell the four directions are tried once (flag bits 0 N, 1 W, 2 E,",
    "3 S in zp_6B); a neighbour is taken when it is on the map, blank, and a scenario random byte is",
    "below the X (west/east) or Y (north/south) threshold, so X and Y control the horizontal and",
    "vertical spread out of 256.  A newly pushed cell has the direction back towards the origin",
    "pre-marked as tried, which keeps the blob growing outwards.  With $0304 bit 6 set (forest) a cell",
    "is only painted when checkAlignedBlockForForest approves its 2x2 block.",
    "In:  A = cells to paint, X = horizontal spread 0-255, Y = vertical spread 0-255,",
    "     zp_A7/zp_A8 = origin, $0301 = base tile, $0304 = blob flags",
    "Out: map cells painted; zp_18, zp_1A, zp_6B, zp_A5/zp_A6, zp_B2 stack level, zp_B3 painted count,",
    "     $91DA/$91DB and $0400-$04EF clobbered.  NOTE: $0400-$04EF is the page that also holds the",
    "     copy-protection answer table at $0401 - harmless, because manualLookupCheck reads its answer",
    "     before it calls the generator",
    "Called from: paintHillSummits ($70FD), growLowerHillsBesideSlopes ($7191), paintForestBlobAt ($73EA)"
   ],
   "block": [
    "Set up the walk: thresholds, counters and stack entry 0 = the origin cell."
   ],
   "line": "X = horizontal accept threshold, parked in the engine's currentUnitCol (free here)"
  },
  "71B3": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = vertical accept threshold, parked in currentUnitRow"
  },
  "71B6": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_18 = how many cells this blob should get"
  },
  "71B8": {
   "unit": "game/mapGenerator6F00",
   "line": "clear A for the three stores below"
  },
  "71BA": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_B3 = cells painted so far"
  },
  "71BC": {
   "unit": "game/mapGenerator6F00",
   "line": "$04A0[0] = tried-direction flags of the origin entry"
  },
  "71BF": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_B2 = stack fill level (index of the next free entry)"
  },
  "71C1": {
   "unit": "game/mapGenerator6F00",
   "line": "blob flags: bit 6 = only paint inside a clean 2x2 block"
  },
  "71C4": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_6B = flags of the cell currently being expanded"
  },
  "71C6": {
   "unit": "game/mapGenerator6F00",
   "line": "the walk starts at the blob origin"
  },
  "71C8": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A5 = column of the current cell"
  },
  "71CA": {
   "unit": "game/mapGenerator6F00",
   "line": "$0400[0] = origin column"
  },
  "71CD": {
   "unit": "game/mapGenerator6F00",
   "line": "origin row"
  },
  "71CF": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A6 = row of the current cell"
  },
  "71D1": {
   "unit": "game/mapGenerator6F00",
   "line": "$0450[0] = origin row"
  },
  "71D4": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_48/49 -> the origin cell (copes with negative coordinates)"
  },
  "71D7": {
   "unit": "game/mapGenerator6F00",
   "line": "offset 0 = the cell itself"
  },
  "71D9": {
   "unit": "game/mapGenerator6F00",
   "line": "paint the origin, then push it as the first stack entry"
  },
  "71DC": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Pop the top stack entry and try its four directions in turn.  zp_48/49 is aimed one row above",
    "the cell, so N/W/E/S are at offsets $00/$27/$29/$50."
   ],
   "line": "drop the fill level to the entry on top of the stack"
  },
  "71DE": {
   "unit": "game/mapGenerator6F00",
   "line": "there is still an entry to expand"
  },
  "71E0": {
   "unit": "game/mapGenerator6F00",
   "line": "stack empty - this blob is finished"
  },
  "71E3": {
   "unit": "game/mapGenerator6F00",
   "line": "y = the entry now on top of the stack"
  },
  "71E5": {
   "unit": "game/mapGenerator6F00",
   "line": "$04A0[y] = directions already tried from this cell"
  },
  "71E8": {
   "unit": "game/mapGenerator6F00",
   "line": "re-apply the global blob flags (bit 6 survives every push/pop)"
  },
  "71EB": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_6B = the flags of the cell being expanded"
  },
  "71ED": {
   "unit": "game/mapGenerator6F00",
   "line": "$0400[y] = its column"
  },
  "71F0": {
   "unit": "game/mapGenerator6F00",
   "line": "$0450[y] = its row"
  },
  "71F3": {
   "unit": "game/mapGenerator6F00",
   "line": "A -> Y so it can be decremented"
  },
  "71F4": {
   "unit": "game/mapGenerator6F00",
   "line": "aim one row above the cell..."
  },
  "71F5": {
   "unit": "game/mapGenerator6F00",
   "line": "...so the north neighbour sits at offset 0"
  },
  "71F7": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A5 = the cell's column"
  },
  "71F9": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_48/49 -> (column, row-1)"
  },
  "71FC": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "71FE": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 0 = north already tried"
  },
  "7200": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - go on to the west neighbour"
  },
  "7202": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "7204": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 0 = north"
  },
  "7206": {
   "unit": "game/mapGenerator6F00",
   "line": "mark north as tried"
  },
  "7208": {
   "unit": "game/mapGenerator6F00",
   "line": "row-1 above the top edge of the map?"
  },
  "720A": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - try west"
  },
  "720C": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $00 = north neighbour"
  },
  "720E": {
   "unit": "game/mapGenerator6F00",
   "line": "the north neighbour's cell"
  },
  "7210": {
   "unit": "game/mapGenerator6F00",
   "line": "only blank terrain can be painted"
  },
  "7212": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank - cannot grow there"
  },
  "7214": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the vertical spread"
  },
  "7217": {
   "unit": "game/mapGenerator6F00",
   "line": "accept while the random byte is below the vertical spread"
  },
  "721A": {
   "unit": "game/mapGenerator6F00",
   "line": "lost the roll - try west"
  },
  "721C": {
   "unit": "game/mapGenerator6F00",
   "line": "grow into the north neighbour (zp_A5/zp_A6 and Y already point at it)"
  },
  "721F": {
   "unit": "game/mapGenerator6F00",
   "line": "undo the -1: back to the cell's own row"
  },
  "7221": {
   "unit": "game/mapGenerator6F00",
   "line": "step one column west"
  },
  "7223": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "7225": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 1 = west already tried"
  },
  "7227": {
   "unit": "game/mapGenerator6F00",
   "line": "west already tried from this cell"
  },
  "7229": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "722B": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 1 = west"
  },
  "722D": {
   "unit": "game/mapGenerator6F00",
   "line": "mark west as tried"
  },
  "722F": {
   "unit": "game/mapGenerator6F00",
   "line": "column-1 off the left edge?"
  },
  "7231": {
   "unit": "game/mapGenerator6F00",
   "line": "column -1 is off the map"
  },
  "7233": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $27 = west neighbour (-1 column, +1 row from the pointer)"
  },
  "7235": {
   "unit": "game/mapGenerator6F00",
   "line": "the west neighbour's cell"
  },
  "7237": {
   "unit": "game/mapGenerator6F00",
   "line": "blank?"
  },
  "7239": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank"
  },
  "723B": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the horizontal spread"
  },
  "723E": {
   "unit": "game/mapGenerator6F00",
   "line": "accept while the random byte is below the horizontal spread"
  },
  "7241": {
   "unit": "game/mapGenerator6F00",
   "line": "grow into the west neighbour"
  },
  "7243": {
   "unit": "game/mapGenerator6F00",
   "line": "back to the cell's own column..."
  },
  "7245": {
   "unit": "game/mapGenerator6F00",
   "line": "two columns east: the cell's column + 1"
  },
  "7247": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "7249": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 2 = east already tried"
  },
  "724B": {
   "unit": "game/mapGenerator6F00",
   "line": "east already tried"
  },
  "724D": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "724F": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 2 = east"
  },
  "7251": {
   "unit": "game/mapGenerator6F00",
   "line": "mark east as tried"
  },
  "7253": {
   "unit": "game/mapGenerator6F00",
   "line": "the column the east neighbour sits in"
  },
  "7255": {
   "unit": "game/mapGenerator6F00",
   "line": "column 40 is off the right edge"
  },
  "7257": {
   "unit": "game/mapGenerator6F00",
   "line": "column 40 is off the map"
  },
  "7259": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $29 = east neighbour (+1 column, +1 row)"
  },
  "725B": {
   "unit": "game/mapGenerator6F00",
   "line": "the east neighbour's cell"
  },
  "725D": {
   "unit": "game/mapGenerator6F00",
   "line": "blank?"
  },
  "725F": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank"
  },
  "7261": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the horizontal spread"
  },
  "7264": {
   "unit": "game/mapGenerator6F00",
   "line": "horizontal spread again"
  },
  "7267": {
   "unit": "game/mapGenerator6F00",
   "line": "grow into the east neighbour"
  },
  "7269": {
   "unit": "game/mapGenerator6F00",
   "line": "back to the cell's own column"
  },
  "726B": {
   "unit": "game/mapGenerator6F00",
   "line": "step one row south"
  },
  "726D": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "726F": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 3 = south already tried"
  },
  "7271": {
   "unit": "game/mapGenerator6F00",
   "line": "south already tried"
  },
  "7273": {
   "unit": "game/mapGenerator6F00",
   "line": "tried-direction flags"
  },
  "7275": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 3 = south"
  },
  "7277": {
   "unit": "game/mapGenerator6F00",
   "line": "mark south as tried"
  },
  "7279": {
   "unit": "game/mapGenerator6F00",
   "line": "the row the south neighbour sits in"
  },
  "727B": {
   "unit": "game/mapGenerator6F00",
   "line": "row 40 is off the bottom edge"
  },
  "727D": {
   "unit": "game/mapGenerator6F00",
   "line": "row 40 is off the map"
  },
  "727F": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $50 = south neighbour (+2 rows)"
  },
  "7281": {
   "unit": "game/mapGenerator6F00",
   "line": "the south neighbour's cell"
  },
  "7283": {
   "unit": "game/mapGenerator6F00",
   "line": "blank?"
  },
  "7285": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank"
  },
  "7287": {
   "unit": "game/mapGenerator6F00",
   "line": "roll for the vertical spread"
  },
  "728A": {
   "unit": "game/mapGenerator6F00",
   "line": "vertical spread again"
  },
  "728D": {
   "unit": "game/mapGenerator6F00",
   "line": "grow into the south neighbour"
  },
  "728F": {
   "unit": "game/mapGenerator6F00",
   "line": "all four directions used up - pop the next cell"
  },
  "7292": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Paint the accepted cell (Y = its offset from zp_48/49) and push it on the stack."
   ],
   "line": "the candidate cell"
  },
  "7294": {
   "unit": "game/mapGenerator6F00",
   "line": "blank terrain?"
  },
  "7296": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank (only possible for the origin) - push it without painting"
  },
  "7298": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 = the 2x2 forest constraint"
  },
  "729A": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 clear - paint unconditionally"
  },
  "729C": {
   "unit": "game/mapGenerator6F00",
   "line": "forest: the aligned 2x2 block must contain only blank and forest"
  },
  "729F": {
   "unit": "game/mapGenerator6F00",
   "line": "block rejected - do not paint, but still expand from here"
  },
  "72A1": {
   "unit": "game/mapGenerator6F00",
   "line": "base tile for this pass"
  },
  "72A4": {
   "unit": "game/mapGenerator6F00",
   "line": "add a random variant (Y is preserved through a self-modified LDY at $7891+1)"
  },
  "72A7": {
   "unit": "game/mapGenerator6F00",
   "line": "paint the cell"
  },
  "72A9": {
   "unit": "game/mapGenerator6F00",
   "line": "one more cell of this blob placed"
  },
  "72AB": {
   "unit": "game/mapGenerator6F00",
   "line": "cells placed so far"
  },
  "72AD": {
   "unit": "game/mapGenerator6F00",
   "line": "reached the requested number of cells?"
  },
  "72AF": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - blob finished"
  },
  "72B1": {
   "unit": "game/mapGenerator6F00",
   "line": "y = the parent entry that is being expanded"
  },
  "72B3": {
   "unit": "game/mapGenerator6F00",
   "line": "the parent's flags with the direction just used marked as tried"
  },
  "72B5": {
   "unit": "game/mapGenerator6F00",
   "line": "$04A0[parent] = its updated tried-direction flags"
  },
  "72B8": {
   "unit": "game/mapGenerator6F00",
   "line": "the child entry goes one slot higher"
  },
  "72B9": {
   "unit": "game/mapGenerator6F00",
   "line": "the accepted cell's column"
  },
  "72BB": {
   "unit": "game/mapGenerator6F00",
   "line": "$0400[child] = column"
  },
  "72BE": {
   "unit": "game/mapGenerator6F00",
   "line": "and its row"
  },
  "72C0": {
   "unit": "game/mapGenerator6F00",
   "line": "$0450[child] = row"
  },
  "72C3": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Pre-mark the direction back towards the blob origin as already tried, so a blob never folds",
    "back on itself."
   ],
   "line": "clear A"
  },
  "72C5": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_1A = the child's preset flags"
  },
  "72C7": {
   "unit": "game/mapGenerator6F00",
   "line": "$02 = 'west already tried'"
  },
  "72C9": {
   "unit": "game/mapGenerator6F00",
   "line": "the child's column"
  },
  "72CB": {
   "unit": "game/mapGenerator6F00",
   "line": "child column against the blob origin column"
  },
  "72CD": {
   "unit": "game/mapGenerator6F00",
   "line": "same column - no horizontal bias"
  },
  "72CF": {
   "unit": "game/mapGenerator6F00",
   "line": "child is east of the origin - block growth back west"
  },
  "72D1": {
   "unit": "game/mapGenerator6F00",
   "line": "$04 = 'east already tried' (child is west of the origin)"
  },
  "72D3": {
   "unit": "game/mapGenerator6F00",
   "line": "horizontal bias"
  },
  "72D5": {
   "unit": "game/mapGenerator6F00",
   "line": "$01 = 'north already tried'"
  },
  "72D7": {
   "unit": "game/mapGenerator6F00",
   "line": "the child's row"
  },
  "72D9": {
   "unit": "game/mapGenerator6F00",
   "line": "child row against the blob origin row"
  },
  "72DB": {
   "unit": "game/mapGenerator6F00",
   "line": "same row - no vertical bias"
  },
  "72DD": {
   "unit": "game/mapGenerator6F00",
   "line": "child is below the origin - block growth back north"
  },
  "72DF": {
   "unit": "game/mapGenerator6F00",
   "line": "$08 = 'south already tried' (child is above the origin)"
  },
  "72E1": {
   "unit": "game/mapGenerator6F00",
   "line": "combine with the horizontal bias"
  },
  "72E3": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_1A = the child's preset tried-direction flags"
  },
  "72E5": {
   "unit": "game/mapGenerator6F00",
   "line": "the child's preset tried-direction flags"
  },
  "72E7": {
   "unit": "game/mapGenerator6F00",
   "line": "$04A0[child] = its preset flags"
  },
  "72EA": {
   "unit": "game/mapGenerator6F00",
   "line": "point one past the child entry"
  },
  "72EB": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_B2 = new fill level = child + 1"
  },
  "72ED": {
   "unit": "game/mapGenerator6F00",
   "line": "80 entries is all that fits ($0400/$0450/$04A0 x 80 = $0400-$04EF)"
  },
  "72EF": {
   "unit": "game/mapGenerator6F00",
   "line": "still room on the stack"
  },
  "72F1": {
   "unit": "game/mapGenerator6F00",
   "line": "stack full - abandon this blob"
  },
  "72F2": {
   "unit": "game/mapGenerator6F00",
   "line": "expand the cell just pushed"
  },
  "72F5": {
   "unit": "game/mapGenerator6F00",
   "line": "blob finished: cell count reached, or the stack ran dry"
  },
  "72F6": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "checkAlignedBlockForForest - constrains forest to whole 2x2 blocks on an even grid.  It takes the",
    "block containing (zp_A5,zp_A6) - both coordinates rounded down to even - and returns C = 0 only if",
    "all four cells are terrain class 0 (blank $40) or class 2 (forest $5D-$60).  On success zp_48/49",
    "is re-pointed at the caller's own cell with Y = 0, so the caller can store straight through it.",
    "Note that the river keep-clear markers $80/$81 index past terrainClassTable into the zero filler",
    "at $07F3, so they read as class 0 here; growTerrainBlob's own $40 test still refuses to paint them.",
    "In:  zp_A5/zp_A6 = the cell, map, terrainClassTable $077E",
    "Out: C = 0 accept / C = 1 reject; zp_48/49, A/X/Y clobbered",
    "Called from: growTerrainBlob ($729C) when $0304 bit 6 is set"
   ],
   "line": "column of the cell about to be painted"
  },
  "72F8": {
   "unit": "game/mapGenerator6F00",
   "line": "round the column down to the even grid"
  },
  "72FA": {
   "unit": "game/mapGenerator6F00",
   "line": "X = block column"
  },
  "72FB": {
   "unit": "game/mapGenerator6F00",
   "line": "its row"
  },
  "72FD": {
   "unit": "game/mapGenerator6F00",
   "line": "round the row down as well"
  },
  "72FF": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = block row"
  },
  "7300": {
   "unit": "game/mapGenerator6F00",
   "line": "A = the block's top-left cell, zp_48/49 -> it, Y = 0"
  },
  "7303": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "7304": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of that cell"
  },
  "7307": {
   "unit": "game/mapGenerator6F00",
   "line": "class 0 = blank: acceptable"
  },
  "7309": {
   "unit": "game/mapGenerator6F00",
   "line": "class 2 = forest: also acceptable"
  },
  "730B": {
   "unit": "game/mapGenerator6F00",
   "line": "anything else (river, hill, contour, unit) rejects the block"
  },
  "730D": {
   "unit": "game/mapGenerator6F00",
   "line": "offset 1 = top-right cell"
  },
  "730E": {
   "unit": "game/mapGenerator6F00",
   "line": "the top-right cell of the block"
  },
  "7310": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "7311": {
   "unit": "game/mapGenerator6F00",
   "line": "its terrain class"
  },
  "7314": {
   "unit": "game/mapGenerator6F00",
   "line": "blank"
  },
  "7316": {
   "unit": "game/mapGenerator6F00",
   "line": "or forest"
  },
  "7318": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank or forest - reject the block"
  },
  "731A": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $28 = bottom-left cell"
  },
  "731C": {
   "unit": "game/mapGenerator6F00",
   "line": "the bottom-left cell of the block"
  },
  "731E": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "731F": {
   "unit": "game/mapGenerator6F00",
   "line": "its terrain class"
  },
  "7322": {
   "unit": "game/mapGenerator6F00",
   "line": "blank"
  },
  "7324": {
   "unit": "game/mapGenerator6F00",
   "line": "or forest"
  },
  "7326": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank or forest - reject the block"
  },
  "7328": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $29 = bottom-right cell"
  },
  "7329": {
   "unit": "game/mapGenerator6F00",
   "line": "the bottom-right cell of the block"
  },
  "732B": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "732C": {
   "unit": "game/mapGenerator6F00",
   "line": "its terrain class"
  },
  "732F": {
   "unit": "game/mapGenerator6F00",
   "line": "blank"
  },
  "7331": {
   "unit": "game/mapGenerator6F00",
   "line": "or forest"
  },
  "7333": {
   "unit": "game/mapGenerator6F00",
   "line": "not blank or forest - reject the block"
  },
  "7335": {
   "unit": "game/mapGenerator6F00",
   "line": "the caller's own column"
  },
  "7337": {
   "unit": "game/mapGenerator6F00",
   "line": "and row"
  },
  "7339": {
   "unit": "game/mapGenerator6F00",
   "line": "re-point zp_48/49 at the caller's own cell (leaves Y = 0)"
  },
  "733C": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0: this block may be forested"
  },
  "733D": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0 from $733C"
  },
  "733E": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1: the block holds something else"
  },
  "733F": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1 set at $733E"
  },
  "7340": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "placeForestClusters - the last terrain pass.  Rolls a number of forest clusters (3-10 normally,",
    "with a 1-in-32 chance of no forest at all; exactly 10 for QB SNEAK; 1-4 for DEFENDER), gives each",
    "cluster a random centre at column/row 4-35 and scatters 6 seed points around it (+/-16 columns,",
    "+/-8 rows, re-rolled while off the map).  Every seed becomes a 4x2 patch of small blobs through",
    "paintForestClusterSeeds.  Blob flags $40 make all of it respect the 2x2 forest grid.",
    "In:  $032E map style, scenario RNG",
    "Out: forest tiles $5D-$60 in the map; $0301, $0302, $0304, zp_2A cluster counter, zp_2B seed",
    "     counter, zp_92-zp_95, zp_A5/zp_A6",
    "Called from: runMapGeneratorPasses ($6F6F)"
   ],
   "line": "blob flag bit 6: forest only grows inside a clean aligned 2x2 block"
  },
  "7342": {
   "unit": "game/mapGenerator6F00",
   "line": "$0304 blob flags"
  },
  "7345": {
   "unit": "game/mapGenerator6F00",
   "line": "$41 = upper contour tile"
  },
  "7347": {
   "unit": "game/mapGenerator6F00",
   "line": "dead store: nothing in this overlay ever reads $0302 (XREF has no reader)"
  },
  "734A": {
   "unit": "game/mapGenerator6F00",
   "line": "$5D = forest tile ($5D-$60 variants), terrain class 2"
  },
  "734C": {
   "unit": "game/mapGenerator6F00",
   "line": "$0301 = the tile growTerrainBlob paints"
  },
  "734F": {
   "unit": "game/mapGenerator6F00",
   "line": "QB SNEAK: 9 -> ten clusters, a deliberately cluttered field"
  },
  "7351": {
   "unit": "game/mapGenerator6F00",
   "line": "mapGenGameFlags"
  },
  "7354": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 = QB SNEAK style - keep the fixed count"
  },
  "7356": {
   "unit": "game/mapGenerator6F00",
   "line": "roll the cluster count"
  },
  "7359": {
   "unit": "game/mapGenerator6F00",
   "line": "0-31"
  },
  "735B": {
   "unit": "game/mapGenerator6F00",
   "line": "1 chance in 32 of a completely bare map"
  },
  "735D": {
   "unit": "game/mapGenerator6F00",
   "line": "0-7..."
  },
  "735F": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "7360": {
   "unit": "game/mapGenerator6F00",
   "line": "...+2, so 3-10 clusters in total"
  },
  "7362": {
   "unit": "game/mapGenerator6F00",
   "line": "mapGenGameFlags"
  },
  "7365": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 6 clear - not DEFENDER"
  },
  "7367": {
   "unit": "game/mapGenerator6F00",
   "line": "DEFENDER: at most 3, i.e. 1-4 clusters (the map has to stay open)"
  },
  "7369": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2A = clusters left minus one"
  },
  "736B": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Per cluster: pick a centre, then scatter six seed patches around it."
   ],
   "line": "roll the cluster centre column"
  },
  "736E": {
   "unit": "game/mapGenerator6F00",
   "line": "0-31"
  },
  "7370": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "7371": {
   "unit": "game/mapGenerator6F00",
   "line": "cluster centre column 4-35"
  },
  "7373": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_95 = centre column, the base for the column jitter"
  },
  "7375": {
   "unit": "game/mapGenerator6F00",
   "line": "vestigial: growTerrainBlob overwrites zp_A6 at once, and this is a column, not a row"
  },
  "7377": {
   "unit": "game/mapGenerator6F00",
   "line": "roll the cluster centre row"
  },
  "737A": {
   "unit": "game/mapGenerator6F00",
   "line": "0-31"
  },
  "737C": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the add"
  },
  "737D": {
   "unit": "game/mapGenerator6F00",
   "line": "cluster centre row 4-35"
  },
  "737F": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_94 = centre row, the base for the row jitter"
  },
  "7381": {
   "unit": "game/mapGenerator6F00",
   "line": "vestigial in the same way (a row written to the view-origin column)"
  },
  "7383": {
   "unit": "game/mapGenerator6F00",
   "line": "six seeds per cluster (5 down through 0)"
  },
  "7385": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2B = six seed points per cluster (5 down through 0)"
  },
  "7387": {
   "unit": "game/mapGenerator6F00",
   "line": "centre row"
  },
  "7389": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 4 jitter steps = an offset of 0, +/-2, +/-4, +/-6 or +/-8 rows"
  },
  "738B": {
   "unit": "game/mapGenerator6F00",
   "line": "scatter the seed row around the cluster centre"
  },
  "738E": {
   "unit": "game/mapGenerator6F00",
   "line": "still on the map?"
  },
  "7390": {
   "unit": "game/mapGenerator6F00",
   "line": "off the map - roll the row again"
  },
  "7392": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_92 = seed row"
  },
  "7394": {
   "unit": "game/mapGenerator6F00",
   "line": "centre column"
  },
  "7396": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = 8 jitter steps = up to +/-16 columns, so clusters are wide"
  },
  "7398": {
   "unit": "game/mapGenerator6F00",
   "line": "scatter the seed column around the cluster centre"
  },
  "739B": {
   "unit": "game/mapGenerator6F00",
   "line": "still on the map?"
  },
  "739D": {
   "unit": "game/mapGenerator6F00",
   "line": "off the map - roll the column again"
  },
  "739F": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_93 = seed column"
  },
  "73A1": {
   "unit": "game/mapGenerator6F00",
   "line": "paint the 4x2 patch of blobs around this seed"
  },
  "73A4": {
   "unit": "game/mapGenerator6F00",
   "line": "one seed done"
  },
  "73A6": {
   "unit": "game/mapGenerator6F00",
   "line": "six seeds per cluster"
  },
  "73A8": {
   "unit": "game/mapGenerator6F00",
   "line": "one cluster done"
  },
  "73AA": {
   "unit": "game/mapGenerator6F00",
   "line": "next cluster"
  },
  "73AC": {
   "unit": "game/mapGenerator6F00",
   "line": "all forest placed"
  },
  "73AD": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "paintForestClusterSeeds - paints eight small forest blobs covering the 4x2 cell block from",
    "column zp_93-2 to zp_93+1 and rows zp_92 to zp_92+1, walking it in the order (c,r), (c+1,r),",
    "(c+1,r+1), (c,r+1), (c-2,r), (c-1,r), (c-1,r+1) and finally (c-2,r+1) by fall-through.  Because",
    "the block is four columns wide it always covers two whole 2x2 forest blocks.",
    "In:  zp_93 = seed column, zp_92 = seed row, $0301/$0304 from placeForestClusters",
    "Out: forest painted; on exit zp_93 = c-2 and zp_92 = r+1 (they are not restored - the caller",
    "     re-rolls both for the next seed)",
    "Called from: placeForestClusters ($73A1)"
   ],
   "line": "seed (c,r)"
  },
  "73B0": {
   "unit": "game/mapGenerator6F00",
   "line": "-> column c+1"
  },
  "73B2": {
   "unit": "game/mapGenerator6F00",
   "line": "(c+1,r)"
  },
  "73B5": {
   "unit": "game/mapGenerator6F00",
   "line": "-> row r+1"
  },
  "73B7": {
   "unit": "game/mapGenerator6F00",
   "line": "(c+1,r+1)"
  },
  "73BA": {
   "unit": "game/mapGenerator6F00",
   "line": "-> column c"
  },
  "73BC": {
   "unit": "game/mapGenerator6F00",
   "line": "(c,r+1)"
  },
  "73BF": {
   "unit": "game/mapGenerator6F00",
   "line": "-> column c-1"
  },
  "73C1": {
   "unit": "game/mapGenerator6F00",
   "line": "-> column c-2"
  },
  "73C3": {
   "unit": "game/mapGenerator6F00",
   "line": "-> row r"
  },
  "73C5": {
   "unit": "game/mapGenerator6F00",
   "line": "(c-2,r)"
  },
  "73C8": {
   "unit": "game/mapGenerator6F00",
   "line": "-> column c-1"
  },
  "73CA": {
   "unit": "game/mapGenerator6F00",
   "line": "(c-1,r)"
  },
  "73CD": {
   "unit": "game/mapGenerator6F00",
   "line": "-> row r+1"
  },
  "73CF": {
   "unit": "game/mapGenerator6F00",
   "line": "(c-1,r+1)"
  },
  "73D2": {
   "unit": "game/mapGenerator6F00",
   "line": "-> column c-2, then fall through for the eighth seed (c-2,r+1)"
  },
  "73D4": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "paintForestBlobAt - grows one 4-cell forest blob at (zp_93,zp_92) if both coordinates are inside",
    "the 40x40 map; out-of-range coordinates (including the $FF a DEC produced at column 0) are",
    "silently ignored.  Spread is 220/256 in both axes, so the blobs are compact and round.",
    "In:  zp_93 column, zp_92 row, $0301 tile, $0304 flags",
    "Out: up to 4 forest cells; zp_A7/zp_A8 = the blob origin",
    "Called from: paintForestClusterSeeds (all eight seeds, $73AD-$73D2 and by fall-through)"
   ],
   "line": "seed column"
  },
  "73D6": {
   "unit": "game/mapGenerator6F00",
   "line": "columns 0-39 only"
  },
  "73D8": {
   "unit": "game/mapGenerator6F00",
   "line": "off the map (or wrapped to $FF by a DEC) - ignore this seed"
  },
  "73DA": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A7 = blob origin column"
  },
  "73DC": {
   "unit": "game/mapGenerator6F00",
   "line": "seed row"
  },
  "73DE": {
   "unit": "game/mapGenerator6F00",
   "line": "rows 0-39 only"
  },
  "73E0": {
   "unit": "game/mapGenerator6F00",
   "line": "off the map - ignore"
  },
  "73E2": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A8 = blob origin row"
  },
  "73E4": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = vertical spread 220/256"
  },
  "73E6": {
   "unit": "game/mapGenerator6F00",
   "line": "X = horizontal spread 220/256 - forest grows evenly in all directions"
  },
  "73E8": {
   "unit": "game/mapGenerator6F00",
   "line": "A = 4 cells per seed"
  },
  "73EA": {
   "unit": "game/mapGenerator6F00",
   "line": "grow the blob"
  },
  "73ED": {
   "unit": "game/mapGenerator6F00",
   "line": "seed outside the map, or blob finished"
  },
  "73EE": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "applyContourTiles - draws the contour ring around a hill layer.  A is the layer's interior tile",
    "($65 summit or $61 lower hill); zp_8E becomes its terrain class (6 or 4) and zp_91 the class of",
    "its ring (5 or 3).  All 1600 cells are scanned in order: a cell that already holds a ring tile of",
    "this layer is erased to blank and re-evaluated, cells of the interior class or higher and river",
    "cells (class 1) are left alone, and everything else is handed to applyContourRuleAtCell.  When",
    "that returns C = 1 it has changed a cell that earlier cells depended on, so the scan is backed up",
    "two columns and two rows and continues from there until the whole map is stable.",
    "In:  A = interior tile, $0324 = contour offset (0 for $41-$54, $20 for $21-$34), contour rule",
    "     table at $0200, terrainClassTable $077E, map",
    "Out: contour tiles in the map; $0312 = interior tile, zp_8E, zp_91, zp_2D/zp_2E scan position,",
    "     zp_8C/zp_8D random-bit state, zp_21",
    "Called from: runMapGeneratorPasses ($6F54 with $65, $6F69 with $61)"
   ],
   "line": "$0312 = the interior tile this pass belongs to"
  },
  "73F1": {
   "unit": "game/mapGenerator6F00",
   "line": "use the tile code as the class-table index"
  },
  "73F2": {
   "unit": "game/mapGenerator6F00",
   "line": "its terrain class: 6 for the summit, 4 for the lower hill"
  },
  "73F5": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_8E = the 'high ground' class for the neighbour test"
  },
  "73F7": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_91 starts as the interior class..."
  },
  "73F9": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_91 = class of this layer's contour ring (5 or 3)"
  },
  "73FB": {
   "unit": "game/mapGenerator6F00",
   "line": "clear A for the three stores below"
  },
  "73FD": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_8C = 0: force a fresh random byte on the first irregular rule"
  },
  "73FF": {
   "unit": "game/mapGenerator6F00",
   "line": "column 0"
  },
  "7401": {
   "unit": "game/mapGenerator6F00",
   "line": "start the scan at cell (0,0)"
  },
  "7403": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Scan every cell of the map.  zp_2E/zp_2D are the cell; zp_48/49 addresses the top-left corner of",
    "its 3x3 block, so the cell itself is at offset $29."
   ],
   "line": "X = scan column"
  },
  "7405": {
   "unit": "game/mapGenerator6F00",
   "line": "Y = scan row"
  },
  "7407": {
   "unit": "game/mapGenerator6F00",
   "line": "step back one column to the block corner"
  },
  "7408": {
   "unit": "game/mapGenerator6F00",
   "line": "address the block corner (column-1,row-1)"
  },
  "7409": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A5 = column-1"
  },
  "740B": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_A6 = row-1"
  },
  "740D": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_48/49 -> the corner, clipped correctly for negative coordinates"
  },
  "7410": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $29 = the cell itself"
  },
  "7412": {
   "unit": "game/mapGenerator6F00",
   "line": "the cell's terrain code"
  },
  "7414": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 = a unit or a river keep-clear marker - never touched"
  },
  "7416": {
   "unit": "game/mapGenerator6F00",
   "line": "use it as the class-table index"
  },
  "7417": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of the cell"
  },
  "741A": {
   "unit": "game/mapGenerator6F00",
   "line": "is it already a ring tile of this layer?"
  },
  "741C": {
   "unit": "game/mapGenerator6F00",
   "line": "yes - erase it so the rule table can redraw it"
  },
  "741E": {
   "unit": "game/mapGenerator6F00",
   "line": "class above the ring = hill interior or higher - leave it"
  },
  "7420": {
   "unit": "game/mapGenerator6F00",
   "line": "class 1 = river"
  },
  "7422": {
   "unit": "game/mapGenerator6F00",
   "line": "not the river - run the rule"
  },
  "7424": {
   "unit": "game/mapGenerator6F00",
   "line": "river cells are never overwritten by a contour"
  },
  "7426": {
   "unit": "game/mapGenerator6F00",
   "line": "$40 = blank"
  },
  "7428": {
   "unit": "game/mapGenerator6F00",
   "line": "erase the stale ring tile"
  },
  "742A": {
   "unit": "game/mapGenerator6F00",
   "line": "let the neighbourhood rule table decide what this cell becomes"
  },
  "742D": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1: a neighbour changed, restart from the backed-up position"
  },
  "742F": {
   "unit": "game/mapGenerator6F00",
   "line": "next column"
  },
  "7431": {
   "unit": "game/mapGenerator6F00",
   "line": "the column just finished"
  },
  "7433": {
   "unit": "game/mapGenerator6F00",
   "line": "columns 0-39"
  },
  "7435": {
   "unit": "game/mapGenerator6F00",
   "line": "not at the right edge yet"
  },
  "7437": {
   "unit": "game/mapGenerator6F00",
   "line": "next row"
  },
  "7439": {
   "unit": "game/mapGenerator6F00",
   "line": "column 0 of the next row"
  },
  "743B": {
   "unit": "game/mapGenerator6F00",
   "line": "back to column 0"
  },
  "743D": {
   "unit": "game/mapGenerator6F00",
   "line": "the row just finished"
  },
  "743F": {
   "unit": "game/mapGenerator6F00",
   "line": "rows 0-39"
  },
  "7441": {
   "unit": "game/mapGenerator6F00",
   "line": "not at the bottom yet"
  },
  "7443": {
   "unit": "game/mapGenerator6F00",
   "line": "the whole map is stable"
  },
  "7444": {
   "unit": "game/mapGenerator6F00",
   "routine": [
    "applyContourRuleAtCell - decides what one cell becomes, from which of its eight neighbours are",
    "high ground.  It builds an 8-bit mask (bit 0 NW, 1 N, 2 NE, 3 W, 4 E, 5 SW, 6 S, 7 SE) of the",
    "neighbours whose terrain class is >= zp_8E, clears the bits that would point off the map, and uses",
    "the mask as the index into the 256-byte rule table at $0200 (track 18 sector 15):",
    "  $00       leave the cell alone, C = 0",
    "  $01-$7F   paint that tile minus the contour offset $0324, with a random variant, C = 0",
    "  $80-$8F   irregular: 50% chance (bit taken from a random byte, 7 bits per byte) to erase the",
    "            neighbour named by the low 3 bits when it is of the interior class; otherwise fill",
    "            the cell with the interior tile.  Either way C = 1",
    "  $90-$FE   same 50% erase attempt, but if it does not fire the cell is left alone, C = 0",
    "  $FF       fill the cell with the interior tile $0312, C = 1",
    "C = 1 also backs the scan position zp_2E/zp_2D up by two columns and two rows (floored at 0) so",
    "applyContourTiles re-examines the cells around the change.",
    "In:  zp_2E/zp_2D = the cell, zp_48/49 -> its 3x3 block corner, zp_8E interior class, $0312",
    "     interior tile, $0324 contour offset, rule table $0200, terrainClassTable $077E",
    "Out: C flag, map cells changed, zp_2D/zp_2E, zp_21 mask, zp_18 rule value, zp_8C/zp_8D random bits",
    "Called from: applyContourTiles ($742A)"
   ],
   "block": [
    "Build the high-ground neighbour mask, bit 7 (SE) down to bit 0 (NW)."
   ],
   "line": "clear the neighbour mask"
  },
  "7446": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_21 = neighbour mask"
  },
  "7448": {
   "unit": "game/mapGenerator6F00",
   "line": "walk the eight neighbours backwards: 7 = SE .. 0 = NW"
  },
  "744A": {
   "unit": "game/mapGenerator6F00",
   "line": "offset of neighbour X from the block corner"
  },
  "744D": {
   "unit": "game/mapGenerator6F00",
   "line": "that neighbour's terrain code"
  },
  "744F": {
   "unit": "game/mapGenerator6F00",
   "line": "bit 7 = unit or keep-clear marker - not high ground"
  },
  "7451": {
   "unit": "game/mapGenerator6F00",
   "line": "use it as the class-table index"
  },
  "7452": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of the neighbour"
  },
  "7455": {
   "unit": "game/mapGenerator6F00",
   "line": "high ground = class >= the interior class of this pass"
  },
  "7457": {
   "unit": "game/mapGenerator6F00",
   "line": "lower - leave the bit clear"
  },
  "7459": {
   "unit": "game/mapGenerator6F00",
   "line": "mask built so far"
  },
  "745B": {
   "unit": "game/mapGenerator6F00",
   "line": "bit X: NW,N,NE,W,E,SW,S,SE = bits 0-7"
  },
  "745E": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_21 = mask so far"
  },
  "7460": {
   "unit": "game/mapGenerator6F00",
   "line": "next neighbour"
  },
  "7461": {
   "unit": "game/mapGenerator6F00",
   "line": "all eight neighbours"
  },
  "7463": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Clear the mask bits that point off the edge of the 40x40 map."
   ],
   "line": "the cell's own column"
  },
  "7465": {
   "unit": "game/mapGenerator6F00",
   "line": "its row"
  },
  "7467": {
   "unit": "game/mapGenerator6F00",
   "line": "the raw mask"
  },
  "7469": {
   "unit": "game/mapGenerator6F00",
   "line": "on the left edge?"
  },
  "746B": {
   "unit": "game/mapGenerator6F00",
   "line": "not on the left edge"
  },
  "746D": {
   "unit": "game/mapGenerator6F00",
   "line": "$D6 clears bits 0/3/5 = NW, W, SW"
  },
  "746F": {
   "unit": "game/mapGenerator6F00",
   "line": "on the right edge (column 39)?"
  },
  "7471": {
   "unit": "game/mapGenerator6F00",
   "line": "not on the right edge"
  },
  "7473": {
   "unit": "game/mapGenerator6F00",
   "line": "$6B clears bits 2/4/7 = NE, E, SE"
  },
  "7475": {
   "unit": "game/mapGenerator6F00",
   "line": "on the top edge?"
  },
  "7477": {
   "unit": "game/mapGenerator6F00",
   "line": "not on the top edge"
  },
  "7479": {
   "unit": "game/mapGenerator6F00",
   "line": "$F8 clears bits 0/1/2 = NW, N, NE"
  },
  "747B": {
   "unit": "game/mapGenerator6F00",
   "line": "on the bottom edge (row 39)?"
  },
  "747D": {
   "unit": "game/mapGenerator6F00",
   "line": "not on the bottom edge"
  },
  "747F": {
   "unit": "game/mapGenerator6F00",
   "line": "$1F clears bits 5/6/7 = SW, S, SE"
  },
  "7481": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_21 = the clipped mask"
  },
  "7483": {
   "unit": "game/mapGenerator6F00",
   "line": "use it as the rule-table index"
  },
  "7484": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "Look the neighbourhood up in the 256-byte contour rule table loaded to $0200 from track 18",
    "sector 15."
   ],
   "line": "rule byte for this exact neighbourhood"
  },
  "7487": {
   "unit": "game/mapGenerator6F00",
   "line": "$00 = this neighbourhood needs no contour - leave the cell (C = 0)"
  },
  "7489": {
   "unit": "game/mapGenerator6F00",
   "line": "$01-$7F = a contour tile code - paint it"
  },
  "748B": {
   "unit": "game/mapGenerator6F00",
   "line": "$FF = the cell is surrounded, fill it with the hill interior"
  },
  "748D": {
   "unit": "game/mapGenerator6F00",
   "line": "fill the cell with the interior tile and force a rescan"
  },
  "748F": {
   "unit": "game/mapGenerator6F00",
   "line": "$80-$FE: irregular rule; zp_18 keeps the value"
  },
  "7491": {
   "unit": "game/mapGenerator6F00",
   "line": "any random bits left in zp_8D?"
  },
  "7493": {
   "unit": "game/mapGenerator6F00",
   "line": "yes"
  },
  "7495": {
   "unit": "game/mapGenerator6F00",
   "line": "seven bits per random byte: counter 6 down through 0"
  },
  "7497": {
   "unit": "game/mapGenerator6F00",
   "line": "seven bits are taken from each random byte"
  },
  "7499": {
   "unit": "game/mapGenerator6F00",
   "line": "fetch a fresh batch of random bits"
  },
  "749C": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_8D = fresh random bits"
  },
  "749E": {
   "unit": "game/mapGenerator6F00",
   "line": "shift out the next bit"
  },
  "74A0": {
   "unit": "game/mapGenerator6F00",
   "line": "bit clear - do not erase a neighbour this time"
  },
  "74A2": {
   "unit": "game/mapGenerator6F00",
   "line": "the rule value"
  },
  "74A4": {
   "unit": "game/mapGenerator6F00",
   "line": "low 3 bits of the rule value = which neighbour it wants removed"
  },
  "74A6": {
   "unit": "game/mapGenerator6F00",
   "line": "neighbour index 0-7"
  },
  "74A7": {
   "unit": "game/mapGenerator6F00",
   "line": "its offset from the block corner"
  },
  "74AA": {
   "unit": "game/mapGenerator6F00",
   "line": "that neighbour's terrain code"
  },
  "74AC": {
   "unit": "game/mapGenerator6F00",
   "line": "unit or marker - leave it alone"
  },
  "74AE": {
   "unit": "game/mapGenerator6F00",
   "line": "use the terrain code as the class-table index"
  },
  "74AF": {
   "unit": "game/mapGenerator6F00",
   "line": "terrain class of that neighbour"
  },
  "74B2": {
   "unit": "game/mapGenerator6F00",
   "line": "only a cell of the interior class may be nibbled away"
  },
  "74B4": {
   "unit": "game/mapGenerator6F00",
   "line": "not a cell of the hill interior - leave it alone"
  },
  "74B6": {
   "unit": "game/mapGenerator6F00",
   "line": "$40 = blank"
  },
  "74B8": {
   "unit": "game/mapGenerator6F00",
   "line": "erase the neighbour - this is what makes hill edges irregular"
  },
  "74BA": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1 and back the scan up"
  },
  "74BD": {
   "unit": "game/mapGenerator6F00",
   "line": "the rule value again"
  },
  "74BF": {
   "unit": "game/mapGenerator6F00",
   "line": "rule values $90-$FE..."
  },
  "74C1": {
   "unit": "game/mapGenerator6F00",
   "line": "...leave the cell untouched when the erase did not fire (C = 0)"
  },
  "74C3": {
   "unit": "game/mapGenerator6F00",
   "line": "values $80-$8F (and $FF): fill the cell with the hill interior tile"
  },
  "74C6": {
   "unit": "game/mapGenerator6F00",
   "line": "write it into the centre cell"
  },
  "74C9": {
   "unit": "game/mapGenerator6F00",
   "block": [
    "A cell changed under the scan: back up two columns and two rows so applyContourTiles",
    "re-evaluates the neighbourhood, and return C = 1."
   ],
   "line": "current scan column"
  },
  "74CB": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the subtract"
  },
  "74CC": {
   "unit": "game/mapGenerator6F00",
   "line": "two columns back"
  },
  "74CE": {
   "unit": "game/mapGenerator6F00",
   "line": "still positive"
  },
  "74D0": {
   "unit": "game/mapGenerator6F00",
   "line": "but never before column 0"
  },
  "74D2": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2E = backed-up scan column"
  },
  "74D4": {
   "unit": "game/mapGenerator6F00",
   "line": "current scan row"
  },
  "74D6": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the subtract"
  },
  "74D7": {
   "unit": "game/mapGenerator6F00",
   "line": "two rows back"
  },
  "74D9": {
   "unit": "game/mapGenerator6F00",
   "line": "still positive"
  },
  "74DB": {
   "unit": "game/mapGenerator6F00",
   "line": "but never before row 0"
  },
  "74DD": {
   "unit": "game/mapGenerator6F00",
   "line": "zp_2D = backed-up scan row"
  },
  "74DF": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1: applyContourTiles restarts its scan here"
  },
  "74E0": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 1 set at $74DF"
  },
  "74E1": {
   "unit": "game/mapGenerator6F00",
   "line": "prepare the subtract"
  },
  "74E2": {
   "unit": "game/mapGenerator6F00",
   "line": "tile = rule value - $0324: offset 0 keeps $41-$54, offset $20 gives $21-$34"
  },
  "74E5": {
   "unit": "game/mapGenerator6F00",
   "line": "offset $29 = the cell itself"
  },
  "74E7": {
   "unit": "game/mapGenerator6F00",
   "line": "pick a random variant of the tile (Y is preserved)"
  },
  "74EA": {
   "unit": "game/mapGenerator6F00",
   "line": "paint the contour tile"
  },
  "74EC": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0: the scan carries on normally"
  },
  "74ED": {
   "unit": "game/mapGenerator6F00",
   "line": "C = 0 set at $74EC"
  }
 },
 "dataTypes": {
  "6F00": [
   "byte",
   4
  ],
  "71AB": [
   "byte",
   5
  ]
 },
 "zpComments": {
  "1D": "general scratch: bounds mode flag of computeGroupBounds (bit 7 = use destinations), division remainder (hi); the map generator holds the candidate row of the hill site being placed",
  "1E": "general scratch: running terrain height in the line-of-sight walk, decimal digit index, group destination centre column; the map generator counts the column attempts left for a hill site",
  "1F": "general scratch: line-of-sight rise flag, divide bit counter, group destination centre row; the map generator remembers which candidate row a hill site started on",
  "28": "map row of point B (the centre/reference point) for distanceSquared and cellDistance; the map generator reuses it as the highest valid index of the hill row-candidate list $0325",
  "29": "index of the last entry written to the area-scan result lists at $0400/$0432/$0464 ($FF = empty); the map generator reuses it as the current index into the hill row-candidate list $0325",
  "8E": "line stepper: length of the line along its major axis, max(|dRow|,|dCol|); the contour passes reuse it as the terrain class that counts as high ground (6 summit, 4 lower hill)",
  "91": "line stepper: steps still to walk (0 = finished); returned in A by initLineStepper/stepLine; the contour passes reuse it as the terrain class of the ring being redrawn (5 or 3)",
  "B3": "high byte of glyphPtr; growTerrainBlob reuses it as the count of cells painted so far",
  "A5": "map column of the left edge of the 7x5 battlefield view (may be negative); the cursor cell is viewOriginCol+3; the map generator reuses it as the column of the cell being painted or scanned",
  "A6": "map row of the top edge of the battlefield view; the cursor cell is viewOriginRow+2; the map generator reuses it as the row of the cell being painted or scanned"
 }
}
