the whole game

This commit is contained in:
2026-03-02 22:04:18 +03:00
parent 816e9060b4
commit f0617a5d22
2069 changed files with 581500 additions and 0 deletions

Binary file not shown.

Binary file not shown.

Binary file not shown.

Binary file not shown.

100
project/raspberry/py/api.py Executable file
View File

@@ -0,0 +1,100 @@
import socket, select
import apiutil
from vec3 import Vec3
from event import TileEvent
comm = None
def connect(address, port=4711):
global comm
comm = socket.socket(socket.AF_INET,socket.SOCK_STREAM)
comm.connect((address, 4711))
connect("localhost")
def drainSocket(s):
while True:
read, w, x = select.select([s], [], [], 0.0)
if len(read) == 0: break
s.recv(1500)
def generateFunc(name, unpack=None):
def _inner(*l):
s = apiutil.call(name,*l)
drainSocket(comm)
comm.send(s)
if not unpack: return
r = comm.recv(1024)
if r != "Fail\n":
return unpack(r)
return _inner
def unpackArrayTo(func, f=lambda x:x):
"""Calling func with unpacked array element arguments"""
def _inner(s): return [func(*map(f, e.split(","))) for e in s.split("|") if e.strip()]
return _inner
def unpackTo(func, f=lambda x:x):
"""Calling func with unpacked arguments"""
def _inner(s): return func(*map(f, s.split(",")))
return _inner
def postMessageLoop():
n = 0
while 1:
postMessage(n)
n += 1
def Print(s):
print(s)
def readV3(s): return unpackTo(Vec3, float)(s)
def readV3ints(s): return unpackTo(Vec3, lambda x:int(float(x)))(s)
class Holder:
pass
# Block, world
world = Holder()
world.setBlock = generateFunc("world.setBlock")
world.getBlock = generateFunc("world.getBlock", int)
world.setBlocks = generateFunc("world.setBlocks")
world.getHeight = generateFunc("world.getHeight", int)
world.getPlayerIds = generateFunc("world.getPlayerIds", unpackArrayTo(int))
world.setting = generateFunc("world.setting")
# Checkpoint
world.checkpoint = Holder()
world.checkpoint.save = generateFunc("world.checkpoint.save")
world.checkpoint.restore= generateFunc("world.checkpoint.restore")
# = generateFunc("entity.getType
# Player
player = Holder()
player.setTile = generateFunc("player.setTile")
player.getTile = generateFunc("player.getTile", readV3ints)
player.setPos = generateFunc("player.setPos")
player.getPos = generateFunc("player.getPos", readV3)
player.setting = generateFunc("player.setting")
# Camera
camera = Holder()
camera.setNormal = generateFunc("camera.mode.setNormal")
#camera.setThirdPerson = generateFunc("camera.mode.setThirdPerson")
camera.setFixed = generateFunc("camera.mode.setFixed")
camera.setFollow = generateFunc("camera.mode.setFollow")
camera.setPos = generateFunc("camera.setPos")
#setCameraFollow1 = generateFunc("camera.mode.setFollowWithPosition")
#setCameraFollow2 = generateFunc("camera.mode.setFollowWithRotation")
# Events
events = Holder()
events.block = Holder()
events.block.hits = generateFunc("events.block.hits", unpackArrayTo(TileEvent.Hit, int))
#pollChat = generateFunc("events.chat", unpackArrayTo(TileEvent.Hit, int))
# Chat
chat = Holder()
chat.post = generateFunc("chat.post")
from functools import partial
setAutojump = partial(player.setting, "autojump")

13
project/raspberry/py/apiutil.py Executable file
View File

@@ -0,0 +1,13 @@
import collections
def flatten(l):
for e in l:
if isinstance(e, collections.Iterable) and not isinstance(e, basestring):
for ee in flatten(e): yield ee
else: yield e
def toParameters(l):
return ",".join(map(str, flatten(l)))
def call(name, *l):
return "%s(%s)\n"%(name, toParameters(l))

19
project/raspberry/py/event.py Executable file
View File

@@ -0,0 +1,19 @@
from vec3 import Vec3
class TileEvent:
HIT = 0
def __init__(self, type, x, y, z, face, entityId):
self.type = type
self.pos = Vec3(x, y, z)
self.face = face
self.entityId = entityId
def __str__(self):
types = {TileEvent.HIT: "Hit"}
return "TileEvent(%s @ %s:%d by %d)"%(types.get(self.type, 0),
self.pos, self.face, self.entityId);
@staticmethod
def Hit(x, y, z, face, entityId):
return TileEvent(TileEvent.HIT, x, y, z, face, entityId)

View File

@@ -0,0 +1,199 @@
import time, random
import api, kbhelp
from vec3 import Vec3
class BlockType:
AIR = 0
ROCK = 1
DIRT = 3
SANDSTONE = 24
CLOTH = 35
CACTUS = 81
class ClothColor:
WHITE = 0
RED = 14
@staticmethod
def dark(x): return x + 8 if x < 8 else x
def bright(x): return x - 8 if x >= 8 else x
class Level:
Wall = BlockType.DIRT
Food = BlockType.SANDSTONE
def __init__(self, w, h, pos=Vec3(0,0,0)):
self.w = w
self.h = h
self.pos = pos
self.m = [0] * (w * h)
def setup(self, numApples):
size = Vec3(self.w-1, 0, self.h-1)
margin = Vec3(1, 0, 1)
api.world.setBlocks(self.pos - margin + Vec3.down(3), self.pos + size + margin, BlockType.ROCK)
api.world.setBlocks(self.pos, self.pos + size + Vec3.up(8), BlockType.AIR)
for i in random.sample(range(self.w * self.h), numApples):
xx = i % self.w
yy = i / self.w
self.m[i] = Level.Food
api.world.setBlock(xx, self.pos.y, yy, Level.Food)
def getTile(self, x, y):
return self.m[y * self.w + x] if self.inRange(x, y) else None
def clearTile(self, x, y):
if self.inRange(x, y): self.m[y * self.w + x] = 0
def isFood(self, x, y):
return self.inRange(x, y) and Level.Food == self.getTile(x, y)
def isWall(self, x, y):
return (not self.inRange(x, y)) or Level.Wall == self.getTile(x, y)
def inRange(self, x, y):
return x >= 0 and y >= 0 and x < self.w and y < self.h
def countApples(self):
return self.m.count(Level.Food)
class Snake:
def __init__(self, pos=Vec3(0,0,0), length=5):
self.dir = Vec3(1, 0, 0)
self.seg = [pos]
self.dead = False
self.growTicks = 0
for i in range(length-1):
self._add()
def left(self): self.dir.rotateLeft()
def right(self): self.dir.rotateRight()
def next(self):
return self.head() + self.dir
def head(self):
return self.seg[-1]
def tick(self):
self._add()
if self.growTicks == 0: self._remove()
if self.growTicks > 0: self.growTicks -= 1
def _add(self):
n = self.next()
if n in self.seg:
self.kill()
return
self.seg.append( n )
api.world.setBlock(n.x, n.y, n.z, 45)
def _remove(self):
h, self.seg = self.seg[0], self.seg[1:]
api.world.setBlock(h.x, h.y, h.z, 0)
def grow(self, ticks):
self.growTicks = ticks
def kill(self):
for p in self.seg:
api.world.setBlock(p.x, p.y, p.z, BlockType.CLOTH, 14)
self.dead = True
class SnakeGame:
def __init__(self, numSnakes):
self.numSnakes = numSnakes
self.snakes = []
self.level = None
self.noActionTicks = 10
def startLevel(self, level, numApples=8):
self.level = level
self.level.setup(numApples)
self.snakes = [Snake(Vec3(3, 0, 3)) for x in range(self.numSnakes)]
self.noActionTicks = 10
for s in self.snakes:
for t in s.seg: self.level.clearTile(t.x, t.z)
api.camera.setFixed()
api.camera.setPos(Vec3((level.w-1)/2.0, 10, level.h/2.0 - 1))
def tick(self):
if self.noActionTicks > 0:
self.noActionTicks -= 1
return
for s in self.snakes:
self.tickSnake(s)
def tickSnake(self, snake):
if snake.dead: return
self.onTile(snake, snake.next())
if not snake.dead: snake.tick()
def isFinished(self):
return self.isWon() or self.allSnakesDead()
def isWon(self):
#print self.level.countApples()
return self.level.countApples() == 0
def allSnakesDead(self):
for s in self.snakes:
if not s.dead: return False
return True
def onTile(self, snake, pos):
x, y = pos.x, pos.z
if self.level.isWall(x, y): snake.kill()
if self.level.isFood(x, y): snake.grow(2)
self.level.clearTile(x, y)
def run():
kb = kbhelp.KeyboardInput()
keys = (('a', 'd'),
('4', '6'))
numSnakes = 1
def play(level, numApples, tickDelay):
g = SnakeGame(numSnakes)
g.startLevel(Level(16, 12), numApples)
api.chat.post("Snake - level %d"%level)
while 1:
# Update input
if kb.hasChar():
key = kb.readChar()
for i in range(min(len(g.snakes), len(keys))):
LeftKey, RightKey = keys[i]
s = g.snakes[i]
if key == LeftKey: s.left()
if key == RightKey: s.right()
# Update game
g.tick()
time.sleep(tickDelay)
if g.isFinished():
return g.isWon()
delay = 0.15
level = 0
apples = 5
while 1:
level += 1
apples += 1
won = play(level, apples, delay)
if not won:
api.chat.post("Snake - Game over! [ level %d ]!"%level)
return
delay -= 0.01
if delay < 0.04:
return
if __name__ == "__main__":
run()

38
project/raspberry/py/image.py Executable file
View File

@@ -0,0 +1,38 @@
import Image
import apiutil
def hexToRgb(hex):
return (hex >> 16) & 255, (hex >> 8) & 255, hex & 255
cgaColors = map(hexToRgb, (
0x000000,
0x0000A8,
0x00A800,
0x00A8A8,
0xFF0000,
0xA800A8,
0xA85400,
0xA8A8A8,
0x545454,
0x5454FE,
0x54FE54,
0x54FEFE,
0xFE5454,
0xFE54FE,
0xFEFE54,
0xFEFEFE))
cgaPalette = apiutil.flatten(cgaColors)
def _padPalette(values, count):
v = tuple(values)
return v + (0, 0, 0) * (count - len(v))
def imageToCga(im):
p = Image.new("P", (1,1))
p.putpalette(_padPalette(cgaPalette, 256))
return im.convert("RGB").quantize(palette=p, kmeans=255)
def imageToWool(im, (w, h)):
cga = imageToCga(im.resize((w, h)))

60
project/raspberry/py/kbhelp.py Executable file
View File

@@ -0,0 +1,60 @@
try:
import msvcrt
"""Win32 implementation of a keyboard input reader"""
class KeyboardInput_win32:
def __init__(self):
self.setBlocking(True)
def clear(self):
while 1:
if self.readChar_nonblocking() is None:
break
def setBlocking(self, block):
self.readChar = self.readChar_blocking if block else \
self.readChar_nonblocking
def hasChar(self):
return msvcrt.kbhit()
def readChar_blocking(self):
return msvcrt.getch()
def readChar_nonblocking(self):
if not msvcrt.kbhit(): return None
return msvcrt.getch()
KeyboardInput = KeyboardInput_win32
except:
try:
class KeyboardInput_unix:
def hasChar(self):
import sys, tty, termios
from select import select
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
[i, o, e] = select([sys.stdin.fileno()], [], [], 5)
if i: ch = True
else: ch = False
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
def readChar(self):
import sys, tty, termios
from select import select
fd = sys.stdin.fileno()
old_settings = termios.tcgetattr(fd)
try:
tty.setraw(sys.stdin.fileno())
ch = sys.stdin.read(1)
finally:
termios.tcsetattr(fd, termios.TCSADRAIN, old_settings)
return ch
KeyboardInput = KeyboardInput_unix
except: pass

Binary file not shown.

After

Width:  |  Height:  |  Size: 3.5 KiB

80
project/raspberry/py/vec3.py Executable file
View File

@@ -0,0 +1,80 @@
class Vec3:
def __init__(self, x=0, y=0, z=0):
self.x = x
self.y = y
self.z = z
def __add__(self, rhs):
c = self.clone()
c += rhs
return c
def __iadd__(self, rhs):
self.x += rhs.x
self.y += rhs.y
self.z += rhs.z
return self
def clone(self):
return Vec3(self.x, self.y, self.z)
def __neg__(self):
return Vec3(-self.x, -self.y, -self.z)
def __sub__(self, rhs):
return self.__add__(-rhs)
def __isub__(self, rhs):
return self.__iadd__(-rhs)
def __repr__(self):
return "Vec3(%s,%s,%s)"%(self.x,self.y,self.z)
def __iter__(self):
return iter((self.x, self.y, self.z))
def _map(self, func):
self.x = func(self.x)
self.y = func(self.y)
self.z = func(self.z)
def __cmp__(self, rhs):
dx = self.x - rhs.x
if dx != 0: return dx
dy = self.y - rhs.y
if dy != 0: return dy
dz = self.z - rhs.z
if dz != 0: return dz
return 0
def iround(self): self._map(lambda v:int(v+0.5))
def ifloor(self): self._map(int)
def rotateLeft(self): self.x, self.z = self.z, -self.x
def rotateRight(self): self.x, self.z = -self.z, self.x
@staticmethod
def y(n=1): return Vec3(0, n, 0)
@staticmethod
def up(n=1): return Vec3.y(n)
@staticmethod
def down(n=1): return Vec3.y(-n)
def testVec3():
# Note: It's not testing everything
# 1.1 Test initialization
it = Vec3(1, -2, 3)
assert it.x == 1
assert it.y == -2
assert it.z == 3
# 2.1 Test cloning and equality
clone = it.clone()
assert it == clone
it.x += 1
assert it != clone
# Test repr
e = eval(repr(it))
assert e == it