cookchar

Maze Game

Dec 12th, 2017
113
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. import random as rnd
  2.  
  3. maze = []
  4.  
  5. #   Note: Blocked cells/Walls are encoded as 0,
  6. #   Hallways/Unblocked cells are encoded as 1
  7.  
  8. #   NODENAME , [nodeX, nodeY], [*list of nearby nodes*]
  9. #   Nearby Node: [NODENAME, DISTANCE, DIRECTION]
  10. nodeList = [ ["A", [1, 1], [["B", 5, "R"], ["F", 10, "D"]]],
  11.     ["B", [6, 1], [["A", 5, "L"], ["C", 5, "R"], ["H", 2, "D"]]],
  12.     ["C", [11, 1], [["B", 5, "L"], ["D", 10, "D"]]],
  13.     ["D", [11, 11], [["C", 10, "U"], ["E", 3, "L"]]],
  14.     ["E", [8, 11], [["D", 3, "R"], ["F", 7, "L"], ["R", 2, "U"]]],
  15.     ["F", [1, 11], [["A", 10, "U"], ["E", 7, "R"]]],
  16.     ["G", [3, 3], [["J", 2, "D"], ["S", 1, "R"]]],
  17.     ["H", [6, 3], [["B", 2, "U"], ["I", 1, "R"]]],
  18.     ["I", [7, 3], [["H", 1, "L"], ["K", 2, "D"]]],
  19.     ["J", [3, 5], [["G", 2, "U"], ["K", 4, "R"], ["M", 2, "D"]]],
  20.     ["K", [7, 5], [["I", 2, "U"], ["J", 4, "L"], ["L", 2, "R"], ["N", 2, "D"]]],
  21.     ["L", [9, 5], [["K", 2, "L"], ["T", 2, "U"], ["O", 2, "D"]]],
  22.     ["M", [3, 7], [["J", 2, "U"], ["N", 4, "R"], ["P", 2, "D"]]],
  23.     ["N", [7, 7], [["K", 2, "U"], ["M", 4, "L"], ["O", 2, "R"], ["Q", 2, "D"]]],
  24.     ["O", [9, 7], [["L", 2, "U"], ["N", 2, "L"]]],
  25.     ["P", [3, 9], [["M", 2, "U"], ["U", 1, "R"]]],
  26.     ["Q", [7, 9], [["N", 2, "U"], ["R", 1, "R"], ["W", 1, "L"]]],
  27.     ["R", [8, 9], [["Q", 1, "L"], ["V", 1, "R"], ["E", 2, "D"]]],
  28.     ["S", [4, 3], [["G", 1, "L"]]],
  29.     ["T", [9, 3], [["L", 2, "D"]]],
  30.     ["U", [4, 9], [["P", 1, "L"]]],
  31.     ["V", [9, 9], [["R", 1, "L"]]],
  32.     ["W", [6, 9], [["Q", 1, "R"]]],
  33. ]
  34. '''
  35. Game Map:
  36. = = = = = = = = = = = = =
  37. = A         B         C =
  38. =   = = = =   = = = =   =
  39. =   = G S = H I = T =   =
  40. =   =   = = =   =   =   =
  41. =   = J       K   L =   =
  42. =   =   = = =   =   =   =
  43. =   = M       N   O =   =
  44. =   =   = = =   = = =   =
  45. =   = P U = W Q R V =   =
  46. =   = = = = = =   = =   =
  47. = F             E     D =
  48. = = = = = = = = = = = = =
  49. '''
  50.  
  51. def makeMaze(): #Overly long function that builds up the maze list into a 13x13 matrix of 0's and 1's via a for-loop and if-else block
  52.     for i in range(13):
  53.         temp = []
  54.  
  55.         if i in (0, 12):
  56.             for j in range(13):
  57.                 temp.append(0)
  58.  
  59.         elif i in (1, 11):
  60.             temp.append(0)
  61.  
  62.             for j in range(11):
  63.                 temp.append(1)
  64.  
  65.             temp.append(0)
  66.         elif i == 2:
  67.             temp.append(0)
  68.             temp.append(1)
  69.    
  70.             for j in range(4):
  71.                 temp.append(0)
  72.  
  73.             temp.append(1)
  74.  
  75.             for j in range(4):
  76.                 temp.append(0)
  77.  
  78.             temp.append(1)
  79.             temp.append(0)
  80.         elif i == 3:
  81.             temp.append(0)
  82.             temp.append(1)
  83.             temp.append(0)
  84.             temp.append(1)
  85.             temp.append(1)
  86.             temp.append(0)
  87.             temp.append(1)
  88.             temp.append(1)
  89.             temp.append(0)
  90.             temp.append(1)
  91.             temp.append(0)
  92.             temp.append(1)
  93.             temp.append(0)
  94.         elif i in (4, 6):
  95.             temp.append(0)
  96.             temp.append(1)
  97.             temp.append(0)
  98.             temp.append(1)
  99.  
  100.             for j in range(3):
  101.                 temp.append(0)
  102.  
  103.             temp.append(1)
  104.             temp.append(0)
  105.             temp.append(1)
  106.             temp.append(0)
  107.             temp.append(1)
  108.             temp.append(0)
  109.         elif i in (5, 7):
  110.             temp.append(0)
  111.             temp.append(1)
  112.             temp.append(0)
  113.  
  114.             for j in range(7):
  115.                 temp.append(1)
  116.  
  117.             temp.append(0)
  118.             temp.append(1)
  119.             temp.append(0)
  120.         elif i == 8:
  121.             temp.append(0)
  122.             temp.append(1)
  123.             temp.append(0)
  124.             temp.append(1)
  125.  
  126.             for j in range(3):
  127.                 temp.append(0)
  128.  
  129.             temp.append(1)
  130.  
  131.             for j in range(3):
  132.                 temp.append(0)
  133.  
  134.             temp.append(1)
  135.             temp.append(0)
  136.         elif i == 9:
  137.             temp.append(0)
  138.             temp.append(1)
  139.             temp.append(0)
  140.             temp.append(1)
  141.             temp.append(1)
  142.             temp.append(0)
  143.  
  144.             for j in range(4):
  145.                 temp.append(1)
  146.  
  147.             temp.append(0)
  148.             temp.append(1)
  149.             temp.append(0)
  150.         elif i == 10:
  151.             temp.append(0)
  152.             temp.append(1)
  153.  
  154.             for j in range(6):
  155.                 temp.append(0)
  156.            
  157.             temp.append(1)
  158.             temp.append(0)
  159.             temp.append(0)
  160.             temp.append(1)
  161.             temp.append(0)
  162.  
  163.         maze.append(temp)
  164.  
  165. def printMaze(px, py, robot):   #Prints out the maze's current state, showing the position of the player and robot
  166.     i = 0
  167.  
  168.     for row in maze:
  169.         j = 0
  170.  
  171.         for cell in row:
  172.             if j == px and i == py:
  173.                 print('@', end = ' ')
  174.             elif j == robot[0] and i == robot[1]:
  175.                 print('&', end = ' ')
  176.             elif j == 7 and (i == 5 or i == 7):
  177.                 print('?', end = ' ')
  178.             elif cell == 0:
  179.                 print('#', end = ' ')
  180.             elif cell == 1:
  181.                 print(' ', end = ' ')
  182.  
  183.             j += 1
  184.  
  185.         print()
  186.  
  187.         i += 1
  188.  
  189. def moveRobot(robot):   #Invoked after the player moves or waits. Uses the direction string of the robot to move it
  190.     if robot[2] == 'U':
  191.         robot[1] -= 1
  192.     elif robot[2] == 'D':
  193.         robot[1] += 1
  194.     elif robot[2] == 'R':
  195.         robot[0] += 1
  196.     elif robot[2] == 'L':
  197.         robot[0] -= 1
  198.  
  199. def nodeCheck(robot):   #Checks if the robot is on any of the lettered nodes in the nodeList
  200.     for node in nodeList:
  201.         if robot[0] == node[1][0] and robot[1] == node[1][1]:
  202.             return True
  203.  
  204.     return False
  205.  
  206. def getCurrentNode(robot)#Gets the index of the node in the nodeList the robot is on
  207.     for node in nodeList:
  208.         if robot[0] == node[1][0] and robot[1] == node[1][1]:
  209.             return nodeList.index(node)
  210.  
  211. def getAnyNode(nodeName):   #Gets the index of a node in the nodeList based on it's lettered name
  212.     for i in range(len(nodeList)):
  213.         if nodeList[i][0] == nodeName:
  214.             return i
  215.  
  216. def checkPath(node, destination, axis): #Sees if there is a straight-line path from the given node to the destination coordinate along the indicated axis
  217.     if axis == 'x':
  218.         if node[0] > destination:
  219.             for i in range(node[0], destination - 1, -1):
  220.                 if maze[node[1]][i] == 0:
  221.                     return False
  222.         else:
  223.             for i in range(destination, node[0] + 1, -1):
  224.                 if maze[node[1]][i] == 0:
  225.                     return False
  226.  
  227.     elif axis == 'y':
  228.         if node[1] > destination:
  229.             for i in range(node[1], destination - 1, -1):
  230.                 if maze[i][node[0]] == 0:
  231.                     return False
  232.         else:
  233.             for i in range(destination, node[1] + 1, -1):
  234.                 if maze[i][node[0]] == 0:
  235.                     return False
  236.     else:
  237.         return False
  238.     return True
  239.  
  240. def calcBestPath(player, robot):    #Calculates the best path for the robot to take when it reaches a lettered node
  241.     currentNode = getCurrentNode(robot)
  242.  
  243.     immNeighbors = nodeList[currentNode][2]
  244.     maxDist = 0
  245.     nextDir = ''
  246.  
  247.     if len(immNeighbors) == 4#If the current node has four neighbors, choose a random direction
  248.         directions = ('U', 'D', 'L', 'R')
  249.         robot[2] = directions[rnd.randint(0,3)]
  250.     #Only two 4-way nodes exist in the maze
  251.     else:
  252.         for neighbor in immNeighbors:   #Do the following to each immediate neighbor-node of the current node
  253.             neighborIndex = getAnyNode(neighbor[0])
  254.             neighborCoords = nodeList[neighborIndex][1]
  255.             #Get the index and coordinates of the neighbor-node
  256.  
  257.             #If the neighbor-node is not the node the robot was just at, and the player is not within a straight-line path of the neighbor-node, by either a vertical or horizontal path, process the neighbor-node
  258.             if neighbor[0] != robot[3] \
  259.             and not ( (player[0] == neighborCoords[0] and checkPath(neighborCoords, player[1], 'y') )\
  260.                 or (player[1] == neighborCoords[1] and checkPath(neighborCoords, player[0], 'x') )\
  261.             )
  262.                 #The first coordinate, [0], is the x, and [1] is the y. If the player and neighbor-node have the same x coordinate, they might have a vertical path or y-path between each other, and vice versa
  263.  
  264.                 tempDist = neighbor[1]
  265.  
  266.                 secNeighbors = nodeList[neighborIndex][2]   #Get the secondary neighbors of the neighbor-node
  267.                 secDistances = []
  268.  
  269.                 for otherNeighbor in secNeighbors:  #Do the following for each secondary-neighbor-node
  270.                     otherCoords = nodeList[getAnyNode(otherNeighbor[0])][1] #Get the secondary-neighbor's coordinates
  271.  
  272.                     #If the secondary neighbor node is not the current/original node, and the player does not have a straight-line path to the secondary neighbor node, by either a horizontal or vertical path, process the node
  273.                     if otherNeighbor[0] != nodeList[currentNode][0] \
  274.                         and not ( (player[0] == otherCoords[0] and checkPath(otherCoords, player[1], 'y') )\
  275.                             or (player[1] == otherCoords[1] and checkPath(otherCoords, player[0], 'x') )\
  276.                         ):
  277.  
  278.                         secDistances.append(otherNeighbor[1])
  279.  
  280.                     else:   #0's must be appended in case of a failure of the above condition as to keep the distances list the same length as the list of neighbors, so the maximum distance neighbor's index can be chosen
  281.                         secDistances.append(0)
  282.  
  283.                 bestNode = secDistances.index(max(secDistances))
  284.                 #After processing the secondary neighbor nodes, choose one furthest away and add its distance to the distance to the primary neighbor node
  285.                 tempDist += secNeighbors[bestNode][1]
  286.                 #If the path to the neighbor node and beyond is greater than the current maximum length path, update the maximum path length and the direction that the robot should move next
  287.                 if tempDist > maxDist:
  288.                     maxDist = tempDist
  289.                     nextDir = neighbor[2]
  290.  
  291.         robot[2] = nextDir
  292.         #After processing all neighbor nodes, give the robot its next direction
  293.    
  294.     robot[3] = nodeList[currentNode][0]
  295.     #Tell the robot of the node it just visited and got a new direction out of
  296.  
  297. def spawnRobot(player, robot)#Spawns a robot on a random lettered node that the player is not on
  298.     spawnNode = [-1, -1]
  299.  
  300.     while (spawnNode[0] == -1 and spawnNode[1] == -1) or (player[0] == spawnNode[0] and player[1] == spawnNode[1]):
  301.         tempIndex = rnd.randint(0, len(nodeList) - 1)
  302.         spawnNode[0] = nodeList[tempIndex][1][0]
  303.         spawnNode[1] = nodeList[tempIndex][1][1]
  304.  
  305.     robot[0] = spawnNode[0]
  306.     robot[1] = spawnNode[1]
  307.  
  308. def main(): #Main function. Handles input, robot AI & movement, score-keeping, and updating the display
  309.     playerCoordX = 1
  310.     playerCoordY = 1
  311.     playerScore = 0
  312.     playerSteps = 0
  313.     playerWaits = 0
  314.  
  315.     direction = ''
  316.     wallMsg = "There's a wall there, try moving in another direction...\n"
  317.     prompt = "Enter a direction to move [W:^, A:<, S:v, D:>] then ENTER," + \
  318.     "\njust ENTER to wait, \'H\' then ENTER for help," + \
  319.     "\n\'C\' then ENTER for Credits, or \'X\' to quit\n-={ "
  320.  
  321.     moved = False
  322.  
  323.     robotData = [-1, -1, 'direction', 'previousNode']
  324.     spawnCountdown = 10
  325.     robotInPlay = False
  326.  
  327.     helpMsg = "Welcome to Charlie Cook's Maze Game!" + \
  328.         "\nThere are robots in this game (represented by \'&\')" + \
  329.         "\nthat appear in the maze every now and again." + \
  330.         "\nYou (represented by \'@\') need to catch them to earn points." + \
  331.         "\nThe robots can sense where you are and will try to avoid you." + \
  332.         "\nHowever, the \'?\' tiles mix them up and send them in a random direction." + \
  333.         "\nUse this to your advantage! Good luck!\n"
  334.  
  335.     creditsMsg = "Coded by Charles \"Charlie\" \"The Gnarly\" Cook" + \
  336.         "\nfrom November to December, 2017. All Rights Reserved.\n"
  337.  
  338.     makeMaze()
  339.     printMaze(playerCoordX, playerCoordY, robotData)
  340.  
  341.  
  342.     while direction.upper() != 'X':
  343.         direction = str(input(prompt))
  344.  
  345.         while direction.upper() not in "WASDXHC":
  346.             print("Error: Unknown Direction")
  347.             direction = str(input(prompt))
  348.  
  349.         if direction.upper() == 'W':
  350.             if maze[playerCoordY - 1][playerCoordX] == 1:
  351.                 playerCoordY -= 1
  352.                 moved = True
  353.                 playerSteps += 1
  354.             else:
  355.                 print(wallMsg)
  356.  
  357.         elif direction.upper() == 'A':
  358.             if maze[playerCoordY][playerCoordX - 1] == 1:
  359.                 playerCoordX -= 1
  360.                 moved = True
  361.                 playerSteps += 1
  362.             else:
  363.                 print(wallMsg)
  364.  
  365.         elif direction.upper() == 'S':
  366.             if maze[playerCoordY + 1][playerCoordX] == 1:
  367.                 playerCoordY += 1
  368.                 moved = True
  369.                 playerSteps += 1
  370.             else:
  371.                 print(wallMsg)
  372.  
  373.         elif direction.upper() == 'D':
  374.             if maze[playerCoordY][playerCoordX + 1] == 1:
  375.                 playerCoordX += 1
  376.                 moved = True
  377.                 playerSteps += 1
  378.             else:
  379.                 print(wallMsg)
  380.  
  381.         elif direction.upper() == 'X':
  382.             if str(input("Are you sure you want to quit? [Y/N]: ")).upper() == 'Y':
  383.                 print("Your final score was", playerScore, "point(s).")
  384.                 print("You took a total of", playerSteps, "step(s).")
  385.                 print("You waited for a total of", playerWaits, "turn(s).")
  386.                 print("See you later!")
  387.             else:
  388.                 direction = ''
  389.  
  390.         elif direction == '':
  391.             playerWaits += 1
  392.             moved = True
  393.  
  394.         elif direction.upper() == 'H':
  395.             print(helpMsg)
  396.  
  397.         elif direction.upper() == 'C':
  398.             print(creditsMsg)
  399.  
  400.         if moved:
  401.             if robotInPlay:
  402.                 moveRobot(robotData)
  403.  
  404.                 if playerCoordX == robotData[0] and playerCoordY == robotData[1]:
  405.                     print("You caught a robot! Well done!")
  406.                     playerScore += 1
  407.                     print("Your score is now", playerScore, "points.")
  408.                     robotInPlay = False
  409.                     robotData[0] = -1
  410.                     robotData[1] = -1
  411.                 else:
  412.                     if nodeCheck(robotData):
  413.                     #   print(robotData)
  414.                         calcBestPath([playerCoordX, playerCoordY], robotData)
  415.                     #   print(robotData)
  416.             else:
  417.                 spawnCountdown -= 1
  418.                 if spawnCountdown == 0:
  419.                     spawnCountdown = 10
  420.                     spawnRobot([playerCoordX, playerCoordY], robotData)
  421.                     print("A robot has appeared! Catch it!\n(You need to move onto the same spot as the robot to catch it.\nThey're small, and can run right under you!)")
  422.                 #   print(robotData)
  423.                     robotInPlay = True
  424.                     calcBestPath([playerCoordX, playerCoordY], robotData)
  425.                 #   print(robotData)
  426.  
  427.             moved = False
  428.  
  429.             printMaze(playerCoordX, playerCoordY, robotData)
  430.  
  431. main()
RAW Paste Data