'// HEATMAP-TO-FLOWFIELD TEST \\' '// J. KOHER \\' '// JANUARY 2023 \\' '*DESCRIPTION*' '// CREATES A GOAL-BASED HEAT MAP 20 WIDE BY 16 HIGH WITH A CELL SIZE OF 8X8 PIXELS GAMEPAD 1 GLOBAL M_WIDTH,M_HEIGHT,FLOOD_PERIMETER,H_CHAR,DIAG_DIST GLOBAL PX,PY,HOR_INPUT,VERT_INPUT GLOBAL TAR_C,OBST_C,SEED_HEAT GLOBAL VEC_X,VEC_Y,V_CLOCK GLOBAL BOTTOM_POINT,TOP_POINT,CURRENT_MIN,MAX_SUM,CURRENT_SUM_X,CURRENT_SUM_Y M_WIDTH=20 M_HEIGHT=16 DIAG_DIST=1.4 PX=80 PY=64 HOR_INPUT=1 TAR_C=16 OBST_C=17 FLOOD_PERIMETER=2*(M_WIDTH+M_HEIGHT) '// HEAT FIELD MAP ARRAY DIM GLOBAL H_MAP((M_WIDTH-1),(M_HEIGHT-1)) '// (A,)= WIDTH INDEX '// (,B)= HEIGHT INDEX '// ARRAY FOR HANDLING THE PSUEDO-CLASS OF FLOOD-SEED POSITIONS TO BE HEAT-CHECKED '// *NOTE THAT SETTING THE FIRST INDEX SIZE TO 'FLOOD_PERIMETER' IS JUST TO GET A LOOSE OVER-APPROXIMATION FOR THE ACTUAL MAX FLOOD_PERIMETER '// AND MOREOVER, FOR AN APPROXIMATION OF THE MAXIMUM POSITIONS THAT IT WILL TRY TO TEST AT A TIME IN MOST CASES '// IF THERE ARE A LOT OF INDIVIDUAL TARGETS SPACED OUT ACROSS THE MAP, THEN GO WITH THE AREA OF THE MAP IN CELLS - # OF TARGET CELLS TO BE SURE '// BUT THE FORMER WORKS FINE WITH JUST ONE TARGET OR A SMALL, SIMPLE CLUMP OF TARGETS. JUST KNOW THE PROGRAM WOULD NEED FURTHER REFINEMENT TO DO OTHERWISE DIM GLOBAL FLOOD_CLASS(FLOOD_PERIMETER,1) '// (A,)= INDICATES STACK INDEX POSITION '// (,B)= INDICATES X-POSITION (,0) , AND Y-POSITION (,1) '// ARRAY FOR HANDLING THE PSUEDO-CLASS OF VECTORS BASED ON THE MIN. HEAT VALUE(S) SURROUNDING A TEST SEED DIM GLOBAL V_MIN_CLASS(7,1) '// VECTOR FIELD MAP ARRAY DIM GLOBAL V_FIELD(M_WIDTH-1,M_HEIGHT-1) '// (A,)= WIDTH INDEX '// (,B)= HEIGHT INDEX SPRITE 0 PAL 6 BG 1 BG COPY 0,0,20,16 TO 0,0 DO '// TAKE INPUT WHILE HOR_INPUT=0 AND VERT_INPUT=0 IF LEFT(0) THEN IF PX-8>-1 AND MCELL.C((PX-8)/8,PY/8)<>17 THEN HOR_INPUT=-1 ELSE IF RIGHT(0) THEN IF PX+817 THEN HOR_INPUT=1 ELSE HOR_INPUT=0 END IF IF UP(0) THEN IF PY-8>-1 AND MCELL.C(PX/8,(PY-8)/8)<>17 THEN VERT_INPUT=-1 ELSE IF DOWN(0) THEN IF PY+817 THEN VERT_INPUT=1 ELSE VERT_INPUT=0 END IF WEND '// UPDATE POSITIONS AND RESET INPUTS PX=PX+HOR_INPUT*8 HOR_INPUT=0 PY=PY+VERT_INPUT*8 VERT_INPUT=0 '// CLEAR BG CELLS AT CURRENT TARGET POSITION BG 1 CELL PX/8,PY/8,0 BG 0 CELL PX/8,PY/8,0 BG 1 '// PRINT TARGET SPRITE SPRITE 0,PX,PY,16 '// RUN LOOPS TO CHECK X & Y (I,J) CELL POSITIONS FOR TARGET(S) AND OBSTRUCTION(S) WITHIN THE SPECIFIED BG MAP '// IF A TARGET IS FOUND, THEN SET ITS EQUIVELANT H_MAP(I,J) ELEMENT TO '0' AND SET THE SEED POS. '// IF NO TARGET IS FOUND AT A POSITION, THEN SET THE EQUIVELANT H_MAP(I,J) ELEMENT TO '-1' FOR I=0 TO (M_WIDTH-1) FOR J=0 TO (M_HEIGHT-1) CURRENT_C=MCELL.C(I,J) IF CURRENT_C=OBST_C THEN H_MAP(I,J)=254 ELSE IF INT(PX/8)=I AND INT(PY/8)=J THEN H_MAP(I,J)=0 '// SET THE FIRST SEED VALUE FROM THE FLOOD_CLASS TO THE SPRITE'S CELL POSITION FLOOD_CLASS(TOP_POINT,0)=INT(PX/8) FLOOD_CLASS(TOP_POINT,1)=INT(PY/8) INC TOP_POINT ELSE H_MAP(I,J)=-1 END IF NEXT J NEXT I '// RUN SEED-HEATING LOOP UNTIL THE BOTTOM POINTER CATCHES UP WITH THE TOP POINTER, IN WHICH CASE THE ELEMENTS WILL BE -1 WHILE BOTTOM_POINT<>TOP_POINT '// UPDATE HEAT VALUES CALL HEAT_THE_SEED(FLOOD_CLASS(BOTTOM_POINT,0),FLOOD_CLASS(BOTTOM_POINT,1)) WEND BOTTOM_POINT=0 TOP_POINT=0 '// SET THE CURRENT MIN. TO THE HIGHEST VALUE (254 IN THIS CASE) AND RUN LOOPS TO FIND THE TRUE MIN'(S) AND THEN SETUP VECTOR VALUES FROM THEM: '// I AND J (X AND Y RESPECTIVELY) LOOPS WALK VECTOR SEED THROUGH EACH CELL IJ_PASS=0 RERUN_IJ: FOR I=0 TO (M_WIDTH-1) FOR J=0 TO (M_HEIGHT-1) '// ON IJ_PASS 0, SKIP TARGET CELLS AND SET INITIAL VARIABLES IF IJ_PASS<1 THEN IF H_MAP(I,J)=0 OR H_MAP(I,J)=254 THEN GOTO SKIP_J CURRENT_MIN=254 V_POINTER=0 AB_PASS=0 ELSE '// ON IJ_PASS 1, SKIP ANY V_FIELD() ELEMENTS WITH SET VALUES (>-1) IF H_MAP(I,J)=0 OR H_MAP(I,J)=254 OR V_FIELD(I,J)>-1 THEN GOTO SKIP_J ELSE BG 0 PAL 0 IF J-1>-1 THEN IF V_FIELD(I,J-1)=0 THEN V_FIELD(I,J)=0 CELL I,J,5 END IF END IF IF I+1-1 THEN IF V_FIELD(I+1,J-1)=1 THEN V_FIELD(I,J)=1 CELL I,J,6 END IF END IF IF I+1-1 AND I+A-1 AND J+B0 AND B<>0 AND H_MAP(I,(J+B))=254 AND H_MAP((I+A),J)=254) THEN GOTO SKIP_B IF AB_PASS<1 THEN IF H_MAP(I+A,J+B)<=CURRENT_MIN THEN CURRENT_MIN=H_MAP(I+A,J+B) ELSE IF H_MAP(I+A,J+B)=CURRENT_MIN THEN V_MIN_CLASS(V_POINTER,0)=A V_MIN_CLASS(V_POINTER,1)=B INC V_POINTER END IF END IF END IF SKIP_B: NEXT B NEXT A '// POST-LOOP PROCESS EITHER RETURNS TO LOOPS A/B (PASS '0') OR CALCULATES THE WEIGHTED-AVERAGE OF ALL THE MIN. CELL VECTOR-EQUIVELANTS IF AB_PASS<1 THEN INC AB_PASS GOTO RERUN_AB ELSE '// ADD THE VECTORS AND FIND THE MAXIMUM VALUE TO WEIGHT THE AVERAGE AND ROUND TO BRING THEM BACK TO SCALE IN A DECIDED DIRECTION (ANY OF EIGHT) CURRENT_SUM_X=0 CURRENT_SUM_Y=0 FOR V=0 TO 7 CURRENT_SUM_X=CURRENT_SUM_X+V_MIN_CLASS(V,0) CURRENT_SUM_Y=CURRENT_SUM_Y+V_MIN_CLASS(V,1) V_MIN_CLASS(V,0)=0 V_MIN_CLASS(V,1)=0 NEXT V '// UPDATE CURRENT SUMS IF ABS(CURRENT_SUM_X)>=ABS(CURRENT_SUM_Y) THEN MAX_SUM=ABS(CURRENT_SUM_X) ELSE MAX_SUM=ABS(CURRENT_SUM_Y) '// SET VECTORS TO THE AVERAGES WEIGHTED BY THE MAX SUM IF MAX SUM IS NOT ZERO IF MAX_SUM<>0 THEN VEC_X=CURRENT_SUM_X/MAX_SUM VEC_Y=CURRENT_SUM_Y/MAX_SUM ELSE VEC_X=0 VEC_Y=0 END IF '// THE ROUNDING FAVORS 0'S TO HELP BALANCE THE BIAS IN THE HEATMAP TOWARDS THE DIAGONALS IN THIS DISTANCE-COUNTING REGIME IF VEC_X>=0 THEN IF VEC_X-INT(VEC_X)<=0.5 THEN VEC_X=INT(VEC_X) ELSE VEC_X=1 ELSE IF INT(VEC_X)<>VEC_X AND INT(VEC_X)-VEC_X>=-0.5 THEN VEC_X=INT(VEC_X)+1 ELSE VEC_X=-1 END IF IF VEC_Y>=0 THEN IF VEC_Y-INT(VEC_Y)<=0.5 THEN VEC_Y=INT(VEC_Y) ELSE VEC_Y=1 ELSE IF INT(VEC_Y)<>VEC_Y AND INT(VEC_Y)-VEC_Y>=-0.5 THEN VEC_Y=INT(VEC_Y)+1 ELSE VEC_Y=-1 END IF '// ENCODE THE RESULTS AS ONE OF EIGHT 'CLOCK VALUES' WITH '0' AT THE TOP (12 O'CLOCK) INCREASING CLOCKWISE BG 0 PAL 0 IF VEC_X=0 AND VEC_Y<0 THEN V_CLOCK=0 CELL I,J,5 ELSE IF VEC_X>0 AND VEC_Y<0 THEN V_CLOCK=1 CELL I,J,6 ELSE IF VEC_X>0 AND VEC_Y=0 THEN V_CLOCK=2 CELL I,J,4 ELSE IF VEC_X>0 AND VEC_Y>0 THEN V_CLOCK=3 CELL I,J,22 ELSE IF VEC_X=0 AND VEC_Y>0 THEN V_CLOCK=4 CELL I,J,21 ELSE IF VEC_X<0 AND VEC_Y>0 THEN V_CLOCK=5 CELL I,J,23 ELSE IF VEC_X<0 AND VEC_Y=0 THEN V_CLOCK=6 CELL I,J,20 ELSE IF VEC_X<0 AND VEC_Y<0 THEN V_CLOCK=7 CELL I,J,7 ELSE V_CLOCK=-1 END IF BG 1 '// SET THE VECTOR FIELD ARRAY VALUES V_FIELD(I,J)=V_CLOCK END IF SKIP_J: NEXT J NEXT I '// I/J LOOP RETURN CONTROL IF IJ_PASS<1 THEN INC IJ_PASS GOTO RERUN_IJ END IF LOOP '// CYCLES THROUGH THE CELLS SURROUNDING THE CURRENT SEED AND UPDATES THEIR HEAT VALUES WHEN APPROPRIATE SUB HEAT_THE_SEED(X,Y) SEED_HEAT=H_MAP(X,Y) CALL SEED_HEAT_PO(X,Y) FOR A=-1 TO 1 FOR B=-1 TO 1 '// IF AT SEED CELL, THEN SKIP UPDATING THE HEAT VALUES IF A=0 AND B=0 THEN GOTO NEXT_B '// CHECK TO SEE THAT THE CELL TO BE UPDATED IS ON THE MAP ELSE IF X+A>M_WIDTH-1 OR X+A<0 OR Y+B>M_HEIGHT-1 OR Y+B<0 THEN GOTO NEXT_B ELSE IF A<>0 AND B<>0 THEN '// CHECK TO MAKE SURE DIAGONALS AREN'T BLOCKED IN BY BOTH OF THEIR PERPENDICULAR NEIGHBORS (THE IMPRACTICALITY OF WHICH IS SPECIFIED BY GAME MECHANICS) IF H_MAP(X,(Y+B))=254 AND H_MAP((X+A),Y)=254 THEN GOTO NEXT_B ELSE CALL HEAT_TEST(X,Y,A,B,DIAG_DIST) END IF ELSE CALL HEAT_TEST(X,Y,A,B,1) END IF NEXT_B: NEXT B NEXT A '// INCREASE BOTTOM POINTER FOR THE FLOOD_CLASS() ARRAY, WRAPPING IF NEEDED IF BOTTOM_POINT=FLOOD_PERIMETER THEN BOTTOM_POINT=0 ELSE INC BOTTOM_POINT END SUB SUB HEAT_TEST(X,Y,A,B,D) N_X=X+A N_Y=Y+B N_C=H_MAP(N_X,N_Y) IF N_C<0 OR (SEED_HEAT+D0 THEN H_PAL=INT(SEED_HEAT/3) IF H_PAL>7 THEN H_PAL=7 H_CHAR=(SEED_HEAT MOD 3)+1 BG 1 PAL H_PAL CELL X,Y,H_CHAR ELSE IF SEED_HEAT<0 THEN NUMBER X,Y,0,1 END IF END SUB #1:MAIN PALETTES 003E3D3C00383430003B373300323120 001F0F0B00070301002C1C0C00180804 #2:MAIN CHARACTERS 00000000000000000000000000000000 FFFFFFFFFFFFFFFF0000000000000000 0000000000000000FFFFFFFFFFFFFFFF FFFFFFFFFFFFFFFFFFFFFFFFFFFFFFFF 0008047E7E0408000000000000000000 00183C5A181818000000000000000000 001E060A122040000000000000000000 00786050480402000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 FFBDA5FF424242A5FFBDA5FF424242A5 FFBDE7DBDBE7BDFF817E5A66665A7E81 00000000000000000000000000000000 00000000000000000000000000000000 0010207E7E2010000000000000000000 001818185A3C18000000000000000000 004020120A061E000000000000000000 00020448506078000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 C3810000000081C30000000000000000 #3:MAIN BG 00001410000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00001107000000000000000000001107 00000000000000000000000000000000 00000000000000000000000011071107 11071107110700000000000000000000 00000000000000000000110700000000 00000000000000000000000000000000 00000000110700000000000000000000 00000000110700000000000000000000 00000000000000000000110700000000 00000000000000000000000011070000 00000000000000000000000000000000 00001107000000000000000000000000 00000000110700000000000000000000 00000000000000000000110700000000 00000000000000000000000011070000 00000000000000000000000000000000 00001107000000000000000000000000 00000000110700000000000000000000 00000000000000000000110700000000 00000000000000000000110700000000 00000000110711071107110711070000 00000000110700000000000000000000 00000000000000000000110700000000 00000000000011070000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000000000000000000000000000 00000000