• enceladus

    You can also initialise these double underscore global variables in pythonista_startup as suggested by @JonB.

    sys.modules['__main__'].__var = 2
    

    posted in Pythonista read more
  • enceladus

    Thanks @cvp . Global variables whose names start with double underscores seem to be alive across sessions.

    posted in Pythonista read more
  • enceladus

    I do not think that it is possible to keep the global variables live across sesssions. I think you need to save them in a file before exiting and load them from the file at the start of the next session. May be you can use json for this.

    posted in Pythonista read more
  • enceladus

    I think that it is the expected behaviour. Executing in console is different from executing the script. I think that when you execute a script, existing global variables are removed before start running the script but the global variables are not removed or cleared after the script is run. If you run a script from console global variables are not removed or cleared unless you set the configuration to clear the global variables before running. That is the reason why you see the global variables of previously run script. If you run a new script from outside old global variables are removed before running the new script.

    posted in Pythonista read more
  • enceladus

    Not tested well. Seems to work fine. Hopefully gives an idea on how to implement with nodes.
    https://gist.github.com/168e93ca05f213124f1aec4c329d9c73

    posted in Pythonista read more
  • enceladus

    If you delete the following two lines, the script works.

    if DOCUMENTS.startswith("/private"):
        DOCUMENTS = DOCUMENTS[len("/private"):]
    

    posted in Pythonista read more
  • enceladus

    See https://forum.omz-software.com/topic/3969/why-are-posts-containing-python-code-flagged-as-spam-by-akismet-com
    Put the text somewhere (may be in pythonista-issues if relevant) and post the link.

    posted in Pythonista read more
  • enceladus

    The following word game by Omz was in the examples directory of old version of Pythonista. I have modified it slightly to run on new version (python 3).

    # coding: utf-8
    from scene import *
    import ui
    import sound
    import marshal
    import string
    import time
    from itertools import product, chain
    from random import choice, random
    from copy import copy
    import os
    from math import sqrt
    import json
    A = Action
    
    game_duration = 90
    screen_w, screen_h = get_screen_size()
    min_screen = min(screen_w, screen_h)
    if max(get_screen_size()) >= 760:
        cols, rows = 10, 11
    else:
        cols, rows = 7, 7
    tile_size = min_screen / (max(cols, rows) + 1)
    font_size = int(tile_size * 0.6)
    tile_font = ('AvenirNext-Regular', font_size)
    score_font = ('AvenirNext-Regular', 50)
    time_font = ('AvenirNext-Regular', 32)
    preview_font = ('AvenirNext-Regular', 24)
    game_over_font = ('AvenirNext-Regular', 72)
    points_font = ('AvenirNextCondensed-Regular', 32)
    
    # Derived from http://en.m.wikipedia.org/wiki/Letter_frequency
    letter_freq = {'a': 8.2, 'b': 1.5, 'c': 2.8, 'd': 4.3, 'e': 12.7, 'f': 2.3, 'g': 2.0, 'h': 6.1, 'i': 7.0, 'j': 0.2, 'k': 7.7, 'l': 4.0, 'm': 2.4, 'n': 6.7, 'o': 7.5, 'p': 1.9, 'q': 0.1, 'r': 6.0, 's': 6.3, 't': 9.0, 'u': 2.8, 'v': 1.0, 'w': 2.4, 'x': 0.2, 'y': 2.0, 'z': 0.1}
    letter_bag = list(chain(*[[letter] * int(letter_freq[letter]*10) for letter in letter_freq]))
    
    def build_dictionary():
        # Generate the word list if it doesn't exist yet.
        # It's represented as a set for fast lookup, and saved to disk using the `marshal` module.
        if os.path.exists('words.data'):
            return
        #import urllib
        import requests
        words = []
        #f = urllib.urlopen('https://github.com/atebits/Words/blob/master/Words/en.txt?raw=true')
        f = str(requests.get('https://github.com/atebits/Words/blob/master/Words/en.txt?raw=true').text)
        for line in f.split():
            words.append(line.strip())
        with open('words.data', 'w') as out:
            #marshal.dump(words, out)
            json.dump(words, out)
    
    with ui.ImageContext(tile_size, tile_size) as ctx:
        ui.set_color('silver')
        ui.Path.rounded_rect(2, 2, tile_size-4, tile_size-4, 4).fill()
        ui.set_color('white')
        ui.Path.rounded_rect(2, 2, tile_size-4, tile_size-6, 4).fill()
        tile_texture = Texture(ctx.get_image())
    
    class Tile (SpriteNode):
        def __init__(self, x, y, letter, color='white', multiplier=1):
            SpriteNode.__init__(self, tile_texture)
            self.x = x
            self.y = y
            self.letter = letter
            self._selected = False
            pos_y = y * tile_size + (tile_size/2 if x % 2 == 0 else 0)
            self.position = x * tile_size, pos_y
            self.tile_color = color
            self.color = color
            self.label = LabelNode(letter.upper(), font=tile_font)
            self.label.color = 'black'
            self.multiplier = multiplier
            self.add_child(self.label)
        
        @property
        def selected(self):
            return self._selected
        
        @selected.setter
        def selected(self, value):
            self._selected = value
            self.color = '#fdffce' if value else self.tile_color
    
    class Game (Scene):
        def setup(self):
            self.current_size = None
            self.current_word = None
            build_dictionary()
            with open('words.data') as f:
                #self.words = marshal.load(f)
                self.words = set(json.load(f))
            self.root = Node(parent=self)
            self.background_color = '#0f2634'
            self.tiles = []
            self.selected = []
            self.touched_tile = None
            self.score_label = LabelNode('0', font=score_font, parent=self)
            self.score = 0
            self.game_over = False
            self.game_over_time = 0
            self.word_label = LabelNode(font=preview_font, parent=self)
            self.time_label = LabelNode('00:00', font=time_font, parent=self)
            self.time_label.anchor_point = (0, 0.5)
            self.start_time = time.time()
            self.overlay = SpriteNode(color='black', alpha=0, z_position=3, parent=self)
            time_up_label = LabelNode('Time Up!', font=game_over_font, parent=self.overlay)
            self.did_change_size()
            self.new_game()
        
        def create_tile(self, x, y):
            letter = choice(letter_bag)
            bonus = random() < 0.07
            t = Tile(x, y, letter, '#cef9ff' if bonus else 'white', 2 if bonus else 1)
            return t
            
        def did_change_size(self):
            x_margin = (self.size.w - cols * tile_size)/2
            y_margin = (self.size.h - rows * tile_size)/2 - tile_size/2
            self.root.position = x_margin + tile_size/2, y_margin + tile_size/2
            self.overlay.position = self.size/2
            self.overlay.size = self.size
            if self.size.w < self.size.h:
                self.score_label.position = self.size.w/2, self.size.h - 100
                self.word_label.position = self.size.w/2, self.size.h - 140
                self.time_label.position = 20, self.size.h - 100
                self.time_label.anchor_point = (0, 0.5)
            else:
                self.score_label.position = x_margin/2, self.size.h - 100
                self.word_label.position = x_margin/2, self.size.h - 140
                self.time_label.position = self.size - (20, 100)
                self.time_label.anchor_point = (1, 0.5)
            
        def update(self):
            time_passed = time.time() - self.start_time
            t = max(0, int(game_duration - time_passed))
            self.time_label.text = '{0}:{1:0>2}'.format(t//60, t%60)
            if t == 0 and not self.game_over:
                self.end_game()
        
        def new_game(self, animated=False):
            if self.game_over:
                self.play_sound('digital:ZapThreeToneUp')
            for tile in self.tiles:
                tile.remove_from_parent()
            self.tiles = []
            for x, y in product(range(cols), range(rows)):
                s = self.create_tile(x, y)
                if animated:
                    s.scale = 0
                    s.run_action(Action.scale_to(1, 0.5, TIMING_EASE_OUT_2))
                self.tiles.append(s)
                self.root.add_child(s)
            self.game_over = False
            self.start_time = time.time()
            self.score = 0
            self.score_label.text = '0'
            self.overlay.run_action(Action.fade_to(0))
            self.word_label.text = ''
            self.selected = []
            
        def end_game(self):
            self.play_sound('digital:ZapThreeToneDown')
            self.game_over = True
            self.game_over_time = time.time()
            self.overlay.run_action(Action.fade_to(0.7))
        
        def get_selected_word(self):
            return ''.join([t.letter for t in self.selected]).lower()
        
        def touch_to_tile(self, location):
            touch_x = location[0] - self.root.position[0]
            touch_y = location[1] - self.root.position[1]
            x = int(touch_x / tile_size)
            if x % 2 != 0:
                y = int((touch_y - tile_size/2) / tile_size)
            else:
                y = int(touch_y / tile_size)
            return x, y
        
        def tile_at(self, location):
            x = location[0] - self.root.position[0]
            y = location[1] - self.root.position[1]
            for tile in self.tiles:
                if abs(tile.position - (x, y)) < tile_size/2:
                    if tile.alpha < 1:
                        continue
                    return tile
            return None
        
        def is_neighbor(self, tile1, tile2):
            if (not tile1 or not tile2 or tile1 == tile2):
                return True
            x1, y1 = tile1.x, tile1.y
            x2, y2 = tile2.x, tile2.y
            if x1 == x2:
                return abs(y2-y1) <= 1
            elif x1 % 2 == 0:
                return abs(x2-x1) <= 1 and 0 <= (y2-y1) <= 1
            else:
                return abs(x2-x1) <= 1 and -1 <= (y2-y1) <= 0
        
        def select_tile(self, tile):
            if not tile or (self.selected and self.selected[-1] == tile):
                return
            if tile in self.selected:
                self.selected = self.selected[:self.selected.index(tile)+1]
            else:
                if self.selected:
                    last_selected = self.selected[-1]
                    if not self.is_neighbor(tile, last_selected):
                        self.selected = []
                    self.selected.append(tile)
                else:
                    self.selected = [tile]
            for tile in self.tiles:
                tile.selected =  (tile in self.selected)
            self.play_sound('8ve:8ve-tap-resonant')
            self.update_word_label()
        
        def update_word_label(self):
            word = self.get_selected_word()
            if word != self.current_word:
                self.word_label.color = '#ddffc2' if word in self.words else '#ffcece'
                self.word_label.text = word.upper()
                self.current_word = word
        
        def calc_score(self, word_tiles):
            n = len(word_tiles)
            multiplier = 1
            for tile in word_tiles:
                multiplier *= tile.multiplier
            return int((2 ** (n-2)) * 50 * multiplier)
        
        def submit_word(self):
            word = self.get_selected_word()
            if not word:
                return
            if word in self.words:
                added_score = self.calc_score(self.selected)
                self.score += added_score
                self.score_label.text = str(self.score)
                self.play_sound('digital:PowerUp7')
            else:
                added_score = 0
                self.play_sound('digital:PepSound4')
                for tile in self.selected:
                    tile.selected = False
                self.selected = []
                self.touched_tile = None
            for tile in self.selected:
                tile.run_action(A.group(A.fade_to(0, 0.25), A.scale_to(0.5, 0.25)))
            self.tiles[:] = [t for t in self.tiles if t not in self.selected]
            sorted_selection = sorted(self.selected, key=lambda t: t.y, reverse=True)
            new_tiles_by_col = [0] * cols
            offsets = [0] * len(self.tiles)
            for t in sorted_selection:
                x, y = t.x, t.y
                new_tiles_by_col[x] += 1
                for i, tile in enumerate(self.tiles):
                    if tile.x == x and tile.y > y:
                        tile.y -= 1
                        offsets[i] += 1
            for i, offset in enumerate(offsets):
                if offset > 0:
                    tile = self.tiles[i]
                    d = sqrt(offset * tile_size/750.0)
                    tile.run_action(A.move_by(0, -offset*tile_size, d, TIMING_EASE_IN_2))
            for i, n in enumerate(new_tiles_by_col):
                for j in range(n):
                    s = self.create_tile(i, rows-j-1)
                    to_pos = s.position
                    from_pos = to_pos[0], (rows + n-j) * tile_size
                    s.position = from_pos
                    self.tiles.append(s)
                    self.root.add_child(s)
                    s.alpha = 0
                    s.run_action(Action.fade_to(1, 0.25))
                    s.run_action(Action.move_to(to_pos[0], to_pos[1], sqrt((from_pos[1] - to_pos[1])/750.0), TIMING_EASE_IN_2))
            if added_score > 0:
                self.show_points(self.selected[-1].position, added_score)
            self.selected = []
            self.touched_tile = None
            self.update_word_label()
            
        def show_points(self, position, added_score):
            points_bg = ShapeNode(ui.Path.oval(0, 0, 100, 100), '#49b8ff', alpha=0)
            points_bg.position = position
            points_label = LabelNode('+%i' % (added_score,), font=points_font, parent=points_bg)
            points_bg.run_action(A.sequence(
                A.fade_to(1, 0.25),
                A.wait(0.5),
                A.fade_to(0, 0.5, TIMING_EASE_IN),
                A.remove()
            ))
            points_bg.run_action(Action.move_by(0, 100, 1.5))
            self.root.add_child(points_bg)
        
        def touch_began(self, touch):
            if self.game_over:
                return
            prev_touched_tile = self.touched_tile
            self.touched_tile = self.tile_at(touch.location)
            if prev_touched_tile == self.touched_tile:
                self.submit_word()
            elif self.touched_tile:
                self.select_tile(self.touched_tile)
        
        def touch_moved(self, touch):
            if not self.game_over:
                self.select_tile(self.tile_at(touch.location))
        
        def touch_ended(self, touch):
            if self.game_over:
                if time.time() - self.game_over_time > 2.0:
                    self.new_game(animated=True)
                return
            tile = self.tile_at(touch.location)
            if tile == self.touched_tile:
                self.select_tile(tile)
            else:
                self.submit_word()
        
        def play_sound(self, name):
            sound.play_effect(name)
    
    if __name__ == '__main__':
        run(Game(), multi_touch=False)
        
    
    

    posted in Pythonista read more

Internal error.

Oops! Looks like something went wrong!