add synchrod

This commit is contained in:
Pavel 2021-11-08 18:43:06 +01:00
parent 058e219021
commit ec19e4a218
7 changed files with 1245 additions and 0 deletions

12
synchrod/README Normal file
View File

@ -0,0 +1,12 @@
This is a copy of the Python scripts for the TI-Planet and Planete Casio
back to school 2021 contest.
The original code can be found at:
https://tiplanet.org/forum/viewtopic.php?f=49&t=25200
The demonstration script can be executed with the following commands:
g++ -O3 -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` astar.cpp -o astar`python3-config --extension-suffix`
python3 ia.py

118
synchrod/astar.cpp Normal file
View File

@ -0,0 +1,118 @@
/*
compilation command:
g++ -O3 -shared -std=c++11 -fPIC `python3 -m pybind11 --includes` astar.cpp -o astar`python3-config --extension-suffix`
*/
#include <algorithm>
#include <vector>
#include <queue>
#include <unordered_map>
#include <pybind11/pybind11.h>
#include <pybind11/stl.h>
#define MAX(a,b) (((a)>(b))?(a):(b))
namespace py = pybind11;
using namespace std;
int deltas[4] = {-16, 16, -1, 1};
struct result
{
double cost;
int players;
};
struct result cost(const vector<double> &t, int players, int exits, int m, int l)
{
int i, n, dn, p, e, mask;
double c, v;
struct result r;
p = players;
dn = deltas[m];
c = 1;
for(i = 0; i < 4; ++i)
{
n = p >> i * 8 & 0xff;
e = exits >> i * 8 & 0xff;
if(n == e) continue;
n += dn;
v = t[n + i * l];
if(v < 0) continue;
mask = 0xff << i * 8;
p = (p & ~mask) | (n << i * 8);
c += v;
}
r.cost = c;
r.players = p;
return r;
}
double heuristic(int u, int d)
{
int result, dx[4], i;
for(i = 0; i < 4; ++i)
{
dx[i] = abs(u >> i * 8 & 0xff) % 16 - abs(d >> i * 8 & 0xff) % 16 ;
}
return MAX(dx[0], dx[2]) + MAX(dx[1], dx[3]);
}
vector<int> astar(const vector<double> &t, int s, int d, int l)
{
int m, n, u;
double c, cu;
struct result r;
vector<int> path;
typedef pair<double, int> element;
priority_queue<element, vector<element>, greater<element> > q;
unordered_map<int, int> prev, move;
unordered_map<int, double> dist;
q.emplace(0, s);
prev[s] = s;
dist[s] = 0;
move[s] = 0;
while(!q.empty())
{
u = q.top().second;
q.pop();
if(u == d) break;
cu = dist[u];
for(m = 0; m < 4; ++m)
{
r = cost(t, u, d, m, l);
c = r.cost;
n = r.players;
if(u == n) continue;
c += cu;
if(dist.find(n) == dist.end() || c < dist[n])
{
q.emplace(c + heuristic(n, d), n);
prev[n] = u;
dist[n] = c;
move[n] = m;
}
}
}
if(u == d)
{
while(u != s)
{
path.push_back(move[u]);
u = prev[u];
}
reverse(path.begin(), path.end());
}
return path;
}
PYBIND11_MODULE(astar, m)
{
m.def("astar", &astar, "");
}

54
synchrod/ia.py Normal file
View File

@ -0,0 +1,54 @@
from synchrod import *
from astar import astar
def convert(board):
t = []
for i in range(4):
for c in board:
if c == WALL or (is_a(c, EXIT) and c != EXIT + i): v = -1
elif c == EXIT + i or not affects(c, i): v = 0
elif is_a(c, MONSTER): v = 1
elif is_a(c, SPIKES): v = 10
elif is_a(c, TRAP): v = 10 / 3
t.append(v)
return t
def hash(p):
return p[3] << 24 | p[2] << 16 | p[1] << 8 | p[0];
moves = [GO_UP, GO_DOWN, GO_LEFT, GO_RIGHT]
deltas = [-16, +16, -1, +1]
path = []
def turn(board, players, events):
global path
sleep(50)
if {NEW_GAME, TRAP_APPEARED, SPIKES_APPEARED}.intersection([e[2] for e in events]):
t = convert(board)
p = players.copy()
e = [0, 0, 0, 0]
l = len(board)
for i in range(4):
e[i] = board.index(EXIT + i)
if p[i] < 0: p[i] = e[i]
path = astar(t, hash(p), hash(e), l)
m = moves[path[0]]
dn = deltas[path[0]]
for i in range(4):
n = players[i]
if n < 0: continue
dest = board[n + dn]
if est_un(dest, MONSTER) and affects(dest, i):
return ATTACK
path = path[1:]
return m
play_game(turn, blind = False)

511
synchrod/polycal4.py Normal file
View File

@ -0,0 +1,511 @@
#cas
from math import pi, asin
KEY_NONE, KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_ENTER, KEY_ESC, KEY_7, KEY_8, KEY_9, KEY_LEFT_PARENTHESIS, KEY_RIGHT_PARENTHESIS, KEY_4, KEY_5, KEY_6, KEY_1, KEY_2, KEY_3, KEY_0 = 0, 1, 2, 3, 4, 53, 6, 30, 31, 32, 34, 35, 36, 37, 38, 42, 43, 44, 48
def fix_angle(a):
return a * 2 * asin(1) / pi
def col3_2_rgb(c, bits, bgr):
return c[2*bgr]//2**(8 - bits[0]) + c[1]//2**(8 - bits[1])*2**bits[0] + c[2*(not(bgr))]//2**(8-bits[2])*2**(bits[0] + bits[1])
def hp_draw_line(x1, y1, x2, y2, c):
line_p(x1, y1, x2, y2, col3_2_rgb(c, [8, 8, 8], 1))
def hp_fill_rect(x, y, w, h, c):
rect_p(x, y, x + w - 1, y + h - 1, col3_2_rgb(c, [8, 8, 8], 1))
def hp_draw_circle(x, y, r, c):
global L1
c = col3_2_rgb(c, [8, 8, 8], 1)
arc_p(x, y, r, 0, fix_angle(2*pi), c)
def hp_fill_circle(x, y, r, c):
global L1, L2
c = col3_2_rgb(c, [8, 8, 8], 1)
L2 = [c, c]
arc_p(x, y, r, 0, fix_angle(2*pi), L2)
def hp_draw_ellipse(x, y, rx, ry, c):
global L1
c, L1 = col3_2_rgb(c, [8, 8, 8], 1), [rx, ry]
arc_p(x, y, L1, 0, fix_angle(2*pi), c)
def hp_fill_ellipse(x, y, rx, ry, c):
global L1, L2
c, L1 = col3_2_rgb(c, [8, 8, 8], 1), [rx, ry]
L2 = [c, c]
arc_p(x, y, L1, 0, fix_angle(2*pi), L2)
def hp_draw_string(s, x, y, cf, cb=(255,255,255)):
textout_p(s, x, y, 1, col3_2_rgb(cf, [8, 8, 8], 1), len(s) * 9, col3_2_rgb(cb, [8, 8, 8], 1))
def hp_clear_screen():
rect_p(0, 0, 319, 239, 16777215)
def hp_pause():
wait()
def hp_sleep(d):
wait(d)
def hp_monotonic(d):
return time()
def hp_get_key():
d_key = {KEY_LEFT:7, KEY_UP:2, KEY_DOWN:12, KEY_RIGHT:8, KEY_ENTER:30, KEY_ESC:4, KEY_LEFT_PARENTHESIS:28, KEY_0:47, KEY_1:42, KEY_2:43, KEY_3:44, KEY_4:37, KEY_5:38, KEY_6:39, KEY_7:32, KEY_8:33, KEY_9:34 }
key = get_key()
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
def kc1_draw_line(x1, y1, x2, y2, c):
draw_line(float(x1), float(y1), float(x2), float(y2), not(col3_2_rgb(c, [1, 1, 1], 0)))
def kc1_fill_rect(x, y, w, h, c):
draw_rectangle(float(x), float(y), float(w), float(h), (not (col3_2_rgb(c, [1, 1, 1], 0))) + filled)
def kc1_draw_circle(x, y, r, c):
draw_arc(float(x), float(y), float(r), not (col3_2_rgb(c, [1, 1, 1], 0)))
def kc1_fill_circle(x, y, r, c):
draw_arc(float(x), float(y), float(r), (not (col3_2_rgb(c, [1, 1, 1], 0))) + filled)
def kc1_draw_ellipse(x, y, rx, ry, c):
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, not (col3_2_rgb(c, [1, 1, 1], 0)))
def kc1_fill_ellipse(x, y, rx, ry, c):
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, (not (col3_2_rgb(c, [1, 1, 1], 0))) + filled)
def kc1_draw_string(s, x, y, cf, cb=(255,255,255)):
draw_string(s, float(x), float(y), col3_2_rgb(cf, [1, 1, 1], 1), col3_2_rgb(cb, [1, 1, 1], 1))
def kc_get_key():
d_key = {KEY_LEFT:0, KEY_UP:1, KEY_DOWN:2, KEY_RIGHT:3, KEY_ENTER:30004, KEY_ESC:5, KEY_LEFT_PARENTHESIS:40, KEY_RIGHT_PARENTHESIS:41, KEY_0:48, KEY_1:49, KEY_2:50, KEY_3:51, KEY_4:52, KEY_5:53, KEY_6:54, KEY_7:55, KEY_8:56, KEY_9:57 }
key = get_key()
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
tcanvas = None
def get_infos(keys, sdl_width=640, sdl_height=480, sdl_scale=1):
global hp_draw_line, hp_fill_rect, hp_draw_circle, hp_fill_circle, hp_draw_ellipse, hp_fill_ellipse, hp_draw_string, kc1_draw_line, kc1_fill_rect, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string, hp_clear_screen, hp_pause, tcanvas
fnop = lambda : None
ffalse = lambda : False
screen_w, screen_h, screen_y0, color_bits, font_w, font_num_w, font_h, poly_has_color, poly_get_pixel, poly_set_pixel, poly_show, poly_draw_line, poly_fill_rect, poly_draw_circle, poly_fill_circle, poly_draw_ellipse, poly_fill_ellipse, poly_monotonic, poly_sleep, poly_draw_string, poly_clear_screen, poly_pause, poly_set_buffer, poly_get_key, poly_wait_key, poly_wait_release, poly_test_key, poly_esc_key, show_need_pause_on_exit, screen_need_clear_on_init, need_clear, need_line, need_rect, need_ellipse, need_string, need_monotonic, need_sleep, has_keys = 0, 0, 0, [5, 6, 5], 0, 0, 0, 1, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, fnop, ffalse, ffalse, ffalse, ffalse, 0, 0, 0, 1, 1, 1, 1, 1, 1, 1
if not (screen_w):
try:
if chr(256)==chr(0): # KhiCAS Python compat.
need_line, need_rect, need_ellipse, need_string, need_sleep, need_monotonic = 0, 0, 0, 0, 0, 0
if "HP" in version():
kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string = None, None, None, None, None, None, None
screen_w, screen_h, font_w, font_h, show_need_pause_on_exit = 320, 240, 9, 11, 1
font_num_w = font_w
def poly_set_pixel(x, y, c):
set_pixel(x, y, col3_2_rgb(c, [8, 8, 8], 1))
poly_draw_line, poly_fill_rect, poly_draw_circle, poly_fill_circle, poly_draw_ellipse, poly_fill_ellipse, poly_draw_string, poly_clear_screen, poly_pause, poly_sleep, poly_monotonic = hp_draw_line, hp_fill_rect, hp_draw_circle, hp_fill_hp_draw_circle, hp_draw_ellipse, hp_fill_ellipse, hp_draw_string, hp_clear_screen, hp_pause, hp_sleep, hp_monotonic
else: # Graph 35+E II / NumWorks or Nspire / Graph 90+E
hp_draw_line, hp_fill_rect, hp_draw_string, hp_clear_screen, hp_pause = None, None, None, None, None
t_mono, t_nw, t_ns, need_clear = not (white), "Numworks" in version(), "Nspire" in version(), 1
screen_w, screen_h, font_w, font_h, poly_get_pixel, poly_pause, poly_sleep = 384 - (t_ns or t_nw)*64 - t_mono*256, 192 + (t_ns or t_nw)*30 - t_mono*128, get_pixel, 10 - 4*t_mono + 5*t_ns + t_nw, 10 - 5*t_mono + 8*(t_ns or t_nw), getKey, sleep
font_num_w = font_w
def poly_monotonic():
return monotonic / (1 + (not(t_nw or t_ns))*99)
key_d = {KEY_LEFT:0, KEY_UP:1, KEY_DOWN:2, KEY_RIGHT:3, KEY_ENTER:4, KEY_ESC:5, KEY_LEFT_PARENTHESIS:40, KEY_RIGHT_PARENTHESIS:41}
def poly_wait_key():
key = get_key()
for k in key_d:
if key == key_d[k]:
return k
return 0
if t_mono:
def poly_set_pixel(x, y, c):
set_pixel(x, y, not(col3_2_rgb(c, [1,1,1], 0)))
poly_draw_line, poly_fill_rect, poly_draw_circle, poly_fill_circle, poly_draw_ellipse, poly_fill_ellipse, poly_draw_string = kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string
else:
kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string = None, None, None, None, None, None, None
def poly_set_pixel(x, y, c):
set_pixel(x, y, col3_2_rgb(c, [5,6,5], 0))
def poly_draw_line(x1, y1, x2, y2, c):
draw_line(float(x1), float(y1), float(x2), float(y2), col3_2_rgb(c, color_bits, 1))
def poly_fill_rect(x, y, w, h, c):
draw_rectangle(float(x), float(y), float(w), float(h), col3_2_rgb(c, color_bits, 1) + filled)
def poly_draw_circle(x, y, r, c):
draw_arc(float(x), float(y), float(r), float(r), 0, 2*pi, col3_2_rgb(c, color_bits, 1))
def poly_fill_circle(x, y, r, c):
draw_arc(float(x), float(y), float(r), float(r), 0, 2*pi, col3_2_rgb(c, color_bits, 1) + filled)
def poly_draw_ellipse(x, y, rx, ry, c):
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, col3_2_rgb(c, color_bits, 1))
def poly_fill_ellipse(x, y, rx, ry, c):
draw_arc(float(x), float(y), float(rx), float(ry), 0, 2*pi, col3_2_rgb(c, color_bits, 1) + filled)
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
draw_string(s, float(x), float(y), col3_2_rgb(cf, color_bits, 1), col3_2_rgb(cb, color_bits, 1))
except:
pass
if not (screen_w):
hp_draw_line, hp_fill_rect, hp_draw_circle, hp_fill_circle, hp_draw_ellipse, hp_fill_ellipse, hp_draw_string, kc1_draw_line, kc1_fill_rect, kc1_draw_circle, kc1_fill_circle, kc1_draw_ellipse, kc1_fill_ellipse, kc1_draw_string, hp_clear_screen, hp_pause = None, None, None, None, None, None, None, None, None, None, None, None, None, None, None, None
try:
import sys
try:
t_nw = sys.platform == "numworks"
if sys.platform == "nspire" or t_nw:
try: # KhiCAS Micropython
import graphic, nsp, cas, time
def poly_draw_line(x1, y1, x2, y2, c):
graphic.draw_line(int(x1), int(y1), int(x2), int(y2), col3_2_rgb(c, color_bits, 1))
def poly_fill_rect(x1, y1, x2, y2, c):
graphic.draw_filled_rectangle(int(x1), int(y1), int(x2), int(y2), c)
def poly_draw_circle(x, y, r, c):
graphic.draw_circle(int(x), int(y), int(r), c)
def poly_fill_circle(x, y, r, c):
graphic.draw_filled_circle(int(x), int(y), int(r), c)
def poly_draw_ellipse(x, y, rx, ry, c):
graphic.draw_arc(int(x), int(y), int(rx), int(ry), 0, 360, c)
def poly_fill_ellipse(x, y, rx, ry, c):
graphic.draw_filled_arc(int(x), int(y), int(rx), int(ry), 0, 360, c)
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
cas.caseval('draw_string("' + s + '", ' + str(float(x)) + ', ' + str(float(y)) + ', ' + str(col3_2_rgb(cf, color_bits, 1)) + ', ' + str(col3_2_rgb(cb, color_bits, 1)) + ')')
def poly_wait_key():
d_key = {KEY_LEFT:0, KEY_UP:1, KEY_DOWN:2, KEY_RIGHT:3, KEY_ENTER:4, KEY_ESC:5, KEY_LEFT_PARENTHESIS:40, KEY_RIGHT_PARENTHESIS:41, KEY_0:48, KEY_1:49, KEY_2:50, KEY_3:51, KEY_4:52, KEY_5:53, KEY_6:54, KEY_7:55, KEY_8:56, KEY_9:57}
key = int(cas.caseval("get_key()"))
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
def poly_monotonic():
return time.monotonic() / (1 + t_nw*999)
screen_w, screen_h, font_w, font_h, poly_get_pixel, poly_set_pixel, poly_show, poly_pause, need_clear, need_line, need_rect, need_ellipse, need_string, need_monotonic, screen_need_clear_on_init = 320, 222, 15, 18, graphic.get_pixel, graphic.set_pixel, graphic.show_screen, nsp.waitKeypress, 1, 0, 0, 0, 0, 0, 1
font_num_w = font_w
except: # Nspire MicroPython
import nsp
screen_w, screen_h, need_clear, show_need_pause_on_exit = 320, 240, 1, 1
tcanvas = nsp.Texture(screen_w, screen_h, 0)
poly_get_pixel = tcanvas.getPx
def poly_set_pixel(x, y, c):
if x>=0 and x<=screen_w-1 and y>=0 and y <=screen_h-1:
tcanvas.setPx(x, y, col3_2_rgb(c, color_bits, 1))
poly_show, poly_pause = tcanvas.display, nsp.waitKeypress
elif sys.platform == "TI-Nspire": # CX II
import time
screen_w, screen_h, font_w, font_h, need_monotonic, need_sleep, poly_sleep = 318, 212, 12, 12, 0, 0, time.sleep
font_num_w = font_w
def test(d,f):
t=f()
time.sleep(d)
return round((f()-t)/d,0)
if test(0.1, time.clock) == 1:
poly_monotonic = time.clock
else:
poly_monotonic = time.time
try:
import ti_system
d_key = {KEY_LEFT:'left', KEY_UP:'up', KEY_DOWN:'down', KEY_RIGHT:'right', KEY_ENTER:'enter', KEY_ESC:'esc', KEY_LEFT_PARENTHESIS:'(', KEY_RIGHT_PARENTHESIS:')', KEY_0:'0', KEY_1:'1', KEY_2:'2', KEY_3:'3', KEY_4:'4', KEY_5:'5', KEY_6:'6', KEY_7:'7', KEY_8:'8', KEY_9:'9'}
def poly_get_key():
key = ti_system.get_key()
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
def poly_wait_key():
key = ""
while key == "":
key = ti_system.get_key()
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
def poly_test_key(v):
return poly_get_key() == d_key[v]
def poly_esc_key():
return poly_test_key(KEY_ESC)
except:
has_keys = 0
if "gp" in keys:
import ti_image
need_line, need_rect, need_ellipse, need_string = 1, 1, 1, 1
tcanvas = ti_image.new_image(screen_w, screen_h, (255,255,255))
poly_get_pixel, poly_set_pixel = tcanvas.get_pixel, tcanvas.set_pixel
def poly_show():
tcanvas.show_image(0,0)
else:
import ti_draw
ti_draw.use_buffer()
ti_draw.set_pen("thin","solid")
need_line, need_rect, need_ellipse, need_string, poly_show, set_buffer = 0, 0, 0, 0, ti_draw.paint_buffer, ti_draw.use_buffer
def poly_set_pixel(x, y, c):
ti_draw.set_color(tuple(c))
ti_draw.plot_xy(x, y, 7)
def poly_draw_line(x1, y1, x2, y2, c):
ti_draw.set_color(tuple(c))
ti_draw.draw_line(x1, y1, x2, y2)
def poly_fill_rect(x, y, w, h, c):
ti_draw.set_color(tuple(c))
ti_draw.fill_rect(x, y, w, h)
def poly_draw_circle(x, y, r, c):
ti_draw.set_color(tuple(c))
ti_draw.draw_circle(x, y, r)
def poly_fill_circle(x, y, r, c):
ti_draw.set_color(tuple(c))
ti_draw.fill_circle(x, y, r)
def poly_draw_ellipse(x, y, rx, ry, c):
ti_draw.set_color(tuple(c))
x0, y0 = x - rx, y - ry
for dy in range(1 + (y0 > int(y0))):
for dx in range(1 + (x0 > int(x0))):
ti_draw.draw_arc(x0 + dx, y0 + dy, 2 * rx, 2 * ry, 0, 360)
def poly_fill_ellipse(x, y, rx, ry, c):
ti_draw.set_color(tuple(c))
ti_draw.fill_arc(x - rx, y - ry, 2 * rx, 2 * ry, 0, 360)
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
poly_fill_rect(x, y, font_w * len(s), font_h, cb)
ti_draw.set_color(tuple(cf))
ti_draw.draw_text(x, y + font_h, s)
elif sys.platform.startswith('TI-Python'):
import ti_graphics, ti_system, time
screen_w, screen_h, font_w, font_h, screen_y0, need_line, need_rect, need_ellipse, need_string, need_monotonic, need_sleep, poly_pause, poly_wait_key, poly_sleep, poly_monotonic, poly_esc_key, need_clear, show_need_pause_on_exit, need_sleep, screen_need_clear_on_init = 320, 210, 10, 15, 30, 0, 0, 0, 0, 0, ti_system.disp_wait, ti_system.wait_key, time.sleep, time.monotonic, ti_system.escape, 1, 1, 0, 1
font_num_w = font_w
def poly_draw_line(x1, y1, x2, y2, c):
ti_graphics.setColor(c)
ti_graphics.drawLine(x1, y1 + screen_y0, x2, y2 + screen_y0)
def poly_fill_rect(x, y, w, h, c):
ti_graphics.setColor(c)
ti_graphics.fillRect(x, y + screen_y0, w, h)
def poly_get_pixel(x, y):
return ti_graphics.getPixel(x, y + screen_y0)
def poly_set_pixel(x, y, c):
ti_graphics.setPixel(x, y + screen_y0, c)
def poly_draw_ellipse(x, y, rx, ry, c):
ti_graphics.setColor(c)
x0, y0 = x - rx, y - ry
for dy in range(1 + (y0 > int(y0))):
for dx in range(1 + (x0 > int(x0))):
ti_graphics.drawArc(x0 + dx, y0 + dy + screen_y0, 2 * rx, 2 * ry, 0, 3600)
def poly_fill_ellipse(x, y, rx, ry, c):
ti_graphics.setColor(c)
ti_graphics.fillArc(x - rx, y - ry + screen_y0, 2 * rx, 2 * ry, 0, 3600)
def poly_draw_circle(x, y, r, c):
poly_draw_ellipse(x, y, r, r, c)
def poly_fill_circle(x, y, r, c):
ti_graphics.setColor(c)
ti_graphics.fillCircle(x, y + screen_y0, r)
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
poly_fill_rect(x, y, font_w * len(s), font_h, cb)
ti_graphics.setColor(cf)
ti_graphics.drawString(s, x, y + screen_y0)
def poly_wait_key():
d_key = {KEY_LEFT:2, KEY_UP:3, KEY_DOWN:4, KEY_RIGHT:1, KEY_ENTER:5, KEY_ESC:9, KEY_LEFT_PARENTHESIS:133, KEY_RIGHT_PARENTHESIS:134, KEY_0:142, KEY_1:143, KEY_2:144, KEY_3:145, KEY_4:146, KEY_5:147, KEY_6:148, KEY_7:149, KEY_8:150, KEY_9:151}
key = ti_system.wait_key()
return key in d_key.values() and list(d_key.keys())[list(d_key.values()).index(key)]
except:
pass
except:
pass
if not (screen_w): # Casio Graph 90/35+E II
try:
import casioplot
casioplot.set_pixel(0, 0, (0, 0, 255))
col = casioplot.get_pixel(0, 0)
t = col[0] == col[2]
screen_w, screen_h, poly_has_color, font_w, font_h, poly_get_pixel, poly_set_pixel, poly_show, poly_clear_screen, need_string, has_keys = t and 128 or 384, t and 64 or 192, not (t), t and 6 or 10, t and 5 or 10, casioplot.get_pixel, casioplot.set_pixel, casioplot.show_screen, casioplot.clear_screen, 0, 0
font_num_w = t and 4 or 8
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
poly_fill_rect(x, y, font_w * len(s), font_h, cb)
casioplot.draw_string(x, y, s, cf, "small")
def poly_pause():
try:
while(1):
pass
except KeyboardInterrupt:
pass
except:
try: # NumWorks
import kandinsky, ion, time
screen_w, screen_h, font_w, font_h, poly_get_pixel, poly_set_pixel, poly_draw_string, poly_sleep, poly_monotonic, need_rect, need_string, need_monotonic, need_sleep = 320, 222, 11, 18, kandinsky.get_pixel, kandinsky.set_pixel, kandinsky.draw_string, time.sleep, time.monotonic, 0, 0, 0, 0
font_num_w = font_w
def poly_fill_rect(x, y, w, h, c):
kandinsky.fill_rect(int(x), int(y), int(w), int(h), c)
def poly_pause():
def key_down():
for k in range(53):
if ion.keydown(k):
return 1
return 0
while key_down():
pass
while not (key_down()):
pass
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
kandinsky.draw_string(s, x, y, cf, cb)
d_key = {KEY_LEFT:0, KEY_UP:1, KEY_RIGHT:2, KEY_DOWN:3, KEY_ENTER:52, KEY_ESC:5, KEY_LEFT_PARENTHESIS:33, KEY_RIGHT_PARENTHESIS:34, KEY_0:48, KEY_1:42, KEY_2:43, KEY_3:44, KEY_4:36, KEY_5:37, KEY_6:38, KEY_7:30, KEY_8:31, KEY_9:32}
def poly_get_key():
for k in d_key:
if poly_test_key(d_key[k]):
return k
return 0
def poly_wait_key():
k = 0
while not k:
k = poly_get_key()
return k
def poly_test_key(v):
return ion.keydown(d_key[v])
def poly_esc_key():
return poly_test_key(KEY_ESC)
except:
try: # HP Prime
import hpprime
screen_w, screen_h, font_h, color_bits, need_clear, show_need_pause_on_exit, screen_need_clear_on_init, need_line, need_rect, need_string = 320, 240, 15, (8, 8, 8), 1, 1, 1, 0, 0, 0
hpprime.dimgrob(1, screen_w, screen_h, 0)
def poly_set_pixel(x, y, c):
hpprime.pixon(1, x, y, col3_2_rgb(c, color_bits, 1))
def poly_draw_line(x1, y1, x2, y2, c):
hpprime.line(1, x1, y1, x2, y2, col3_2_rgb(c, color_bits, 1))
def poly_fill_rect(x, y, w, h, c):
hpprime.fillrect(1, x, y, w, h, col3_2_rgb(c, color_bits, 1), col3_2_rgb(c, color_bits, 1))
def poly_show():
hpprime.strblit(0, 0, 0, screen_w, screen_h, 1)
def poly_pause():
while hpprime.keyboard(): pass
while not(hpprime.keyboard()): pass
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
sz = hpprime.eval('TEXTSIZE("'+s+'")')
poly_fill_rect(x, y, sz[0], sz[1], cb)
hpprime.textout(1, x, y, s, col3_2_rgb(cf, color_bits, 1))
d_key = {KEY_LEFT:7, KEY_UP:2, KEY_DOWN:12, KEY_RIGHT:8, KEY_ENTER:30, KEY_ESC:4, KEY_LEFT_PARENTHESIS:28, KEY_RIGHT_PARENTHESIS:28, KEY_0:47, KEY_1:42, KEY_2:43, KEY_3:44, KEY_4:37, KEY_5:38, KEY_6:39, KEY_7:32, KEY_8:33, KEY_9:34 }
def poly_get_key():
for k in d_key:
if poly_test_key(k):
return k
return 0
def poly_wait_key():
while not hpprime.keyboard(): pass
return poly_get_key()
def poly_wait_release():
while hpprime.keyboard(): pass
def poly_test_key(v):
return hpprime.keyboard() & (1 << d_key[v])
def poly_esc_key():
return poly_test_key(KEY_ESC)
except: # computer
import polycalc_sdl2
polycalc_sdl2.polycalc_pc_init(sdl_width, sdl_height, sdl_scale)
screen_w, screen_h, poly_set_pixel, poly_fill_rect, poly_clean_screen, poly_show, poly_pause, poly_wait_key, poly_get_key, poly_test_key, need_line, need_string = polycalc_sdl2.screen_w, polycalc_sdl2.screen_h, polycalc_sdl2.poly_set_pixel, polycalc_sdl2.poly_fill_rect, polycalc_sdl2.poly_clean_screen, polycalc_sdl2.poly_show, polycalc_sdl2.poly_pause, polycalc_sdl2.poly_wait_key, polycalc_sdl2.poly_get_key, polycalc_sdl2.poly_test_key, 1, 1
color_bits = [8, 8, 8]
poly_has_color = 1
show_need_pause_on_exit = 0
if screen_w:
if need_line:
def poly_draw_line(x1, y1, x2, y2, c):
m, a1, b1, a2, b2 = 0, int(x1), int(y1), int(x2), int(y2)
if (x2 - x1) ** 2 < (y2 - y1) ** 2:
m, a1, a2, b1, b2 = 1, b1, b2, a1, a2
if min(a1, a2) != a1: a1, b1, a2, b2 = a2, b2, a1, b1
for a in range(a1, a2 + 1):
b = int(b1 + (b2 - b1) * (a - a1) / ((a2 - a1) or 1))
poly_set_pixel((a, b)[m], (b, a)[m], c)
if need_rect:
def poly_fill_rect(x, y, w, h, c):
for k in range(h):
poly_draw_line(x, y + k, x + w - 1, y + k, c)
if need_ellipse:
from math import sqrt
def poly_draw_ellipse(x, y, rx, ry, c):
for h in range(-int(ry), int(ry)+1):
w = sqrt(max(0, rx*rx*(1-h*h/ry/ry)))
x1, x2 = int(x - w), int(x + w)
yc = int(y + h)
poly_set_pixel(x1, yc, c)
poly_set_pixel(x2, yc, c)
for w in range(-int(rx), int(rx)+1):
h = sqrt(max(0, ry*ry*(1-w*w/rx/rx)))
y1, y2 = int(y - h), int(y + h)
xc = int(x + w)
poly_set_pixel(xc, y1, c)
poly_set_pixel(xc, y2, c)
def poly_fill_ellipse(x, y, rx, ry, c):
for h in range(-int(ry), int(ry)+1):
w = sqrt(max(0, rx*rx*(1-h*h/ry/ry)))
poly_fill_rect(int(x - w), int(y + h), int(2 * w), 1, c)
def poly_draw_circle(x, y, r, c):
poly_draw_ellipse(x, y, r, r, c)
def poly_fill_circle(x, y, r, c):
poly_fill_ellipse(x, y, r, r, c)
if need_string:
from polyfont import poly_font
font_w, font_h = 11, 10
font_num_w = 9
def poly_draw_string(s, x, y, cf, cb=(255,255,255)):
for c in s:
c = ord(c) >= 33 and ord(c) <= 127 and ord(c) - 32 or 0
poly_fill_rect(x, y, font_w, font_h, cb)
for v in (0,) + poly_font[c] + (0,):
ty = y
while v:
if v & 1:
poly_set_pixel(x, ty, cf)
ty += 1
v //= 2
x += 1
if need_clear:
def poly_clear_screen():
poly_fill_rect(0, 0, screen_w, screen_h, [255, 255, 255])
if screen_need_clear_on_init:
poly_clear_screen_init = poly_clear_screen
else:
poly_clear_screen_init = fnop
if need_sleep:
def poly_sleep(d):
if need_monotonic:
for k in range(int(d*250000)):
pass
else:
s = poly_monotonic() + d
while poly_monotonic() < s:
pass
if show_need_pause_on_exit:
def poly_show_exit():
poly_show()
poly_pause()
else:
poly_show_exit = poly_show
l = []
for k in keys:
if k=="w":
l.append(screen_w)
if k=="h":
l.append(screen_h)
if k=="hc":
l.append(poly_has_color)
if k=="fw":
l.append(font_w)
if k=="fwn":
l.append(font_num_w)
if k=="fh":
l.append(font_h)
if k=="gp":
l.append(poly_get_pixel)
if k=="sp":
l.append(poly_set_pixel)
if k=="dl":
l.append(poly_draw_line)
if k=="fr":
l.append(poly_fill_rect)
if k=="dc":
l.append(poly_draw_circle)
if k=="fc":
l.append(poly_fill_circle)
if k=="de":
l.append(poly_draw_ellipse)
if k=="fe":
l.append(poly_fill_ellipse)
if k=="ds":
l.append(poly_draw_string)
if k=="cl":
l.append(poly_clear_screen)
if k=="cli":
l.append(poly_clear_screen_init)
if k=="sh":
l.append(poly_show)
if k=="she":
l.append(poly_show_exit)
if k=="p":
l.append(poly_pause)
if k=="sb":
l.append(poly_set_buffer)
if k=="m":
l.append(poly_monotonic)
if k=="s":
l.append(poly_sleep)
if k=="ek":
l.append(poly_esc_key)
if k=="gk":
l.append(poly_get_key)
if k=="wk":
l.append(poly_wait_key)
if k=="wr":
l.append(poly_wait_release)
if k=="tk":
l.append(poly_test_key)
if k=="hk":
l.append(has_keys)
return l

150
synchrod/polycalc_sdl2.py Normal file
View File

@ -0,0 +1,150 @@
from sdl2 import *
from ctypes import byref
import atexit
from polycal4 import KEY_NONE, KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT, \
KEY_ENTER, KEY_ESC, KEY_LEFT_PARENTHESIS, KEY_RIGHT_PARENTHESIS
window = None
renderer = None
texture = None
pause_on_quit = False
def polycalc_pc_init(width=0, height=0, scale=1):
if SDL_Init(SDL_INIT_VIDEO) < 0:
raise Exception("Failed to initialize SDL")
dm = SDL_DisplayMode()
SDL_GetCurrentDisplayMode(0, byref(dm))
global window
global renderer
global texture
global screen_w, screen_h, SCALE
if width <= 0: width = dm.w // SCALE
if height <= 0: height = dm.h // SCALE
screen_w, screen_h, SCALE = width, height, scale
window = SDL_CreateWindow("Polycalc SDL2".encode(),
SDL_WINDOWPOS_CENTERED, SDL_WINDOWPOS_CENTERED,
width*SCALE, height*SCALE, SDL_WINDOW_SHOWN)
renderer = SDL_CreateRenderer(window, -1, SDL_RENDERER_ACCELERATED)
texture = SDL_CreateTexture(renderer, SDL_PIXELFORMAT_ARGB8888,
SDL_TEXTUREACCESS_TARGET, width, height)
if window is None or renderer is None or texture is None:
raise Exception("Failed to create either window, renderer or texture")
SDL_SetHint(SDL_HINT_RENDER_SCALE_QUALITY, b'0')
SDL_SetRenderTarget(renderer, texture)
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255)
SDL_RenderClear(renderer)
atexit.register(polycalc_pc_quit)
def poly_clean_screen():
SDL_SetRenderDrawColor(renderer, 255, 255, 255, 255)
SDL_RenderClear(renderer)
def poly_set_pixel(x, y, color):
SDL_SetRenderDrawColor(renderer, *color, 255)
SDL_RenderDrawPoint(renderer, x, y)
def poly_show():
global renderer
global texture
SDL_SetRenderTarget(renderer, None)
SDL_RenderSetScale(renderer, SCALE, SCALE)
SDL_RenderCopy(renderer, texture, None, None)
SDL_RenderPresent(renderer)
SDL_SetRenderTarget(renderer, texture)
SDL_RenderSetScale(renderer, 1, 1)
def poly_sdl2_screenshot(scale=-1, fname=None):
global renderer
global texture
if scale == -1:
scale = SCALE
w = screen_w * scale
h = screen_h * scale
if fname == None:
fname = b"poly_sdl2_screenshot.bmp"
fname = bytes(fname)
surface = SDL_CreateRGBSurface(0, w, h, 32, 0, 0, 0, 0)
SDL_SetRenderTarget(renderer, None)
SDL_RenderSetScale(renderer, scale, scale)
SDL_RenderReadPixels(renderer, None, 0, surface.contents.pixels,
surface.contents.pitch)
SDL_SaveBMP(surface, fname)
SDL_SetRenderTarget(renderer, texture)
SDL_RenderSetScale(renderer, 1, 1)
def poly_pause():
event = SDL_Event()
while 1:
SDL_WaitEvent(event)
if event.type == SDL_KEYDOWN:
break
if event.type == SDL_QUIT:
raise SystemExit
def poly_fill_rect(x, y, w, h, color):
SDL_SetRenderDrawColor(renderer, *color, 255)
SDL_RenderFillRect(renderer, SDL_Rect(x, y, w, h))
_keys = {
KEY_LEFT: (SDLK_LEFT, SDL_SCANCODE_LEFT),
KEY_UP: (SDLK_UP, SDL_SCANCODE_UP),
KEY_DOWN: (SDLK_DOWN, SDL_SCANCODE_DOWN),
KEY_RIGHT: (SDLK_RIGHT, SDL_SCANCODE_RIGHT),
KEY_ENTER: (SDLK_RETURN, SDL_SCANCODE_RETURN),
KEY_ESC: (SDLK_ESCAPE, SDL_SCANCODE_ESCAPE),
KEY_LEFT_PARENTHESIS: (SDLK_LEFTPAREN, SDL_SCANCODE_5),
KEY_RIGHT_PARENTHESIS: (SDLK_RIGHTPAREN, SDL_SCANCODE_MINUS),
}
def poly_wait_key():
event = SDL_Event()
while 1:
SDL_WaitEvent(event)
if event.type == SDL_KEYDOWN:
for key, value in _keys.items():
if event.key.keysym.sym == value[0]:
return key
def poly_test_key(key):
st = SDL_GetKeyboardState(None)
return st[_keys[key][1]] != 0
def poly_get_key():
for key in _keys:
if poly_test_key(key):
return key
return KEY_NONE
def polycalc_pc_quit():
global window
global renderer
global texture
poly_show()
if pause_on_quit:
poly_pause()
SDL_SetRenderTarget(renderer, None)
SDL_DestroyTexture(texture)
SDL_DestroyRenderer(renderer)
SDL_DestroyWindow(window)
SDL_Quit()

105
synchrod/polyfont.py Normal file
View File

@ -0,0 +1,105 @@
# font
# height : 10px
# width : variable
# margin-left : 1px
# margin-top : 0px
# margin-right : 1px
# margin-bottom : 0px
poly_font = (
(0,),
(0, 447, 0, 0), # !
(11, 7, 0, 11, 7, 0), # "
(64, 452, 124, 455, 124, 71, 4), # #
(140, 274, 1023, 290, 196), # $
(6, 393, 102, 24, 198, 288, 192), # %
(192, 302, 273, 297, 198, 288, 272), # &
(11, 7, 0), # '
(120, 390, 513, 0), # (
(513, 390, 120, 0), # )
(68, 40, 254, 40, 68, 0), # *
(16, 16, 16, 254, 16, 16, 16), # +
(384, 896, 0), # ,
(16, 16, 16, 16, 16, 16, 16), # -
(384, 384, 0), # .
(384, 96, 24, 6, 0), # /
(254, 257, 257, 257, 257, 254, 0), # 0
(0, 258, 258, 511, 256, 256, 0), # 1
(390, 321, 289, 289, 273, 398, 0), # 2
(198, 257, 273, 273, 273, 238, 0), # 3
(96, 88, 70, 321, 511, 320, 0), # 4
(159, 265, 265, 265, 265, 241, 0), # 5
(254, 273, 273, 273, 273, 226, 0), # 6
(7, 1, 449, 49, 13, 3, 0), # 7
(238, 273, 273, 273, 273, 238, 0), # 8
(142, 273, 273, 273, 273, 254, 0), # 9
(204, 204, 0), # :
(716, 460, 0), # ;
(16, 40, 68, 130, 0), # <
(40, 40, 40, 40, 40, 40, 40), # =
(130, 68, 40, 16, 0), # >
(6, 1, 433, 9, 6, 0), # ?
(124, 130, 313, 325, 381, 322, 60), # @
(384, 112, 76, 67, 76, 112, 384), # A
(257, 511, 273, 273, 273, 273, 238), # B
(124, 130, 257, 257, 257, 130, 71), # C
(257, 511, 257, 257, 257, 130, 124), # D
(257, 511, 273, 273, 273, 313, 387), # E
(257, 511, 273, 17, 17, 57, 3), # F
(124, 130, 257, 273, 273, 146, 503), # G
(257, 511, 273, 16, 273, 511, 257), # H
(257, 257, 511, 257, 257), # I
(192, 256, 257, 257, 255, 1), # J
(257, 511, 273, 8, 309, 451, 257), # K
(257, 511, 257, 256, 256, 256, 448), # L
(257, 511, 262, 56, 192, 56, 262, 511, 257), # M
(257, 511, 262, 24, 97, 511, 1), # N
(124, 130, 257, 257, 257, 130, 124), # O
(257, 511, 273, 17, 17, 17, 14), # P
(124, 130, 321, 321, 321, 130, 380), # Q
(257, 511, 273, 17, 49, 209, 270), # R
(454, 137, 273, 273, 290, 199), # S
(3, 1, 257, 511, 257, 1, 3), # T
(1, 255, 257, 256, 257, 255, 1), # U
(1, 15, 113, 384, 113, 15, 1), # V
(1, 63, 449, 56, 7, 56, 449, 63, 1), # W
(257, 387, 365, 16, 365, 387, 257), # X
(1, 7, 281, 480, 281, 7, 1), # Y
(259, 385, 353, 273, 269, 387), # Z
(1023, 513, 513, 0), # [
(6, 24, 96, 384, 0), # \
(513, 513, 1023, 0), # ]
(4, 2, 1, 2, 4, 0), # ^
(256, 256, 256, 256, 256, 256, 256), # _
(1, 2, 4, 0), # `
(200, 296, 296, 296, 240, 256), # a
(1, 511, 144, 264, 264, 240), # b
(240, 264, 264, 264, 144), # c
(240, 264, 264, 145, 511, 256), # d
(240, 296, 296, 296, 176), # e
(264, 510, 265, 265, 2), # f
(336, 680, 680, 680, 656, 264), # g
(257, 511, 272, 8, 264, 496, 256), # h
(264, 507, 256), # i
(128, 256, 264, 251, 0), # j
(257, 511, 320, 40, 344, 392, 256), # k
(257, 511, 256), # l
(264, 504, 272, 8, 496, 16, 264, 496, 256), # m
(264, 504, 272, 8, 264, 496, 256), # n
(240, 264, 264, 264, 240), # o
(520, 1016, 592, 136, 136, 112), # p
(112, 136, 136, 592, 1016, 520), # q
(264, 504, 272, 8, 16), # r
(144, 296, 296, 328, 144), # s
(8, 8, 254, 264, 264, 128), # t
(8, 248, 256, 256, 136, 504, 256), # u
(8, 56, 200, 256, 200, 56, 8), # v
(8, 120, 392, 96, 24, 96, 392, 120, 8), # w
(264, 144, 96, 144, 264), # x
(264, 536, 616, 384, 104, 24, 8), # y
(280, 392, 328, 296, 408), # z
(48, 462, 513, 0), # {
(0, 1023, 0), # |
(513, 462, 48, 0), # }
(16, 8, 8, 16, 32, 32, 16), # ~
)

295
synchrod/synchrod.py Normal file
View File

@ -0,0 +1,295 @@
from polycal4 import get_infos, KEY_NONE, KEY_LEFT, KEY_UP, KEY_DOWN, KEY_RIGHT, KEY_ENTER, KEY_ESC
screen_w, screen_h, poly_has_color, poly_set_pixel, draw_line, fill_rect, show_screen, init_clean_screen, wait_key, wait_release, esc_key, HAS_KEYS, poly_pause, sleep = get_infos(["w","h","hc","sp","dl","fr","sh","cli","wk","wr","ek","hk","p","s"], 256, 128, 4)
get_infos = None
SCALE = min(screen_w // 128, screen_h // 64)
YELLOW, RED, BLUE, GREEN, ALL = 0, 1, 2, 3, 4
VOID, WALL, SPIKES, MONSTER, TRAP, EXIT = 100, 101, 102, 107, 112, 117
GO_UP, GO_RIGHT, GO_DOWN, GO_LEFT, ATTACK, QUIT = 10, 11, 12, 13, 14, 15
NEW_GAME, TRAP_APPEARED, SPIKES_APPEARED = 20, 21, 22
JAUNE, ROUGE, BLEU, VERT, TOUS = 0, 1, 2, 3, 4
VIDE, MUR, PICS, MONSTRE, PIEGE, SORTIE = 100, 101, 102, 107, 112, 117
ALLER_HAUT, ALLER_DROITE, ALLER_BAS, ALLER_GAUCHE, ATTAQUER, QUITTER = 10, 11, 12, 13, 14, 15
NOUVELLE_PARTIE, PIEGE_APPARU, PICS_APPARUS = 20, 21, 22
def ri(rs,a,b):
rs[0] = (rs[0] * 214013 + 2531011) % 4294967296
r = (rs[0] // 65536) & 0x7fff
return r % (b-a) + a
### Rendering
def px(x, y, c):
for sx in range(SCALE):
for sy in range(SCALE):
poly_set_pixel(x*SCALE+sx, y*SCALE+sy, c)
if poly_has_color:
colors = [(77,71,63), (210,217,217), (241,233,103), (234,96,88), (97,156,236), (111,226,126), (178,126,206)]
s=0x002a2a55005454aa00
m=0x00005ae7bd18000000
t=0x00182c4a5234180000
e=0xf080e0c080e0c0f000
f=0x0f0107030107030f00
p=0x386565396dd7ff7d00
tiles = [0,0xff818181818181ff01,s+2,s+3,s+4,s+5,s+6,m+2,m+3,m+4,m+5,m+6,t+2,t+3,t+4,t+5,t+6,f+2,e+3,f+4,e+5]
sprites = [p+2,p+3,p+4,p+5]
def render_image(tile, x0, y0):
fg, bg = colors[tile & 0xff], colors[0]
tile >>= 8
if tile:
for y in range(8):
for x in range(8):
px(x0*8+7-x, y0*8+7-y, fg if tile & 1 else bg)
tile >>= 1
else:
fill_rect(x0*8*SCALE, y0*8*SCALE, 8*SCALE, 8*SCALE, colors[0])
else:
colors = [(255,255,255),(0,0,0)]
p1=0x040a00<<40
p2=0x040a06<<40
p3=0x040a0e<<40
p4=0x040e04<<40
s=0x5454aa00
m=0x00005ae7bd18
t=0x1028542810
e=0xe080e0c080e0c0f0
tiles = [0,0xff818181818181ff,s+p1,s+p2,s+p3,s+p4,(s<<31)+s,m+p1,m+p2,m+p3,m+p4,m<<16,t+p1,t+p2,t+p3,t+p4,t<<8,0x275107030107030f,e+p2,0x275177030107030f,e+p4]
sprites = [0x386565396dd7ff7d,0x386565396dd7e77d,0x386565396dd7c77d,0x386565396dc7ef7d]
def render_image(tile, x0, y0):
if tile:
for y in range(8):
for x in range(8):
px(x0*8+7-x, y0*8+7-y, colors[tile & 1])
tile >>= 1
else:
fill_rect(x0*8*SCALE, y0*8*SCALE, 8*SCALE, 8*SCALE, colors[0])
def render_game(board, players, old_players, update):
for xy in update:
if xy == -1:
for y in range(8):
for x in range(16):
render_image(tiles[board[16*y+x]-VOID], x, y)
else:
render_image(tiles[board[xy]-VOID], xy%16, xy//16)
for xy in old_players:
render_image(tiles[board[xy]-VOID], xy%16, xy//16)
for i in range(4):
render_image(sprites[i], players[i]%16, players[i]//16)
### API for submissions
if HAS_KEYS:
interactive_actions = {KEY_UP:GO_UP, KEY_RIGHT:GO_RIGHT, KEY_DOWN:GO_DOWN, KEY_LEFT:GO_LEFT, KEY_ENTER:ATTACK, KEY_ESC:QUIT}
else:
interactive_actions = {"8":GO_UP, "6":GO_RIGHT, "2":GO_DOWN, "4":GO_LEFT, "5":ATTACK, "9":QUIT}
def input_action():
if HAS_KEYS:
wait_release()
i = KEY_NONE
while not i in interactive_actions.keys():
i = wait_key()
else:
print("Déplacement:")
print(" 8")
print(" 4 6")
print(" 2")
print("Attaquer: 5")
print("Voir plateau: 0")
print("Quitter: 9")
i = input("Que faire ?> ")
return interactive_actions.get(i)
def is_a(obj, kind):
if kind == VOID or kind == WALL:
return obj == kind
return kind <= obj <= kind + 4
def affects(obj, player):
return (is_a(obj, SPIKES) or is_a(obj, MONSTER) or is_a(obj, TRAP)) and obj != SPIKES+player and obj != MONSTER+player and obj != TRAP+player
pathfind_d = [-16, +16, -1, +1, GO_UP, GO_DOWN, GO_LEFT, GO_RIGHT]
def pathfind(board, start, end):
n = len(board)
parent = [-1]*n
directions = [-1]*n
queue = [start]
parent[start] = start
cell = -1
while queue:
cell = queue.pop(0)
if cell == end:
break
for i in range(4):
d = cell+pathfind_d[i]
if board[d] != WALL and parent[d] < 0:
parent[d] = cell
directions[d] = pathfind_d[i+4]
queue.append(d)
if cell == end:
path = []
while cell != start:
path = [directions[cell]] + path
cell = parent[cell]
return path
demander_action, est_un, affecte, calculer_chemin = input_action, is_a, affects, pathfind
### Board generator
def ufc():
return [i for i in range(128)]
def ufr(uf,i):
if uf[i] == i:
return i
rep = ufr(uf, uf[i])
uf[i] = rep
return rep
def ufm(uf,i,j):
uf[ufr(uf,i)]=ufr(uf,j)
def gb(rs):
board = [WALL] * 128
pp = [17,30,97,110]
pe = [47,80,95,32]
for i in range(4):
board[pp[i]] = VOID
board[pe[i]] = EXIT+i
uf = [i for i in range(128)]
while any(ufr(uf,pp[i]) != ufr(uf,pe[i]) for i in range(4)):
i = ri(rs,1,7)*16 + ri(rs,1,15)
if board[i] == WALL and any(board[n] != VOID for n in (i-16,i+16,i-1,i+1)):
board[i] = VOID
for n in (i-16,i+16,i-1,i+1):
if board[n] != WALL:
ufm(uf,i,n)
for i in range(128):
if board[i] == VOID and ri(rs,0,16)<2:
board[i]=[MONSTER, MONSTER, SPIKES, TRAP][ri(rs,0,4)]+ri(rs,0,5)
return board
### Game logic
def play_board(rs, turn_function, blind):
board = gb(rs)
players = [17,30,97,110]
old_players = []
ev = [(-1,-1,NEW_GAME,-1)]
update = [-1]
turns = 0
penalty = 0
while True:
if not blind:
render_game(board, players, old_players, update)
show_screen()
if not HAS_KEYS:
poly_pause()
action = turn_function(board, players, ev)
ev = []
update = []
old_players = players[:]
if action is None:
continue
if action == QUIT:
return None
turns += 1
traps_activated = 0
for p in range(4):
coord = players[p]
if coord < 0:
continue
if action == ATTACK:
for direction in range(4):
dx = (direction == 1) - (direction == 3)
dy = (direction == 2) - (direction == 0)
i = coord + dx + 16*dy
dest = board[i]
if is_a(dest, MONSTER):
board[i] = VOID
update.append(i)
elif is_a(dest, TRAP) and affects(dest, p):
traps_activated += 1
board[i] = VOID
update.append(i)
else:
dx = (action == GO_RIGHT) - (action == GO_LEFT)
dy = (action == GO_DOWN) - (action == GO_UP)
i = coord + dx + 16*dy
dest = board[i]
if dest == EXIT+p:
players[p] = -1
continue
if dest == WALL or is_a(dest, EXIT):
continue
players[p] = i
if not affects(dest, p):
continue
if is_a(dest, SPIKES):
penalty += 10
elif is_a(dest, MONSTER):
penalty += 10
board[i] = VOID
update.append(i)
elif is_a(dest, TRAP):
traps_activated += 1
board[i] = VOID
update.append(i)
while traps_activated > 0:
effect = ri(rs,0,3)
if effect == 0:
penalty += 10
x = ri(rs,1,15)
y = ri(rs,1,7)
if board[y*16+x] == VOID and y*16+x not in players:
board[y*16+x] = (TRAP if effect==1 else SPIKES) + ri(rs,0,4)
ev.append((x, y, TRAP_APPEARED if effect==1 else SPIKES_APPEARED, p))
update.append(y*16+x)
traps_activated -= 1
if all(p < 0 for p in players):
score = 150 - penalty - turns
print("Bravo! "+str(turns)+"T "+str(penalty)+"D -> "+str(score))
return score
def play_game(turn_function, blind=False, seed=0xc0ffee, maxgames=100):
if not blind:
init_clean_screen()
rs = [seed]
games = 0
score = 0
while games != maxgames:
print("#"+str(games)+": "+str(rs[0]))
board_score = play_board(rs, turn_function, blind)
if board_score is None:
print("")
print("Quit!")
return
else:
score += max(board_score, 0)
games += 1
print("Games solved:", games)
print("Score:", score)
if __name__ == "__main__":
def turn(board, player, ev):
return input_action()
play_game(turn)