Sfoglia il codice sorgente

Added ScriptExplore v1.00

Woot! Travel the stars with this cool auto-explore script!
david 5 anni fa
parent
commit
e2fed88c25
1 ha cambiato i file con 211 aggiunte e 46 eliminazioni
  1. 211 46
      flexible.py

+ 211 - 46
flexible.py

@@ -10,28 +10,6 @@ from itertools import cycle
 import pendulum
 from pprint import pformat
 
-class SpinningCursor(object):
-    """ Spinner class, that handles every so many clicks 
-    
-    s = SpinningCursor(5)  # every 5
-    for x in range(10):
-        if s.click():
-            print(s.cycle())
-
-    """
-    def __init__(self, every=10):
-        self.itercycle = cycle(["/", "-", "\\", "|"])
-        self.count = 0
-        self.every = every
-    def reset(self):
-        self.itercycle = cycle(["/", "-", "\\", "|"])
-        self.count = 0
-    def click(self):
-        self.count += 1
-        return self.count % self.every == 0
-    def cycle(self):
-        return next(self.itercycle)
-
 
 def merge(color_string):
     """ Given a string of colorama ANSI, merge them if you can. """
@@ -261,13 +239,13 @@ class CIMWarpReport(object):
         self.queue_player.put("^")  # Activate CIM
         self.state = 1
         # self.warpdata = {}
-        self.warpcycle = SpinningCursor() 
+        self.warpcycle = cycle(["/", "-", "\\", "|"])
 
     def game_prompt(self, prompt):
         if prompt == ": ":
             if self.state == 1:
                 # Ok, then we're ready to request the port report
-                self.warpcycle.reset()
+                self.warpcycle = cycle(["/", "-", "\\", "|"])
                 self.queue_player.put("I")
                 self.state = 2
             elif self.state == 2:
@@ -297,8 +275,8 @@ class CIMWarpReport(object):
 
         # This should be the CIM Report Data -- parse it
         if self.warpcycle:
-            if self.warpcycle.click():
-                self.queue_game.put("\b" + self.warpcycle.cycle())
+            if len(self.game.gamedata.warps) % 10 == 0:
+                self.queue_game.put("\b" + next(self.warpcycle))
 
         work = line.strip()
         parts = re.split(r"(?<=\d)\s", work)
@@ -389,13 +367,13 @@ class CIMPortReport(object):
         self.queue_player.put("^")  # Activate CIM
         self.state = 1
         # self.portdata = {}
-        self.portcycle = SpinningCursor()
+        self.portcycle = cycle(["/", "-", "\\", "|"])
 
     def game_prompt(self, prompt):
         if prompt == ": ":
             if self.state == 1:
                 # Ok, then we're ready to request the port report
-                self.portcycle.reset()
+                self.portcycle = cycle(["/", "-", "\\", "|"])
                 self.queue_player.put("R")
                 self.state = 2
             elif self.state == 2:
@@ -423,8 +401,8 @@ class CIMPortReport(object):
 
         # This should be the CIM Report Data -- parse it
         if self.portcycle:
-            if self.portcycle.click():
-                self.queue_game.put("\b" + self.portcycle.cycle())
+            if len(self.game.gamedata.ports) % 10 == 0:
+                self.queue_game.put("\b" + next(self.portcycle))
 
         work = line.replace("%", "")
 
@@ -1030,22 +1008,200 @@ class ScriptPort(object):
         #     self.deactivate()
         #     return
 
-def color_pct(pct):
-    if pct > 50:
-        # green
-        return "{0}{1:3}{2}".format( Fore.GREEN, pct, Style.RESET_ALL)
-    elif pct > 25:
-        return "{0}{1:3}{2}".format( merge(Fore.YELLOW + Style.BRIGHT), pct, Style.RESET_ALL)
-    else:
-        return "{0:3}".format(pct)
+class ScriptExplore(object):
+    """ Script Explore
+
+        WARNINGS:
+         We assume the player has a Holo-Scanner!
+    """
+    def __init__(self, game):
+        self.game = game
+        self.queue_game = game.queue_game
+        self.queue_player = game.queue_player
+        self.observer = game.observer
+        self.r = Style.RESET_ALL
+        self.nl = "\n\r"
+        
+        # Our Stuff, Not our pants!
+        self.dense = []         # We did a density, store that
+        self.didScan = False    # Track if we did a scan already... prevents us calling a scan multiple times.
+        self.clear = []         # Warps that we know are clear
+        self.highsector = 0     # Selected Sector to move to next!
+        self.highwarp = 0       # Selected Sector's Warp Count!
+        self.times = 5          # How many times have we gone thru this? (Maybe add a simple question for if the user doesn't want it to run forever)
+        self.maxtimes = self.times
+
+        # Activate
+        self.prompt = game.buffer
+        self.save = self.observer.save()
+        self.observer.connect('player', self.player)
+        self.observer.connect("prompt", self.game_prompt)
+        self.observer.connect("game-line", self.game_line)
+
+        self.defer = None
+        self.send2player("Explorer v1.00")
+
+        self.state = 1
+
+        # Begin to Gather cur_sector, and cur_warps
+        self.send2game("D")
+    
+    def whenDone(self):
+        self.defer = defer.Deferred()
+        # Call this to chain something after we exit.
+        return self.defer
+    
+    def deactivate(self):
+        self.state = 0
+        log.msg("ScriptExplore.deactivate()")
+        assert(not self.save is None)
+        self.observer.load(self.save)
+        self.save = None
+        if self.defer:
+            self.defer.callback('done')
+            self.defer = None
+    
+    def player(self, chunk: bytes):
+        # If we receive anything -- ABORT!
+        self.deactivate()
+    
+    def send2game(self, txt):
+        self.queue_player.put("{0}".format(txt))
+
+    def send2player(self, txt):
+        self.queue_game.put(
+            self.nl + txt + self.r + self.nl
+        )
+
+    def game_prompt(self, prompt: str):
+        log.msg("{0} : {1}".format(self.state, prompt))
+        if self.state == 3:
+            log.msg("dense is {0} sectors big".format(len(self.dense)))
+            self.state = 4
+            self.send2game("SH")
+    
+    def game_line(self, line: str):
+        log.msg("{0} | {1}".format(self.state, line))
+        if self.state == 1:
+            # Density Scan, (Assume we have the Holo-Scanner)
+            if not self.didScan:
+                self.send2game("SD")
+                self.didScan = True
+            
+            if "Relative Density Scan" in line:
+                self.state = 2
+        elif self.state == 2:
+            if line.startswith("Sector"):
+                work = line.replace(':', '').replace(')', '').replace('%', '').replace('==>', '')
+                work = re.split(r"\s+", work)
+                # 'Sector', '8192', '0', 'Warps', '4', 'NavHaz', '0', 'Anom', 'No'
+                # 'Sector', '(', '8192)', '0', 'Warps', '4', 'NavHaz', '0', 'Anom', 'No'
+                # New Sector?
+                if work[1] == '(':
+                    temp1 = True
+                else:
+                    temp1 = False
+
+                # Yes new sector! So we will add it!
+                if temp1:
+                    if(work[9] == 'No'):
+                        temp = False
+                    else:
+                        temp = True
+                
+                    self.dense.append( {'sector': int(work[2]), 'density': int(work[3]), 'warps': int(work[5]), 'navhaz': int(work[7]), 'anom': temp} )
+                    # {'sector': 8192, 'density': 0, 'warps': 4, 'navhaz': 0, 'anom': False}
+                
+            elif line == "":
+                self.state = 3
+        elif self.state == 4:
+            # Ok so we do our Holo-Scan now how can we parse this... hmm.
+            # Or do we just do that and then do a move? Hmmm... (I think we get enough info to make a choice)
+            # Perhaps what we will do is do a Holo-Scan just to "count" as us going into that sector
+            if not self.dense:
+                log.msg("No New Sectors Found!")
+                self.send2player("Find a new area for me to search in!")
+                self.deactivate()
+
+            for d in self.dense:
+                if not d['anom']:
+                    # Sector does not contain a Anomoly
+                    if d['navhaz'] == 0:
+                        # Sector does not contain Hazards
+                        if d['density'] == 0 or d['density'] == 1 or d['density'] == 100 or d['density'] == 101:
+                            # Sector does contain empty space / a beacon / a port / or a beacon and port
+                            if d['warps'] > 1:
+                                # If Sector is worth checking out?
+                                self.clear.append(d['sector'])
+            
+            if self.clear:
+                log.msg("Clear Sectors: {0}".format(len(self.clear)))
+                self.state = 5
+        elif self.state == 5:
+            # Ok so we now have a idea of howmany and what sectors are clear and have greater than 1 warps
+            # Now to sort thru that to see which ones have the highest warps and if they have a port or not
+            # Then randomly if needed pick from those to actually move too! \o/ And poof we will be ready to make it loop
+
+            # TEST, Just to show that my code picks the highest sector number if multiple sectors have the same warp count!
+            #self.clear = [1, 2, 3]
+            #self.dense = [
+            #    {'sector': 1, 'density': 0, 'warps': 2, 'navhaz': 0, 'anom': False},
+            #    {'sector': 2, 'density': 0, 'warps': 3, 'navhaz': 0, 'anom': False},
+            #    {'sector': 3, 'density': 0, 'warps': 3, 'navhaz': 0, 'anom': False},
+            #]
+            #log.msg("Clear: {0} Dense: {1}".format(len(self.clear), len(self.dense)))
+
+            # Sort to find greatest warp count
+            for c in self.clear:
+                for d in self.dense:
+                    if d['sector'] == c:
+                        if d['warps'] > self.highwarp:
+                            self.highwarp = d['warps']
+                            self.highsector = c
+                        elif d['warps'] == self.highwarp:
+                                if c > self.highsector:
+                                    self.highsector = c
+                                    
+            # Is this the same sector we were at a few seconds ago?
+            # If it is go for one of the other sectors
+            
+            # If we found the best sector to move to and with previous test of safety we will now move to that sector!
+            if self.highwarp != 0 or self.highsector != 0:
+                log.msg("Sector: {0:5d} Warps: {1}".format(self.highsector, self.highwarp))
+                self.state = 6
+            else:
+                log.msg("Oh Nose! We didn't find any Sector with higher Warps than any of the others!")
+                self.deactivate()
+        elif self.state == 6:
+            # Ok we know the sector we want to go to now let's move it!
+            self.send2game("m{0}\n\r".format(self.highsector))
+
+            # Reset Variables for fresh data
+            self.didScan = False
+            self.dense = []
+            self.clear = []
+            self.highwarp = 0
+            self.highsector = 0
+            self.state = 1
+            
+            # To prevent infinite loop we ask for how many times to execute!
+            #self.times -= 1
+            # If we hit our last turn end ourselves, Note the user can always manually abort via sending any key!
+            # And now if we find no new sectors we will also abort as well!
+            #if self.times <= 0:
+            #    self.send2player("Completed {0} Times".format(self.maxtimes))
+            #    self.deactivate()
+
+
+       
 
 def port_pct(port):
     # Make sure these exist in the port data given.
     if all( x in port for x in ['fuel', 'org', 'equ']):
-        return "{0},{1},{2}%".format(
-            color_pct(port['fuel']['pct']),
-            color_pct(port['org']['pct']),
-            color_pct(port['equ']['pct']))
+        return "{0:3},{1:3},{2:3}%".format(
+            port['fuel']['pct'],
+            port['org']['pct'],
+            port['equ']['pct'])
     else:
         return "---,---,---%"
 
@@ -1165,9 +1321,8 @@ class ProxyMenu(object):
         ok_trades = []
         best_trades = []
 
-        # for sector, pd in self.game.gamedata.ports.items():
-        for sector in sorted(self.game.gamedata.ports.keys()):
-            pd = self.game.gamedata.ports[sector]
+
+        for sector, pd in self.game.gamedata.ports.items():
             if not port_burnt(pd):
                 pc = pd['class']
 
@@ -1366,7 +1521,7 @@ class ProxyMenu(object):
             )
 
         menu_item("1", "Ports (Trades between two sectors)")
-        menu_item("2", "TODO")
+        menu_item("2", "Explore (Travel the universe auto-magically)")
         menu_item("3", "TODO")
         menu_item("X", "eXit")
         self.queue_game.put("   " + c1 + "-=>" + self.r + " ")
@@ -1386,6 +1541,16 @@ class ProxyMenu(object):
             d.addCallback(self.deactivate_scripts_menu)
             d.addErrback(self.deactivate_scripts_menu)
             return
+        if key == '2':
+            self.queue_game.put(self.c + key + self.r + self.nl)
+            # Activate this magical event here
+            explore = ScriptExplore(self.game)
+            d = explore.whenDone()
+            # d.addCallback(self.scripts_menu)
+            # d.addErrback(self.scripts_menu)
+            d.addCallback(self.deactivate_scripts_menu)
+            d.addErrback(self.deactivate_scripts_menu)
+            return
         elif key == 'X':
             self.queue_game.put(self.c + key + self.r + self.nl)            
             self.deactivate_scripts_menu()