Return Styles: Pseud0ch, Terminal, Valhalla, NES, Geocities, Blue Moon. Entire thread

New coding contest

Name: Anonymous 2009-11-28 15:49

We haven't had one in a while so let's have a new coding contest. I'm open to suggestions for the challenge, but if we don't have any good suggestions we will default to something stupid like "implement cowsay in erlang shitty language X".

Name: Anonymous 2009-11-29 21:04

Fully functional Tetris with a touch of Fibonacci.  My first FIOC.  Shouldn't be too hard to integrate a Pong if you're into that sort of thing.

#!/usr/bin/python

from curses import *
from curses.wrapper import *
import time
import random

blockShapes = [
    # http://tetris.wikia.com/wiki/File:NESTetris-pieces.png
    [[ (1, 1), (2, 1), (1, 2), (2, 2) ]]*4,    # O
    [[ (0, 1), (1, 1), (2, 1), (3, 1) ],
     [ (2, 0), (2, 1), (2, 2), (2, 3) ]]*2,    # I
    [[ (1, 1), (2, 1), (1, 2), (0, 1) ],
     [ (1, 1), (1, 2), (0, 1), (1, 0) ],
     [ (1, 1), (0, 1), (1, 0), (2, 1) ],
     [ (1, 1), (1, 0), (2, 1), (1, 2) ]],    # T
    [[ (1, 1), (2, 1), (1, 2), (0, 2) ],
     [ (1, 0), (1, 1), (2, 1), (2, 2) ]]*2,    # S
    [[ (1, 1), (2, 2), (1, 2), (0, 1) ],
     [ (1, 1), (2, 0), (2, 1), (1, 2) ]]*2,    # Z
    [[ (2, 1), (1, 1), (0, 1), (0, 2) ],
     [ (1, 2), (1, 1), (1, 0), (0, 0) ],
     [ (0, 1), (1, 1), (2, 1), (2, 0) ],
     [ (1, 0), (1, 1), (1, 2), (2, 2) ]],    # L
    [[ (2, 2), (1, 2), (0, 2), (0, 1) ],
     [ (1, 3), (1, 2), (1, 1), (2, 1) ],
     [ (0, 2), (1, 2), (2, 2), (2, 3) ],
     [ (1, 1), (1, 2), (1, 3), (0, 3) ]],    # J
]

boardSymbols = ["  "] + ["()"]*7 + ["%%"]    # empty, 7 normal blocks, garbage

def fibs(n):
    a, b = 0, 1
    for i in xrange(n):
        a, b = b, a + b
    return a

class Tetris:
    RUNNING, LOST = range(2)    # gamestate values
   
    def __init__(self, nrows, ncols):
        self.nrows = nrows
        self.ncols = ncols
        self.board = [[0]*ncols for y in xrange(nrows)]
        self.blockbuf = []
        self.falling = None    # (type, rotation, (x, y))
        self.gamestate = Tetris.RUNNING
        self.score = 0
        self.level = 0
        self.preview = None
   
    def genBlock(self):
        if not self.blockbuf:
            self.blockbuf = range(7)
            random.shuffle(self.blockbuf)
        return self.blockbuf.pop()
   
    def nextBlock(self):
        block = self.preview
        if block == None:
            block = self.genBlock()
        self.preview = self.genBlock()
        return block
   
    def squaresOccupiedBy(self, (type, rotation, (x, y))):
        shape = blockShapes[type][rotation]
        return [(x+s[0], y+s[1]) for s in shape]
   
    def blockFits(self, newBlock):
        for (x,y) in self.squaresOccupiedBy(newBlock):
            if x < 0 or x >= self.ncols or y < 0 or y >= self.nrows or self.board[y][x]:
                return False
        return True
   
    def placeBlock(self, newBlock, allowClear=True):
        for (x,y) in self.squaresOccupiedBy(newBlock):
            self.board[y][x] = newBlock[0]+1
        if allowClear:
            self.clearFullRows()
   
    def clearFullRows(self):
        ncleared = 0
        runStart = None
        def clear(start, until):
            n = until - start
            self.board = [[0]*self.ncols for y in xrange(n)] \
                + self.board[0:start] + self.board[until:]
            return n
        for y in xrange(self.nrows):
            if 0 in self.board[y]:
                if runStart != None:
                    ncleared += clear(runStart, y)
                    runStart = None
            elif runStart == None:
                runStart = y
        if runStart != None:
            ncleared += clear(runStart, self.nrows)
        if ncleared:
            self.score += 50 * ncleared * (ncleared + 1)
            self.maybeLevelUp()
   
    def maybeLevelUp(self):
        while self.score >= 1000 * fibs(self.level + 1):
            self.addGarbageRows(self.level)
            self.level += 1
   
    def addGarbageRows(self, count):
        self.board = self.board[count:]
        for row in xrange(count):
            self.board.append([8*random.randrange(0, 2) for x in xrange(self.ncols)])
       
    def drawBoard(self, window):
        window.border(0, 0, 32)
        window.addch(0, 0, 32)
        window.addch(0, 21, 32)
        for y in xrange(self.nrows):
            for x in xrange(self.ncols):
                window.addstr(1 + y, 1 + 2*x, boardSymbols[self.board[y][x]])
        if self.falling:
            for (x,y) in self.squaresOccupiedBy(self.falling):
                if x >= 0 and x < self.ncols and y >= 0 and y < self.nrows:
                    window.addstr(1 + y, 1 + 2*x, "[]")
   
    def drawPreview(self, window, x0, y0):
        for y in xrange(y0 + 1, y0 + 3):
            window.addstr(y, x0, "        ")
        if self.preview != None:
            for (x,y) in blockShapes[self.preview][0]:
                window.addstr(y0 + y, x0 + 2*x, "[]")
   
    def step(self):
        if self.gamestate != Tetris.RUNNING:
            return
        if self.falling:
            (type, rotation, (x, y)) = self.falling
            newPos = (type, rotation, (x, y+1))
            if self.blockFits(newPos):
                self.falling = newPos
            else:
                self.placeBlock(self.falling)
                self.falling = None
        else:
            newBlock = (self.nextBlock(), 0, (self.ncols//2 - 2, 0))
            if self.blockFits(newBlock):
                self.falling = newBlock
            else:
                self.placeBlock(newBlock, False)
                self.gamestate = Tetris.LOST
   
    def shift(self, dir):
        if self.falling:
            (type, rotation, (x, y)) = self.falling
            newPos = (type, rotation, (x+dir, y))
            if self.blockFits(newPos):
                self.falling = newPos
   
    def rotate(self, dir):
        if self.falling:
            (type, rotation, (x, y)) = self.falling
            newPos = (type, (rotation+dir)%4, (x, y))
            if self.blockFits(newPos):
                self.falling = newPos
   
    def drop(self):
        if self.falling:
            (type, rotation, (x, y)) = self.falling
            newPos = self.falling
            for ny in xrange(y+1, self.nrows):
                testPos = (type, rotation, (x, ny))
                if self.blockFits(testPos):
                    newPos = testPos
                else:
                    break
            self.placeBlock(newPos)
            self.falling = None

def tet(screen):
    try:
        curs_set(0)
    except:
        pass
    halfdelay(1)
    t = Tetris(20, 10)
    window = screen.derwin(22, 22, 0, 10)
    window.keypad(1)
    def redraw():
        t.drawBoard(window)
        window.refresh()
        screen.addstr( 8, 35, "LEFT/RIGHT to move")
        screen.addstr( 9, 35, "    UP     to spin")
        screen.addstr(10, 35, "   DOWN    to drop")
        screen.addstr(11, 35, "    Q      to quit")
        screen.addstr(14, 35, "Level: " + str(t.level))
        screen.addstr(15, 35, "Score: " + str(t.score))
        screen.addstr(16, 35, "Next:")
        t.drawPreview(screen, 36, 17)
        screen.move(0, 0)
        screen.refresh()
    while True:
        gamespeed = .5 - .03 * t.level
        nextStep = time.time() + gamespeed
        redraw()
        while time.time() < nextStep:
            key = window.getch()
            if key == ERR:
                pass
            elif key == KEY_LEFT:
                t.shift(-1)
                redraw()
            elif key == KEY_RIGHT:
                t.shift(1)
                redraw()
            elif key == KEY_UP:
                t.rotate(1)
                redraw()
            elif key == KEY_DOWN:
                t.drop()
                break
            elif key in [ord('q'), ord('Q')]:
                return
        t.step()
        if t.gamestate == Tetris.LOST:
            redraw()
            screen.addstr(22, 10, "***  You have died  ***")
            screen.refresh()
            while window.getch() not in [ord('q'), ord('Q'), 10]: pass
            return

wrapper(tet)

Newer Posts
Don't change these.
Name: Email:
Entire Thread Thread List