CYLGame package

Submodules

CYLGame.Comp module

class CYLGame.Comp.MultiplayerComp(bots, room_size, default_bot_class, run_factor=10)[source]

Bases: object

static make_bot(gamedb, compiler, token, debug=False)[source]
next()[source]
static sim_comp(c_token, gamedb, game, compiler, save_games=False, debug=False)[source]
static sim_multiplayer(s_token, gamedb, game, compiler, save_games=False, debug=False)[source]
class CYLGame.Comp.MultiplayerCompRunner(interval, gamedb, game, compiler, debug=False)[source]

Bases: multiprocessing.context.Process

run()[source]

Method to be run in sub-process; can be overridden in sub-class

stop()[source]
class CYLGame.Comp.Ranking(bots)[source]

Bases: object

add_rank(standing, bot)[source]
class CYLGame.Comp.RollingMultiplayerComp(room_size, default_bot_class, rolling_n)[source]

Bases: object

add_bot(bot, gamedb)[source]
add_bot_if_needed(bot, gamedb)[source]
next()[source]
save_rolling_scores(gamedb)[source]
class CYLGame.Comp.RollingMultiplayerCompRunner(interval, gamedb, game, compiler, rolling_n=100, batch_size=4, debug=False)[source]

Bases: multiprocessing.context.Process

clean_up_old_games()[source]
make_bot(token)[source]
run()[source]

Method to be run in sub-process; can be overridden in sub-class

stop()[source]
CYLGame.Comp.avg(scores)[source]
CYLGame.Comp.create_room(gamedb, bot, compiler, size)[source]
CYLGame.Comp.sim_competition(compiler, game, gamedb, token, runs, ncores=None, debug=False, score_func=<function avg>)[source]
Parameters
  • compiler

  • game

  • gamedb

  • token

  • runs

  • ncores – If None will default to the number of all available cores.

  • debug

  • score_func

Returns:

CYLGame.Comp.sim_prog_for_score(game, compiler, code, options, seed, debug=True)[source]

CYLGame.Database module

class CYLGame.Database.GameDB(root_dir)[source]

Bases: object

This is the database that stores all persisted data. This database is a file based DB.

/ => Root game directory /data => Should be named something like “users”. This stores user related data. /data/TOKEN => A directory containing data for the user with the token TOKEN. /data/TOKEN/avg_score => File containing a single float representing the average score for the user. /data/TOKEN/name => File containing the name for the user. /data/TOKEN/code => Directory containing all code submitted by the user. /data/TOKEN/code/CTIME_HASH => The code submitted or played at CTIME. /data/TOKEN/code/CTIME_HASH/code.lp /data/TOKEN/code/CTIME_HASH/options.mp.gz /data/TOKEN/games => A directory related games. /data/TOKEN/games/GTOKEN => An empty file representing that the users bot was used in game GTOKEN. /games => Stores game related data. /schools => Stores school related data. /competitions => Stores competition related data. /www => Stores static and template files for the server. This is a cache that is deleted and

recreated on each restart.

ACTIVE_CODE_KEY = 'active_code'
CODE_DIR = 'code'
CODE_FILENAME = 'code.lp'
OPTIONS_FILENAME = 'options.mp.gz'
TOKEN_LEN = 8
add_game_to_comp(ctoken, gtoken)[source]
add_new_competition(name='', _token=None)[source]
add_new_game(frames=None, per_player_data=None, player_tokens=None)[source]
add_new_school(name='', _token=None)[source]
add_school_to_comp(ctoken, stoken)[source]
delete_game(gtoken)[source]
get_active_code_and_options(token)[source]
get_all_comp_tokens()[source]
get_all_game_tokens()[source]
get_avg_score(token, default_value=None)[source]
get_code_by_hash(code_hash_prefix)[source]

Returns the code for the code hash or a list of hashes if the code hash prefix matches multiple codes.

get_comp_avg_score(ctoken, stoken)[source]
get_comp_code(ctoken, stoken)[source]
get_comp_tokens()[source]
get_comps_for_token(utoken)[source]
get_ctime_for_game(token)[source]
get_exception(token)[source]
get_exception_tokens()[source]
get_game_frames(gtoken)[source]
get_games_for_token(token)[source]
get_name(token)[source]
get_new_token(school_tk, _token=None)[source]
get_player_game_data(gtoken, token)[source]
get_players_for_game(gtoken)[source]
get_school_for_token(token)[source]
get_school_tokens()[source]
get_schools_in_comp(ctoken)[source]
get_tokens_for_school(school_tk)[source]
get_value(token, key, default_value=None)[source]
is_comp_token(token)[source]
is_exception_token(token)[source]
is_game_token(gtoken)[source]
is_school_token(token)[source]
is_user_token(token)[source]
remove_game_from_comp(ctoken, gtoken)[source]
replace_games_in_comp(ctoken, new_gtokens, cleanup=True)[source]
save_avg_score(token, score)[source]

Save a user’s average score.

Parameters
  • token (str) – The user’s token.

  • score (int) – The user’s average score.

save_code(token, code, options=None, set_as_active=True)[source]

Save a user’s code under their token.

Parameters
  • token (str) – The user’s token.

  • code (str) – The user’s code.

  • options (json-able object) – The user’s options.

  • set_as_active (bool) – Whether to set the saved code as the active code for the token.

save_exception(exception_report)[source]
save_game_frames(gtoken, frames)[source]
save_name(token, name)[source]

Save a user’s name under their token.

Parameters
  • token (str) – The user’s token.

  • name (str) – The user’s name.

save_value(token, key, value)[source]
Save a key value pair to a tokens directory. If a value has been saved under the same key it will be

overwritten by the new value passed in. The value can be looked up using the get_value function.

Parameters
  • token (str) – Any valid token.

  • key (str) – The key to store the value under.

  • value (str or int or float) – The value to be stored.

set_comp_avg_score(ctoken, stoken, score)[source]
set_comp_school_code(ctoken, stoken, code)[source]
set_game_player(gtoken, token, data=None)[source]
class CYLGame.Database.WWWCache(root_dir)[source]

Bases: object

safe_replace_cache(www_dir)[source]

This function safely replaces the current www cached data with the data found in www_dir

property static_dir
property template_dir
CYLGame.Database.read_json(filename)[source]
CYLGame.Database.write_json(o, filename)[source]

CYLGame.Display module

class CYLGame.Display.CharSet(image_filepath: pathlib.Path, char_width: int, char_height: int, char_rows: int, char_columns: int)[source]

Bases: CYLGame.Sprite.SpriteSet

char_columns: int
char_height: int
char_rows: int
char_size_to_pix(size)[source]
char_width: int
create_char_img(char)[source]
classmethod from_sprite_set(sprite_set)[source]
get_img(char)[source]
image_filepath: pathlib.Path
pix_size_to_char(size)[source]
class CYLGame.Display.Display(width, height, title=None)[source]

Bases: object

get_keys()[source]

Gets the keys that were press since last time you called this function.

Returns

Key

get_size()[source]
update(frame_buffer)[source]

Updates the display with the buffer given.

Parameters

frame_buffer (FrameBuffer) – The buffer to use when redrawing the screen.

class CYLGame.Display.PyGameDisplay(width, height, title=None)[source]

Bases: CYLGame.Display.Display

get_keys()[source]

Gets the keys that were press since last time you called this function.

Returns

Key

update(frame_buffer)[source]

Updates the display with the buffer given.

Parameters

frame_buffer (FrameBuffer) – The buffer to use when redrawing the screen.

CYLGame.Display.get_clock()[source]

CYLGame.Frame module

class CYLGame.Frame.FrameBuffer[source]

Bases: object

class CYLGame.Frame.GameFrame[source]

Bases: CYLGame.Frame.FrameBuffer

draw_char(c, x, y, height, width)[source]
draw_crater(x, y, rotation, color)[source]
draw_sensors(x, y, rotation, turret, color, sensors)[source]
draw_tank(x, y, rotation, turret, fire, led, color)[source]
get_obj_array()[source]
class CYLGame.Frame.GridFrameBuffer(width, height, charset=None, init_value='\x00')[source]

Bases: CYLGame.Frame.FrameBuffer

draw_to_surface(surface)[source]
dump()[source]
Returns

a copy of the frame buffer’s grid

Return type

List[List[int]]

classmethod from_string_array(frame)[source]
set(x, y, char)[source]
Parameters
  • x (int) –

  • y (int) –

  • char (int) – The id of the char.

CYLGame.Frame.grid_char_to_int(c: Union[int, str, CYLGame.Sprite.Char]) int[source]

CYLGame.Game module

class CYLGame.Game.Game(random)[source]

Bases: object

GAME_TITLE = ''
MULTIPLAYER = False
OPTIONS: Optional[str] = None
SCREEN_HEIGHT = 0
SCREEN_WIDTH = 0
WEBONLY = True
create_new_player(prog)[source]

This creates n new objects that inherits from the Player class.

Returns

n new objects that inherit from the Player class with the given program.

static default_prog_for_bot(language)[source]
static default_prog_for_computer()[source]

This method is only for multi-player games to implement. :returns: type[Prog]

do_turn()[source]
get_debug_vars()[source]
get_frame()[source]
static get_intro()[source]
static get_move_consts()[source]
static get_number_of_players()[source]

This method is only for multi-player games to implement. :returns: The number of players needed to play the game. :rtype: int

init_board()[source]
is_running()[source]

This is how the game runner knows if the game is over.

Returns

True if the game should still be play. False otherwise

Return type

bool

start_game()[source]
class CYLGame.Game.GameLanguage[source]

Bases: object

LITTLEPY = 0
static get_language_description(language)[source]
class CYLGame.Game.GameRunner(game_class: Type[CYLGame.Game.Game])[source]

Bases: object

init_game(seed: int) CYLGame.Game.PlayGameState[source]
static move_game(state: CYLGame.Game.PlayGameState, move: str) CYLGame.Game.PlayGameState[source]
run(room, playback=True)[source]

The the game.

Parameters
  • room (Room) – The room to play.

  • playback (bool) – if True save the playback.

Returns

Return type

Room

run_for_avg_score(room, times=1, func=<function scorer.<locals>.wrapped>)[source]

Runs the given game keeping only the scores.

Parameters

times (int) – The number of times to run to get the average score.

Returns

The return value the average score for the times runs.

run_with_local_display(seed=None)[source]

Will run the game for a user.

Returns:

class CYLGame.Game.GridGame(random)[source]

Bases: CYLGame.Game.Game

CHAR_HEIGHT = 8
CHAR_SET = '/home/runner/work/CYLGame/CYLGame/CYLGame/data/fonts/terminal8x8_gs_ro.png'
CHAR_WIDTH = 8
GAME_TITLE = ''
SCREEN_HEIGHT = 25
SCREEN_WIDTH = 80
WEBONLY = False
create_new_player(prog)[source]

TODO: write this

static default_prog_for_bot(language)[source]
do_turn()[source]

This function should read the new state of all the players and react to them.

draw_screen(frame_buffer)[source]

WARNING: There MUST NOT be any game logic in this function since it isn’t called when simulating the game during the competitions.

get_frame()[source]
static get_intro()[source]
static get_move_consts()[source]
get_score()[source]

This is the game runner gets the ending or mid-game score

Returns

The current score.

Return type

int

classmethod get_sprite_set() CYLGame.Sprite.SpriteSet[source]
get_vars(player)[source]

TODO: write this

is_running()[source]

This is how the game runner knows if the game is over.

Returns

True if the game should still be play. False otherwise

Return type

bool

class CYLGame.Game.NonGridGame(random)[source]

Bases: CYLGame.Game.Game

WEBONLY = True
get_vars_for_bot()[source]
read_bot_state(state)[source]
class CYLGame.Game.PlayGameState(game: CYLGame.Game.Game, computer_players: List[CYLGame.Player.Player], human_player: CYLGame.Player.Player, human_prog: CYLGame.Player.UserProg, seed: int, moves: str, frame: Optional[List[List[int]]])[source]

Bases: object

computer_players: List[CYLGame.Player.Player]
frame: Optional[List[List[int]]]
game: CYLGame.Game.Game
human_player: CYLGame.Player.Player
human_prog: CYLGame.Player.UserProg
moves: str
seed: int
CYLGame.Game.average(a, b=None)[source]
CYLGame.Game.data_file(filename)[source]
CYLGame.Game.run(game_class, avg_game_func=<function scorer.<locals>.wrapped>)[source]
CYLGame.Game.scorer(func)[source]

This function is a decorator for a scoring function. This is hack a to get around self being passed as the first argument to the scoring function.

CYLGame.Panels module

class CYLGame.Panels.Map(width, height, default_char=' ')[source]

Bases: object

char_to_ps: This is a dictionary which has a character for the keys and the value for the key is a set of all the

positions where that char is located.

p_to_char: The is a dictionary which has a position(tuple with two elements: x and y) as a key and the current

ColoredChar as the value.

add(char: Union[str, int, CYLGame.Sprite.Char], pos)[source]
get_all_pos(char)[source]
get_char_at(pos)[source]
get_diff()[source]
get_x_y_dist_to_foo(pos, foo, wrapping=False, diagonal_moving=False, default=None)[source]
in_bounds(pos)[source]
rm_char(pos)[source]
shift_all(offset, wrap_x=False, wrap_y=False)[source]
wrap(pos, wrap_x=False, wrap_y=False)[source]
class CYLGame.Panels.MapPanel(x, y, w, h, default_char=' ', border=<CYLGame.Panels.PanelBorder object>, padding=<CYLGame.Panels.PanelPadding object>)[source]

Bases: CYLGame.Panels.Panel

first_draw(frame_buffer)[source]
redraw(frame_buffer)[source]
class CYLGame.Panels.MessagePanel(x, y, w, h, default_char=' ', border=<CYLGame.Panels.PanelBorder object>, padding=<CYLGame.Panels.PanelPadding object>)[source]

Bases: CYLGame.Panels.Panel

This panel contains messages to be displayed to the user. It acts as a scrolling text log. This means that the first message is display on the first line and some on till you have enough messages to fill the height. Then the next message added will push all the other messages up and the first message will be discarded.

Example

A MessagePanel with height of 3. Add messages “A”, “B” and “C”. It will display like the following:

A B C

Add message “D” and it will display like the following:

B C D

Note

The following is deprecated: >>> m = MessagePanel() >>> m += [“Hi”] You should do this instead: >>> m = MessagePanel() >>> m.add(“Hi”)

add(messages)[source]
clear()[source]
get_current_messages()[source]
redraw(frame_buffer)[source]
class CYLGame.Panels.Panel(x, y, w, h, background_char=' ', border=<CYLGame.Panels.PanelBorder object>, padding=<CYLGame.Panels.PanelPadding object>)[source]

Bases: CYLGame.Panels.Map

draw_char(char, pos, frame_buffer)[source]
redraw(frame_buffer)[source]
class CYLGame.Panels.PanelBorder(sides=0, char=None)[source]

Bases: object

BOTTOM = 8
DEFAULT_CHARS = {1: 'Ä', 2: '³', 3: '¿', 4: '³', 5: 'Ú', 8: 'Ä', 10: 'Ù', 12: 'À'}
LEFT = 4
RIGHT = 2
TOP = 1
static create(top=False, bottom=False, right=False, left=False, top_right=False, top_left=False, bottom_right=False, bottom_left=False)[source]

Use this method for an easy way to create nice borders. Set any side to true to create a border with the default characters. You can also set any side to a character which will create a border with that character instead. In order for the corners (top_right, top_left, …) to be rendered both of their respective sides must be set to True or a char.

Ex. >>> PanelBorder.create(top=True) # This will create a top border with the default char

>>> PanelBorder.create(top='$')  # This will create a top border of '$'s.
>>> PanelBorder.create(top='=', left='!', top_left='?')  # This will create a border looking like some thing below.
    ?====
    !
    !
has_side(side)[source]
class CYLGame.Panels.PanelPadding(sides=0, size=0)[source]

Bases: object

BOTTOM = 8
DEFAULT_SIZE = 0
LEFT = 4
RIGHT = 2
TOP = 1
static create(top=False, bottom=False, right=False, left=False)[source]
has_side(side)[source]
class CYLGame.Panels.StatusPanel(x, y, w, h, default_char=' ', border=<CYLGame.Panels.PanelBorder object>, padding=<CYLGame.Panels.PanelPadding object>)[source]

Bases: CYLGame.Panels.MessagePanel

get_current_messages()[source]
CYLGame.Panels.to_char(c: Union[str, int, CYLGame.Sprite.Char]) str[source]
CYLGame.Panels.to_coord(p: Union[Tuple[int, int], List[int]]) Tuple[int, int][source]

CYLGame.Player module

class CYLGame.Player.DefaultGridPlayer(prog: CYLGame.Player.Prog, bot_consts: CYLGame.structures.const_mapping.ConstMapping)[source]

Bases: CYLGame.Player.Player

Make sure that all bot_vars are updated in game.do_turn

get_state() dict[source]
update_state(state: dict)[source]
class CYLGame.Player.LittlePythonProg(prog: littlepython.interpreter.LPProg, options: dict, token: Optional[str] = None, name: Optional[str] = None, code_hash: Optional[str] = None)[source]

Bases: CYLGame.Player.Prog

run(*args, **kargs)[source]
class CYLGame.Player.Player(prog: CYLGame.Player.Prog)[source]

Bases: abc.ABC

abstract get_state() dict[source]
run_turn(random: random.Random, max_ops: int = 1000000)[source]
abstract update_state(new_state: dict)[source]
class CYLGame.Player.Prog(options: dict, token: Optional[str] = None, name: Optional[str] = None, code_hash: Optional[str] = None)[source]

Bases: abc.ABC

abstract run(state: dict, max_op_count: int = - 1, random=None)[source]
class CYLGame.Player.Room(bots: Optional[List[CYLGame.Player.Prog]] = None, seed=None)[source]

Bases: object

property rand_seeded

A randomly seeded room with the same bots.

save(gamedb)[source]

The method saves the game data to a new game. Note: this room must be run before calling this function.

Parameters

gamedb (GameDB) – The current game database.

Returns: The gtoken of the newly created game.

class CYLGame.Player.UserProg[source]

Bases: CYLGame.Player.Prog

run(*args, **kwargs)[source]

CYLGame.SensorGame module

class CYLGame.SensorGame.SensorGame(random)[source]

Bases: CYLGame.Game.NonGridGame

NONGRID = True
OPTIONS: Optional[str] = 'sensors'
WEBONLY = True
do_sensors()[source]
class CYLGame.SensorGame.SensorPlayer(prog: CYLGame.Player.Prog)[source]

Bases: CYLGame.Player.Player

add_sensor(_range, angle, width, turret)[source]

Adds a sensor to this player. _range: integer [0, 100], the distance that the sensor travels angle: integer [0, 360], the direction in degrees the sensor points width: integer [0, 360], the width in degrees of the sensor turret: bool, if True, the angle is relative to the turret’s angle, otherwise angle is relative to the tank’s angle

sensor_calc(other, dist_sq, vector, tank_sensor_range)[source]

See if other is in any of our sensors.

class CYLGame.SensorGame.SensorSanitizers[source]

Bases: object

color_re = re.compile('#[0-9A-Fa-f]{6}')
static san_angle(a)[source]
static san_color(c)[source]
static san_range(r)[source]
static san_turret(t)[source]
static san_width(w)[source]
CYLGame.SensorGame.compute_vector(start, end, screen_width, screen_height)[source]

Computes the vector and distance between two objects, start and end. start and end must have a position attribute which is a list/tuple of the x and y coord.

CYLGame.SensorGame.deg2rad(deg)[source]
CYLGame.SensorGame.dprint(string)[source]
CYLGame.SensorGame.rad2deg(rad)[source]
CYLGame.SensorGame.rotate_point(angle, point)[source]

CYLGame.Server module

class CYLGame.Server.GameServer[source]

Bases: flask_classful.FlaskView

avg_game_count = None
before_request(name, **kwarg)[source]
charset = None
check_token()[source]
comp_scoreboards()[source]
compression = None
game = None
gamedb = None
get_game_data(gtoken)[source]
get_player()[source]
get_player_game_data(gtoken, token)[source]
host = None
index()[source]
language = None
load_code()[source]
play()[source]
play_game_cache: cachetools.LRUCache
port = None
route_base = '/'
save_code()[source]
scoreboard()[source]
classmethod serve(game, host='', port=5000, compression=False, language=0, avg_game_count=10, multiplayer_scoring_interval=20, num_of_threads=None, game_data_path='temp_game', avg_game_func=<function scorer.<locals>.wrapped>, debug=False, reuse_addr=None, play_cache_size=64, error_log_file='{dbfile}/log/error.log', debug_log_file='{dbfile}/log/debug.log')[source]
sim()[source]
sim_avg()[source]
CYLGame.Server.find_name_from_code(code)[source]
CYLGame.Server.get_public_ip()[source]
CYLGame.Server.serve(game, host='', port=5000, compression=False, language=0, avg_game_count=10, multiplayer_scoring_interval=20, num_of_threads=None, game_data_path='temp_game', avg_game_func=<function scorer.<locals>.wrapped>, debug=False, reuse_addr=None, play_cache_size=64, error_log_file='{dbfile}/log/error.log', debug_log_file='{dbfile}/log/debug.log')

CYLGame.Utils module

class CYLGame.Utils.OnlineMean(i=0, mean=0, roll_after_n=- 1)[source]

Bases: object

add(n)[source]
property floored_mean
rounded_mean(places=2)[source]
CYLGame.Utils.choose(n, k)[source]
CYLGame.Utils.decrypt_token_list(tokens, key)[source]
CYLGame.Utils.deprecated(message='')[source]
CYLGame.Utils.encrypt_token_list(tokens, key)[source]
CYLGame.Utils.hash_stream(fp)[source]
CYLGame.Utils.hash_string(s, encoding='utf8')[source]
CYLGame.Utils.int2base(x, base)[source]

This function converts an int to a str using a specific base.

Note: This function was created to support weird bases that don’t already have a builtin method. So if you want to

convert ints to base 2, 8, 16 it is better to use bin, oct, hex method respectively.

CYLGame.Utils.prefix_filename(p: pathlib.Path, prefix: str)[source]

CYLGame.version module

Module contents