All pastes #30664 Raw Edit

Stuff

public text v1 · immutable
#30664 ·published 2005-11-23 19:32 UTC
rendered paste body
% -------------- TURING WARS.T

% Declare the unit type
type units :
    record
        name, unitType, targetType : string
        typeNum, attack, defense, attackRng, moveRng, los, currentHP, totalHP, locX, locY, team : int
    end record

type point :
    record
        x, y, parentX, parentY : int
    end record

% Declare the unit properties
var unitNames : array 1 .. 3 of string := init ("Infantry", "Tank", "Artilery")
var unitGraphics : array 1 .. 3 of string := init ("I", "T", "A")                   % Just strings for now. Pictures later :)
var unitTypes : array 1 .. 3 of string := init ("ground,light", "ground,med", "ground,moveCountd")
var unitTargets : array 1 .. 3 of string := init ("ground,lowair", "ground", "ground,sea")
var unitAttackVals : array 1 .. 3 of int := init (1, 3, 3)
var unitDefVals : array 1 .. 3 of int := init (1, 3, 2)
var unitAttackRng : array 1 .. 3 of int := init (1, 1, 3)
var unitMoveRng : array 1 .. 3 of int := init (1, 3, 2)
var unitHP : array 1 .. 3 of int := init (5, 15, 10)
var unitLOS : array 1 .. 3 of int := init (2, 3, 4)

% Fonts, pictures, etc.
var verdana := Font.New ("verdana:10")
var verdanaBold := Font.New ("verdana:12:bold")

% Declare the terrain constants
const CITY := 1
const GRASS := 2
const FOREST := 3
const MOUNTAIN := 4
const ROAD := 5
const SHALLOW := 6
const WATER := 7
const SHORE := 8
var movementCosts : array 1 .. 8 of real := init (1.5, 1, 2, 3, 0.5, 1, 1.5, 1)
var terrainTypes : array 1 .. 8 of int := init (42, 48, 2, 66, 15, 53, 55, 91)
var terrainBonus : array 1 .. 8 of int := init (2, 0, 1, 2, 2, -1, 0, 1)
var unitLocations : array 1 .. 40, 1 .. 40 of boolean                             % The array whether a space has a unit in it
var unitData : flexible array 1 .. 1 of units                                         % The actual unit data
var unitToAdd : int := 1
var map : array 1 .. 40, 1 .. 40 of int
var mx, my, mb, terrType : int := 1
var isHuman : boolean := true
var tileSize := (maxx - 250) div 13
var scrollX, scrollY : int := 0
var chars : array char of boolean
var possibleMovePoints : flexible array 1 .. 1 of point
var possibleAttackPoints : flexible array 1 .. 1 of point
var expandedPoint : array 1 .. 40, 1 .. 40 of boolean
var showingMoveTiles : boolean := false

View.Set ("graphics:" + intstr (tileSize * 18 + 300) + "," + intstr (tileSize * 13 + 200) + ";position:10,100;nobuttonbar")
var screenX := tileSize * 18 + 220
var screenY := tileSize * 13 + 200

% ********************* COMMON PROCEDURES AND FUNCTIONS *************************
var addTerr : boolean := false

function pixToGridX (mx : int) : int         % -> The next 4 were done by both
    result (mx - 100) div tileSize
end pixToGridX

function pixToGridY (my : int) : int
    result (my - 100) div tileSize
end pixToGridY

function gridToPixX (gridX : int) : int
    result 100 + gridX * tileSize
end gridToPixX

function gridToPixY (gridY : int) : int
    result 100 + gridY * tileSize
end gridToPixY

function findCharInString (word : string, character : string (1)) : int     % -> Josh
    for i : 1 .. length (word)
        if word (i) = character then
            result i
        end if
    end for
    result 0
end findCharInString

function isPassable (gridX, gridY : int) : boolean
    var terrtype : int
    if gridX > 0 and gridY > 0 and gridX <= 40 and gridY <= 40 then
        terrtype := map (gridX, gridY)
        if terrtype = SHALLOW or terrtype = WATER then
            result false
        else
            result true
        end if
    else
        result false
    end if
end isPassable

proc updateTile (tileX, tileY, terrType : int)         % -> Josh
    drawfillbox (100 + tileX * tileSize, 100 + tileY * tileSize, 100 + tileSize + tileX * tileSize, 100 + tileSize + tileY * tileSize, terrainTypes (map (scrollX + tileX, scrollY + tileY)))
end updateTile

proc refreshUnit (unitType, x, y, side : int)
    var diffX, diffY, col : int
    if side = 0 then
        col := red
    else
        col := blue
    end if
    if x > scrollX and y > scrollY and x < scrollX + 19 and y < scrollY + 14 then
        diffX := x - scrollX
        diffY := y - scrollY
        locate (5, 1)
        drawfillbox (gridToPixX (diffX) + (tileSize div 5), gridToPixY (diffY) + (tileSize div 5), gridToPixX (diffX) + tileSize - (tileSize div 5), gridToPixY (diffY) + tileSize - (tileSize div
            5),
            col)
        Font.Draw (unitGraphics (unitType), gridToPixX (diffX) + (tileSize div 4), gridToPixY (diffY) + (tileSize div 3), verdanaBold, white)
    end if
end refreshUnit

proc newUnit (unitType, x, y : int, side : boolean)
    var temp : int
    new unitData, upper (unitData) + 1
    temp := upper (unitData)
    unitData (temp).typeNum := unitType
    if side = true then
        unitData (temp).team := 0
    else
        unitData (temp).team := 1
    end if
    unitData (temp).name := unitNames (unitType)
    unitData (temp).unitType := unitTypes (unitType)
    unitData (temp).targetType := unitTargets (unitType)
    unitData (temp).attack := unitAttackVals (unitType)
    unitData (temp).defense := unitDefVals (unitType)
    unitData (temp).attackRng := unitAttackRng (unitType)
    unitData (temp).moveRng := unitMoveRng (unitType)
    unitData (temp).los := unitLOS (unitType)
    unitData (temp).totalHP := 10
    unitData (temp).currentHP := unitHP (unitType)
    unitData (temp).locX := x
    unitData (temp).locY := y
    unitLocations (x, y) := true
    refreshUnit (unitData (temp).typeNum, unitData (temp).locX, unitData (temp).locY, unitData (temp).team)
end newUnit



proc drawMinimap
    drawbox (15, screenY - 140, 97, screenY - 59, black)
    for i : 1 .. 40
        for j : 1 .. 40
            drawfillbox (14 + i * 2, screenY - 141 + j * 2, 16 + i * 2, screenY - 140 + j * 2, terrainTypes (map (i, j)))
        end for
    end for
    drawbox (16 + scrollX * 2, screenY - 139 + scrollY * 2, 52 + scrollX * 2, screenY - 114 + scrollY * 2, white)
end drawMinimap

function unitQuery (x, y : int) : int
    for i : 2 .. upper (unitData)
        if unitData (i).locX = x and unitData (i).locY = y then
            result i
        end if
    end for
    result 0
end unitQuery

function findCombinations (x, y, arrayStart : int) : int
    var temp : int
    if x - 1 >= 1 and isPassable (x - 1, y) and unitLocations (x - 1, y) = false then
        new possibleMovePoints, upper (possibleMovePoints) + 1
        temp := upper (possibleMovePoints)
        possibleMovePoints (temp).x := x - 1
        possibleMovePoints (temp).y := y
        possibleMovePoints (temp).parentX := x
        possibleMovePoints (temp).parentY := y
    end if
    if x + 1 <= 40 and isPassable (x + 1, y) and unitLocations (x + 1, y) = false then
        new possibleMovePoints, upper (possibleMovePoints) + 1
        temp := upper (possibleMovePoints)
        possibleMovePoints (temp).x := x + 1
        possibleMovePoints (temp).y := y
        possibleMovePoints (temp).parentX := x
        possibleMovePoints (temp).parentY := y
    end if
    if x >= 1 and y - 1 >= 1 and x <= 40 and isPassable (x, y - 1) and unitLocations (x, y - 1) = false then
        new possibleMovePoints, upper (possibleMovePoints) + 1
        temp := upper (possibleMovePoints)
        possibleMovePoints (temp).x := x
        possibleMovePoints (temp).y := y - 1
        possibleMovePoints (temp).parentX := x
        possibleMovePoints (temp).parentY := y
    end if
    if x >= 1 and y + 1 <= 40 and x <= 40 and isPassable (x, y + 1) and unitLocations (x, y + 1) = false then
        new possibleMovePoints, upper (possibleMovePoints) + 1
        temp := upper (possibleMovePoints)
        possibleMovePoints (temp).x := x
        possibleMovePoints (temp).y := y + 1
        possibleMovePoints (temp).parentX := x
        possibleMovePoints (temp).parentY := y
    end if
    result upper (possibleMovePoints) - arrayStart
end findCombinations

function findAttackCombinations (x, y, arrayStart : int) : int
    var temp : int
    if x - 1 >= 1 and isPassable (x - 1, y) then
        new possibleAttackPoints, upper (possibleAttackPoints) + 1
        temp := upper (possibleAttackPoints)
        possibleAttackPoints (temp).x := x - 1
        possibleAttackPoints (temp).y := y
        possibleAttackPoints (temp).parentX := x
        possibleAttackPoints (temp).parentY := y
    end if
    if x + 1 <= 40 and isPassable (x + 1, y) then
        new possibleAttackPoints, upper (possibleAttackPoints) + 1
        temp := upper (possibleAttackPoints)
        possibleAttackPoints (temp).x := x + 1
        possibleAttackPoints (temp).y := y
        possibleAttackPoints (temp).parentX := x
        possibleAttackPoints (temp).parentY := y
    end if
    if x >= 1 and y - 1 >= 1 and x <= 40 and isPassable (x, y - 1) then
        new possibleAttackPoints, upper (possibleAttackPoints) + 1
        temp := upper (possibleAttackPoints)
        possibleAttackPoints (temp).x := x
        possibleAttackPoints (temp).y := y - 1
        possibleAttackPoints (temp).parentX := x
        possibleAttackPoints (temp).parentY := y
    end if
    if x >= 1 and y + 1 <= 40 and x <= 40 and isPassable (x, y + 1) then
        new possibleAttackPoints, upper (possibleAttackPoints) + 1
        temp := upper (possibleAttackPoints)
        possibleAttackPoints (temp).x := x
        possibleAttackPoints (temp).y := y + 1
        possibleAttackPoints (temp).parentX := x
        possibleAttackPoints (temp).parentY := y
    end if
    result upper (possibleAttackPoints) - arrayStart
end findAttackCombinations

proc findPossibleMoves (x, y, moveCount : int)
    % Use some of the principles of pathfinding to find the possible squares a unit can move to.
    var costs : array 1 .. 40, 1 .. 40 of real
    var diffX, diffY : int
    var movesLeft : real := moveCount
    var numNodes, nodeFirst, nodeLast, nodeNextLast : int := 0
    var nodeX, nodeY, retVal : int
    var costToAdd : real := 0

    possibleMovePoints (1).x := x
    possibleMovePoints (1).y := y
    possibleMovePoints (1).parentX := x
    possibleMovePoints (1).parentY := y

    % Reset the values
    numNodes := 0
    for i : 1 .. 40
        for j : 1 .. 40
            costs (i, j) := 0
        end for
    end for

    new possibleMovePoints, 1
    nodeFirst := 1
    nodeLast := findCombinations (x, y, numNodes)
    for i : 1 .. (moveCount)
        nodeNextLast += 1
        for a : nodeFirst .. nodeLast
            if possibleMovePoints (a).parentX not= -2 then
                costToAdd := costs (possibleMovePoints (a).parentX, possibleMovePoints (a).parentY)
                % Store nodeX and nodeY values for speed
                nodeX := possibleMovePoints (a).x
                nodeY := possibleMovePoints (a).y
                if nodeX >= 1 and nodeY >= 1 then
                    if a > 1 then
                        costs (nodeX, nodeY) := movementCosts (map (nodeX, nodeY)) + costToAdd
                    end if
                    if round (costs (nodeX, nodeY)) >= moveCount + 3 then
                        % Kill off the node
                        possibleMovePoints (a).x := -2
                        possibleMovePoints (a).y := -2
                    else
                        % Find the next 4 nodes
                        retVal := findCombinations (possibleMovePoints (a).x, possibleMovePoints (a).y, nodeNextLast)
                        nodeNextLast := nodeNextLast + round (retVal)

                        if nodeX > scrollX and nodeY > scrollY and nodeX < scrollX + 19 and nodeY < scrollY + 14 then
                            diffX := nodeX - scrollX
                            diffY := nodeY - scrollY
                            drawbox (gridToPixX (diffX), gridToPixY (diffY), gridToPixX (diffX) + tileSize, gridToPixY (diffY) + tileSize, black)
                        end if
                        nodeFirst += 1
                        nodeLast := nodeNextLast
                    end if
                else
                    nodeFirst += 1
                    nodeLast := nodeNextLast
                end if
            end if
        end for
    end for
    showingMoveTiles := true
end findPossibleMoves

proc findPossibleAttacks (x, y, attackRange : int)
    % Use some of the principles of pathfinding to find the possible squares a unit can move to.
    var costs : array 1 .. 40, 1 .. 40 of real
    var diffX, diffY : int
    var numAttackNodes, attackNodeFirst, attackNodeLast, attackNodeNextLast : int := 0
    var nodeX, nodeY, retVal : int
    var count : int := 0

    possibleAttackPoints (1).x := x
    possibleAttackPoints (1).y := y
    possibleAttackPoints (1).parentX := x
    possibleAttackPoints (1).parentY := y
    new possibleAttackPoints, 1
    % Reset the values
    numAttackNodes := 0
    for i : 1 .. 40
        for j : 1 .. 40
            costs (i, j) := 0
        end for
    end for

    attackNodeFirst := 1
    attackNodeLast := findAttackCombinations (x, y, numAttackNodes)
    for i : 1 .. (attackRange)
        attackNodeNextLast += 1
        for a : attackNodeFirst .. attackNodeLast
            if possibleAttackPoints (a).parentX not= -2 then
                % Store nodeX and nodeY values for speed
                nodeX := possibleAttackPoints (a).x
                nodeY := possibleAttackPoints (a).y
                if nodeX >= 1 and nodeY >= 1 then
                    if a > 1 then
                        costs (nodeX, nodeY) := costs (possibleAttackPoints (a).parentX, possibleAttackPoints (a).y) + 1
                    end if
                    if count >= attackRange + 1 then
                        % Kill off the node
                        possibleAttackPoints (a).x := -2
                        possibleAttackPoints (a).y := -2
                    else
                        % Find the next 4 nodes
                        retVal := findAttackCombinations (possibleAttackPoints (a).x, possibleAttackPoints (a).y, attackNodeNextLast)
                        attackNodeNextLast := attackNodeNextLast + round (retVal)

                        if nodeX > scrollX and nodeY > scrollY and nodeX < scrollX + 19 and nodeY < scrollY + 14 and unitLocations (nodeX, nodeY) and unitData (unitQuery (nodeX, nodeY)).team = 1 then
                            diffX := nodeX - scrollX
                            diffY := nodeY - scrollY
                            drawfillbox (gridToPixX (diffX), gridToPixY (diffY), gridToPixX (diffX) + tileSize, gridToPixY (diffY) + tileSize, red)
                        end if
                        attackNodeFirst += 1
                        attackNodeLast := attackNodeNextLast
                    end if
                else
                    attackNodeFirst += 1
                    attackNodeLast := attackNodeNextLast
                end if
            end if
        end for
    end for
    showingMoveTiles := true
end findPossibleAttacks

function isValidMove (x, y : int) : boolean
    for i : 1 .. upper (possibleMovePoints)
        if possibleMovePoints (i).x = x and possibleMovePoints (i).y = y then
            result true
        end if
    end for
    result false
end isValidMove

% Back

proc drawMap (minX, minY : int)         % -> Josh
    for i : 1 .. 18
        for j : 1 .. 13
            drawfillbox (100 + i * tileSize, 100 + j * tileSize, 100 + i * tileSize + tileSize, 100 + j * tileSize + tileSize, terrainTypes (map (minX + i, minY + j)))
        end for
    end for
    View.Update
end drawMap

proc initializeMap         % -> Josh
    for i : 1 .. 40
        for j : 1 .. 40
            map (i, j) := 2
            unitLocations (i, j) := false
            expandedPoint (i, j) := false
        end for
    end for
    drawMap (0, 0)
end initializeMap

proc changeAllMap (terrType : int)
    for i : 1 .. 40
        for j : 1 .. 40
            map (i, j) := terrType
        end for
    end for
    drawMap (0, 0)
end changeAllMap

proc refreshAllUnits
    % Update the unit pictures
    for i : 2 .. upper (unitData)
        refreshUnit (unitData (i).typeNum, unitData (i).locX, unitData (i).locY, unitData (i).team)
    end for
end refreshAllUnits

proc scrollMap
    % If an arrow key is pressed, move the scrollable map
    Input.KeyDown (chars)
    if chars (KEY_UP_ARROW) and scrollY < 27 then
        scrollY += 1
        drawMap (scrollX, scrollY)
        refreshAllUnits
        drawMinimap
    elsif chars (KEY_DOWN_ARROW) and scrollY > 0 then
        scrollY -= 1
        drawMap (scrollX, scrollY)
        refreshAllUnits
        drawMinimap
    elsif chars (KEY_RIGHT_ARROW) and scrollX < 22 then
        scrollX += 1
        drawMap (scrollX, scrollY)
        refreshAllUnits
        drawMinimap
    elsif chars (KEY_LEFT_ARROW) and scrollX > 0 then
        scrollX -= 1
        drawMap (scrollX, scrollY)
        refreshAllUnits
        drawMinimap
    end if
end scrollMap

proc doBattle (atkrAttack, atkrDef, atkrTerrtype, defAttack, defDef, defTerrtype : int, var atkrHP, defHP : int, isRanged : boolean)
    var damageDone : int
    damageDone := (atkrHP + atkrAttack) div 2 - defDef - defTerrtype + Rand.Int (-2, 2)
    defHP -= damageDone
    if ~isRanged then
        atkrHP -= (damageDone div (4 + Rand.Int (-2, 1)))
    end if
    put damageDone, " ", atkrHP, " ", defHP
end doBattle

% ********************* GUI FUNCTIONS AND PROCEDURES ********************************
proc updateLeftDisp (displayType : string, num : int)
    if displayType = "unit" then
        Font.Draw ("Unit Name: " + unitData (num).name, screenX - 70, screenY - 40, verdana, black)
        Font.Draw ("Attack: " + intstr (unitData (num).attack), screenX - 70, screenY - 55, verdana, black)
        Font.Draw ("Defense: " + intstr (unitData (num).defense), screenX - 70, screenY - 70, verdana, black)
        Font.Draw ("Movement Range: " + intstr (unitData (num).moveRng), screenX - 70, screenY - 85, verdana, black)
        unitData (num).currentHP := 10
        Font.Draw ("HP: " + intstr (unitData (num).currentHP) + "/" + intstr (unitData (num).totalHP), screenX - 50, screenY - 100, verdana, black)
        drawbox (screenX - 60, screenY - 115, screenX + 30, screenY - 105, black)
        drawfillbox (screenX - 59, screenY - 114, (screenX - 59) + unitData (num).currentHP div 10 * 88, screenY - 106, blue)
    elsif displayType = "clear" then
        drawfillbox (screenX - 80, 0, maxx, maxy, grey)
    end if
end updateLeftDisp

% ********************* MAP EDITOR PROCEDURES AND FUNCTIONS *************************

proc changeTerrType (x, y, terrType : int)
    map (x, y) := terrType
end changeTerrType

proc saveMap
    var filename : string := ""
    var output : int
    locate (3, 1)
    put "Enter a name: " ..
    get filename
    open : output, "maps\\" + filename + ".map", put
    for i : 1 .. 40
        for j : 1 .. 40
            put : output, map (i, j), " " ..
        end for
    end for
    put ""
    for i : 2 .. upper (unitData)
        put : output, unitData (i).team, unitData (i).typeNum, ",", unitData (i).locX, ",", unitData (i).locY
    end for
    close : output
    locate (1, 1)
    put "Map Saving Completed."
end saveMap

proc loadMap
    var filename : string := ""
    var input : int
    var Char : string (1)
    var character : string
    var temp, temp2, unitX, unitY, side : int := 0
    var onHuman : boolean := false
    locate (3, 1)
    put "Enter a name: " ..
    get filename
    open : input, "maps\\" + filename + ".map", get

    if Error.Last = eNoError then
        for i : 1 .. 40
            for j : 1 .. 40
                get : input, Char
                if strintok (Char) = false and Char not= " " then
                    put "Data file corrupted! Tile (", i, ",", j, ") returned to Default Type"
                elsif strintok (Char) then
                    map (i, j) := strint (Char)
                end if
            end for
        end for
        drawMap (0, 0)

        if eof (input) then
            return
        end if
        loop
            get : input, character : *
            if length (character) > 4 and strintok (character (1)) then            % Evil little region of code, took me 20min!
                side := strint (character (1))
                if side = 0 then
                    onHuman := true
                else
                    onHuman := false
                end if
                temp := findCharInString (character, ",")
                temp2 := temp + findCharInString (character (temp + 1 .. *), ",")
                unitX := strint (character (temp + 1 .. temp2 - 1))
                unitY := strint (character (temp2 + 1 .. *))
                if strintok (character (1)) then
                    newUnit (strint (character (2)), unitX, unitY, onHuman)
                else
                    put "Data file corrupted, unit ignored"
                end if
            end if
            exit when eof (input)
        end loop
        close : input
    else
        locate (1, 1)
        put "File not Found."
    end if
end loadMap

proc exitEditor
    return
end exitEditor

proc initializeEditor
    % The Save Button
    drawbox (50, 250, 100, 275, black)
    drawfill (51, 251, red, black)
    Font.Draw ("SAVE", 58, 258, verdana, white)

    % The Load Button
    drawbox (50, 280, 100, 305, black)
    drawfill (51, 281, red, black)
    Font.Draw ("LOAD", 58, 288, verdana, white)

    % The New Button
    drawbox (50, 310, 100, 335, black)
    drawfill (51, 311, red, black)
    Font.Draw ("NEW", 58, 318, verdana, white)

    % The Fill Button
    drawbox (50, 340, 100, 365, black)
    drawfill (51, 341, red, black)
    Font.Draw ("FILL", 58, 348, verdana, white)

    var unitnames : array 1 .. 3 of string := init ("Inf.", "Tank", "Art.")
    Draw.Text ("Units", 125, 90, verdana, black)
    drawbox (65, 75, 95, 100, black)
    drawfill (66, 76, red, black)
    drawbox (65, 30, 95, 55, black)
    drawfill (66, 31, blue, black)
    for u : 1 .. 3
        drawbox (130 + (u * 35), 55, 155 + (u * 35), 80, black)
        Draw.Text (unitnames (u), 130 + (u * 35), 40, verdana, black)
    end for
    % This first bit was done by Mike. Following done by Josh, with help from Mike
    for i : 1 .. 2
        for j : 1 .. 4
            if i = 1 then
                drawfillbox (25 + (i * 25), 100 + (j * 25), 50 + (i * 25), 125 + (j * 25), terrainTypes (j))
            else
                drawfillbox (25 + (i * 25), 100 + (j * 25), 50 + (i * 25), 125 + (j * 25), terrainTypes (4 + j))
            end if
        end for
    end for
end initializeEditor

proc mapEditor          % Created by both
    initializeMap
    initializeEditor
    drawMap (0, 0)
    drawMinimap

    View.Set ("offscreenonly")
    loop
        mousewhere (mx, my, mb)
        if isHuman = true then
            drawbox (64, 29, 96, 56, white)
            drawbox (64, 74, 96, 101, green)
        else
            drawbox (64, 74, 96, 101, white)
            drawbox (64, 29, 96, 56, green)
        end if
        scrollMap

        if mx >= 65 and mx <= 95 then
            if my >= 75 and my <= 100 and mb = 1 then
                isHuman := true
            elsif my >= 30 and my <= 55 and mb = 1 then
                isHuman := false
            end if
        end if

        % Choose units to add
        if my > 54 and my < 80 and mb = 1 then
            if mx > 165 and mx < 190 then
                unitToAdd := 1
                addTerr := false
            elsif mx > 200 and mx < 225 then
                unitToAdd := 2
                addTerr := false
            elsif mx > 235 and mx < 260 then
                unitToAdd := 3
                addTerr := false
            end if
        end if

        % Add New Units to the Map
        if mx > 100 + (tileSize) and my > 100 + (tileSize) and mx < 100 + (tileSize * 19) and my < 100 + (tileSize * 14) and mb = 1 then
            if unitLocations (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)) = false and isPassable (scrollX + pixToGridX (mx), scrollY + pixToGridY (my))
                    and addTerr = false then
                newUnit (unitToAdd, scrollX + pixToGridX (mx), scrollY + pixToGridY (my), isHuman)
                delay (100)
            end if
        end if

        % Choose the terrain type to add
        if mx > 50 and my > 125 and mx < 100 and my < 224 and mb = 1 then
            if mx < 75 then
                terrType := 1 + (my - 125) div 25
                addTerr := true
            else
                terrType := 5 + ((my - 125) div 25)
                addTerr := true
            end if
        end if
        if mx > 100 + (tileSize) and my > 100 + (tileSize) and mx < 100 + (tileSize * 19) and my < 100 + (tileSize * 14) and mb = 1 and addTerr = true then
            changeTerrType (scrollX + pixToGridX (mx), scrollY + pixToGridY (my), terrType)
            updateTile (pixToGridX (mx), pixToGridY (my), map (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)))
            drawMinimap
        end if
        if mx > 50 and my > 250 and mx < 100 and my < 275 and mb = 1 then
            saveMap
        elsif mx > 50 and my > 280 and mx < 100 and my < 305 and mb = 1 then
            loadMap
            drawMinimap
        elsif mx > 50 and my > 310 and mx < 100 and my < 335 and mb = 1 then         % New Map
            new unitData, 1                                                         % Eliminate the other elements in the unitData array
            initializeMap
            drawMap (0, 0)
            drawMinimap
        elsif mx > 50 and my > 340 and mx < 100 and my < 365 and mb = 1 then
            changeAllMap (terrType)
            drawMinimap
        end if

        % Update display
        % if addTerr = false then
        %     if unitToAdd = 1 then
        %         put "INFANTRY   " ..
        %     elsif unitToAdd = 2 then
        %         put "TANKS      " ..
        %     elsif unitToAdd = 3 then
        %         put "ARTILLERY  " ..
        %     end if
        % elsif addTerr = true then
        %     if terrType = 1 then
        %         put "CITY    " ..
        %     elsif terrType = 2 then
        %         put "GRASS     " ..
        %     elsif terrType = 3 then
        %         put "FOREST    " ..
        %     elsif terrType = 4 then
        %         put "MOUNTAIN    " ..
        %     elsif terrType = 5 then
        %         put "ROAD    " ..
        %     elsif terrType = 6 then
        %         put "SHALLOWS    " ..
        %     elsif terrType = 7 then
        %         put "WATER    " ..
        %     elsif terrType = 8 then
        %         put "SAND    " ..
        %     end if
        % end if
        View.Update
    end loop

end mapEditor

proc playGame
    var unitNum : int
    initializeMap
    loadMap

    View.Set ("offscreenonly")
    % Draw the GUI
    drawfillbox (screenX - 80, 0, maxx, maxy, grey)
    drawfillbox (0, 0, 135, maxy, grey)
    drawfillbox (0, 0, maxx, 135, grey)
    drawMinimap
    View.Update
    loop
        mousewhere (mx, my, mb)
        scrollMap
        if mb = 1 then
            if unitQuery (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)) > 0 then
                unitNum := unitQuery (scrollX + pixToGridX (mx), scrollY + pixToGridY (my))
                updateLeftDisp ("clear", 0)
                updateLeftDisp ("unit", unitQuery (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)))
                if unitData (unitNum).team = 0 then
                    findPossibleMoves (scrollX + pixToGridX (mx), scrollY + pixToGridY (my), unitData (unitNum).moveRng)
                    findPossibleAttacks (scrollX + pixToGridX (mx), scrollY + pixToGridY (my), unitData (unitNum).attackRng)
                end if
            elsif showingMoveTiles and isValidMove (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)) and unitData (unitNum).team = 0 then
                unitLocations (unitData (unitNum).locX, unitData (unitNum).locY) := false
                unitData (unitNum).locX := scrollX + pixToGridX (mx)
                unitData (unitNum).locY := scrollY + pixToGridY (my)
                refreshUnit (unitData (unitNum).typeNum, unitData (unitNum).locX, unitData (unitNum).locY, unitData (unitNum).team)
                drawMap (scrollX, scrollY)
                refreshAllUnits
                showingMoveTiles := false
                delay (75)
            elsif showingMoveTiles and isValidAttack (scrollX + pixToGrid (mx), scrollY + pixToGrid (my)) then
                %doBattle (unitData (unitNum).attack, unitData (unitNum).defense, terrainBonus (map (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)), 
            elsif showingMoveTiles and isValidMove (scrollX + pixToGridX (mx), scrollY + pixToGridY (my)) = false then
                drawMap (scrollX, scrollY)
                refreshAllUnits
            else
                updateLeftDisp ("clear", 0)
            end if
        end if
        View.Update
    end loop
end playGame
playGame