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?

P#66865 2019-08-22 20:48 ( Edited 2019-08-22 20:49)

:: dw817

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.

P#66869 2019-08-22 21:07 ( Edited 2019-08-22 21:07)

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

P#66868 2019-08-22 21:08

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

P#66870 2019-08-22 21:15
:: dw817

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

P#66873 2019-08-23 00:10

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)

P#66874 2019-08-23 05:39

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

P#66875 2019-08-23 05:40

@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

P#66878 2019-08-23 11:16

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).

P#66997 2019-08-28 19:38 ( Edited 2019-08-28 19:45)

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)

P#67017 2019-08-29 21:21

[Please log in to post a comment]

Follow Lexaloffle:        
Generated 2020-02-25 16:25 | 0.052s | 2097k | Q:31