TinTin++ Configs for DiscworldMUD
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

158 lines
6.4 KiB

  1. #!/usr/bin/env python
  2. import sys
  3. import sqlite3
  4. class MapRoute:
  5. def __init__(self):
  6. self.locations_by_room_id = {}
  7. self.exits_by_id = {}
  8. self.exits_by_exit = {}
  9. self.return_alias = None
  10. self.db = self.database_connect()
  11. self.load_locations()
  12. self.load_exits()
  13. def database_connect(self):
  14. con = sqlite3.connect('src/quow.db')
  15. con.row_factory = sqlite3.Row
  16. return con
  17. def load_locations(self):
  18. cur = self.db.cursor()
  19. cur.execute("SELECT room_id, map_id, xpos, ypos, room_short, room_type FROM rooms")
  20. for row in cur.fetchall():
  21. self.locations_by_room_id[row[0]] = [row[1], row[2], row[3], row[4], row[5]]
  22. self.exits_by_id[row['room_id']] = {}
  23. self.exits_by_exit[row['room_id']] = {}
  24. def load_exits(self):
  25. cur = self.db.cursor()
  26. cur.execute("SELECT room_id, connect_id, exit FROM room_exits")
  27. for row in cur.fetchall():
  28. if self.exits_by_id.get(row['room_id']) is not None and self.exits_by_id.get(row['connect_id']) is not None:
  29. self.exits_by_id[row['room_id']][row['connect_id']] = row['exit']
  30. self.exits_by_exit[row['room_id']][row['exit']] = row['connect_id']
  31. def route_to_room(self, current_id, target_id, same_place):
  32. # If we can't match one of the room identifiers, back out
  33. if not current_id or not target_id or not self.locations_by_room_id.get(target_id) or not self.locations_by_room_id.get(current_id):
  34. return
  35. sDoPath, sFinalDestination, iResults = self.route_find(
  36. current_id, target_id,
  37. self.locations_by_room_id[target_id][0],
  38. self.locations_by_room_id[target_id][1],
  39. self.locations_by_room_id[target_id][2],
  40. same_place
  41. )
  42. if sDoPath != "":
  43. sDoPath = "alias RuhsSpeedRun {}".format(sDoPath)
  44. if len(sDoPath) > 1700:
  45. pass
  46. else:
  47. self.return_alias = sDoPath
  48. def route_find(self, start_id, dest_id, dest_map, dest_x, dest_y, same_place=True):
  49. sDoRoom = [start_id]
  50. bEverDone = {start_id: True}
  51. sIDToRoomNum = {start_id: 1}
  52. iGotHereFrom = {}
  53. iNextRoom = 1
  54. iTotalRooms = 1
  55. sLinkedTo = []
  56. iSearchDepth = 0
  57. bDone = False
  58. iFinalRoom = 0
  59. iPreviousTotal = 0
  60. # "Infinite" loop
  61. while bDone == False:
  62. # Loop through all the rooms we have yet to do
  63. iPreviousTotal = iTotalRooms
  64. for iN in xrange(iNextRoom - 1, iPreviousTotal):
  65. # Loop through all exits from this room
  66. for sKey, sExitData in self.exits_by_id[sDoRoom[iN]].iteritems():
  67. # Make sure we aren't looping back around on ourselves, and that we haven't already finished
  68. if sKey != start_id and bEverDone.get(sKey) == None and iFinalRoom == 0:
  69. iTotalRooms = iTotalRooms + 1
  70. # Add THIS destination of THIS room to the "to-be-processed" list
  71. sDoRoom.append(sKey)
  72. # Flag this room so we never come here again
  73. bEverDone[sKey] = True
  74. # Record ID to room-num
  75. sIDToRoomNum[sKey] = iTotalRooms
  76. # Record back-tracking data
  77. iGotHereFrom[iTotalRooms] = [sIDToRoomNum[sDoRoom[iN]], sExitData]
  78. # See if we made it yet
  79. if sDoRoom[iN] == dest_id:
  80. bDone = True
  81. iFinalRoom = iN
  82. elif sKey == dest_id:
  83. bDone = True
  84. iFinalRoom = iTotalRooms
  85. elif (same_place == True and self.locations_by_room_id[sDoRoom[iN]][0] == dest_map
  86. and self.locations_by_room_id[sDoRoom[iN]][1] == dest_x
  87. and self.locations_by_room_id[sDoRoom[iN]][2] == dest_y):
  88. # Maybe we reached the co-ordinates instead - eg a house with multiple rooms in one pixels -- only stop here if we didn't START here
  89. if (self.locations_by_room_id[start_id][0] != dest_map or
  90. self.locations_by_room_id[start_id][1] != dest_x or
  91. self.locations_by_room_id[start_id][2] != dest_y):
  92. bDone = True
  93. iFinalRoom = iN
  94. # elif
  95. # not back to beginning
  96. # loop through exit rooms
  97. # loop through "to-do"
  98. iNextRoom = iPreviousTotal + 1
  99. if iNextRoom > iTotalRooms:
  100. # Failed to find a route
  101. bDone = True
  102. iSearchDepth = iSearchDepth + 1
  103. if iSearchDepth > 500:
  104. # Failed, too deep
  105. bDone = True
  106. iFinalRoom = 0
  107. break
  108. # infinite loop end
  109. # Did we actually find a room?
  110. if iFinalRoom != 0:
  111. sPath = []
  112. bDone = False
  113. iCurRoom = iFinalRoom
  114. while bDone == False:
  115. sPath.append(iGotHereFrom[iCurRoom][1])
  116. iCurRoom = iGotHereFrom[iCurRoom][0]
  117. if iCurRoom == 1:
  118. bDone = True
  119. sRealPath = ""
  120. for iN in xrange(len(sPath), 0, -1):
  121. if sRealPath != "":
  122. sRealPath = "{};".format(sRealPath)
  123. sRealPath = "{}{}".format(sRealPath, sPath[iN-1])
  124. return sRealPath, sDoRoom[iFinalRoom-1], len(sPath)
  125. # Didn't find a route, return blanks
  126. return "", "", 0
  127. if __name__ == '__main__':
  128. if len(sys.argv) < 2:
  129. print('[error] No input provided.')
  130. sys.exit()
  131. current_room, target_room = sys.argv.pop(1), sys.argv.pop(1)
  132. router = MapRoute()
  133. router.route_to_room(current_room, target_room, True)
  134. # TODO: Can we determine samePlace? We need to compare the MapID of current_room and target_room when found?
  135. # d route between df6506b79c67080920fccbf27ce0d06cd392e01a and 03360211b315daf089d9ba329dd32417b9c7f54c.
  136. if router.return_alias:
  137. print(router.return_alias)
  138. else:
  139. print(0)