<commit_before>from __future__ import division
import math
import operator
import os

import numpy
import pyglet
from pyglet.gl import *
import yaml

from edge import *
from const import *
from model import *
from state import *

class Util(object):
    '''Utility class with various helpful functions.'''

    @staticmethod
    def showHelp():
        '''Prints command line usage help.'''
        helpLines = [
            ("-h, --help", "Shows this help."),
            ("-d", "Displays debug information in-game."),
            ("--worldtype TYPE", "Choose a world type to generate. Options: {}".format(Const.WORLD_TYPES)),
            ("--seed STRING", "Specify a world seed to use. Uses system time by default.")
        ]
        for line in helpLines:
            print "{:<16}\t{}".format(*line)

    @staticmethod
    def loadModels(modeltype):
        '''Loads flyweight models from yaml files given the model type'''
        models = {}
        defaultmodel = None
        counter = -1
        for dict in yaml.load_all(open("{}/{}models.yml".format(Const.RESOURCE_PATH, modeltype), 'r')):
            
            counter += 1
            dict['modeltype'] = modeltype
            model = Model(dict)
            models[dict['type']] = model
            
            # Set the default model
            if dict['type'] == 'default':
                defaultmodel = model
            elif 'defaultmodel' not in dict:
                model.set('defaultmodel', defaultmodel)

        print "Loaded {} {} models".format(counter, modeltype)
        return models

    @staticmethod
    def circle(x, y, r):
        blocks = []
        for ix in xrange(int(x-r), int(x+r)):
            for iy in xrange(int(y-r), int(y+r)):
                if (ix-x)**2 + (iy-y)**2 < r**2:
                    blocks.append((ix, iy))
        return blocks

    @staticmethod
    def line((x, y), (x2, y2)):
        '''
        Returns a list of all block coordinates between the two points, inclusive, using Brensenham's line algorithm.
        From http://mail.scipy.org/pipermail/scipy-user/2009-September/022602.html
        '''
        steep = 0
        coords = []
        dx = abs(x2 - x)
        if (x2 - x) > 0: sx = 1
        else: sx = -1
        dy = abs(y2 - y)
        if (y2 - y) > 0: sy = 1
        else: sy = -1
        if dy > dx:
            steep = 1
            x,y = y,x
            dx,dy = dy,dx
            sx,sy = sy,sx
        d = (2 * dy) - dx
        for i in range(0,dx):
            if steep: coords.append((y,x))
            else: coords.append((x,y))
            while d >= 0:
                y = y + sy
                d = d - (2 * dx)
            x = x + sx
            d = d + (2 * dy)
        return coords #added by me

    @staticmethod
    def distancePoint(a, b):
         ax, ay = a
         bx, by = b
         return math.sqrt((bx-ax)**2 + (by-ay)**2)

    @staticmethod
    def getAdjacentCoords(loc, world=None, multiLayer=False):
        '''
        Returns all coords directly adjacent to the given coords (i.e. left, right, above, and below).
        If a world is specified, it will only return coordinates valid for the world.
        This works on any "world" object that has a "isValidCoords" method, including World, WorldGen, WorldLayer, and Chunk.
        If multiLayer is enabled, it will also return the coords behind and in front, with the layer in each tuple.
        The layer of the input coords must be specified as the third element in the location tuple if using multiLayer.
        '''
        x, y = loc[:2]
        if multiLayer:
            l = loc[2]
            checkCoords = [(x+1,y,l),(x-1,y,l),(x,y+1,l),(x,y-1,l),(x,y,l+1),(x,y,l-1)]
        else:
            checkCoords = (x+1,y),(x-1,y),(x,y+1),(x,y-1)

        if world is not None:
            validCoords = []
            for coords in checkCoords:
                if world.isValidCoords(coords):
                    validCoords.append(coords)
        else:
            validCoords = checkCoords

        return validCoords

    @staticmethod
    def add_tuple(*args):
        return tuple(map(sum, zip(*args)))

    @staticmethod
    def sub_tuple(a, b):
        return tuple(map(operator.sub, a, b))

    @staticmethod
    def mul_tuple(a, b):
        return tuple(map(operator.mul, a, b))

    @staticmethod
    def div_tuple(a, b):
        return tuple(map(operator.div, a, b))

    @staticmethod
    def int_tuple(a):
        return tuple(map(int, a))

    @staticmethod
    def int_floor(a):
        return tuple(map(int, map(math.floor, a)))

    @staticmethod
    def getLineOfSightBlocks((dx, dy), world, loc, l=1, maxblocks=None, maxdistance=None):
        '''Returns a list of all coordinates up to and including the first solid block found in 'world' on layer 'l' at 'loc' in the direction of the unit vector '(dx, dy)'.  Stops checking if maxdistance or maxblocks are specified and reached.  The returned list is ordered from closest to farthest.'''

        blocks = []

        # Special case: Direction is zero. Return current block.
        if dx == 0 and dy == 0:
            if world.isSolidAt(loc, l=l):
                blocks.append(Util.int_floor(loc))

        # Special case: Direction is vertical or horizontal. Add direction vector to location until solid block is found.
        elif dx == 0 or dy == 0:
            newloc = loc
            while True:
                blocks.append(Util.int_floor(newloc))
                if world.isSolidAt(newloc, l=l) is not False: break # Stop once we hit a solid block or the edge of the world.
                if maxblocks is not None and len(blocks) >= maxblocks: break # Stop once we hit the maxblocks limit.
                if maxdistance is not None and Util.distancePoint(loc, newloc) >= maxdistance: break # Stop once we hit the maxdistance limit.
                newloc = Util.add_tuple(newloc, (dx, dy))

        # Otherwise, use Bresenham's line algorithm.
        else:
            slope = dy / dx
            x, y = loc
            while True:
                blocks.append(Util.int_floor((x, y)))
                if world.isSolidAt((x, y), l=l) is not False: break # Stop once we hit a solid block or the edge of the world.
                if maxblocks is not None and len(blocks) >= maxblocks: break # Stop once we hit the maxblocks limit.
                if maxdistance is not None and Util.distancePoint(loc, (x, y)) >= maxdistance: break # Stop once we hit the maxdistance limit.
                x += dx
                y = slope * (x - loc[0]) + loc[1]
            
        return blocks

    @staticmethod
    def getClosestSolidBlock((dx, dy), world, loc, l=1, maxdistance=None):
        '''Returns the coordinates of the closest solid block in 'world' on layer 'l' at 'loc' in the direction of the unit vector '(dx, dy)'.  Stops checking if maxdistance is specified and reached.'''
        blocks = Util.getLineOfSightBlocks((dx, dy), world, loc, l, maxdistance=maxdistance)
        if len(blocks) == 0: return None
        else: return blocks[-1]

    @staticmethod
    def getNearbySolidBlocks(entity):
        bb = entity.shape.getAABB(entity.body.transform, 0)
        blocks = []
        for x in xrange(int(bb.lowerBound[0] - 2), int(bb.upperBound[0] + 2)):
            for y in xrange(int(bb.lowerBound[1] - 2), int(bb.upperBound[1] + 2)):
                if entity.world.isSolidAt((x, y)):
                    blocks.append(Util.int_floor((x, y)))
        return blocks

    @staticmethod
    def getSurroundingBlocks(coords, r=1):
        '''Returns the blocks around (in square formation) the given block coordinates within the given range r, not including the center block.'''
        x, y = Util.int_floor(coords)
        blocks = []
        for bx in xrange(x-r, x+r+1):
            for by in xrange(y-r, y+r+1):
                blocks.append((bx, by))
        blocks.remove(coords)
        return blocks

    @staticmethod
    def addDebugStats(texts):
        '''Adds new debug stats to the HUD'''
        for text in texts:
            number = len(State().debugStats)
            label = pyglet.text.Label(text, font_size=14, color=(228, 228, 0, 255), batch=State().batch, group=State().group['debug'])
            State().debugStats.append((number, label, text))
<commit_msg>reduce physics blocks range around entities, slight performance increase<commit_after>from __future__ import division
import math
import operator
import os

import numpy
import pyglet
from pyglet.gl import *
import yaml

from edge import *
from const import *
from model import *
from state import *

class Util(object):
    '''Utility class with various helpful functions.'''

    @staticmethod
    def showHelp():
        '''Prints command line usage help.'''
        helpLines = [
            ("-h, --help", "Shows this help."),
            ("-d", "Displays debug information in-game."),
            ("--worldtype TYPE", "Choose a world type to generate. Options: {}".format(Const.WORLD_TYPES)),
            ("--seed STRING", "Specify a world seed to use. Uses system time by default.")
        ]
        for line in helpLines:
            print "{:<16}\t{}".format(*line)

    @staticmethod
    def loadModels(modeltype):
        '''Loads flyweight models from yaml files given the model type'''
        models = {}
        defaultmodel = None
        counter = -1
        for dict in yaml.load_all(open("{}/{}models.yml".format(Const.RESOURCE_PATH, modeltype), 'r')):
            
            counter += 1
            dict['modeltype'] = modeltype
            model = Model(dict)
            models[dict['type']] = model
            
            # Set the default model
            if dict['type'] == 'default':
                defaultmodel = model
            elif 'defaultmodel' not in dict:
                model.set('defaultmodel', defaultmodel)

        print "Loaded {} {} models".format(counter, modeltype)
        return models

    @staticmethod
    def circle(x, y, r):
        blocks = []
        for ix in xrange(int(x-r), int(x+r)):
            for iy in xrange(int(y-r), int(y+r)):
                if (ix-x)**2 + (iy-y)**2 < r**2:
                    blocks.append((ix, iy))
        return blocks

    @staticmethod
    def line((x, y), (x2, y2)):
        '''
        Returns a list of all block coordinates between the two points, inclusive, using Brensenham's line algorithm.
        From http://mail.scipy.org/pipermail/scipy-user/2009-September/022602.html
        '''
        steep = 0
        coords = []
        dx = abs(x2 - x)
        if (x2 - x) > 0: sx = 1
        else: sx = -1
        dy = abs(y2 - y)
        if (y2 - y) > 0: sy = 1
        else: sy = -1
        if dy > dx:
            steep = 1
            x,y = y,x
            dx,dy = dy,dx
            sx,sy = sy,sx
        d = (2 * dy) - dx
        for i in range(0,dx):
            if steep: coords.append((y,x))
            else: coords.append((x,y))
            while d >= 0:
                y = y + sy
                d = d - (2 * dx)
            x = x + sx
            d = d + (2 * dy)
        return coords #added by me

    @staticmethod
    def distancePoint(a, b):
         ax, ay = a
         bx, by = b
         return math.sqrt((bx-ax)**2 + (by-ay)**2)

    @staticmethod
    def getAdjacentCoords(loc, world=None, multiLayer=False):
        '''
        Returns all coords directly adjacent to the given coords (i.e. left, right, above, and below).
        If a world is specified, it will only return coordinates valid for the world.
        This works on any "world" object that has a "isValidCoords" method, including World, WorldGen, WorldLayer, and Chunk.
        If multiLayer is enabled, it will also return the coords behind and in front, with the layer in each tuple.
        The layer of the input coords must be specified as the third element in the location tuple if using multiLayer.
        '''
        x, y = loc[:2]
        if multiLayer:
            l = loc[2]
            checkCoords = [(x+1,y,l),(x-1,y,l),(x,y+1,l),(x,y-1,l),(x,y,l+1),(x,y,l-1)]
        else:
            checkCoords = (x+1,y),(x-1,y),(x,y+1),(x,y-1)

        if world is not None:
            validCoords = []
            for coords in checkCoords:
                if world.isValidCoords(coords):
                    validCoords.append(coords)
        else:
            validCoords = checkCoords

        return validCoords

    @staticmethod
    def add_tuple(*args):
        return tuple(map(sum, zip(*args)))

    @staticmethod
    def sub_tuple(a, b):
        return tuple(map(operator.sub, a, b))

    @staticmethod
    def mul_tuple(a, b):
        return tuple(map(operator.mul, a, b))

    @staticmethod
    def div_tuple(a, b):
        return tuple(map(operator.div, a, b))

    @staticmethod
    def int_tuple(a):
        return tuple(map(int, a))

    @staticmethod
    def int_floor(a):
        return tuple(map(int, map(math.floor, a)))

    @staticmethod
    def getLineOfSightBlocks((dx, dy), world, loc, l=1, maxblocks=None, maxdistance=None):
        '''Returns a list of all coordinates up to and including the first solid block found in 'world' on layer 'l' at 'loc' in the direction of the unit vector '(dx, dy)'.  Stops checking if maxdistance or maxblocks are specified and reached.  The returned list is ordered from closest to farthest.'''

        blocks = []

        # Special case: Direction is zero. Return current block.
        if dx == 0 and dy == 0:
            if world.isSolidAt(loc, l=l):
                blocks.append(Util.int_floor(loc))

        # Special case: Direction is vertical or horizontal. Add direction vector to location until solid block is found.
        elif dx == 0 or dy == 0:
            newloc = loc
            while True:
                blocks.append(Util.int_floor(newloc))
                if world.isSolidAt(newloc, l=l) is not False: break # Stop once we hit a solid block or the edge of the world.
                if maxblocks is not None and len(blocks) >= maxblocks: break # Stop once we hit the maxblocks limit.
                if maxdistance is not None and Util.distancePoint(loc, newloc) >= maxdistance: break # Stop once we hit the maxdistance limit.
                newloc = Util.add_tuple(newloc, (dx, dy))

        # Otherwise, use Bresenham's line algorithm.
        else:
            slope = dy / dx
            x, y = loc
            while True:
                blocks.append(Util.int_floor((x, y)))
                if world.isSolidAt((x, y), l=l) is not False: break # Stop once we hit a solid block or the edge of the world.
                if maxblocks is not None and len(blocks) >= maxblocks: break # Stop once we hit the maxblocks limit.
                if maxdistance is not None and Util.distancePoint(loc, (x, y)) >= maxdistance: break # Stop once we hit the maxdistance limit.
                x += dx
                y = slope * (x - loc[0]) + loc[1]
            
        return blocks

    @staticmethod
    def getClosestSolidBlock((dx, dy), world, loc, l=1, maxdistance=None):
        '''Returns the coordinates of the closest solid block in 'world' on layer 'l' at 'loc' in the direction of the unit vector '(dx, dy)'.  Stops checking if maxdistance is specified and reached.'''
        blocks = Util.getLineOfSightBlocks((dx, dy), world, loc, l, maxdistance=maxdistance)
        if len(blocks) == 0: return None
        else: return blocks[-1]

    @staticmethod
    def getNearbySolidBlocks(entity):
        bb = entity.shape.getAABB(entity.body.transform, 0)
        blocks = []
        for x in xrange(int(bb.lowerBound[0] - 1), int(bb.upperBound[0] + 2)):
            for y in xrange(int(bb.lowerBound[1] - 1), int(bb.upperBound[1] + 2)):
                if entity.world.isSolidAt((x, y)):
                    blocks.append(Util.int_floor((x, y)))
        return blocks

    @staticmethod
    def getSurroundingBlocks(coords, r=1):
        '''Returns the blocks around (in square formation) the given block coordinates within the given range r, not including the center block.'''
        x, y = Util.int_floor(coords)
        blocks = []
        for bx in xrange(x-r, x+r+1):
            for by in xrange(y-r, y+r+1):
                blocks.append((bx, by))
        blocks.remove(coords)
        return blocks

    @staticmethod
    def addDebugStats(texts):
        '''Adds new debug stats to the HUD'''
        for text in texts:
            number = len(State().debugStats)
            label = pyglet.text.Label(text, font_size=14, color=(228, 228, 0, 255), batch=State().batch, group=State().group['debug'])
            State().debugStats.append((number, label, text))

{'fraction_non_alphanumeric': 0.11438006604623237, 'fraction_numerical': 0.010087060942659862, 'mean_word_length': 2.0070409821267376, 'pattern_counts': {'":': 0, '<': 7, '<?xml version=': 0, '>': 19, 'https://': 0, 'lorem ipsum': 0, 'www.': 0, 'xml': 0}, 'pii_count': 0, 'substrings_counts': 0, 'word_list_counts': {'cursed_substrings.json': 0, 'profanity_word_list.json': 0, 'sexual_word_list.json': 0, 'zh_pornsignals.json': 0}}
{'dir': 'git-commits-cleaned', 'id': '5852847', 'n_tokens_mistral': 5088, 'n_tokens_neox': 4863, 'n_words': 1682}