Browse Source

added picking model selector + new AI model: ALice

epsylon 4 years ago
parent
commit
83c9070eb8
2 changed files with 162 additions and 20 deletions
  1. 53 0
      models/AIAlice.py
  2. 109 20
      snake.py

+ 53 - 0
models/AIAlice.py

@@ -0,0 +1,53 @@
+#!/usr/bin/env python 
+# -*- coding: utf-8 -*-"
+"""
+PyAISnake - 2018/2020 - by psy (epsylon@riseup.net)
+
+You should have received a copy of the GNU General Public License along
+with PyAISnake; if not, write to the Free Software Foundation, Inc., 51
+Franklin St, Fifth Floor, Boston, MA  02110-1301  USA
+"""
+from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
+import random
+
+# movements strategy (evading suicidal behavior) and trying to identify next location...
+class AIAlice(object):
+    def extractName(self):
+        name = "AliC3"
+        return name
+
+    def makeStrategy(self, allowed_moves, food, snake):
+        if snake[0][0] == food[0]:
+            if snake[0][1] < food[1]:
+                    move = KEY_RIGHT
+                    if move not in allowed_moves:
+                        move = KEY_LEFT
+            else:
+                move = KEY_LEFT
+                if move not in allowed_moves:
+                    move = KEY_RIGHT
+        else:
+            if snake[0][0] < food[0]: 
+                move = KEY_UP
+                if move not in allowed_moves:
+                    move = KEY_DOWN
+            else:
+                move = KEY_DOWN
+                if move not in allowed_moves:
+                    move = KEY_UP
+        return move
+
+    def makeMove(self, win, prev_move, food, snake):
+        name = self.extractName()
+        if prev_move == KEY_UP:
+            allowed_moves = [KEY_UP, KEY_LEFT, KEY_RIGHT]
+        elif prev_move == KEY_LEFT:
+            allowed_moves = [KEY_UP, KEY_LEFT, KEY_DOWN]
+        elif prev_move == KEY_RIGHT:
+            allowed_moves = [KEY_UP, KEY_RIGHT, KEY_DOWN]
+        elif prev_move == KEY_DOWN:
+            allowed_moves = [KEY_LEFT, KEY_RIGHT, KEY_DOWN]
+        else:
+            allowed_moves = [KEY_UP, KEY_LEFT, KEY_RIGHT, KEY_DOWN]
+        move = self.makeStrategy(allowed_moves, food, snake)
+        return move

+ 109 - 20
snake.py

@@ -14,15 +14,101 @@ from curses import KEY_RIGHT, KEY_LEFT, KEY_UP, KEY_DOWN
 
 # import AI models into sandbox
 from models.AIBob import AIBob
-AIBob = AIBob() # BoB
+from models.AIAlice import AIAlice
 
-# extract name from players
-def extract_name(p):
-    name = AIBob.extractName() # BoB
-    return name
+bots = ['AIBoB','AIAlice']
 
 ######################################################################3
 
+class BoxSelector:
+    def __init__(self, bots):
+        self.TEXTBOX_WIDTH = 50
+        self.TEXTBOX_HEIGHT = 6
+        self.PAD_WIDTH = 400
+        self.PAD_HEIGHT = 10000
+
+    def pick(self):
+        self._init_curses()
+        self._create_pad()
+        windows = self._make_textboxes()
+        picked = self._select_textbox(windows)
+        self._end_curses()
+        return picked
+
+    def _init_curses(self):
+        self.stdscr = curses.initscr()
+        curses.noecho()
+        curses.cbreak()
+        curses.curs_set(0)
+        self.stdscr.keypad(1)
+        curses.start_color()
+        curses.init_pair(1, curses.COLOR_BLACK, curses.COLOR_GREEN)
+        curses.init_pair(2, curses.COLOR_WHITE, curses.COLOR_BLACK)
+        self.stdscr.bkgd(curses.color_pair(2))
+        self.stdscr.refresh()
+
+    def _end_curses(self):
+        curses.nocbreak()
+        self.stdscr.keypad(0)
+        curses.echo()
+        curses.endwin()
+
+    def _create_pad(self):
+        self.pad = curses.newpad(self.PAD_HEIGHT, self.PAD_WIDTH)
+        self.pad.box()
+
+    def _make_textboxes(self):
+        maxy, maxx = self.stdscr.getmaxyx()
+        windows = []
+        i = 1
+        for s in bots:
+            windows.append(self.pad.derwin(self.TEXTBOX_HEIGHT,
+                    self.TEXTBOX_WIDTH, i, self.PAD_WIDTH//2-self.TEXTBOX_WIDTH//2))
+            i += self.TEXTBOX_HEIGHT
+        for k in range(len(windows)):
+            windows[k].box()
+            windows[k].addstr(4, 4, '{0:X} - {1}'.format(k, bots[k]))
+        return windows
+
+    def _center_view(self, window):
+        cy, cx = window.getbegyx()
+        maxy, maxx = self.stdscr.getmaxyx()
+        self.pad.refresh(cy, cx, 1, maxx//2 - self.TEXTBOX_WIDTH//2, maxy-1, maxx-1)
+        return (cy, cx)
+
+    def _select_textbox(self, windows):
+        topy, topx = self._center_view(windows[0])
+        current_selected = 0
+        last = 1
+        top_textbox = windows[0]
+        while True:
+            windows[current_selected].bkgd(curses.color_pair(1))
+            windows[last].bkgd(curses.color_pair(2))
+            maxy, maxx = self.stdscr.getmaxyx()
+            cy, cx = windows[current_selected].getbegyx()
+            if ((topy + maxy - self.TEXTBOX_HEIGHT) <= cy):
+                top_textbox = windows[current_selected]
+            if topy >= cy + self.TEXTBOX_HEIGHT:
+                top_textbox = windows[current_selected]
+            if last != current_selected:
+                last = current_selected
+            topy, topx = self._center_view(top_textbox)
+            c = self.stdscr.getch()
+            if c == ord('0') or c == 258: # KEY_UP
+                if current_selected >= len(windows)-1:
+                    current_selected = 0 
+                else:
+                    current_selected += 1
+            elif c == ord('1') or c == 259: # KEY_DOWN
+                if current_selected <= 0:
+                    current_selected = len(windows)-1
+                else:
+                    current_selected -= 1
+            elif c == ord('q') or c == 27: # ESC
+                break
+            elif c == curses.KEY_ENTER or c == 10:
+                return int(current_selected)
+
 # translate a thought into a text
 def text_to_thought(move):
     if move == KEY_UP:
@@ -66,14 +152,15 @@ def startGame(win, food, snake, evol, record, max_moves):
     moves = 0
     score = 0
     thought = "WAKING UP..."
-
-######################################################################3
-
-    name = AIBob.extractName() # BoB
-    move = AIBob.makeMove(win, None, food, snake) # BoB
-
-######################################################################3
-
+    choice = BoxSelector(bots).pick()
+    if not choice:
+        choice = 0 # BoB
+    name = bots[choice]
+    if name == "AIBoB":
+        bot = AIBob() # BoB
+    else:
+        bot = AIAlice() #Alice
+    move = bot.makeMove(win, None, food, snake) # first move
     moves += 1
     thought = text_to_thought(move)
     # build game
@@ -84,17 +171,19 @@ def startGame(win, food, snake, evol, record, max_moves):
         win.timeout(150 - int((len(snake)/5) + int(len(snake)/10)%120)) # if > length: > speed
         prevMove = move  
         event = win.getch()
-
-######################################################################3
-
-        move = AIBob.makeMove(win, prevMove, food, snake) # BoB
-
-######################################################################3
-
+        move = bot.makeMove(win, prevMove, food, snake) # rest of movements
         moves += 1
         thought = text_to_thought(move)
         move = move if event == -1 else event
         if move != KEY_UP and move != KEY_DOWN and move != KEY_LEFT and move != KEY_RIGHT : # ANY KEY for pause
+            if move == 27: # ESC
+                breaked = ' GAME FINISHED: GOOD BYE! ;-)'
+                win.addstr(9, 9, breaked)
+                win.getch()
+                curses.nocbreak()
+                curses.echo()
+                curses.endwin()
+                break
             move = -1 # pause
             paused = ' GAME PAUSED: PRESS -SPACEBAR- TO RESTORE'
             win.addstr(9, 9, paused)