示例#1
0
    def find_snake_by_tail(self, tail):
        cur_y, cur_x = tail
        cur_elem = self.get_element_at(Point(cur_x, cur_y))
        snake_coords = [(cur_y, cur_x)]

        while cur_elem not in heads_elements:
            #print(cur_elem.get_char(), end='')
            #print(self.get_element_type_at(cur_x, cur_y - 1).get_char(), end='')
            #print(self.get_element_type_at(cur_x, cur_y + 1).get_char(), end='')
            #print(self.get_element_type_at(cur_x - 1, cur_y).get_char(), end='')
            #print(self.get_element_type_at(cur_x + 1, cur_y).get_char(), end='\n')
            got = 0
            for crnt, direction, nxt in SEARCH_HELPER:
                if direction == 'UP' and Element(
                        crnt) == cur_elem and self.get_element_type_at(
                            cur_x, cur_y - 1) == Element(nxt):
                    if (cur_y - 1, cur_x) not in snake_coords:
                        cur_x, cur_y = cur_x, cur_y - 1
                        got = 1
                        break
                if direction == 'DOWN' and Element(
                        crnt) == cur_elem and self.get_element_type_at(
                            cur_x, cur_y + 1) == Element(nxt):
                    if (cur_y + 1, cur_x) not in snake_coords:
                        cur_x, cur_y = cur_x, cur_y + 1
                        got = 1
                        break
                if direction == 'LEFT' and Element(
                        crnt) == cur_elem and self.get_element_type_at(
                            cur_x - 1, cur_y) == Element(nxt):
                    if (cur_y, cur_x - 1) not in snake_coords:
                        cur_x, cur_y = cur_x - 1, cur_y
                        got = 1
                        break
                if direction == 'RIGHT' and Element(
                        crnt) == cur_elem and self.get_element_type_at(
                            cur_x + 1, cur_y) == Element(nxt):
                    if (cur_y, cur_x + 1) not in snake_coords:
                        cur_x, cur_y = cur_x + 1, cur_y
                        got = 1
                        break

            if got == 0:
                break

            cur_elem = self.get_element_at(Point(cur_x, cur_y))

            snake_coords.append((cur_y, cur_x))

        snake_coords.reverse()
        evil = cur_elem in [Element('ENEMY_HEAD_EVIL'), Element('HEAD_EVIL')]
        snake = {'coords': snake_coords, 'evil': evil, 'evil_capacity': 0}

        return snake
示例#2
0
 def get_my_head(self):
     return self.find_first_element(Element('HEAD_HEAD'),
                                    Element('HEAD_DOWN'),
                                    Element('HEAD_UP'),
                                    Element('HEAD_LEFT'),
                                    Element('HEAD_RIGHT'),
                                    Element('HEAD_EVIL'),
                                    Element('HEAD_FLY'),
                                    Element('HEAD_SLEEP'))
示例#3
0
def is_good(gcb: Board, p: Point, rage, allow_stones, allow_body):
    a = gcb.get_element_at(p)
    #print('NEW EL:', a.get_char())
    if not rage:
        if not allow_stones and not allow_body and a not in base_good_elements:
            return False
        if allow_stones and not allow_body and a not in base_good_elements + [
                Element('STONE')
        ]:
            return False
        if allow_stones and allow_body and a not in base_good_elements + [
                Element('STONE')
        ] + my_bodies:
            return False
    else:
        if a not in base_good_elements + [Element('STONE')
                                          ] + enemies_bodies + enemies_tails:
            return False
    next_steps = [
        p.shift_top(1),
        p.shift_bottom(1),
        p.shift_left(1),
        p.shift_right(1)
    ]
    if not rage:
        if not allow_stones:
            s = np.count_nonzero([
                gcb.get_element_at(x) in base_good_elements for x in next_steps
            ])
        else:
            s = np.count_nonzero([
                gcb.get_element_at(x)
                in base_good_elements + [Element('STONE')] for x in next_steps
            ])
    else:
        s = np.count_nonzero([
            gcb.get_element_at(x) in base_good_elements + [Element('STONE')] +
            enemies_tails + enemies_bodies + enemies_heads for x in next_steps
        ])
    #print('s:', s)
    return s > 0
示例#4
0
 def get_barriers(self):
     """ Return the list of barriers Points."""
     points = set()
     points.update(
         self._find_all(Element('WALL'), Element('START_FLOOR'),
                        Element('ENEMY_HEAD_SLEEP'),
                        Element('ENEMY_TAIL_INACTIVE'),
                        Element('TAIL_INACTIVE'), Element('STONE')))
     return list(points)
示例#5
0
 def get_element_at(self, point):
     """ Return an Element object at coordinates x,y."""
     return Element(self._string[self._xy2strpos(point.get_x(),
                                                 point.get_y())])
示例#6
0
 def get_golds(self):
     return self._find_all(Element('GOLD'))
示例#7
0
 def get_start_points(self):
     return self._find_all(Element('START_FLOOR'))
示例#8
0
 def get_flying_pills(self):
     return self._find_all(Element('FLYING_PILL'))
示例#9
0
 def get_furry_pills(self):
     return self._find_all(Element('FURY_PILL'))
示例#10
0
    def __call__(self, gcb: Board):
        try:
            board_str = gcb._line_by_line()
            src_gcb = Board(board_str)

            my_head = gcb.get_my_head()

            if my_head is None:
                print('my_head is None')
                if self.head is None:
                    return SnakeAction.RIGHT
                if self.prev_action == SnakeAction.RIGHT:
                    self.head = self.head.shift_right(1)
                if self.prev_action == SnakeAction.LEFT:
                    self.head = self.head.shift_left(1)
                if self.prev_action == SnakeAction.UP:
                    self.head = self.head.shift_top(1)
                if self.prev_action == SnakeAction.DOWN:
                    self.head = self.head.shift_bottom(1)
                my_head = self.head
                #return SnakeAction.RIGHT
            else:
                self.head = my_head

            my_head_el = gcb.get_element_at(my_head)
            rage = my_head_el == Element('HEAD_EVIL')

            if rage:
                if self.prev_action == SnakeAction.RIGHT:
                    my_head_el = Element('HEAD_RIGHT')
                if self.prev_action == SnakeAction.LEFT:
                    my_head_el = Element('HEAD_LEFT')
                if self.prev_action == SnakeAction.UP:
                    my_head_el = Element('HEAD_UP')
                if self.prev_action == SnakeAction.DOWN:
                    my_head_el = Element('HEAD_DOWN')

            #print(my_head, my_head_el)
            gcb.assign_point(my_head, my_head_el)

            first_rage = False

            if rage and not self.prev_rage:
                first_rage = True
                self.ticks_rage = 9
            self.ticks_rage -= 1
            self.prev_rage = rage
            if self.ticks_rage <= 0:
                rage = False

            use_new = True  #not rage

            #gcb.update_board(my_head, rage, self.prev_action)
            gcb.update_board(my_head, False, self.prev_action)
            if use_new:
                gcb.create_access_reprs(my_head)
            #my_head_el = gcb.get_element_at(my_head)

            if my_head_el not in good_positions and False:
                self.prev_action = get_same_direction(my_head_el)
                return self.prev_action
            else:
                if True:
                    if use_new:
                        if not rage:
                            targets = gcb._find_all(Element('APPLE'),
                                                    Element('FURY_PILL'),
                                                    Element('GOLD'))
                        else:
                            print('rage: ',
                                  len(gcb._find_all(*enemies_bodies)))
                            targets = gcb._find_all(Element('APPLE'),
                                                    Element('FURY_PILL'),
                                                    Element('GOLD'),
                                                    Element('STONE'),
                                                    *enemies_bodies)

                            #targets = [t for t in targets if src_gcb.get_element_at(t) != Element('WALL')]

                        if first_rage:
                            pass
                            #print('TARGETS:', targets)

                        dists = [gcb.get_dist_to(t, rage) for t in targets]

                        targets_with_dists = [
                            (t,
                             d if gcb.get_element_at(t) != Element('FURY_PILL')
                             else 0.66 * d,
                             scores[gcb.get_element_at(t).get_char()])
                            for t, d in zip(targets, dists) if d != 666
                        ]
                        targets_with_dists = [
                            tdc for tdc in targets_with_dists
                            if tdc[1] < self.ticks_rage
                            or gcb.get_element_at(tdc[0]) in [
                                Element('APPLE'),
                                Element('FURY_PILL'),
                                Element('GOLD')
                            ]
                        ]
                        targets_with_dists.sort(key=itemgetter(1))

                        for tdc in targets_with_dists:
                            if gcb.get_element_at(tdc[0]) in enemies_bodies:
                                print('ENEMY FOUND:', tdc[1])

                        #targets_with_dists = targets_with_dists[:10]

                        if rage:
                            pass
                            #print('targets_with_dists:', targets_with_dists)

                        if len(targets_with_dists) > 0 and True:
                            dist = targets_with_dists[0][1]
                            targets_with_dists = [
                                td for td in targets_with_dists
                                if td[1] == dist
                            ]

                            solution_found = False
                            ps = []

                            for t, d, c in targets_with_dists:
                                if gcb.get_element_at(t) in enemies_bodies:
                                    ps = list(gcb.get_next_step_to(t, rage))
                                    if len(ps) > 0:
                                        solution_found = True
                                        break

                            if not solution_found:
                                targets_with_dists.sort(key=itemgetter(2))
                                #if rage:
                                #print('targets_with_dists sorted by:', targets_with_dists)

                                ne = 1
                                while True and ne <= 3:

                                    target = targets_with_dists[-ne]
                                    ne += 1
                                    if rage:
                                        pass
                                        #print('TARGET:', target)

                                    ps = gcb.get_next_step_to(target[0], rage)
                                    ps = list(ps)
                                    if len(ps) > 0:
                                        break
                                    #ps = [x for x in ps if src_gcb.get_element_at(x) != Element('WALL')]

                            if rage:
                                pass
                                #print('ps:', ps)

                            if rage:
                                pass
                                #print(ps)
                            if len(ps) > 0:
                                random.shuffle(ps)
                                p = ps[0]
                                if gcb.get_element_at(p) == Element(
                                        'FURY_PILL'):
                                    self.ticks_rage += 10
                                if my_head.shift_top(1) == p:
                                    self.prev_action = SnakeAction.UP
                                    return self.prev_action
                                if my_head.shift_bottom(1) == p:
                                    self.prev_action = SnakeAction.DOWN
                                    return self.prev_action
                                if my_head.shift_left(1) == p:
                                    self.prev_action = SnakeAction.LEFT
                                    return self.prev_action
                                if my_head.shift_right(1) == p:
                                    self.prev_action = SnakeAction.RIGHT
                                    return self.prev_action
                            else:
                                print('use old algo:', targets_with_dists)

                    res = []
                    for action_index in range(4):
                        #action_index = random.randint(0,3)
                        act = actions[action_index]
                        if is_opposite(act, my_head_el):
                            continue
                        if act == SnakeAction.UP:
                            new_point = my_head.shift_top(1)
                        elif act == SnakeAction.DOWN:
                            new_point = my_head.shift_bottom(1)
                        elif act == SnakeAction.LEFT:
                            new_point = my_head.shift_left(1)
                        elif act == SnakeAction.RIGHT:
                            new_point = my_head.shift_right(1)
                        if is_good(gcb, new_point, rage, False):
                            #print('GOOD:', act, 'RAGE:', rage)
                            res.append(
                                (action_index, get_score(gcb, new_point,
                                                         rage)))

                    if len(res) == 0:
                        for action_index in range(4):
                            #action_index = random.randint(0,3)
                            act = actions[action_index]
                            if is_opposite(act, my_head_el):
                                continue
                            if act == SnakeAction.UP:
                                new_point = my_head.shift_top(1)
                            elif act == SnakeAction.DOWN:
                                new_point = my_head.shift_bottom(1)
                            elif act == SnakeAction.LEFT:
                                new_point = my_head.shift_left(1)
                            elif act == SnakeAction.RIGHT:
                                new_point = my_head.shift_right(1)
                            if is_good(gcb, new_point, rage, True):
                                #print('GOOD:', act, 'RAGE:', rage)
                                res.append((action_index,
                                            get_score(gcb, new_point, rage)))

                    if len(res) == 0:
                        for action_index in range(4):
                            #action_index = random.randint(0,3)
                            act = actions[action_index]
                            if is_opposite(act, my_head_el):
                                continue
                            if act == SnakeAction.UP:
                                new_point = my_head.shift_top(1)
                            elif act == SnakeAction.DOWN:
                                new_point = my_head.shift_bottom(1)
                            elif act == SnakeAction.LEFT:
                                new_point = my_head.shift_left(1)
                            elif act == SnakeAction.RIGHT:
                                new_point = my_head.shift_right(1)
                            if is_good(gcb, new_point, rage, True, True):
                                #print('GOOD:', act, 'RAGE:', rage)
                                res.append((action_index,
                                            get_score(gcb, new_point, rage)))

                    random.shuffle(res)
                    #print(rage, res)
                    res.sort(key=itemgetter(1))
                    #print(rage, res)
                    if len(res) == 0:
                        for action_index in range(4):
                            act = actions[action_index]
                            if is_opposite(act, my_head_el):
                                continue
                            if act == SnakeAction.UP:
                                new_point = my_head.shift_top(1)
                            elif act == SnakeAction.DOWN:
                                new_point = my_head.shift_bottom(1)
                            elif act == SnakeAction.LEFT:
                                new_point = my_head.shift_left(1)
                            elif act == SnakeAction.RIGHT:
                                new_point = my_head.shift_right(1)
                            if gcb.get_element_at(new_point) != Element(
                                    'WALL'):
                                res.append((action_index,
                                            get_score(gcb, new_point, rage)))
                    if len(res) == 0:
                        return
                    action_index = res[-1][0]

                self.df = self.df.append(
                    {
                        'tick': self.tick,
                        'board': board_str,
                        'action': action_index
                    },
                    ignore_index=True)
                self.df.to_csv(f'logs/log_new_{self.n}.csv', index=False)
                self.tick += 1
                self.prev_action = actions[action_index]
                return self.prev_action
        except Exception as e:
            print('Exception', e)
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)
            pass
示例#11
0
 def am_i_flying(self):
     return self._find_all(Element('HEAD_FLY')).__contains__(
         self.get_my_head())
示例#12
0
 def get_enemies_tails(self):
     return self._find_all(Element('ENEMY_TAIL_END_DOWN'),
                           Element('ENEMY_TAIL_END_LEFT'),
                           Element('ENEMY_TAIL_END_UP'),
                           Element('ENEMY_TAIL_END_RIGHT'))
示例#13
0
def turn(gcb: Board):

    global fileRoundOpen
    global fileRound

    if emul == 0:  #Save state
        f = open("pole.txt", "w")
        # Записываем данные доски
        f.write(gcb._string + "\n")
        f.write(gcb._size.__str__() + "\n")
        f.write(gcb._len.__str__() + "\n")
        f.close()

    else:
        gcb.print_board()

    timeStart = datetime.datetime.now()

    try:
        pole = Pole(gcb)
    except ValueError:
        print('Ошибка1')

    try:
        pole.read()  # считываем данные с поля
    except ValueError:
        print('Ошибка2')

    if emul == 0:
        if pole.time == 1:
            fileRoundOpen = 1
            fileRound = open("raunds/" + timeStart.__str__() + ".txt", "w")

        if fileRoundOpen == 1:
            # Записываем данные доски
            fileRound.write(gcb._string + "\n")
            fileRound.write(gcb._size.__str__() + "\n")
            fileRound.write(gcb._len.__str__() + "\n")

        if fileRoundOpen == 1 and pole.time < 1:
            fileRound.close()
            fileRoundOpen = 0

    print("Finish " + datetime.datetime.now().__str__())

    try:
        pole.printSnakesInfo()
    except ValueError:
        print('Ошибка3')

    firstAction = SnakeAction.RIGHT

    if pole.snake.slep == 0 or not (pole.snake.x == 0 and pole.snake.y == 0):
        # try:
        napravlenie = pole.fill()

        if napravlenie == Mapping.SNAKE_LEFT:
            firstAction = SnakeAction.LEFT
        elif napravlenie == Mapping.SNAKE_RIGHT:
            firstAction = SnakeAction.RIGHT
        elif napravlenie == Mapping.SNAKE_UP:
            firstAction = SnakeAction.UP
        elif napravlenie == Mapping.SNAKE_DOWN:
            firstAction = SnakeAction.DOWN

    # except ValueError:
    #     print('Ошибка4')
    else:
        firstAction = SnakeAction.STOP

    # return random.choice(list(SnakeAction))

    # point = gcb.get_point_by_shift(SnakeAction.UP)
    # wormHead = gcb.get_my_head()

    # firstAction = None

    # if pole.snake.x > 0:
    # # if isinstance(wormHead, Point):
    #     print("head x = ", pole.snake.x,", y = ", pole.snake.y)

    #     pole.full_map()

    #     nextElement = pole.findElement(pole.snake.x, pole.snake.y)

    #     if isinstance(nextElement, Point):
    #         firstAction = goTo(pole, nextElement)
    #     else:
    #         print("Not find next element")

    # point = gcb.find_first_element(Element.get_char.STONE)
    # print(head)

    # nextElement = gcb.find_first_element(Element('APPLE'), Element('FURY_PILL'),
    #                                    Element('GOLD'), Element('FLYING_PILL'), Element('FURY_PILL'))

    # if isinstance(nextElement, Point):
    #     # el = gcb.get_element_at(nextElement)
    #     print("element x = ", nextElement._x,", y = ", nextElement._y)

    if isinstance(firstAction, SnakeAction):
        nextAction = firstAction

        max = len(pole.snake.coordinates)
        if max > 1:
            x, y = pole.snake.coordinates[max - 1]
            el_tail = pole.get_element_at(
                pole._strpos2pt(pole._xy2strpos(x, y)))
            stone = 0
            if el_tail == Element('TAIL_END_DOWN'):
                dx = 0
                dy = +1
                stone = 1
            elif el_tail == Element('TAIL_END_LEFT'):
                dx = -1
                dy = 0
                stone = 1
            elif el_tail == Element('TAIL_END_UP'):
                dx = 0
                dy = -1
                stone = 1
            elif el_tail == Element('TAIL_END_RIGHT'):
                dx = +1
                dy = 0
                stone = 1
            if stone == 1:
                el = pole.get_element_at(
                    pole._strpos2pt(pole._xy2strpos(x + dx, y + dy)))
                if el == Element('ENEMY_HEAD_DOWN') or el == Element(
                        'ENEMY_HEAD_LEFT') or el == Element(
                            'ENEMY_HEAD_RIGHT') or el == Element(
                                'ENEMY_HEAD_UP'):
                    # Бросим камень
                    if nextAction == SnakeAction.RIGHT:
                        nextAction == SnakeAction.ACT_RIGHT
                    elif nextAction == SnakeAction.LEFT:
                        nextAction == SnakeAction.ACT_LEFT
                    elif nextAction == SnakeAction.UP:
                        nextAction == SnakeAction.ACT_UP
                    elif nextAction == SnakeAction.DOWN:
                        nextAction == SnakeAction.ACT_DOWN

    else:
        nextAction = SnakeAction.RIGHT

    if pole.snake.x <= 0:
        nextAction = SnakeAction.STOP

    print("sent: " + nextAction.__str__())

    # poleLastCourse = pole

    # nextAction = SnakeAction.LEFT

    timeFinish = datetime.datetime.now()
    raznica = timeFinish - timeStart

    print("Start " + timeStart.__str__() + ", finish " + timeFinish.__str__() +
          " === " + raznica.microseconds.__str__())

    if emul == 2:
        time.sleep(0)

    return nextAction
示例#14
0
 def get_walls(self):
     walls = self._find_all(Element('WALL'))
     start_points = self._find_all(Element('START_FLOOR'))
     return walls + start_points
示例#15
0
 def get_stones(self):
     return self._find_all(Element('STONE'))
示例#16
0
from builtins import enumerate

from math import sqrt
from snakebattleclient.internals.Element import Element, SEARCH_HELPER
from snakebattleclient.internals.Point import Point

heads_elements = [
    Element('ENEMY_HEAD_DOWN'),
    Element('ENEMY_HEAD_LEFT'),
    Element('ENEMY_HEAD_RIGHT'),
    Element('ENEMY_HEAD_UP'),
    Element('ENEMY_HEAD_EVIL'),
    Element('ENEMY_HEAD_DEAD'),
    Element('HEAD_DOWN'),
    Element('HEAD_LEFT'),
    Element('HEAD_RIGHT'),
    Element('HEAD_UP'),
    Element('HEAD_EVIL'),
    Element('HEAD_DEAD')
]


class Board:
    """ Class describes the Board field for Bomberman game."""
    def __init__(self, board_string):
        self._string = board_string.replace('\n', '')
        self._len = len(self._string)  # the length of the string
        self._size = int(sqrt(self._len))  # size of the board
        self.walls = None
        self.stones = None
        self.golds = None
示例#17
0
 def get_walls(self):
     return self._find_all(Element('WALL'))
示例#18
0
from snakebattleclient.internals.Element import Element

import pandas as pd
import numpy as np
from operator import itemgetter
import os
import sys

from collections import defaultdict

actions = list(SnakeAction)

logging.basicConfig(format='%(asctime)s %(levelname)s:%(message)s',
                    level=logging.ERROR)

my_down = Element('HEAD_DOWN')
my_left = Element('HEAD_LEFT')
my_right = Element('HEAD_RIGHT')
my_up = Element('HEAD_UP')

good_positions = [my_down, my_left, my_right, my_up]

base_good_elements = [
    Element('NONE'),
    Element('APPLE'),
    Element('FLYING_PILL'),
    Element('FURY_PILL'),
    Element('GOLD'),
]

good_elements = [
示例#19
0
 def get_free_space(self):
     return self._find_all(Element('NONE'))
示例#20
0
 def am_i_evil(self):
     return self._find_all(Element('HEAD_EVIL')).__contains__(
         self.get_my_head())
示例#21
0
 def get_my_tail(self):
     return self.find_first_element(Element('TAIL_END_DOWN'),
                                    Element('TAIL_END_LEFT'),
                                    Element('TAIL_END_UP'),
                                    Element('TAIL_END_RIGHT'))
示例#22
0
def get_score(gcb, new_point, rage):
    n = 25
    score = 0
    value = 8**(n + 1)

    if not rage:
        target_els = [Element('APPLE'), Element('FURY_PILL'), Element('GOLD')]
    else:
        target_els = [
            Element('APPLE'),
            Element('FURY_PILL'),
            Element('GOLD'),
            Element('STONE')
        ] + enemies_bodies

    if gcb.get_element_at(new_point) in target_els:
        score += value

    if gcb.get_element_at(new_point) == Element('FURY_PILL'):
        score += 35 * value
        return score

    if gcb.get_element_at(new_point) in enemies_bodies:
        score += 75 * value
        return score

    value /= 8

    for d in range(1, n):
        p1 = new_point.shift_top(d)
        p2 = new_point.shift_bottom(d)
        p3 = new_point.shift_right(d)
        p4 = new_point.shift_left(d)
        ps = [p1, p2, p3, p4]
        for p in ps:
            if p.is_out_of_board(gcb._size):
                continue
            if gcb.get_element_at(p) in target_els:
                #score += value
                if gcb.get_element_at(p) == Element('FURY_PILL'):
                    score += 35 * value
                if gcb.get_element_at(new_point) in enemies_bodies:
                    score += 55 * value
                #TODO:
                next_steps = [
                    p.shift_top(1),
                    p.shift_bottom(1),
                    p.shift_left(1),
                    p.shift_right(1)
                ]
                if not rage:
                    s = np.count_nonzero([
                        gcb.get_element_at(x) in good_elements
                        for x in next_steps
                    ])
                else:
                    s = np.count_nonzero([
                        gcb.get_element_at(x) in good_elements + [
                            Element('STONE'),
                        ] + enemies_bodies + enemies_tails for x in next_steps
                    ])
                if s > 1:
                    score += value
                    #return score
        value /= 8
    return score
示例#23
0
 def get_apples(self):
     return self._find_all(Element('APPLE'))
示例#24
0
    def __call__(self, gcb: Board):
        try:
            board_str = gcb._line_by_line()
            #src_gcb = Board(board_str)

            my_head = gcb.get_my_head()

            if my_head is None:
                print('my_head is None')
                if self.head is None:
                    return SnakeAction.RIGHT
                if self.prev_action == SnakeAction.RIGHT:
                    self.head = self.head.shift_right(1)
                if self.prev_action == SnakeAction.LEFT:
                    self.head = self.head.shift_left(1)
                if self.prev_action == SnakeAction.UP:
                    self.head = self.head.shift_top(1)
                if self.prev_action == SnakeAction.DOWN:
                    self.head = self.head.shift_bottom(1)
                my_head = self.head
                #return SnakeAction.RIGHT
                if self.prev_action == SnakeAction.RIGHT:
                    my_head_el = Element('HEAD_RIGHT')
                if self.prev_action == SnakeAction.LEFT:
                    my_head_el = Element('HEAD_LEFT')
                if self.prev_action == SnakeAction.UP:
                    my_head_el = Element('HEAD_UP')
                if self.prev_action == SnakeAction.DOWN:
                    my_head_el = Element('HEAD_DOWN')
                gcb.assign_point(my_head, my_head_el)
                rage = self.ticks_rage > 0
            else:
                self.head = my_head
                my_head_el = gcb.get_element_at(my_head)
                rage = my_head_el == Element('HEAD_EVIL')

            if rage:
                if self.prev_action == SnakeAction.RIGHT:
                    my_head_el = Element('HEAD_RIGHT')
                if self.prev_action == SnakeAction.LEFT:
                    my_head_el = Element('HEAD_LEFT')
                if self.prev_action == SnakeAction.UP:
                    my_head_el = Element('HEAD_UP')
                if self.prev_action == SnakeAction.DOWN:
                    my_head_el = Element('HEAD_DOWN')

            #print(my_head, my_head_el)
            gcb.assign_point(my_head, my_head_el)

            first_rage = False

            if rage and not self.prev_rage:
                first_rage = True
                self.ticks_rage = RAGE_TICKS - 1
            self.ticks_rage -= 1
            self.prev_rage = rage
            if self.ticks_rage <= 0:
                rage = False

            use_new = True  #not rage

            print_rage = False

            gcb.update_board(my_head, rage, self.prev_action)
            #gcb.update_board(my_head, False, self.prev_action)
            if use_new:
                gcb.create_access_reprs(my_head)
            #my_head_el = gcb.get_element_at(my_head)

            if my_head_el not in good_positions and False:
                self.prev_action = get_same_direction(my_head_el)
                return self.prev_action
            else:
                if True:
                    if use_new:
                        base_targets = [
                            Element('APPLE'),
                            Element('FURY_PILL'),
                            Element('GOLD')
                        ]
                        if not rage:
                            targets = gcb._find_all(*base_targets)
                        else:
                            if print_rage:
                                print(
                                    'rage: ',
                                    len(
                                        gcb._find_all(*enemies_bodies,
                                                      *enemies_heads)))
                            targets = gcb._find_all(Element('STONE'),
                                                    *enemies_bodies,
                                                    *enemies_heads,
                                                    *base_targets)
                            if print_rage:
                                print(
                                    'STONES:',
                                    len([
                                        t for t in targets
                                        if gcb.get_element_at(t) == Element(
                                            'STONE')
                                    ]))

                        dists = [gcb.get_dist_to(t, rage) for t in targets]
                        els = [gcb.get_element_at(t) for t in targets]

                        #                         targets_with_dists = [
                        #                             (t, d if e != Element('FURY_PILL') else 0.66*d, scores[e.get_char()], e )
                        #                                               for t, d, e in zip(targets, dists, els) if d != 666
                        #                                               and (d <= self.ticks_rage or e in base_targets)
                        #                                              ]
                        targets_with_dists = [
                            (t, d, scores[e.get_char()], e)
                            for t, d, e in zip(targets, dists, els)
                            if d != 666 and (
                                d <= self.ticks_rage or e in base_targets)
                        ]
                        if print_rage:
                            print(
                                'STONES:',
                                len([
                                    t[0] for t in targets_with_dists
                                    if t[-1] == Element('STONE')
                                ]))

                        next_steps = [
                            my_head.shift_top(1),
                            my_head.shift_bottom(1),
                            my_head.shift_left(1),
                            my_head.shift_right(1)
                        ]

                        if print_rage:
                            for p in next_steps:
                                print(
                                    p,
                                    p.is_out_of_board(gcb._size),
                                    str(gcb.get_element_at(p)),
                                    #str(src_gcb.get_element_at(p))
                                )

                        next_steps_els = [(p, gcb.get_element_at(p))
                                          for p in next_steps]
                        #print('next_steps_els 1:', [ (p, str(e)) for p,e in next_steps_els])

                        next_steps_els = [(p, e) for p, e in next_steps_els
                                          if e != Element('WALL')
                                          and not p.is_out_of_board(gcb._size)]

                        #print('next_steps_els 2:', [ (p, str(e)) for p,e in next_steps_els])

                        if not rage:
                            next_steps_els = [
                                se for se in next_steps_els
                                if se[1] not in enemies_bodies
                            ]

                        target_with_scores = {
                            se[0]: 0.0
                            for se in next_steps_els
                        }

                        for t, d, s, e in targets_with_dists:
                            ps = list(gcb.get_next_step_to(t, rage))
                            for p in ps:
                                if p in target_with_scores:
                                    target_with_scores[p] += s / d
                                    #target_with_scores[p] += s/(d**1.5)
                                    #target_with_scores[p] += s/(d**4)
                                    #target_with_scores[p] += s/(d**2)

                        target_with_scores_list = [
                            (k, v) for k, v in target_with_scores.items()
                        ]
                        target_with_scores_list.sort(key=itemgetter(1))
                        #print(f'target_with_scores_list {str(my_head_el)} :', target_with_scores_list)

                        #                         targets_with_dists.sort(key=itemgetter(1))
                        #                         for tdc in targets_with_dists:
                        #                             if gcb.get_element_at(tdc[0]) in enemies_bodies:
                        #                                 print('ENEMY FOUND:', tdc[1])

                        #                         #targets_with_dists = targets_with_dists[:10]

                        #                         if rage:
                        #                             pass
                        #                             print('targets_with_dists:', targets_with_dists)

                        if len(target_with_scores_list) > 0 and True:
                            target = target_with_scores_list[-1][0]
                            if gcb.get_element_at(target) == Element(
                                    'FURY_PILL'):
                                self.ticks_rage += RAGE_TICKS
                            if my_head.shift_top(1) == target:
                                self.prev_action = SnakeAction.UP
                                return self.prev_action
                            if my_head.shift_bottom(1) == target:
                                self.prev_action = SnakeAction.DOWN
                                return self.prev_action
                            if my_head.shift_left(1) == target:
                                self.prev_action = SnakeAction.LEFT
                                return self.prev_action
                            if my_head.shift_right(1) == target:
                                self.prev_action = SnakeAction.RIGHT
                                return self.prev_action
                            else:
                                print('use old algo:', targets_with_dists)

                    res = []
                    for action_index in range(4):
                        #action_index = random.randint(0,3)
                        act = actions[action_index]
                        if is_opposite(act, my_head_el):
                            continue
                        if act == SnakeAction.UP:
                            new_point = my_head.shift_top(1)
                        elif act == SnakeAction.DOWN:
                            new_point = my_head.shift_bottom(1)
                        elif act == SnakeAction.LEFT:
                            new_point = my_head.shift_left(1)
                        elif act == SnakeAction.RIGHT:
                            new_point = my_head.shift_right(1)
                        if is_good(gcb,
                                   new_point,
                                   rage,
                                   allow_stones=False,
                                   allow_body=False):
                            #print('GOOD:', act, 'RAGE:', rage)
                            res.append(
                                (action_index, get_score(gcb, new_point,
                                                         rage)))

                    if len(res) == 0:
                        for action_index in range(4):
                            #action_index = random.randint(0,3)
                            act = actions[action_index]
                            if is_opposite(act, my_head_el):
                                continue
                            if act == SnakeAction.UP:
                                new_point = my_head.shift_top(1)
                            elif act == SnakeAction.DOWN:
                                new_point = my_head.shift_bottom(1)
                            elif act == SnakeAction.LEFT:
                                new_point = my_head.shift_left(1)
                            elif act == SnakeAction.RIGHT:
                                new_point = my_head.shift_right(1)
                            if is_good(gcb, new_point, rage, True):
                                #print('GOOD:', act, 'RAGE:', rage)
                                res.append((action_index,
                                            get_score(gcb, new_point, rage)))

                    if len(res) == 0:
                        for action_index in range(4):
                            #action_index = random.randint(0,3)
                            act = actions[action_index]
                            if is_opposite(act, my_head_el):
                                continue
                            if act == SnakeAction.UP:
                                new_point = my_head.shift_top(1)
                            elif act == SnakeAction.DOWN:
                                new_point = my_head.shift_bottom(1)
                            elif act == SnakeAction.LEFT:
                                new_point = my_head.shift_left(1)
                            elif act == SnakeAction.RIGHT:
                                new_point = my_head.shift_right(1)
                            if is_good(gcb, new_point, rage, True, True):
                                #print('GOOD:', act, 'RAGE:', rage)
                                res.append((action_index,
                                            get_score(gcb, new_point, rage)))

                    random.shuffle(res)
                    #print(rage, res)
                    res.sort(key=itemgetter(1))
                    #print(rage, res)
                    if len(res) == 0:
                        for action_index in range(4):
                            act = actions[action_index]
                            if is_opposite(act, my_head_el):
                                continue
                            if act == SnakeAction.UP:
                                new_point = my_head.shift_top(1)
                            elif act == SnakeAction.DOWN:
                                new_point = my_head.shift_bottom(1)
                            elif act == SnakeAction.LEFT:
                                new_point = my_head.shift_left(1)
                            elif act == SnakeAction.RIGHT:
                                new_point = my_head.shift_right(1)
                            if gcb.get_element_at(new_point) != Element(
                                    'WALL'):
                                res.append((action_index,
                                            get_score(gcb, new_point, rage)))
                    if len(res) == 0:
                        return
                    action_index = res[-1][0]

                self.df = self.df.append(
                    {
                        'tick': self.tick,
                        'board': board_str,
                        'action': action_index
                    },
                    ignore_index=True)
                self.df.to_csv(f'logs/log_new_{self.n}.csv', index=False)
                self.tick += 1
                self.prev_action = actions[action_index]
                return self.prev_action
        except Exception as e:
            print('Exception', e)
            exc_type, exc_obj, exc_tb = sys.exc_info()
            fname = os.path.split(exc_tb.tb_frame.f_code.co_filename)[1]
            print(exc_type, fname, exc_tb.tb_lineno)
            pass