1# Copyright 2004-2021 Tom Rothamel <pytom@bishoujo.us>
2#
3# Permission is hereby granted, free of charge, to any person
4# obtaining a copy of this software and associated documentation files
5# (the "Software"), to deal in the Software without restriction,
6# including without limitation the rights to use, copy, modify, merge,
7# publish, distribute, sublicense, and/or sell copies of the Software,
8# and to permit persons to whom the Software is furnished to do so,
9# subject to the following conditions:
10#
11# The above copyright notice and this permission notice shall be
12# included in all copies or substantial portions of the Software.
13#
14# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
15# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
16# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
17# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
18# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
19# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
20# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
21
22# This file contains functions that are exported to the script namespace as
23# the renpy namespace. (So renpy.say, renpy.pause, and so on.)
24
25from __future__ import division, absolute_import, with_statement, print_function, unicode_literals
26from renpy.compat import *
27
28import re
29import gc
30
31import renpy.display
32import renpy.audio
33
34from renpy.pyanalysis import const, pure, not_const
35
36
37def renpy_pure(fn):
38    """
39    Marks renpy.`fn` as a pure function.
40    """
41
42    name = fn
43
44    if not isinstance(name, basestring):
45        name = fn.__name__
46
47    pure("renpy." + name)
48
49    return fn
50
51
52import pygame_sdl2
53
54from renpy.text.extras import ParameterizedText, filter_text_tags
55from renpy.text.font import register_sfont, register_mudgefont, register_bmfont
56from renpy.text.text import language_tailor, BASELINE
57from renpy.display.behavior import Keymap
58from renpy.display.behavior import run, run as run_action, run_unhovered, run_periodic
59from renpy.display.behavior import map_event, queue_event, clear_keymap_cache
60from renpy.display.behavior import is_selected, is_sensitive
61
62from renpy.display.minigame import Minigame
63from renpy.display.screen import define_screen, show_screen, hide_screen, use_screen, current_screen
64from renpy.display.screen import has_screen, get_screen, get_displayable, get_widget, ScreenProfile as profile_screen
65from renpy.display.screen import get_displayable_properties, get_widget_properties
66
67from renpy.display.focus import focus_coordinates
68from renpy.display.predict import screen as predict_screen
69
70from renpy.display.image import image_exists, image_exists as has_image, list_images
71from renpy.display.image import get_available_image_tags, get_available_image_attributes, check_image_attributes, get_ordered_image_attributes
72from renpy.display.image import get_registered_image
73
74from renpy.display.im import load_surface, load_image
75
76from renpy.curry import curry, partial
77from renpy.display.video import movie_start_fullscreen, movie_start_displayable, movie_stop
78
79from renpy.loadsave import load, save, list_saved_games, can_load, rename_save, copy_save, unlink_save, scan_saved_game
80from renpy.loadsave import list_slots, newest_slot, slot_mtime, slot_json, slot_screenshot, force_autosave
81
82from renpy.python import py_eval as eval
83from renpy.python import rng as random
84from renpy.atl import atl_warper
85from renpy.easy import predict, displayable, split_properties
86from renpy.parser import unelide_filename, get_parse_errors
87
88from renpy.translation import change_language, known_languages, translate_string
89from renpy.translation.generation import generic_filter as transform_text
90
91from renpy.persistent import register_persistent
92
93from renpy.character import show_display_say, predict_show_display_say, display_say
94
95import renpy.audio.sound as sound
96import renpy.audio.music as music
97
98from renpy.statements import register as register_statement
99from renpy.text.extras import check_text_tags
100
101from renpy.memory import profile_memory, diff_memory, profile_rollback
102
103from renpy.text.textsupport import TAG as TEXT_TAG, TEXT as TEXT_TEXT, PARAGRAPH as TEXT_PARAGRAPH, DISPLAYABLE as TEXT_DISPLAYABLE
104
105from renpy.execution import not_infinite_loop
106
107from renpy.sl2.slparser import CustomParser as register_sl_statement, register_sl_displayable
108
109from renpy.ast import eval_who
110
111from renpy.loader import add_python_directory
112
113from renpy.lint import try_compile, try_eval
114
115from renpy.gl2.gl2shadercache import register_shader
116from renpy.gl2.live2d import has_live2d
117
118renpy_pure("ParameterizedText")
119renpy_pure("Keymap")
120renpy_pure("has_screen")
121renpy_pure("image_exists")
122renpy_pure("curry")
123renpy_pure("partial")
124renpy_pure("unelide_filename")
125renpy_pure("known_languages")
126renpy_pure("check_text_tags")
127renpy_pure("filter_text_tags")
128
129import time
130import sys
131import threading
132import fnmatch
133
134
135def public_api():
136    """
137    :undocumented:
138
139    This does nothing, except to make warnings about unused imports go away.
140    """
141    ParameterizedText, filter_text_tags
142    register_sfont, register_mudgefont, register_bmfont
143    Keymap
144    run, run_action, run_unhovered, run_periodic, map_event
145    Minigame
146    curry, partial
147    play
148    movie_start_fullscreen, movie_start_displayable, movie_stop
149    load, save, list_saved_games, can_load, rename_save, copy_save, unlink_save, scan_saved_game
150    list_slots, newest_slot, slot_mtime, slot_json, slot_screenshot, force_autosave
151    eval
152    random
153    atl_warper
154    show_display_say, predict_show_display_say, display_say
155    sound
156    music
157    time
158    define_screen, show_screen, hide_screen, use_screen, has_screen
159    current_screen, get_screen, get_widget, profile_screen, get_widget_properties
160    focus_coordinates
161    predict, predict_screen
162    displayable, split_properties
163    unelide_filename, get_parse_errors
164    change_language, known_languages, translate_string
165    transform_text
166    language_tailor
167    register_persistent
168    register_statement
169    check_text_tags
170    map_event, queue_event, clear_keymap_cache
171    const, pure, not_const
172    image_exists, has_image, list_images
173    get_available_image_tags, get_available_image_attributes, check_image_attributes, get_ordered_image_attributes
174    get_registered_image
175    load_image, load_surface
176    profile_memory, diff_memory, profile_rollback
177    TEXT_TAG
178    TEXT_TEXT
179    TEXT_PARAGRAPH
180    TEXT_DISPLAYABLE
181    not_infinite_loop
182    register_sl_statement, register_sl_displayable
183    eval_who
184    is_selected, is_sensitive
185    add_python_directory
186    try_compile, try_eval
187    register_shader, has_live2d
188
189
190del public_api
191
192# The number of bits in the architecture.
193if sys.maxsize > (2 << 32):
194    bits = 64
195else:
196    bits = 32
197
198
199def roll_forward_info():
200    """
201    :doc: rollback
202
203    When in rollback, returns the data that was supplied to :func:`renpy.checkpoint`
204    the last time this statement executed. Outside of rollback, returns None.
205    """
206
207    if not renpy.game.context().rollback:
208        return None
209
210    return renpy.game.log.forward_info()
211
212
213def roll_forward_core(value=None):
214    """
215    :undocumented:
216
217    To cause a roll_forward to occur, return the value of this function
218    from an event handler.
219    """
220
221    if value is None:
222        value = roll_forward_info()
223    if value is None:
224        return
225
226    renpy.game.interface.suppress_transition = True
227    renpy.game.after_rollback = True
228    renpy.game.log.rolled_forward = True
229
230    return value
231
232
233def in_rollback():
234    """
235    :doc: rollback
236
237    Returns true if the game has been rolled back.
238    """
239
240    return renpy.game.log.in_rollback() or renpy.game.after_rollback
241
242
243def can_rollback():
244    """
245    :doc: rollback
246
247    Returns true if we can rollback.
248    """
249
250    if not renpy.config.rollback_enabled:
251        return False
252
253    return renpy.game.log.can_rollback()
254
255
256def in_fixed_rollback():
257    """
258    :doc: blockrollback
259
260    Returns true if rollback is currently occurring and the current
261    context is before an executed renpy.fix_rollback() statement.
262    """
263
264    return renpy.game.log.in_fixed_rollback()
265
266
267def checkpoint(data=None, keep_rollback=None, hard=True):
268    """
269    :doc: rollback
270    :args: (data=None)
271
272    Makes the current statement a checkpoint that the user can rollback to. Once
273    this function has been called, there should be no more interaction with the
274    user in the current statement.
275
276    This will also clear the current screenshot used by saved games.
277
278    `data`
279        This data is returned by :func:`renpy.roll_forward_info` when the
280        game is being rolled back.
281
282    `hard`
283        If true, this is a hard checkpoint that rollback will stop at. If false,
284        this is a soft checkpoint that will not stop rollback.
285    """
286
287    if keep_rollback is None:
288        keep_rollback = renpy.config.keep_rollback_data
289
290    renpy.game.log.checkpoint(data, keep_rollback=keep_rollback, hard=renpy.store._rollback and hard)
291
292    if renpy.store._rollback and renpy.config.auto_clear_screenshot:
293        renpy.game.interface.clear_screenshot = True
294
295
296def block_rollback(purge=False):
297    """
298    :doc: blockrollback
299    :args: ()
300
301    Prevents the game from rolling back to before the current
302    statement.
303    """
304
305    renpy.game.log.block(purge=purge)
306
307
308def suspend_rollback(flag):
309    """
310    :doc: rollback
311    :args: (flag)
312
313    Rollback will skip sections of the game where rollback has been
314    suspended.
315
316    `flag`:
317        When `flag` is true, rollback is suspended. When false,
318        rollback is resumed.
319    """
320
321    renpy.game.log.suspend_checkpointing(flag)
322
323
324def fix_rollback():
325    """
326    :doc: blockrollback
327
328    Prevents the user from changing decisions made before the current
329    statement.
330    """
331    renpy.game.log.fix_rollback()
332
333
334def retain_after_load():
335    """
336    :doc: retain_after_load
337
338    Causes data modified between the current statement and the statement
339    containing the next checkpoint to be retained when a load occurs.
340    """
341
342    renpy.game.log.retain_after_load()
343
344
345scene_lists = renpy.display.core.scene_lists
346
347
348def count_displayables_in_layer(layer):
349    """
350    Returns how many displayables are in the supplied layer.
351    """
352
353    sls = scene_lists()
354
355    return len(sls.layers[layer])
356
357
358def image(name, d):
359    """
360    :doc: se_images
361
362    Defines an image. This function is the Python equivalent of the
363    image statement.
364
365    `name`
366        The name of the image to display, a string.
367
368    `d`
369        The displayable to associate with that image name.
370
371    This function may only be run from inside an init block. It is an
372    error to run this function once the game has started.
373    """
374
375    if d is None:
376        raise Exception("Images may not be declared to be None.")
377
378    if not renpy.game.context().init_phase:
379        raise Exception("Images may only be declared inside init blocks.")
380
381    if not isinstance(name, tuple):
382        name = tuple(name.split())
383
384    d = renpy.easy.displayable(d)
385    renpy.display.image.register_image(name, d)
386
387
388def copy_images(old, new):
389    """
390    :doc: image_func
391
392    Copies images beginning with one prefix to images beginning with
393    another. For example::
394
395        renpy.copy_images("eileen", "eileen2")
396
397    will create an image beginning with "eileen2" for every image beginning
398    with "eileen". If "eileen happy" exists, "eileen2 happy" will be
399    created.
400
401    `old`
402        A space-separated string giving the components of the old image
403        name.
404
405    `new`
406        A space-separated string giving the components of the new image
407        name.
408
409    """
410
411    if not isinstance(old, tuple):
412        old = tuple(old.split())
413
414    if not isinstance(new, tuple):
415        new = tuple(new.split())
416
417    lenold = len(old)
418
419    for k, v in renpy.display.image.images.items():
420        if len(k) < lenold:
421            continue
422
423        if k[:lenold] == old:
424            renpy.display.image.register_image(new + k[lenold:], v)
425
426
427def default_layer(layer, tag, expression=False):
428    """
429    :undocumented:
430
431    If layer is not None, returns it. Otherwise, interprets `tag` as a name
432    or tag, then looks up what the default layer for that tag is, and returns
433    the result.
434    """
435
436    if layer is not None:
437        return layer
438
439    if expression:
440        return 'master'
441
442    if isinstance(tag, tuple):
443        tag = tag[0]
444    elif " " in tag:
445        tag = tag.split()[0]
446
447    return renpy.config.tag_layer.get(tag, renpy.config.default_tag_layer)
448
449
450def can_show(name, layer=None, tag=None):
451    """
452    :doc: image_func
453
454    Determines if `name` can be used to show an image. This interprets `name`
455    as a tag and attributes. This is combined with the attributes of the
456    currently-showing image with `tag` on `layer` to try to determine a unique image
457    to show. If a unique image can be show, returns the name of that image as
458    a tuple. Otherwise, returns None.
459
460    `tag`
461        The image tag to get attributes from. If not given, defaults to the first
462        component of `name`.
463
464    `layer`
465        The layer to check. If None, uses the default layer for `tag`.
466    """
467
468    if not isinstance(name, tuple):
469        name = tuple(name.split())
470
471    if tag is None:
472        tag = name[0]
473
474    layer = default_layer(layer, None)
475
476    try:
477        return renpy.game.context().images.apply_attributes(layer, tag, name)
478    except:
479        return None
480
481
482def showing(name, layer=None):
483    """
484    :doc: image_func
485
486    Returns true if an image with the same tag as `name` is showing on
487    `layer`.
488
489    `image`
490        May be a string giving the image name or a tuple giving each
491        component of the image name. It may also be a string giving
492        only the image tag.
493
494    `layer`
495        The layer to check. If None, uses the default layer for `tag`.
496    """
497
498    if not isinstance(name, tuple):
499        name = tuple(name.split())
500
501    layer = default_layer(layer, name)
502
503    return renpy.game.context().images.showing(layer, name)
504
505
506def get_showing_tags(layer='master', sort=False):
507    """
508    :doc: image_func
509
510    Returns the set of image tags that are currently being shown on `layer`. If
511    sort is true, returns a list of the tags from back to front.
512    """
513
514    if sort:
515        return scene_lists().get_sorted_tags(layer)
516
517    return renpy.game.context().images.get_showing_tags(layer)
518
519
520def get_hidden_tags(layer='master'):
521    """
522    :doc: image_func
523
524    Returns the set of image tags on `layer` that are currently hidden, but
525    still have attribute information associated with them.
526    """
527
528    return renpy.game.context().images.get_hidden_tags(layer)
529
530
531def get_attributes(tag, layer=None, if_hidden=None):
532    """
533    :doc: image_func
534
535    Return a tuple giving the image attributes for the image `tag`. If
536    the image tag has not had any attributes associated since the last
537    time it was hidden, returns `if_hidden`.
538
539    `layer`
540        The layer to check. If None, uses the default layer for `tag`.
541    """
542
543    layer = default_layer(layer, tag)
544    return renpy.game.context().images.get_attributes(layer, tag, if_hidden)
545
546
547def _find_image(layer, key, name, what):
548    """
549    :undocumented:
550
551    Finds an image to show.
552    """
553
554    if renpy.config.image_attributes:
555
556        new_what = renpy.game.context().images.apply_attributes(layer, key, name)
557        if new_what is not None:
558            what = new_what
559            name = (key,) + new_what[1:]
560            return name, what
561
562    f = renpy.config.adjust_attributes.get(what[0], None) or renpy.config.adjust_attributes.get(None, None)
563    if f is not None:
564        new_what = f(what)
565        name = (key,) + new_what[1:]
566        return name, new_what
567
568    return name, what
569
570
571def predict_show(name, layer=None, what=None, tag=None, at_list=[ ]):
572    """
573    :undocumented:
574
575    Predicts a scene or show statement.
576
577    `name`
578        The name of the image to show, a string.
579
580    `layer`
581        The layer the image is being shown on.
582
583    `what`
584        What is being show - if given, overrides `name`.
585
586    `tag`
587        The tag of the thing being shown.
588
589    `at_list`
590        A list of transforms to apply to the displayable.
591    """
592
593    key = tag or name[0]
594
595    layer = default_layer(layer, key)
596
597    if what is None:
598        what = name
599    elif isinstance(what, basestring):
600        what = tuple(what.split())
601
602    if isinstance(what, renpy.display.core.Displayable):
603        base = img = what
604
605    else:
606
607        name, what = _find_image(layer, key, name, what)
608        base = img = renpy.display.image.ImageReference(what, style='image_placement')
609
610        if not base.find_target():
611            return
612
613    for i in at_list:
614        if isinstance(i, renpy.display.motion.Transform):
615            img = i(child=img)
616        else:
617            img = i(img)
618
619        img._unique()
620
621    renpy.game.context().images.predict_show(layer, name, True)
622    renpy.display.predict.displayable(img)
623
624
625def set_tag_attributes(name, layer=None):
626    """
627    :doc: side
628
629    This sets the attributes associated with an image tag when that image
630    tag is not showing. The main use of this would be to directly set the
631    attributes used by a side image.
632
633    For example::
634
635        $ renpy.set_tag_attributes("lucy mad")
636        $ renpy.say(l, "I'm rather cross.")
637
638    and::
639
640        l mad "I'm rather cross."
641
642    are equivalent.
643    """
644
645    if not isinstance(name, tuple):
646        name = tuple(name.split())
647
648    tag = name[0]
649    name = renpy.game.context().images.apply_attributes(layer, tag, name)
650
651    renpy.game.context().images.predict_show(layer, name, False)
652
653
654def show(name, at_list=[ ], layer=None, what=None, zorder=None, tag=None, behind=[ ], atl=None, transient=False, munge_name=True):
655    """
656    :doc: se_images
657    :args: (name, at_list=[], layer='master', what=None, zorder=0, tag=None, behind=[])
658
659    Shows an image on a layer. This is the programmatic equivalent of the show
660    statement.
661
662    `name`
663        The name of the image to show, a string.
664
665    `at_list`
666        A list of transforms that are applied to the image.
667        The equivalent of the ``at`` property.
668
669    `layer`
670        A string, giving the name of the layer on which the image will be shown.
671        The equivalent of the ``onlayer`` property. If None, uses the default
672        layer associated with the tag.
673
674    `what`
675        If not None, this is a displayable that will be shown in lieu of
676        looking on the image. (This is the equivalent of the show expression
677        statement.) When a `what` parameter is given, `name` can be used to
678        associate a tag with the image.
679
680    `zorder`
681        An integer, the equivalent of the ``zorder`` property. If None, the
682        zorder is preserved if it exists, and is otherwise set to 0.
683
684    `tag`
685        A string, used to specify the image tag of the shown image. The
686        equivalent of the ``as`` property.
687
688    `behind`
689        A list of strings, giving image tags that this image is shown behind.
690        The equivalent of the ``behind`` property.
691    """
692
693    default_transform = renpy.config.default_transform
694
695    if renpy.game.context().init_phase:
696        raise Exception("Show may not run while in init phase.")
697
698    if not isinstance(name, tuple):
699        name = tuple(name.split())
700
701    if zorder is None and not renpy.config.preserve_zorder:
702        zorder = 0
703
704    sls = scene_lists()
705    key = tag or name[0]
706
707    layer = default_layer(layer, key)
708
709    if renpy.config.sticky_positions:
710        if not at_list and key in sls.at_list[layer]:
711            at_list = sls.at_list[layer][key]
712
713    if not at_list:
714        tt = renpy.config.tag_transform.get(key, None)
715        if tt is not None:
716            if not isinstance(tt, list):
717                at_list = [ tt ]
718            else:
719                at_list = list(tt)
720
721    if what is None:
722        what = name
723    elif isinstance(what, basestring):
724        what = tuple(what.split())
725
726    if isinstance(what, renpy.display.core.Displayable):
727
728        if renpy.config.wrap_shown_transforms and isinstance(what, renpy.display.motion.Transform):
729            base = img = renpy.display.image.ImageReference(what, style='image_placement')
730
731            # Semi-principled, but mimics pre-6.99.6 behavior - if `what` is
732            # already a transform, do not apply the default transform to it.
733            default_transform = None
734
735        else:
736            base = img = what
737
738    else:
739        name, what = _find_image(layer, key, name, what)
740        base = img = renpy.display.image.ImageReference(what, style='image_placement')
741
742        if not base.find_target() and renpy.config.missing_show:
743            result = renpy.config.missing_show(name, what, layer)
744
745            if isinstance(result, renpy.display.core.Displayable):
746                base = img = result
747            elif result:
748                return
749
750    for i in at_list:
751        if isinstance(i, renpy.display.motion.Transform):
752            img = i(child=img)
753        else:
754            img = i(img)
755
756        # Mark the newly created images unique.
757        img._unique()
758
759    # Update the list of images we have ever seen.
760    renpy.game.persistent._seen_images[name] = True # @UndefinedVariable
761
762    if tag and munge_name:
763        name = (tag,) + name[1:]
764
765    if renpy.config.missing_hide:
766        renpy.config.missing_hide(name, layer)
767
768    sls.add(layer, img, key, zorder, behind, at_list=at_list, name=name, atl=atl, default_transform=default_transform, transient=transient)
769
770
771def hide(name, layer=None):
772    """
773    :doc: se_images
774
775    Hides an image from a layer. The Python equivalent of the hide statement.
776
777    `name`
778         The name of the image to hide. Only the image tag is used, and
779         any image with the tag is hidden (the precise name does not matter).
780
781    `layer`
782         The layer on which this function operates. If None, uses the default
783         layer associated with the tag.
784    """
785
786    if renpy.game.context().init_phase:
787        raise Exception("Hide may not run while in init phase.")
788
789    if not isinstance(name, tuple):
790        name = tuple(name.split())
791
792    sls = scene_lists()
793    key = name[0]
794
795    layer = default_layer(layer, key)
796
797    sls.remove(layer, key)
798
799    if renpy.config.missing_hide:
800        renpy.config.missing_hide(name, layer)
801
802
803def scene(layer='master'):
804    """
805    :doc: se_images
806
807    Removes all displayables from `layer`. This is equivalent to the scene
808    statement, when the scene statement is not given an image to show.
809
810    A full scene statement is equivalent to a call to renpy.scene followed by a
811    call to :func:`renpy.show`. For example::
812
813        scene bg beach
814
815    is equivalent to::
816
817        $ renpy.scene()
818        $ renpy.show("bg beach")
819    """
820
821    if layer is None:
822        layer = 'master'
823
824    if renpy.game.context().init_phase:
825        raise Exception("Scene may not run while in init phase.")
826
827    sls = scene_lists()
828    sls.clear(layer)
829
830    if renpy.config.missing_scene:
831        renpy.config.missing_scene(layer)
832
833    # End a transition that's affecting layer.
834    renpy.display.interface.ongoing_transition.pop(layer, None)
835
836
837def input(prompt, default='', allow=None, exclude='{}', length=None, with_none=None, pixel_width=None, screen="input", mask=None, **kwargs): # @ReservedAssignment
838    """
839    :doc: input
840
841    Calling this function pops up a window asking the player to enter some
842    text. It returns the entered text.
843
844    `prompt`
845        A string giving a prompt to display to the player.
846
847    `default`
848        A string giving the initial text that will be edited by the player.
849
850    `allow`
851        If not None, a string giving a list of characters that will
852        be allowed in the text.
853
854    `exclude`
855        If not None, if a character is present in this string, it is not
856        allowed in the text.
857
858    `length`
859        If not None, this must be an integer giving the maximum length
860        of the input string.
861
862    `pixel_width`
863        If not None, the input is limited to being this many pixels wide,
864        in the font used by the input to display text.
865
866    `screen`
867        The name of the screen that takes input. If not given, the ``input``
868        screen is used.
869
870    `mask`
871        If not None, a single-character string that replaces the input text that
872        is shown to the player, such as to conceal a password.
873
874    If :var:`config.disable_input` is True, this function only returns
875    `default`.
876
877    Keywords prefixed with ``show_`` have the prefix stripped and
878    are passed to the screen.
879    """
880
881    if renpy.config.disable_input:
882        return default
883
884    renpy.exports.mode('input')
885
886    roll_forward = renpy.exports.roll_forward_info()
887    if not isinstance(roll_forward, basestring):
888        roll_forward = None
889
890    # use previous data in rollback
891    if roll_forward is not None:
892        default = roll_forward
893
894    fixed = in_fixed_rollback()
895
896    # put arguments with show_ prefix aside
897    show_properties, kwargs = renpy.easy.split_properties(kwargs, "show_", "")
898
899    if kwargs:
900        raise TypeError("renpy.input() got unexpected keyword argument(s): {}".format(", ".join(kwargs.keys())))
901
902    if has_screen(screen):
903        widget_properties = { }
904        widget_properties["input"] = dict(default=default, length=length, allow=allow, exclude=exclude, editable=not fixed, pixel_width=pixel_width, mask=mask)
905
906        show_screen(screen, _transient=True, _widget_properties=widget_properties, prompt=prompt, **show_properties)
907
908    else:
909
910        if screen != "input":
911            raise Exception("The '{}' screen does not exist.".format(screen))
912
913        renpy.ui.window(style='input_window')
914        renpy.ui.vbox()
915
916        renpy.ui.text(prompt, style='input_prompt')
917
918        inputwidget = renpy.ui.input(default, length=length, style='input_text', allow=allow, exclude=exclude)
919
920        # disable input in fixed rollback
921        if fixed:
922            inputwidget.disable()
923
924        renpy.ui.close()
925
926    renpy.exports.shown_window()
927
928    if renpy.config.autosave_on_input and not renpy.game.after_rollback:
929        renpy.loadsave.force_autosave(True)
930
931    # use normal "say" click behavior if input can't be changed
932    if fixed:
933        renpy.ui.saybehavior()
934
935    rv = renpy.ui.interact(mouse='prompt', type="input", roll_forward=roll_forward)
936    renpy.exports.checkpoint(rv)
937
938    if with_none is None:
939        with_none = renpy.config.implicit_with_none
940
941    if with_none:
942        renpy.game.interface.do_with(None, None)
943
944    return rv
945
946
947# The arguments and keyword arguments for the current menu call.
948menu_args = None
949menu_kwargs = None
950
951
952def get_menu_args():
953    """
954    :other:
955
956    Returns a tuple giving the arguments (as a tuple) and the keyword arguments
957    (as a dict) passed to the current menu statement.
958    """
959
960    if menu_args is None:
961        return tuple(), dict()
962
963    return menu_args, menu_kwargs
964
965
966def menu(items, set_expr, args=None, kwargs=None, item_arguments=None):
967    """
968    :undocumented:
969
970    Displays a menu, and returns to the user the value of the selected
971    choice. Also handles conditions and the menuset.
972    """
973
974    global menu_args
975    global menu_kwargs
976
977    args = args or tuple()
978    kwargs = kwargs or dict()
979
980    nvl = kwargs.pop("nvl", False)
981
982    if renpy.config.menu_arguments_callback is not None:
983        args, kwargs = renpy.config.menu_arguments_callback(*args, **kwargs)
984
985    if renpy.config.old_substitutions:
986
987        def substitute(s):
988            return s % tag_quoting_dict
989
990    else:
991
992        def substitute(s):
993            return s
994
995    if item_arguments is None:
996        item_arguments = [ (tuple(), dict()) ] * len(items)
997
998    # Filter the list of items on the set_expr:
999    if set_expr:
1000        set = renpy.python.py_eval(set_expr) # @ReservedAssignment
1001
1002        new_items = [ ]
1003        new_item_arguments = [ ]
1004
1005        for i, ia in zip(items, item_arguments):
1006            if i[0] not in set:
1007                new_items.append(i)
1008                new_item_arguments.append(ia)
1009
1010        items = new_items
1011        item_arguments = new_item_arguments
1012    else:
1013        set = None # @ReservedAssignment
1014
1015    # Filter the list of items to only include ones for which the
1016    # condition is true.
1017
1018    if renpy.config.menu_actions:
1019
1020        location = renpy.game.context().current
1021
1022        new_items = [ ]
1023
1024        for (label, condition, value), (item_args, item_kwargs) in zip(items, item_arguments):
1025            label = substitute(label)
1026            condition = renpy.python.py_eval(condition)
1027
1028            if (not renpy.config.menu_include_disabled) and (not condition):
1029                continue
1030
1031            if value is not None:
1032                new_items.append((label, renpy.ui.ChoiceReturn(label, value, location, sensitive=condition, args=item_args, kwargs=item_kwargs)))
1033            else:
1034                new_items.append((label, None))
1035
1036    else:
1037
1038        new_items = [ (substitute(label), value)
1039                      for label, condition, value in items
1040                      if renpy.python.py_eval(condition) ]
1041
1042    # Check to see if there's at least one choice in set of items:
1043    choices = [ value for label, value in new_items if value is not None ]
1044
1045    # If not, bail out.
1046    if not choices:
1047        return None
1048
1049    # Show the menu.
1050    try:
1051        old_menu_args = menu_args
1052        old_menu_kwargs = menu_kwargs
1053
1054        menu_args = args
1055        menu_kwargs = kwargs
1056
1057        if nvl:
1058            rv = renpy.store.nvl_menu(new_items) # @UndefinedVariable
1059        else:
1060            rv = renpy.store.menu(new_items)
1061
1062    finally:
1063        menu_args = old_menu_args
1064        menu_kwargs = old_menu_kwargs
1065
1066    # If we have a set, fill it in with the label of the chosen item.
1067    if set is not None and rv is not None:
1068        for label, condition, value in items:
1069            if value == rv:
1070                try:
1071                    set.append(label)
1072                except AttributeError:
1073                    set.add(label)
1074
1075    return rv
1076
1077
1078def choice_for_skipping():
1079    """
1080    :doc: other
1081
1082    Tells Ren'Py that a choice is coming up soon. This currently has
1083    two effects:
1084
1085    * If Ren'Py is skipping, and the Skip After Choices preferences is set
1086      to stop skipping, skipping is terminated.
1087
1088    * An auto-save is triggered.
1089    """
1090
1091    if renpy.config.skipping and not renpy.game.preferences.skip_after_choices:
1092        renpy.config.skipping = None
1093
1094    if renpy.config.autosave_on_choice and not renpy.game.after_rollback:
1095        renpy.loadsave.force_autosave(True)
1096
1097
1098def predict_menu():
1099    """
1100    :undocumented:
1101
1102    Predicts widgets that are used by the menu.
1103    """
1104
1105    # This only makes sense for non-NVL menus. But when we have
1106    # NVL menus, they're likely to have already been predicted.
1107    #
1108    # An item lets us load imagebuttons as necessary.
1109
1110    if not renpy.config.choice_screen_chosen:
1111        return
1112
1113    items = [ ("Menu Prediction", True, False) ]
1114
1115    predict_screen(
1116        "choice",
1117        items=items,
1118        )
1119
1120
1121class MenuEntry(tuple):
1122    """
1123    The object passed into the choice screen.
1124    """
1125
1126
1127def display_menu(items,
1128                 window_style='menu_window',
1129                 interact=True,
1130                 with_none=None,
1131                 caption_style='menu_caption',
1132                 choice_style='menu_choice',
1133                 choice_chosen_style='menu_choice_chosen',
1134                 choice_button_style='menu_choice_button',
1135                 choice_chosen_button_style='menu_choice_chosen_button',
1136                 scope={ },
1137                 widget_properties=None,
1138                 screen="choice",
1139                 type="menu", # @ReservedAssignment
1140                 predict_only=False,
1141                 **kwargs):
1142    """
1143    :doc: se_menu
1144    :name: renpy.display_menu
1145    :args: (items, interact=True, screen="choice")
1146
1147    This displays a menu to the user. `items` should be a list of 2-item tuples.
1148    In each tuple, the first item is a textual label, and the second item is
1149    the value to be returned if that item is selected. If the value is None,
1150    the first item is used as a menu caption.
1151
1152    This function takes many arguments, of which only a few are documented.
1153    Except for `items`, all arguments should be given as keyword arguments.
1154
1155    `interact`
1156        If false, the menu is displayed, but no interaction is performed.
1157
1158    `screen`
1159        The name of the screen used to display the menu.
1160
1161    Note that most Ren'Py games do not use menu captions, but use narration
1162    instead. To display a menu using narration, write::
1163
1164        $ narrator("Which direction would you like to go?", interact=False)
1165        $ result = renpy.display_menu([ ("East", "east"), ("West", "west") ])
1166
1167    """
1168
1169    menu_args, menu_kwargs = get_menu_args()
1170    screen = menu_kwargs.pop("screen", screen)
1171    with_none = menu_kwargs.pop("_with_none", with_none)
1172    mode = menu_kwargs.pop("_mode", type)
1173
1174    if interact:
1175        renpy.exports.mode(mode)
1176        choice_for_skipping()
1177
1178    choices = [ ]
1179
1180    for _, val in items:
1181        if isinstance(val, renpy.ui.ChoiceReturn):
1182            val = val.value
1183
1184        if val is None:
1185            continue
1186
1187        choices.append(val)
1188
1189    # Roll forward.
1190    roll_forward = renpy.exports.roll_forward_info()
1191
1192    if roll_forward not in choices:
1193        roll_forward = None
1194
1195    # Auto choosing.
1196    if renpy.config.auto_choice_delay:
1197
1198        renpy.ui.pausebehavior(renpy.config.auto_choice_delay,
1199                               random.choice(choices))
1200
1201    # The location
1202    location = renpy.game.context().current
1203
1204    # change behavior for fixed rollback
1205    if in_fixed_rollback() and renpy.config.fix_rollback_without_choice:
1206        renpy.ui.saybehavior()
1207
1208    scope = dict(scope)
1209
1210    scope.update(menu_kwargs)
1211
1212    # Show the menu.
1213    if has_screen(screen):
1214
1215        item_actions = [ ]
1216
1217        if widget_properties is None:
1218            props = { }
1219        else:
1220            props = widget_properties
1221
1222        for (label, value) in items:
1223
1224            if not label:
1225                value = None
1226
1227            if isinstance(value, renpy.ui.ChoiceReturn):
1228                action = value
1229                chosen = action.get_chosen()
1230                item_args = action.args
1231                item_kwargs = action.kwargs
1232
1233            elif value is not None:
1234                action = renpy.ui.ChoiceReturn(label, value, location)
1235                chosen = action.get_chosen()
1236                item_args = ()
1237                item_kwargs = { }
1238
1239            else:
1240                action = None
1241                chosen = False
1242                item_args = ()
1243                item_kwargs = { }
1244
1245            if renpy.config.choice_screen_chosen:
1246                me = MenuEntry((label, action, chosen))
1247            else:
1248                me = MenuEntry((label, action))
1249
1250            me.caption = label
1251            me.action = action
1252            me.chosen = chosen
1253            me.args = item_args
1254            me.kwargs = item_kwargs
1255
1256            item_actions.append(me)
1257
1258        show_screen(
1259            screen,
1260            items=item_actions,
1261            _widget_properties=props,
1262            _transient=True,
1263            _layer=renpy.config.choice_layer,
1264            *menu_args,
1265            **scope)
1266
1267    else:
1268        renpy.exports.shown_window()
1269
1270        renpy.ui.window(style=window_style, focus="menu")
1271        renpy.ui.menu(items,
1272                      location=renpy.game.context().current,
1273                      focus="choices",
1274                      default=True,
1275                      caption_style=caption_style,
1276                      choice_style=choice_style,
1277                      choice_chosen_style=choice_chosen_style,
1278                      choice_button_style=choice_button_style,
1279                      choice_chosen_button_style=choice_chosen_button_style,
1280                      **kwargs)
1281
1282    if renpy.config.menu_showed_window:
1283        renpy.exports.shown_window()
1284
1285    # Log the chosen choice.
1286    for label, val in items:
1287        if val is not None:
1288            log("Choice: " + label)
1289        else:
1290            log(label)
1291
1292    log("")
1293
1294    if interact:
1295
1296        rv = renpy.ui.interact(mouse='menu', type=type, roll_forward=roll_forward)
1297
1298        for label, val in items:
1299
1300            if isinstance(val, renpy.ui.ChoiceReturn):
1301                val = val.value
1302
1303            if rv == val:
1304                log("Player chose: " + label)
1305                break
1306        else:
1307            log("No choice chosen.")
1308
1309        log("")
1310
1311        checkpoint(rv)
1312
1313        if with_none is None:
1314            with_none = renpy.config.implicit_with_none
1315
1316        if with_none:
1317            renpy.game.interface.do_with(None, None)
1318
1319        return rv
1320
1321    return None
1322
1323
1324class TagQuotingDict(object):
1325
1326    def __getitem__(self, key):
1327
1328        store = renpy.store.__dict__
1329
1330        if key in store:
1331            rv = store[key]
1332
1333            if isinstance(rv, basestring):
1334                rv = rv.replace("{", "{{")
1335
1336            return rv
1337        else:
1338            if renpy.config.debug:
1339                raise Exception("During an interpolation, '%s' was not found as a variable." % key)
1340            return "<" + key + " unbound>"
1341
1342
1343tag_quoting_dict = TagQuotingDict()
1344
1345
1346def predict_say(who, what):
1347    """
1348    :undocumented:
1349
1350    This is called to predict the results of a say command.
1351    """
1352
1353    if who is None:
1354        who = renpy.store.narrator # E1101 @UndefinedVariable
1355
1356    if isinstance(who, basestring):
1357        return renpy.store.predict_say(who, what)
1358
1359    predict = getattr(who, 'predict', None)
1360    if predict:
1361        predict(what)
1362
1363
1364def scry_say(who, scry):
1365    """
1366    :undocumented:
1367
1368    Called when scry is called on a say statement. Needs to set
1369    the interacts field.
1370    """
1371
1372    try:
1373        scry.interacts = who.will_interact()
1374    except:
1375        scry.interacts = True
1376
1377
1378def say(who, what, *args, **kwargs):
1379    """
1380    :doc: se_say
1381
1382    The equivalent of the say statement.
1383
1384    `who`
1385        Either the character that will say something, None for the narrator,
1386        or a string giving the character name. In the latter case, the
1387        :func:`say` is used to create the speaking character.
1388
1389    `what`
1390        A string giving the line to say. Percent-substitutions are performed
1391        in this string.
1392
1393    `interact`
1394        If true, Ren'Py waits for player input when displaying the dialogue. If
1395        false, Ren'Py shows the dialogue, but does not perform an interaction.
1396        (This is passed in as a keyword argument.)
1397
1398    This function is rarely necessary, as the following three lines are
1399    equivalent. ::
1400
1401        e "Hello, world."
1402        $ renpy.say(e, "Hello, world.")
1403        $ e("Hello, world.")
1404    """
1405
1406    if renpy.config.old_substitutions:
1407        # Interpolate variables.
1408        what = what % tag_quoting_dict
1409
1410    if who is None:
1411        who = renpy.store.narrator # E1101 @UndefinedVariable
1412
1413    if renpy.config.say_arguments_callback:
1414        args, kwargs = renpy.config.say_arguments_callback(who, *args, **kwargs)
1415
1416    if isinstance(who, basestring):
1417        renpy.store.say(who, what, *args, **kwargs)
1418    else:
1419        who(what, *args, **kwargs)
1420
1421
1422def imagemap(ground, selected, hotspots, unselected=None, overlays=False,
1423             style='imagemap', mouse='imagemap', with_none=None, **properties):
1424    """
1425    :undocumented: Use screens already.
1426
1427    Displays an imagemap. An image map consists of two images and a
1428    list of hotspots that are defined on that image. When the user
1429    clicks on a hotspot, the value associated with that hotspot is
1430    returned.
1431
1432    @param ground: The name of the file containing the ground
1433    image. The ground image is displayed for areas that are not part
1434    of any hotspots.
1435
1436    @param selected: The name of the file containing the selected
1437    image. This image is displayed in hotspots when the mouse is over
1438    them.
1439
1440    @param hotspots: A list of tuples defining the hotspots in this
1441    image map. Each tuple has the format (x0, y0, x1, y1, result).
1442    (x0, y0) gives the coordinates of the upper-left corner of the
1443    hotspot, (x1, y1) gives the lower-right corner, and result gives
1444    the value returned from this function if the mouse is clicked in
1445    the hotspot.
1446
1447    @param unselected: If provided, then it is the name of a file
1448    containing the image that's used to fill in hotspots that are not
1449    selected as part of any image. If not provided, the ground image
1450    is used instead.
1451
1452    @param overlays: If True, overlays are displayed when this imagemap
1453    is active. If False, the overlays are suppressed.
1454
1455    @param with_none: If True, performs a with None after the input. If None,
1456    takes the value from config.implicit_with_none.
1457    """
1458
1459    renpy.exports.mode('imagemap')
1460
1461    renpy.ui.imagemap_compat(ground, selected, hotspots, unselected=unselected,
1462                             style=style, **properties)
1463
1464    roll_forward = renpy.exports.roll_forward_info()
1465    if roll_forward not in [ result for _x0, _y0, _x1, _y1, result in hotspots]:
1466        roll_forward = None
1467
1468    if in_fixed_rollback() and renpy.config.fix_rollback_without_choice:
1469        renpy.ui.saybehavior()
1470
1471    rv = renpy.ui.interact(suppress_overlay=(not overlays),
1472                           type='imagemap',
1473                           mouse=mouse,
1474                           roll_forward=roll_forward)
1475
1476    renpy.exports.checkpoint(rv)
1477
1478    if with_none is None:
1479        with_none = renpy.config.implicit_with_none
1480
1481    if with_none:
1482        renpy.game.interface.do_with(None, None)
1483
1484    return rv
1485
1486
1487def pause(delay=None, music=None, with_none=None, hard=False, checkpoint=None):
1488    """
1489    :doc: other
1490    :args: (delay=None, hard=False)
1491
1492    Causes Ren'Py to pause. Returns true if the user clicked to end the pause,
1493    or false if the pause timed out or was skipped.
1494
1495    `delay`
1496        If given, the number of seconds Ren'Py should pause for.
1497
1498    `hard`
1499        This must be given as a keyword argument. When True, Ren'Py may prevent
1500        the user from clicking to interrupt the pause. If the player enables
1501        skipping, the hard pause will be skipped. There may be other circumstances
1502        where the hard pause ends early or prevents Ren'Py from operating properly,
1503        these will not be treated as bugs.
1504
1505        In general, using hard pauses is rude. When the user clicks to advance
1506        the game, it's an explicit request - the user wishes the game to advance.
1507        To override that request is to assume you understand what the player
1508        wants more than the player does.
1509
1510        Calling renpy.pause guarantees that whatever is on the screen will be
1511        displayed for at least one frame, and hence has been shown to the
1512        player.
1513
1514        tl;dr - Don't use renpy.pause with hard=True.
1515    """
1516
1517    if renpy.config.skipping == "fast":
1518        return False
1519
1520    if checkpoint is None:
1521        if delay is not None:
1522            checkpoint = False
1523        else:
1524            checkpoint = True
1525
1526    roll_forward = renpy.exports.roll_forward_info()
1527
1528    if roll_forward not in [ True, False ]:
1529        roll_forward = None
1530
1531    if (delay is not None) and renpy.game.after_rollback and not renpy.config.pause_after_rollback:
1532
1533        rv = roll_forward
1534        if rv is None:
1535            rv = False
1536
1537        if checkpoint:
1538            renpy.exports.checkpoint(rv, keep_rollback=True, hard=False)
1539
1540        return rv
1541
1542    renpy.exports.mode('pause')
1543
1544    if music is not None:
1545        newdelay = renpy.audio.music.get_delay(music)
1546
1547        if newdelay is not None:
1548            delay = newdelay
1549
1550    if (delay is not None) and renpy.game.after_rollback and roll_forward is None:
1551        delay = 0
1552
1553    if delay is None:
1554        afm = " "
1555    else:
1556        afm = None
1557
1558    if hard or not renpy.store._dismiss_pause:
1559        renpy.ui.saybehavior(afm=afm, dismiss='dismiss_hard_pause', dismiss_unfocused=[])
1560    else:
1561        renpy.ui.saybehavior(afm=afm)
1562
1563    rv = renpy.ui.interact(mouse='pause', type='pause', roll_forward=roll_forward, pause=delay)
1564
1565    if checkpoint:
1566        renpy.exports.checkpoint(rv, keep_rollback=True, hard=renpy.config.pause_after_rollback or (delay is None))
1567
1568    if with_none is None:
1569        with_none = renpy.config.implicit_with_none
1570
1571    if with_none:
1572        renpy.game.interface.do_with(None, None)
1573
1574    return rv
1575
1576
1577def movie_cutscene(filename, delay=None, loops=0, stop_music=True):
1578    """
1579    :doc: movie_cutscene
1580
1581    This displays a movie cutscene for the specified number of
1582    seconds. The user can click to interrupt the cutscene.
1583    Overlays and Underlays are disabled for the duration of the cutscene.
1584
1585    `filename`
1586        The name of a file containing any movie playable by Ren'Py.
1587
1588    `delay`
1589        The number of seconds to wait before ending the cutscene.
1590        Normally the length of the movie, in seconds. If None, then the
1591        delay is computed from the number of loops (that is, loops + 1) *
1592        the length of the movie. If -1, we wait until the user clicks.
1593
1594    `loops`
1595        The number of extra loops to show, -1 to loop forever.
1596
1597    Returns True if the movie was terminated by the user, or False if the
1598    given delay elapsed uninterrupted.
1599    """
1600
1601    renpy.exports.mode('movie')
1602
1603    if stop_music:
1604        renpy.audio.audio.set_force_stop("music", True)
1605
1606    movie_start_fullscreen(filename, loops=loops)
1607
1608    renpy.ui.saybehavior()
1609
1610    if delay is None or delay < 0:
1611        renpy.ui.soundstopbehavior("movie")
1612    else:
1613        renpy.ui.pausebehavior(delay, False)
1614
1615    if renpy.game.log.forward:
1616        roll_forward = True
1617    else:
1618        roll_forward = None
1619
1620    rv = renpy.ui.interact(suppress_overlay=True,
1621                           roll_forward=roll_forward)
1622
1623    # We don't want to put a checkpoint here, as we can't roll back while
1624    # playing a cutscene.
1625
1626    movie_stop()
1627
1628    if stop_music:
1629        renpy.audio.audio.set_force_stop("music", False)
1630
1631    return rv
1632
1633
1634def with_statement(trans, always=False, paired=None, clear=True):
1635    """
1636    :doc: se_with
1637    :name: renpy.with_statement
1638    :args: (trans, always=False)
1639
1640    Causes a transition to occur. This is the Python equivalent of the
1641    with statement.
1642
1643    `trans`
1644        The transition.
1645
1646    `always`
1647        If True, the transition will always occur, even if the user has
1648        disabled transitions.
1649
1650    This function returns true if the user chose to interrupt the transition,
1651    and false otherwise.
1652    """
1653
1654    if renpy.game.context().init_phase:
1655        raise Exception("With statements may not run while in init phase.")
1656
1657    if renpy.config.skipping:
1658        trans = None
1659
1660    if not (renpy.game.preferences.transitions or always):
1661        trans = None
1662
1663    renpy.exports.mode('with')
1664
1665    if isinstance(paired, dict):
1666        paired = paired.get(None, None)
1667
1668        if (trans is None) and (paired is None):
1669            return
1670
1671    if isinstance(trans, dict):
1672
1673        for k, v in trans.items():
1674            if k is None:
1675                continue
1676
1677            renpy.exports.transition(v, layer=k)
1678
1679        if None not in trans:
1680            return
1681
1682        trans = trans[None]
1683
1684    return renpy.game.interface.do_with(trans, paired, clear=clear)
1685
1686
1687globals()["with"] = with_statement
1688
1689
1690def rollback(force=False, checkpoints=1, defer=False, greedy=True, label=None, abnormal=True, current_label=None):
1691    """
1692    :doc: rollback
1693    :args: (force=False, checkpoints=1, defer=False, greedy=True, label=None, abnormal=True)
1694
1695    Rolls the state of the game back to the last checkpoint.
1696
1697    `force`
1698        If true, the rollback will occur in all circumstances. Otherwise,
1699        the rollback will only occur if rollback is enabled in the store,
1700        context, and config.
1701
1702    `checkpoints`
1703        Ren'Py will roll back through this many calls to renpy.checkpoint. It
1704        will roll back as far as it can, subject to this condition.
1705
1706    `defer`
1707        If true, the call will be deferred until control returns to the main
1708        context.
1709
1710    `greedy`
1711        If true, rollback will finish just after the previous checkpoint.
1712        If false, rollback finish just before the current checkpoint.
1713
1714    `label`
1715        If not None, a label that is called when rollback completes.
1716
1717    `abnormal`
1718        If true, the default, script executed after the transition is run in
1719        an abnormal mode that skips transitions that would have otherwise
1720        occured. Abnormal mode ends when an interaction begins.
1721    """
1722
1723    if defer and len(renpy.game.contexts) > 1:
1724        renpy.game.contexts[0].defer_rollback = (force, checkpoints)
1725        return
1726
1727    if not force:
1728
1729        if not renpy.store._rollback:
1730            return
1731
1732        if not renpy.game.context().rollback:
1733            return
1734
1735        if not renpy.config.rollback_enabled:
1736            return
1737
1738    renpy.config.skipping = None
1739    renpy.game.log.complete()
1740    renpy.game.log.rollback(checkpoints, greedy=greedy, label=label, force=(force is True), abnormal=abnormal, current_label=current_label)
1741
1742
1743def toggle_fullscreen():
1744    """
1745    :undocumented:
1746    Toggles the fullscreen mode.
1747    """
1748
1749    renpy.game.preferences.fullscreen = not renpy.game.preferences.fullscreen
1750
1751
1752def toggle_music():
1753    """
1754    :undocumented:
1755    Does nothing.
1756    """
1757
1758
1759@renpy_pure
1760def has_label(name):
1761    """
1762    :doc: label
1763
1764    Returns true if `name` is a valid label the program, or false otherwise.
1765
1766    `name`
1767        Should be a string to check for the existence of a label. It can
1768        also be an opaque tuple giving the name of a non-label statement.
1769    """
1770
1771    return renpy.game.script.has_label(name)
1772
1773
1774@renpy_pure
1775def get_all_labels():
1776    """
1777    :doc: label
1778
1779    Returns the set of all labels defined in the program, including labels
1780    defined for internal use in the libraries.
1781    """
1782    rv = [ ]
1783
1784    for i in renpy.game.script.namemap.keys():
1785        if isinstance(i, basestring):
1786            rv.append(i)
1787
1788    return renpy.python.RevertableSet(rv)
1789
1790
1791def take_screenshot(scale=None, background=False):
1792    """
1793    :doc: loadsave
1794
1795    Causes a screenshot to be taken. This screenshot will be saved as part of
1796    a save game.
1797    """
1798
1799    if scale is None:
1800        scale = (renpy.config.thumbnail_width, renpy.config.thumbnail_height)
1801
1802    renpy.game.interface.take_screenshot(scale, background=background)
1803
1804
1805def full_restart(transition=False, label="_invoke_main_menu", target="_main_menu", save=False):
1806    """
1807    :doc: other
1808
1809    Causes Ren'Py to restart, returning the user to the main menu.
1810
1811    `transition`
1812        If given, the transition to run, or None to not run a transition.
1813        False uses :var:`config.end_game_transition`.
1814
1815    `save`
1816        If true, the game is saved in :var:`_quit_slot` before Ren'Py
1817        restarts and returns the user to the main menu.
1818    """
1819
1820    if save and (renpy.store._quit_slot is not None):
1821        renpy.loadsave.save(renpy.store._quit_slot, getattr(renpy.store, "save_name", ""))
1822
1823    if transition is False:
1824        transition = renpy.config.end_game_transition
1825
1826    raise renpy.game.FullRestartException((transition, label, target))
1827
1828
1829def utter_restart(keep_renderer=False):
1830    """
1831    :undocumented: Used in the implementation of shift+R.
1832
1833    Causes an utter restart of Ren'Py. This reloads the script and
1834    re-runs initialization.
1835    """
1836
1837    renpy.session["_keep_renderer"] = keep_renderer
1838
1839    raise renpy.game.UtterRestartException()
1840
1841
1842def reload_script():
1843    """
1844    :doc: other
1845
1846    Causes Ren'Py to save the game, reload the script, and then load the
1847    save.
1848    """
1849
1850    # Avoid reloading in a replay.
1851    if renpy.store._in_replay:
1852        return
1853
1854    s = get_screen("menu")
1855
1856    session.pop("_reload_screen", None)
1857    session.pop("_reload_screen_args", None)
1858    session.pop("_reload_screen_kwargs", None)
1859
1860    if not renpy.store.main_menu:
1861
1862        if s is not None:
1863            session["_reload_screen"] = s.screen_name[0]
1864            session["_reload_screen_args"] = s.scope.get("_args", ())
1865            session["_reload_screen_kwargs"] = s.scope.get("_kwargs", { })
1866
1867        renpy.game.call_in_new_context("_save_reload_game")
1868
1869    else:
1870
1871        if s is not None:
1872            session["_main_menu_screen"] = s.screen_name[0]
1873            session["_main_menu_screen_args"] = s.scope.get("_args", ())
1874            session["_main_menu_screen_kwargs"] = s.scope.get("_kwargs", { })
1875
1876        utter_restart()
1877
1878
1879def quit(relaunch=False, status=0, save=False): # @ReservedAssignment
1880    """
1881    :doc: other
1882
1883    This causes Ren'Py to exit entirely.
1884
1885    `relaunch`
1886        If true, Ren'Py will run a second copy of itself before quitting.
1887
1888    `status`
1889        The status code Ren'Py will return to the operating system.
1890        Generally, 0 is success, and positive integers are failure.
1891
1892    `save`
1893        If true, the game is saved in :var:`_quit_slot` before Ren'Py
1894        terminates.
1895    """
1896
1897    if save and (renpy.store._quit_slot is not None):
1898        renpy.loadsave.save(renpy.store._quit_slot, getattr(renpy.store, "save_name", ""))
1899
1900    if has_label("quit"):
1901        call_in_new_context("quit")
1902
1903    raise renpy.game.QuitException(relaunch=relaunch, status=status)
1904
1905
1906def jump(label):
1907    """
1908    :doc: se_jump
1909
1910    Causes the current statement to end, and control to jump to the given
1911    label.
1912    """
1913
1914    raise renpy.game.JumpException(label)
1915
1916
1917def jump_out_of_context(label):
1918    """
1919    :doc: label
1920
1921    Causes control to leave the current context, and then to be
1922    transferred in the parent context to the given label.
1923    """
1924
1925    raise renpy.game.JumpOutException(label)
1926
1927
1928def call(label, *args, **kwargs):
1929    """
1930    :doc: se_call
1931
1932    Causes the current Ren'Py statement to terminate, and a jump to a
1933    `label` to occur. When the jump returns, control will be passed
1934    to the statement following the current statement.
1935
1936    `from_current`
1937        If true, control will return to the current statement, rather than
1938        the statement following the current statement. (This will lead to
1939        the current statement being run twice. This must be passed as a
1940        keyword argument.)
1941    """
1942
1943    from_current = kwargs.pop("from_current", False)
1944    raise renpy.game.CallException(label, args, kwargs, from_current=from_current)
1945
1946
1947def return_statement(value=None):
1948    """
1949    :doc: se_call
1950
1951    Causes Ren'Py to return from the current Ren'Py-level call.
1952    """
1953
1954    renpy.store._return = value
1955    jump("_renpy_return")
1956
1957
1958def screenshot(filename):
1959    """
1960    :doc: other
1961
1962    Saves a screenshot in `filename`.
1963
1964    Returns True if the screenshot was saved successfully, False if saving
1965    failed for some reason.
1966
1967    The :var:`config.screenshot_pattern` and :var:`_screenshot_pattern`
1968    variables control the file the screenshot is saved in.
1969    """
1970
1971    return renpy.game.interface.save_screenshot(filename)
1972
1973
1974def screenshot_to_bytes(size):
1975    """
1976    :doc: other
1977
1978    Returns a screenshot as a bytes object, that can be passed to im.Data().
1979    The bytes will be a png-format image, such that::
1980
1981        $ data = renpy.screenshot_to_bytes((640, 360))
1982        show expression im.Data(data, "screenshot.png"):
1983            align (0, 0)
1984
1985    Will show the image. The bytes objects returned can be stored in save
1986    files and persistent data. However, these may be large, and care should
1987    be taken to not include too many.
1988
1989    `size`
1990        The size the screenshot will be resized to. If None, the screenshot
1991        will be resized, and hence will be the size of the player's window,
1992        without any letterbars.
1993
1994    This function may be slow, and so it's intended for save-like screenshots,
1995    and not realtime effects.
1996    """
1997
1998    return renpy.game.interface.screenshot_to_bytes(size)
1999
2000
2001@renpy_pure
2002def version(tuple=False): # @ReservedAssignment
2003    """
2004    :doc: renpy_version
2005
2006    If `tuple` is false, returns a string containing "Ren'Py ", followed by
2007    the current version of Ren'Py.
2008
2009    If `tuple` is true, returns a tuple giving each component of the
2010    version as an integer.
2011    """
2012
2013    if tuple:
2014        return renpy.version_tuple
2015
2016    return renpy.version
2017
2018
2019version_string = renpy.version
2020version_only = renpy.version_only
2021version_name = renpy.version_name
2022version_tuple = renpy.version_tuple
2023license = "" # @ReservedAssignment
2024
2025try:
2026    import platform as _platform
2027    platform = "-".join(_platform.platform().split("-")[:2])
2028except:
2029    if renpy.android:
2030        platform = "Android"
2031    elif renpy.ios:
2032        platform = "iOS"
2033    else:
2034        platform = "Unknown"
2035
2036
2037def transition(trans, layer=None, always=False, force=False):
2038    """
2039    :doc: other
2040    :args: (trans, layer=None, always=False)
2041
2042    Sets the transition that will be used during the next interaction.
2043
2044    `layer`
2045        The layer the transition applies to. If None, the transition
2046        applies to the entire scene.
2047
2048    `always`
2049        If false, this respects the transition preference. If true, the
2050        transition is always run.
2051    """
2052
2053    if isinstance(trans, dict):
2054        for layer, t in trans.items():
2055            transition(t, layer=layer, always=always, force=force)
2056        return
2057
2058    if (not always) and not renpy.game.preferences.transitions:
2059        trans = None
2060
2061    renpy.game.interface.set_transition(trans, layer, force=force)
2062
2063
2064def get_transition(layer=None):
2065    """
2066    :doc: other
2067
2068    Gets the transition for `layer`, or the entire scene if
2069    `layer` is None. This returns the transition that is queued up
2070    to run during the next interaction, or None if no such
2071    transition exists.
2072    """
2073
2074    return renpy.game.interface.transition.get(layer, None)
2075
2076
2077def clear_game_runtime():
2078    """
2079    :doc: other
2080
2081    Resets the game runtime counter.
2082    """
2083
2084    renpy.game.contexts[0].runtime = 0
2085
2086
2087def get_game_runtime():
2088    """
2089    :doc: other
2090
2091    Returns the game runtime counter.
2092
2093    The game runtime counter counts the number of seconds that have
2094    elapsed while waiting for user input in the top-level context.
2095    (It does not count time spent in the main or game menus.)
2096    """
2097
2098    return renpy.game.contexts[0].runtime
2099
2100
2101@renpy_pure
2102def loadable(filename):
2103    """
2104    :doc: file
2105
2106    Returns True if the given filename is loadable, meaning that it
2107    can be loaded from the disk or from inside an archive. Returns
2108    False if this is not the case.
2109    """
2110
2111    return renpy.loader.loadable(filename)
2112
2113
2114@renpy_pure
2115def exists(filename):
2116    """
2117    :doc: file_rare
2118
2119    Returns true if the given filename can be found in the
2120    searchpath. This only works if a physical file exists on disk. It
2121    won't find the file if it's inside of an archive.
2122
2123    You almost certainly want to use :func:`renpy.loadable` in preference
2124    to this function.
2125    """
2126
2127    try:
2128        renpy.loader.transfn(filename)
2129        return True
2130    except:
2131        return False
2132
2133
2134def restart_interaction():
2135    """
2136    :doc: other
2137
2138    Restarts the current interaction. Among other things, this displays
2139    images added to the scene, re-evaluates screens, and starts any
2140    queued transitions.
2141
2142    This only does anything when called from within an interaction (for
2143    example, from an action). Outside an interaction, this function has
2144    no effect.
2145    """
2146
2147    try:
2148        renpy.game.interface.restart_interaction = True
2149    except:
2150        pass
2151
2152
2153def context():
2154    """
2155    :doc: context
2156
2157    Returns an object that is unique to the current context. The object
2158    is copied when entering a new context, but changes to the copy do
2159    not change the original.
2160
2161    The object is saved and participates in rollback.
2162    """
2163
2164    return renpy.game.context().info
2165
2166
2167def context_nesting_level():
2168    """
2169    :doc: context
2170
2171    Returns the nesting level of the current context. This is 0 for the
2172    outermost context (the context that is saved, loaded, and rolled-back),
2173    and is non-zero in other contexts, such as menu and replay contexts.
2174    """
2175
2176    return len(renpy.game.contexts) - 1
2177
2178
2179def music_start(filename, loops=True, fadeout=None, fadein=0):
2180    """
2181    Deprecated music start function, retained for compatibility. Use
2182    renpy.music.play() or .queue() instead.
2183    """
2184
2185    renpy.audio.music.play(filename, loop=loops, fadeout=fadeout, fadein=fadein)
2186
2187
2188def music_stop(fadeout=None):
2189    """
2190    Deprecated music start function, retained for compatibility. Use
2191    renpy.music.play() or .queue() instead.
2192    """
2193
2194    renpy.audio.music.stop(fadeout=fadeout)
2195
2196
2197def get_filename_line():
2198    """
2199    :doc: debug
2200
2201    Returns a pair giving the filename and line number of the current
2202    statement.
2203    """
2204
2205    n = renpy.game.script.namemap.get(renpy.game.context().current, None)
2206
2207    if n is None:
2208        return "unknown", 0
2209    else:
2210        return n.filename, n.linenumber
2211
2212
2213# A file that log logs to.
2214logfile = None
2215
2216
2217def log(msg):
2218    """
2219    :doc: debug
2220
2221    If :var:`config.log` is not set, this does nothing. Otherwise, it opens
2222    the logfile (if not already open), formats the message to :var:`config.log_width`
2223    columns, and prints it to the logfile.
2224    """
2225
2226    global logfile
2227
2228    if not renpy.config.log:
2229        return
2230
2231    if msg is None:
2232        return
2233
2234    try:
2235        msg = unicode(msg)
2236    except:
2237        pass
2238
2239    try:
2240
2241        if not logfile:
2242            import os
2243            logfile = open(os.path.join(renpy.config.basedir, renpy.config.log), "a")
2244
2245            if not logfile.tell():
2246                logfile.write("\ufeff")
2247
2248        import textwrap
2249
2250        wrapped = textwrap.fill(msg, renpy.config.log_width)
2251        wrapped = unicode(wrapped)
2252
2253        logfile.write(wrapped + "\n")
2254        logfile.flush()
2255
2256    except:
2257        renpy.config.log = None
2258
2259
2260def force_full_redraw():
2261    """
2262    :doc: other
2263
2264    Forces the screen to be redrawn in full. Call this after using pygame
2265    to redraw the screen directly.
2266    """
2267
2268    renpy.game.interface.full_redraw = True
2269
2270
2271def do_reshow_say(who, what, interact=False, *args, **kwargs):
2272
2273    if who is not None:
2274        who = renpy.python.py_eval(who)
2275
2276    say(who, what, interact=interact, *args, **kwargs)
2277
2278
2279curried_do_reshow_say = curry(do_reshow_say)
2280
2281
2282def get_reshow_say(**kwargs):
2283    kw = dict(renpy.store._last_say_kwargs)
2284    kw.update(kwargs)
2285
2286    return curried_do_reshow_say(
2287        renpy.store._last_say_who,
2288        renpy.store._last_say_what,
2289        renpy.store._last_say_args,
2290        **kw)
2291
2292
2293def reshow_say(**kwargs):
2294    get_reshow_say()(**kwargs)
2295
2296
2297def current_interact_type():
2298    return getattr(renpy.game.context().info, "_current_interact_type", None)
2299
2300
2301def last_interact_type():
2302    return getattr(renpy.game.context().info, "_last_interact_type", None)
2303
2304
2305def dynamic(*vars, **kwargs): # @ReservedAssignment
2306    """
2307    :doc: other
2308
2309    This can be given one or more variable names as arguments. This makes
2310    the variables dynamically scoped to the current call. The variables will
2311    be reset to their original value when the call returns.
2312
2313    If the variables are given as keyword arguments, the value of the argument
2314    is assigned to the variable name.
2315
2316    Example calls are::
2317
2318        $ renpy.dynamic("x", "y", "z")
2319        $ renpy.dynamic(players=2, score=0)
2320    """
2321
2322    vars = vars + tuple(kwargs) # @ReservedAssignment
2323    renpy.game.context().make_dynamic(vars)
2324
2325    for k, v in kwargs.items():
2326        setattr(renpy.store, k, v)
2327
2328
2329def context_dynamic(*vars): # @ReservedAssignment
2330    """
2331    :doc: other
2332
2333    This can be given one or more variable names as arguments. This makes
2334    the variables dynamically scoped to the current context. The variables will
2335    be reset to their original value when the call returns.
2336
2337    An example call is::
2338
2339        $ renpy.context_dynamic("x", "y", "z")
2340    """
2341
2342    renpy.game.context().make_dynamic(vars, context=True)
2343
2344
2345def seen_label(label):
2346    """
2347    :doc: label
2348
2349    Returns true if the named label has executed at least once on the current user's
2350    system, and false otherwise. This can be used to unlock scene galleries, for
2351    example.
2352    """
2353    return label in renpy.game.persistent._seen_ever # @UndefinedVariable
2354
2355
2356def mark_label_seen(label):
2357    """
2358    :doc: label
2359
2360    Marks the named label as if it has been already executed on the current user's
2361    system.
2362    """
2363    renpy.game.persistent._seen_ever[label] = True
2364
2365
2366def mark_label_unseen(label):
2367    """
2368    :doc: label
2369
2370    Marks the named label as if it has not been executed on the current user's
2371    system yet.
2372    """
2373    if label in renpy.game.persistent._seen_ever:
2374        del renpy.game.persistent._seen_ever[label]
2375
2376
2377def seen_audio(filename):
2378    """
2379    :doc: audio
2380
2381    Returns True if the given filename has been played at least once on the current
2382    user's system.
2383    """
2384    filename = re.sub(r'^<.*?>', '', filename)
2385
2386    return filename in renpy.game.persistent._seen_audio # @UndefinedVariable
2387
2388
2389def mark_audio_seen(filename):
2390    """
2391    :doc: audio
2392
2393    Marks the given filename as if it has been already played on the current user's
2394    system.
2395    """
2396    filename = re.sub(r'^<.*?>', '', filename)
2397
2398    renpy.game.persistent._seen_audio[filename] = True
2399
2400
2401def mark_audio_unseen(filename):
2402    """
2403    :doc: audio
2404
2405    Marks the given filename as if it has not been played on the current user's
2406    system yet.
2407    """
2408    filename = re.sub(r'^<.*?>', '', filename)
2409
2410    if filename in renpy.game.persistent._seen_audio:
2411        del renpy.game.persistent._seen_audio[filename]
2412
2413
2414def seen_image(name):
2415    """
2416    :doc: image_func
2417
2418    Returns True if the named image has been seen at least once on the user's
2419    system. An image has been seen if it's been displayed using the show statement,
2420    scene statement, or :func:`renpy.show` function. (Note that there are cases
2421    where the user won't actually see the image, like a show immediately followed by
2422    a hide.)
2423    """
2424    if not isinstance(name, tuple):
2425        name = tuple(name.split())
2426
2427    return name in renpy.game.persistent._seen_images # @UndefinedVariable
2428
2429
2430def mark_image_seen(name):
2431    """
2432    :doc: image_func
2433
2434    Marks the named image as if it has been already displayed on the current user's
2435    system.
2436    """
2437    if not isinstance(name, tuple):
2438        name = tuple(name.split())
2439
2440    renpy.game.persistent._seen_images[name] = True
2441
2442
2443def mark_image_unseen(name):
2444    """
2445    :doc: image_func
2446
2447    Marks the named image as if it has not been displayed on the current user's
2448    system yet.
2449    """
2450    if not isinstance(name, tuple):
2451        name = tuple(name.split())
2452
2453    if name in renpy.game.persistent._seen_images:
2454        del renpy.game.persistent._seen_images[name]
2455
2456
2457def file(fn): # @ReservedAssignment
2458    """
2459    :doc: file
2460
2461    Returns a read-only file-like object that accesses the file named `fn`. The file is
2462    accessed using Ren'Py's standard search method, and may reside in an RPA archive.
2463    or as an Android asset.
2464
2465    The object supports a wide subset of the fields and methods found on Python's
2466    standard file object, opened in binary mode. (Basically, all of the methods that
2467    are sensible for a read-only file.)
2468    """
2469    return renpy.loader.load(fn)
2470
2471
2472def notl_file(fn): # @ReservedAssignment
2473    """
2474    :undocumented:
2475
2476    Like file, but doesn't search the translation prefix.
2477    """
2478    return renpy.loader.load(fn, tl=False)
2479
2480
2481def image_size(im):
2482    """
2483    :doc: file_rare
2484
2485    Given an image manipulator, loads it and returns a (``width``,
2486    ``height``) tuple giving its size.
2487
2488    This reads the image in from disk and decompresses it, without
2489    using the image cache. This can be slow.
2490    """
2491
2492    # Index the archives, if we haven't already.
2493    renpy.loader.index_archives()
2494
2495    im = renpy.easy.displayable(im)
2496
2497    if not isinstance(im, renpy.display.im.Image):
2498        raise Exception("renpy.image_size expects it's argument to be an image.")
2499
2500    surf = im.load()
2501    return surf.get_size()
2502
2503
2504def get_at_list(name, layer=None, camera=False):
2505    """
2506    :doc: se_images
2507
2508    Returns the list of transforms being applied to the image with tag `name`
2509    on `layer`. Returns an empty list if no transforms are being applied, or
2510    None if the image is not shown.
2511
2512    If `layer` is None, uses the default layer for the given tag.
2513    """
2514
2515    if isinstance(name, basestring):
2516        name = tuple(name.split())
2517
2518    tag = name[0]
2519    layer = default_layer(layer, tag)
2520
2521    return renpy.game.context().scene_lists.at_list[layer].get(tag, None)
2522
2523
2524def show_layer_at(at_list, layer='master', reset=True, camera=False):
2525    """
2526    :doc: se_images
2527    :name: renpy.show_layer_at
2528
2529    The Python equivalent of the ``show layer`` `layer` ``at`` `at_list`
2530    statement. If `camera` is True, the equivalent of the ``camera`` statement.
2531
2532    `reset`
2533        If true, the transform state is reset to the start when it is shown.
2534        If false, the transform state is persisted, allowing the new transform
2535        to update that state.
2536    """
2537
2538    if not isinstance(at_list, list):
2539        at_list = [ at_list ]
2540
2541    renpy.game.context().scene_lists.set_layer_at_list(layer, at_list, reset=reset, camera=camera)
2542
2543
2544layer_at_list = show_layer_at
2545
2546
2547def free_memory():
2548    """
2549    :doc: other
2550
2551    Attempts to free some memory. Useful before running a renpygame-based
2552    minigame.
2553    """
2554
2555    force_full_redraw()
2556    renpy.display.interface.kill_textures()
2557    renpy.display.interface.kill_surfaces()
2558    renpy.text.font.free_memory()
2559
2560    gc.collect(2)
2561
2562    if gc.garbage:
2563        del gc.garbage[:]
2564
2565
2566def flush_cache_file(fn):
2567    """
2568    :doc: other
2569
2570    This flushes all image cache entries that refer to the file `fn`.  This
2571    may be called when an image file changes on disk to force Ren'Py to
2572    use the new version.
2573    """
2574
2575    renpy.display.im.cache.flush_file(fn)
2576
2577
2578@renpy_pure
2579def easy_displayable(d, none=False):
2580    """
2581    :undocumented:
2582    """
2583
2584    if none:
2585        return renpy.easy.displayable(d)
2586    else:
2587        return renpy.easy.displayable_or_none(d)
2588
2589
2590def quit_event():
2591    """
2592    :doc: other
2593
2594    Triggers a quit event, as if the player clicked the quit button in the
2595    window chrome.
2596    """
2597
2598    renpy.game.interface.quit_event()
2599
2600
2601def iconify():
2602    """
2603    :doc: other
2604
2605    Iconifies the game.
2606    """
2607
2608    renpy.game.interface.iconify()
2609
2610
2611# New context stuff.
2612call_in_new_context = renpy.game.call_in_new_context
2613curried_call_in_new_context = renpy.curry.curry(renpy.game.call_in_new_context)
2614invoke_in_new_context = renpy.game.invoke_in_new_context
2615curried_invoke_in_new_context = renpy.curry.curry(renpy.game.invoke_in_new_context)
2616call_replay = renpy.game.call_replay
2617
2618renpy_pure("curried_call_in_new_context")
2619renpy_pure("curried_invoke_in_new_context")
2620
2621
2622# Error handling stuff.
2623def _error(msg):
2624    raise Exception(msg)
2625
2626
2627_error_handlers = [ _error ]
2628
2629
2630def push_error_handler(eh):
2631    _error_handlers.append(eh)
2632
2633
2634def pop_error_handler():
2635    _error_handlers.pop()
2636
2637
2638def error(msg):
2639    """
2640    :doc: lint
2641
2642    Reports `msg`, a string, as as error for the user. This is logged as a
2643    parse or lint error when approprate, and otherwise it is raised as an
2644    exception.
2645    """
2646
2647    _error_handlers[-1](msg)
2648
2649
2650def timeout(seconds):
2651    """
2652    :doc: udd_utility
2653
2654    Causes an event to be generated before `seconds` seconds have elapsed.
2655    This ensures that the event method of a user-defined displayable will be
2656    called.
2657    """
2658
2659    renpy.game.interface.timeout(seconds)
2660
2661
2662def end_interaction(value):
2663    """
2664    :doc: udd_utility
2665
2666    If `value` is not None, immediately ends the current interaction, causing
2667    the interaction to return `value`. If `value` is None, does nothing.
2668
2669    This can be called from inside the render and event methods of a
2670    creator-defined displayable.
2671    """
2672
2673    if value is None:
2674        return
2675
2676    raise renpy.display.core.EndInteraction(value)
2677
2678
2679def scry():
2680    """
2681    :doc: other
2682
2683    Returns the scry object for the current statement.
2684
2685    The scry object tells Ren'Py about things that must be true in the
2686    future of the current statement. Right now, the scry object has one
2687    field:
2688
2689    ``nvl_clear``
2690        Is true if an ``nvl clear`` statement will execute before the
2691        next interaction.
2692    """
2693
2694    name = renpy.game.context().current
2695    node = renpy.game.script.lookup(name)
2696    return node.scry()
2697
2698
2699@renpy_pure
2700def munged_filename():
2701    return renpy.parser.munge_filename(get_filename_line()[0])
2702
2703# Module loading stuff.
2704
2705
2706loaded_modules = set()
2707
2708
2709def load_module(name, **kwargs):
2710    """
2711    :doc: other
2712
2713    This loads the Ren'Py module named name. A Ren'Py module consists of Ren'Py script
2714    that is loaded into the usual (store) namespace, contained in a file named
2715    name.rpym or name.rpymc. If a .rpym file exists, and is newer than the
2716    corresponding .rpymc file, it is loaded and a new .rpymc file is created.
2717
2718    All of the init blocks (and other init-phase code) in the module are run
2719    before this function returns. An error is raised if the module name cannot
2720    be found, or is ambiguous.
2721
2722    Module loading may only occur from inside an init block.
2723    """
2724
2725    if not renpy.game.context().init_phase:
2726        raise Exception("Module loading is only allowed in init code.")
2727
2728    if name in loaded_modules:
2729        return
2730
2731    loaded_modules.add(name)
2732
2733    old_locked = renpy.config.locked
2734    renpy.config.locked = False
2735
2736    initcode = renpy.game.script.load_module(name)
2737
2738    context = renpy.execution.Context(False)
2739    context.init_phase = True
2740    renpy.game.contexts.append(context)
2741
2742    context.make_dynamic(kwargs)
2743    renpy.store.__dict__.update(kwargs) # @UndefinedVariable
2744
2745    for prio, node in initcode: # @UnusedVariable
2746        if isinstance(node, renpy.ast.Node):
2747            renpy.game.context().run(node)
2748        else:
2749            node()
2750
2751    context.pop_all_dynamic()
2752
2753    renpy.game.contexts.pop()
2754
2755    renpy.config.locked = old_locked
2756
2757
2758def load_string(s, filename="<string>"):
2759    """
2760    :doc: other
2761
2762    Loads `s` as Ren'Py script that can be called.
2763
2764    Returns the name of the first statement in s.
2765
2766    `filename` is the name of the filename that statements in the string will
2767    appear to be from.
2768    """
2769
2770    old_exception_info = renpy.game.exception_info
2771
2772    try:
2773
2774        old_locked = renpy.config.locked
2775        renpy.config.locked = False
2776
2777        stmts, initcode = renpy.game.script.load_string(filename, str(s))
2778
2779        if stmts is None:
2780            return None
2781
2782        context = renpy.execution.Context(False)
2783        context.init_phase = True
2784        renpy.game.contexts.append(context)
2785
2786        for prio, node in initcode: # @UnusedVariable
2787            if isinstance(node, renpy.ast.Node):
2788                renpy.game.context().run(node)
2789            else:
2790                node()
2791
2792        context.pop_all_dynamic()
2793        renpy.game.contexts.pop()
2794
2795        renpy.config.locked = old_locked
2796
2797        renpy.game.script.analyze()
2798
2799        return stmts[0].name
2800
2801    finally:
2802        renpy.game.exception_info = old_exception_info
2803
2804
2805def pop_call():
2806    """
2807    :doc: other
2808    :name: renpy.pop_call
2809
2810    Pops the current call from the call stack, without returning to
2811    the location.
2812
2813    This can be used if a label that is called decides not to return
2814    to its caller.
2815    """
2816
2817    renpy.game.context().pop_call()
2818
2819
2820pop_return = pop_call
2821
2822
2823def call_stack_depth():
2824    """
2825    :doc: other
2826
2827    Returns the depth of the call stack of the current context - the number
2828    of calls that have run without being returned from or popped from the
2829    call stack.
2830    """
2831
2832    return len(renpy.game.context().return_stack)
2833
2834
2835def game_menu(screen=None):
2836    """
2837    :undocumented: Probably not what we want in the presence of
2838    screens.
2839    """
2840
2841    if screen is None:
2842        call_in_new_context("_game_menu")
2843    else:
2844        call_in_new_context("_game_menu", _game_menu_screen=screen)
2845
2846
2847def shown_window():
2848    """
2849    :doc: other
2850
2851    Call this to indicate that the window has been shown. This interacts
2852    with the "window show" statement, which shows an empty window whenever
2853    this functions has not been called during an interaction.
2854    """
2855
2856    renpy.game.context().scene_lists.shown_window = True
2857
2858
2859class placement(renpy.python.RevertableObject):
2860
2861    def __init__(self, p):
2862        super(placement, self).__init__()
2863
2864        self.xpos = p[0]
2865        self.ypos = p[1]
2866        self.xanchor = p[2]
2867        self.yanchor = p[3]
2868        self.xoffset = p[4]
2869        self.yoffset = p[5]
2870        self.subpixel = p[6]
2871
2872    @property
2873    def pos(self):
2874        return self.xpos, self.ypos
2875
2876    @property
2877    def anchor(self):
2878        return self.xanchor, self.yanchor
2879
2880    @property
2881    def offset(self):
2882        return self.xoffset, self.yoffset
2883
2884
2885def get_placement(d):
2886    """
2887    :doc: image_func
2888
2889    This gets the placement of displayable d. There's very little warranty on this
2890    information, as it might change when the displayable is rendered, and might not
2891    exist until the displayable is first rendered.
2892
2893    This returns an object with the following fields, each corresponding to a style
2894    property:
2895
2896    * pos
2897    * xpos
2898    * ypos
2899    * anchor
2900    * xanchor
2901    * yanchor
2902    * offset
2903    * xoffset
2904    * yoffset
2905    * subpixel
2906
2907    """
2908    p = d.get_placement()
2909
2910    return placement(p)
2911
2912
2913def get_image_bounds(tag, width=None, height=None, layer=None):
2914    """
2915    :doc: image_func
2916
2917    If an image with `tag` exists on `layer`, returns the bounding box of
2918    that image. Returns None if the image is not found.
2919
2920    The bounding box is an (x, y, width, height) tuple. The components of
2921    the tuples are expressed in pixels, and may be floating point numbers.
2922
2923    `width`, `height`
2924        The width and height of the area that contains the image. If None,
2925        defaults the width and height of the screen, respectively.
2926
2927    `layer`
2928        If None, uses the default layer for `tag`.
2929    """
2930
2931    tag = tag.split()[0]
2932    layer = default_layer(layer, tag)
2933
2934    if width is None:
2935        width = renpy.config.screen_width
2936    if height is None:
2937        height = renpy.config.screen_height
2938
2939    return scene_lists().get_image_bounds(layer, tag, width, height)
2940
2941# User-Defined Displayable stuff.
2942
2943
2944Render = renpy.display.render.Render
2945render = renpy.display.render.render
2946IgnoreEvent = renpy.display.core.IgnoreEvent
2947redraw = renpy.display.render.redraw
2948
2949
2950class Displayable(renpy.display.core.Displayable, renpy.python.RevertableObject):
2951    pass
2952
2953
2954class Container(renpy.display.layout.Container, renpy.python.RevertableObject):
2955    _list_type = renpy.python.RevertableList
2956
2957
2958def get_roll_forward():
2959    return renpy.game.interface.shown_window
2960
2961
2962def cache_pin(*args):
2963    """
2964    :undocumented: Cache pin is deprecated.
2965    """
2966
2967    new_pins = renpy.python.RevertableSet()
2968
2969    for i in args:
2970
2971        im = renpy.easy.displayable(i)
2972
2973        if not isinstance(im, renpy.display.im.ImageBase):
2974            raise Exception("Cannot pin non-image-manipulator %r" % im)
2975
2976        new_pins.add(im)
2977
2978    renpy.store._cache_pin_set = new_pins | renpy.store._cache_pin_set
2979
2980
2981def cache_unpin(*args):
2982    """
2983    :undocumented: Cache pin is deprecated.
2984    """
2985
2986    new_pins = renpy.python.RevertableSet()
2987
2988    for i in args:
2989
2990        im = renpy.easy.displayable(i)
2991
2992        if not isinstance(im, renpy.display.im.ImageBase):
2993            raise Exception("Cannot unpin non-image-manipulator %r" % im)
2994
2995        new_pins.add(im)
2996
2997    renpy.store._cache_pin_set = renpy.store._cache_pin_set - new_pins
2998
2999
3000def expand_predict(d):
3001    """
3002    :undocumented:
3003
3004    Use the fnmatch function to expland `d` for the purposes of prediction.
3005    """
3006
3007    if not isinstance(d, basestring):
3008        return [ d ]
3009
3010    if not "*" in d:
3011        return [ d ]
3012
3013    if "." in d:
3014        l = list_files(False)
3015    else:
3016        l = list_images()
3017
3018    return fnmatch.filter(l, d)
3019
3020
3021def start_predict(*args):
3022    """
3023    :doc: image_func
3024
3025    This function takes one or more displayables as arguments. It causes
3026    Ren'Py to predict those displayables during every interaction until
3027    the displayables are removed by :func:`renpy.stop_predict`.
3028
3029    If a displayable name is a string containing one or more \\*
3030    characters, the asterisks are used as a wildcard pattern. If there
3031    is at least one . in the string, the pattern is matched against
3032    filenames, otherwise it is matched against image names.
3033
3034    For example::
3035
3036        $ renpy.start_predict("eileen *")
3037
3038    starts predicting all images with the name eileen, while::
3039
3040        $ renpy.start_predict("images/concert*.*")
3041
3042    matches all files starting with concert in the images directory.
3043    """
3044
3045    new_predict = renpy.python.RevertableSet(renpy.store._predict_set)
3046
3047    for i in args:
3048        for d in expand_predict(i):
3049            d = renpy.easy.displayable(d)
3050            new_predict.add(d)
3051
3052    renpy.store._predict_set = new_predict
3053
3054
3055def stop_predict(*args):
3056    """
3057    :doc: image_func
3058
3059    This function takes one or more displayables as arguments. It causes
3060    Ren'Py to stop predicting those displayables during every interaction.
3061
3062    Wildcard patterns can be used as described in :func:`renpy.start_predict`.
3063    """
3064
3065    new_predict = renpy.python.RevertableSet(renpy.store._predict_set)
3066
3067    for i in args:
3068        for d in expand_predict(i):
3069            d = renpy.easy.displayable(d)
3070            new_predict.discard(d)
3071
3072    renpy.store._predict_set = new_predict
3073
3074
3075def start_predict_screen(_screen_name, *args, **kwargs):
3076    """
3077    :doc: screens
3078
3079    Causes Ren'Py to start predicting the screen named `_screen_name`
3080    with the given arguments. This replaces any previous prediction
3081    of `_screen_name`. To stop predicting a screen, call :func:`renpy.stop_predict_screen`.
3082    """
3083
3084    new_predict = renpy.python.RevertableDict(renpy.store._predict_screen)
3085    new_predict[_screen_name] = (args, kwargs)
3086    renpy.store._predict_screen = new_predict
3087
3088
3089def stop_predict_screen(name):
3090    """
3091    :doc: screens
3092
3093    Causes Ren'Py to stop predicting the screen named `name`.
3094    """
3095
3096    new_predict = renpy.python.RevertableDict(renpy.store._predict_screen)
3097    new_predict.pop(name, None)
3098    renpy.store._predict_screen = new_predict
3099
3100
3101def call_screen(_screen_name, *args, **kwargs):
3102    """
3103    :doc: screens
3104
3105    The programmatic equivalent of the call screen statement.
3106
3107    This shows `_screen_name` as a screen, then causes an interaction
3108    to occur. The screen is hidden at the end of the interaction, and
3109    the result of the interaction is returned.
3110
3111    Positional arguments, and keyword arguments that do not begin with
3112    _ are passed to the screen.
3113
3114    If the keyword argument `_with_none` is false, "with None" is not
3115    run at the end of end of the interaction.
3116
3117    If the keyword argument `_mode` in kwargs, it will be mode of this
3118    interaction, otherwise it will be "screen" mode.
3119    """
3120
3121    mode = "screen"
3122    if "_mode" in kwargs:
3123        mode = kwargs.pop("_mode")
3124    renpy.exports.mode(mode)
3125
3126    with_none = renpy.config.implicit_with_none
3127
3128    if "_with_none" in kwargs:
3129        with_none = kwargs.pop("_with_none")
3130
3131    show_screen(_screen_name, _transient=True, *args, **kwargs)
3132
3133    roll_forward = renpy.exports.roll_forward_info()
3134
3135    try:
3136        rv = renpy.ui.interact(mouse="screen", type="screen", roll_forward=roll_forward)
3137    except (renpy.game.JumpException, renpy.game.CallException) as e:
3138        rv = e
3139
3140    renpy.exports.checkpoint(rv)
3141
3142    if with_none:
3143        renpy.game.interface.do_with(None, None)
3144
3145    if isinstance(rv, (renpy.game.JumpException, renpy.game.CallException)):
3146        raise rv
3147
3148    return rv
3149
3150
3151@renpy_pure
3152def list_files(common=False):
3153    """
3154    :doc: file
3155
3156    Lists the files in the game directory and archive files. Returns
3157    a list of files, with / as the directory separator.
3158
3159    `common`
3160        If true, files in the common directory are included in the
3161        listing.
3162    """
3163
3164    rv = [ ]
3165
3166    for dir, fn in renpy.loader.listdirfiles(common): # @ReservedAssignment
3167        if fn.startswith("saves/"):
3168            continue
3169
3170        rv.append(fn)
3171
3172    rv.sort()
3173
3174    return rv
3175
3176
3177def get_renderer_info():
3178    """
3179    :doc: other
3180
3181    Returns a dictionary, giving information about the renderer Ren'Py is
3182    currently using. Defined keys are:
3183
3184    ``"renderer"``
3185        A string giving the name of the renderer that is in use.
3186
3187    ``"resizable"``
3188        True if and only if the window is resizable.
3189
3190    ``"additive"``
3191        True if and only if the renderer supports additive blending.
3192
3193    ``"model"``
3194        Present and true if model-based rendering is supported.
3195
3196    Other, renderer-specific, keys may also exist. The dictionary should
3197    be treated as immutable. This should only be called once the display
3198    has been started (that is, after the init phase has finished).
3199    """
3200
3201    return renpy.display.draw.info
3202
3203
3204def display_reset():
3205    """
3206    :undocumented: Used internally.
3207
3208    Causes the display to be restarted at the start of the next interaction.
3209    """
3210
3211    renpy.display.interface.display_reset = True
3212
3213
3214def mode(mode):
3215    """
3216    :doc: modes
3217
3218    Causes Ren'Py to enter the named mode, or stay in that mode if it's
3219    already in it.
3220    """
3221
3222    ctx = renpy.game.context()
3223
3224    if not ctx.use_modes:
3225        return
3226
3227    modes = ctx.modes
3228
3229    try:
3230        ctx.use_modes = False
3231
3232        if mode != modes[0]:
3233            for c in renpy.config.mode_callbacks:
3234                c(mode, modes)
3235
3236    finally:
3237        ctx.use_modes = True
3238
3239    if mode in modes:
3240        modes.remove(mode)
3241
3242    modes.insert(0, mode)
3243
3244
3245def get_mode():
3246    """
3247    :doc: modes
3248
3249    Returns the current mode, or None if it is not defined.
3250    """
3251
3252    ctx = renpy.game.context()
3253
3254    if not ctx.use_modes:
3255        return None
3256
3257    modes = ctx.modes
3258
3259    return modes[0]
3260
3261
3262def notify(message):
3263    """
3264    :doc: other
3265
3266    Causes Ren'Py to display the `message` using the notify screen. By
3267    default, this will cause the message to be dissolved in, displayed
3268    for two seconds, and dissolved out again.
3269
3270    This is useful for actions that otherwise wouldn't produce feedback,
3271    like screenshots or quicksaves.
3272
3273    Only one notification is displayed at a time. If a second notification
3274    is displayed, the first notification is replaced.
3275
3276    This function just calls :var:`config.notify`, allowing its implementation
3277    to be replaced by assigning a new function to that variable.
3278    """
3279
3280    renpy.config.notify(message)
3281
3282
3283def display_notify(message):
3284    """
3285    :doc: other
3286
3287    The default implementation of :func:`renpy.notify`.
3288    """
3289
3290    hide_screen('notify')
3291    show_screen('notify', message=message)
3292    restart_interaction()
3293
3294
3295@renpy_pure
3296def variant(name):
3297    """
3298    :doc: screens
3299
3300    Returns true if a `name` is a screen variant that can be chosen
3301    by Ren'Py. See :ref:`screen-variants` for more details. This function
3302    can be used as the condition in a Python if statement to set up the
3303    appropriate styles for the selected screen variant.
3304
3305    `name` can also be a list of variants, in which case this function
3306    returns True if any of the variants is selected.
3307    """
3308
3309    if isinstance(name, basestring):
3310        return name in renpy.config.variants
3311    else:
3312        for n in name:
3313            if n in renpy.config.variants:
3314                return True
3315
3316        return False
3317
3318
3319def vibrate(duration):
3320    """
3321    :doc: other
3322
3323    Causes the device to vibrate for `duration` seconds. Currently, this
3324    is only supported on Android.
3325    """
3326
3327    if renpy.android:
3328        import android # @UnresolvedImport
3329        android.vibrate(duration)
3330
3331
3332def get_say_attributes():
3333    """
3334    :doc: other
3335
3336    Gets the attributes associated with the current say statement, or
3337    None if no attributes are associated with this statement.
3338
3339    This is only valid when executing or predicting a say statement.
3340    """
3341
3342    return renpy.game.context().say_attributes
3343
3344
3345def get_side_image(prefix_tag, image_tag=None, not_showing=None, layer=None):
3346    """
3347    :doc: side
3348
3349    This attempts to find an image to show as the side image.
3350
3351    It begins by determining a set of image attributes. If `image_tag` is
3352    given, it gets the image attributes from the tag. Otherwise, it gets
3353    them from the currently showing character.
3354
3355    It then looks up an image with the tag `prefix_tag` and those attributes,
3356    and returns it if it exists.
3357
3358    If not_showing is True, this only returns a side image if the image the
3359    attributes are taken from is not on the screen. If Nome, the value
3360    is taken from :var:`config.side_image_only_not_showing`.
3361
3362    If `layer` is None, uses the default layer for the currently showing
3363    tag.
3364    """
3365
3366    if not_showing is None:
3367        not_showing = renpy.config.side_image_only_not_showing
3368
3369    images = renpy.game.context().images
3370
3371    if image_tag is not None:
3372        image_layer = default_layer(layer, image_tag)
3373        attrs = (image_tag,) + images.get_attributes(image_layer, image_tag)
3374
3375        if renpy.config.side_image_requires_attributes and (len(attrs) < 2):
3376            return None
3377
3378    else:
3379        attrs = renpy.store._side_image_attributes
3380
3381    if not attrs:
3382        return None
3383
3384    attr_layer = default_layer(layer, attrs)
3385
3386    if not_showing and images.showing(attr_layer, (attrs[0],)):
3387        return None
3388
3389    required = [ attrs[0] ]
3390    optional = list(attrs[1:])
3391
3392    return images.choose_image(prefix_tag, required, optional, None)
3393
3394
3395def get_physical_size():
3396    """
3397    :doc: other
3398
3399    Returns the size of the physical window.
3400    """
3401
3402    return renpy.display.draw.get_physical_size()
3403
3404
3405def set_physical_size(size):
3406    """
3407    :doc: other
3408
3409    Attempts to set the size of the physical window to `size`. This has the
3410    side effect of taking the screen out of fullscreen mode.
3411    """
3412
3413    width = int(size[0])
3414    height = int(size[1])
3415
3416    renpy.game.preferences.fullscreen = False
3417
3418    if get_renderer_info()["resizable"]:
3419
3420        renpy.game.preferences.physical_size = (width, height)
3421
3422        if renpy.display.draw is not None:
3423            renpy.display.draw.resize()
3424
3425
3426def reset_physical_size():
3427    """
3428    :doc: other
3429
3430    Attempts to set the size of the physical window to the specified values
3431    in renpy.config. (That is, screen_width and screen_height.) This has the
3432    side effect of taking the screen out of fullscreen mode.
3433    """
3434
3435    set_physical_size((renpy.config.screen_width, renpy.config.screen_height))
3436
3437
3438@renpy_pure
3439def fsencode(s):
3440    """
3441    :doc: file_rare
3442    :name: renpy.fsencode
3443
3444    Converts s from unicode to the filesystem encoding.
3445    """
3446
3447    if not PY2:
3448        return s
3449
3450    if not isinstance(s, str):
3451        return s
3452
3453    fsencoding = sys.getfilesystemencoding() or "utf-8"
3454    return s.encode(fsencoding)
3455
3456
3457@renpy_pure
3458def fsdecode(s):
3459    """
3460    :doc: file_rare
3461    :name: renpy.fsdecode
3462
3463    Converts s from filesystem encoding to unicode.
3464    """
3465
3466    if not PY2:
3467        return s
3468
3469    if not isinstance(s, pystr):
3470        return s
3471
3472    fsencoding = sys.getfilesystemencoding() or "utf-8"
3473    return s.decode(fsencoding)
3474
3475
3476from renpy.editor import launch_editor # @UnusedImport
3477
3478
3479def get_image_load_log(age=None):
3480    """
3481    :doc: other
3482
3483    A generator that yields a log of image loading activity. For the last 100
3484    image loads, this returns:
3485
3486    * The time the image was loaded (in seconds since the epoch).
3487    * The filename of the image that was loaded.
3488    * A boolean that is true if the image was preloaded, and false if the
3489      game stalled to load it.
3490
3491    The entries are ordered from newest to oldest.
3492
3493    `age`
3494        If not None, only images that have been loaded in the past `age`
3495        seconds are included.
3496
3497    The image load log is only kept if config.developer = True.
3498    """
3499
3500    if age is not None:
3501        deadline = time.time() - age
3502    else:
3503        deadline = 0
3504
3505    for i in renpy.display.im.cache.load_log:
3506        if i[0] < deadline:
3507            break
3508
3509        yield i
3510
3511
3512def end_replay():
3513    """
3514    :doc: replay
3515
3516    If we're in a replay, ends the replay immediately. Otherwise, does
3517    nothing.
3518    """
3519
3520    if renpy.store._in_replay:
3521        raise renpy.game.EndReplay()
3522
3523
3524def save_persistent():
3525    """
3526    :doc: persistent
3527
3528    Saves the persistent data to disk.
3529    """
3530
3531    renpy.persistent.update(True)
3532
3533
3534def is_seen(ever=True):
3535    """
3536    :doc: other
3537
3538    Returns true if the current line has been seen by the player.
3539
3540    If `ever` is true, we check to see if the line has ever been seen by the
3541    player. If false, we check if the line has been seen in the current
3542    play-through.
3543    """
3544
3545    return renpy.game.context().seen_current(ever)
3546
3547
3548def get_mouse_pos():
3549    """
3550    :doc: other
3551
3552    Returns an (x, y) tuple giving the location of the mouse pointer or the
3553    current touch location. If the device does not support a mouse and is not
3554    currently being touched, x and y are numbers, but not meaningful.
3555    """
3556    return renpy.display.draw.get_mouse_pos()
3557
3558
3559def set_mouse_pos(x, y, duration=0):
3560    """
3561    :doc: other
3562
3563    Jump the mouse pointer to the location given by arguments x and y.
3564    If the device does not have a mouse pointer, this does nothing.
3565
3566    `duration`
3567        The time it will take to perform the move, in seconds.
3568        During this time, the mouse may be unresponsive.
3569    """
3570
3571    renpy.display.interface.set_mouse_pos(x, y, duration)
3572
3573
3574def set_autoreload(autoreload):
3575    """
3576    :doc: other
3577
3578    Sets the autoreload flag, which determines if the game will be
3579    automatically reloaded after file changes. Autoreload will not be
3580    fully enabled until the game is reloaded with :func:`renpy.utter_restart`.
3581    """
3582
3583    renpy.autoreload = autoreload
3584
3585
3586def get_autoreload():
3587    """
3588    :doc: other
3589
3590    Gets the autoreload flag.
3591    """
3592
3593    return renpy.autoreload
3594
3595
3596def count_dialogue_blocks():
3597    """
3598    :doc: other
3599
3600    Returns the number of dialogue blocks in the game's original language.
3601    """
3602
3603    return renpy.game.script.translator.count_translates()
3604
3605
3606def count_seen_dialogue_blocks():
3607    """
3608    :doc: other
3609
3610    Returns the number of dialogue blocks the user has seen in any play-through
3611    of the current game.
3612    """
3613
3614    return renpy.game.seen_translates_count
3615
3616
3617def count_newly_seen_dialogue_blocks():
3618    """
3619    :doc: other
3620
3621    Returns the number of dialogue blocks the user has seen for the first time
3622    during this session.
3623    """
3624
3625    return renpy.game.new_translates_count
3626
3627
3628def substitute(s, scope=None, translate=True):
3629    """
3630    :doc: other
3631
3632    Applies translation and new-style formatting to the string `s`.
3633
3634    `scope`
3635        If not None, a scope which is used in formatting, in addition to the
3636        default store.
3637
3638    `translate`
3639        Determines if translation occurs.
3640
3641    Returns the translated and formatted string.
3642    """
3643
3644    return renpy.substitutions.substitute(s, scope=scope, translate=translate)[0]
3645
3646
3647def munge(name, filename=None):
3648    """
3649    :doc: other
3650
3651    Munges `name`, which must begin with __.
3652
3653    `filename`
3654        The filename the name is munged into. If None, the name is munged
3655        into the filename containing the call to this function.
3656    """
3657
3658    if filename is None:
3659        filename = sys._getframe(1).f_code.co_filename
3660
3661    if not name.startswith("__"):
3662        return name
3663
3664    if name.endswith("__"):
3665        return name
3666
3667    return renpy.parser.munge_filename(filename) + name[2:]
3668
3669
3670def get_return_stack():
3671    """
3672    :doc: label
3673
3674    Returns a list giving the current return stack. The return stack is a
3675    list of statement names.
3676
3677    The statement names will be strings (for labels), or opaque tuples (for
3678    non-label statements).
3679    """
3680
3681    return renpy.game.context().get_return_stack()
3682
3683
3684def set_return_stack(stack):
3685    """
3686    :doc: label
3687
3688    Sets the current return stack. The return stack is a list of statement
3689    names.
3690
3691    Statement names may be strings (for labels) or opaque tuples (for
3692    non-label statements).
3693    """
3694
3695    renpy.game.context().set_return_stack(stack)
3696
3697
3698def invoke_in_thread(fn, *args, **kwargs):
3699    """
3700    :doc: other
3701
3702    Invokes the function `fn` in a background thread, passing it the
3703    provided arguments and keyword arguments. Restarts the interaction
3704    once the thread returns.
3705
3706    This function creates a daemon thread, which will be automatically
3707    stopped when Ren'Py is shutting down.
3708
3709    This thread is very limited in what it can do with the Ren'Py API.
3710    Changing store variables is allowed, as is calling the :func:`renpy.queue_event`
3711    function. Most other portions of the Ren'Py API are expected to be called from
3712    the main thread.
3713
3714    The primary use of this function is to place accesss to a web API in a second
3715    thread, and then update variables with the results of that call, by storing
3716    the result in variables and then relying on the interaction restart to cause
3717    screens to display those variables.
3718    """
3719
3720    def run():
3721        try:
3722            fn(*args, **kwargs)
3723        except:
3724            import traceback
3725            traceback.print_exc()
3726
3727        restart_interaction()
3728
3729    t = threading.Thread(target=run)
3730    t.daemon = True
3731    t.start()
3732
3733
3734def cancel_gesture():
3735    """
3736    :doc: gesture
3737
3738    Cancels the current gesture, preventing the gesture from being recognized.
3739    This should be called by displayables that have gesture-like behavior.
3740    """
3741
3742    renpy.display.gesture.recognizer.cancel() # @UndefinedVariable
3743
3744
3745def execute_default_statement(start=False):
3746    """
3747    :undocumented:
3748
3749    Executes the default statement.
3750    """
3751
3752    for i in renpy.ast.default_statements:
3753        i.set_default(start)
3754
3755
3756def write_log(s, *args):
3757    """
3758    :undocumented:
3759
3760    Writes to log.txt.
3761    """
3762
3763    renpy.display.log.write(s, *args)
3764
3765
3766def predicting():
3767    """
3768    :doc: screens
3769
3770    Returns true if Ren'Py is currently predicting the screen.
3771    """
3772
3773    return renpy.display.predict.predicting
3774
3775
3776def get_line_log():
3777    """
3778    :undocumented:
3779
3780    Returns the list of lines that have been shown since the last time
3781    :func:`renpy.clear_line_log` was called.
3782    """
3783
3784    return renpy.game.context().line_log[:]
3785
3786
3787def clear_line_log():
3788    """
3789    :undocumented:
3790
3791    Clears the line log.
3792    """
3793
3794    renpy.game.context().line_log = [ ]
3795
3796
3797def add_layer(layer, above=None, below=None, menu_clear=True):
3798    """
3799    :doc: other
3800
3801    Adds a new layer to the screen. If the layer already exists, this
3802    function does nothing.
3803
3804    One of `behind` or `above` must be given.
3805
3806    `layer`
3807        A string giving the name of the new layer to add.
3808
3809    `above`
3810        If not None, a string giving the name of a layer the new layer will
3811        be placed above.
3812
3813    `below`
3814        If not None, a string giving the name of a layer the new layer will
3815        be placed below.
3816
3817    `menu_clear`
3818        If true, this layer will be cleared when entering the game menu
3819        context, and restored when leaving the
3820    """
3821
3822    layers = renpy.config.layers
3823
3824    if layer in renpy.config.layers:
3825        return
3826
3827    if (above is not None) and (below is not None):
3828        raise Exception("The above and below arguments to renpy.add_layer are mutually exclusive.")
3829
3830    elif above is not None:
3831        try:
3832            index = layers.index(above) + 1
3833        except ValueError:
3834            raise Exception("Layer '%s' does not exist." % above)
3835
3836    elif below is not None:
3837        try:
3838            index = layers.index(below)
3839        except ValueError:
3840            raise Exception("Layer '%s' does not exist." % below)
3841
3842    else:
3843        raise Exception("The renpy.add_layer function requires either the above or below argument.")
3844
3845    layers.insert(index, layer)
3846
3847    if menu_clear:
3848        renpy.config.menu_clear_layers.append(layer) # @UndefinedVariable
3849
3850
3851def maximum_framerate(t):
3852    """
3853    :doc: other
3854
3855    Forces Ren'Py to draw the screen at the maximum framerate for `t` seconds.
3856    If `t` is None, cancels the maximum framerate request.
3857    """
3858
3859    if renpy.display.interface is not None:
3860        renpy.display.interface.maximum_framerate(t)
3861    else:
3862        if t is None:
3863            renpy.display.core.initial_maximum_framerate = 0
3864        else:
3865            renpy.display.core.initial_maximum_framerate = max(renpy.display.core.initial_maximum_framerate, t)
3866
3867
3868def is_start_interact():
3869    """
3870    :doc: other
3871
3872    Returns true if restart_interaction has not been called during the current
3873    interaction. This can be used to determine if the interaction is just being
3874    started, or has been restarted.
3875    """
3876
3877    return renpy.display.interface.start_interact
3878
3879
3880def play(filename, channel=None, **kwargs):
3881    """
3882    :doc: audio
3883
3884    Plays a sound effect. If `channel` is None, it defaults to
3885    :var:`config.play_channel`. This is used to play sounds defined in
3886    styles, :propref:`hover_sound` and :propref:`activate_sound`.
3887    """
3888
3889    if filename is None:
3890        return
3891
3892    if channel is None:
3893        channel = renpy.config.play_channel
3894
3895    renpy.audio.music.play(filename, channel=channel, loop=False, **kwargs)
3896
3897
3898def get_editable_input_value():
3899    """
3900    :undocumented:
3901
3902    Returns the current input value, and a flag that is true if it is editable.
3903    and false otherwise.
3904    """
3905
3906    return renpy.display.behavior.current_input_value, renpy.display.behavior.input_value_active
3907
3908
3909def set_editable_input_value(input_value, editable):
3910    """
3911    :undocumented:
3912
3913    Sets the currently active input value, and if it should be marked as
3914    editable.
3915    """
3916
3917    renpy.display.behavior.current_input_value = input_value
3918    renpy.display.behavior.input_value_active = editable
3919
3920
3921def get_refresh_rate(precision=5):
3922    """
3923    :doc: other
3924
3925    Returns the refresh rate of the current screen, as a floating-point
3926    number of frames per second.
3927
3928    `precision`
3929        The raw data Ren'Py gets is number of frames per second, rounded down.
3930        This means that a monitor that runs at 59.95 frames per second will
3931        be reported at 59 fps. The precision argument reduces the precision
3932        of this reading, such that the only valid readings are multiples of
3933        the precision.
3934
3935        Since all monitor framerates tend to be multiples of 5 (25, 30, 60,
3936        75, and 120), this likely will improve accuracy. Setting precision
3937        to 1 disables this.
3938    """
3939
3940    precision *= 1.0
3941
3942    info = renpy.display.get_info()
3943    rv = info.refresh_rate
3944    rv = round(rv / precision) * precision
3945
3946    return rv
3947
3948
3949def get_identifier_checkpoints(identifier):
3950    """
3951    :doc: rollback
3952
3953    Given a rollback_identifier from a HistoryEntry object, returns the number
3954    of checkpoints that need to be passed to :func:`renpy.rollback` to reach
3955    that identifier. Returns None of the identifier is not in the rollback
3956    history.
3957    """
3958
3959    return renpy.game.log.get_identifier_checkpoints(identifier)
3960
3961
3962def get_adjustment(bar_value):
3963    """
3964    :doc: other
3965
3966    Given `bar_value`, a  :class:`BarValue`, returns the :func:`ui.adjustment`
3967    if uses. The adjustment has the following to attributes defined:
3968
3969    .. attribute:: value
3970
3971        The current value of the bar.
3972
3973    .. attribute:: range
3974
3975        The current range of the bar.
3976    """
3977
3978    return bar_value.get_adjustment()
3979
3980
3981def get_skipping():
3982    """
3983    :doc: other
3984
3985    Returns "slow" if the Ren'Py is skipping, "fast" if Ren'Py is fast skipping,
3986    and None if it is not skipping.
3987    """
3988
3989    return renpy.config.skipping
3990
3991
3992def get_texture_size():
3993    """
3994    :undocumented:
3995
3996    Returns the number of bytes of memory locked up in OpenGL textures and the
3997    number of textures that are defined.
3998    """
3999
4000    return renpy.display.draw.get_texture_size()
4001
4002
4003old_battery = False
4004
4005
4006def get_on_battery():
4007    """
4008    :other:
4009
4010    Returns True if Ren'Py is running on a device that is powered by an internal
4011    battery, or False if the device is being charged by some external source.
4012    """
4013
4014    global old_battery
4015
4016    pi = pygame_sdl2.power.get_power_info() # @UndefinedVariable
4017
4018    if pi.state == pygame_sdl2.POWERSTATE_UNKNOWN: # @UndefinedVariable
4019        return old_battery
4020    elif pi.state == pygame_sdl2.POWERSTATE_ON_BATTERY: # @UndefinedVariable
4021        old_battery = True
4022        return True
4023    else:
4024        old_battery = False
4025        return False
4026
4027
4028def get_say_image_tag():
4029    """
4030    :doc: image_func
4031
4032    Returns the tag corresponding to the currently speaking character (the
4033    `image` argument given to that character). Returns None if no character
4034    is speaking or the current speaking character does not have a corresponding
4035    image tag.
4036    """
4037
4038    if renpy.store._side_image_attributes is None:
4039        return None
4040
4041    return renpy.store._side_image_attributes[0]
4042
4043
4044def is_skipping():
4045    """
4046    :doc: other
4047
4048    Returns True if Ren'Py is currently skipping (in fast or slow skip mode),
4049    or False otherwise.
4050    """
4051
4052    return not not renpy.config.skipping
4053
4054
4055def is_init_phase():
4056    """
4057    :doc: other
4058
4059    Returns True if Ren'Py is currently executing init code, or False otherwise.
4060    """
4061
4062    return renpy.game.context().init_phase
4063
4064
4065def add_to_all_stores(name, value):
4066    """
4067    :doc: other
4068
4069    Adds the `value` by the `name` to all creator defined namespaces. If the name
4070    already exist in that namespace - do nothing for it.
4071
4072    This function may only be run from inside an init block. It is an
4073    error to run this function once the game has started.
4074    """
4075
4076    if not is_init_phase():
4077        raise Exception("add_to_all_stores is only allowed in init code.")
4078
4079    for _k, ns in renpy.python.store_dicts.items():
4080
4081        if name not in ns:
4082            ns[name] = value
4083
4084
4085def get_zorder_list(layer):
4086    """
4087    :doc: image_func
4088
4089    Returns a list of (tag, zorder) pairs for `layer`.
4090    """
4091
4092    return renpy.display.core.scene_lists().get_zorder_list(layer)
4093
4094
4095def change_zorder(layer, tag, zorder):
4096    """
4097    :doc: image_func
4098
4099    Changes the zorder of `tag` on `layer` to `zorder`.
4100    """
4101
4102    return renpy.display.core.scene_lists().change_zorder(layer, tag, zorder)
4103
4104
4105sdl_dll = False
4106
4107
4108def get_sdl_dll():
4109    """
4110    :doc: sdl
4111
4112    This returns a ctypes.cdll object that refers to the library that contains
4113    the instance of SDL2 that Ren'Py is using.
4114
4115    If this can not be done, None is returned.
4116    """
4117
4118    global sdl_dll
4119
4120    if sdl_dll is not False:
4121        return sdl_dll
4122
4123    try:
4124
4125        DLLS = [ None, "librenpython.dll", "librenpython.dylib", "librenpython.so", "SDL2.dll", "libSDL2.dylib", "libSDL2-2.0.so.0" ]
4126
4127        import ctypes
4128
4129        for i in DLLS:
4130            try:
4131                # Look for the DLL.
4132                dll = ctypes.cdll[i]
4133                # See if it has SDL_GetError..
4134                dll.SDL_GetError
4135            except:
4136                continue
4137
4138            sdl_dll = dll
4139            return dll
4140
4141    except:
4142        pass
4143
4144    sdl_dll = None
4145    return None
4146
4147
4148def get_sdl_window_pointer():
4149    """
4150    :doc: sdl
4151
4152    Returns a pointer (of type ctypes.c_void_p) to the main window, or None
4153    if the main window is not displayed, or some other problem occurs.
4154    """
4155
4156    try:
4157        window = pygame_sdl2.display.get_window()
4158
4159        if window is None:
4160            return
4161
4162        return window.get_sdl_window_pointer()
4163
4164    except:
4165        return None
4166
4167
4168def is_mouse_visible():
4169    """
4170    :doc: other
4171
4172    Returns True if the mouse cursor is visible, False otherwise.
4173    """
4174
4175    if not renpy.display.interface:
4176        return True
4177
4178    if not renpy.display.interface.mouse_focused:
4179        return False
4180
4181    return renpy.display.interface.is_mouse_visible()
4182
4183
4184def get_mouse_name(interaction=False):
4185    """
4186    :doc: other
4187
4188    Returns the name of the mouse that should be shown.
4189
4190
4191    `interaction`
4192        If true, get a mouse name that is based on the type of interaction
4193        occuring. (This is rarely useful.)
4194    """
4195
4196    if not renpy.display.interface:
4197        return 'default'
4198
4199    return renpy.display.interface.get_mouse_name(interaction=interaction)
4200
4201
4202def set_focus(screen, id, layer="screens"): # @ReservedAssignment
4203    """
4204    :doc: screens
4205
4206    This attempts to focus the displayable with `id` in the screen `screen`.
4207    Focusing will fail if the displayable isn't found, the window isn't
4208    focused, or something else is grabbing focus.
4209
4210    The focus may change if the mouse moves, even slightly, after this call
4211    is processed.
4212    """
4213
4214    renpy.display.focus.override = (screen, id, layer)
4215    renpy.display.interface.last_event = None
4216    restart_interaction()
4217
4218
4219def check_permission(permission):
4220    """
4221    :doc: android_permission
4222
4223    Checks to see if an Android permission has been granted to this application.
4224
4225    `permission`
4226        A string giving the name of the permission, for example, "android.permission.WRITE_EXTERNAL_STORAGE".
4227
4228    Returns true if the permission has been granted, false if it has not or if called on
4229    a non-Android platform.
4230    """
4231
4232    if not renpy.android:
4233        return False
4234
4235    from jnius import autoclass
4236    PythonSDLActivity = autoclass("org.renpy.android.PythonSDLActivity")
4237    activity = PythonSDLActivity.mActivity
4238
4239    try:
4240        return activity.checkSelfPermission(permission) == 0 # PackageManager.PERMISSION_GRANTED
4241    except:
4242        return False
4243
4244
4245def request_permission(permission):
4246    """
4247    :doc: android_permission
4248
4249    Asks Android to grant a permission to this application. The user may be
4250    prompted to grant the permission.
4251
4252    `permission`
4253        A string giving the name of the permission, for example, "android.permission.WRITE_EXTERNAL_STORAGE".
4254
4255    Returns true if the permission has been granted, false if not or if called on a
4256    non-Android platform.
4257    """
4258
4259    if not renpy.android:
4260        return False
4261
4262    return get_sdl_dll().SDL_AndroidRequestPermission(permission.encode("utf-8"))
4263