Log In  


As shown in the picture above, the "from" variable is being considered a function at some time during execution. Problem is: there's nowhere in the program that I can turn that variable into a function, because it is a local variable (and the only place the 2nd argument is ever assigned is in the function itself):

function unpack(list,from,to)
 from,to=from or 1,to or #list
 if from<=to then
  return list[from],unpack(list,from+1,to)
 end
end
function to_tab_unp(tab)
 return unpack(str_to_table(tab))
end

The weirdest thing is that I call the line "in cr_char line 5 (tab 2)" every time I create a character. In this particular instance I'm recreating battles to get until I get one with a formation that fits the difficulty level I want. So it's like 1/10000 of cases generates that error. But the table being unpacked is always the same:

to_tab_unp(",{,{,{,{,,f,{,,,{,{,,,{,{,{,{,{,,,,")

So it seems to me that this is a pico-8 bug, because the function is always exactly the same but and the error pops for no apparent reason...?

Thoughts?



Avoid using keywords for variable names. I've run into this problem as well. Watch as you type a variable name and if any part of it turns pink or green while typing, choose a different variable name instead.


I can't post the cart without minifying it, so here's the code if needed:

Tab 0

--constants
--cartdata("bonevolt_jack_of_spades")
--if (stat(6)=="a") load("jostitle.p8")
poke(0x5f2d,1)
function str_to_table(str)
 local tab,sptab={},{}
 for i=1,#str do
  if sub(str,i,i)=="," then
   for j=i+1,#str do
    local strn=sub(str,j,j)
    if(strn=="|")add(sptab,tab)tab={}i+=1 break
    if strn=="," then
     local s=sub(str,i+1,j-1)
     if tonum(s) then
      s=tonum(s)
     elseif s=="" then
      s=0
     elseif s=="t" then
      s=true
     elseif s=="f" then
      s=false
     elseif s=="{" then
      s={}
     end
     add(tab,s)
     i=j
     break
    end
   end
  end
 end
 if (#sptab>0) return sptab
 return tab
end

function unpack(list,from,to)
 from,to=from or 1,to or #list
 if from<=to then
  return list[from],unpack(list,from+1,to)
 end
end

function to_tab_unp(tab)
 return unpack(str_to_table(tab))
end

function checkered_floor(ww,hh,xr,yr,ox,oy,cc)
	for i=1,xr do
	 for j=1,yr do
	  if (i+j)%2==0 then
	 		rectfill(ww*i+ox,hh*j+oy,ww+ww*i+ox-1,hh+hh*j+oy-1,cc)
	 	end
	 end
	end
end

function cam(xx,yy)
 camera(cam_x+xx,cam_y+yy)
end

chk,chatt,chhp,cheff,cheffa,cheffd,cheffc,cheffv,chdesc,chvfxc,char_vptc=str_to_table(",1,2,3,4,,6,5,,"),str_to_table(",6,4,5,5,8,3,9,5,5,3,3,4,,10,5,6,9,3,4,5,6,10,6,6,4,12,1,5,6,4,12,6,6,7,3,6,,"),str_to_table(",30,40,35,30,50,60,30,50,10,10,15,5,20,100,40,30,15,25,45,30,30,25,30,30,20,60,5,25,20,40,80,40,40,300,25,25,25,"),str_to_table(",,,,,,,,,16,15,,,,,2,7,,,,,,18,,,19,16,15,6,12,,20,2,24,7,2,2,,"),str_to_table(",,,,,,,,,21,,23,3,,1,5,,,21,,23,10,,3,5,,,,,,22,,,,3,,,,"),str_to_table(",,,,,,,,,999,,,,,4,,,,999,,,,,,,,,,,,,,,,,,999,,"),str_to_table(",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"),str_to_table(",,,,,,,,,1,1,1,,,-1,1,1,,1,,1,12,1,1,1,1,1,1,1,99,1,2,4,1,1,2,3,,"),str_to_table(",jack of spades,queen of hearts,king of diamonds - 1 armor,jack of clubs - crit x3,black king,joker,lance,chester,sleeping flower,static cactus,muncher,multi flower,dummy,white king - fear,white pawn - pierce,white bishop - heal,floaty,snaky - poison,pumpky,batty - lifesteal,skully - kill <13 hp,mouthface - stone form 3 turns,furkniceght - splash attack,cyclopt - pierce,daymon - confused,tombzord - sleep,skelly,swordslime - double attack,spellslime - sp immunity,wardrobber - detroy 1st card,jimmy - crit chance x3,rook,knight - allies att+1,white queen - splash att/heal,stumpy,steel mech,illusion crystal,"),str_to_table(",,,,,,,,,4,7,4,6,,3,5,2,1,4,3,2,2,5,8,5,5,11,7,4,6,8,2,5,1,1,4,,,"),str_to_table(",6,14,6,13,14,6,6,6,14,6,6,7,1,14,6,14,14,6,6,6,6,6,5,6,6,6,6,6,14,6,6,6,6,24,7,6,6,")
pawn_clr,item_att,item_eff,item_effd,item_effc,item_effa,item_effv,item_desc,item_vfxc,chtr,c_val,csprb,draw_funct,fade_c,hcol,kcol,kposx,kposy,kflip,typ_ch_area,c_typ_to_algn=str_to_table(",,,,,2,9,10,,,,,,4,,,|,,,,,1,8,14,,,,,,2,,,|,,,,,1,3,11,,,,,,1,,,|"),str_to_table(",6,4,5,5,8,3,9,5,6,6,5,6,12,6,5,8,8,4,5,5,8,8,8,3,3,3,9,9,9,9,5,"),str_to_table(",,,2,,,,,,6,7,,,,,15,,,,2,,,20,24,,,,,31,32,,,"),str_to_table(",,,,,,,,,,,4,999,,4,,,,,,2,,,,,,,,,,,,"),str_to_table(",,,,,,,,,,,,,,,,25,,,,17,23,,,,,,,,,,,"),str_to_table(",,,,,,,,,,,1,21,5,2,,,3,,,,,,,,,,,,,10,,"),str_to_table(",,,1,,,,,,1,1,-2,2,1,-1,1,,1,,4,1,,2,1,,,,,1,2,18,,"),str_to_table(",,,,,,,,,twin sword - x2 att,crystal heart - 50% heal ally\n+2 att,grand king's crown - enm att-2,humble pouch - poison x2\n+1 att,silver edge - pierce\n+6 att,pocket ocean - enm def-1\n+2 att,sparkling mantle - return dmg,perpetual wind - crit pull enm\n+3 att,heat blade - 50% splash dmg\n+2 att,living whip - summon stumpy\nhp:25 att:3 armor:2,stone mask - 4 armor,winter star - crit freeze,red raindrop - crit lifesteal,scarlet shadow - 75% crit,black pearl - allies att+1,magic mirror - mirrors allies\nkinds,ultra glove - hold 9 cards,chaos scepter - shuffle x5,,lance of willpower - attack\nafter defeated,swift staff - attack enemy\nback lines,execution lance - kill <19 hp,chester's items,"),str_to_table(",5,2,5,5,11,11,5,5,2,2,3,4,5,1,7,9,6,4,8,10,2,2,11,10,9,11,5,5,5,5,,"),str_to_table(",11,11,11,11,11,11,11,,,,,,,11,11,11,,,,11,,,,,,,,,,,,11,11,11,,11,11,"),str_to_table(",1,1,1,1,1,3,5,2,2,3,3,3,2,3,4,"),{nil,nil,nil,nil,0,0,nil,to_tab_unp(",,,,,,,1,1,1,,,,,,,,,,,,1,1,,,1,1,1,,,,")},{cls,rect,rectfill,fillp,sspr,checkered_floor},str_to_table(",,1,1,1,1,13,6,2,4,9,3,13,5,8,14,1,13,8,11,9,13,7,7,14,10,15,10,6,12,15,7,"),str_to_table(",1,9,10,13,"),str_to_table(",1,8,9,3,"),str_to_table(",7,7,7,7,7,7,7,11,11,11,11,11,11,11,15,15,15,15,15,15,15,11,11,"),str_to_table(",6,9,12,15,18,21,24,6,9,12,15,18,21,24,6,9,12,15,18,21,24,10,20,"),str_to_table(",f,f,f,f,t,t,t,f,f,f,f,t,t,t,f,f,f,f,t,t,t,f,t,"),str_to_table(",,,1,,,2,,,,3,,"),str_to_table(",,1,1,1,2,2,4,2,2,3,3,")
card_tgt,card_eff,card_dur,card_eff_v,card_dmg,card_sub,card_vptc,card_txt=str_to_table(",2,5,2,3,7,5,5,6,6,3,2,6,2,|,2,1,3,5,1,2,6,6,6,1,1,2,5,|,2,5,5,2,8,9,11,5,2,6,9,10,5,|,5,5,5,1,11,5,6,5,9,2,6,9,6,|,2,1,1,7,2,6,7,5,3,6,2,6,6,|,1,,1,6,10,5,1,|"),str_to_table(",1,3,6,1,3,5,,,5,2,1,,8,|,,14,,2,14,9,10,2,12,14,14,13,,|,20,,,4,,,18,19,15,1,,3,1,|,,17,25,14,25,4,20,16,,11,,,17,|,,14,14,21,27,,3,,27,19,34,2,33,|,14,,28,16,17,29,30,|"),str_to_table(",4,,2,4,,,,,,4,2,,2,|,,5,,4,99,99,,4,4,,,4,,|,4,,,1,,,3,4,4,4,,,4,|,,2,,,,2,3,9,,2,,,1,|,,,,99,1,,,,1,1,99,8,,|,,,,99,2,,,|"),str_to_table(",2,,1,1,,,,,,1,8,,2,|,,9,,-2,10,8,15,-1,-3,11,12,6,,|,2,,,1,,,1,1,1,-1,,,-4,|,,1,,13,,1,-1,1,,1,,,1,|,,36,37,6,4,,,,2,2,5,-3,,|,15,,,1,1,,,|"),str_to_table(",,8,,,14,12,,5,6,,,6,,|,-8,,-5,,,,,,,,,,,|,,15,10,,8,6,,,,,15,3,,|,3,,9,,,,,,4,,2,4,,|,-40,,,12,,80,,8,,,,,20,|,,,,,,,,|"),str_to_table(",1,9,1,1,9,5,1,9,5,5,1,9,5,|,2,10,2,6,10,2,6,6,2,10,10,2,6,|,3,7,11,3,11,7,11,3,7,3,7,11,3,|,4,12,8,4,8,4,12,12,8,4,4,8,12,|,37,38,39,40,41,42,43,44,45,46,47,48,49,|,56,,56,56,56,56,56,|"),str_to_table(",1,5,1,1,5,6,23,5,16,1,1,5,1,2,7,2,8,7,2,21,8,2,7,7,2,22,3,18,10,3,15,9,3,3,9,3,9,17,3,13,12,11,4,11,4,12,12,19,4,13,19,20,43,14,14,39,14,38,42,14,14,14,43,40,41,14,,14,14,12,45,14,"),str_to_table(",silver sharp: att+2 to ally\nlasts 4 turns,fireball: dmg enemy+neighbors\n8 dmg to target and 4 to others,honor: ally attacks twice\nlasts 2 turns,empower: att+1 to all allies\nlasts 4 turns,fire bomb: 7 dmg 3x3 area\ncan target ground,metal blade: pierces defense\n12 dmg,soul blade: jack deals\n1 dmg per hp he's missing,fire storm: dmg all enemies\n5 dmg,ultra blade: pierce all enemies\n6 dmg,super armor: def+1 all allies\nlasts 4 turns,ultra sharp: att+8 to ally\nlasts 2 turn,ultra fire: dmgs self and\nenemies - 6 dmg,ultra armor: halves ally dmg\nlasts 2 turns,|,heal: ally hp +8,sleeping seed: wakes up if hit\nhp:10 att:5 - poison,heal allies: all allies hp +5,corrosion: enemy def-2\nlasts 4 turns,static cactus: reflects dmg\nhp:10 att:3,barrier: absorbs 8 dmg,flood: kills all enemies with\n 15 hp or less,rust: all enemies def-1\nlasts 4 turns,heartbreak: enemies spdef-3\nlasts 4 turns,muncher: lifesteal\nhp:15 att:3,multi flower: splash att\nhp:5 att:5,super barrier: detroyed if\ndmg 6 or more. lasts 4 turns,flood bubble: deals damage\nequal to hp missing from enemy,|,super focus: critical chance x3\nlasts 4 turns,thunder:\n15 dmg to enemy,boulder: push enemy back\n10 dmg,taunt: all enemies attack ally\nlasts 1 turn,fissure: dmg 1 collumn\n8 dmg,shock: dmg 3 lines\n6 dmg,stone form: attack and damage\nreduced t0 1. lasts 3 turns,confusion: 50% enemy att allies\nlasts 4 turns,electrify: return dmg received\nlasts 4 turns,fear: enemies att-1\nlasts 4 turns,static: 15 dmg spread between\nenemies (3 rows; rounded up),quake: 3 dmg to enemies and\nallies for each neighbor,overwhelm: enemy att-4\nlasts 4 turns,|,super bow: hits enemy 4 times\n3 dmg per shot,freeze: stops enemy\nlasts 2 turns,wind shot: pull enemy\n9 dmg,dummy:\nhp:20 att:0,anti-magic wind: pull unit left\nand remove all effects,track: all allies attack enemy\nlasts 2 turns,mind freeze: enemies critical\nchance=0 lasts 3 turns,sleep: wakes up if attacked\nlasts 9 turns,vacuum: pull all enemies\nto line. 4 dmg,invisibility: enemies don't\nattack ally. lasts 2 turns,ultra bow: hits all enemies 4\ntimes. 2 dmg,wind blast: push all enemies\naway from line. 4 dmg,blizzard: stops all enemies\nlasts 1 turn,|,healing light: ally hp +40,steel mech:\nhp:25 att:6 armor:3,illusion crystal: splashes\ndirect dmg received - hp:30,poison cloud: 6 dmg+6 poison on\n3x3 area. can target ground,shadow form: ally atacks one\nenemy +4 times,chaos bolt: deals 80 dmg to a\n random enemy,rainbow wave: 3x3 area enemies\nhp is halved. can target ground,neutral shot: 8 dmg to enemy\ncan be combined with any card,time distortion: each ally\nattacks one enemy +2 times,madness: all enemies are\nconfused for 1 turn,ultra barrier: absorbs 5 hits,acid burst: all enemies def-3\nlasts 8 turns,meteor blast: dmg all enemies\n20 dmg skips 1 turn,|,ludo squad: summon 3 ludo\nrangers,poker token: use 5 cards of any\nkind. extra dmg if poker hand,amulet: summon ally to free\ntile. reshuffles deck,music box: all enemies sleep,ultra freeze: freezes all for\n2 turns,devour:,spit:,|")
vp_spr,vp_sfx,vp_bit,vp_clr,vp_spwn,vp_spd,sprv,kpos,to_col,armorc,hplay,hcanc,mousep,c_val[0],level=str_to_table(",300,300,300,300,300,300,300,300,300,300,300,300,327,328,329,330,244,245,246,247,248,249,250,251,252,331,233,-1,235,231,227,-1,173,302,245,302,263,263,263,263,265,265,302,265,265,267,267,267,267,229,-1,-1,302,302,302,269,-1,"),str_to_table(",59,59,59,59,59,59,59,59,59,59,59,59,2,4,7,7,1,,5,6,53,19,56,3,58,3,54,,54,53,56,57,57,57,,62,59,59,59,59,59,59,59,59,59,59,59,59,59,53,53,53,1,3,3,59,,"),str_to_table(",101,102,104,108,101,102,104,108,101,102,104,108,,,,,,,,,,,,,,,,,,,,,,,,,101,102,104,108,101,102,101,104,108,101,102,104,108,,,,101,101,101,101,,"),str_to_table(",1,2,3,4,5,1,7,9,6,4,8,10,1,2,3,4,,,,,,,,,,,,,,,,,,1,1,5,7,5,1,4,11,2,12,10,5,2,3,4,6,,,,6,12,7,2,3,"),str_to_table(",,,,,,,,,,,,,,,,,8,,,,,,,,,,,,,,,,12,12,,12,,,,,,,,,,,,,,,3,11,8,12,,,,"),str_to_table(",1,1,1,1,1,1,1,1,1,1,1,1,1.5,1.5,1.5,1.5,3,3,3,3,3,3,2,3,3,3,1,3,3,3,2,.7,2,1,2,1.5,1,1,1,1,1,1,1,1,1,1,1,1,1,3,2,2,3,1,1,1,3,"),str_to_table(",,,3,5,|,5,,3,5,|,10,,3,5,|,24,,3,5,|,7,,3,5,|,2,,3,5,|,19,,3,5,|,12,,3,5,|,27,,3,5,|,14,,5,5,|,17,,3,5,|,30,,3,5,|,21,,3,5,|,,5,5,5,|,5,5,5,5,|,10,5,5,5,|,15,5,5,5,|,20,5,5,5,|,25,5,5,5,|,,10,5,5,|,5,10,5,5,|,10,10,5,5,|,15,10,5,5,|,20,10,5,5,|,25,10,5,5,|,30,11,3,4,|,33,11,3,4,|,36,11,3,4,|,39,11,3,4,|,71,11,5,5,-1,-1,|,,15,16,9,|,,24,16,7,|,16,89,16,7,|,60,11,11,6,|,76,,52,11,|,96,41,14,16,|,16,15,16,15,1,1,|,33,18,15,13,|,48,18,16,13,2,|,77,11,16,15,2,2,|,64,17,13,15,1,|,42,11,18,7,|,,96,20,20,,1,|,72,0,16,11,|,77,26,17,16,2,|,13,47,13,16,1,|,47,31,17,16,2,|,64,32,13,14,|,,31,16,16,|,52,47,14,16,|,,96,20,20,,1,|,72,0,16,11,|,16,30,17,16,2,|,108,24,12,15,|,111,40,17,14,2,|,94,27,14,14,|,26,47,13,16,|,39,47,13,16,2,|,,96,20,20,,1,|,72,0,16,11,|,66,56,12,13,|,66,46,11,10,|,83,52,13,9,3,|,90,61,11,12,1,|,101,57,11,14,|,35,80,13,16,|,107,11,13,13,|,93,10,14,17,|,120,13,8,11,|,120,24,8,8,|,120,32,8,8,|,104,71,8,9,|,88,42,8,8,|,78,85,10,9,|,80,74,8,11,|,80,61,10,13,|,35,64,13,12,-1,|,90,73,14,21,|,61,,10,14,3,|,19,64,16,19,-1,|,,64,19,14,-2,|,59,80,19,16,|,44,,10,10,|,33,31,14,16,|,,47,13,16,|,112,64,16,32,|,88,,11,10,|,72,96,12,13,|,48,80,11,13,|,115,,12,11,|,77,42,10,13,|,33,,11,8,-1,|,16,101,4,3,|,16,101,4,3,|,16,101,4,3,|,16,101,4,3,|,16,101,4,3,|,16,101,4,3,|,56,144,5,5,|,61,144,5,5,|,66,144,5,5,|,71,144,5,5,|,76,144,5,5,|,81,144,5,5,|,86,144,5,5,|,91,144,5,5,|,56,149,5,5,|,61,149,5,5,|,66,149,5,5,|,71,149,5,5,|,76,149,5,5,|,81,149,5,5,|,86,149,5,5,|,91,149,5,5,|,56,154,5,5,|,61,154,5,5,|,66,154,5,5,|,71,154,5,5,|,76,154,5,5,|,81,154,5,5,|,64,72,16,8,|,112,54,16,10,|,42,102,5,5,|,47,102,5,5,|,52,102,5,5,|,57,102,5,5,|,62,102,5,5,|,67,102,5,5,|,42,107,5,5,|,47,107,5,5,|,52,107,5,5,|,57,107,5,5,|,62,107,5,5,|,67,107,5,5,|,78,55,5,5,|"),str_to_table(",11,|,9,13,|,8,11,14,|,1,7,15,21,|,1,7,15,21,11,|,1,7,15,21,4,18,|,1,7,15,21,4,18,22,|,1,7,15,21,4,18,22,23,|,1,3,5,7,15,17,19,21,11,|,1,3,5,7,15,17,19,21,22,23,|"),str_to_table(",1,1,2,1,1,2,4,1,13,13,1,1,2,4,3,5,8,7,2,6,13,2,13,8,9,11,13,9,9,5,13,12,13,12,14,10,11,6,10,6,4,6,6,14,6,15,15,6,6,15,10,9,7,7,6,7,7,7,7,7,7,7,13,7,7,7,"),str_to_table(",8,14,15,7,6,13,12,1,13,2,8,"),to_tab_unp(",,,1,,310,")
char_item,glob_hp=str_to_table(",1,9,13,17,|,2,10,14,18,|,3,11,15,19,|,4,12,16,20,|,5,21,22,23,|,6,24,25,26,|,27,28,29,30,|,32,33,|"),str_to_table(",30,40,35,30,50,60,30,50,")

Tab 1

--init
function _init()
 --draw_fade_out()
 b_party,char_curr_item,summ_tilex,summ_tiley,handanditem,en_typ,ptc,vfx,g_time,tomb2,hand_kind,end_count,wperc,turn_card,txt,summ_chars,turn,deck,hand,chs_item,char,vfx,t_loop,jk17,reshuffle,start_batt,curr_k,curr_n,allowk,allown,poker,skipturn,lastx,newx=str_to_table(",1,2,3,4,5,6,7,8,"),str_to_table(",1,1,1,1,1,1,1,1,"),str_to_table(",2,2,2,"),str_to_table(",2,4,6,"),to_tab_unp(",{,{,{,{,,f,{,,,{,{,,,{,{,{,{,{,,,,")

 --level+=5
 difficulty,ltries=0,0
 while abs(level-difficulty)>25 do
  ltries+=1
  difficulty,char=0,{}
	 for i=1,4 do
	  en_typ[i]=irnd(19)+15
	 end
	 for i=1,9 do
	  while newx==lastx do
	   newx=irnd(3)
	  end
	  lastx,ttyp=newx,en_typ[irnd(4)+1]
	  cr_char(newx+5,i-1,ttyp,2)
	  difficulty+=ttyp
	 end
	 --if (ltries%20==0) cls(7) print("\n\n\n\n\n\n\n\n\n\n"..stat(0).."\n\n"..stat(1),0,0,0) flip()
 end
 --music(28)
end

Tab 2

--init functions
function cr_char(x,y,t,a)
 if tile_free(x,y) then
	 c={}
	 s,c.tx,c.ty,c.tgtx,c.tgty,c.typ,c.algn,c.hp,c.desc,c.act,c.mperc,c.eff,c.ischar,c.sprt,c.flp,c.crit,c.cmult,c.quake=s or 1,x,y,x,y,t,a,chhp[t],chdesc[t],to_tab_unp(",,,{,1,,f,25,2,-1,")
	 --if (a==2) c.hp+=peek(0x5eca)*(t==32 and 100 or 5)
	 if (t==4) c.cmult=3
	 --if (t<=8) c.hp+=min(charlevel[t]-2,10)
	 c.hpmx=c.hp
	 if (t<=8) c.hp=glob_hp[t]
  --c.hp=1
	 if (cheff[t]>0) add(c.eff,new_eff(cheff[t],cheffv[t],999))
	 --if (t==3) add(c.eff,new_eff(2,1,999))
	 move(c)
	 add(char,c)
	 return c
 end
end

function add_card(k,n,tab,ch,item)
 c={}
 c.k,c.n,c.h,c.char,c.tgttyp,c.tab,c.item=k,n,0,ch,card_tgt[k][n],tab,item
 add(tab,c)
end

function deal_hand()
 count,handanditem=1,{}
 while count<=7+jk17*2 do
  if not hand[count] then
   for crd in all(deck) do
    hand[count]=crd del(deck,crd) break
   end
  end
  count+=1
 end
 reset_crd_pos()

	if chester and #chs_item==0 then
	 if devoured then
	  add_card(6,7,chs_item,chester)
	 else
	  if (countchars[2]>1) add_card(6,6,chs_item,chester)
	 end
	end

	transf_tab(handanditem,hand)
	transf_tab(handanditem,chs_item)
end

function new_vfx(typ,x,y,c)
	v={}
	v.typ,v.x,v.y,v.clr,v.ys,v.dur,v.dt,v.xs=typ,x,y,c,c==8 and 1 or 0,to_tab_unp(",10,0,0,")
 add(vfx,v)
 return v
end

function new_ptc(ch,typ,tgt,spec)
 p={}
 local k,n,iscrit,chtyp=flr((spec-1)/13)+1,(spec-1)%13+1,rnd(100)<=ch.crit*(1+count_eff(curr_ch,20)),ch.typ
 p.spec,p.vfxc,p.mperc,p.ch,p.typ,p.tgt,p.tx,p.ty,p.tgtx,p.tgty,p.multi=spec,spec>0 and vp_clr[card_sub[k][n]] or chvfxc[ch.typ],0,ch,typ,tgt,ch.tgtx+.45,ch.tgty+1,tgt.tx+.45,tgt.ty+1,multi
 if typ==0 then
  if spec>0 then
   p.eff=new_eff(card_eff[k][n],card_eff_v[k][n],card_dur[k][n])
  else
   local sel_eff=cheffa[chtyp]
   if (iscrit and cheffc[chtyp]~=0) sel_eff=cheffc[chtyp]
   p.eff=new_eff(sel_eff,cheffv[chtyp],cheffd[chtyp])
  end
 end
 --p.eff=new_eff_c(flr((spec-1)/13)+1,(spec-1)%13+1)
 --p.dur=dur
 --local norm=(min(spec,1)+1)%2
 --typ 0 is charging effect
 local vptc=card_vptc[spec]
 if typ==0 then
  if spec==0 then
	  vptc,p.dmg=char_vptc[chtyp],ch.att*buff_ally*(bool_to_num(iscrit)*(ch.cmult-1)+1)
 	elseif spec==7 then
 	 p.dmg=ch.hpmx-ch.hp
 	elseif spec==26 then
 	 p.dmg=tgt.hpmx-tgt.hp
 	else
		 p.dmg=card_dmg[k][n]
 	end
 	vptc+=12
 else
  vptc,p.charge=typ,1
 end
 p.spwn,p.bit,p.sprt,p.clr,p.spd,p.sprtflip=vp_spwn[vptc],vp_bit[vptc],vp_spr[vptc],vp_clr[vptc],vp_spd[vptc],false
 if (tgt.algn==1) p.sprtflip=true
 --if (tgt==ch) p.sprt=0
 if (p.sprt==331) p.clr=p.vfxc
 add(ptc,p)
 sfx(vp_sfx[vptc])
 return p
end

function new_eff(t,v,d)
 e={}
 e.typ,e.val,e.dur=t,v,d
 return e
end

function new_fl_text(x,y,ftxt)
 t={}
 t.x,t.y,t.txt,t.tim=x,y,ftxt,0
 add(txt,t)
end

Tab 3

--update
function _update()
 --if (btn()>0) load("jostitle.p8",nil)
 --mouse
 mousex,mousey=stat(32),stat(33)
 mousep+=1
 if (stat(34)==0)mousep=0

 g_time+=1
 t22,t4,t2,hplay,hcanc,tilex,tiley,countchars,loopspr=flr(g_time/2%2),g_time%4,g_time%2,0,0,flr((mousex+8)/16),flr((mousey-4)/10),{0,0}

 if (g_time==10) _init()
 if (g_time==2640) g_time,t_loop=0,1

 --upd battle
 --update attack damage
 for ch in all(char) do
  if (ch.typ==6) joker=ch
  if (ch.typ==34) tomb2=true
  if (tomb2 and ch.algn==2) ch.und=true
	 if (ch.hp>0) countchars[ch.algn]+=1
	 ch.att=chatt[ch.typ]+(ch.clr and (ch.clr*2-3) or 0)
	 --if (ch.algn==2) ch.att+=peek(0x5eca)
	 --stone form attack
	 if (count_eff(ch,18)>0) ch.att=1
	 --att buff
	 ch.att=max(0,ch.att+count_eff(ch,1))
	 --knight aura
	 for ch2 in all(char) do
	 	if (ch2.hp>0 and ch.algn==ch2.algn) ch.att+=count_eff(ch2,24)
	 end
 end
 if (devoured) countchars[2]+=1
 if (g_time==1 and t_loop==0) start_batt,pre_battle=true,true

 if start_batt then
 function refr_crd_tgt()
		--card targeting
	 hchars,hareax1,hareay1,hareax2,hareay2=0
 	for crd in all(handanditem) do
 	 if crd.h==2 then
 	  local tgttyp=crd.tgttyp
 	  hchars=c_typ_to_algn[tgttyp]
  	 --mouse tile
  	 if mouse_area(to_tab_unp(",-8,4,136,93,")) then
  	  hareax1,hareay1,hareax2,hareay2=tilex,tiley,tilex,tiley
   	 if tgttyp==9 then
    	 hareax1,hareax2=0,8
   	 elseif tgttyp==8 then
    	 hareay1,hareay2=0,8
   	 elseif typ_ch_area[tgttyp]>0 then
   	  hareax1,hareax2,hareay1,hareay2=to_tab_unp(",8,,8,,")
					 for ch in all(char) do
					  if typ_ch_area[tgttyp]==ch.algn or typ_ch_area[tgttyp]==3 then
					   hareax1,hareax2,hareay1,hareay2=min(hareax1,ch.tx),max(hareax2,ch.tx),min(hareay1,ch.ty),max(hareay2,ch.ty)
					  end
					 end
   	 end
   	end
 	 end
 	end
	end
	refr_crd_tgt()

 if end_count==0 then
  reset_crd_pos()
  --if turn==-1 then
  if pre_battle then
   if summ_chars<#summ_tilex then
    chx,chy=flr((mousex+12)/15),flr((mousey+6)/16)
    if mousep==1 and mousey<=112 then
     local t=b_party[chx]
     if t then
      if chy==6 then
     		local i=min(char_item[t][char_curr_item[t]],31)
     		chatt[t],cheff[t],cheffa[t],cheffc[t],cheffv[t],cheffd[t],chvfxc[t]=item_att[i],item_eff[i],item_effa[i],item_effc[i],item_effv[i],item_effd[i],item_vfxc[i]
	      summ_chars+=1
	      local ch=cr_char(summ_tilex[summ_chars],summ_tiley[summ_chars],t,1)
	      if (i==18) cr_char(summ_tilex[summ_chars]+1,summ_tiley[summ_chars],35,1)
	      add_char_cards(ch)
	      --chester
	      if t==8 then
	       chester=ch
	       for i=1,#char_item[8] do
	        add_card(6,char_item[8][i]-30,chs_item,ch,char_item[8][i])
	       end
	      end
	      hand_kind[chk[t]],b_party[chx]=true
      elseif chy==7 and t<8 then
     		char_curr_item[t]=char_curr_item[t]%#char_item[t]+1
     	end
     end
    end
   else --all chars picked
    pre_battle=nil
    --joker cards
    if hand_kind[6] then
	    jk_item=char_item[6][char_curr_item[6]]
	    jk17=bool_to_num(jk_item==25)
	    if (jk_item==26) reshuffle=5
     for k=1,5 do
      if hand_kind[k]==(jk_item==24 or nil) then
       if k<5 or jk_item==24 then
	       for i=1,13 do
	        add_card(k,i,deck,joker)
	       end
       end
      end
     end
    end
    -----
    shuffle_deck()
   end
  elseif turn==0 then
   deal_hand()
   --highlight cards
   if (hlight and hlight.h~=2) hlight=nil
   not_sel_fr,hlaux,hover=1
   --hover cards
   for crd in all(hand) do
    crd.y=96
    if (crd.h==1) crd.h=0
    if mouse_area(crd.x,crd.y-9,crd.x+24,crd.y+53) then
     hlight,hlaux,hover=crd,crd,1
    end
   end
	  --hover chester items
	  for i,itm in pairs(chs_item) do
	   if (itm.h==1) itm.h=0
	   if mouse_area(95+i*8,97,101+i*8,103) then
	    hlight,hlaux,hover=itm,itm,1
	   end
   end
   function select_new()
    hlight.h=max(1,hlight.h)
	   if mousep==1 then
	    if (sel_card) sel_card.h=0
     hlight.h,sel_card,not_sel_fr=2,hlight
     refr_crd_tgt()
    end
   end
   --press
   if hlight and 
   (
    (
     (
      (
	      not allowk or 
	      (
	       (
		       allowk==hlight.k
		       or allown==hlight.n
	       )
	       and allowk<5 and
	       hlight.k<5
	      )
	     )
	     or
	     (
		     hlight.k==5 and
		     hlight.n==8 
	     )
	    )
	    and not poker
	   )
	   or poker and poker<5
	   or hlight.k==6
	  )
	  and hlight.h~=3 and
	  hover then
    select_new()
   end
-- if mouse_area(88,96,92,100) then
   --selected card
   if sel_card and ((hareax1 and mousep==1 and not_sel_fr) or sel_card.tgttyp==0) then
    local tgttyp=sel_card.tgttyp
    if tgttyp==0 then
     --poker token
     if (sel_card.n==2) poker=#turn_card
     --graveyard
     --if (sel_card.n==5) tomb1,sel_card.used=1,20
     sel_card.h,sel_card=3
    else
	    sel_card.isline,sel_card.tgt,tgt_ok=0,in_area(hchars,hareax1,hareay1,hareax2,hareay2)
	    if typ_ch_area[tgttyp]>0 or tgttyp==8 or tgttyp==9 then
	     sel_card.isline,sel_card.tgt=sel_card.tgttyp,hareay1
	     if (tgttyp==8) sel_card.tgt=hareax1
	    end
	    if sel_card.tgt then
	    	sel_card.h=3
	     add(turn_card,sel_card)
	     if (poker and sel_card.k<6) poker+=1
	     if ((sel_card.k~=5 or sel_card.n~=8) and sel_card.k~=6) then
		     if not allowk then
		      allowk,allown=sel_card.k,sel_card.n
		     elseif allown~=sel_card.n then
		      allown=0
		     elseif allowk~=sel_card.k then
		      allowk=0
		     end
	     end
	     hlight,sel_card=nil
	    end
	   end
   end
   --play turn
   if mouse_area(to_tab_unp(",107,105,124,115,")) or skipturn then
    hplay=1
    if mousep==1 and turn==0 or skipturn then
     turn,sel_card,skipturn=1
     for crd in all(handanditem) do
     	if crd.h==2 then
     	 crd.h=0
     	elseif crd.h==3 then
     	 crd.used=1
     	end
     end
    end
   end
   --cancel turn
   if mouse_area(to_tab_unp(",107,117,124,125,")) then
    hcanc=1
    if mousep==1 and turn==0 then
				 if reshuffle>0 and #turn_card==0 then
				 	for crd in all(hand) do
				 		add(deck,crd) del(hand,crd)
				 		shuffle_deck()
				 	end
				 	reshuffle-=1
				 	deal_hand()
				 end
     turn_card,sel_card,allowk,allown,poker={}
     for crd in all(handanditem) do
     	crd.h=0
     end
    end
   end
  else --turn>0
   --battle
   --select spell acting char
   if #turn_card>0 then
    for crd in all(turn_card) do
     if not curr_ch then
      curr_ch,curr_opp,opp_isline,opp_ln_algn,curr_k,curr_n,card_turn,walk=crd.char,crd.tgt,crd.isline,c_typ_to_algn[crd.tgttyp],crd.k,crd.n,true,0
      del(turn_card,crd)
      break
     end
    end
   --select normal att char
   else
    for ch in all(char) do
     if not curr_ch then
      if ch.act<=count_eff(ch,6) and count_eff(ch,16)==0 and count_eff(ch,17)==0 and ch.algn==turn and (ch.hp>0 or count_eff(ch,31)>0) and ch.typ~=13 and ch.typ~=37 or (devoured and ch.typ==8 and countchars[2]==1) then 
       curr_ch,curr_opp=ch
      end
      opp_isline,card_turn=0,false
     end
    end
   end
   --curr_char attack
   if curr_ch then
    --search closest opponents
    if not curr_opp and not card_turn then
	    local conf_att=(count_eff(curr_ch,19)>rnd(2))
	    buff_ally=1
	    if count_eff(curr_ch,7)>rnd(2) then
	     buff_ally=-1
	    end
     function closest_enm(ch_t,y)
      local dist,oppn=99,{}
      for opp in all(ch_t) do
       if curr_ch~=opp and ((opp.algn~=turn and not conf_att) or (conf_att and opp.algn==turn)) and (count_eff(opp,11)==0) and opp.hp>0 then
        local diff=abs(opp.tx-curr_ch.tx)*(1-count_eff(curr_ch,32))+abs(opp.ty-curr_ch.ty)*y
        if diff<=dist then
         if diff~=dist then
          oppn={}
         end
         add(oppn,opp)
         dist=diff
        end
       	if (count_eff(opp,4)>0) oppn[1],oppn[2]=opp,opp break
       end
      end
      return oppn
     end
     if (buff_ally==-1) then
      for buff_tgt in all(char) do
       if ((buff_tgt.algn==curr_ch.algn)~=conf_att and (not curr_opp or buff_tgt.hp/buff_tgt.hpmx<=curr_opp.hp/curr_opp.hpmx)) curr_opp=buff_tgt
      end
     else
	     oppn=closest_enm(char,1)
	     oppn=closest_enm(oppn,0)
	     curr_opp,opp2=oppn[1],oppn[2]
	     if(opp2 and(opp2.tx<curr_opp.tx or(opp2.tx==curr_opp.tx and rnd()<.5)))curr_opp=opp2
     end
     --if (conf_att and curr_opp.algn~=curr_ch.algn) curr_opp=nil
     --[[opp2,]]curr_opp,walk=--[[curr_opp,]]{curr_opp},0
    else
     --attack
     if #ptc==0 then
      --where to walk, set line targets
      if walk==0 then
      	oppx,oppy,spec,typ,multi=to_tab_unp(",,,,,1,")
       if (curr_k) spec,typ=curr_k*13-13+curr_n,card_sub[curr_k][curr_n]
       if (spec==40 or spec==50) multi=4
       if (spec==38) multi=9
       if (spec==0) multi+=count_eff(curr_ch,27)
       curr_ch.willflip=false
       if opp_isline==9 then
        oppx,oppy,lny,topp,bott=4,curr_opp,curr_opp,0,8
        if spec~=48 and spec~=51 then
        	topp,bott=lny-1,lny+1
        end
        curr_opp=in_area(opp_ln_algn,0,topp,8,bott)
       elseif opp_isline==8 then
        oppx,oppy,curr_opp=curr_opp-2,4,in_area(opp_ln_algn,curr_opp,0,curr_opp,8)
       else
        if (opp_isline>0) curr_opp=in_area(opp_ln_algn,to_tab_unp(",,,8,8,"))
        curr_ch.willflip=true
        for opp in all(curr_opp) do
         if opp.hp<=0 and not opp.und and opp.typ>8 or opp==devoured then
          del(curr_opp,opp)
         else
	         oppx+=opp.tx-(opp.algn*4)+6
	         oppy+=opp.ty
	         if (opp.algn~=curr_ch.algn or curr_ch.typ==34) curr_ch.willflip=false
         end
        end
        if curr_opp then
	        if (#curr_opp==1 and curr_opp[1]==curr_ch)curr_ch.willflip=false
	        oppx,oppy=oppx/#curr_opp,oppy/#curr_opp
	        if #curr_opp==0 then
	         --forced spit
	         if devoured and countchars[2]==1 and curr_ch.typ==8 then
	          local tries=0
	          while (not curr_opp or #curr_opp==0) and tries<100 do
	           tries+=1
	           curr_opp=in_area(0,mid(0,8,curr_ch.tx+irnd(4)+1),mid(0,8,curr_ch.ty+irnd(3)-1))
	          end
	          if curr_opp then
		          curr_k,curr_n,spec,typ,curr_ch.willflip=to_tab_unp(",6,7,72,56,f,")
		          del(chs_item,chs_item[1])
		         else
		          curr_opp={}
		         end
	         end
	         oppx,oppy=curr_ch.tx,curr_ch.ty
	         --end
	        end
	       else
	        oppx,oppy,curr_opp=4,4,{}
        end
        --if (#curr_opp==1 and (curr_opp[1].hp<=0 and not curr_opp[1].und) or curr_opp[1]==devoured) curr_opp[1]=nil
       end
       --if (#curr_opp==0) curr_ch.willflip=false
       if (curr_ch.typ==34) oppx,oppy=curr_ch.tx-1,curr_ch.ty
       curr_ch.tgtx,curr_ch.tgty,curr_ch.tgt,curr_ch.srching=oppx,oppy,curr_opp
      end
      --walk in
      walk+=1
      --???
      --if (not curr_opp) in_area(4,oppx+2,oppy,oppx+2,oppy)
      if walk==1 and type(curr_opp)=="table" and #curr_opp==0 then
       curr_ch.srching=true
      end
      if (walk%5==0 and curr_ch.srching) new_fl_text(curr_ch.x+irnd(10),curr_ch.y,"?") curr_ch.flp=not curr_ch.flp
      if walk<=5 then
       curr_ch.mperc+=.2
      elseif walk<=20 then
       if (not curr_ch.srching) curr_ch.flp=curr_ch.willflip
       --charge k
       if walk==14 then
        if curr_k and not curr_ch.srching then
         curr_ch.sprt=1
        	new_ptc(curr_ch,typ,curr_ch,spec)
        end
       --attack
       elseif walk==16 then
        curr_ch.sprt=0
	       --opp is line; wind effect
	       if opp_isline==9 then
	        --wind move
	        local moved=true
	        while moved do
	         moved=false
	        	for opp in all(curr_opp) do
	         	if not opp.moved then
	          	local diff=mid(opp.ty-lny,1,-1)
            function moveopp(v)
             opp.moved=push_char(opp,0,diff*v)
             moved=opp.moved or moved
            end
            if spec==48 then
             moveopp(-1)
            elseif spec==51 then
             moveopp(1)
            end
	          end
	         end
	        end
	        for opp in all(curr_opp) do
	         opp.moved=nil
	        end
	       --elseif opp_isline==8 then
	        --curr_opp=in_area(opp_ln_algn,curr_opp,0,curr_opp,8)
	       end
        --multi or normal att
        if multi>0 then
         if (spec==58) curr_opp={curr_opp[irnd(#curr_opp)+1]}
         for opp in all(curr_opp) do
          if opp.hp<=0 and not opp.und and opp.typ>8 then
           del(curr_opp,opp)
          else
	          local last_ptc=new_ptc(curr_ch,0,opp,spec)
	          --quake
	          if (spec==38 and 9-multi>opp.quake and multi<9) last_ptc.dmg=0
	          if (opp==curr_ch and last_ptc.sprt>0) last_ptc.mperc=1
	          --spread dmg
	          if (spec==37) last_ptc.dmg=-flr(-last_ptc.dmg/#curr_opp)
          end
          if (spec==52) add(opp.eff,new_eff(26,-5,1))
         end
         multi-=1
         walk-=1
         --self dmg
         if (spec==12) dmg_char(curr_ch,6,spec)
        end
        opp_isline=0
       end
      elseif walk<26 then
       curr_ch.flp=false
       curr_ch.mperc-=.2
      else
       if (not card_turn) curr_ch.act+=1
       curr_ch.tgtx,curr_ch.tgty,curr_ch,curr_k,curr_n=curr_ch.tx,curr_ch.ty
      end
     end
    end
   else
   --if no char to act, change
    --turn and clear acts
   	for ch in all(char) do
     if (ch.algn==turn) ch.act=0
    end
    turn,allowk,allown,poker=(turn+1)%3
    if turn==0 then
    	for ch in all(char) do
					 for ef in all(ch.eff) do
					  if (ef.typ==18) ef.dur=min(ef.dur,3)
					  ef.dur-=1
					  if ef.dur<=0 then
					   del(ch.eff,ef)
					  end
					 end
					 if (ch.hp>0) dmg_char(ch,count_eff(ch,21),0,5)
    	end
    end
   end
  end
 end

 --del from hand
 for crd in all(handanditem) do
  if crd.used then
   crd.used+=1
   if crd.used>=20 then
    del(hand,crd)
    del(chs_item,crd)
    del(char_item[8],crd.item)
   end
	 end
	end

	foreach(char,move)
	--particles
	for p in all(ptc) do
	 local tgt,sprt,peff=p.tgt,p.sprt,p.eff
 	local tgttx,tgtty=tgt.tx,tgt.ty
 	p.mperc+=.05*p.spd
 	move(p)
 	if (p.typ==0 and p.spec==9) p.y=p.ch.y
 	--p.spwndt+=1
-- 	if (sprt==244) local lastv=new_vfx(1,p.x,p.y,8) lastv.ys=1
-- 	if (sprt==173 or sprt==302) new_vfx(1,p.x,p.y,12)
--  if (sprt==500) new_vfx(1,p.x,p.y,11)
  if (p.spwn>0) new_vfx(1,p.x,p.y,p.spwn)
  if (sprt<=234 and sprt>=227) loopspr,p.loop=p,1
 	if p.mperc>1 then
 	 count_eff(tgt,26,true)
 	 if peff then
 	  local pefftyp=peff.typ
 	 	--apply buff
 	 	function apply_buff(tgt)
	 	 	if count_eff(tgt,12)<99 then
	 	   if (pefftyp==25) push_char(tgt,-1,0)
				  add(tgt.eff,peff)
				  if (pefftyp==17) sfx(55)
				 end
			 end
			 apply_buff(tgt)
			 --aoe
		  if pefftyp==3 or p.spec==56 or tgt.typ==37 then
		   local tgts,div=in_area(tgt.algn,tgttx-1,tgtty-1,tgttx+1,tgtty+1),tgt.typ==37 and 1 or 2
     for t in all(tgts) do
		    if p.spec==38 then
		     if (p.multi==9) tgt.quake+=1
		    else
		     local dmgg=p.spec==59 and -t.hp or -p.dmg
		     if (t~=tgt) apply_buff(t) dmg_char(t,-flr(dmgg/div),p.spec,peff,p.ch)
		   	end
		   end
		  end
		  --summon
		  if pefftyp==14 then
		   local algnn=p.ch.algn
		   if (peff.val==37) algnn=algnn%2+1
		   local i1,i2=0,0
		   if (peff.val==15) i1,i2=-1,1
		   for i=i1,i2 do
		    local last_ch=cr_char(mid(0,8,tgttx-abs(i)),mid(0,8,tgtty+i),peff.val,algnn)
		    if (last_ch and peff.val==15) last_ch.clr=i+2 last_ch.hp-=i*10+20 last_ch.hpmx=last_ch.hp last_ch.desc="ludo ranger - pierce"
		   end
		  --amulet
		  elseif pefftyp==28 and tile_free(tgttx,tgtty) then
	    add(summ_tilex,tgttx)
	    add(summ_tiley,tgtty)
     deck,hand,pre_battle={},{},true
     foreach(char,add_char_cards)
		  --devour
		  elseif pefftyp==29 then
		   devoured,devour_time=tgt,2
		   del(char,tgt)
		  --spit out
		  elseif pefftyp==30 then
			  if tile_free(tgttx,tgtty) then
			   add(char,devoured)
		    devoured.tx,devoured.ty=tgttx,tgtty
			   move(devoured)
			   devoured=nil
		   end
		   multi=0
		  elseif pefftyp==33 then
		   skipturn=true
		  end
   end
	  --dmg
	  if (tgt.ischar) dmg_char(tgt,p.dmg,p.spec,peff,p.ch)
   if p.typ==0 and p.ch~=tgt then
    local ang=rnd()
	   for i=1,12 do
	    local rang=rnd(2)
	    ang,last_vfx=sprt==245 and ang+.5*irnd(2) or rnd(),new_vfx(3,p.x,p.y,p.vfxc)
	    last_vfx.xs,last_vfx.ys,last_vfx.brg,last_vfx.dur,last_vfx.dt=sin(ang)*rang,cos(ang)*rang,2,9,2
	    if (sprt==244) last_vfx.typ=1
	   end
   end
   --del
  	del(ptc,p)
  end
	end
 --if all from 1 side are dead
 if not pre_battle then
 	--loss
 	if countchars[1]==0 then
 	 --if (end_count==20) music(33)
 	 end_count+=1
 	--victory
 	elseif countchars[2]==0 then
 	 if end_count==20 then
 	  --music(32)
 	  for ch in all(char) do
 	  	if ch.typ<=8 then
  	  	ch.sprt=1
  	  	glob_hp[ch.typ]=ch.hp
  	  end
   	end
 	  for i=1,8 do
  	  glob_hp[i]=min(glob_hp[i]+5,chhp[i])
  	 end
 	 end
 	 end_count+=1
  end
 end
	if end_count>80 then
 	--fade_out(ending or 0)
	 --[[
		if ending then
		 poke(0x5ec9,3)
		 poke(0x5eca,peek(0x5eca)+1)
		 music(-1,3000)
		 for i=0,35 do flip() end
		 load("jostitle.p8")
	 end
	 ]]
 	if (char_item[8][1]==36) char_item[8]={}
 	if (#char_item[8]<3) add(char_item[8],irnd(5)+31)
 	_init()
 end
 --correct draw order
 if (char) char=sort_chars()
 end
end

Tab 4

--update functions
function count_eff(ent,eff,delete)
 local count=0
 for ef in all(ent.eff) do
  if ef.typ==eff then
   count+=ef.val
   if (delete) del(ent.eff,ef)
  end
 end
 return count
end

function in_area(algn,x1,y1,x2,y2)
 local tgt={}
 y2=y2 or y1
  if algn==4 or (algn==0 and tile_free(x1,y1)) then
   e={}
   e.tx,e.ty,e.algn,e.hp=x1,y1,2,1
   add(tgt,e)
  else
   for ch in all(char) do
    if x1 and (algn==3 or algn==ch.algn) and ch.tx>=x1 and ch.ty>=y1 and ch.tx<=x2 and ch.ty<=y2 then
     add(tgt,ch)
    end
   end
  end
 if (#tgt>0) return tgt
end

function move(e)
 if(e.charge)e.tgtx,e.tgty=e.tx,e.ty-.5
 local tgtx,tgty,mperc=e.tgtx,e.tgty,e.mperc
 if mperc==0 and e.pushed then
  e.pushed-=.3
  mperc,tgtx,tgty=e.pushed,e.wx,e.wy
  if (e.pushed<=.3) e.pushed=nil
 end
 e.x,e.y=(tgtx*mperc+e.tx*(1-mperc))*16-7,(tgty*mperc+e.ty*(1-mperc))*10-5
end

function push_char(ch,xs,ys)
 if count_eff(ch,12)<99 then
	 local moved=false
	 if (tile_free(ch.tx+xs,ch.ty+ys)) ch.pushed,ch.wx,ch.wy,moved=1,ch.tx,ch.ty,true ch.tx+=xs ch.ty+=ys
	 if (max(ch.tx,ch.ty)>8 or min(ch.tx,ch.ty)<0) del(char,ch)
	 move(ch)
	 return moved
 end
end

function dmg_char(ch,v,spec,eff,srcch,ref)
 if v then
  --push
  local isalive,barrier,supbarr,ultbarr,efftyp=ch.hp>0,count_eff(ch,9),count_eff(ch,13),count_eff(ch,34),0
  if (eff) efftyp=eff==5 and 5 or eff.typ
  if v<0 or max(supbarr,max(barrier,ultbarr))==0 then
   --if v~=0 then
		  --stone form
		  if (count_eff(ch,18)>0 and v>1 and efftyp~=5) v=1
    --armor
    local armor=count_eff(ch,2)
    --magic armor
    if (spec>0) armor+=count_eff(ch,12)
    --pierce/reflect
    if (efftyp==5 or ref) armor=0
    if v>0 then
     v=max(0,v-armor)
     --def/2
     if (count_eff(ch,8)>0 and efftyp~=5) v=flr(v/count_eff(ch,8))
    end
    --reflect
    if (count_eff(ch,15)>0 and not ref and srcch and v>0) dmg_char(srcch,v,0,nil,ch,true)
   --end
   --flood effect
   if (efftyp==10 and ch.hp+count_eff(ch,12)<=eff.val and isalive) ch.hp,vfxx=0,new_vfx(9,ch.x+2,ch.y) vfxx.ys=1
 	 --apply dmg
 	 ch.hp=mid(0,ch.hp-v,ch.hpmx)
 	 --lifesteal
 	 if (efftyp==23) dmg_char(srcch,-v,0)
 	 --stop sleep
 	 if (v>0) count_eff(ch,16,true)
 	 --destroy card
 	 if (ch.typ<=8 and #hand>0 and efftyp==22) hand[1].used=20
 	else
 	 if ultbarr>0 then
 	  mod_eff(ch,34,-min(1,v))
 	 elseif supbarr>0 then
 	  if (v>=supbarr) mod_eff(ch,13,-v)
 	 else
 	 	mod_eff(ch,9,-v)
 	 end
 	end
 	if (v>0 and isalive or v<0) new_fl_text(mid(1,ch.x+7-#tostr(v)*2,124-flr(min(v/10,1))*4),max(8,ch.y+5),v)
 	if ch.hp<=0 and ch.typ>8 and not ch.und then
  	del(char,ch)
 	end
  if (spec==29) push_char(ch,1,0)
--  if (spec==42) push_char(ch,-1,0)
	 if (spec==44) ch.eff={}
	end
end

function mod_eff(ch,typ,val)
 for e in all(ch.eff) do
  if e.typ==typ then
   e.val+=val
   if (e.val<0) del(ch.eff,e)
   break
  end
 end
end

function mouse_area(x1,y1,x2,y2)
	if mousex>=x1 and mousey>=y1 and mousex<=x2 and mousey<=y2 then
  return true
 end
 return false
end

function tile_free(x,y)
 for ch in all(char) do
  if (ch.tx==x and ch.ty==y) return nil
 end
 return true
end

function irnd(n)
 return flr(rnd(n))
end

function shuffle_deck()
 for i=#deck,1,-1 do
  local j=irnd(i)+1
  deck[i],deck[j]=deck[j],deck[i]
 end
end

function sort_chars()
 new_t={}
 for j=#char,1,-1 do
  v,k=999
  for i=#char,1,-1 do
   local vv=char[i].y
  	if (vv<=v) k,v=char[i],vv
  end
  add(new_t,k) del(char,k)
 end
 return new_t
end

function reset_crd_pos()
 for n,crd in pairs(hand) do
  crd.x,crd.y=n*(7-jk17)+26,114
 end
end

function bool_to_num(bool)
 if (bool) return 1
 return 0
end

function transf_tab(rec,tab)
 foreach(tab,function(a)add(rec,a)end)
end

function add_char_cards(ch)
 local t=ch.typ
 if t<=4 then
  for i=1,13 do
   add_card(t,i,deck,ch)
  end
 end
 if t==7 then
  for i=1,13 do
   add_card(5,i,deck,ch)
  end
 end
end

Tab 5

--draw
function _draw()
	cls(7)
	if shk then
  cam_x,cam_y,shk=2-rnd(4),2-rnd(4)	
	else--if g_time>45 or t_loop==1 then
	 cam_x,cam_y=0,0
	--pan camera
-- else
--  g60,g90=g_time/60,g_time*2-90
--  cam_x,cam_y=cos(g60)*(g90)/1.5,-sin(g60)*(g90)/10
--  cam()
--	 draw_chain(",6,16,10,14,16,-88,-33,6,|,3,-61,27,151,76,1,|,6,16,10,14,5,-88,17,12,|,2,-62,28,152,75,7,|")
	end
 cam(0,0)

	--floor
	draw_chain(",6,16,10,9,4,-24,87,6,|,6,16,10,9,1,-24,-13,6,|,3,-8,9,142,102,1,|,3,-8,4,135,93,7,|,3,-8,24,135,73,1,|,3,-8,4,135,23,6,|,6,16,10,9,2,-24,-6,7,|,6,16,10,9,2,-24,64,6,|,6,16,10,9,5,-24,14,12,|,2,-9,25,136,72,7,|,3,-9,94,136,101,6,|,3,-9,99,136,101,1,|,2,-9,94,136,101,1,|,2,-9,3,136,94,1,|")
 pal()
 --draw_chain("11,|")
 if loopspr then
  if (loopspr.sprt==231 or loopspr.sprt==229) loopspr.thunder=1 cls()
  loopdraw()
 end

	--play/cancel button
	outline(xspr,1+hplay*8,to_tab_unp(",,31,108,106,"))
	local resh=(reshuffle>0 and #turn_card==0)
	outline(xspr,1+hcanc*8,0,32+bool_to_num(resh),108,118)

	hlight_chars(hchars)
 if (hareax1 and not hover) hlight_area(hareax1,hareay1,hareax2,hareay2)

	--pre-battle
 if pre_battle then
 	for i=1,#summ_tilex do
 	 hlight_area(summ_tilex[i],summ_tiley[i])
 	end
	end

	--char
	for ch in all(char) do
	 draw_char(ch.typ,ch.x,ch.y,(ch.algn==2) ~= ch.flp,ch.hp,ch.hpmx,ch,ch.sprt)
	end

	draw_vfx()

	--particles
	for p in all(ptc) do
		local sprt=p.sprt
		if (sprt>228 and sprt<236) shk=1
	 if not p.loop then
		 --if not p.invis then
		 local lance_charge=sprt>=263 and sprt<=302
		 local ww,hh,offx=(sprt==252 or lance_charge) and 2 or 1,(sprt==173 or lance_charge) and 2 or 1,sprt==173 and 4 or 0
		 if p.clr==0 then
		  if (sprt~=250 or t2==0) spr(sprt,p.x-ww*4+offx,p.y-hh*4,ww,hh,p.sprtflip)
		 else
		  --tspr(sprt,p.x-ww*4,p.y-hh*4,ww,hh,p.clr,t4,p.bit)
		 	stspr(sprt%16*8,flr(sprt/16)*8,ww*8,hh*8,p.x-ww*4,p.y-hh*4-(lance_charge and 2 or 0),0,0,p.clr,t4,p.bit)
		 end
		 --end
		 if p.typ==0 and p.spec==9 then
		  local y2=max(0,flr(p.mperc*64-16))
		  local y3=min(flr(p.mperc*64+16),64-y2*2)
			 stspr(0,128+y2,56,y2+y3,p.x-32+p.mperc*5,p.y-16+y2,to_tab_unp(",0,0,0,99,0,f,"))
			 break
		 end
	 end
	end

 --cards
	for crd in all(hand) do
		local x,y,k,n,h=crd.x,crd.y,crd.k,crd.n,crd.h
	 if not crd.used or crd.used%2<1 then
	  if (h>0) y=87
	  y-=(crd.used or 0)/4
	  if (h==2 and t4<2) h=1
	  outline(rectfill,hcol[h+1],0,x,y,x+24,y+33,k==5 and 5 or 7)
	  pal(8,kcol[k])

	  --pal()
	  --kind
	  local c,s,l=7,card_sub[k][n],0
	  if s>36 then
	   l=5
	   s+=86
	   c=g_time%20<3 and 6 or 0
	  else
		  --text
		  local function txt(f,t)
		   xspr(n,x+2+f*18-(n==10 and 1 or 0),y+1+f*27,t,t)
		  end
		  --if (k<5)
		  txt(0,false)txt(1,true)

		  if s>4 and ((g_time%20<3) or y<90) then
		   c=kcol[k]
		   s+=13
		  else
		   s=(s-1)%4+14
		  end
	  end
	  outline(xspr,c,0,s,x+1,y+8-l)
	  outline(xspr,c,0,s,x+19,y+21+l,5,5,false,true)

	  --small kind
	  if k<5 then
		  function d_kn(n)
		   xspr(25+k,x+kposx[n],y+kposy[n],false,kflip[n])
		  end

		  for i in all(kpos[n]) do
		   d_kn(i)
		  end
	  end
 	end
	end

	--chester items
 for k=1,#chs_item do
  outline(sspr,chs_item[k].h*2,0,15+(chs_item[k].n)*5,96,5,5,96+k*8,98)
 end

	--floating text
	for t in all(txt) do
	 t.y-=.5
	 t.tim+=1
	 if (t.tim>18) del(txt,t)

	 local ttxt,tcol=t.txt,4
	 if type(ttxt)=="number" then
	  tcol=9
	  if (ttxt<0) ttxt,tcol="♥"..abs(ttxt),14
	 end
	 print(ttxt,t.x,t.y,tcol+t2)
	end

	--deck
	local col,maxx=13,flr((#deck+9)/10)
	for i=1,maxx do
	 if (i==maxx) col=7--84
	 local y=i*2
	 outline(rectfill,1,0,3,94-y,27,127-y,col)
	 fillp(0x5852) 
	 outline(rectfill,8,0,6,97-y,24,124-y,232)
	 fillp()
	end

	--pre-battle
 if pre_battle then
  draw_chain(",3,2,81,125,114,2,|,4,0x33cc,|,3,4,82,124,113,239,|,4,|,2,3,82,124,113,9,|")
  if chx<=8 and chx>0 and (chy==6 or chy==7) and mousey<=112 then
  	local ch=b_party[chx]
  	if ch then
  	 rect(chx*15-12,chy*16-6,chx*15+4,min(chy*16+10,112),9+t22)
  		local txt=chdesc[ch].."\nlvl:13  hp:"..glob_hp[ch].."/"..chhp[ch].."  att:"..item_att[ch]
				if chy>6 then
				 local itemnum=min(char_item[chx][char_curr_item[chx]],31)
				 if (itemnum>6 and itemnum~=27) txt=item_desc[itemnum]
				end
  		aux_text(txt)
  	end
  end
  for i=8,1,-1 do
   if (b_party[i]) draw_char(i,i*15-11,90) --monoc=0
  	--outline(xspr,0,0,93+char_item[party[i]][char_curr_item[party[i]]],i*15-7,107)
	  rect(i*15-10,85,i*15+1,86,2)
	  rect(i*15-10,85,i*15-10+11*glob_hp[i]/chhp[i],85,8)
  	if i<8 then
	   local itm=char_item[i][char_curr_item[i]]-9
--	  	local sx,sy=56+(itm%8)*5,144+flr(itm/8)*5
	  	if (itm<0) itm=18
--	  	outline(stspr,0,0,sx,sy,5,5,i*15-7,107,1,1,1,99)
	  	outline(xtspr,0,0,itm+99,i*15-6,107,1,99)
	  	--outline(spr,0,0,195,i*15-7,107)
   else
    --chester
    for k=1,#char_item[8] do
     outline(sspr,0,0,20+((char_item[8][k]-31)%8)*5,96,5,5,102+k*6,107)
    end
   end
  end
  --print("character select",33,80,9+t22)
 end

	--card descr
	if hlaux --and hlight
	then
	 local ctxt=card_txt[hlaux.k][hlaux.n]
		if (sub(ctxt,1,4)=="soul") ctxt=ctxt.." (".. hlaux.char.hpmx-hlaux.char.hp ..")"
		aux_text(ctxt)
	--char desc
	elseif start_batt and turn==0 then
 	for ch in all(char) do
 	 if tilex==ch.tx and tiley==ch.ty then
 	 	for chh in all(char) do
 	 		if (chh.hp>0) print(chh.hp,chh.x+7-#tostr(chh.hp)*2,chh.hph-6,9+t2)
 	 	end 
 	  aux_text(ch.desc.."\nhp:"..ch.hp.."/"..ch.hpmx.."  att:"..ch.att.."  armor:"..count_eff(ch,2))
 	 end
 	end
	end

	--play/canc desc
	--[[
	if (hplay==1) aux_text("play: start attack phase",24)
	if hcanc==1 then
	 if resh then
	 	aux_text("reshuffle hand: \n"..reshuffle.." reshuffles left",24)
	 else
	 	aux_text("cancel: undo all selected\n cards",24)
	 end
	end]]

	--mouse cursor
	outline(xspr,0,1,30,mousex+1,mousey+1)
	--if (fade_in>0) rectfill(fade_in*13,to_tab_unp(",,127,127,,"))

 if (end_count>70) cls()

-- ?level,0,0,0
-- ?ltries,0,6,0
end

Tab 6

--draw functions
function draw_chain(c)
 local t=str_to_table(c)
 for i=1,#t do
 	draw_funct[t[i][1]](unpack(t[i],2))
 end
end

--[[
function draw_fade_out()
 for i=0,11 do
  flip()
  rectfill(0,0,i*13,127,0)
 end
 fade_in=1
end]]

function aux_text(txt)
 rectfill(0,115,128,128,1)
 print(txt,2,116,13)
end

function tpx(x,y,h,v)
 pset(x,y,to_col[h+mid(0,v-1+c_val[band(pget(x,y),15)],5)*11])
end

--[[
function tspr(s,x,y,w,h,phue,pval,tr)
 local sx,sy=s%16*8,flr(s/16)*8
	stspr(sx,sy,w*8,h*8,x,y,0,0,phue,pval,tr)
end]]

function stspr(sx,sy,w,h,x,y,dw,dh,phue,pval,tr,fl)
 local func=tpx
	if (pval>=99) func=pset
 fl,tr,phue=fl or false,tr or 0,phue<12 and phue or irnd(11)+1

	for j=0,h-1 do
		for i=0,w-1 do
	  local pc=peek(flr((sx+i)/2)+(sy+j)*64)
	  pc=(sx+i)%2==1 and flr(pc/16) or pc%16
	  --local pc=sget(sx+i,sy+j)
	  if (tr<99 and pc!=tr) or (tr>=99 and band(pc,tr-100)>0) then
	   if (fl) i=-i+w-1
	   if (pval>=99) phue=pc
	   func(x+i,y+j,phue,pval)
	  end
	 end
	end
end

function xfunc(func,n,x,y,...)
 local n=sprv[n]
 func(n[1],n[2],n[3],n[4],x,y,n[3],n[4],...)
end

function xtspr(...)
 xfunc(stspr,...)
end

function xspr(...)
	xfunc(sspr,...)
end

function draw_char(typ,x,y,f,hp,hpmx,ch,sprt) 
	function count_eff_ch(eff)
	 return count_eff(ch,eff)
	end
 function count_eff_ch0(eff)
 	return count_eff_ch(eff)~=0
 end

	local sprt=sprt or 0

	--barriers
	if ch then
	 local xx,yy=x+6,y+7
 	if (count_eff_ch0(34)) circfill(xx,yy,11,to_col[(min(count_eff_ch(34),5)+t2)*11-8])
 	if (count_eff_ch0(9)) circfill(xx,yy,10,14+t22)
 	local cc=13
 	if (count_eff_ch(12)>0) cc=8
 	if count_eff_ch0(13) or cc==8 then
 	 circ(xx,yy,12,cc+t22)
 	end
	end

 outl,colr,fspr,hh,tombspr=csprb[typ],0,typ+52

	--alt sprite
	if ch  then
	 --dead
	 --tombspr=nil
	 if hp==0 and ch.mperc==0 and ch.sprt==0 then
	  if ch.typ<=8 then
	   sprt=2
	  else
	  	fspr,tombspr=90,1
	  end
	 end
  --sleeping sprite
  if (count_eff_ch0(16)) fspr=typ==10 and 84 or typ==24 and 85 or fspr
 end
 fspr-=sprt*8
 local sprn=sprv[fspr]
 hh=sprn[4]
 local hph=y+8-(hh/1.2)

	if (hp and ch.hp>0) rect(x+1,hph,x+12,hph+1,2)
 local chxx,chyy=x-(sprn[3]/2-7-(sprn[5] or 0)*(f and -1 or 1)),y-(hh-15)+(sprn[6] or 0)

 function schar()
  function paltt()
	 	palt(0,false)
	 	palt(tombspr or chtr[typ],true)
 	end
 	paltt()
		local useoutl,chyyy=csprb[typ]
	 if (useoutl) useoutl=tombspr or outl
	 if ch and ch.typ==34 and ch.hp>0 then
	  local wave=count_eff_ch0(17) and 0 or g_time
   chyyy=sin(wave/50)*1.25+2
   outline(xspr,useoutl,0,122,chxx,chyy+22+sin((wave-4)/50)+2,f)
  	paltt()
   outline(xspr,useoutl,0,121,chxx,chyy+18+sin((wave-8)/50)*1.1+2,f)
  	paltt()
	 end
  outline(xspr,useoutl,0,fspr,chxx,chyy+(chyyy or 0),f)
 end

 --char select
	if not ch then
 	schar()
 end

 if ch then
  --if (loopspr and loopspr.sprt==231 and loopspr.tgt==ch)
  if (loopspr and loopspr.thunder and loopspr.tgt==ch) loopdraw()
	 ch.hph=hph
  if ch.hp>0 or ch.typ<=8 then
	  function t_ball_part(e,c,v,yy)
		  local pmax=mid(-5,count_eff_ch(e),5)
		  local spmx=sgn(pmax)
		  for i=spmx,pmax,spmx do
		 	 last_vptc=new_vfx(2+t4,x+rnd(14),hph+rnd(16-yy*8)+10*yy-3+spmx*6)
		 		last_vptc.ys,last_vptc.clr,last_vptc.brg,last_vptc.ch=(spmx+pmax/10)*yy,c-spmx,v,ch
		 		--if (e==26) last_vptc.y-=5 last_vptc.xs=.5
		 	end
	 	end
	 	t_ball_part(to_tab_unp(",1,2,2,1,"))
	 	t_ball_part(to_tab_unp(",21,5,,,"))
	 	t_ball_part(to_tab_unp(",26,9,3,1,"))
	 	if (count_eff_ch0(6)) xtspr(fspr,chxx+irnd(5)-2,chyy+irnd(5)-2,2,2,chtr[typ],f)

	  --pal()
	 	if (count_eff_ch0(18)) ch_pal,outl=8,1
	 	if (count_eff_ch0(17)) ch_pal,outl=10,1
	 	if count_eff_ch0(20) then
	 	 local c=sgn(count_eff_ch(20))+9
	 	 if (g_time%(5-count_eff_ch(20))==0) c+=1
	 	 outl=armorc[c]
	 	end
	 	if (count_eff_ch0(19)) spr(236,x+3,hph-9,1,1,g_time%8<4,(g_time+2)%8<4)
	 	if count_eff_ch(11)==0 or t4<2 then
	 	 if (g_time%6<count_eff_ch(8)) monoc=7
	 	 if (g_time%5<count_eff_ch(27)) monoc=0
	 	 pal_pwn=ch.clr
	 	 schar()
	 	 pal_pwn=nil
	 	 if (count_eff_ch0(2)) monoc=armorc[mid(1,count_eff_ch(2)+4,7)] clip(0,y+g_time*-sgn(count_eff_ch(2))*4%160-74,128,6) schar() clip()
	 	end

	  --pal()
	 	if (count_eff_ch0(4)) spr(239,x+sin(g_time/60)*4+4,y+cos(g_time/44)*4+6)
			if (count_eff_ch(12)<0 and g_time%16<8) spr(255,x+3,hph-8)
			if (count_eff_ch0(15) and t4<2) spr(237,x+irnd(17)-4,y+irnd(17)-4,1,1,rnd()>.5,rnd()>.5)

		 if (hp and ch.hp>0) rect(x+1,hph,x+1+11*hp/hpmx,hph,8)

			if (count_eff_ch0(16)) print("z",x+sin(g_time/20)*3+7,hph-g_time/5%8,0)
		else
			schar()
		end
		draw_vfx(ch)
	end
	outl,monoc,ch_pal=0
	--pal()
end

function outline(draw,c,t,...)
 if c then
  --t:0 normal t:1 bold
  pal_all(c or outl)
  for i=-1,1 do
   for j=-1,1 do
    if ((i==0 or j==0) and i~=j) or t==1 then
     cam(i,j)
     draw(...)
    end
   end
  end
 end
 cam(0,0)
--	for i=0,15 do
--		pal(i,pal_pwn and pawn_clr[pal_pwn][i] or i)
--	end
 --if ch_pal then
 for i=0,15 do
	 pal(i,pal_pwn and pawn_clr[pal_pwn][i] or i)
  if (ch_pal) pal(i,to_col[ch_pal+c_val[i]*11])
 end
 pal(0,outl)
 --end
 if (monoc) pal_all(monoc)
 draw(...)
 pal()
end

function pal_all(p)
 for i=0,15 do
  pal(i,p)
 end
end

function hlight_area(x1,y1,x2,y2,cc)
 local col=cc or 9+t22
 x2,y2=x2 or x1,y2 or y1
 rect(x1*16-8,y1*10+4,x2*16+7,y2*10+13,col)
end

function hlight_chars(algn)
 local cc=14+t22
	for ch in all (char) do
  if ch.algn==algn or algn==3 then
		 hlight_area(ch.tx,ch.ty,nil,nil,cc)
		end
 end
 if algn==4 then
  hlight_area(5,1,7,7,cc)
 end
end

--[[
function fade_out(added)
 for i=1,5 do
  local n=0
  for j=0,63 do
   for k=0,127 do
    function fd(j)
    	pset(j,k,fade_c[pget(j,k)+added])
    end
    fd(j+added*4)
    fd(127-j-added*4)
   end
   n+=1
   if (n%32==16) flip()
  end
 end
end]]

function loopdraw()
 --if loopspr and (not ch or loopspr.tgt==ch) then
  --if loopspr.sprt==231 and not ch then 
   --cls()
  --else
 rnd1,rnd2=rnd(3),rnd(3)
 local j=128
 if(loopspr.thunder)j=loopspr.tgt.y+4
 for i=-8,j,8 do
  local x,y=loopspr.tgtx*16-13+rnd1,i+rnd2
  if(loopspr.sprt==227)x,y=y,loopspr.ch.tgty*10-4+rnd2*6
  spr(loopspr.sprt,x,y,2,1)
 end
  --end
	--end
end

function draw_vfx(ch)
	for v in all(vfx) do
	 if v.ch==ch then
		 v.dt+=1
		 --fire
	  v.x-=v.xs
	  v.y-=v.ys
		 if v.typ==1 then
	 	 v.x+=rnd(1.5)-.75
	 	 v.y+=rnd(1.5)-.75
	  	if (v.clr==6) v.clr=8
	  	circfill(v.x,v.y,(12-v.dt)/2,v.clr)
	 	--att+ pixel
		 elseif v.typ==2 then
		  tpx(v.x,v.y,v.clr,2)
	 	--att+ ball
		 elseif v.typ==3 then
		  --tspr(238,v.x,v.y,1,1,v.clr,v.brg)
	 		stspr(1,16,2,2,v.x,v.y,0,0,v.clr,v.brg)
	 		if (v.dt>7) v.typ-=1
		 elseif v.typ==9 and t2==1 then
		  spr(13,v.x,v.y)
	 	end
	 	if (v.dt>v.dur) del(vfx,v)
 	end
	end
end


@dw817 the variables "to" and "from" have normal gray color. I tried changing the names, but got the same problem:


Post entire code please, BoneVolt, where error occurs, and I'll see if I can find what is causing it - and a remedy.


Not related pbly but you are setting i=j in the str_to_tqb function.
This is actually a no-op as the for loop will reset i (unlike say, c/c++ for loops)


To reproduce, suggest to create a simple cart that does this decoding in a loop.


@dw817 I posted the entire code above, separated by tabs so it's easier to know which lines are being cited in the error message.

@freds72 I didn't know that, thanks for the info! (yeah, I probably did that at some point in C++ and assumed it would be the same here)

I tried to reproduce it in a small cart yesterday, but it doesn't reproduce the error... It also only happens on that particular string.

I tried to reproduce again now by making a bare bones version of the game one with the same strings and it also doesn't repeat the error (I kept it running for 10 minutes... the error usually pops up in ~2 minutes in the original cart)

Here is the code with just the relevant stuff (probably not very useful since no error happens, but at least it's a good summary):

function str_to_table(str)
 local tab,sptab={},{}
 for i=1,#str do
  if sub(str,i,i)=="," then
   for j=i+1,#str do
    local strn=sub(str,j,j)
    if(strn=="|")add(sptab,tab)tab={}i+=1 break
    if strn=="," then
     local s=sub(str,i+1,j-1)
     if tonum(s) then
      s=tonum(s)
     elseif s=="" then
      s=0
     elseif s=="t" then
      s=true
     elseif s=="f" then
      s=false
     elseif s=="{" then
      s={}
     end
     add(tab,s)
     break
    end
   end
  end
 end
 if (#sptab>0) return sptab
 return tab
end

function unpack(list,from,to)
 from,to=from or 1,to or #list
 if from<=to then
  return list[from],unpack(list,from+1,to)
 end
end

function irnd(n)
 return flr(rnd(n))
end

function to_tab_unp(tab)
 return unpack(str_to_table(tab))
end

level=310

function _init()
b_party,char_curr_item,summ_tilex,summ_tiley,handanditem,en_typ,ptc,vfx,g_time,tomb2,hand_kind,end_count,wperc,turn_card,txt,summ_chars,turn,deck,hand,chs_item,char,vfx,t_loop,jk17,reshuffle,start_batt,curr_k,curr_n,allowk,allown,poker,skipturn,lastx,newx=str_to_table(",1,2,3,4,5,6,7,8,"),str_to_table(",1,1,1,1,1,1,1,1,"),str_to_table(",2,2,2,"),str_to_table(",2,4,6,"),to_tab_unp(",{,{,{,{,,f,{,,,{,{,,,{,{,{,{,{,,,,")

 difficulty,ltries=0,0
 while abs(level-difficulty)>25 do
  ltries+=1
  difficulty,char=0,{}
	 for i=1,4 do
	  en_typ[i]=irnd(19)+15
	 end
	 for i=1,9 do
	  while newx==lastx do
	   newx=irnd(3)
	  end
	  lastx,ttyp=newx,en_typ[irnd(4)+1]
	  cr_char(newx+5,i-1,ttyp,2)
	  difficulty+=ttyp
	 end
	 --if (ltries%20==0) cls(7) print("\n\n\n\n\n\n\n\n\n\n"..stat(0).."\n\n"..stat(1),0,0,0) flip()
 end
 --music(28)
end

chk,chatt,chhp,cheff,cheffa,cheffd,cheffc,cheffv,chdesc,chvfxc,char_vptc=str_to_table(",1,2,3,4,,6,5,,"),str_to_table(",6,4,5,5,8,3,9,5,5,3,3,4,,10,5,6,9,3,4,5,6,10,6,6,4,12,1,5,6,4,12,6,6,7,3,6,,"),str_to_table(",30,40,35,30,50,60,30,50,10,10,15,5,20,100,40,30,15,25,45,30,30,25,30,30,20,60,5,25,20,40,80,40,40,300,25,25,25,"),str_to_table(",,,,,,,,,16,15,,,,,2,7,,,,,,18,,,19,16,15,6,12,,20,2,24,7,2,2,,"),str_to_table(",,,,,,,,,21,,23,3,,1,5,,,21,,23,10,,3,5,,,,,,22,,,,3,,,,"),str_to_table(",,,,,,,,,999,,,,,4,,,,999,,,,,,,,,,,,,,,,,,999,,"),str_to_table(",,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,,"),str_to_table(",,,,,,,,,1,1,1,,,-1,1,1,,1,,1,12,1,1,1,1,1,1,1,99,1,2,4,1,1,2,3,,"),str_to_table(",jack of spades,queen of hearts,king of diamonds - 1 armor,jack of clubs - crit x3,black king,joker,lance,chester,sleeping flower,static cactus,muncher,multi flower,dummy,white king - fear,white pawn - pierce,white bishop - heal,floaty,snaky - poison,pumpky,batty - lifesteal,skully - kill <13 hp,mouthface - stone form 3 turns,furkniceght - splash attack,cyclopt - pierce,daymon - confused,tombzord - sleep,skelly,swordslime - double attack,spellslime - sp immunity,wardrobber - detroy 1st card,jimmy - crit chance x3,rook,knight - allies att+1,white queen - splash att/heal,stumpy,steel mech,illusion crystal,"),str_to_table(",,,,,,,,,4,7,4,6,,3,5,2,1,4,3,2,2,5,8,5,5,11,7,4,6,8,2,5,1,1,4,,,"),str_to_table(",6,14,6,13,14,6,6,6,14,6,6,7,1,14,6,14,14,6,6,6,6,6,5,6,6,6,6,6,14,6,6,6,6,24,7,6,6,")

function cr_char(x,y,t,a)
 c={}
 s,c.tx,c.ty,c.tgtx,c.tgty,c.typ,c.algn,c.hp,c.desc,c.act,c.mperc,c.eff,c.ischar,c.sprt,c.flp,c.crit,c.cmult,c.quake=s or 1,x,y,x,y,t,a,chhp[t],chdesc[t],to_tab_unp(",,,{,1,,f,25,2,-1,")
 add(char,c)
 return c
end

function _update()
 g_time+=1
 if (g_time==10) _init()
end

function _draw()
 cls()
end


I tried to find the souce of the bug by reducing the code while still having the bug. This left me with this code:

poke(0x5f2d,1)
function str_to_table(str)
 local tab,sptab={},{}
 for i=1,#str do
  if sub(str,i,i)=="," then
   for j=i+1,#str do
    local strn=sub(str,j,j)
    if(strn=="|")add(sptab,tab)tab={}i+=1 break
    if strn=="," then
     local s=sub(str,i+1,j-1)
     if tonum(s) then
      s=tonum(s)
     elseif s=="" then
      s=0
     elseif s=="t" then
      s=true
     elseif s=="f" then
      s=false
     elseif s=="{" then
      s={}
     end
     add(tab,s)
     break
    end
   end
  end
 end
 if (#sptab>0) return sptab
 return tab
end

function unpack(list,from,to)
 from,to=from or 1,to or #list
 if from<=to then
  return list[from],unpack(list,from+1,to)
 end
end

function to_tab_unp(tab)
 return unpack(str_to_table(tab))
end

function _init()
 cls(7)
 level,difficulty=310,0

 while abs(level-difficulty)>25 do
	 for i=1,12 do
	  to_tab_unp(",,,,,,,,,,")
	 end
 end
	_init()
end

This generates the bug at about 1 second.

Let's try to change things to see how it's affected:
Shortening the string to ",," makes the bug pop in 4 seconds;
Removing the FOR loop (leaving just the while loop), no bug after several minutes;
Changing the FOR loop length (with the ",," string):
to 1 - prevents the bug
to 2 - bug happens instantly
3 - half a second
4 - same as 3
5 - 7 seconds
6 - Didn't produce the bug in <2 minutes
7 - Same as 6
8 - Bug in less than a second
9 - Same as 6 (about 9 seconds with the ",,,,,,,,,," string)
So essentially changing either the length of the string or the length changes wildly how much time it take for the bug to happen, while in normal circumstances it shouldn't (especially changing the for loop, since it's not affecting anything)

With ",,,,,,,,,," and FOR<=12:
Changing the while loop to "while 30>25 do" - no bug in 2 minutes
Changin the while loop to "for j=1,10000 do" - no bug in 2 minutes
Removing the outer loop - bug in 3 seconds - no bug in 2 minutes

With ",," and FOR<=2:
Changing the for=i variable name - no effect
Changing the while loop to "while 30>25 do" - bug in 2 seconds
Changin the while loop to "for j=1,10000 do" - bug in 3 seconds
Removing the outer loop - bug in 3 seconds
Without any loop (_init() at the end) - out of memory in 10 seconds. Still can bug if I change the string to ",,,,,"
Moving the code from _init() to _update() - no bug in 2 minutes; Instant bug by changing to for<=3
Just "to_tab_unp(",,")" inside the _update() loop - no bugs
unpack(str_to_table(",,")) instead of to_tab_unp(",,") - no bug in 2 minutes
Tried unpack(str_to_table("...")) in the original cart, still bugs
unpack({0,0}) doesn't seem to bug

Removing 'elseif s=="" then s=0' or 'elseif s=="t" then s=true' or 'elseif s=="f" then s=false' in "str_to_table" doesn't prevent the bug, and doesn't change the "timing" of the bug, but removing all 3 prevented the bug from happening at the expected time.

It seems to me that the bug happens when you combine the unpack code with the str_to_table while in any kind of loop, so a lot of unpacking and string conversion happens in the same frame...

So I tried to go to the original cart and put only the unpack code in the character creation loop:
asdd will be the unpacked table, declared outside of any loop:
asdd=str_to_table(",,,1,,f,25,2,-1,") - removing the third item "{" to prevent all characters using that same table
to_tab_unp(",,,{,1,,f,25,2,-1,") is swapped for unpack(asdd)
And then this happens (after several minutes running):

The same error (attempt to compare function with number) occurred on a completely unrelated piece of code. It would draw the item under Jack of Spades in the character selection UI, you can see it's black because the error happened exactly there. The characters are drawn left to right so that would be the last item draw. Seems really unrelated...

At this point it seems to me that the bug stems from having a huge loop that holds the game on the same frame for a while and at the same time having a function that uses a function as argument. At some point some kind of overflow happens that should be cleared at the end of the frame, but the loop holds it for too long. When the overflow happens functions that use functions as arguments have a probability of generating this error: pico-8 tries to use the function itself as a variable instead of the result of that function.

So to be sure the error is not related to my to_tab_unp function I used just "unpack({0,0,1,0,false,25,2,-1})" in the character generation. After a few minutes:

The last thing to check is generating characters without the unpack code, so I removed it, leaving just normal variables on the character generation. Left for lunch and after 2 hours, no errors.

I think it's safe to assume the bug will only happen when combining several loop layers (to the point a frame takes more than 1/30s) with functions that have a function as an argument. I don't think I can dig any deeper than that, so unless zep wants to look into it at some point the issue ends here.

For Jack of Spades I'm pretty sure I won't run into this bug as long as I don't use the unpack function inside a loop while having a brute force loop that takes more than a few frames(this is where it all started to begin with, I used the unpack/to_tab_unp codes for months, but the bug only popped when I used brute force to generate random enemy battle formations).


I removed the piece of code that generated the bug when creating a character, but today the bug happened again when drawing a character:

It was on the first level when I reset the game. So I think it was because on the first frame is where I load a lot of variables using str_to_table. Checking the CPU in the first frame rpves it: it only surpasses 100% on the first frame, but not when loading a second level (resetting with _INIT() below):

So what I did was prevent the game from drawing in the while the game is loading those initial variables. It seems it worked - the "MAX CPU" is <1 meaning it never surpassed 100% (resetting with LOAD() below):

I hope it works now, gonna do some stess test overnight 8)



[Please log in to post a comment]