continuity

curses game inspired by continuitygame.com
git clone https://a3nm.net/git/continuity/
Log | Files | Refs | README

commit da08927a85bbaf51133c1a1781733e88b22e6ccc
Author: Antoine Amarilli <ant.amarilli@free.fr>
Date:   Sat, 19 Dec 2009 04:08:25 +0100

Added files.

Diffstat:
level | 27+++++++++++++++++++++++++++
level2 | 134+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
level2.best | 10++++++++++
levelb | 30++++++++++++++++++++++++++++++
levelc | 26++++++++++++++++++++++++++
leveld | 42++++++++++++++++++++++++++++++++++++++++++
levele | 26++++++++++++++++++++++++++
main.py | 423+++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++++
8 files changed, 718 insertions(+), 0 deletions(-)

diff --git a/level b/level @@ -0,0 +1,27 @@ +2 +2 +0 +1 +5 +5 +##### Level syntax tips +#@ # First line is number of block lines +###% Second line is number of block cols +#* % Third line is line position of empty block +##### Fourth line is col position of empty block + Fifth line is width of blocks + Sixth line is height of blocks + Following lines are description of blocks one after the other + Blocks will be assigned left to right and then top to bottom + (ie. give the blocks for the first line, then second line, etc.) +##### If there are too many characters on a line, they get ignored +# %% You can use this to write comments (like these) + % # The following sprites are allowed: + %# # - ' ' is empty space (player falls thru, can walk thru) +##### - '#' is a wall (player can walk over, can't pass thru) +##### - '%' is a ladder (player can walk over, can climb over) + ^# - '*' is a key (collect all to open the exit +#%### - '^' is an exit (reach any with all keys to win) +#% *# - '@' is the player's start position (only one allowed, will be empty space when player leaves it) +##### PS: you must give a block description for the empty block, it + will be ignored diff --git a/level2 b/level2 @@ -0,0 +1,134 @@ +4 +4 +3 +3 +8 +8 + ## + ## + @ ## ^ + # ## # + ## + ## + ## + ## end + ## + # + ##### + + + + + ## end + + + + +### ### +### ### + + end + ## + ## + ## + ## + ## ## + ## ## + ## + ## End + ## + ## + *## + ### + ## # + ## + ## + ## end + + + + %%%%## +# +# + + end + + + + ##%%%% + # + # + + end + ## + ## + ## + ## +######## +######## + + End + + + % % + # # ## + + + + end + ## + +### + # + ###### + ###### + + end + + + % % + # # ## + + + + end + ## + ## + ## + ## +## ## +## ## + ## + ## End + + + + +###### +###### + + end + ## + ## + ## + ## + ## ## + ## ## + ## + ## end + + * + %##% + %####% + ###### + + + END + BLANK + BLANK + BLANK + BLANK + BLANK + BLANK + BLANK + BLANK diff --git a/level2.best b/level2.best @@ -0,0 +1,10 @@ + Your score was: + Moves: 14 + Dist: 62 + Swaps: 55 + + +Your score was: + Moves: 20 + Dist: 52 + Swaps: 79 diff --git a/levelb b/levelb @@ -0,0 +1,30 @@ +2 +2 +0 +1 +6 +6 +###### +# @ +###### +# +# ^ +###### + + + + + + +###### + +###### + ### + +###### +###### + ## +# ## # +# ## # + ## +###### diff --git a/levelc b/levelc @@ -0,0 +1,26 @@ +2 +2 +1 +1 +5 +5 +##### +# @# +# ## +# # +### # +### # +# # +# ### +# # +# # # +# # # +# ^ # + #### +# +##### + + + + + diff --git a/leveld b/leveld @@ -0,0 +1,42 @@ +2 +3 +1 +2 +6 +8 +## ##### +## @ # +##### # +##### # +## # +## ##### +### # ## + # # ## +### # ## + # # + #### # +## ## # +## ##### +## +######## + # + # +### # ## +## ## # +## # +###### # +## # +## ^ # +## ##### +######## + #### +### #### + # + # +## ##### + + + + + + diff --git a/levele b/levele @@ -0,0 +1,26 @@ +2 +2 +1 +0 +5 +10 + + + + + # + + + ^ +@ +# + + + + + +# + + + + diff --git a/main.py b/main.py @@ -0,0 +1,423 @@ +#/usr/bin/python + + +import sys +import curses + + +class Square: + wall, ladder, empty, exit, player, blank, key = range(7) + asciiMap = {wall: '#', ladder:'%', empty:' ', exit:'^', player:'@', blank:'!', key:'*'} + + def __init__(self, parent, type, pos): + self.parent = parent + self.type = type + self.pos = pos + + def getNeighbour(self, dir): + return self.parent.getSquare((self.pos[0] + dir[0], self.pos[1] + dir[1])) + + def getType(self): + return self.type + + def setType(self, type): + self.type = type + + def render(self, pad, x, y): + if (self.parent.parent.getPlayer().getPos() == self): + self.parent.parent.getPlayer().setGraphPos((x + self.pos[0],y + self.pos[1])) + c = '@' + mode = curses.A_BOLD + curses.A_BLINK + curses.color_pair(1) + else: + if (self.parent.parent.getPlayer().getPos().getParent() == self.parent): + mode = curses.A_BOLD + else: + mode = 0 + c = Square.asciiMap[self.type] + if (c == '^'): + if (self.parent.parent.keysLeft() == True): + mode = curses.A_BOLD + curses.color_pair(8) + else: + mode = curses.A_BOLD + curses.color_pair(2) + if (c == '%'): mode = curses.color_pair(3) + if (c == '#'): mode = curses.color_pair(4) + if (c == '!'): + mode = curses.color_pair(5) + pad.addch( x + self.pos[0],y + self.pos[1], c, mode) + c = ' ' + if (c == '*'): mode = curses.A_BOLD + curses.color_pair(2) + try: + pad.addch( x + self.pos[0],y + self.pos[1], c, mode) + except curses.error: + pass + + def getParent(self): + return self.parent + + +class Block: + left, right, top, bottom = range(4) + def __init__(self, parent, h, w, pos): + self.parent = parent + self.h = h + self.w = w + self.pos = pos + self.map = [] + for i in range(0, h): + self.map.append([]) + for j in range(0, w): + self.map[i].append(Square(self, 0, (0, 0))) + + def getBorder(self, t): + a = [] + if (t == Block.left): + for i in range(0, self.h): + a.append(self.getSquare((i,0)).getType()) + if (t == Block.right): + for i in range(0, self.h): + a.append(self.getSquare((i, self.w-1)).getType()) + if (t == Block.top): + for i in range(0, self.w): + a.append(self.getSquare((0, i)).getType()) + if (t == Block.bottom): + for i in range(0, self.w): + a.append(self.getSquare((self.h-1, i)).getType()) + return a + + def getNeighbour(self, dir): + return self.parent.getBlock((self.pos[0] + dir[0], self.pos[1] + dir[1])) + + def setSquare(self, x, y, s): + self.map[x][y] = s + + def getSquare(self, p): + x = p[0] + y = p[1] + if (x < 0): + a = self.getNeighbour((-1, 0)) + if (self.getBorder(Block.top) != a.getBorder(Block.bottom)): + return BlockSentry(self.parent, 0, 0, (0, 0)).getSquare((0,0)) + return a.getSquare((a.getH() + p[0], p[1])) + elif (y < 0): + a = self.getNeighbour((0, -1)) + if (self.getBorder(Block.left) != a.getBorder(Block.right)): + return BlockSentry(self.parent, 0, 0, (0, 0)).getSquare((0,0)) + return a.getSquare((p[0], a.getW() + p[1])) + elif (x >= self.getH()): + a = self.getNeighbour((1, 0)) + if (self.getBorder(Block.bottom) != a.getBorder(Block.top)): + return BlockSentry(self.parent, 0, 0, (0, 0)).getSquare((0,0)) + return a.getSquare((p[0] - self.getH(), p[1])) + elif (y >= self.getW()): + a = self.getNeighbour((0, 1)) + if (self.getBorder(Block.right) != a.getBorder(Block.left)): + return BlockSentry(self.parent, 0, 0, (0, 0)).getSquare((0,0)) + return a.getSquare((p[0], p[1] - self.getW())) + else: + return self.map[x][y] + + def getW(self): + return self.w + + def getH(self): + return self.h + + def render(self, pad, x, y): + for i in self.map: + for j in i: + j.render(pad, x, y) + + def loadFromFile(self, f): + for i in range(0, self.getH()): + l = f.readline() + for j in range(0, self.getW()): + x = l[j] + c = {v:k for k, v in Square.asciiMap.items()}[x] + if (x == '*'): + self.parent.addKey() + if (x == '@'): + c = Square.empty + self.map[i][j] = Square(self, c, (i, j)) + if (x == '@'): + self.parent.getPlayer().setPos(self.map[i][j]) + + + def move(self, p): + self.pos = (self.pos[0] + p[0], self.pos[1] + p[1]) + + + +class BlockSentry(Block): + def getSquare(self, p): + return Square(self, Square.blank, (0,0)) + + def render(self, pad, x, y): + for i in range(0, self.h): + for j in range(0, self.w): + (Square(self, Square.blank, (i,j))).render(pad, x, y) + +class Player: + keyMap = {(0, -1): 'h', (1, 0):'j', (-1, 0):'k', (0, 1): 'l'} + + def __init__(self, parent, square): + self.parent = parent + self.pos = square + self.graphPos = (0,0) + + def render(self, pad): + pad.move(self.graphPos[0], self.graphPos[1]) + + def setGraphPos(self, p): + self.graphPos = p + + def move(self, direction, volont): + a = self.pos.getNeighbour(direction) + if (a.getType() != Square.wall and a.getType() != Square.blank): + self.pos = a + self.parent.addDist() + if (volont == True): self.parent.addMoves() + if (self.pos.getType() == Square.key): + self.parent.removeKey() + self.pos.setType(Square.empty) + if (self.pos.getType() == Square.exit and not self.parent.keysLeft()): + return True + else: + return self.fall() + + def getPos(self): + return self.pos + + def setPos(self, pos): + self.pos = pos + + def fall(self): + a = self.pos.getType() + b = self.pos.getNeighbour((1,0)).getType() + while (self.pos.getType() != Square.ladder and (self.pos.getNeighbour((1,0)).getType() == Square.empty or self.pos.getNeighbour((1,0)).getType() == Square.key or self.pos.getNeighbour((1,0)).getType() == Square.exit)): + if self.move((1, 0), 0): + return True + return False + + +class Level: + codeMap = {104: 'h', 106:'j', 107:'k', 108: 'l', 113: 'q', 72: 'H', 74:'J', 75: 'K', 76:'L'} + def __init__(self, h, w, x, y): + self.h = h + self.w = w + self.holeX = x + self.holeY = y + self.map = [] + self.keys = 0 + self.cswap = 0 + self.cmove = 0 + self.cdist = 0 + for i in range(0, h): + self.map.append([]) + for j in range(0, w): + self.map[i].append(Block(0, 0, 0, 0)) + self.player = Player(self, Square(0, 0, (0,0))) + + def loadFromFile(self, f): + bh = int(f.readline()) + bw = int(f.readline()) + for i in range(0, self.h): + for j in range(0, self.w): + if ((i, j) != (self.holeX, self.holeY)): + self.map[i][j] = Block(self, bh, bw, (i, j)) + else: + self.map[i][j] = BlockSentry(self, bh, bw, (i, j)) + self.map[i][j].loadFromFile(f) + + def addKey(self): + self.keys+=1 + + def addDist(self): + self.cdist += 1 + + def addMoves(self): + self.cmove += 1 + + def addSwap(self): + self.cswap += 1 + + def removeKey(self): + self.keys-=1 + + def keysLeft(self): + return self.keys != 0 + + def getPlayer(self): + return self.player + + def render(self, pad): + m = 0 + for i in range(0, self.w): + m = m + self.map[0][i].getW() + 1 + for i in range(0, m+1): + pad.addch( 0 ,i, '\'', curses.color_pair(5)) + pad.addch( 0 ,i, ' ', curses.color_pair(5)) + x = 0 + for j in range(0, self.h): + y = 0 + for i in range(0, self.map[0][j].getH()+1): + pad.addch( j*(self.map[0][j].getH()+1)+1 +i ,0, ' ', curses.color_pair(5)) + for i in range(0, self.w): + a = self.map[j][i] + a.render(pad, j*a.getH()+1+j, i*a.getW()+1+i) + l = a.getBorder(Block.bottom) + l2 = a.getNeighbour((1, 0)).getBorder(Block.top) + if (l != l2): + for k in range(0, a.getW()+1): + if (l2 != [] and l != [] and l[k-1] != l2[k-1]): + pad.addch( x+self.map[0][j].getH() +1,y+k, '?', curses.color_pair(5)) + else: + pad.addch( x+self.map[0][j].getH() +1,y+k, '\'', curses.color_pair(5)) + pad.addch( x+self.map[0][j].getH() +1,y+k, ' ', curses.color_pair(5)) + else: + for k in range(0, a.getW()): + if (l[k] == Square.wall): + pad.addch( x+self.map[0][j].getH()+1,y+k+1, '|', curses.color_pair(6)) + else: + pad.addch( x+self.map[0][j].getH()+1,y+k+1, '\'', curses.color_pair(7)) + pad.addch( x+self.map[0][j].getH()+1,y+k+1, ' ', curses.color_pair(7)) + y = y + a.getW() + 1 + l = a.getBorder(Block.right) + l2 = a.getNeighbour((0, 1)).getBorder(Block.left) + if (l != l2): + for k in range(0, a.getH()+1): + if (l2 != [] and l != [] and l[k-1] != l2[k-1]): + pad.addch( x+k ,y, '?', curses.color_pair(5)) + else: + pad.addch( x+k ,y, '\'', curses.color_pair(5)) + pad.addch( x+k ,y, ' ', curses.color_pair(5)) + else: + for k in range(0, a.getH()): + if (l[k] == Square.wall): + pad.addch( x+k+1 ,y, '-', curses.color_pair(6)) + else: + pad.addch( x+k+1 ,y, '\'', curses.color_pair(7)) + pad.addch( x+k+1 ,y, ' ', curses.color_pair(7)) + for k in range(0, a.getH()+1): + pad.addch( x+k ,y, '\'', curses.color_pair(5)) + pad.addch( x+k ,y, ' ', curses.color_pair(5)) + x = x + self.map[0][j].getH() + 1 + m = 0 + for i in range(0, self.h): + m = m + self.map[i][0].getH() + 1 + for i in range(0, y+1): + pad.addch( m ,i, '\'', curses.color_pair(5)) + pad.addch( m ,i, ' ', curses.color_pair(5)) + x = 0 + for j in range(0, self.h+1): + y = 0 + for i in range(0, self.w+1): + pad.addch(x, y, '+', curses.color_pair(9)) + y += self.getBlock((min(j, self.h-1), i)).getW() + 1; + x += self.getBlock((j, self.w-1)).getH() + 1; + + + pad.addstr( self.scoreRep()) + self.player.render(pad) + pad.refresh() + + def scoreRep(self): + return "Moves: %3d\nDist: %4d\nSwaps: %3d" %(self.cmove, self.cdist, self.cswap ) + + def getH(self): + return self.h + + def getW(self): + return self.w + + def getBlock(self, p): + x = p[0] + y = p[1] + if (x < 0 or y < 0 or x >= self.getH() or y >= self.getW()): + return BlockSentry(self, 0, 0, (0,0)) + else: + return self.map[x][y] + + def move(self, p): + p2 = (-p[0], -p[1]) + tx = p2[0]+self.holeX + ty = p2[1]+self.holeY + t = self.getBlock((tx, ty)) + if (type(t) != BlockSentry): + self.map[tx][ty] = self.map[self.holeX][self.holeY] + self.map[self.holeX][self.holeY] = t + t.move(p) + self.map[tx][ty].move(p2) + self.holeX = tx + self.holeY = ty + self.addSwap() + return self.player.fall() + + + + + + + + + + + +stdscr = curses.initscr() +curses.noecho() +curses.cbreak() +stdscr.keypad(1) + + +f = open(sys.argv[1]) +h = int(f.readline()) +w = int(f.readline()) +x = int(f.readline()) +y = int(f.readline()) +l = Level(h, w, x, y) +l.loadFromFile(f) + +pad = curses.newwin(h*(l.getBlock((0,0)).getH()+1)+4, w*(l.getBlock((0,0)).getW()+1)+1) + +curses.start_color() +curses.init_pair(1, curses.COLOR_WHITE, curses.COLOR_BLACK) +curses.init_pair(2, curses.COLOR_RED, curses.COLOR_YELLOW) +curses.init_pair(3, curses.COLOR_GREEN, curses.COLOR_BLACK) +curses.init_pair(4, curses.COLOR_BLUE, curses.COLOR_BLUE) +curses.init_pair(5, curses.COLOR_BLACK, curses.COLOR_RED) +curses.init_pair(6, curses.COLOR_RED, curses.COLOR_BLUE) +curses.init_pair(7, curses.COLOR_WHITE, curses.COLOR_BLACK) +curses.init_pair(8, curses.COLOR_YELLOW, curses.COLOR_BLACK) +curses.init_pair(9, curses.COLOR_MAGENTA, curses.COLOR_MAGENTA) + +exit = False +won = False + +stdscr.addstr ("Continuity\nGame\n\nNameless\ncurses\nclone\n\nPress\nany\nkey\n") + +while (not exit): + l.render(pad) + try: input = Level.codeMap[stdscr.getch()] + except KeyError: + input = '' + pass + if (input == 'q'): + exit = True + elif (input == input.upper()): + try: won = l.move({v:k for k, v in Player.keyMap.items()}[input.lower()]) + except KeyError: pass + else: + try: won = l.getPlayer().move({v:k for k, v in Player.keyMap.items()}[input], 1) + except KeyError: pass + exit = exit or won + +curses.endwin() + +curses.nocbreak(); stdscr.keypad(0); curses.echo() + + +if (won): + print ("Congratulations, you won!\n") + print ("Your score was:") + print (l.scoreRep()) +else: print ("Bye.\n") +