From c1e0d938237eab5a99b8f638acc89611cc602f9a Mon Sep 17 00:00:00 2001 From: your-favorite-hacker Date: Sun, 5 Jul 2015 22:28:01 +0200 Subject: [PATCH] initial commit - 0ldsk00l --- README.txt | 28 ++++ cmate.py | 161 ++++++++++++++++++ cmatelib.py | 432 ++++++++++++++++++++++++++++++++++++++++++++++++ cmatelib.pyc | Bin 0 -> 12168 bytes cmatescenes.py | 339 +++++++++++++++++++++++++++++++++++++ cmatescenes.pyc | Bin 0 -> 9403 bytes levelfile.txt | 28 ++++ 7 files changed, 988 insertions(+) create mode 100644 README.txt create mode 100755 cmate.py create mode 100644 cmatelib.py create mode 100644 cmatelib.pyc create mode 100644 cmatescenes.py create mode 100644 cmatescenes.pyc create mode 100644 levelfile.txt diff --git a/README.txt b/README.txt new file mode 100644 index 0000000..84c2884 --- /dev/null +++ b/README.txt @@ -0,0 +1,28 @@ +///////////////////////// +\\\\ cursedmate v0.1b\\\\ +\\\\\\\\\\\\\\\\\\\\\\\\\\ + +main() +====== + +building in 2010 oldshool games - heya! +during reading the ncurses lib for python +this little piece of software was put +together. sweeeeet. + +facts() +======= + +* 20 levels +* 35 exploits spends a life +* monsters alias fedz, whitehats, blackhats(whatever ur enemy is) try to eat u +* run for the exploits to make it to the next level and escalating privs +* in the end i spent more time on it as i planned, but i think it was worth it + +final() +======= + +shouts to my friends, you know who u are! + +have fun, + dash diff --git a/cmate.py b/cmate.py new file mode 100755 index 0000000..f89bb47 --- /dev/null +++ b/cmate.py @@ -0,0 +1,161 @@ +#!/usr/bin/env python +#this is not even an exploit!!!1111 + +# Copyright (C) 2010 dash@uberwall.org +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by dash. +# 4. The name dash may not be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + + +import cmatescenes +import cmatelib +import random +import curses +import sys +import time + +def play_level(win1,win2,cm,mspeed): + + try: + cm.update_lifebar(win1) + win1.move(cm.sizex/2,cm.sizey/2) + curses.curs_set(1) + win1.nodelay(1) + o=0 + while 1: + a = win1.getch() + if a == 65: + cm.move_player(a,win1) + elif a == 66: + cm.move_player(a,win1) + elif a == 68: + cm.move_player(a,win1) + elif a == 67: + cm.move_player(a,win1) + elif a == 112: + cmatescenes.pause_game(win2,cm) + win1.redrawwin() + + cm.check_position(win1) + + if (o%mspeed == 0): + cm.move_monster(win1) + + #watch out for ur lifes + ret = cm.check_collision(win1) + if ret == 1: + cmatescenes.lost_a_live(win2,cm) + win1.move(cm.sizex-2,cm.sizey-2) + time.sleep(2) + cm.update_lifebar(win1) + win1.redrawwin() + if cm.lives < 0: + cmatescenes.ur_dead(win2,cm) + return -1 + + #check if a zero day was eaten + cm.check_object(win1) + + if cm.gcount + cm.eaten >= cm.gold: + cmatescenes.congrats(win2,cm) + return 0 + if cm.gold == cm.gcount: + cmatescenes.congrats(win2,cm) + return 0 + o+=1 + + if cm.elive == 35: + cm.lives+=1 + cm.elive = 0 + + except KeyboardInterrupt: + if cmatescenes.really_quit(win2,cm) != -1: + cm.close_stdscr() + sys.exit(1) + +def create_level(win1,win2,cm,ming,maxg,minm,maxm): + rc = random.randint(0,10) + cm.config_window(win1,1) + cm.generate_map(cm.sizex-1,cm.sizey-1) + cm.generate_item(500,1000,35) + cm.generate_gold(int(ming),int(maxg)) + cm.generate_monster(int(minm),int(maxm)) + cm.throw_items(win1,rc) + cmatescenes.level_info(win2,cm) + cm.throw_items(win1,rc) + cm.update_lifebar(win1) + win1.move(cm.sizex/2,cm.sizey/2) + win1.refresh() + +cm = cmatelib.cmate() +cm.create_stdscr() +cm.create_colors() + +cm.sizex=24 +cm.sizey=80 + +cmatescenes.pre_intro(cm,2) +cmatescenes.intro(cm) +win1 = cm.create_window(cm.sizex,cm.sizey,0,0) +win2 = cm.create_window(8,50,5,16) +win3 = cm.create_window(16,50,5,16) +cmatescenes.start_of_game(win3,cm) + +#open level file +l = open('levelfile.txt','r') +for lvl in l.readlines(): + if lvl[0]!='#' and lvl[0]!='\n': + cm.gcount=0 + cm.eaten=0 + cm.gomap=[] + cm.mmap=[] + items = lvl.split(',') + level=items[0] + ming=items[1] + maxg=items[2] + minm=items[3] + maxm=items[4] + mspeed=items[5] + cm.lvl=level + create_level(win1,win2,cm,ming,maxg,minm,maxm) + + while 1: + ret = play_level(win1,win2,cm,int(mspeed)) + if ret ==0: + break + elif ret ==-1: + endgame=-1 + cm.close_stdscr() + sys.exit(1) + + cmatescenes.pre_intro(cm,1) + +cmatescenes.end_of_game(win2,cm) + +#the end +cm.close_stdscr() diff --git a/cmatelib.py b/cmatelib.py new file mode 100644 index 0000000..47fbdb9 --- /dev/null +++ b/cmatelib.py @@ -0,0 +1,432 @@ +#!/usr/bin/env python + +# Copyright (C) 2010 dash@uberwall.org +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by dash. +# 4. The name dash may not be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + + +import random +import curses +import time +import sys +import os + +class cmate(object): + def __init__(self): + self.name="the hunt for 0days" + self.lvl=0 + self.gold=0 + self.gcount=0 + self.collected=0 + self.eaten=0 + self.ms=0 + self.elive=0 + self.lives=3 + self.time=60 + self.gmap=[] + self.mmap=[] + self.gomap=[] + self.win1=0 + self.win2=0 + self.sizex=25 + self.sizey=80 + self.winlist=[] + self.stdscr=0 + self.msspeed=100 + + def close_stdscr(self): + """ at the end - we reset everything """ + curses.nocbreak() + curses.echo() + self.stdscr.keypad(0) + curses.endwin() + + def create_stdscr(self): + """ function for the stdscr """ + self.stdscr = curses.initscr() + self.stdscr.border() + self.stdscr.keypad(1) + + curses.cbreak() + curses.noecho() + curses.start_color() + curses.curs_set(1) + + def create_colors(self): + curses.init_pair(1,curses.COLOR_GREEN,curses.COLOR_BLACK) + curses.init_pair(2,curses.COLOR_YELLOW,curses.COLOR_BLACK) + curses.init_pair(3,curses.COLOR_RED,curses.COLOR_BLACK) + curses.init_pair(4,curses.COLOR_WHITE,curses.COLOR_BLACK) + curses.init_pair(5,curses.COLOR_WHITE,curses.COLOR_RED) + curses.init_pair(6,curses.COLOR_YELLOW,curses.COLOR_BLUE) + curses.init_pair(7,curses.COLOR_WHITE,curses.COLOR_BLUE) + curses.init_pair(8,curses.COLOR_WHITE,curses.COLOR_WHITE) + curses.init_pair(9,curses.COLOR_YELLOW,curses.COLOR_YELLOW) + curses.init_pair(10,curses.COLOR_BLACK,curses.COLOR_BLACK) + + def check_windows(self): + """ how many windows are in the list """ + wlen = len(self.winlist) + return wlen + + def create_window(self,sizex,sizey,posx,posy): + """ function for creating a new window """ + win = curses.newwin(sizex,sizey,posx,posy) + self.winlist.append(win) + return win + + def compute_strpos(self,win,pos,string): + """ find relative positions for texts in the middle of the window""" + sizex,sizey = win.getmaxyx() + if pos == 1: + l = len(string) + spos = sizey - l + rpos = spos /2 + + return rpos + + def write_window(self,win,posx,posy,text,attr): + """ wrapper function for writing strings to a window """ + if posx!=-1 and posy!=-1 and attr !=-1: + win.addstr(posx,posy,text,attr) + elif posx!=-1 and posy!=-1 and attr == -1: + win.addstr(posx,posy,text) + elif posx==-1 and posy==-1 and attr == -1: + win.addstr(text) + elif posx==-1 and posy==-1 and attr !=-1: + win.addstr(text,attr) + + win.refresh() + + def config_window(self,win,func): + if func==1: + win.box() + win.refresh() + elif func == 2: + win.erase() + win.refresh() + + def generate_map(self,x,y): + fill = 35 # 35 is the fill element '#' + gmap = [] + fields = x*y + i = 0 + for cx in range(0,x): + for cy in range(0,y): + gmap.append([cx,cy,32]) + i+=1 + i+=1 + self.gmap = gmap + + def generate_monster(self,f,t): + + #gmap + gmap = self.gmap + #monsters + ms = [f,t] + ms = random.randint(ms[0],ms[1]) + l = len(gmap)-1 + mmap=[] + + for g in range(0,ms): + while 1: + p = random.randint(0,l) + if (gmap[p][0] != 0 and gmap[p][1] != 0) and (gmap[p][0] != 23 and gmap[p][1] != 79): + gmap[p][2] = 164 + mmap.append(gmap[p]) + break + + self.gmap = gmap + self.mmap = mmap + self.ms = ms + + def generate_gold(self,f,t): + + gmap = self.gmap + + #gold aka 0days + gold = [f,t] + gold = random.randint(gold[0],gold[1]) + l = len(gmap)-1 + + for g in range(0,gold): + while 1: + p = random.randint(0,l) + if (gmap[p][0] != 0 and gmap[p][1] != 0) and (gmap[p][0] != 23 and gmap[p][1] != 79): + gmap[p][2] = 163 + self.gomap.append(gmap[p]) + break + + self.gold = gold + self.gmap = gmap + + def generate_item(self,f,t,item): + + gmap = self.gmap + #chill number 35 + f = [f,t] + f = random.randint(f[0],f[1]) + l = len(gmap)-1 + for g in range(0,f): + while 1: + p = random.randint(0,l) + if (gmap[p][0] != 0 and gmap[p][1] != 0) and (gmap[p][0] != 23 and gmap[p][1] != 79) and gmap[p][2] != 163: + gmap[p][2] = item + break + + self.gmap = gmap + + def throw_items(self,win,rc): + """ populate the map with the window with pre-generated items in gmap """ + gmap = self.gmap + + #general map + for val in gmap: + if (val[0] != 0 and val[1] != 0) and (val[0] != 23 and val[1] != 79): + if val[2] == 163: + win.addstr(val[0],val[1],chr(val[2]),curses.A_REVERSE) + win.refresh() + elif val[2] == 164: + win.addstr(val[0],val[1],chr(val[2]),curses.color_pair(5)) + win.refresh() + else: + win.addstr(val[0],val[1],chr(val[2]),curses.color_pair(rc)) + win.refresh() + win.refresh() + + + self.gmap = gmap + + def update_lifebar(self,win): + """ show the player whats going on """ + + #save my coordinates + me = win.getyx() + + #which level + collect = "lvl:%s" % (self.lvl) + win.addstr(0,3,collect) + + #how much zerodays to grep + gold = "%s / %s" % (self.gcount,self.gold) + win.addstr(0,12,gold) + + #zeroday collection + collect = "xploitz: %s" % (self.collected) + win.addstr(0,20,collect) + + #lives + lives = "live: %d" % (self.lives) + win.addstr(0,35,lives) + + #knights name + name = "%s" % (self.name) + win.addstr(0,50,name) + + #time + #time = "%s" % (self.time) + #win.addstr(0,70,time) + + + #how many fedz and whittezzzz + fedz = "%s fedz" % (str(self.ms)) + win.addstr(23,3, fedz) + + #published by wh and eaten by fedz + ate = "[%s]" % (str(self.eaten)) + win.addstr(23,20, ate) + + win.move(me[0],me[1]) + win.refresh() + + def check_object(self,win): + """ check if a monster ate our zeroday """ +# f = open('logme.txt','a') + mmap = self.mmap + gomap = self.gomap + for gold in gomap: + for monster in mmap: + if gold[0] == monster[0] and gold[1] == monster[1]: + self.eaten=int(self.eaten) + 1 + gomap.remove(gold) + #g = "%s\n" % (gold) + #f.write(g) + #m = "%s\n" % (monster) + #f.write(m) + self.update_lifebar(win) + #f.close() + self.gomap = gomap + + def check_position(self,win): + """ checks position for gold, this function should be optimized as + by now the whole gmap is searched, which could be done simpler """ + + gmap = self.gmap + i=0 + me = win.getyx() + for val in gmap: + if me[0] == val[0] and me[1] == val[1] and val[2] == 163: + + self.gcount = int(self.gcount) + 1 + self.elive = int(self.elive) + 1 + self.collected = int(self.collected) + 1 + self.update_lifebar(win) + + #changing the field - clearing space + win.addch(me[0],me[1]," ") + + #clearing space in table + gmap[i][2]=32 + + #ok i am back at the same old place + win.move(me[0],me[1]) + win.refresh() + self.gmap = gmap + i+=1 + + def check_collision(self,win): + """ lets check if a monster is byting our ass """ + + me = win.getyx() + mmap = self.mmap + + for val in mmap: + if val[0] == me[0] and val[1] == me[1]: + self.lives = self.lives - 1 + return 1 + + return -1 + + def move_monster(self,win): + gmap = self.gmap + mmap = self.mmap + i=0 + me = win.getyx() + for val in mmap: + + m = random.randint(1,4) + +#check what direction the random gen spitted +#check if monster has reached the cage + + if m == 1: + if val[0]!=1: + win.addstr(val[0],val[1]," ") + x = val[0] + x = x - 1 + mmap[i][0] = x + win.addstr(x,val[1],"O",curses.color_pair(5)) + win.refresh() + + elif m == 2: + if val[0]!=self.sizex-2: + win.addstr(val[0],val[1]," ") + x = val[0] + x = x + 1 + mmap[i][0] = x + win.addstr(x,val[1],"O",curses.color_pair(5)) + win.refresh() + + elif m == 3: + if val[1]!=1: + win.addstr(val[0],val[1]," ") + y = val[1] + y = y - 1 + mmap[i][1] = y + win.addstr(val[0],y,"O",curses.color_pair(5)) + win.refresh() + + elif m == 4: + if val[1]!=self.sizey-2: + win.addstr(val[0],val[1]," ") + y = val[1] + y = y + 1 + mmap[i][1] = y + win.addstr(val[0],y,"O",curses.color_pair(5)) + win.refresh() +#former monster field is empty now + i+=1 + + win.move(me[0],me[1]) + win.refresh() + self.mmap = mmap + + def move_cursor(self,win, x,y): + """ for other useful and great animations """ + win.move(x,y) + + def delete_item(self, win, item, x,y): + """ for deleting the littel things at the position xy """ + win.addch(x,y,item) + + def move_item(self, win, item, x,y,color): + """ for moving "sprites" :) """ + win.move(x,y) + self.write_window(win,x,y,item,color) +# win.refresh() + + def move_player(self,action,win): + + a = action + xy = win.getyx() + x=xy[0] + y=xy[1] + + win.addch(x,y," ") + if a == 65: + if x!=1: + win.move(x-1,y) + win.refresh() + else: + win.move(x,y) + win.refresh() + + elif a == 66: + if x!=self.sizex-2: + win.move(x+1,y) + win.refresh() + else: + win.move(x,y) + win.refresh() + + elif a == 68: + if y!=1: + win.move(x,y-1) + win.refresh() + else: + win.move(x,y) + win.refresh() + + elif a == 67: + if y!=self.sizey-2: + win.move(x,y+1) + win.refresh() + else: + win.move(x,y) + win.refresh() diff --git a/cmatelib.pyc b/cmatelib.pyc new file mode 100644 index 0000000000000000000000000000000000000000..17ccaf3cabae8ebce104e93959e8bf4bd88f515d GIT binary patch literal 12168 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 UlGtUF(YMcICK;zg(d*CuKi#1pegFUf literal 0 HcmV?d00001 diff --git a/cmatescenes.py b/cmatescenes.py new file mode 100644 index 0000000..5df7e4e --- /dev/null +++ b/cmatescenes.py @@ -0,0 +1,339 @@ +# Copyright (C) 2010 dash@uberwall.org +# All rights reserved. +# +# Redistribution and use in source and binary forms, with or without +# modification, are permitted provided that the following conditions +# are met: +# 1. Redistributions of source code must retain the above copyright +# notice, this list of conditions and the following disclaimer. +# 2. Redistributions in binary form must reproduce the above copyright +# notice, this list of conditions and the following disclaimer in the +# documentation and/or other materials provided with the distribution. +# 3. All advertising materials mentioning features or use of this software +# must display the following acknowledgement: +# This product includes software developed by dash. +# 4. The name dash may not be used to endorse or promote +# products derived from this software without specific prior written +# permission. +# +# THIS SOFTWARE IS PROVIDED BY THE AUTHOR ``AS IS'' AND ANY +# EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE +# IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE +# ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR BE LIABLE +# FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL +# DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS +# OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION) +# HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT +# LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY +# OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF +# SUCH DAMAGE. + +import cmatelib +import random +import curses +import sys +import time + +def pre_intro(cm,func): + """ what can i say, the coordinates are fucked up """ + win20 = cm.create_window(cm.sizex,cm.sizey,0,0) + curses.curs_set(0) + x=0 + y=13 + y1=11 + char="|" + while 1: + win20.hline(y,x,char,cm.sizey) + win20.hline(y1,x,char,cm.sizey) + y+=1 + y1-=1 + win20.refresh() + time.sleep(0.1) + if y == cm.sizex: + break + + if func==1: + y=12 + x=0 + curses.curs_set(1) + while 1: + cm.move_cursor(win20,y,x) + win20.refresh() + time.sleep(0.1) + x+=1 + if x == 80: + break + + if func==2: + y=12 + x=79 + curses.curs_set(1) + while 1: + cm.move_cursor(win20,y,x) + win20.refresh() + time.sleep(0.1) + x-=1 + if x == 0: + break + +def intro(cm): + win5 = cm.create_window(cm.sizex,cm.sizey,0,0) + cm.config_window(win5,1) + welc = ".oOo.oOO w3lcome to cursedmate OOo.oOo." + rpos = cm.compute_strpos(win5,1,welc) + cm.write_window(win5,5,rpos,welc,curses.color_pair(2)) + i = 0 + y = 78 + x = 16 + y1 = 78 + x1 = 16 + while 1: + if y == 0: + curses.curs_set(0) + + if y >= 0: + cm.move_cursor(win5,x,y) + + if y == 60: + cm.move_item(win5,"O",x1,y1,curses.color_pair(5)) + cm.config_window(win5,1) + curses.curs_set(0) + shitno0days = "oh shit!!111 it is a fed!!!" + rpos = cm.compute_strpos(win5,1,shitno0days) + cm.write_window(win5,(cm.sizex/4)+2,rpos,shitno0days,curses.color_pair(1)) + time.sleep(2) + curses.curs_set(1) + elif y < 60: + if y1 == 0: + cm.delete_item(win5," ",x1,y1+1) + win5.refresh() + break + cm.delete_item(win5," ",x1,y1+1) + cm.move_item(win5,"O",x1,y1,curses.color_pair(5)) + cm.config_window(win5,1) + y1 = y1 -1 + + if y >= 0: + cm.move_cursor(win5,x,y) + + if y != 0 and y >= 50: + y = y -1 + + elif y > 2 and y <= 50: + y = y - 2 + + elif y <= 2 and y <=50: + y = y - 1 + + win5.refresh() + time.sleep(0.1) + + win5.nodelay(1) + win5.move(cm.sizex/2,rpos) + win5.box() + + i = 0 + o = 100 + win5.nodelay(1) + while 1: + a = win5.getch() + if i%o == 0: + space = "press to contiue" + rpos = cm.compute_strpos(win5,1,space) + cm.write_window(win5,cm.sizex/2,rpos,space,curses.color_pair(5)) + win5.refresh() + time.sleep(3) + win5.move(cm.sizex/2,rpos) + win5.clrtoeol() + win5.box() + win5.refresh() + time.sleep(0.1) + if a == 32: + return + +def level_info(win,cm): + string = "there are %s zerodays and %s fed(z)" % (cm.gold, cm.ms) + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,3,rpos,string,curses.color_pair(2)) + win.box() + win.refresh() + time.sleep(0.1) + string = ">- Go -<" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,6,rpos,string,curses.color_pair(4)) + win.box() + win.refresh() + while 1: + a = win.getch() + if a == 32: + win.erase() + return + +def congrats(win,cm): + string = "awesome! u collected enough zerodays" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,3,rpos,string,curses.color_pair(2)) + win.box() + win.refresh() + time.sleep(0.5) + if cm.collected<=10: + string = "uid=65535(nobody) gid=65535(nobody)" + elif cm.collected>=10 and cm.collected <40: + string = "uid=8080(www) gid=8080(www)" + elif cm.collected>=40 and cm.collected <70: + string = "uid=1(operator) gid=1(operator)" + elif cm.collected>=70 and cm.collected <100: + string = "uid=0(root) gid=0(wheel) groups=0(wheel)" + elif cm.collected>=100 and cm.collected <=120: + string = "isn't there a remote shell waiting for you?" + color=curses.color_pair(2) + elif cm.collected>=120 and cm.collected <=140: + string = "yes. yes. xss is dangerous too" + color=curses.color_pair(2) + elif cm.collected>=140 and cm.collected <=160: + string = "moaarr - do u ever considered stop playing?" + color=curses.color_pair(2) + elif cm.collected>=160 and cm.collected <=180: + string = "the latest phrack is out! yes!" + color=curses.color_pair(2) + elif cm.collected>=180 and cm.collected <=200: + string = "btw. what happened to phrack.ru?!" + color=curses.color_pair(2) + elif cm.collected>=200 and cm.collected <=220: + string = "..." + color=curses.color_pair(2) + elif cm.collected>=220 and cm.collected <=240: + string = "strange things happen in the dark edges of the morloch" + color=curses.color_pair(2) + elif cm.collected>=240: + string = "ok, i am off have fun!" + color=curses.color_pair(2) + + color=curses.color_pair(5) + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,5,rpos,string,color) + win.box() + win.refresh() + win.nodelay(0) + while 1: + a = win.getch() + if a == 32: + win.erase() + return + +def lost_a_live(win,cm): + string = "watch out man!" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,3,rpos,string,curses.color_pair(2)) + win.box() + win.refresh() + while 1: + a = win.getch() + if a == 32: + win.erase() + return + +def start_of_game(win,cm): + win.box() + win.refresh() + win.scrollok(1) + win.idlok(1) + curses.curs_set(1) + string = "here u go stranger, u installed ncurses,\nhave a working python interpreter\na fully colorable xterm or rxvt\nsitting at work on a boring monday morning\nTHIS IS THE CHANCE TO FEEL LIKE 1985\n(no matter if u were not born yet)\n\n\nnow, you have 20 levels\ndont worry if u loose a life\nu get new one with 35 exploits collected\n(from now on this is working in RL as well)\nu meet already one of the bad guys\n%s <---- this is what u want to collect\nu move ur ass with the cursors\n\nif ur listening to LCP\nnow is the time to turn it up\nbring da noize\n\n\n(press space)\n\n\n\n\n\n\n" % (chr(163)) + parts = string.split('\n') + xpos=0 + win.nodelay(1) + for ln in parts: + if xpos < 14: + xpos+=1 + if xpos>=14: + win.scroll(1) + win.move(xpos,1) + win.clrtoeol() + win.box() + + rpos = cm.compute_strpos(win,1,ln) + cm.write_window(win,xpos,rpos,ln,curses.color_pair(1)) + time.sleep(2.0) + + a = win.getch() + if a == 32: + win.erase() + return + win.box(0,0) + + while 1: + a = win.getch() + if a == 32: + win.erase() + return + +def end_of_game(win,cm): + string = "that's it stranger!\nu did it! the game is over\neven the fedz from hell could not stop u!\n\n\ni hope u had fun.\n" + parts = string.split('\n') +# win.move(0,0) + xpos=1 + for ln in parts: + rpos = cm.compute_strpos(win,1,ln) +# win.addstr(ln, curses.color_pair(1)) + cm.write_window(win,xpos,rpos,ln,curses.color_pair(1)) + time.sleep(2) + xpos+=1 + + win.nodelay(1) + while 1: + rc = random.randint(0,10) + string = "~~ keep the spirit - hack the planet! ~~" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,5,rpos,string,curses.color_pair(rc)) + win.box() + win.refresh() + time.sleep(0.3) + a = win.getch() + if a == 32: + win.erase() + return + +def ur_dead(win,cm): + string = "dangit! .gov has u!" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,3,rpos,string,curses.color_pair(2)) + + string = "# rm -fr /" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,5,rpos,string,curses.color_pair(2)) + win.box() + win.refresh() + while 1: + a = win.getch() + if a == 32: + win.erase() + return + +def pause_game(win,cm): + win.nodelay(0) + string = "PAUSE" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,3,rpos,string,curses.color_pair(2)) + win.box() + win.refresh() + while 1: + a = win.getch() + if a == 32: + win.erase() + return + +def really_quit(win,cm): + string = "Quit the game Y/N" + rpos = cm.compute_strpos(win,1,string) + cm.write_window(win,3,rpos,string,curses.color_pair(2)) + win.box() + win.refresh() + while 1: + a = win.getch() + if a == 110: #110 == n + return -1 + if a == 122 or a ==121 : #122 == z / 121 == y + return 1 + win.erase() + diff --git a/cmatescenes.pyc b/cmatescenes.pyc new file mode 100644 index 0000000000000000000000000000000000000000..b86f512e946efaa1859470f3c0dac7ec890a024e GIT binary patch literal 9403 zcmdT~O^h5z6|SEBo$-!$W5++3B-A)W9)rDW#~2)N;zY(Kfv`5SMiCZh)jQq0)83x0 z*{&YXthEjxb3iCTLY#sW2?PfY9FY(lI6w}83kOaJ4uornK;py+zVB7{%5}n|0&_`)A-nLp$YKosaUC-gTAM3dc}B2-7FRT z33YR#=ufJflPV~wuYhq%1rySlR>7onW>hdGommx3OQ)=Y8R=A1Fe{yXDkw{5P6ZX| zR8_D~I{PWoN_`IEMSsK3a+4y@;4_8KWqj;+Jf(J&y5(9=`VbUyd+Oe#x?57>`S0 z@#rZJf9^u|lDdnb33V4DgJ@dyt=cK6TT^OhQteEro#}icOyT7(@NVx5%rT`tf~j^e z&y>1==}0`S?kVMEGwPOXo9l8~Na?A~l1i_t>swb9es>_|lni~)!?92%kuMi{N<{8| zQdrBJ+DUhB!U;8Q9c+#wK~nT)W$rhy+#3qN2@VM>mSyzSV#NwiW1h8?;NfFWqbTnQr=tjZUPi5G8&VTJ5KyUhg(H!$5aCIs%J| zs%-Y5$#B_fCt|zttylQ-<4cif$90lWIihQ5mg^O?8Tp!NhZUfd*=*ijwP7X{tvE_TT%=NIxSoc#l})0bMeWc{5QkwWqhxJ!J6z=~Case^ zqb$v~kgs=>rjSF3$Ir+f`qFL-)%IDTYPS5e4kjgyeGa{)mT8AeT^puL%`-u`)Y;Bj zCRq|;gEqFcl!kHWL-LWa(`OdXt}QkB+BU-^w2NRXW42Bju0~0gn#b^9KZ!<_9`UN) zbpCI`dk_9qC9oA4g~CJCsaY6=X<^V=CyaVp-4bwtaowA8b`9&97K?@@0fEp51^Tn9 z|9FWO>Xh^Q!VJrFh(M!o@1|7x%fi$k9v}b)2vf@`oH5<;C`=_cq@7u{GgAmNNpqzz zq!`^9g&nL1jJpe49^Gbn?>6}so86}l!I+N_cFM&fI1;xA)b17#(_uuug1q#SS7b+! z7ixR31OfA%|3oCKitKaB$&SN6A|U6fTl)pKu5-T-;2+T8&A+yLu3u6|aT&Xg`h1Ct z;3UQzH7;sGr8ni$s%jG#X5V?Ln6Lvb- zcYdHa1mN}7OY&x3l#}=kvIRL7+{=_Yggc?ma`*u`H3Byja9-V&)44U^?Egw;IzXzs z`vk!&>TrG|Kbi;@)Lq;Kj$)wobN@gc+_F1!g(?j7ZSNi+(mTt1P-GrTKRgB8(XNBo zfqOn64r6u#A;QX*`%^y%Ltl3AOxw37&@7s32A^xXcP?%Mx^!mr5Ulhyd21FUqOb$& zW%d@>Ttp+Fc+I{SUDMLG6=k*B*|TSLl<5ebL9d5FtyYT!g1M-U9!ER$1dvbJqi6ti z*6NEZ*Ppq36~M`?pQY={pc@``f+N4r4>)8LRejR5G4dE|{a4K|6v zu)i%nfsF9XO05~^u{Of2*>Y|wPBRmlxK7k4?zWXw;Y|DYw+% zk&E-`pA|`X)`>Y2_}f-4!AR>nC)e?t;eGQ=q6_p&^xO7JXq5Mew*b#`$U8ppP1Eo} zbKU}c&tZIy<30V>A@4N)F5u0acMRTX60N)wx}#pTRD3Gnt$Ih`z3A=e(J-6La8f)Q z-pJo7#wEt2SOZ`7Cp^GlX(SFXJhfg@hv}^_Bt8oWH}qB*6rUBK#V@?oB>fkh*NB5~ z!5a;KMvM`+3N*~|oX+cAXP?jp} z0;pyCD0Yqr4KW$xvd65x6Q+h*qWvV`Gfc96=cGhr&bVkz1B@(zm@JKb^`%|5jck(ARk3QBXljE_AA zW2Yx^cQ1Z;uVzW$G}J7l8wm7wX%-%^G&Kvs0eYjcl6Wl1N;csaZ%cesQpw>GHQ9~B z+rBD_jYk(lyh>$(Ov#@Lc8r7UwSuf7p~h>BSV;DIL56XVy;+dW3E7(}s0!J43Nnm? ztX4ekSCp;h(V4<_Ms^4fn{1Adf$N3haY49V@PY@%ah)F_1J}#NBU~HSdf5vOj^p}U zAvwsv_49)3LE-wj7aSVL^^1ZFWZ?R1!F5=;{^|us#&LbK-~t)AmWmrWDqKsY;63BG zzEE(13|wKsbxgRzQt;k!Tqg=Hkb&!^Qt;3?GT4+m{D%oGOmiIqLPz(&om0w(b3g*R z6k+gQU8Gh5q}r|2q)-iL-nXX~Z|SjtT5$VQ$cY(rU2Ny0Pr)R@c>VcJ$0#&}3gw`1|n zJx6_Vd=O1!lM@;9Wumc8!?wvn1W92W>z*HFKsvo{QoU`um!g-*M2y@<{->qsBO*c+ z75K>pFuZFK7MbYVq~qjmL?u|{QuISI2>>H^ zkC|s?y3~-K@qHYtieZtD#xTdW$acZ~2`La?*e?nPXW@yO(Ow???*lQ;Um> z(VzM7VK!MxX|ZRlYqew6Q6fcyz)v@I7;Kf%x zVH;38`vdgt8X6@L&hb39nfJ(mZ^bs}H#NY2d+j#Y$hsvj1@p zmIH-^OoSmsFRpBML!uWKKoKFfZn)@$*RgCF>h^p@%v4I<_Mre02vgBq{-M#U^X%S5 z3#jexqPf{|7kz)Pmr4~Q`B?Q=Ua{W5k<;8lab040Px zM37pkWQ!m`B;kr8dBEx(0QLwW0%W|N3wq%ckkd=df#M9Vf_DP;L5-vT20g*YzwjHD zV|ZKB;`!m?(D$Tbnm{D?0uJcc!VbUS7UW#WqJ>tnY&<(>Fx&v2p>6Ws2rt&BZ6}y%M9_0xZDqNB0Nr|2$W%sC7Zdq)U;W^U&txUa; z>*U*+Z|q^-x*>Danf5J<0@|gLQi9`MyN9O`?6hW*8jn zwn-4r<4>C4v2x?t=T7Al8a_IZ`87%>_tprHLDMq^Om}6rs9a$`qO7IQo!4Q%6PqZrLsws^ucxMsHAzVSAik|QB6x_#^V+u%ERIiN(sqbh z{TQX-U|VL+J;s_J=#B2Stss-Rcp5*$saU4Q&U^^VDu#kjF{Z=PzI9S3LD){Wlb(3@Ub0~rg3z2SHG}Kym^%T ziM~rqCVW*QG%6yvZLo)*rz4G4YBIxYNy-GanL>24DSjvl&~u5^AYp2@(mczLqfERS zY#l2JU*jQk8;om4@KJIy!AxrOh!2#p-9AvJ?)YhDCDZG(fCAlDaq?ft%2*kJHKp0A zSzq1o+ufwiViSN%NWK0mYEVZ2=mM+q8n{a+2P?b6xsnEZYOQt z|L`MBg2ImGagO!_SeN0)JW6U+?@$TW;_XL~Z302%u+%}T8XqYB6zsXxymMALD58xN z0%#MAJDgg>aK!3%Rp6YiL#JH@ZVxlHc5iMvCd!-H4aKp#yEoLdRJKPoyz=SwR4=(qL}Tp#A^c?Vt(&d}@Si7n_s8&@hn~27BIVo4 zTDy{huY;T?E;mllKuDS2-5yB7WkDMpBq6ADcjv%RzUeCJ3a+xnIb9t!zdO03JVQXt z2_W)iVbn$oAoAVaaZB#|3-M9cpZV;{m9g2uz<9^n_pmnkzfKXTUmYJ`7K^KUg4aYq zQZUPZ=89eg>Az);V=d}qa{6!2+d51MR_MsY!t7Ti+IPV>Qn-?2a-4B!bS{3j4?xb( zbOF#rX7Lc8TXIqLu>Kq&IdK1BB)Y@iHk$tjGoy1vjEYcxbqia($~$DV_4X`p(mU$S zcy)fE # +############################################################################# + +0,5,5,1,1,1000 +1,10,15,2,3,1000 +2,10,20,2,2,500 +3,15,20,4,4,1000 +4,10,20,3,3,500 +5,20,30,5,5,700 +6,30,30,3,3,100 +7,20,30,4,5,100 +8,20,50,7,7,400 +9,20,50,5,9,400 +10,15,50,3,10,100 +11,15,50,4,10,100 +12,15,50,5,10,100 +13,15,50,6,10,100 +14,15,50,7,10,100 +15,15,50,8,10,100 +16,15,50,9,10,100 +17,15,50,10,10,100 +18,15,50,1,10,100 +19,15,50,1,10,100 +20,15,50,1,10,100