191 lines
5.0 KiB
Python
Executable File
191 lines
5.0 KiB
Python
Executable File
#
|
|
# requires Windows and pywin32
|
|
#
|
|
from mc import *
|
|
from time import sleep,time
|
|
from random import randint
|
|
import win32con,win32api
|
|
|
|
HEIGHT = 22
|
|
WIDTH = 9
|
|
BORDER = WOOL_BLACK
|
|
BACKGROUND = STAINED_GLASS_BLACK
|
|
|
|
PIECES = ( (('XXXX',), ('.X','.X','.X','.X')),
|
|
(('XX','XX'),),
|
|
(('XXX', '..X'), ('.X', '.X', 'XX'), ('X','XXX'), ('XX', 'X', 'X')),
|
|
(('XXX', 'X'), ('XX', '.X', '.X'), ('..X', 'XXX'), ('X.', 'X.', 'XX')),
|
|
(('XX', '.XX'), ('.X','XX', 'X.')),
|
|
(('.XX', 'XX'), ('X.', 'XX', '.X')) )
|
|
|
|
def drawBoard():
|
|
mc.setBlocks(left-1, bottom-1, plane, left+WIDTH, bottom-1, plane, BORDER)
|
|
mc.setBlocks(left-1, bottom+HEIGHT, plane, left+WIDTH, bottom+HEIGHT, plane, BORDER)
|
|
mc.setBlocks(left-1, bottom, plane, left, bottom+HEIGHT-1, plane, BORDER)
|
|
mc.setBlocks(left+WIDTH, bottom, plane, left+WIDTH, bottom+HEIGHT-1, plane, BORDER)
|
|
mc.setBlocks(left-1, bottom-1, plane-1, left+WIDTH, bottom+HEIGHT, plane-1, BACKGROUND)
|
|
mc.setBlocks(left, bottom, plane, left+WIDTH-1, bottom+HEIGHT-1, plane, AIR)
|
|
|
|
def pieceWidth(piece):
|
|
return max((len(a) for a in piece[orientation]))
|
|
|
|
def enumeratePiece(x, y, piece):
|
|
for row in range(len(piece)):
|
|
for col in range(len(piece[row])):
|
|
if piece[row][col] == 'X':
|
|
yield (x+col,y-row)
|
|
|
|
def erasePiece(buffer, x, y, piece):
|
|
for (xx,yy) in enumeratePiece(x,y, piece):
|
|
buffer[(left+xx,bottom+yy)] = AIR
|
|
|
|
def drawPiece(buffer, x, y, piece, color):
|
|
for (xx,yy) in enumeratePiece(x,y, piece):
|
|
if (left+xx,bottom+yy) in buffer and buffer[(left+xx,bottom+yy)] == AIR:
|
|
del buffer[(left+xx,bottom+yy)]
|
|
else:
|
|
buffer[(left+xx,bottom+yy)] = color
|
|
|
|
def drawBuffer(buffer):
|
|
for x,y in buffer:
|
|
mc.setBlock(x,y,plane,buffer[(x,y)])
|
|
|
|
def placePiece():
|
|
global pieceNum, color, family, orientation, x, y, fall, descendDelay
|
|
pieceNum = randint(0, len(PIECES)-1)
|
|
color = Block(WOOL.id, (pieceNum+1) % 16)
|
|
family = PIECES[pieceNum]
|
|
orientation = 0
|
|
x = WIDTH // 2 - pieceWidth(family[orientation])
|
|
y = HEIGHT - 1
|
|
descendDelay = currentDescendDelay
|
|
fall = False
|
|
|
|
def fit(x, y, piece):
|
|
for (xx,yy) in enumeratePiece(x, y, piece):
|
|
if yy >= HEIGHT or yy < 0 or xx >= WIDTH or xx < 0 or board[xx][yy] is not None:
|
|
return False
|
|
return True
|
|
|
|
|
|
def descend():
|
|
global descendTimer
|
|
if descendTimer + descendDelay <= time():
|
|
descendTimer += descendDelay
|
|
return True
|
|
return False
|
|
|
|
def moveDown():
|
|
return (win32api.GetAsyncKeyState(win32con.VK_DOWN)&1)
|
|
|
|
def moveLeft():
|
|
return (win32api.GetAsyncKeyState(win32con.VK_LEFT)&1)
|
|
|
|
def moveRight():
|
|
return (win32api.GetAsyncKeyState(win32con.VK_RIGHT)&1)
|
|
|
|
def rotateLeft():
|
|
return (win32api.GetAsyncKeyState(win32con.VK_PRIOR)&1)
|
|
|
|
def rotateRight():
|
|
return (win32api.GetAsyncKeyState(win32con.VK_NEXT)&1) or (win32api.GetAsyncKeyState(win32con.VK_UP)&1)
|
|
|
|
def addPiece(x, y, piece, color):
|
|
for (xx,yy) in enumeratePiece(x, y, piece):
|
|
board[xx][yy] = color
|
|
while True:
|
|
foundRow = False
|
|
for y in range(HEIGHT):
|
|
full = True
|
|
for x in range(WIDTH):
|
|
if board[x][y] is None:
|
|
full = False
|
|
break
|
|
if full:
|
|
foundRow = True
|
|
for y2 in range(y, HEIGHT-1):
|
|
for x in range(WIDTH):
|
|
b = board[x][y2+1]
|
|
board[x][y2] = b
|
|
mc.setBlock(left+x,bottom+y2,plane,b if b is not None else AIR)
|
|
for x in range(WIDTH):
|
|
board[x][HEIGHT-1] = None
|
|
mc.setBlock(left+x,bottom+HEIGHT-1,plane,AIR)
|
|
|
|
if not foundRow:
|
|
break
|
|
|
|
|
|
mc = Minecraft()
|
|
|
|
playerPos = mc.player.getTilePos()
|
|
mc.player.setRotation(180)
|
|
mc.player.setPitch(-30)
|
|
mc.player.setTilePos(playerPos.x, playerPos.y, playerPos.z + 10)
|
|
left = playerPos.x - WIDTH // 2
|
|
plane = playerPos.z
|
|
bottom = playerPos.y + 1
|
|
board = [[None for i in range(HEIGHT)] for j in range(WIDTH)]
|
|
currentDescendDelay = 0.5
|
|
|
|
drawBoard()
|
|
|
|
newPiece = True
|
|
|
|
while True:
|
|
if newPiece:
|
|
placePiece()
|
|
oldPiece = None
|
|
if not fit(x, y, family[orientation]):
|
|
mc.postToChat("Doesn't fit: End of game")
|
|
print "no fit"
|
|
break
|
|
draw = True
|
|
newPiece = False
|
|
descendTimer = time()
|
|
else:
|
|
oldPiece = family[orientation]
|
|
draw = False
|
|
oldX = x
|
|
oldY = y
|
|
|
|
if not fall:
|
|
if moveLeft() and fit(x-1, y, family[orientation]):
|
|
x -= 1
|
|
draw = True
|
|
|
|
if moveRight() and fit(x+1, y, family[orientation]):
|
|
x += 1
|
|
draw = True
|
|
|
|
if rotateLeft() and fit(x, y, family[(orientation-1)%len(family)]):
|
|
orientation = (orientation-1)%len(family)
|
|
draw = True
|
|
|
|
if rotateRight() and fit(x, y, family[(orientation+1)%len(family)]):
|
|
orientation = (orientation+1)%len(family)
|
|
draw = True
|
|
|
|
if moveDown():
|
|
fall = True
|
|
descendDelay = 0.05
|
|
|
|
if descend():
|
|
if not fit(x, y-1, family[orientation]):
|
|
addPiece(x, y, family[orientation], color)
|
|
newPiece = True
|
|
else:
|
|
draw = True
|
|
y -= 1
|
|
|
|
if draw:
|
|
buffer = {}
|
|
if oldPiece:
|
|
erasePiece(buffer, oldX, oldY, oldPiece)
|
|
drawPiece(buffer, x, y, family[orientation], color)
|
|
drawBuffer(buffer)
|
|
|
|
sleep(0.1)
|
|
|
|
print "done"
|