castle_defence_v7.py

Created by mathieu-croslacoste

Created on March 14, 2025

11.6 KB


from ion import keydown as kd
from random import*
from kandinsky import draw_string as D,fill_rect as r
from time import*
R=range
can_place=0;w=0;M=100;HP=100;map_pos=[0,0];prevPos=None;wave_on="";frozen=0;e_count=[];t_count=[];t_a_count=[];d_l=[]
Map=((0,4,13),(13,5,4),(3,9,10),(3,10,6),(4,16,18),(22,7,9),(23,7,8),(31,8,11))
try:
 from os import*;s=D
except:
 ref="0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz?!.,:;%+-*/=<>'_→[](){}"
 font="2jg02oN06Fd07AE04l907dE07dl079907gl07h906lj06kl03aZ06jk07dd07da03bh05lj07IN079h05kj04ad05zj01li03jk06la06jwG6kj03YE07II05jl05jg05jz05gj05gI07Ad003l04cl003d01Bl007p03ca003lE4cj026N0119g4br04aZ007z006j007l006la03l907a003M04dZ005l005g005?005L005hE07AO7A202I200020002W0220022W5Ab00NG007000ge01AKW0uu01KH04HK02G00000u4NK03IJ06IM01IH04IK03MJ06JM0"
 def dml(l,x,y,c1,c2):
  if c2:F(x,y,4,6,c2)
  for seq in R(4):
   v=ref.index(font[(ref.index(l)*4)+seq]);b=32
   for i in R(6):
    if v>=b:S(i%3+x,i//3+(2*seq)+y,c1);v-=b
    b//=2
 def dm(s,x,y,c1=(0,)*3,c2=(255,)*3,c3=(150)*3):
  rx=x
  for l in R(len(s)):
   if(s[l]in(" ","\n","\t"))^1:dml(s[l],x,y,c1,c2)
   elif s[l]==" "and c2:F(x,y,4,6,c2)
   x+=4
   if s[l]=="\n":y+=6;x=rx
   elif s[l]=="\t":x+=12
   if x>319:x=rx;y+=6
 def s(t,x,y,c1="k",c2="w",m=0):
  if m:dm(t,x,y,c1,c2)
  else:D(t,x,y,c1,c2)
class ennemy():
 def __init__(it,level,speed):global e_count;e_count.append(it);it.eAttr=[level,level,1,34,90,speed,0]
 #level,og_level,x,y,heading,speed,dist travelled
 def draw(it):
  colors=((20,255,0),(255,127,0),(255,0,20),(127,0,127),(20,0,255),(255,)*3)
  if 0<it.eAttr[0]<7:r(it.eAttr[2],it.eAttr[3],4,4,colors[it.eAttr[0]-1])
  elif it.eAttr[0]>0:r(it.eAttr[2],it.eAttr[3],4,4,(0,)*3)
 def finished(it):
  global HP,e_count
  if it.eAttr[0]<=0:#dead?
   if it in e_count:it.remove_e();return 1
  elif(it.eAttr[2]>=246)and(it.eAttr[3]>=166):HP-=(it.eAttr[0]*3);it.remove_e();draw_castle();return 1#reached castle?
  return 0
 def remove_e(it):global M,e_count;e_count.remove(it);M+=it.eAttr[1]+3*it.eAttr[5]-3+randint(0,2);u_s()
 def move(it):
  turn=(104,144,224,280,432,504,576,700)
  if 1-it.finished():
   for i in R(8):
    if it.eAttr[6]<turn[i]:
     if(i+1)%3==0:mod=-1
     else:mod=1
     it.eAttr[2+i%2]+=it.eAttr[5]*mod;it.eAttr[6]+=it.eAttr[5];break
class t_attack:
 def __init__(it,x,y,damage,type,mod):global t_a_count;t_a_count.append(it);it.aAttr=[x,y,damage,type,mod]
 def draw_attack(it):
  if it.aAttr[3]=="normal":r(it.aAttr[0],it.aAttr[1],3,3,(110,)*3)
  elif it.aAttr[3]=="double":r(it.aAttr[0],it.aAttr[1],2,2,(120,)*3)
  elif it.aAttr[3]=="fire":r(it.aAttr[0],it.aAttr[1],3,3,(255,155,155))
  elif it.aAttr[3]=="ice":r(it.aAttr[0],it.aAttr[1],3,3,(155,155,255))
 def move_attack(it):
  r(it.aAttr[0],it.aAttr[1],3,3,(0,)*3)
  if len(e_count)>0+it.aAttr[4]:
   if it.aAttr[0]<e_count[it.aAttr[4]].eAttr[2]:
    if it.aAttr[1]<e_count[it.aAttr[4]].eAttr[3]:it.aAttr[0]+=4;it.aAttr[1]+=4
    elif it.aAttr[1]>e_count[it.aAttr[4]].eAttr[3]:it.aAttr[0]+=4;it.aAttr[1]-=4
    else:it.aAttr[0]+=8
   elif it.aAttr[0]>e_count[it.aAttr[4]].eAttr[2]:
    if it.aAttr[1]<e_count[it.aAttr[4]].eAttr[3]:it.aAttr[0]-=4;it.aAttr[1]+=4
    elif it.aAttr[1]>e_count[it.aAttr[4]].eAttr[3]:it.aAttr[0]-=4;it.aAttr[1]-=4
    else:it.aAttr[0]-=8
   elif it.aAttr[1]<e_count[it.aAttr[4]].eAttr[3]:it.aAttr[1]+=8
   elif it.aAttr[1]>e_count[it.aAttr[4]].eAttr[3]:it.aAttr[1]-=8
   hit_target(it)
  else:t_a_count.remove(it);t_a_count.remove(it);del it
def hit_target(it):
 global t_a_count,frozen;attr=it.aAttr
 if(attr[0]-9<e_count[attr[4]].eAttr[2]<attr[0]+9)and(attr[1]-9<e_count[attr[4]].eAttr[3]<attr[1]+9):
  t_a_count.remove(it);t_a_count.remove(it);r(attr[0],attr[1],3,3,(0,)*3);e_count[attr[4]].eAttr[0]-=attr[2];e_count[attr[4]].finished()
  if attr[3]=="ice":frozen=1
  del it
class t():
 def __init__(it,x,y,dmg,rel,range,type):
  global t_count;it.tx=x;it.ty=y;it.dmg=dmg;it.rel=rel;it.r_t=rel;it.ran=range;it.type=type;it.level=1
  if it.type=="normal":it.c=25
  elif it.type=="double":it.c=60
  elif it.type=="fire":it.c=130
  elif it.type=="ice":it.c=350
 def draw_t(it):
  if it.type=="normal":instr=((1,1,6,6,(70,)*3),(3,4,2,5,(120,)*3))
  elif it.type=="double":instr=((1,1,6,6,(70,)*3),(1,4,2,4,(120,)*3),(4,4,2,4,(120,)*3))
  elif it.type=="fire":instr=((1,1,6,6,(200,50,15)),(3,4,2,5,(70,160,10)))
  elif it.type=="ice":instr=((1,1,6,6,(80,80,180)),(3,4,2,5,(30,30,180)))
  for i in instr:r(it.tx+i[0],it.ty+i[1],i[2],i[3],i[4])
 def do_t_attack(it):
  if it.r_t>=it.rel:
   e_mod,target=0,0
   for e in e_count:
    if(it.tx-it.ran<e.eAttr[2]<it.tx+it.ran)and(it.ty-it.ran<e.eAttr[3]<it.ty+it.ran):target=1;break
    e_mod+=1
   if target:a=t_attack(it.tx,it.ty,it.dmg,it.type,e_mod);t_a_count.append(a);it.r_t=0
  else:it.r_t+=1
 def upgrade(it,upg_type):
  global M;UPGs=(
((25,0,4,12),(60,1,0,0),(150,0,5,8),(350,),(5,-12,32),(1,8,8)),
((60,0,2,12),(150,1,0,0),(350,0,3,8),(850,),(1,8,24),(4,0,8)),
((130,0,4,12),(300,2,0,0),(700,0,8,8),(2000,),(0,12,0),(1,4,16)),
((350,0,3,12),(850,2,0,0),(2000,0,5,16),(4500,),(-4,9,16),(10,-6,40)))
  if it.type=="normal":id=0
  elif it.type=="double":id=1
  elif it.type=="fire":id=2
  elif it.type=="ice":id=3
  if M>=UPGs[id][it.level-1][0]:
   M-=UPGs[id][it.level-1][0]
   if it.level<4:it.c=UPGs[id][it.level][0];it.dmg+=UPGs[id][it.level-1][1];it.rel-=UPGs[id][it.level-1][2];it.ran+=UPGs[id][it.level-1][3]
   elif it.level==4:del it.c;it.dmg+=UPGs[id][it.level+upg_type-1][0];it.rel-=UPGs[id][it.level+upg_type-1][1];it.ran+=UPGs[id][it.level+upg_type-1][2]
   it.level+=1;map_selection(-1)
def update_et():
 global frozen
 if(1-frozen)or(randint(1,5)==1):
  draw_path()
  for e in e_count:e.move();e.draw()
 frozen=0;sleep(.03)
 for t in t_count:t.do_t_attack();t.draw_t()
 for a in t_a_count:a.move_attack()
def z(nb,lvl,speed):
 for i in R(nb):
  e_count.append(ennemy(lvl,speed))
  for i in R(9-3*speed):update_et();control()
def start_w():
 global w;w+=1
 if w==0:u_s();z(4,1,1)
 elif w==1:u_s();z(3,1,1);z(3,2,1)
 elif w==2:u_s();z(6,1,2);z(6,2,1)
 elif w<30:u_s();z(w//4+1+w//16,w//4,2);z(w//3+1+w//16,w//3,1);z(w//4+2+w//16,w//3+w%3,1)
 else:u_s();z(w//8+w//16,w//5,2);z(w//4+w//16,w//4,2);z(w//3+1+w//16,w//3,1);z(w//4+w//16,w//3+w%3,1)
def map_selection(key):
 global map_pos,can_place,wave_on,prevPos;upg=""
 if wave_on!="":
  for a in t_a_count:a.draw_attack()
 if can_place:r(map_pos[0]*8,map_pos[1]*8,8,8,(0,)*3)
 if prevPos==0:
  draw_path()
  for e in e_count:e.draw()
 elif prevPos==1:
  for t in t_count:t.draw_t()
 elif prevPos==2:draw_castle()
 elif prevPos==3:draw_button()
 u_s()
 if key==0:map_pos[0]-=1
 elif key==1:map_pos[1]-=1
 elif key==2:map_pos[1]+=1
 elif key==3:map_pos[0]+=1
 if map_pos[0]<0:map_pos[0]=39
 elif map_pos[0]>39:map_pos[0]=0
 if map_pos[1]<0:map_pos[1]=24
 elif map_pos[1]>24:map_pos[1]=0
 can_place=1
 for i in t_count:
  if i.tx==map_pos[0]*8 and i.ty==map_pos[1]*8:can_place,upg,prevPos=0,i,1
 if can_place:#on path?
  for i in R(8):
   if can_place and(((i%2==0)and map_pos[1]==Map[i][1]and(Map[i][0]<=map_pos[0]<=Map[i][0]+Map[i][2]))or(i%2 and map_pos[0]==Map[i][0]and(Map[i][1]<=map_pos[1]<=Map[i][1]+Map[i][2]))):can_place,prevPos=0,0
 if can_place:
  if(28<map_pos[0]<34)and(19<map_pos[1]<25):can_place,prevPos=0,2#on castle ?
  elif(36<map_pos[0]<40)and(map_pos[1]<3):#on wave button ?
   can_place,onWbutton,prevPos=0,0,3
   if key==4:
    if wave_on=="":wave_on="-in progress";start_w()
  elif map_pos[1]<3:can_place,prevPos=0,4
 if can_place:r(map_pos[0]*8+1,map_pos[1]*8+1,6,6,(200,)*3);t_costs()
 elif upg!="":
  if upg.level<4:r(map_pos[0]*8+1,map_pos[1]*8+1,6,6,(160,160,255));init_disp();s("level "+str(upg.level)+". "+str(upg.c)+" to level up",0,205,(200,100,50),"k")
  elif upg.level==4:r(map_pos[0]*8+1,map_pos[1]*8+1,6,6,(255,100,255));init_disp();s("level 4. {} to max ([(] or [)])".format(upg.c),0,205,(200,120,100),"k",1)
  elif upg.level==5:init_disp();s("level MAX",0,205,(200,100,50),(0,)*3);r(map_pos[0]*8+1,map_pos[1]*8+1,6,6,(255,160,160))
  if key==16 and upg.level<4:upg.upgrade(0);sleep(.5)
  elif(key==33)or(key==34)and upg.level==4:upg.upgrade(key-32);sleep(.5)
  else:sleep(.065)
 else:
  try:onWbutton+=1;r(map_pos[0]*8+1,map_pos[1]*8+1,6,6,(200,255,200));del onWbutton
  except:r(map_pos[0]*8+1,map_pos[1]*8+1,6,6,(255,160,160))
 sleep(.12)
def draw_castle():
 r(232,160,40,40,(0,)*3);r(238,170,30,30,(70,)*3)
 for i in R(0,30,10):r((239+i),163,7,7,(70,)*3)
 for i in(0,12):r((242+i),174,9,9,(0,)*3)
 for i in R(4):r((248+i),(190-i),(10-2*i),10,(149,69,49))
def init_disp():r(0,200,238+10*(HP<100+HP<10),50,(0,)*3)
def t_costs():init_disp();s("50:  100:  200:  500:",0,205,(200,100,50),(0,)*3);r(33,205,12,12,(70,)*3);r(37,211,4,9,(120,)*3);r(93,205,12,12,(70,)*3);r(95,212,3,8,(120,)*3);r(100,212,3,8,(120,)*3);r(153,205,12,12,(200,50,15));r(157,211,4,10,(200,100,50));r(213,205,12,12,(80,80,180));r(217,211,4,10,(30,30,180))
def buy_t(key):
 global M,can_place;total_lvl=0
 for i in t_count:total_lvl+=i.level
 if len(t_count)*2.5>=total_lvl and len(t_count)>4:
  s("upgrade your turrets first",25,50,(200,10,25),(0,)*3);sleep(2);s("                          ",25,50,(0,)*3,(0,)*3)
  for i in t_count:i.draw_t()
  if wave_on=="":draw_path()
 else:
  if key==42 and M>=50 and can_place:place_t(map_pos[0]*8,map_pos[1]*8,1,42,56,"normal");M-=50;can_place=0
  elif key==43 and M>=100 and can_place:place_t(map_pos[0]*8,map_pos[1]*8,1,18,40,"double");M-=100;can_place=0
  elif key==44 and M>=200 and can_place:place_t(map_pos[0]*8,map_pos[1]*8,3,40,56,"fire");M-=200;can_place=0
  elif key==36 and M>=500 and can_place:place_t(map_pos[0]*8,map_pos[1]*8,3,40,72,"ice");M-=500;can_place=0
  u_s();sleep(.2)
def place_t(x,y,damage,reload,range,type):t_count.append(t(x,y,damage,reload,range,type));t_count[-1].draw_t();map_selection(-1)
def draw_button():
 r(296,0,24,24,(140,)*3)
 for i in R(10):r(303+i,2+i,1,17-2*i,(250,)*3)
def draw_path():c=(130,90,5);r(0,32,112,8,c);r(104,40,8,32,c);r(32,72,80,8,c);r(24,72,8,64,c);r(32,128,152,8,c);r(176,56,8,72,c);r(184,56,72,8,c);r(248,64,8,104,c)
def control():
 for k in(42,43,44,36):
  if kd(k):buy_t(k)
 for i in(0,1,2,3,4,16,33,34):
  if kd(i):map_selection(i)
def u_s():
 col=(200,10,25);r(0,0,296,24,(0,)*3);s("Money "+str(M),230-10*len(str(M)),0,(200,100,50),(0,)*3);s("Wave "+str(w)+wave_on,0,0,col,(0,)*3)
 if(HP<100)and(HP>9):s("     "+str(HP),238,203,(0,)*3,(0,)*3);s("HP : "+str(HP),250,203,col,(0,)*3)
 elif(HP<10):s("     "+str(HP),250,203,(0,)*3,(0,)*3);s("HP : "+str(HP),260,203,col,(0,)*3)
 else:s("HP : "+str(HP),238,203,col,(0,)*3)
opt=1;col=[200,10,25];r(0,0,320,230,(0,)*3);s("Castle Defence",87,80,col,(0,)*3);sleep(.4)
while 1-kd(4):
 if col[0]>70 and opt==1:col[0]-=1
 else:
  col[0]+=1
  if col[0]<200:opt=0
  else:opt=1
 s("Press [OK] to continue",52,125,col,(0,)*3);sleep(.004)
while kd(4):0
col=[200,10,25];r(0,0,320,230,(0,)*3);s("Select with arrow keys",50,8,col,(0,)*3);s("1,2,3 and 4 to place turrets",20,32,col,(0,)*3);s("(1 costs 50,2 costs 100...)",25,48,col,(0,)*3);s("Select the play button and",30,72,col,(0,)*3);s("press [OK] to start next wave",15,88,col,(0,)*3);s("press toolbox/parenthesis",35,112,col,(0,)*3);s("to upgrade turrets",70,128,col,(0,)*3)
while 1-kd(4):
 if col[0]>70 and opt==1:col[0]-=1
 else:
  col[0]+=1
  if col[0]<200:opt=0
  else:opt=1
 s("Press [OK] to start",65,200,col,(0,)*3);sleep(.004)
while kd(4):0
r(0,0,320,222,(0,)*3);del col;draw_button();draw_path();draw_castle();t_costs()
while HP>0:
 while len(e_count):
  update_et();control()
  if HP<=0:break
 wave_on="";t_a_count.clear();r(0,24,320,181,(0,)*3);draw_path();draw_castle()
 for i in t_count:i.draw_t();i.rt=9999
 map_selection(-1);u_s()
 while wave_on=="":control()
r(0,0,320,222,(0,)*3);s("GAME OVER",120,50,(200,10,25),(0,)*3);s("you lost at wave "+str(w),70,100,(200,10,25),(0,)*3)
#456

During your visit to our site, NumWorks needs to install "cookies" or use other technologies to collect data about you in order to:

With the exception of Cookies essential to the operation of the site, NumWorks leaves you the choice: you can accept Cookies for audience measurement by clicking on the "Accept and continue" button, or refuse these Cookies by clicking on the "Continue without accepting" button or by continuing your browsing. You can update your choice at any time by clicking on the link "Manage my cookies" at the bottom of the page. For more information, please consult our cookies policy.