KodyVanRy
KodyVanRy

Reputation: 1108

Turn Based Movement Algorithm

I am programming a turn-based strategy, like Fire Emblem, game in Python using pygame, but I am running into a problem with movement of players. The way that it works is that you select a player and it will show you all allowed moves highlighted in Blue, but my problem is that I am having a problem coming up with a list for all possible moves.

def showPerson(tilex, tiley, personAtTile):
global ALLOWEDMOVES
ALLOWEDMOVES = []
prepare = {k:v for v,k in PLAYERSPOSITION.items()}
z = PLAYERDISTANCE[personAtTile]
#get all coords for the possible moves
currentNewSpots = []
oldSpots = []
a = PLAYERSPOSITION[personAtTile][0]
b = PLAYERSPOSITION[personAtTile][1]
c = a + 1
test = findTileLetter(c, b)
if test:
    currentNewSpots.append((c, b))
    ALLOWEDMOVES.append((c, b))
c = a -1
test = findTileLetter(c, b)
if test:
    currentNewSpots.append((c, b))
    ALLOWEDMOVES.append((c, b))
c = b + 1
test = findTileLetter(a, c)
if test:
    currentNewSpots.append((a, c))
    ALLOWEDMOVES.append((a, c))
c = b - 1
test = findTileLetter(a, c)
if test:
    currentNewSpots.append((a, c))
    ALLOWEDMOVES.append((a, c))

for x in range(PLAYERDISTANCE[prepare[(tilex, tiley)]]):
    for y in range(len(currentNewSpots) - 1):
        a = currentNewSpots[y][0]
        b = currentNewSpots[y][1]
        c = a + 1
        test = findTileLetter(c, b)
        if test and ((c, b)) not in ALLOWEDMOVES:
            currentNewSpots.append((c, b))
            ALLOWEDMOVES.append((c, b))
        c = a -1
        test = findTileLetter(c, b)
        if test and ((c, b)) not in ALLOWEDMOVES:
            currentNewSpots.append((c, b))
            ALLOWEDMOVES.append((c, b))
        c = b + 1
        test = findTileLetter(a, c)
        if test and ((c, b)) not in ALLOWEDMOVES:
            currentNewSpots.append((a, c))
            ALLOWEDMOVES.append((a, c))
        c = b - 1
        test = findTileLetter(a, c)
        if test and ((c, b)) not in ALLOWEDMOVES:
            currentNewSpots.append((a, c))
            ALLOWEDMOVES.append((a, c))

Upvotes: 0

Views: 1453

Answers (1)

atomicinf
atomicinf

Reputation: 3736

Because I don't know what you have in mind, I'll proceed under the following assumptions:

  • findTileLetter(x, y) tells me if the square at (x, y) is passable. That is, it tells me if a unit could pass through or end their turn on that square.
  • Units can step up to PLAYERDISTANCE[unit] + 1 times per turn. Each step can be taken up, down, left, or right. Diagonal steps are not allowed, but instead must be accomplished by stepping e.g. left and up.

With that in mind, we note that on the line

for y in range(len(currentNewSpots) - 1):

you iterate over one fewer element of currentNewSpots than you should, and thus every x loop you omit stepping from the element in currentNewSpots that was added last in the preceding x loop. Hence you leave out potential destination squares.

Changing the line to

for y in range(len(currentNewSpots))

fixes this issue.

Additionally, your delta-y tests in the y loop are not quite right:

    c = b + 1
    test = findTileLetter(a, c)
    if test and ((c, b)) not in ALLOWEDMOVES: ### <--- should be (a, c)
        currentNewSpots.append((a, c))
        ALLOWEDMOVES.append((a, c))

Blob of working test code follows. The grid defines a world of tiles: 0 tiles are impassable, while 1 tiles are passable. The MY_X and MY_Y define where we're searching from. After every step, we output the map to stdout, illustrating which squares we've found so far.

import sys

MY_X = 3
MY_Y = 4
MY_RNG = 2

grid = [
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 1, 0, 0, 0, 0, 0],
    [0, 0, 1, 1, 1, 1, 0, 0, 1, 0],
    [0, 1, 1, 1, 1, 1, 1, 1, 1, 1],
    [0, 0, 1, 1, 0, 1, 1, 0, 0, 1],
    [0, 0, 1, 1, 1, 1, 1, 0, 0, 0],
    [0, 0, 0, 0, 1, 1, 1, 1, 1, 0],
    [0, 0, 0, 1, 1, 1, 1, 0, 0, 0],
    [0, 1, 1, 1, 0, 0, 0, 0, 0, 0],
    [0, 0, 0, 0, 0, 0, 0, 0, 0, 0],
]

def findTileLetter(x, y):
    return grid[y][x]

class Person:
    pass

def showMap():
    for y in range(len(grid)):
        for x in range(len(grid[y])):
            if grid[y][x] == 0:
                sys.stdout.write(' ')
            elif x == MY_X and y == MY_Y:
                sys.stdout.write('x')
            elif (x, y) in ALLOWEDMOVES:
                sys.stdout.write('o')
            else:
                sys.stdout.write('-')
        sys.stdout.write('\n')

me = Person()

ALLOWEDMOVES = []

PLAYERDISTANCE = {}
PLAYERDISTANCE[me] = MY_RNG

PLAYERSPOSITION = {}
PLAYERSPOSITION[me] = (MY_X, MY_Y)

def showPerson(tilex, tiley, personAtTile):
    global ALLOWEDMOVES
    ALLOWEDMOVES = []
    prepare = {k:v for v,k in PLAYERSPOSITION.items()}
    z = PLAYERDISTANCE[personAtTile]
    #get all coords for the possible moves
    currentNewSpots = []
    oldSpots = []
    a = PLAYERSPOSITION[personAtTile][0]
    b = PLAYERSPOSITION[personAtTile][1]
    c = a + 1
    test = findTileLetter(c, b)
    if test:
        currentNewSpots.append((c, b))
        ALLOWEDMOVES.append((c, b))
    c = a -1
    test = findTileLetter(c, b)
    if test:
        currentNewSpots.append((c, b))
        ALLOWEDMOVES.append((c, b))
    c = b + 1
    test = findTileLetter(a, c)
    if test:
        currentNewSpots.append((a, c))
        ALLOWEDMOVES.append((a, c))
    c = b - 1
    test = findTileLetter(a, c)
    if test:
        currentNewSpots.append((a, c))
        ALLOWEDMOVES.append((a, c))

    showMap()

    for x in range(PLAYERDISTANCE[prepare[(tilex, tiley)]]):
        for y in range(len(currentNewSpots)):
            a = currentNewSpots[y][0]
            b = currentNewSpots[y][1]
            c = a + 1
            test = findTileLetter(c, b)
            if test and ((c, b)) not in ALLOWEDMOVES:
                currentNewSpots.append((c, b))
                ALLOWEDMOVES.append((c, b))
            c = a - 1
            test = findTileLetter(c, b)
            if test and ((c, b)) not in ALLOWEDMOVES:
                currentNewSpots.append((c, b))
                ALLOWEDMOVES.append((c, b))
            c = b + 1
            test = findTileLetter(a, c)
            if test and ((a, c)) not in ALLOWEDMOVES:
                currentNewSpots.append((a, c))
                ALLOWEDMOVES.append((a, c))
            c = b - 1
            test = findTileLetter(a, c)
            if test and ((a, c)) not in ALLOWEDMOVES:
                currentNewSpots.append((a, c))
                ALLOWEDMOVES.append((a, c))
        showMap()

showPerson(MY_X, MY_Y, me)
print ALLOWEDMOVES

Upvotes: 1

Related Questions