x01.AntWorld: An Python AI Game



1. 学习了一下 AI 五子棋,顺手改作 19 路的棋盘,便于围棋通用。render.py 主要修改如下:

 

  # 常量部分:

IMAGE_PATH = 'img/'

StoneSize = 32

WIDTH = 650

HEIGHT = 732

ColSize = 33

RowSize = 34.44

H_Pad = (HEIGHT- RowSize * 19) / 2 + (RowSize - StoneSize) / 2 + 1

W_Pad = (WIDTH - ColSize * 19) / 2 + (ColSize - StoneSize) / 2 + 1

Pad = ColSize - StoneSize, RowSize - StoneSize

PIECE = StoneSize


# 坐标转换部分:

    def coordinate_transform_map2pixel(self, i, j):   

        # 从 chessMap 里的逻辑坐标到 UI 上的绘制坐标的转换

        return j * (PIECE+Pad[0]) + W_Pad, i * (PIECE+Pad[1]) + H_Pad


    def coordinate_transform_pixel2map(self, x, y):   

        # 从 UI 上的绘制坐标到 chessMap 里的逻辑坐标的转换

        i , j = int((y-H_Pad) / (PIECE+Pad[1])), int((x-W_Pad) / (PIECE+Pad[0]))

       

        if i < 0 or i >= N or j < 0 or j >= N:

            return None, None

        else:

            return i, j

 

2. 发现 pygame 还不错,便从网上搜索到《Beginning Game Development With PYTHON And Pygame》,其中蚂蚁游戏的 AI 表现甚好,主要代码如下:



  

   import pygame


from pygame.locals import *

from random import randint

from core.vector2d import Vector2D


ScreenSize = (640, 480)

NestLocation = (320, 240)

AntCount = 20

NestSize = 100.0

ImgPath = "img/"


class State(object):

    def __init__(self, name):

        self.name = name

    def do_actions(self):

        pass

    def check_conditions(self):

        pass

    def entry_actions(self):

        pass

    def exit_actions(self):

        pass


class StateMachine(object):

    def __init__(self):

        self.states = {}

        self.active_state = None

    def add_state(self, state):

        self.states[state.name] = state

    def think(self):

        if self.active_state is None:

            return

        self.active_state.do_actions()

        new_state_name = self.active_state.check_conditions()

        if new_state_name is not None:

            self.set_state(new_state_name)

    def set_state(self, new_state_name):

        if self.active_state is not None:

            self.active_state.exit_actions()

        self.active_state = self.states[new_state_name]

        self.active_state.entry_actions()


class World(object):

    def __init__(self):

        self.entities = {}

        self.entity_id = 0

        self.background = pygame.surface.Surface(ScreenSize).convert()

        self.background.fill((255,255,255))

        pygame.draw.circle(self.background, (200,255,200), NestLocation, int(NestSize))

    def add_entity(self, entity):

        self.entities[self.entity_id] = entity

        entity.id = self.entity_id

        self.entity_id += 1

    def remove_entity(self, entity):

        del self.entities[entity.id]

    def get(self, entity_id):

        if entity_id in self.entities:

            return self.entities[entity_id]

        else:

            return None

    def process(self, time_passed):

        time_passed_seconds = time_passed / 1000.0

        entities = list(self.entities.values())

        for entity in entities:

            entity.process(time_passed_seconds)

    def render(self, surface):

        surface.blit(self.background, (0,0))

        for entity in self.entities.values():

            entity.render(surface)

    def [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_close_entity(self, name, location, range=100.0):

        location = Vector2D(*location)

        for entity in self.entities.values():

            if entity.name == name:

                distance = location.get_distance_to(entity.location)

                if distance < range:

                    return entity

        return None


class GameEntity(object):

    def __init__(self, world, name, image):

        self.world = world

        self.name = name

        self.image = image

        self.location = Vector2D(0, 0)

        self.destination = Vector2D(0, 0)

        self.speed = 0

        self.brain = StateMachine()

        self.id = 0

    def render(self, surface):

        x,y = self.location

        w,h = self.image.get_size()

        surface.blit(self.image, (x-w/2, y-h/2))

    def process(self, time_passed):

        self.brain.think()

        if self.speed > 0 and self.location != self.destination:

            vec_to_destination = self.destination - self.location

            distance_to_destination = vec_to_destination.get_length()

            heading = vec_to_destination.get_normalized()

            travel_distance = min(distance_to_destination, time_passed * self.speed)

            self.location += travel_distance * heading

   

class Leaf(GameEntity):

    def __init__(self, world, image):

        GameEntity.__init__(self, world, "leaf", image)

   

class Spider(GameEntity):

    def __init__(self, world, image):

        GameEntity.__init__(self, world, "spider", image)

        self.dead_image = pygame.transform.flip(image, 0, 1)

        self.health = 25

        self.speed = 50.0 + randint(-20,20)

    def bitten(self):

        self.health -= 1

        if self.health <= 0:

            self.speed = 0

            self.image = self.dead_image

        self.speed = 140

    def render(self, surface):

        GameEntity.render(self, surface)

        x,y = self.location

        w,h = self.image.get_size()

        bar_x = x - 12

        bar_y = y + h/2

        surface.fill((255,0,0), (bar_x, bar_y, 25, 4))

        surface.fill((0,255,0), (bar_x, bar_y, self.health, 4))

    def process(self, time_passed):

        x,y = self.location

        if x > ScreenSize[0] + 2:

            self.world.remove_entity(self)

            return

        GameEntity.process(self, time_passed)

   

class Ant(GameEntity):

    def __init__(self, world, image):

        GameEntity.__init__(self, world, "ant", image)

        exploring_state = AntStateExploring(self)

        seeking_state = AntStateSeeking(self)

        delivering_state = AntStateDelivering(self)

        hunting_state = AntStateHunting(self)

        self.brain.add_state(exploring_state)

        self.brain.add_state(seeking_state)

        self.brain.add_state(delivering_state)

        self.brain.add_state(hunting_state)

        self.carry_image = None

    def carry(self, image):

        self.carry_image = image

    def drop(self, surface):

        if self.carry_image:

            x,y = self.location

            w,h = self.carry_image.get_size()

            surface.blit(self.carry_image, (x-w, y-h/2))

            self.carry_image = None

    def render(self, surface):

        GameEntity.render(self, surface)

        if self.carry_image:

            x,y = self.location

            w,h = self.carry_image.get_size()

            surface.blit(self.carry_image, (x-w, y-h/2))


class AntStateExploring(State):

    def __init__(self, ant):

        State.__init__(self, "exploring")

        self.ant = ant

    def random_destination(self):

        w,h = ScreenSize

        self.ant.destination = Vector2D(randint(0, w), randint(0, h))

    def do_actions(self):

        if randint(1,20) == 1:

            self.random_destination()

    def check_conditions(self):

        leaf = self.ant.world. [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_close_entity("leaf", self.ant.location)

        if leaf is not None:

            self.ant.leaf_id = leaf.id

            return "seeking"

        spider = self.ant.world. [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_close_entity("spider", NestLocation, NestSize)

        if spider is not None:

            if self.ant.location.get_distance_to(spider.location) < 100:

                self.ant.spider_id = spider.id

                return "hunting"

        return None

    def entry_actions(self):

        self.ant.speed = 120 + randint(-30, 30)

        self.random_destination()


class AntStateSeeking(State):

    def __init__(self, ant):

        State.__init__(self, "seeking")

        self.ant = ant

        self.leaf_id = None

    def check_conditions(self):

        leaf = self.ant.world.get(self.ant.leaf_id)

        if leaf is None:

            return "exploring"

        if self.ant.location.get_distance_to(leaf.location) < 5:

            self.ant.carry(leaf.image)

            self.ant.world.remove_entity(leaf)

            return "delivering"

        return None

    def entry_actions(self):

        leaf = self.ant.world.get(self.ant.leaf_id)

        if leaf is not None:

            self.ant.destination = leaf.location

            self.ant.speed = 160 + randint(-20,20)


class AntStateDelivering(State):

    def __init__(self, ant):

        State.__init__(self, "delivering")

        self.ant = ant

    def check_conditions(self):

        if Vector2D(*NestLocation).get_distance_to(self.ant.location) < NestSize:

            if randint(1, 10) == 1:

                self.ant.drop(self.ant.world.background)

                return "exploring"

        return None

    def entry_actions(self):

        self.ant.speed = 60

        random_offset = Vector2D(randint(-20,20), randint(-20,20))

        self.ant.destination = Vector2D(*NestLocation) + random_offset


class AntStateHunting(State):

    def __init__(self, ant):

        State.__init__(self, "hunting")

        self.ant = ant

        self. [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_kill = False

    def do_actions(self):

        spider = self.ant.world.get(self.ant.spider_id)

        if spider is None:

            return

        self.ant.destination = spider.location

        if self.ant.location.get_distance_to(spider.location) < 15:

            if randint(1,5) == 1:

                spider.bitten()

                if spider.health <= 0:

                    self.ant.carry(spider.image)

                    self.ant.world.remove_entity(spider)

                    self. [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_kill = True

    def check_conditions(self):

        if self. [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_kill:

            return "delivering"

        spider = self.ant.world.get(self.ant.spider_id)

        if spider is None:

            return "exploring"

        if spider.location.get_distance_to(NestLocation) > NestSize * 3:

            return "exploring"

        return None

    def entry_actions(self):

        self.speed = 160 + randint(0,50)

    def exit_actions(self):

        self. [url=http://www.cppentry.com/list.php?fid=77]PYTHON[/url]t_kill = False


def run():

    pygame.init()

    screen = pygame.display.set_mode(ScreenSize, 0, 32)

    world = World()

    w,h = ScreenSize

    clock = pygame.time.Clock()


    ant_image = pygame.image.load(ImgPath + "ant.png").convert_alpha()

    leaf_image = pygame.image.load(ImgPath + "leaf.png").convert_alpha()

    spider_image = pygame.image.load(ImgPath + "spider.png").convert_alpha()


    for ant_nr in range(AntCount):

        ant = Ant(world, ant_image)

        ant.location = Vector2D(randint(0,w), randint(0,h))

        ant.brain.set_state("exploring")

        world.add_entity(ant)


    while True:

        for e in pygame.event.get():

            if e.type == QUIT:

                return

        time_passed = clock.tick(30)

        if randint(1,10) == 1:

            leaf = Leaf(world, leaf_image)

            leaf.location = Vector2D(randint(0,w), randint(0,h))

            world.add_entity(leaf)

        if randint(1,100) == 1:

            spider = Spider(world, spider_image)

            spider.location = Vector2D(-50, randint(0,h))

            spider.destination = Vector2D(w+50, randint(0,h))

            world.add_entity(spider)

        world.process(time_passed)

        world.render(screen)


        pygame.display.update()

  

  antworld.py

 

运行效果图如下:

                   

 

完整源代码下载:http://download.csdn.net/download/china_x01/10125074

 

猜你喜欢

转载自epoll-select.iteye.com/blog/2406359